[llvm] [LVI] Remove support for SPF selects (PR #115305)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 03:53:49 PST 2024


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/115305

None

>From 6b88b7f1d2ffa2335f92530d70a8f1dc50b27e57 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 7 Nov 2024 12:50:34 +0100
Subject: [PATCH] [LVI] Remove support for SPF selects

---
 llvm/lib/Analysis/LazyValueInfo.cpp           | 50 -------------------
 .../CorrelatedValuePropagation/basic.ll       | 44 ++++++++++------
 .../do-not-handle-impossible-values.ll        | 12 ++---
 3 files changed, 32 insertions(+), 74 deletions(-)

diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 42b04046ce10d3..f0cb6604c60e36 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -804,56 +804,6 @@ LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) {
     return std::nullopt;
   ValueLatticeElement &FalseVal = *OptFalseVal;
 
-  if (TrueVal.isConstantRange() || FalseVal.isConstantRange()) {
-    const ConstantRange &TrueCR = TrueVal.asConstantRange(SI->getType());
-    const ConstantRange &FalseCR = FalseVal.asConstantRange(SI->getType());
-    Value *LHS = nullptr;
-    Value *RHS = nullptr;
-    SelectPatternResult SPR = matchSelectPattern(SI, LHS, RHS);
-    // Is this a min specifically of our two inputs?  (Avoid the risk of
-    // ValueTracking getting smarter looking back past our immediate inputs.)
-    if (SelectPatternResult::isMinOrMax(SPR.Flavor) &&
-        ((LHS == SI->getTrueValue() && RHS == SI->getFalseValue()) ||
-         (RHS == SI->getTrueValue() && LHS == SI->getFalseValue()))) {
-      ConstantRange ResultCR = [&]() {
-        switch (SPR.Flavor) {
-        default:
-          llvm_unreachable("unexpected minmax type!");
-        case SPF_SMIN:                   /// Signed minimum
-          return TrueCR.smin(FalseCR);
-        case SPF_UMIN:                   /// Unsigned minimum
-          return TrueCR.umin(FalseCR);
-        case SPF_SMAX:                   /// Signed maximum
-          return TrueCR.smax(FalseCR);
-        case SPF_UMAX:                   /// Unsigned maximum
-          return TrueCR.umax(FalseCR);
-        };
-      }();
-      return ValueLatticeElement::getRange(
-          ResultCR, TrueVal.isConstantRangeIncludingUndef() ||
-                        FalseVal.isConstantRangeIncludingUndef());
-    }
-
-    if (SPR.Flavor == SPF_ABS) {
-      if (LHS == SI->getTrueValue())
-        return ValueLatticeElement::getRange(
-            TrueCR.abs(), TrueVal.isConstantRangeIncludingUndef());
-      if (LHS == SI->getFalseValue())
-        return ValueLatticeElement::getRange(
-            FalseCR.abs(), FalseVal.isConstantRangeIncludingUndef());
-    }
-
-    if (SPR.Flavor == SPF_NABS) {
-      ConstantRange Zero(APInt::getZero(TrueCR.getBitWidth()));
-      if (LHS == SI->getTrueValue())
-        return ValueLatticeElement::getRange(
-            Zero.sub(TrueCR.abs()), FalseVal.isConstantRangeIncludingUndef());
-      if (LHS == SI->getFalseValue())
-        return ValueLatticeElement::getRange(
-            Zero.sub(FalseCR.abs()), FalseVal.isConstantRangeIncludingUndef());
-    }
-  }
-
   // Can we constrain the facts about the true and false values by using the
   // condition itself?  This shows up with idioms like e.g. select(a > 5, a, 5).
   // TODO: We could potentially refine an overdefined true value above.
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
index 3c3b1d4bef45bb..f7cdd3c0036224 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
@@ -581,7 +581,8 @@ define i1 @umin(i32 %a, i32 %b) {
 ; CHECK:       b_guard:
 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MIN]], 7
+; CHECK-NEXT:    ret i1 [[RES]]
 ; CHECK:       out:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -614,7 +615,8 @@ define i1 @smin(i32 %a, i32 %b) {
 ; CHECK:       b_guard:
 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp ule i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MIN]], 7
+; CHECK-NEXT:    ret i1 [[RES]]
 ; CHECK:       out:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -647,7 +649,8 @@ define i1 @smax(i32 %a, i32 %b) {
 ; CHECK:       b_guard:
 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MAX]], 7
+; CHECK-NEXT:    ret i1 [[RES]]
 ; CHECK:       out:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -680,7 +683,8 @@ define i1 @umax(i32 %a, i32 %b) {
 ; CHECK:       b_guard:
 ; CHECK-NEXT:    [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[MAX]], 7
+; CHECK-NEXT:    ret i1 [[RES]]
 ; CHECK:       out:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -706,7 +710,8 @@ define i1 @umin_lhs_overdefined_rhs_const(i32 %a) {
 ; CHECK-SAME: (i32 [[A:%.*]]) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], 42
 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 42
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[SEL]], 42
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp ult i32 %a, 42
   %sel = select i1 %cmp, i32 %a, i32 42
@@ -719,7 +724,8 @@ define i1 @umin_rhs_overdefined_lhs_const(i32 %a) {
 ; CHECK-SAME: (i32 [[A:%.*]]) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A]], 42
 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[A]]
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[SEL]], 42
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %cmp = icmp uge i32 %a, 42
   %sel = select i1 %cmp, i32 42, i32 %a
