Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ValueTracking] Improve isImpliedCondICmps to handle binops #69840

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Oct 21, 2023

This PR improves isImpliedCondICmps to handle the pattern R0 = L0 binop V.
Alive2: https://alive2.llvm.org/ce/z/B9nc5d
Fixes #68799.
Fixes #69038.

@llvmbot
Copy link
Member

llvmbot commented Oct 21, 2023

@llvm/pr-subscribers-backend-amdgpu
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Author: Yingwei Zheng (dtcxzyw)

Changes

This PR improves isImpliedCondICmps to handle the pattern R0 = L0 binop V.
Alive2: https://alive2.llvm.org/ce/z/PPCfP9
Fixes #68799.


Full diff: https://github.com/llvm/llvm-project/pull/69840.diff

4 Files Affected:

  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+41-7)
  • (added) llvm/test/Analysis/ValueTracking/implied-icmp-binop.ll (+193)
  • (modified) llvm/test/Transforms/InstCombine/icmp-or.ll (+4-14)
  • (modified) llvm/test/Transforms/InstCombine/icmp-power2-and-icmp-shifted-mask.ll (+8-32)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8824a05e3aa6ccd..e1fae66946e0e56 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8231,14 +8231,11 @@ isImpliedCondMatchingOperands(CmpInst::Predicate LPred,
   return std::nullopt;
 }
 
-/// Return true if "icmp LPred X, LC" implies "icmp RPred X, RC" is true.
-/// Return false if "icmp LPred X, LC" implies "icmp RPred X, RC" is false.
+/// Return true if `X in DomCR` implies `X in CR` is true.
+/// Return false if `X in DomCR` implies `X in CR` is false.
 /// Otherwise, return std::nullopt if we can't infer anything.
-static std::optional<bool> isImpliedCondCommonOperandWithConstants(
-    CmpInst::Predicate LPred, const APInt &LC, CmpInst::Predicate RPred,
-    const APInt &RC) {
-  ConstantRange DomCR = ConstantRange::makeExactICmpRegion(LPred, LC);
-  ConstantRange CR = ConstantRange::makeExactICmpRegion(RPred, RC);
+static std::optional<bool> isImpliedCondWithRange(const ConstantRange &DomCR,
+                                                  const ConstantRange &CR) {
   ConstantRange Intersection = DomCR.intersectWith(CR);
   ConstantRange Difference = DomCR.difference(CR);
   if (Intersection.isEmptySet())
@@ -8248,6 +8245,17 @@ static std::optional<bool> isImpliedCondCommonOperandWithConstants(
   return std::nullopt;
 }
 
+/// Return true if "icmp LPred X, LC" implies "icmp RPred X, RC" is true.
+/// Return false if "icmp LPred X, LC" implies "icmp RPred X, RC" is false.
+/// Otherwise, return std::nullopt if we can't infer anything.
+static std::optional<bool> isImpliedCondCommonOperandWithConstants(
+    CmpInst::Predicate LPred, const APInt &LC, CmpInst::Predicate RPred,
+    const APInt &RC) {
+  ConstantRange DomCR = ConstantRange::makeExactICmpRegion(LPred, LC);
+  ConstantRange CR = ConstantRange::makeExactICmpRegion(RPred, RC);
+  return isImpliedCondWithRange(DomCR, CR);
+}
+
 /// Return true if LHS implies RHS (expanded to its components as "R0 RPred R1")
 /// is true.  Return false if LHS implies RHS is false. Otherwise, return
 /// std::nullopt if we can't infer anything.
@@ -8298,6 +8306,32 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
       return LPred == RPred;
   }
 
+  // handle R0 = L0 binop V
+  Value *R0Op1 = nullptr;
+  if (match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)) &&
+      match(R0, m_c_BinOp(m_Specific(L0), m_Value(R0Op1)))) {
+    ConstantRange LHSRange = ConstantRange::makeExactICmpRegion(LPred, *LC);
+    ConstantRange CR = ConstantRange::makeExactICmpRegion(RPred, *RC);
+    // TODO: use contextual information from SimplifyQuery
+    ConstantRange RHSRange = computeConstantRange(
+        R0Op1, ICmpInst::isSigned(RPred), /*UseInstrInfo*/ true, /*AC*/ nullptr,
+        /*CtxI*/ nullptr, /*DT*/ nullptr, Depth);
+    auto BO = cast<BinaryOperator>(R0);
+    if (BO->getOperand(0) != L0)
+      std::swap(LHSRange, RHSRange);
+    unsigned NoWrapKind = 0;
+    if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO)) {
+      if (OBO->hasNoUnsignedWrap())
+        NoWrapKind |= OverflowingBinaryOperator::NoUnsignedWrap;
+      if (OBO->hasNoSignedWrap())
+        NoWrapKind |= OverflowingBinaryOperator::NoSignedWrap;
+    }
+    ConstantRange Range =
+        LHSRange.overflowingBinaryOp(BO->getOpcode(), RHSRange, NoWrapKind);
+    if (auto Res = isImpliedCondWithRange(Range, CR))
+      return Res;
+  }
+
   if (LPred == RPred)
     return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth);
 
