Skip to content

Commit d1a6a71

Browse files
[InstCombine] Opt phi(freeze(undef), C) -> phi(C, C)
Change-Id: I29fd2663a5c0e4e3a6d98a2c9536f515a12947a5
1 parent 1cf5466 commit d1a6a71

File tree

2 files changed

+282
-1
lines changed

2 files changed

+282
-1
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4821,8 +4821,51 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
48214821
// TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid
48224822
// duplicating logic for binops at least.
48234823
auto getUndefReplacement = [&](Type *Ty) {
4824-
Value *BestValue = nullptr;
4824+
auto pickCommonConstantFromPHI = [](PHINode &PN) -> Value * {
4825+
// phi(freeze(undef), C, C). Choose C for freeze so the PHI can be
4826+
// removed.
4827+
Constant *BestValue = nullptr;
4828+
Constant *C = nullptr;
4829+
for (Value *V : PN.incoming_values()) {
4830+
if (match(V, m_Freeze(m_Undef())))
4831+
continue;
4832+
4833+
if (!isa<Constant>(V))
4834+
return nullptr;
4835+
4836+
C = cast<Constant>(V);
4837+
4838+
if (BestValue && BestValue != C)
4839+
return nullptr;
4840+
4841+
BestValue = C;
4842+
}
4843+
return BestValue;
4844+
};
4845+
48254846
Value *NullValue = Constant::getNullValue(Ty);
4847+
4848+
bool OnlyPHIUsers =
4849+
all_of(I.users(), [](const User *U) { return isa<PHINode>(U); });
4850+
if (OnlyPHIUsers) {
4851+
Value *BestValue = nullptr;
4852+
for (auto *U : I.users()) {
4853+
Value *V = pickCommonConstantFromPHI(*cast<PHINode>(U));
4854+
if (!V)
4855+
continue;
4856+
4857+
if (!BestValue) {
4858+
BestValue = V;
4859+
} else if (BestValue && BestValue == NullValue) {
4860+
BestValue = NullValue;
4861+
}
4862+
}
4863+
4864+
if (BestValue)
4865+
return BestValue;
4866+
}
4867+
4868+
Value *BestValue = nullptr;
48264869
for (const auto *U : I.users()) {
48274870
Value *V = NullValue;
48284871
if (match(U, m_Or(m_Value(), m_Value())))
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
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(i1 %c0, i1 %c1) {
151+
; CHECK-LABEL: define i32 @multi_use_one_folds_one_not(
152+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]]) {
153+
; CHECK-NEXT: [[ENTRY:.*:]]
154+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_FREEZE:.*]], label %[[BB_OTHER:.*]]
155+
; CHECK: [[BB_FREEZE]]:
156+
; CHECK-NEXT: br label %[[MID:.*]]
157+
; CHECK: [[BB_OTHER]]:
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: [[A:%.*]] = phi i32 [ 2, %[[BB_FREEZE]] ], [ 4, %[[CA]] ], [ 3, %[[CB]] ]
165+
; CHECK-NEXT: ret i32 [[A]]
166+
;
167+
entry:
168+
br i1 %c0, label %bb_freeze, label %bb_other
169+
bb_freeze:
170+
%f = freeze i32 undef
171+
br label %mid
172+
bb_other:
173+
br i1 %c1, label %cA, label %cB
174+
cA:
175+
br label %mid
176+
cB:
177+
br label %mid
178+
mid:
179+
%phi_fold = phi i32 [ %f, %bb_freeze ], [ 1, %cA ], [ 1, %cB ]
180+
%phi_nofld = phi i32 [ %f, %bb_freeze ], [ 3, %cA ], [ 2, %cB ]
181+
%a = add i32 %phi_fold, %phi_nofld
182+
ret i32 %a
183+
}
184+
185+
define i32 @multi_use_one_folds_one_not_zero(i1 %c0, i1 %c1, i1 %c2) {
186+
; CHECK-LABEL: define i32 @multi_use_one_folds_one_not_zero(
187+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
188+
; CHECK-NEXT: [[ENTRY:.*:]]
189+
; CHECK-NEXT: br i1 [[C0]], label %[[BB_OTHER3:.*]], label %[[CC1:.*]]
190+
; CHECK: [[BB_OTHER3]]:
191+
; CHECK-NEXT: br label %[[MID:.*]]
192+
; CHECK: [[CC1]]:
193+
; CHECK-NEXT: br i1 [[C1]], label %[[CA:.*]], label %[[CB:.*]]
194+
; CHECK: [[CA]]:
195+
; CHECK-NEXT: br label %[[MID]]
196+
; CHECK: [[CB]]:
197+
; CHECK-NEXT: br label %[[MID]]
198+
; CHECK: [[MID]]:
199+
; CHECK-NEXT: [[PHI_FOLD:%.*]] = phi i32 [ 0, %[[BB_OTHER3]] ], [ 1, %[[CA]] ], [ 1, %[[CB]] ]
200+
; CHECK-NEXT: br i1 [[C2]], label %[[BB_FREEZE2:.*]], label %[[CD:.*]]
201+
; CHECK: [[BB_FREEZE2]]:
202+
; CHECK-NEXT: br label %[[FINAL:.*]]
203+
; CHECK: [[BB_OTHER2:.*:]]
204+
; CHECK-NEXT: br i1 true, label %[[CA]], label %[[CB]]
205+
; CHECK: [[CC:.*:]]
206+
; CHECK-NEXT: br label %[[FINAL]]
207+
; CHECK: [[CD]]:
208+
; CHECK-NEXT: br label %[[FINAL]]
209+
; CHECK: [[FINAL]]:
210+
; CHECK-NEXT: ret i32 [[PHI_FOLD]]
211+
;
212+
entry:
213+
%f = freeze i32 undef
214+
br i1 %c0, label %bb_freeze, label %bb_other
215+
bb_freeze:
216+
br label %mid
217+
bb_other:
218+
br i1 %c1, label %cA, label %cB
219+
cA:
220+
br label %mid
221+
cB:
222+
br label %mid
223+
mid:
224+
%phi_no_fold = phi i32 [ %f, %bb_freeze ], [ 1, %cA ], [ 1, %cB ]
225+
br i1 %c2, label %bb_freeze2, label %cD
226+
bb_freeze2:
227+
br label %final
228+
bb_other2:
229+
br i1 %c1, label %cA, label %cB
230+
cC:
231+
br label %final
232+
cD:
233+
br label %final
234+
final:
235+
%phi_fold = phi i32 [ %f, %bb_freeze2 ], [ 0, %cC ], [ 0, %cD ]
236+
%a = add i32 %phi_fold, %phi_no_fold
237+
ret i32 %a
238+
}

0 commit comments

Comments
 (0)