Skip to content

Commit 6958633

Browse files
[InstCombine] Opt phi(freeze(undef), C) -> phi(C, C) (llvm#161181)
Try to choose a value for freeze that enables the PHI to be replaced with its input constants if they are equal.
1 parent 5baf1c1 commit 6958633

File tree

2 files changed

+303
-2
lines changed

2 files changed

+303
-2
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,7 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
51695169
// - or: pick -1
51705170
// - select's condition: if the true value is constant, choose it by making
51715171
// the condition true.
5172+
// - phi: pick the common constant across operands
51725173
// - default: pick 0
51735174
//
51745175
// Note that this transform is intentionally done here rather than
@@ -5179,9 +5180,32 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
51795180
// TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid
51805181
// duplicating logic for binops at least.
51815182
auto getUndefReplacement = [&](Type *Ty) {
5182-
Value *BestValue = nullptr;
5183+
auto pickCommonConstantFromPHI = [](PHINode &PN) -> Value * {
5184+
// phi(freeze(undef), C, C). Choose C for freeze so the PHI can be
5185+
// removed.
5186+
Constant *BestValue = nullptr;
5187+
for (Value *V : PN.incoming_values()) {
5188+
if (match(V, m_Freeze(m_Undef())))
5189+
continue;
5190+
5191+
Constant *C = dyn_cast<Constant>(V);
5192+
if (!C)
5193+
return nullptr;
5194+
5195+
if (!isGuaranteedNotToBeUndefOrPoison(C))
5196+
return nullptr;
5197+
5198+
if (BestValue && BestValue != C)
5199+
return nullptr;
5200+
5201+
BestValue = C;
5202+
}
5203+
return BestValue;
5204+
};
5205+
51835206
Value *NullValue = Constant::getNullValue(Ty);
5184-
for (const auto *U : I.users()) {
5207+
Value *BestValue = nullptr;
5208+
for (auto *U : I.users()) {
51855209
Value *V = NullValue;
51865210
if (match(U, m_Or(m_Value(), m_Value())))
51875211
V = ConstantInt::getAllOnesValue(Ty);
@@ -5190,6 +5214,9 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
51905214
else if (match(U, m_c_Select(m_Specific(&I), m_Value(V)))) {
51915215
if (!isGuaranteedNotToBeUndefOrPoison(V, &AC, &I, &DT))
51925216
V = NullValue;
5217+
} else if (auto *PHI = dyn_cast<PHINode>(U)) {
5218+
if (Value *MaybeV = pickCommonConstantFromPHI(*PHI))
5219+
V = MaybeV;
51935220
}
51945221

51955222
if (!BestValue)
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3+
4+
define i32 @phi_freeze_same_consts(i1 %c0, i1 %c1) {
5+
; CHECK-LABEL: define i32 @phi_freeze_same_consts(
6+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
9+
; CHECK: [[BB_FREEZE]]:
10+
; CHECK-NEXT: br label %[[FINAL:.*]]
11+
; CHECK: [[BB_OTHER]]:
12+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
13+
; CHECK: [[CA]]:
14+
; CHECK-NEXT: br label %[[FINAL]]
15+
; CHECK: [[CB]]:
16+
; CHECK-NEXT: br label %[[FINAL]]
17+
; CHECK: [[FINAL]]:
18+
; CHECK-NEXT: ret i32 42
19+
;
20+
entry:
21+
br i1 %c0, label %bb_freeze, label %bb_other
22+
23+
bb_freeze:
24+
%f = freeze i32 undef
25+
br label %final
26+
27+
bb_other:
28+
br i1 %c1, label %cA, label %cB
29+
cA:
30+
br label %final
31+
cB:
32+
br label %final
33+
34+
final:
35+
%phi = phi i32 [ %f, %bb_freeze ], [ 42, %cA ], [ 42, %cB ]
36+
ret i32 %phi
37+
}
38+
39+
define i32 @phi_freeze_mixed_consts(i1 %c0, i1 %c1) {
40+
; CHECK-LABEL: define i32 @phi_freeze_mixed_consts(
41+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
42+
; CHECK-NEXT: [[ENTRY:.*:]]
43+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
44+
; CHECK: [[BB_FREEZE]]:
45+
; CHECK-NEXT: br label %[[FINAL:.*]]
46+
; CHECK: [[BB_OTHER]]:
47+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
48+
; CHECK: [[CA]]:
49+
; CHECK-NEXT: br label %[[FINAL]]
50+
; CHECK: [[CB]]:
51+
; CHECK-NEXT: br label %[[FINAL]]
52+
; CHECK: [[FINAL]]:
53+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB_FREEZE]] ], [ 42, %[[CA]] ], [ 7, %[[CB]] ]
54+
; CHECK-NEXT: ret i32 [[PHI]]
55+
;
56+
entry:
57+
br i1 %c0, label %bb_freeze, label %bb_other
58+
59+
bb_freeze:
60+
%f = freeze i32 undef
61+
br label %final
62+
63+
bb_other:
64+
br i1 %c1, label %cA, label %cB
65+
cA:
66+
br label %final
67+
cB:
68+
br label %final
69+
70+
final:
71+
%phi = phi i32 [ %f, %bb_freeze ], [ 42, %cA ], [ 7, %cB ]
72+
ret i32 %phi
73+
}
74+
75+
define i32 @phi_freeze_with_nonconst_incoming(i32 %x, i1 %c0, i1 %c1) {
76+
; CHECK-LABEL: define i32 @phi_freeze_with_nonconst_incoming(
77+
; CHECK-SAME: i32 [[X:%.*]], i1 [[C0:%.*]], i1 [[C1:%.*]]) {
78+
; CHECK-NEXT: [[ENTRY:.*:]]
79+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
80+
; CHECK: [[BB_FREEZE]]:
81+
; CHECK-NEXT: br label %[[FINAL:.*]]
82+
; CHECK: [[BB_OTHER]]:
83+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
84+
; CHECK: [[CA]]:
85+
; CHECK-NEXT: br label %[[FINAL]]
86+
; CHECK: [[CB]]:
87+
; CHECK-NEXT: br label %[[FINAL]]
88+
; CHECK: [[FINAL]]:
89+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB_FREEZE]] ], [ [[X]], %[[CA]] ], [ 13, %[[CB]] ]
90+
; CHECK-NEXT: ret i32 [[PHI]]
91+
;
92+
entry:
93+
br i1 %c0, label %bb_freeze, label %bb_other
94+
95+
bb_freeze:
96+
%f = freeze i32 undef
97+
br label %final
98+
99+
bb_other:
100+
br i1 %c1, label %cA, label %cB
101+
cA:
102+
br label %final
103+
cB:
104+
br label %final
105+
106+
final:
107+
%phi = phi i32 [ %f, %bb_freeze ], [ %x, %cA ], [ 13, %cB ]
108+
ret i32 %phi
109+
}
110+
111+
define <4 x i8> @phi_freeze_vector(i1 %c0, i1 %c1) {
112+
; CHECK-LABEL: define <4 x i8> @phi_freeze_vector(
113+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
114+
; CHECK-NEXT: [[ENTRY:.*:]]
115+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
116+
; CHECK: [[BB_FREEZE]]:
117+
; CHECK-NEXT: br label %[[FINAL:.*]]
118+
; CHECK: [[BB_OTHER]]:
119+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
120+
; CHECK: [[CA]]:
121+
; CHECK-NEXT: br label %[[FINAL]]
122+
; CHECK: [[CB]]:
123+
; CHECK-NEXT: br label %[[FINAL]]
124+
; CHECK: [[FINAL]]:
125+
; CHECK-NEXT: ret <4 x i8> splat (i8 9)
126+
;
127+
entry:
128+
br i1 %c0, label %bb_freeze, label %bb_other
129+
130+
bb_freeze:
131+
%f = freeze <4 x i8> undef
132+
br label %final
133+
134+
bb_other:
135+
br i1 %c1, label %cA, label %cB
136+
137+
cA:
138+
br label %final
139+
140+
cB:
141+
br label %final
142+
143+
final:
144+
%phi = phi <4 x i8> [ %f, %bb_freeze ],
145+
[<i8 9, i8 9, i8 9, i8 9>, %cA ],
146+
[<i8 9, i8 9, i8 9, i8 9>, %cB ]
147+
ret <4 x i8> %phi
148+
}
149+
150+
define i32 @multi_use_one_folds_one_not_zero(i1 %c0, i1 %c1, i1 %c2) {
151+
; CHECK-LABEL: define i32 @multi_use_one_folds_one_not_zero(
152+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
153+
; CHECK-NEXT: [[ENTRY:.*:]]
154+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_OTHER3:.*]], label %[[CC1:.*]]
155+
; CHECK: [[BB_OTHER3]]:
156+
; CHECK-NEXT: br label %[[MID:.*]]
157+
; CHECK: [[CC1]]:
158+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
159+
; CHECK: [[CA]]:
160+
; CHECK-NEXT: br label %[[MID]]
161+
; CHECK: [[CB]]:
162+
; CHECK-NEXT: br label %[[MID]]
163+
; CHECK: [[MID]]:
164+
; CHECK-NEXT: [[PHI_FOLD:%.*]] = phi i32 [ 0, %[[BB_OTHER3]] ], [ 1, %[[CA]] ], [ 1, %[[CB]] ]
165+
; CHECK-NEXT: br i1 [[C2]], label %[[BB_FREEZE2:.*]], label %[[CD:.*]]
166+
; CHECK: [[BB_FREEZE2]]:
167+
; CHECK-NEXT: br label %[[FINAL:.*]]
168+
; CHECK: [[BB_OTHER2:.*:]]
169+
; CHECK-NEXT: br i1 true, label %[[CA]], label %[[CB]]
170+
; CHECK: [[CC:.*:]]
171+
; CHECK-NEXT: br label %[[FINAL]]
172+
; CHECK: [[CD]]:
173+
; CHECK-NEXT: br label %[[FINAL]]
174+
; CHECK: [[FINAL]]:
175+
; CHECK-NEXT: ret i32 [[PHI_FOLD]]
176+
;
177+
entry:
178+
%f = freeze i32 undef
179+
br i1 %c0, label %bb_freeze, label %bb_other
180+
bb_freeze:
181+
br label %mid
182+
bb_other:
183+
br i1 %c1, label %cA, label %cB
184+
cA:
185+
br label %mid
186+
cB:
187+
br label %mid
188+
mid:
189+
%phi_no_fold = phi i32 [ %f, %bb_freeze ], [ 1, %cA ], [ 1, %cB ]
190+
br i1 %c2, label %bb_freeze2, label %cD
191+
bb_freeze2:
192+
br label %final
193+
bb_other2:
194+
br i1 %c1, label %cA, label %cB
195+
cC:
196+
br label %final
197+
cD:
198+
br label %final
199+
final:
200+
%phi_fold = phi i32 [ %f, %bb_freeze2 ], [ 0, %cC ], [ 0, %cD ]
201+
%a = add i32 %phi_fold, %phi_no_fold
202+
ret i32 %a
203+
}
204+
205+
define i32 @phi_freeze_poison(i1 %c0, i1 %c1) {
206+
; CHECK-LABEL: define i32 @phi_freeze_poison(
207+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
208+
; CHECK-NEXT: [[ENTRY:.*:]]
209+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
210+
; CHECK: [[BB_FREEZE]]:
211+
; CHECK-NEXT: br label %[[FINAL:.*]]
212+
; CHECK: [[BB_OTHER]]:
213+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
214+
; CHECK: [[CA]]:
215+
; CHECK-NEXT: br label %[[FINAL]]
216+
; CHECK: [[CB]]:
217+
; CHECK-NEXT: br label %[[FINAL]]
218+
; CHECK: [[FINAL]]:
219+
; CHECK-NEXT: ret i32 0
220+
;
221+
entry:
222+
br i1 %c0, label %bb_freeze, label %bb_other
223+
224+
bb_freeze:
225+
%f = freeze i32 undef
226+
br label %final
227+
228+
bb_other:
229+
br i1 %c1, label %cA, label %cB
230+
cA:
231+
br label %final
232+
cB:
233+
br label %final
234+
235+
final:
236+
%phi = phi i32 [ %f, %bb_freeze ], [ poison, %cA ], [ poison, %cB ]
237+
ret i32 %phi
238+
}
239+
240+
define <2 x i32> @phi_freeze_poison_vec(i1 %c0, i1 %c1) {
241+
; CHECK-LABEL: define <2 x i32> @phi_freeze_poison_vec(
242+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
243+
; CHECK-NEXT: [[ENTRY:.*:]]
244+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
245+
; CHECK: [[BB_FREEZE]]:
246+
; CHECK-NEXT: br label %[[FINAL:.*]]
247+
; CHECK: [[BB_OTHER]]:
248+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
249+
; CHECK: [[CA]]:
250+
; CHECK-NEXT: br label %[[FINAL]]
251+
; CHECK: [[CB]]:
252+
; CHECK-NEXT: br label %[[FINAL]]
253+
; CHECK: [[FINAL]]:
254+
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i32> [ zeroinitializer, %[[BB_FREEZE]] ], [ <i32 poison, i32 1>, %[[CA]] ], [ <i32 poison, i32 1>, %[[CB]] ]
255+
; CHECK-NEXT: ret <2 x i32> [[PHI]]
256+
;
257+
entry:
258+
br i1 %c0, label %bb_freeze, label %bb_other
259+
260+
bb_freeze:
261+
%f = freeze <2 x i32> undef
262+
br label %final
263+
264+
bb_other:
265+
br i1 %c1, label %cA, label %cB
266+
cA:
267+
br label %final
268+
cB:
269+
br label %final
270+
271+
final:
272+
%phi = phi <2 x i32> [ %f, %bb_freeze ], [ <i32 poison, i32 1>, %cA ], [ <i32 poison, i32 1>, %cB ]
273+
ret <2 x i32> %phi
274+
}

0 commit comments

Comments
 (0)