[llvm] [InstCombine] Try optimizing with knownbits which determined from Cond (PR #91762)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 10 09:18:20 PDT 2024
https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/91762
>From 25c836b9a2bca0ca06ab6c6e09d08752ae9f2819 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:00:04 +0900
Subject: [PATCH 1/5] [NFC] [InstCombine] Modify the test to match its intent
proof : https://alive2.llvm.org/ce/z/A4PJ3E
---
llvm/test/Transforms/InstCombine/select-of-bittest.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index e3eb76de459e2..ba1dafaf53e99 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -590,13 +590,13 @@ define i32 @n5(i32 %arg) {
; CHECK-LABEL: @n5(
; CHECK-NEXT: [[T:%.*]] = and i32 [[ARG:%.*]], 2
; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[T]], 0
-; CHECK-NEXT: [[T2:%.*]] = and i32 [[ARG]], 2
+; CHECK-NEXT: [[T2:%.*]] = and i32 [[ARG]], 3
; CHECK-NEXT: [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 1
; CHECK-NEXT: ret i32 [[T3]]
;
%t = and i32 %arg, 2
%t1 = icmp eq i32 %t, 0
- %t2 = and i32 %arg, 2 ; 2 instead of 1
+ %t2 = and i32 %arg, 3 ; 3 instead of 2
%t3 = select i1 %t1, i32 %t2, i32 1
ret i32 %t3
}
>From 7c443f8acca469504cadcdc61e752fac71b9b7d5 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Fri, 10 May 2024 22:42:03 +0900
Subject: [PATCH 2/5] [InstCombine] Add tests
---
.../InstCombine/select-of-bittest.ll | 211 +++++++++++++++++-
1 file changed, 210 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index ba1dafaf53e99..96ac2378cdf4e 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -3,7 +3,216 @@
; https://bugs.llvm.org/show_bug.cgi?id=36950
-; These all should be just and+icmp, there should be no select.
+
+
+; ====================== AND =======================
+define i8 @src_and_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit(
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT: [[AND1:%.*]] = and i8 [[X]], 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %x, 3
+ %and1 = and i8 %x, 2
+ %and2 = and i8 %and, %x
+ %cmp = icmp eq i8 %and2, 2
+ %cond = select i1 %cmp, i8 %and1, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 2, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 poison, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %x, <i8 poison, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+ %and2 = and <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+
+; ====================== OR =======================
+define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit(
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[Z:%.*]], 3
+; CHECK-NEXT: [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT: [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[OR2]], i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %z, 3
+ %and1 = shl i8 %y, 2
+ %shl = and i8 %and1, 12
+ %or = or i8 %shl, %x
+ %cmp = icmp eq i8 %or, 3
+ %or2 = or i8 %and, %x
+ %cond = select i1 %cmp, i8 %or2, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 3, i8 3>
+ %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+ %shl = and <2 x i8> %and1, <i8 12, i8 12>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 3, i8 poison>
+ %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+ %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %z, <i8 poison, i8 3>
+ %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+ %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+ %or = or <2 x i8> %shl, %x
+ %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+ %or2 = or <2 x i8> %and, %x
+ %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+
+define i8 @src_xor_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit(
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT: [[AND1:%.*]] = and i8 [[X]], 3
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT: ret i8 [[COND]]
+;
+ %and = and i8 %y, 12
+ %xor = xor i8 %and, %x
+ %cmp = icmp eq i8 %xor, 3
+ %and1 = and i8 %x, 3
+ %cond = select i1 %cmp, i8 %and1, i8 1
+ ret i8 %cond
+}
+define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 12, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 3, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 poison, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
+define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2(
+; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[COND]]
+;
+ %and = and <2 x i8> %y, <i8 poison, i8 12>
+ %xor = xor <2 x i8> %and, %x
+ %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+ %and1 = and <2 x i8> %x, <i8 3, i8 3>
+ %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+ ret <2 x i8> %cond
+}
define i32 @and_lshr_and(i32 %arg) {
; CHECK-LABEL: @and_lshr_and(
>From e75795031d85b944e36c642153ee32e58cc10ef8 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:01:11 +0900
Subject: [PATCH 3/5] [InstCombine] Export computeKnownBitsFromCond in
ValueTracking
to use `Cond` in `SelectInst` for compute KnownBits.
---
llvm/include/llvm/Analysis/ValueTracking.h | 4 ++++
llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 571e44cdac265..0bf8c4ce0faa7 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -94,6 +94,10 @@ void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, KnownBits &Known);
void computeKnownBitsFromContext(const Value *V, KnownBits &Known,
unsigned Depth, const SimplifyQuery &Q);
+void computeKnownBitsFromCond(const Value *V, Value *Cond, KnownBits &Known,
+ unsigned Depth, const SimplifyQuery &SQ,
+ bool Invert);
+
/// Using KnownBits LHS/RHS produce the known bits for logic op (and/xor/or).
KnownBits analyzeKnownBitsFromAndXorOr(const Operator *I,
const KnownBits &KnownLHS,
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index de38eddaa98fe..dba9b394ff165 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -735,9 +735,9 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
}
-static void computeKnownBitsFromCond(const Value *V, Value *Cond,
- KnownBits &Known, unsigned Depth,
- const SimplifyQuery &SQ, bool Invert) {
+void llvm::computeKnownBitsFromCond(const Value *V, Value *Cond,
+ KnownBits &Known, unsigned Depth,
+ const SimplifyQuery &SQ, bool Invert) {
Value *A, *B;
if (Depth < MaxAnalysisRecursionDepth &&
match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {
>From 3929817ca32fb2063a9c61a9f946e6aa996d3b83 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Tue, 7 May 2024 06:04:30 +0900
Subject: [PATCH 4/5] [InstCombine] Try optimizing with knownbits which
determined from SelectInst Cond
ICmpInst of SelectInst is not included in the calculation of KnownBits
so we are missing the opportunity to optimize the Value of the True or
False Condition via ICmpInst with KnownBits.
Consider:
%or = or i32 %x, %y
%or0 = icmp eq i32 %or, 0
%and = and i32 %x, %y
%cond = select i1 %or0, i32 %and, i32 %or
ret i32 %cond
Expect:
%or = or i32 %x, %y
ret i32 %or
We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
This patch is an implementation that calculates the known bits over ICmp
and optimizes them where possible.
Proof : https://alive2.llvm.org/ce/z/kJ4YBF
---
.../Transforms/InstCombine/InstCombiner.h | 7 +
.../InstCombine/InstCombineSelect.cpp | 157 ++++++++++++++++++
2 files changed, 164 insertions(+)
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index ea1f4fc3b85dc..e654eeb1b234a 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -438,6 +438,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
return llvm::computeKnownBits(V, Depth, SQ.getWithInstruction(CxtI));
}
+ void computeKnownBitsFromCond(const Value *V, ICmpInst *Cmp, KnownBits &Known,
+ unsigned Depth, const Instruction *CxtI,
+ bool Invert) const {
+ llvm::computeKnownBitsFromCond(V, Cmp, Known, Depth,
+ SQ.getWithInstruction(CxtI), Invert);
+ }
+
bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero = false,
unsigned Depth = 0,
const Instruction *CxtI = nullptr) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 117eb7a1dcc93..1b2802e80c1ae 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1790,6 +1790,159 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
return nullptr;
}
+// ICmpInst of SelectInst is not included in the calculation of KnownBits
+// so we are missing the opportunity to optimize the Value of the True or
+// False Condition via ICmpInst with KnownBits.
+//
+// Consider:
+// %or = or i32 %x, %y
+// %or0 = icmp eq i32 %or, 0
+// %and = and i32 %x, %y
+// %cond = select i1 %or0, i32 %and, i32 %or
+// ret i32 %cond
+//
+// Expect:
+// %or = or i32 %x, %y
+// ret i32 %or
+//
+// We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
+static Instruction *foldSelectICmpBinOp(SelectInst &SI, ICmpInst *ICI,
+ Value *CmpLHS, Value *CmpRHS,
+ Value *TVal, Value *FVal,
+ InstCombinerImpl &IC) {
+ Value *X, *Y;
+ const APInt *C;
+
+ if (!((match(CmpLHS, m_BinOp(m_Value(X), m_Value(Y))) &&
+ match(CmpRHS, m_APInt(C))) &&
+ (match(TVal, m_c_BinOp(m_Specific(X), m_Value())) ||
+ match(TVal, m_c_BinOp(m_Specific(Y), m_Value())))))
+ return nullptr;
+
+ enum SpecialKnownBits {
+ NOTHING_SPECIAL = 0,
+ NO_COMMON_BITS = 1 << 1,
+ ALL_COMMON_BITS = 1 << 2,
+ ALL_BITS_ENABLED = 1 << 3,
+ };
+
+ // We cannot know exactly what bits is known in X Y.
+ // Instead, we just know what relationship exist for.
+ auto isSpecialKnownBitsFor = [&](const Instruction *CmpLHS,
+ const APInt *CmpRHS) -> unsigned {
+ unsigned Opc = CmpLHS->getOpcode();
+ if (Opc == Instruction::And) {
+ if (CmpRHS->isZero())
+ return NO_COMMON_BITS;
+ } else if (Opc == Instruction::Xor) {
+ if (CmpRHS->isAllOnes())
+ return NO_COMMON_BITS | ALL_BITS_ENABLED;
+ if (CmpRHS->isZero())
+ return ALL_COMMON_BITS;
+ }
+
+ return NOTHING_SPECIAL;
+ };
+
+ auto hasOperandAt = [&](Instruction *I, Value *Op) -> int {
+ for (unsigned Idx = 0; Idx < I->getNumOperands(); Idx++) {
+ if (I->getOperand(Idx) == Op)
+ return Idx + 1;
+ }
+ return 0;
+ };
+
+ Type *TValTy = TVal->getType();
+ unsigned BitWidth = TVal->getType()->getScalarSizeInBits();
+ auto TValBop = cast<BinaryOperator>(TVal);
+ auto CmpLHSBop = cast<BinaryOperator>(CmpLHS);
+ unsigned XOrder = hasOperandAt(TValBop, X);
+ unsigned YOrder = hasOperandAt(TValBop, Y);
+ unsigned SKB = isSpecialKnownBitsFor(CmpLHSBop, C);
+
+ KnownBits Known;
+ if (TValBop->isBitwiseLogicOp()) {
+ if (SKB != SpecialKnownBits::NOTHING_SPECIAL && XOrder && YOrder) {
+ if (SKB & SpecialKnownBits::NO_COMMON_BITS) {
+ if (SKB & (SpecialKnownBits::ALL_BITS_ENABLED)) {
+ if (TValBop->getOpcode() == Instruction::Xor)
+ Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+ }
+ if (TValBop->getOpcode() == Instruction::And)
+ Known = KnownBits::makeConstant(APInt(BitWidth, 0));
+ else if ((match(TVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+ match(FVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) ||
+ (match(TVal, m_c_Xor(m_Specific(X), m_Specific(Y))) &&
+ match(FVal, m_c_Or(m_Specific(X), m_Specific(Y)))))
+ return IC.replaceInstUsesWith(SI, FVal);
+ } else if (SKB & SpecialKnownBits::ALL_COMMON_BITS) {
+ if (TValBop->getOpcode() == Instruction::And ||
+ TValBop->getOpcode() == Instruction::Or)
+ if (TValBop->hasOneUse())
+ return IC.replaceOperand(SI, 1, X);
+ } else if (SKB & SpecialKnownBits::ALL_BITS_ENABLED) {
+ if (TValBop->getOpcode() == Instruction::Or)
+ Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+ }
+ } else {
+ KnownBits XKnown, YKnown, Temp;
+ KnownBits TValBop0KB, TValBop1KB;
+ XKnown = IC.computeKnownBits(X, 0, &SI);
+ IC.computeKnownBitsFromCond(X, ICI, XKnown, 0, &SI, false);
+ YKnown = IC.computeKnownBits(Y, 0, &SI);
+ IC.computeKnownBitsFromCond(Y, ICI, YKnown, 0, &SI, false);
+
+ // Estimate additional KnownBits from the relationship between X and Y
+ CmpInst::Predicate Pred = ICI->getPredicate();
+ if (Pred == ICmpInst::ICMP_EQ) {
+ if (CmpLHSBop->getOpcode() == Instruction::And) {
+ XKnown.Zero |= ~*C & YKnown.One;
+ YKnown.Zero |= ~*C & XKnown.One;
+ }
+ if (CmpLHSBop->getOpcode() == Instruction::Or) {
+ XKnown.One |= *C & YKnown.Zero;
+ YKnown.One |= *C & XKnown.Zero;
+ }
+ if (CmpLHSBop->getOpcode() == Instruction::Xor) {
+ XKnown.One |= *C & YKnown.Zero;
+ XKnown.Zero |= *C & YKnown.One;
+ YKnown.One |= *C & XKnown.Zero;
+ YKnown.Zero |= *C & XKnown.One;
+ XKnown.Zero |= ~*C & YKnown.Zero;
+ XKnown.One |= ~*C & YKnown.One;
+ YKnown.Zero |= ~*C & XKnown.Zero;
+ YKnown.One |= ~*C & XKnown.One;
+ }
+ }
+
+ auto getTValBopKB = [&](unsigned OpNum) -> KnownBits {
+ unsigned Order = OpNum + 1;
+ if (Order == XOrder)
+ return XKnown;
+ else if (Order == YOrder)
+ return YKnown;
+
+ Value *V = TValBop->getOperand(OpNum);
+ KnownBits Known = IC.computeKnownBits(V, 0, &SI);
+ IC.computeKnownBitsFromCond(V, ICI, Known, 0, &SI, false);
+ return Known;
+ };
+ TValBop0KB = getTValBopKB(0);
+ TValBop1KB = getTValBopKB(1);
+ Known = analyzeKnownBitsFromAndXorOr(
+ cast<Operator>(TValBop), TValBop0KB, TValBop1KB, 0,
+ IC.getSimplifyQuery().getWithInstruction(&SI));
+ }
+ }
+
+ if (Known.isConstant()) {
+ auto Const = ConstantInt::get(TValTy, Known.getConstant());
+ return IC.replaceOperand(SI, 1, Const);
+ }
+
+ return nullptr;
+}
+
/// Visit a SelectInst that has an ICmpInst as its first operand.
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
ICmpInst *ICI) {
@@ -1932,6 +2085,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (Value *V = foldAbsDiff(ICI, TrueVal, FalseVal, Builder))
return replaceInstUsesWith(SI, V);
+ if (Instruction *NewSel = foldSelectICmpBinOp(SI, ICI, CmpLHS, CmpRHS,
+ TrueVal, FalseVal, *this))
+ return NewSel;
+
return Changed ? &SI : nullptr;
}
>From 7e58012f84e47275511569e1cd8badadf9d713a2 Mon Sep 17 00:00:00 2001
From: hanbeom <kese111 at gmail.com>
Date: Fri, 10 May 2024 22:41:32 +0900
Subject: [PATCH 5/5] [InstCombine] Tests that changed due to a patch
---
.../InstCombine/select-of-bittest.ll | 40 +++++-----------
llvm/test/Transforms/InstCombine/select.ll | 47 +++++--------------
2 files changed, 25 insertions(+), 62 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index 96ac2378cdf4e..ab2b93252f0d6 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -9,9 +9,8 @@
define i8 @src_and_bit(i8 %x, i8 %y) {
; CHECK-LABEL: @src_and_bit(
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], 3
-; CHECK-NEXT: [[AND1:%.*]] = and i8 [[X]], 2
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 2
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 2, i8 1
; CHECK-NEXT: ret i8 [[COND]]
;
%and = and i8 %x, 3
@@ -24,9 +23,8 @@ define i8 @src_and_bit(i8 %x, i8 %y) {
define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @src_and_bit_vec(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 2, i8 2>
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %x, <i8 3, i8 3>
@@ -39,9 +37,8 @@ define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @src_and_bit_vec_poison(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -54,9 +51,8 @@ define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @src_and_bit_vec_poison2(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 2>
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %x, <i8 poison, i8 3>
@@ -70,13 +66,11 @@ define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
; ====================== OR =======================
define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @src_or_bit(
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[Z:%.*]], 3
; CHECK-NEXT: [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
; CHECK-NEXT: [[SHL:%.*]] = and i8 [[AND1]], 12
; CHECK-NEXT: [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 3
-; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[OR2]], i8 1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
; CHECK-NEXT: ret i8 [[COND]]
;
%and = and i8 %z, 3
@@ -90,13 +84,11 @@ define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
}
define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
; CHECK-LABEL: @src_or_bit_vec(
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 3>
; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %z, <i8 3, i8 3>
@@ -110,13 +102,11 @@ define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
}
define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
; CHECK-LABEL: @src_or_bit_vec_poison(
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 3, i8 poison>
; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %z, <i8 3, i8 poison>
@@ -130,13 +120,11 @@ define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
}
define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
; CHECK-LABEL: @src_or_bit_vec_poison2(
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Z:%.*]], <i8 poison, i8 3>
; CHECK-NEXT: [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
; CHECK-NEXT: [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
-; CHECK-NEXT: [[OR2:%.*]] = or <2 x i8> [[AND]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[OR2]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %z, <i8 poison, i8 3>
@@ -154,8 +142,7 @@ define i8 @src_xor_bit(i8 %x, i8 %y) {
; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y:%.*]], 12
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
-; CHECK-NEXT: [[AND1:%.*]] = and i8 [[X]], 3
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[AND1]], i8 1
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
; CHECK-NEXT: ret i8 [[COND]]
;
%and = and i8 %y, 12
@@ -170,8 +157,7 @@ define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %y, <i8 12, i8 12>
@@ -186,8 +172,7 @@ define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 poison, i8 3>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %y, <i8 poison, i8 12>
@@ -202,8 +187,7 @@ define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
-; CHECK-NEXT: [[AND1:%.*]] = and <2 x i8> [[X]], <i8 3, i8 3>
-; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[AND1]], <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[COND]]
;
%and = and <2 x i8> %y, <i8 poison, i8 12>
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 2efe2742ca491..e32cb17d85922 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3701,12 +3701,8 @@ exit:
define i32 @src_and_eq_0_or_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_or_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
;
entry:
%and = and i32 %y, %x
@@ -3721,12 +3717,8 @@ entry:
define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_and_eq_0_xor_or(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: ret i32 [[OR]]
;
entry:
%and = and i32 %y, %x
@@ -3743,9 +3735,8 @@ define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[XOR]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -3763,9 +3754,8 @@ define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[OR]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -3878,9 +3868,8 @@ define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -3898,9 +3887,8 @@ define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]]
; CHECK-NEXT: ret i32 [[COND]]
;
entry:
@@ -4301,9 +4289,8 @@ define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) {
; CHECK-LABEL: @src_select_xor_max_negative_int(
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]]
; CHECK-NEXT: ret i32 [[COND]]
;
%xor = xor i32 %x, %y
@@ -4410,10 +4397,7 @@ define i32 @src_no_trans_select_or_eq0_or_xor(i32 %x, i32 %y) {
define i32 @src_no_trans_select_or_eq0_and_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_no_trans_select_or_eq0_and_or(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[OR]]
;
%or = or i32 %x, %y
%or0 = icmp eq i32 %or, 0
@@ -4425,10 +4409,7 @@ define i32 @src_no_trans_select_or_eq0_and_or(i32 %x, i32 %y) {
define i32 @src_no_trans_select_or_eq0_xor_or(i32 %x, i32 %y) {
; CHECK-LABEL: @src_no_trans_select_or_eq0_xor_or(
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[OR0]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: ret i32 [[OR]]
;
%or = or i32 %x, %y
%or0 = icmp eq i32 %or, 0
@@ -4484,8 +4465,7 @@ define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_no_trans_select_xor_eq0_and_xor(
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 0
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[X]], i32 [[XOR]]
; CHECK-NEXT: ret i32 [[COND]]
;
%xor = xor i32 %x, %y
@@ -4500,8 +4480,7 @@ define i32 @src_no_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_no_trans_select_xor_eq0_or_xor(
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[XOR0:%.*]] = icmp eq i32 [[XOR]], 0
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[Y]]
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[XOR0]], i32 [[X]], i32 [[XOR]]
; CHECK-NEXT: ret i32 [[COND]]
;
%xor = xor i32 %x, %y
More information about the llvm-commits
mailing list