[llvm] InstCombine/Select: remove redundant code (NFC) (PR #112388)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 09:15:59 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Ramkumar Ramachandra (artagnon)

<details>
<summary>Changes</summary>

InstCombinerImpl::foldSelectInstWithICmp has some inlined code for select-icmp-xor simplification, but this simplification is already done by other code. Cover the cases that it claims to simplify, and demonstrate that stripping it doesn't cause test changes.

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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (-50) 
- (added) llvm/test/Transforms/InstCombine/select-icmp-xor.ll (+190) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 820d3608c8dc49..39a6e8e191eb28 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1953,56 +1953,6 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
     return &SI;
   }
 
-  // FIXME: This code is nearly duplicated in InstSimplify. Using/refactoring
-  // decomposeBitTestICmp() might help.
-  if (TrueVal->getType()->isIntOrIntVectorTy()) {
-    unsigned BitWidth =
-        DL.getTypeSizeInBits(TrueVal->getType()->getScalarType());
-    APInt MinSignedValue = APInt::getSignedMinValue(BitWidth);
-    Value *X;
-    const APInt *Y, *C;
-    bool TrueWhenUnset;
-    bool IsBitTest = false;
-    if (ICmpInst::isEquality(Pred) &&
-        match(CmpLHS, m_And(m_Value(X), m_Power2(Y))) &&
-        match(CmpRHS, m_Zero())) {
-      IsBitTest = true;
-      TrueWhenUnset = Pred == ICmpInst::ICMP_EQ;
-    } else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) {
-      X = CmpLHS;
-      Y = &MinSignedValue;
-      IsBitTest = true;
-      TrueWhenUnset = false;
-    } else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) {
-      X = CmpLHS;
-      Y = &MinSignedValue;
-      IsBitTest = true;
-      TrueWhenUnset = true;
-    }
-    if (IsBitTest) {
-      Value *V = nullptr;
-      // (X & Y) == 0 ? X : X ^ Y  --> X & ~Y
-      if (TrueWhenUnset && TrueVal == X &&
-          match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
-        V = Builder.CreateAnd(X, ~(*Y));
-      // (X & Y) != 0 ? X ^ Y : X  --> X & ~Y
-      else if (!TrueWhenUnset && FalseVal == X &&
-               match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
-        V = Builder.CreateAnd(X, ~(*Y));
-      // (X & Y) == 0 ? X ^ Y : X  --> X | Y
-      else if (TrueWhenUnset && FalseVal == X &&
-               match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
-        V = Builder.CreateOr(X, *Y);
-      // (X & Y) != 0 ? X : X ^ Y  --> X | Y
-      else if (!TrueWhenUnset && TrueVal == X &&
-               match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C)
-        V = Builder.CreateOr(X, *Y);
-
-      if (V)
-        return replaceInstUsesWith(SI, V);
-    }
-  }
-
   if (Instruction *V =
           foldSelectICmpAndAnd(SI.getType(), ICI, TrueVal, FalseVal, Builder))
     return V;
diff --git a/llvm/test/Transforms/InstCombine/select-icmp-xor.ll b/llvm/test/Transforms/InstCombine/select-icmp-xor.ll
new file mode 100644
index 00000000000000..c8ce114a683eee
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/select-icmp-xor.ll
@@ -0,0 +1,190 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=instcombine -S %s | FileCheck %s
+
+define i8 @select_icmp_eq_pow2(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_eq_pow2(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = and i8 [[X]], -5
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 4
+  %icmp = icmp eq i8 %and, 0
+  %xor = xor i8 %x, 4
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_eq_pow2_flipped(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_eq_pow2_flipped(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = or i8 [[X]], 4
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 4
+  %icmp = icmp eq i8 %and, 0
+  %xor = xor i8 %x, 4
+  %sel = select i1 %icmp, i8 %xor, i8 %x
+  ret i8 %sel
+}
+
+define i8 @select_icmp_eq_not_pow2(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_eq_not_pow2(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], 5
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], 5
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 5
+  %icmp = icmp eq i8 %and, 0
+  %xor = xor i8 %x, 5
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_ne_pow2(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_ne_pow2(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = and i8 [[X]], -5
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 4
+  %icmp = icmp ne i8 %and, 0
+  %xor = xor i8 %x, 4
+  %sel = select i1 %icmp, i8 %xor, i8 %x
+  ret i8 %sel
+}
+
+define i8 @select_icmp_ne_pow2_flipped(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_ne_pow2_flipped(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = or i8 [[X]], 4
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 4
+  %icmp = icmp ne i8 %and, 0
+  %xor = xor i8 %x, 4
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_ne_not_pow2(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_ne_not_pow2(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], 5
+; CHECK-NEXT:    [[ICMP_NOT:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], 5
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP_NOT]], i8 [[X]], i8 [[XOR]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %and = and i8 %x, 5
+  %icmp = icmp ne i8 %and, 0
+  %xor = xor i8 %x, 5
+  %sel = select i1 %icmp, i8 %xor, i8 %x
+  ret i8 %sel
+}
+
+define i8 @select_icmp_slt_zero_smin(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_slt_zero_smin(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = or i8 [[X]], -128
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp slt i8 %x, 0
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_slt_zero_smin_flipped(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_slt_zero_smin_flipped(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = and i8 [[X]], 127
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp slt i8 %x, 0
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %xor, i8 %x
+  ret i8 %sel
+}
+
+define i8 @select_icmp_slt_not_zero(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_slt_not_zero(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp slt i8 [[X]], 1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], -128
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp slt i8 %x, 1
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_slt_not_smin(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_slt_not_smin(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp slt i8 [[X]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], -127
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp slt i8 %x, 0
+  %xor = xor i8 %x, -127
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_sgt_allones_smin(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_sgt_allones_smin(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = and i8 [[X]], 127
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp sgt i8 %x, 255
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_sgt_allones_smin_flipped(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_sgt_allones_smin_flipped(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = or i8 [[X]], -128
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp sgt i8 %x, 255
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %xor, i8 %x
+  ret i8 %sel
+}
+
+define i8 @select_icmp_sgt_not_allones(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_sgt_not_allones(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp sgt i8 [[X]], -2
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], -128
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP]], i8 [[X]], i8 [[XOR]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp sgt i8 %x, 254
+  %xor = xor i8 %x, -128
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}
+
+define i8 @select_icmp_sgt_not_smin(i8 %x) {
+; CHECK-LABEL: define i8 @select_icmp_sgt_not_smin(
+; CHECK-SAME: i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X]], -127
+; CHECK-NEXT:    [[ICMP1:%.*]] = icmp slt i8 [[X]], 0
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[ICMP1]], i8 [[XOR]], i8 [[X]]
+; CHECK-NEXT:    ret i8 [[SEL]]
+;
+  %icmp = icmp sgt i8 %x, 255
+  %xor = xor i8 %x, -127
+  %sel = select i1 %icmp, i8 %x, i8 %xor
+  ret i8 %sel
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/112388


More information about the llvm-commits mailing list