Skip to content

Commit 9a9fbbb

Browse files
[InstructionSimplify] Enhance simplifySelectInst() (#163453)
Fold select instructions with true and false values that act as the same phi, which cleans up the IR and open up opportunities for other passes such as loop vectorization.
1 parent f2b20d3 commit 9a9fbbb

File tree

2 files changed

+334
-1
lines changed

2 files changed

+334
-1
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4866,6 +4866,89 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
48664866
return nullptr;
48674867
}
48684868

4869+
/// Look for the following pattern and simplify %to_fold to %identicalPhi.
4870+
/// Here %phi, %to_fold and %phi.next perform the same functionality as
4871+
/// %identicalPhi and hence the select instruction %to_fold can be folded
4872+
/// into %identicalPhi.
4873+
///
4874+
/// BB1:
4875+
/// %identicalPhi = phi [ X, %BB0 ], [ %identicalPhi.next, %BB1 ]
4876+
/// %phi = phi [ X, %BB0 ], [ %phi.next, %BB1 ]
4877+
/// ...
4878+
/// %identicalPhi.next = select %cmp, %val, %identicalPhi
4879+
/// (or select %cmp, %identicalPhi, %val)
4880+
/// %to_fold = select %cmp2, %identicalPhi, %phi
4881+
/// %phi.next = select %cmp, %val, %to_fold
4882+
/// (or select %cmp, %to_fold, %val)
4883+
///
4884+
/// Prove that %phi and %identicalPhi are the same by induction:
4885+
///
4886+
/// Base case: Both %phi and %identicalPhi are equal on entry to the loop.
4887+
/// Inductive case:
4888+
/// Suppose %phi and %identicalPhi are equal at iteration i.
4889+
/// We look at their values at iteration i+1 which are %phi.next and
4890+
/// %identicalPhi.next. They would have become different only when %cmp is
4891+
/// false and the corresponding values %to_fold and %identicalPhi differ
4892+
/// (similar reason for the other "or" case in the bracket).
4893+
///
4894+
/// The only condition when %to_fold and %identicalPh could differ is when %cmp2
4895+
/// is false and %to_fold is %phi, which contradicts our inductive hypothesis
4896+
/// that %phi and %identicalPhi are equal. Thus %phi and %identicalPhi are
4897+
/// always equal at iteration i+1.
4898+
bool isSimplifierIdenticalPHI(PHINode &PN, PHINode &IdenticalPN) {
4899+
if (PN.getParent() != IdenticalPN.getParent())
4900+
return false;
4901+
if (PN.getNumIncomingValues() != 2)
4902+
return false;
4903+
4904+
// Check that only the backedge incoming value is different.
4905+
unsigned DiffVals = 0;
4906+
BasicBlock *DiffValBB = nullptr;
4907+
for (unsigned i = 0; i < 2; i++) {
4908+
BasicBlock *PredBB = PN.getIncomingBlock(i);
4909+
if (PN.getIncomingValueForBlock(PredBB) !=
4910+
IdenticalPN.getIncomingValueForBlock(PredBB)) {
4911+
DiffVals++;
4912+
DiffValBB = PredBB;
4913+
}
4914+
}
4915+
if (DiffVals != 1)
4916+
return false;
4917+
// Now check that the backedge incoming values are two select
4918+
// instructions with the same condition. Either their true
4919+
// values are the same, or their false values are the same.
4920+
auto *SI = dyn_cast<SelectInst>(PN.getIncomingValueForBlock(DiffValBB));
4921+
auto *IdenticalSI =
4922+
dyn_cast<SelectInst>(IdenticalPN.getIncomingValueForBlock(DiffValBB));
4923+
if (!SI || !IdenticalSI)
4924+
return false;
4925+
if (SI->getCondition() != IdenticalSI->getCondition())
4926+
return false;
4927+
4928+
SelectInst *SIOtherVal = nullptr;
4929+
Value *IdenticalSIOtherVal = nullptr;
4930+
if (SI->getTrueValue() == IdenticalSI->getTrueValue()) {
4931+
SIOtherVal = dyn_cast<SelectInst>(SI->getFalseValue());
4932+
IdenticalSIOtherVal = IdenticalSI->getFalseValue();
4933+
} else if (SI->getFalseValue() == IdenticalSI->getFalseValue()) {
4934+
SIOtherVal = dyn_cast<SelectInst>(SI->getTrueValue());
4935+
IdenticalSIOtherVal = IdenticalSI->getTrueValue();
4936+
} else {
4937+
return false;
4938+
}
4939+
4940+
// Now check that the other values in select, i.e., %to_fold and
4941+
// %identicalPhi, are essentially the same value.
4942+
if (!SIOtherVal || IdenticalSIOtherVal != &IdenticalPN)
4943+
return false;
4944+
if (!(SIOtherVal->getTrueValue() == &IdenticalPN &&
4945+
SIOtherVal->getFalseValue() == &PN) &&
4946+
!(SIOtherVal->getTrueValue() == &PN &&
4947+
SIOtherVal->getFalseValue() == &IdenticalPN))
4948+
return false;
4949+
return true;
4950+
}
4951+
48694952
/// Given operands for a SelectInst, see if we can fold the result.
48704953
/// If not, this returns null.
48714954
static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
@@ -5041,7 +5124,14 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
50415124
std::optional<bool> Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL);
50425125
if (Imp)
50435126
return *Imp ? TrueVal : FalseVal;
5044-
5127+
// Look for same PHIs in the true and false values.
5128+
if (auto *TruePHI = dyn_cast<PHINode>(TrueVal))
5129+
if (auto *FalsePHI = dyn_cast<PHINode>(FalseVal)) {
5130+
if (isSimplifierIdenticalPHI(*TruePHI, *FalsePHI))
5131+
return FalseVal;
5132+
if (isSimplifierIdenticalPHI(*FalsePHI, *TruePHI))
5133+
return TrueVal;
5134+
}
50455135
return nullptr;
50465136
}
50475137

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -S -passes=instcombine | FileCheck %s
3+
@A = extern_weak global float, align 4
4+
5+
; %same.as.v1 is a select with two phis %v1 and %phi.to.remove as the true
6+
; and false values, while %v1 and %phi.to.remove are actually the same.
7+
; Fold the selection instruction %same.as.v1 to %v1.
8+
define void @select_with_identical_phi(ptr %m, ptr %n, i32 %count) {
9+
; CHECK-LABEL: @select_with_identical_phi(
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
12+
; CHECK: for.body:
13+
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
14+
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
15+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
16+
; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
17+
; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
18+
; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
19+
; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
20+
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
21+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
22+
; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
23+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
24+
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
25+
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
26+
; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
27+
; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
28+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
29+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
30+
; CHECK: exit:
31+
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
32+
; CHECK-NEXT: ret void
33+
;
34+
entry:
35+
br label %for.body
36+
37+
for.body: ; preds = %entry, %for.body
38+
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
39+
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
40+
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
41+
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
42+
%q = phi ptr [ %m, %entry ], [ %q.next, %for.body ]
43+
%c = phi ptr [ %n, %entry ], [ %c.next, %for.body ]
44+
%q.load = load float, ptr %q
45+
%c.load = load float, ptr %c
46+
%sub = fsub float %q.load, %c.load
47+
%cmp1 = fcmp olt float %sub, %v0
48+
%v0.1 = select i1 %cmp1, float %sub, float %v0
49+
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
50+
%cmp2 = fcmp ogt float %sub, %same.as.v1
51+
%v1.1 = select i1 %cmp2, float %sub, float %v1
52+
%phi.to.remove.next = select i1 %cmp2, float %sub, float %same.as.v1
53+
%inc.i = add nuw nsw i32 %i, 1
54+
%q.next = getelementptr inbounds i8, ptr %q, i64 4
55+
%c.next = getelementptr inbounds i8, ptr %c, i64 4
56+
%exitcond = icmp eq i32 %inc.i, %count
57+
br i1 %exitcond, label %exit, label %for.body
58+
59+
exit:
60+
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
61+
store float %vl.1.lcssa, ptr @A
62+
ret void
63+
}
64+
65+
; The difference from select_with_identical_phi() is that the true and false values in
66+
; %phi.to.remove.next and %v1.1 are swapped.
67+
; Check that %same.as.v1 can be folded.
68+
define void @select_with_identical_phi_2(ptr %m, ptr %n, i32 %count) {
69+
; CHECK-LABEL: @select_with_identical_phi_2(
70+
; CHECK-NEXT: entry:
71+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
72+
; CHECK: for.body:
73+
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
74+
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
75+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
76+
; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
77+
; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
78+
; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
79+
; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
80+
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
81+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
82+
; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
83+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
84+
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[V1]], float [[SUB]]
85+
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
86+
; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
87+
; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
88+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
89+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
90+
; CHECK: exit:
91+
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
92+
; CHECK-NEXT: ret void
93+
;
94+
entry:
95+
br label %for.body
96+
97+
for.body: ; preds = %entry, %for.body
98+
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
99+
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
100+
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
101+
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
102+
%q = phi ptr [ %m, %entry ], [ %q.next, %for.body ]
103+
%c = phi ptr [ %n, %entry ], [ %c.next, %for.body ]
104+
%q.load = load float, ptr %q
105+
%c.load = load float, ptr %c
106+
%sub = fsub float %q.load, %c.load
107+
%cmp1 = fcmp olt float %sub, %v0
108+
%v0.1 = select i1 %cmp1, float %sub, float %v0
109+
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
110+
%cmp2 = fcmp ogt float %sub, %same.as.v1
111+
%v1.1 = select i1 %cmp2, float %v1, float %sub
112+
%phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %sub
113+
%inc.i = add nuw nsw i32 %i, 1
114+
%q.next = getelementptr inbounds i8, ptr %q, i64 4
115+
%c.next = getelementptr inbounds i8, ptr %c, i64 4
116+
%exitcond = icmp eq i32 %inc.i, %count
117+
br i1 %exitcond, label %exit, label %for.body
118+
119+
exit:
120+
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
121+
store float %vl.1.lcssa, ptr @A
122+
ret void
123+
}
124+
125+
; The difference from select_with_identical_phi() is that the true and false values in
126+
; same.as.v1 are swapped.
127+
; Check that %same.as.v1 can be folded.
128+
define void @select_with_identical_phi_3(ptr %m, ptr %n, i32 %count) {
129+
; CHECK-LABEL: @select_with_identical_phi_3(
130+
; CHECK-NEXT: entry:
131+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
132+
; CHECK: for.body:
133+
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
134+
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
135+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
136+
; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
137+
; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
138+
; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
139+
; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
140+
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
141+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
142+
; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
143+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
144+
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
145+
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
146+
; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
147+
; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
148+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
149+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
150+
; CHECK: exit:
151+
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
152+
; CHECK-NEXT: ret void
153+
;
154+
entry:
155+
br label %for.body
156+
157+
for.body: ; preds = %entry, %for.body
158+
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
159+
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
160+
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
161+
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
162+
%q = phi ptr [ %m, %entry ], [ %q.next, %for.body ]
163+
%c = phi ptr [ %n, %entry ], [ %c.next, %for.body ]
164+
%q.load = load float, ptr %q
165+
%c.load = load float, ptr %c
166+
%sub = fsub float %q.load, %c.load
167+
%cmp1 = fcmp olt float %sub, %v0
168+
%v0.1 = select i1 %cmp1, float %sub, float %v0
169+
%same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1
170+
%cmp2 = fcmp ogt float %sub, %same.as.v1
171+
%v1.1 = select i1 %cmp2, float %sub, float %v1
172+
%phi.to.remove.next = select i1 %cmp2, float %sub, float %same.as.v1
173+
%inc.i = add nuw nsw i32 %i, 1
174+
%q.next = getelementptr inbounds i8, ptr %q, i64 4
175+
%c.next = getelementptr inbounds i8, ptr %c, i64 4
176+
%exitcond = icmp eq i32 %inc.i, %count
177+
br i1 %exitcond, label %exit, label %for.body
178+
179+
exit:
180+
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
181+
store float %vl.1.lcssa, ptr @A
182+
ret void
183+
}
184+
185+
; The difference from select_with_identical_phi() is that the true and false values in
186+
; %same.as.v1, %phi.to.remove.next and %v1.1 are swapped.
187+
; Check that %same.as.v1 can be folded.
188+
define void @select_with_identical_phi_4(ptr %m, ptr %n, i32 %count) {
189+
; CHECK-LABEL: @select_with_identical_phi_4(
190+
; CHECK-NEXT: entry:
191+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
192+
; CHECK: for.body:
193+
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
194+
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
195+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
196+
; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
197+
; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
198+
; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
199+
; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
200+
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
201+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
202+
; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
203+
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
204+
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[V1]], float [[SUB]]
205+
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
206+
; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
207+
; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
208+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
209+
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
210+
; CHECK: exit:
211+
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
212+
; CHECK-NEXT: ret void
213+
;
214+
entry:
215+
br label %for.body
216+
217+
for.body: ; preds = %entry, %for.body
218+
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
219+
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
220+
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
221+
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
222+
%q = phi ptr [ %m, %entry ], [ %q.next, %for.body ]
223+
%c = phi ptr [ %n, %entry ], [ %c.next, %for.body ]
224+
%q.load = load float, ptr %q
225+
%c.load = load float, ptr %c
226+
%sub = fsub float %q.load, %c.load
227+
%cmp1 = fcmp olt float %sub, %v0
228+
%v0.1 = select i1 %cmp1, float %sub, float %v0
229+
%same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1
230+
%cmp2 = fcmp ogt float %sub, %same.as.v1
231+
%v1.1 = select i1 %cmp2, float %v1, float %sub
232+
%phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %sub
233+
%inc.i = add nuw nsw i32 %i, 1
234+
%q.next = getelementptr inbounds i8, ptr %q, i64 4
235+
%c.next = getelementptr inbounds i8, ptr %c, i64 4
236+
%exitcond = icmp eq i32 %inc.i, %count
237+
br i1 %exitcond, label %exit, label %for.body
238+
239+
exit:
240+
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
241+
store float %vl.1.lcssa, ptr @A
242+
ret void
243+
}

0 commit comments

Comments
 (0)