[llvm] 7906827 - [InstCombine] Recursively replace select value equivalence
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 21 06:55:52 PST 2022
Author: Nikita Popov
Date: 2022-12-21T15:55:44+01:00
New Revision: 79068275e7c99dfcc1bf17421b591312f775fa16
URL: https://github.com/llvm/llvm-project/commit/79068275e7c99dfcc1bf17421b591312f775fa16
DIFF: https://github.com/llvm/llvm-project/commit/79068275e7c99dfcc1bf17421b591312f775fa16.diff
LOG: [InstCombine] Recursively replace select value equivalence
In the X == C ? f(X) : Y -> X == C ? f(C) : Y fold, perform the
replacement in f(X) recursively. For now, this just goes two
instructions up rather than one instruction up.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/select-binop-cmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 88086458f31b..e95b86766b80 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1169,6 +1169,28 @@ static Instruction *canonicalizeSPF(SelectInst &Sel, ICmpInst &Cmp,
return nullptr;
}
+static bool replaceInInstruction(Value *V, Value *Old, Value *New,
+ InstCombiner &IC, unsigned Depth = 0) {
+ // Conservatively limit replacement to two instructions upwards.
+ if (Depth == 2)
+ return false;
+
+ auto *I = dyn_cast<Instruction>(V);
+ if (!I || !I->hasOneUse() || !isSafeToSpeculativelyExecute(I))
+ return false;
+
+ bool Changed = false;
+ for (Use &U : I->operands()) {
+ if (U == Old) {
+ IC.replaceUse(U, New);
+ Changed = true;
+ } else {
+ Changed |= replaceInInstruction(U, Old, New, IC, Depth + 1);
+ }
+ }
+ return Changed;
+}
+
/// If we have a select with an equality comparison, then we know the value in
/// one of the arms of the select. See if substituting this value into an arm
/// and simplifying the result yields the same value as the other arm.
@@ -1216,17 +1238,11 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
// with
diff erent operands, which should not cause side-effects or trigger
// undefined behavior). Only do this if CmpRHS is a constant, as
// profitability is not clear for other cases.
- // FIXME: The replacement could be performed recursively.
// FIXME: Support vectors.
if (match(CmpRHS, m_ImmConstant()) && !match(CmpLHS, m_ImmConstant()) &&
!Cmp.getType()->isVectorTy())
- if (auto *I = dyn_cast<Instruction>(TrueVal))
- if (I->hasOneUse() && isSafeToSpeculativelyExecute(I))
- for (Use &U : I->operands())
- if (U == CmpLHS) {
- replaceUse(U, CmpRHS);
- return &Sel;
- }
+ if (replaceInInstruction(TrueVal, CmpLHS, CmpRHS, *this))
+ return &Sel;
}
if (TrueVal != CmpRHS &&
isGuaranteedNotToBeUndefOrPoison(CmpLHS, SQ.AC, &Sel, &DT))
diff --git a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
index 9d57e8bf49e1..8a20b09c2990 100644
--- a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
@@ -1206,13 +1206,11 @@ define i32 @select_replace_fold(i32 %x, i32 %y, i32 %z) {
; Case where the use of %x is in a nested instruction.
-; FIXME: We only perform replacements one level up right now.
define i32 @select_replace_nested(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: @select_replace_nested(
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X]]
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], [[Z:%.*]]
-; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 [[ADD]], i32 [[Y]]
+; CHECK-NEXT: [[ADD:%.*]] = select i1 [[C]], i32 [[Z:%.*]], i32 0
+; CHECK-NEXT: [[S:%.*]] = add i32 [[ADD]], [[Y:%.*]]
; CHECK-NEXT: ret i32 [[S]]
;
%c = icmp eq i32 %x, 0
@@ -1242,7 +1240,7 @@ define i32 @select_replace_nested_extra_use(i32 %x, i32 %y, i32 %z) {
define i32 @select_replace_nested_no_simplify(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: @select_replace_nested_no_simplify(
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 1
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X]]
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[Y:%.*]], -1
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], [[Z:%.*]]
; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 [[ADD]], i32 [[Y]]
; CHECK-NEXT: ret i32 [[S]]
@@ -1254,6 +1252,7 @@ define i32 @select_replace_nested_no_simplify(i32 %x, i32 %y, i32 %z) {
ret i32 %s
}
+; FIXME: We only perform replacements two levels up right now.
define i32 @select_replace_deeply_nested(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: @select_replace_deeply_nested(
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0
More information about the llvm-commits
mailing list