Skip to content

Commit a3c3705

Browse files
committed
[InstCombine] Improve coverage of foldSelectValueEquivalence for constants
We don't need the `noundef` check if the new simplification is a constant. This cleans up regressions from folding multiuse: `(icmp eq/ne (sub/xor x, y), 0)` -> `(icmp eq/ne x, y)`.
1 parent c9c544c commit a3c3705

File tree

3 files changed

+38
-32
lines changed

3 files changed

+38
-32
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,40 +1288,51 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
12881288
Swapped = true;
12891289
}
12901290

1291-
// In X == Y ? f(X) : Z, try to evaluate f(Y) and replace the operand.
1292-
// Make sure Y cannot be undef though, as we might pick different values for
1293-
// undef in the icmp and in f(Y). Additionally, take care to avoid replacing
1294-
// X == Y ? X : Z with X == Y ? Y : Z, as that would lead to an infinite
1295-
// replacement cycle.
12961291
Value *CmpLHS = Cmp.getOperand(0), *CmpRHS = Cmp.getOperand(1);
1297-
if (TrueVal != CmpLHS &&
1298-
isGuaranteedNotToBeUndefOrPoison(CmpRHS, SQ.AC, &Sel, &DT)) {
1299-
if (Value *V = simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, SQ,
1300-
/* AllowRefinement */ true))
1301-
// Require either the replacement or the simplification result to be a
1302-
// constant to avoid infinite loops.
1303-
// FIXME: Make this check more precise.
1304-
if (isa<Constant>(CmpRHS) || isa<Constant>(V))
1292+
auto ReplaceOldOpWithNewOp = [&](Value *OldOp,
1293+
Value *NewOp) -> Instruction * {
1294+
// In X == Y ? f(X) : Z, try to evaluate f(Y) and replace the operand.
1295+
// Take care to avoid replacing X == Y ? X : Z with X == Y ? Y : Z, as that
1296+
// would lead to an infinite replacement cycle.
1297+
// If we will be able to evaluate f(Y) to a constant, we can allow undef,
1298+
// otherwise Y cannot be undef as we might pick different values for undef
1299+
// in the icmp and in f(Y).
1300+
if (TrueVal == OldOp)
1301+
return nullptr;
1302+
1303+
if (Value *V = simplifyWithOpReplaced(TrueVal, OldOp, NewOp, SQ,
1304+
/* AllowRefinement= */ true)) {
1305+
// Need some guarantees about the new simplified op to ensure we don't inf
1306+
// loop.
1307+
// If we simplify to a constant, replace.
1308+
if (match(V, m_ImmConstant()))
13051309
return replaceOperand(Sel, Swapped ? 2 : 1, V);
13061310

1311+
// If NewOp is a constant and OldOp is not replace iff NewOp doesn't
1312+
// contain and undef/poison elements.
1313+
if (match(NewOp, m_ImmConstant()) &&
1314+
isGuaranteedNotToBeUndefOrPoison(NewOp, SQ.AC, &Sel, &DT))
1315+
return replaceOperand(Sel, Swapped ? 2 : 1, V);
1316+
}
1317+
13071318
// Even if TrueVal does not simplify, we can directly replace a use of
13081319
// CmpLHS with CmpRHS, as long as the instruction is not used anywhere
13091320
// else and is safe to speculatively execute (we may end up executing it
13101321
// with different operands, which should not cause side-effects or trigger
13111322
// undefined behavior). Only do this if CmpRHS is a constant, as
13121323
// profitability is not clear for other cases.
13131324
// FIXME: Support vectors.
1314-
if (match(CmpRHS, m_ImmConstant()) && !match(CmpLHS, m_ImmConstant()) &&
1315-
!Cmp.getType()->isVectorTy())
1316-
if (replaceInInstruction(TrueVal, CmpLHS, CmpRHS))
1325+
if (OldOp == CmpLHS && match(NewOp, m_ImmConstant()) &&
1326+
!match(OldOp, m_ImmConstant()) && !Cmp.getType()->isVectorTy())
1327+
if (replaceInInstruction(TrueVal, OldOp, NewOp))
13171328
return &Sel;
1318-
}
1319-
if (TrueVal != CmpRHS &&
1320-
isGuaranteedNotToBeUndefOrPoison(CmpLHS, SQ.AC, &Sel, &DT))
1321-
if (Value *V = simplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, SQ,
1322-
/* AllowRefinement */ true))
1323-
if (isa<Constant>(CmpLHS) || isa<Constant>(V))
1324-
return replaceOperand(Sel, Swapped ? 2 : 1, V);
1329+
return nullptr;
1330+
};
1331+
1332+
if (Instruction *R = ReplaceOldOpWithNewOp(CmpLHS, CmpRHS))
1333+
return R;
1334+
if (Instruction *R = ReplaceOldOpWithNewOp(CmpRHS, CmpLHS))
1335+
return R;
13251336

13261337
auto *FalseInst = dyn_cast<Instruction>(FalseVal);
13271338
if (!FalseInst)

llvm/test/Transforms/InstCombine/abs-1.ll

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -852,11 +852,8 @@ define i8 @abs_diff_signed_sgt_nuw_extra_use3(i8 %a, i8 %b) {
852852

853853
define i32 @abs_diff_signed_slt_swap_wrong_pred1(i32 %a, i32 %b) {
854854
; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_pred1(
855-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
856-
; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]]
857-
; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]]
858-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BA]], i32 [[SUB_AB]]
859-
; CHECK-NEXT: ret i32 [[COND]]
855+
; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A:%.*]], [[B:%.*]]
856+
; CHECK-NEXT: ret i32 [[SUB_AB]]
860857
;
861858
%cmp = icmp eq i32 %a, %b
862859
%sub_ba = sub nsw i32 %b, %a

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2787,8 +2787,7 @@ define <2 x i8> @select_replacement_add_eq_vec_nonuniform(<2 x i8> %x, <2 x i8>
27872787
define <2 x i8> @select_replacement_add_eq_vec_poison(<2 x i8> %x, <2 x i8> %y) {
27882788
; CHECK-LABEL: @select_replacement_add_eq_vec_poison(
27892789
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 1, i8 poison>
2790-
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], <i8 1, i8 1>
2791-
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[ADD]], <2 x i8> [[Y:%.*]]
2790+
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 poison>, <2 x i8> [[Y:%.*]]
27922791
; CHECK-NEXT: ret <2 x i8> [[SEL]]
27932792
;
27942793
%cmp = icmp eq <2 x i8> %x, <i8 1, i8 poison>
@@ -2839,8 +2838,7 @@ define i8 @select_replacement_sub_noundef(i8 %x, i8 noundef %y, i8 %z) {
28392838
define i8 @select_replacement_sub(i8 %x, i8 %y, i8 %z) {
28402839
; CHECK-LABEL: @select_replacement_sub(
28412840
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
2842-
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X]], [[Y]]
2843-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[SUB]], i8 [[Z:%.*]]
2841+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 0, i8 [[Z:%.*]]
28442842
; CHECK-NEXT: ret i8 [[SEL]]
28452843
;
28462844
%cmp = icmp eq i8 %x, %y

0 commit comments

Comments
 (0)