@@ -734,7 +740,8 @@ define i1 @umin_lhs_overdefined_rhs_range(i32 %a, i32 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]]
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[SEL]], 42
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %assume = icmp ult i32 %b, 42
   call void @llvm.assume(i1 %assume)
@@ -751,7 +758,8 @@ define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME]])
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]]
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[SEL]], 42
+; CHECK-NEXT:    ret i1 [[CMP2]]
 ;
   %assume = icmp ult i32 %b, 42
   call void @llvm.assume(i1 %assume)
@@ -1085,10 +1093,11 @@ define void @abs1(i32 %a, ptr %p) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], 0
 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
-; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[ABS]], 19
+; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[ABS]], 19
 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
-; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
-; CHECK-NEXT:    [[C4:%.*]] = icmp uge i32 [[ABS]], 1
+; CHECK-NEXT:    [[C3:%.*]] = icmp sge i32 [[ABS]], 0
+; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
+; CHECK-NEXT:    [[C4:%.*]] = icmp sge i32 [[ABS]], 1
 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
@@ -1131,10 +1140,11 @@ define void @abs2(i32 %a, ptr %p) {
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], 0
 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]]
 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
-; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[ABS]], 19
+; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[ABS]], 19
 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
-; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
-; CHECK-NEXT:    [[C4:%.*]] = icmp uge i32 [[ABS]], 1
+; CHECK-NEXT:    [[C3:%.*]] = icmp sge i32 [[ABS]], 0
+; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
+; CHECK-NEXT:    [[C4:%.*]] = icmp sge i32 [[ABS]], 1
 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
@@ -1179,7 +1189,8 @@ define void @nabs1(i32 %a, ptr %p) {
 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
 ; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
-; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
+; CHECK-NEXT:    [[C3:%.*]] = icmp sle i32 [[NABS]], 0
+; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
 ; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
 ; CHECK-NEXT:    br label [[EXIT]]
@@ -1225,7 +1236,8 @@ define void @nabs2(i32 %a, ptr %p) {
 ; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
 ; CHECK-NEXT:    [[C2:%.*]] = icmp sgt i32 [[NABS]], -19
 ; CHECK-NEXT:    store i1 [[C2]], ptr [[P]], align 1
-; CHECK-NEXT:    store i1 true, ptr [[P]], align 1
+; CHECK-NEXT:    [[C3:%.*]] = icmp sle i32 [[NABS]], 0
+; CHECK-NEXT:    store i1 [[C3]], ptr [[P]], align 1
 ; CHECK-NEXT:    [[C4:%.*]] = icmp sle i32 [[NABS]], -1
 ; CHECK-NEXT:    store i1 [[C4]], ptr [[P]], align 1
 ; CHECK-NEXT:    br label [[EXIT]]
diff --git a/llvm/test/Transforms/LowerSwitch/do-not-handle-impossible-values.ll b/llvm/test/Transforms/LowerSwitch/do-not-handle-impossible-values.ll
index 64ef5829890669..b806e1282b1671 100644
--- a/llvm/test/Transforms/LowerSwitch/do-not-handle-impossible-values.ll
+++ b/llvm/test/Transforms/LowerSwitch/do-not-handle-impossible-values.ll
@@ -801,10 +801,8 @@ define i32 @test16(float %f) {
 ; CHECK-LABEL: @test16(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[I:%.*]] = fptosi float [[F:%.*]] to i64
-; CHECK-NEXT:    [[COND_LEFT:%.*]] = icmp slt i64 [[I]], 0
-; CHECK-NEXT:    [[CLAMP_LEFT:%.*]] = select i1 [[COND_LEFT]], i64 0, i64 [[I]]
-; CHECK-NEXT:    [[COND_RIGHT:%.*]] = icmp sgt i64 [[I]], 3
-; CHECK-NEXT:    [[CLAMP:%.*]] = select i1 [[COND_RIGHT]], i64 3, i64 [[CLAMP_LEFT]]
+; CHECK-NEXT:    [[CLAMP_LEFT:%.*]] = call i64 @llvm.smax.i64(i64 [[I]], i64 0)
+; CHECK-NEXT:    [[CLAMP:%.*]] = call i64 @llvm.smin.i64(i64 [[CLAMP_LEFT]], i64 3)
 ; CHECK-NEXT:    br label [[LEAFBLOCK:%.*]]
 ; CHECK:       LeafBlock:
 ; CHECK-NEXT:    [[SWITCHLEAF:%.*]] = icmp sge i64 [[CLAMP]], 2
@@ -821,10 +819,8 @@ define i32 @test16(float %f) {
 ;
 entry:
   %i = fptosi float %f to i64
-  %cond.left = icmp slt i64 %i, 0
-  %clamp.left = select i1 %cond.left, i64 0, i64 %i
-  %cond.right = icmp sgt i64 %i, 3
-  %clamp = select i1 %cond.right, i64 3, i64 %clamp.left
+  %clamp.left = call i64 @llvm.smax(i64 %i, i64 0)
+  %clamp = call i64 @llvm.smin(i64 %clamp.left, i64 3)
   switch i64 %clamp, label %case.D [
   i64 0, label %case.1
   i64 1, label %case.1



More information about the llvm-commits mailing list