diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4875,6 +4875,21 @@ } } + // canoncalize: + // (icmp eq/ne (and X, C), X) + // -> (icmp eq/ne (and X, ~C), 0) + { + Constant *CMask; + A = nullptr; + if (match(Op0, m_OneUse(m_And(m_Specific(Op1), m_ImmConstant(CMask))))) + A = Op1; + else if (match(Op1, m_OneUse(m_And(m_Specific(Op0), m_ImmConstant(CMask))))) + A = Op0; + if (A) + return new ICmpInst(Pred, Builder.CreateAnd(A, Builder.CreateNot(CMask)), + Constant::getNullValue(A->getType())); + } + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) { // A == (A^B) -> B == 0 Value *OtherVal = A == Op0 ? B : A; diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll @@ -62,8 +62,8 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, @@ -179,8 +179,8 @@ define i1 @n0(i8 %x) { ; CHECK-LABEL: @n0( -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4 -; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -5 +; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %tmp0 = and i8 %x, 4 ; power-of-two, but invalid. @@ -201,8 +201,8 @@ define <2 x i1> @n2(<2 x i8> %x) { ; CHECK-LABEL: @n2( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, ; only the first one is valid. diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll @@ -62,8 +62,8 @@ define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, @@ -189,8 +189,8 @@ define i1 @n0(i8 %x) { ; CHECK-LABEL: @n0( -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4 -; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -5 +; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %tmp0 = and i8 %x, 4 ; power-of-two, but invalid. @@ -211,8 +211,8 @@ define <2 x i1> @n2(<2 x i8> %x) { ; CHECK-LABEL: @n2( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, ; only the first one is valid. diff --git a/llvm/test/Transforms/InstCombine/icmp-logical.ll b/llvm/test/Transforms/InstCombine/icmp-logical.ll --- a/llvm/test/Transforms/InstCombine/icmp-logical.ll +++ b/llvm/test/Transforms/InstCombine/icmp-logical.ll @@ -129,8 +129,8 @@ define i1 @masked_and_notA(i32 %A) { ; CHECK-LABEL: @masked_and_notA( -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A:%.*]], 78 -; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[MASK2]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -79 +; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[TST2]] ; %mask1 = and i32 %A, 14 @@ -143,8 +143,8 @@ define i1 @masked_and_notA_logical(i32 %A) { ; CHECK-LABEL: @masked_and_notA_logical( -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A:%.*]], 78 -; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[MASK2]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -79 +; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[TST2]] ; %mask1 = and i32 %A, 14 @@ -157,11 +157,9 @@ define i1 @masked_and_notA_slightly_optimized(i32 %A) { ; CHECK-LABEL: @masked_and_notA_slightly_optimized( -; CHECK-NEXT: [[T0:%.*]] = icmp ugt i32 [[A:%.*]], 7 -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A]], 39 -; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[MASK2]], [[A]] -; CHECK-NEXT: [[RES:%.*]] = and i1 [[T0]], [[TST2]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -40 +; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TST2]] ; %t0 = icmp uge i32 %A, 8 %mask2 = and i32 %A, 39 @@ -172,11 +170,9 @@ define i1 @masked_and_notA_slightly_optimized_logical(i32 %A) { ; CHECK-LABEL: @masked_and_notA_slightly_optimized_logical( -; CHECK-NEXT: [[T0:%.*]] = icmp ugt i32 [[A:%.*]], 7 -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A]], 39 -; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[MASK2]], [[A]] -; CHECK-NEXT: [[RES:%.*]] = and i1 [[T0]], [[TST2]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -40 +; CHECK-NEXT: [[TST2:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TST2]] ; %t0 = icmp uge i32 %A, 8 %mask2 = and i32 %A, 39 @@ -187,8 +183,8 @@ define i1 @masked_or_A(i32 %A) { ; CHECK-LABEL: @masked_or_A( -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A:%.*]], 78 -; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[MASK2]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -79 +; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[TST2]] ; %mask1 = and i32 %A, 14 @@ -201,8 +197,8 @@ define i1 @masked_or_A_logical(i32 %A) { ; CHECK-LABEL: @masked_or_A_logical( -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A:%.*]], 78 -; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[MASK2]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -79 +; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[TST2]] ; %mask1 = and i32 %A, 14 @@ -215,11 +211,9 @@ define i1 @masked_or_A_slightly_optimized(i32 %A) { ; CHECK-LABEL: @masked_or_A_slightly_optimized( -; CHECK-NEXT: [[T0:%.*]] = icmp ult i32 [[A:%.*]], 8 -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A]], 39 -; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[MASK2]], [[A]] -; CHECK-NEXT: [[RES:%.*]] = or i1 [[T0]], [[TST2]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -40 +; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TST2]] ; %t0 = icmp ult i32 %A, 8 %mask2 = and i32 %A, 39 @@ -230,11 +224,9 @@ define i1 @masked_or_A_slightly_optimized_logical(i32 %A) { ; CHECK-LABEL: @masked_or_A_slightly_optimized_logical( -; CHECK-NEXT: [[T0:%.*]] = icmp ult i32 [[A:%.*]], 8 -; CHECK-NEXT: [[MASK2:%.*]] = and i32 [[A]], 39 -; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[MASK2]], [[A]] -; CHECK-NEXT: [[RES:%.*]] = or i1 [[T0]], [[TST2]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], -40 +; CHECK-NEXT: [[TST2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TST2]] ; %t0 = icmp ult i32 %A, 8 %mask2 = and i32 %A, 39 diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -846,8 +846,8 @@ define i32 @test53(i32 %x) { ; CHECK-LABEL: @test53( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 2 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -3 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 2, i32 1 ; CHECK-NEXT: ret i32 [[SEL]] ;