[llvm] f9f40aa - [InstCombine] fold negated low-bit-mask to cmp+select
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 3 09:27:05 PDT 2022
Author: Sanjay Patel
Date: 2022-07-03T12:25:26-04:00
New Revision: f9f40aa10d9862b8db1b99bb9e7f5898a90b35f7
URL: https://github.com/llvm/llvm-project/commit/f9f40aa10d9862b8db1b99bb9e7f5898a90b35f7
DIFF: https://github.com/llvm/llvm-project/commit/f9f40aa10d9862b8db1b99bb9e7f5898a90b35f7.diff
LOG: [InstCombine] fold negated low-bit-mask to cmp+select
(-(X & 1)) & Y --> (X & 1) == 0 ? 0 : Y
https://alive2.llvm.org/ce/z/rhpH3i
This is noted as a missing IR canonicalization in issue #55618.
We already managed to fix codegen to the expected form.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ae8865651ece..d3578fe4a2ba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1771,6 +1771,16 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
return new ZExtInst(IsZero, Ty);
}
+ // (-(X & 1)) & Y --> (X & 1) == 0 ? 0 : Y
+ Value *Neg;
+ if (match(&I,
+ m_c_And(m_CombineAnd(m_Value(Neg),
+ m_OneUse(m_Neg(m_And(m_Value(), m_One())))),
+ m_Value(Y)))) {
+ Value *Cmp = Builder.CreateIsNull(Neg);
+ return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
+ }
+
const APInt *C;
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 9cf9c720473c..e37a34859dca 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -2171,8 +2171,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_undef3_vec(<3 x i16> %x) {
define i8 @negate_lowbitmask(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_lowbitmask(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1
-; CHECK-NEXT: [[N:%.*]] = sub nsw i8 0, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%a = and i8 %x, 1
@@ -2185,8 +2185,8 @@ define <2 x i5> @negate_lowbitmask_commute(<2 x i5> %x, <2 x i5> %p) {
; CHECK-LABEL: @negate_lowbitmask_commute(
; CHECK-NEXT: [[Y:%.*]] = mul <2 x i5> [[P:%.*]], [[P]]
; CHECK-NEXT: [[A:%.*]] = and <2 x i5> [[X:%.*]], <i5 1, i5 poison>
-; CHECK-NEXT: [[N:%.*]] = sub <2 x i5> <i5 poison, i5 0>, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and <2 x i5> [[Y]], [[N]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i5> [[A]], <i5 poison, i5 0>
+; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP1]], <2 x i5> zeroinitializer, <2 x i5> [[Y]]
; CHECK-NEXT: ret <2 x i5> [[R]]
;
%y = mul <2 x i5> %p, %p ; thwart complexity-based canonicalization
@@ -2200,8 +2200,8 @@ define i8 @negate_lowbitmask_use1(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_lowbitmask_use1(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1
; CHECK-NEXT: call void @use8(i8 [[A]])
-; CHECK-NEXT: [[N:%.*]] = sub nsw i8 0, [[A]]
-; CHECK-NEXT: [[R:%.*]] = and i8 [[N]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: ret i8 [[R]]
;
%a = and i8 %x, 1
@@ -2211,6 +2211,8 @@ define i8 @negate_lowbitmask_use1(i8 %x, i8 %y) {
ret i8 %r
}
+; negative test
+
define i8 @negate_lowbitmask_use2(i8 %x, i8 %y) {
; CHECK-LABEL: @negate_lowbitmask_use2(
; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 1
More information about the llvm-commits
mailing list