Skip to content

Commit b189b89

Browse files
authored
[InstCombine] Relax the conditons of fold of ucmp/scmp into phi by allowing the phi node to use the result of ucmp/scmp more than once (#109593)
This extends the optimisation implemented in #107769 by relaxing the condtions to make it happen. Now, the value produced by `ucmp`/`scmp` doesn't need to be one-use, but only one-user, meaning it can be present in a single phi node more than once.
1 parent bf79156 commit b189b89

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

+14-11
Original file line numberDiff line numberDiff line change
@@ -1826,11 +1826,8 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
18261826
// If the only use of phi is comparing it with a constant then we can
18271827
// put this comparison in the incoming BB directly after a ucmp/scmp call
18281828
// because we know that it will simplify to a single icmp.
1829-
// NOTE: the single-use check here is not only to ensure that the
1830-
// optimization is profitable, but also to avoid creating a potentially
1831-
// invalid phi node when we have a multi-edge in the CFG.
18321829
const APInt *Ignored;
1833-
if (isa<CmpIntrinsic>(InVal) && InVal->hasOneUse() &&
1830+
if (isa<CmpIntrinsic>(InVal) && InVal->hasOneUser() &&
18341831
match(&I, m_ICmp(m_Specific(PN), m_APInt(Ignored)))) {
18351832
OpsToMoveUseToIncomingBB.push_back(i);
18361833
NewPhiValues.push_back(nullptr);
@@ -1868,18 +1865,24 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
18681865

18691866
// Clone the instruction that uses the phi node and move it into the incoming
18701867
// BB because we know that the next iteration of InstCombine will simplify it.
1868+
SmallDenseMap<BasicBlock *, Instruction *> Clones;
18711869
for (auto OpIndex : OpsToMoveUseToIncomingBB) {
18721870
Value *Op = PN->getIncomingValue(OpIndex);
18731871
BasicBlock *OpBB = PN->getIncomingBlock(OpIndex);
18741872

1875-
Instruction *Clone = I.clone();
1876-
for (Use &U : Clone->operands()) {
1877-
if (U == PN)
1878-
U = Op;
1879-
else
1880-
U = U->DoPHITranslation(PN->getParent(), OpBB);
1873+
Instruction *Clone = Clones.lookup(OpBB);
1874+
if (!Clone) {
1875+
Clone = I.clone();
1876+
for (Use &U : Clone->operands()) {
1877+
if (U == PN)
1878+
U = Op;
1879+
else
1880+
U = U->DoPHITranslation(PN->getParent(), OpBB);
1881+
}
1882+
Clone = InsertNewInstBefore(Clone, OpBB->getTerminator()->getIterator());
1883+
Clones.insert({OpBB, Clone});
18811884
}
1882-
Clone = InsertNewInstBefore(Clone, OpBB->getTerminator()->getIterator());
1885+
18831886
NewPhiValues[OpIndex] = Clone;
18841887
}
18851888

llvm/test/Transforms/InstCombine/phi-with-multiple-unsimplifiable-values.ll

+32
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,35 @@ exit:
133133
%r = icmp slt i8 %phi, 0
134134
ret i1 %r
135135
}
136+
137+
; Same as the first transformation, but the phi node uses the result of scmp twice. This verifies that we don't clone values more than once per block
138+
define i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses(i8 %c, i16 %x, i16 %y, i8 %false_val) {
139+
; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_one_user_two_uses(
140+
; CHECK-SAME: i8 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) {
141+
; CHECK-NEXT: [[ENTRY:.*]]:
142+
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]]
143+
; CHECK-NEXT: switch i8 [[C]], label %[[BB_2:.*]] [
144+
; CHECK-NEXT: i8 0, label %[[BB:.*]]
145+
; CHECK-NEXT: i8 1, label %[[BB]]
146+
; CHECK-NEXT: ]
147+
; CHECK: [[BB_2]]:
148+
; CHECK-NEXT: br label %[[BB]]
149+
; CHECK: [[BB]]:
150+
; CHECK-NEXT: [[R:%.*]] = phi i1 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP0]], %[[ENTRY]] ], [ false, %[[BB_2]] ]
151+
; CHECK-NEXT: ret i1 [[R]]
152+
;
153+
entry:
154+
%cmp = call i8 @llvm.scmp(i16 %x, i16 %y)
155+
switch i8 %c, label %bb_2 [
156+
i8 0, label %bb
157+
i8 1, label %bb
158+
]
159+
160+
bb_2:
161+
br label %bb
162+
163+
bb:
164+
%phi = phi i8 [ %cmp, %entry ], [ %cmp, %entry ], [ 0, %bb_2 ]
165+
%r = icmp slt i8 %phi, 0
166+
ret i1 %r
167+
}

0 commit comments

Comments
 (0)