[llvm] [InstCombine] disable select folding resulting in extra instructions (PR #97184)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 29 18:06:33 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Alex MacLean (AlexMaclean)
<details>
<summary>Changes</summary>
Disable conversion of a `(select (icmp))` when it would result in more instructions `(xor (lshr (and)))`. This transformation produces more instructions and can interfere with other more profitable folds for `select`. For example before this change the following folding would occur:
```llvm
%1 = icmp slt i32 %X, 0
%2 = select i1 %1, i64 0, i64 8
```
to
```llvm
%1 = lshr i32 %X, 28
%2 = and i32 %1, 8
%3 = xor i32 %2, 8
%4 = zext nneg i32 %3 to i64
```
---
Full diff: https://github.com/llvm/llvm-project/pull/97184.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+8-2)
- (modified) llvm/test/Transforms/InstCombine/select-icmp-and.ll (+11)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index aff691b000413..db52684e174a4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -202,6 +202,14 @@ static Value *foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp,
const APInt &ValC = !TC.isZero() ? TC : FC;
unsigned ValZeros = ValC.logBase2();
unsigned AndZeros = AndMask.logBase2();
+ bool ShouldNotVal = !TC.isZero();
+ ShouldNotVal ^= Pred == ICmpInst::ICMP_NE;
+
+ // If we would need to create an 'and' + 'shift' + 'xor' to replace a 'select'
+ // + 'icmp', then this transformation would result in more instructions and
+ // potentially interfere with other folding.
+ if (CreateAnd && ShouldNotVal && ValZeros != AndZeros)
+ return nullptr;
// Insert the 'and' instruction on the input to the truncate.
if (CreateAnd)
@@ -221,8 +229,6 @@ static Value *foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp,
// Okay, now we know that everything is set up, we just don't know whether we
// have a icmp_ne or icmp_eq and whether the true or false val is the zero.
- bool ShouldNotVal = !TC.isZero();
- ShouldNotVal ^= Pred == ICmpInst::ICMP_NE;
if (ShouldNotVal)
V = Builder.CreateXor(V, ValC);
diff --git a/llvm/test/Transforms/InstCombine/select-icmp-and.ll b/llvm/test/Transforms/InstCombine/select-icmp-and.ll
index e1799d1091dac..8bedf699dc922 100644
--- a/llvm/test/Transforms/InstCombine/select-icmp-and.ll
+++ b/llvm/test/Transforms/InstCombine/select-icmp-and.ll
@@ -299,6 +299,17 @@ define <2 x i32> @test74vec(<2 x i32> %x) {
ret <2 x i32> %2
}
+define i64 @test75(i32 %X) {
+; CHECK-LABEL: @test75(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 8
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %1 = icmp slt i32 %X, 0
+ %2 = select i1 %1, i64 0, i64 8
+ ret i64 %2
+}
+
;; Code sequence for (X & 16) ? 16 : 0
define i32 @test15a(i32 %X) {
; CHECK-LABEL: @test15a(
``````````
</details>
https://github.com/llvm/llvm-project/pull/97184
More information about the llvm-commits
mailing list