summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYingwei Zheng <dtcxzyw2333@gmail.com>2024-01-06 02:32:57 +0800
committerGitHub <noreply@github.com>2024-01-06 02:32:57 +0800
commit848d7af956442fbf08310cc2d094035802fbe6ea (patch)
treec6429f26e573d374c379440a4bbc2d1ddbb12393
parent0cb98167ecee4b8e91fb07cb186daae616045454 (diff)
[CVP] Improve the value solving of select at use (#76700)
This patch improves the value solving of select at use if the condition is an icmp and we know the result of comparison from `LVI->getPredicateAt`. Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=7e405eb722e40c79b7726201d0f76b5dab34ba0f&to=3c315b1ddcb0ad82554b33f08b9356679fae4bb7&stat=instructions:u |stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang| |--|--|--|--|--|--|--| |-0.01%|+0.01%|-0.00%|-0.00%|-0.08%|+0.02%|-0.01%|
-rw-r--r--llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp51
-rw-r--r--llvm/test/Transforms/CorrelatedValuePropagation/select.ll23
2 files changed, 49 insertions, 25 deletions
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index c44d3748a80d..9235850de92f 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -94,6 +94,31 @@ STATISTIC(NumUDivURemsNarrowedExpanded,
"Number of bound udiv's/urem's expanded");
STATISTIC(NumZExt, "Number of non-negative deductions");
+static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
+ if (Constant *C = LVI->getConstant(V, At))
+ return C;
+
+ // TODO: The following really should be sunk inside LVI's core algorithm, or
+ // at least the outer shims around such.
+ auto *C = dyn_cast<CmpInst>(V);
+ if (!C)
+ return nullptr;
+
+ Value *Op0 = C->getOperand(0);
+ Constant *Op1 = dyn_cast<Constant>(C->getOperand(1));
+ if (!Op1)
+ return nullptr;
+
+ LazyValueInfo::Tristate Result = LVI->getPredicateAt(
+ C->getPredicate(), Op0, Op1, At, /*UseBlockValue=*/false);
+ if (Result == LazyValueInfo::Unknown)
+ return nullptr;
+
+ return (Result == LazyValueInfo::True)
+ ? ConstantInt::getTrue(C->getContext())
+ : ConstantInt::getFalse(C->getContext());
+}
+
static bool processSelect(SelectInst *S, LazyValueInfo *LVI) {
if (S->getType()->isVectorTy() || isa<Constant>(S->getCondition()))
return false;
@@ -106,7 +131,7 @@ static bool processSelect(SelectInst *S, LazyValueInfo *LVI) {
C = LVI->getConstantOnEdge(S->getCondition(), PN->getIncomingBlock(U),
I->getParent(), I);
else
- C = LVI->getConstant(S->getCondition(), I);
+ C = getConstantAt(S->getCondition(), I, LVI);
auto *CI = dyn_cast_or_null<ConstantInt>(C);
if (!CI)
@@ -1109,30 +1134,6 @@ static bool processAnd(BinaryOperator *BinOp, LazyValueInfo *LVI) {
return true;
}
-
-static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
- if (Constant *C = LVI->getConstant(V, At))
- return C;
-
- // TODO: The following really should be sunk inside LVI's core algorithm, or
- // at least the outer shims around such.
- auto *C = dyn_cast<CmpInst>(V);
- if (!C) return nullptr;
-
- Value *Op0 = C->getOperand(0);
- Constant *Op1 = dyn_cast<Constant>(C->getOperand(1));
- if (!Op1) return nullptr;
-
- LazyValueInfo::Tristate Result = LVI->getPredicateAt(
- C->getPredicate(), Op0, Op1, At, /*UseBlockValue=*/false);
- if (Result == LazyValueInfo::Unknown)
- return nullptr;
-
- return (Result == LazyValueInfo::True) ?
- ConstantInt::getTrue(C->getContext()) :
- ConstantInt::getFalse(C->getContext());
-}
-
static bool runImpl(Function &F, LazyValueInfo *LVI, DominatorTree *DT,
const SimplifyQuery &SQ) {
bool FnChanged = false;
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/select.ll b/llvm/test/Transforms/CorrelatedValuePropagation/select.ll
index 28a8516a9102..9842328db702 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/select.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/select.ll
@@ -372,4 +372,27 @@ define i64 @select_cond_may_undef(i32 %a) {
ret i64 %max
}
+define i32 @test_solve_select_at_use(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: define i32 @test_solve_select_at_use
+; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], -1
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i32 [[C]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i32 [[B]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 0
+ %retval = select i1 %cmp, i32 %b, i32 %c
+ %cond = icmp sgt i32 %a, -1
+ br i1 %cond, label %if.then, label %if.else
+if.then:
+ ret i32 %retval
+if.else:
+ ret i32 %retval
+}
+
!0 = !{}