diff --git a/llvm/test/Analysis/ValueTracking/implied-icmp-binop.ll b/llvm/test/Analysis/ValueTracking/implied-icmp-binop.ll
new file mode 100644
index 000000000000000..882c38f329bd884
--- /dev/null
+++ b/llvm/test/Analysis/ValueTracking/implied-icmp-binop.ll
@@ -0,0 +1,193 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+; Tests from PR68799
+
+define i1 @f_and(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_and(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %cmp = icmp ne i32 %x, 0
+  %0 = or i32 %x, %y
+  %and14 = icmp eq i32 %0, 0
+  %and1115 = and i1 %cmp, %and14
+  ret i1 %and1115
+}
+
+define i1 @f_or(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_or(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %cmp.not = icmp eq i32 %x, 0
+  %0 = or i32 %x, %y
+  %or14 = icmp ne i32 %0, 0
+  %or1115 = or i1 %cmp.not, %or14
+  ret i1 %or1115
+}
+
+; Tests for more binops
+
+define i1 @f_add(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_add(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %yr = and i32 %y, 7
+  %cmp = icmp ult i32 %x, 8
+  %0 = add i32 %yr, %x
+  %cmp2 = icmp ugt i32 %0, 16
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+define i1 @f_add_nsw(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_add_nsw(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %yr = and i32 %y, 2147483647
+  %cmp = icmp sgt i32 %x, 5
+  %0 = add nsw i32 %yr, %x
+  %cmp2 = icmp slt i32 %0, 5
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+define i1 @f_add_nuw(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_add_nuw(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %cmp = icmp ugt i32 %x, 1
+  %0 = add nuw i32 %x, %y
+  %cmp2 = icmp eq i32 %0, 1
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+define i1 @f_sub_nsw(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_sub_nsw(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], 5
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %yr = and i32 %y, 2147483647
+  %cmp = icmp slt i32 %x, 5
+  %0 = sub nsw i32 %x, %yr
+  %cmp2 = icmp slt i32 %0, 5
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+define i1 @f_sub_nuw(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_sub_nuw(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %cmp = icmp ult i32 %x, 5
+  %0 = sub nuw i32 %x, %y
+  %cmp2 = icmp eq i32 %0, 6
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+; Negative tests
+
+; non-constant range
+define i1 @f_add_nofold1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i1 @f_add_nofold1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[YR:%.*]] = and i32 [[Y]], 7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X]], [[Z]]
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[YR]], [[X]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[TMP0]], 16
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[AND]]
+;
+entry:
+  %yr = and i32 %y, 7
+  %cmp = icmp ult i32 %x, %z
+  %0 = add i32 %yr, %x
+  %cmp2 = icmp ugt i32 %0, 16
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+define i1 @f_add_nofold2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i1 @f_add_nofold2(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[YR:%.*]] = and i32 [[Y]], 7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X]], 8
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[YR]], [[X]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[TMP0]], [[Z]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[AND]]
+;
+entry:
+  %yr = and i32 %y, 7
+  %cmp = icmp ult i32 %x, 8
+  %0 = add i32 %yr, %x
+  %cmp2 = icmp ugt i32 %0, %z
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+; narrower range
+define i1 @f_add_nofold3(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_add_nofold3(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[YR:%.*]] = and i32 [[Y]], 7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X]], 8
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[YR]], [[X]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[TMP0]], 10
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[AND]]
+;
+entry:
+  %yr = and i32 %y, 7
+  %cmp = icmp ult i32 %x, 8
+  %0 = add i32 %yr, %x
+  %cmp2 = icmp ugt i32 %0, 10
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
+
+; sub is not commutative
+define i1 @f_sub_nsw_nofold(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @f_sub_nsw_nofold(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[YR:%.*]] = and i32 [[Y]], 2147483647
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], 5
+; CHECK-NEXT:    [[TMP0:%.*]] = sub nsw i32 [[YR]], [[X]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[TMP0]], 5
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[CMP2]]
+; CHECK-NEXT:    ret i1 [[AND]]
+;
+entry:
+  %yr = and i32 %y, 2147483647
+  %cmp = icmp slt i32 %x, 5
+  %0 = sub nsw i32 %yr, %x
+  %cmp2 = icmp slt i32 %0, 5
+  %and = and i1 %cmp, %cmp2
+  ret i1 %and
+}
diff --git a/llvm/test/Transforms/InstCombine/icmp-or.ll b/llvm/test/Transforms/InstCombine/icmp-or.ll
index 922845c1e7e2d82..a96341f31132943 100644
--- a/llvm/test/Transforms/InstCombine/icmp-or.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-or.ll
@@ -430,13 +430,8 @@ define i1 @icmp_or_xor_2_ne_fail(i64 %x1, i64 %y1, i64 %x2, i64 %y2) {
 
 define i1 @icmp_or_xor_2_3_fail(i64 %x1, i64 %y1, i64 %x2, i64 %y2) {
 ; CHECK-LABEL: @icmp_or_xor_2_3_fail(
-; CHECK-NEXT:    [[XOR:%.*]] = xor i64 [[X1:%.*]], [[Y1:%.*]]
-; CHECK-NEXT:    [[XOR1:%.*]] = xor i64 [[X2:%.*]], [[Y2:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = or i64 [[XOR]], [[XOR1]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 0
-; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i64 [[XOR]], 0
-; CHECK-NEXT:    [[OR1:%.*]] = or i1 [[CMP]], [[CMP_1]]
-; CHECK-NEXT:    ret i1 [[OR1]]
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i64 [[X1:%.*]], [[Y1:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP_1]]
 ;
   %xor = xor i64 %x1, %y1
   %xor1 = xor i64 %x2, %y2
@@ -451,13 +446,8 @@ define i1 @icmp_or_xor_2_3_fail(i64 %x1, i64 %y1, i64 %x2, i64 %y2) {
 
 define i1 @icmp_or_xor_2_4_fail(i64 %x1, i64 %y1, i64 %x2, i64 %y2) {
 ; CHECK-LABEL: @icmp_or_xor_2_4_fail(
-; CHECK-NEXT:    [[XOR:%.*]] = xor i64 [[X1:%.*]], [[Y1:%.*]]
-; CHECK-NEXT:    [[XOR1:%.*]] = xor i64 [[X2:%.*]], [[Y2:%.*]]
-; CHECK-NEXT:    [[OR:%.*]] = or i64 [[XOR]], [[XOR1]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[OR]], 0
-; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i64 [[XOR1]], 0
-; CHECK-NEXT:    [[OR1:%.*]] = or i1 [[CMP]], [[CMP_1]]
-; CHECK-NEXT:    ret i1 [[OR1]]
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i64 [[X2:%.*]], [[Y2:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP_1]]
 ;
   %xor = xor i64 %x1, %y1
   %xor1 = xor i64 %x2, %y2
diff --git a/llvm/test/Transforms/InstCombine/icmp-power2-and-icmp-shifted-mask.ll b/llvm/test/Transforms/InstCombine/icmp-power2-and-icmp-shifted-mask.ll
index 82fcca07a00ac66..27ecc5686066cf1 100644
--- a/llvm/test/Transforms/InstCombine/icmp-power2-and-icmp-shifted-mask.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-power2-and-icmp-shifted-mask.ll
@@ -250,10 +250,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_swapped_256_239_gap_in_mask_fail(i3
 define i1 @icmp_power2_and_icmp_shifted_mask_8_112_mask_to_left_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_8_112_mask_to_left_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 112
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 112
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 112
@@ -265,10 +262,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_8_112_mask_to_left_fail(i32 %x) {
 define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_112_mask_to_left_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_swapped_8_112_mask_to_left_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 112
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 112
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T3]], [[T1]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 112
@@ -281,10 +275,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_112_mask_to_left_fail(i32
 define i1 @icmp_power2_and_icmp_shifted_mask_8_56_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_8_56_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 56
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 56
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 56
@@ -296,10 +287,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_8_56_mask_overlap_fail(i32 %x) {
 define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_56_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_swapped_8_56_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 56
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 56
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T3]], [[T1]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 56
@@ -312,10 +300,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_56_mask_overlap_fail(i32
 define i1 @icmp_power2_and_icmp_shifted_mask_8_24_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_8_24_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 24
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 24
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 24
@@ -327,10 +312,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_8_24_mask_overlap_fail(i32 %x) {
 define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_24_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_swapped_8_24_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 24
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 24
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T3]], [[T1]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 24
@@ -343,10 +325,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_24_mask_overlap_fail(i32
 define i1 @icmp_power2_and_icmp_shifted_mask_8_12_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_8_12_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 12
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 12
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 12
@@ -358,10 +337,7 @@ define i1 @icmp_power2_and_icmp_shifted_mask_8_12_mask_overlap_fail(i32 %x) {
 define i1 @icmp_power2_and_icmp_shifted_mask_swapped_8_12_mask_overlap_fail(i32 %x) {
 ; CHECK-LABEL: @icmp_power2_and_icmp_shifted_mask_swapped_8_12_mask_overlap_fail(
 ; CHECK-NEXT:    [[T1:%.*]] = icmp ult i32 [[X:%.*]], 8
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[X]], 12
-; CHECK-NEXT:    [[T3:%.*]] = icmp ne i32 [[T2]], 12
-; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T3]], [[T1]]
-; CHECK-NEXT:    ret i1 [[T4]]
+; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t1 = icmp ult i32 %x, 8
   %t2 = and i32 %x, 12

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Oct 21, 2023

Failed Tests (8):
  | LLVM :: CodeGen/AMDGPU/sdiv64.ll
  | LLVM :: CodeGen/AMDGPU/srem64.ll
  | LLVM :: CodeGen/AMDGPU/udiv64.ll
  | LLVM :: CodeGen/AMDGPU/urem64.ll
  | LLVM :: CodeGen/PowerPC/reduce_cr.ll
  | LLVM :: CodeGen/PowerPC/tail-dup-layout.ll
  | LLVM :: CodeGen/Thumb2/mve-float16regloops.ll
  | LLVM :: CodeGen/Thumb2/mve-float32regloops.ll

I will update the failed tests soon.

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Nov 11, 2023

Ping.

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Dec 16, 2023

Ping.

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Dec 22, 2023
@dtcxzyw
Copy link
Member Author

dtcxzyw commented Dec 22, 2023

Ping.

@nikic
Copy link
Contributor

nikic commented Dec 22, 2023

This is a specific instance of the general "optimize using constant range at use" problem, and I'm not convinced that extending isImpliedCond() in this direction makes sense. I'm not sure what the best way to approach this is yet.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs update to main, also last comment questions approach

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Feb 7, 2024

@nikic @arsenm Should I abandon this patch?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[InstCombine] a && (a | b) is not simplified AND with == 0 and OR with != 0
5 participants