Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1887,21 +1887,24 @@ } const APInt *C1; - const APInt *C2; + const APInt *C2 = C; Value *X; - if (C->isPowerOf2() && - match(Op0, - m_OneUse(m_LShr(m_Shl(m_APInt(C1), m_Value(X)), m_APInt(C2)))) && - C1->isPowerOf2()) { - unsigned Log2C1 = C1->countTrailingZeros(); - unsigned Log2C = C->countTrailingZeros(); - unsigned LShrEqBits = Log2C + C2->getZExtValue(); - if (LShrEqBits < Width && LShrEqBits >= Log2C1) { - // iff C,C1 is pow2 and cttz(C1) < cttz(C)+C2 < BitWidth: - // ((C1 << X) >> C2) & C -> X == (cttz(C)+C2-cttz(C1)) ? C : 0 - unsigned CmpC = LShrEqBits - Log2C1; + if (C2->isPowerOf2()) { + if (match(Op0, m_OneUse(m_LShr(m_APInt(C1), m_Value(X)))) && + C1->isPowerOf2()) { + unsigned Log2C1 = C1->countTrailingZeros(); + unsigned Log2C2 = C2->countTrailingZeros(); + unsigned CmpC = Log2C1 - Log2C2; Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC)); - return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C), + return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C2), + ConstantInt::getNullValue(Ty)); + } else if (match(Op0, m_OneUse(m_Shl(m_APInt(C1), m_Value(X)))) && + C1->isPowerOf2()) { + unsigned Log2C1 = C1->countTrailingZeros(); + unsigned Log2C2 = C2->countTrailingZeros(); + unsigned CmpC = Log2C2 - Log2C1; + Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC)); + return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C2), ConstantInt::getNullValue(Ty)); } } Index: llvm/test/Transforms/InstCombine/and.ll =================================================================== --- llvm/test/Transforms/InstCombine/and.ll +++ llvm/test/Transforms/InstCombine/and.ll @@ -1624,8 +1624,9 @@ define i16 @shl_lshr_pow2_const(i16 %x) { ; CHECK-LABEL: @shl_lshr_pow2_const( -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 7 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 8, i16 0 +; CHECK-NEXT: [[SHL:%.*]] = shl i16 4, [[X:%.*]] +; CHECK-NEXT: [[LSHR:%.*]] = lshr i16 [[SHL]], 6 +; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR]], 8 ; CHECK-NEXT: ret i16 [[R]] ; %shl = shl i16 4, %x @@ -1698,8 +1699,8 @@ define i16 @lshr_lshr_pow2_const(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const( -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 32, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 4 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 3 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 4, i16 0 ; CHECK-NEXT: ret i16 [[R]] ; %lshr1 = lshr i16 2048, %x Index: llvm/test/Transforms/InstCombine/icmp-and-shift.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-and-shift.ll +++ llvm/test/Transforms/InstCombine/icmp-and-shift.ll @@ -5,8 +5,8 @@ define i32 @icmp_eq_and_pow2_shl1(i32 %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_shl1( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0:%.*]], 4 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 4 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; %shl = shl i32 1, %0 @@ -18,8 +18,8 @@ define <2 x i32> @icmp_eq_and_pow2_shl1_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_shl1_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], -; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[CMP]] to <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %shl = shl <2 x i32> , %0 @@ -31,8 +31,8 @@ define i32 @icmp_ne_and_pow2_shl1(i32 %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_shl1( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0:%.*]], 4 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 4 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; %shl = shl i32 1, %0 @@ -44,8 +44,8 @@ define <2 x i32> @icmp_ne_and_pow2_shl1_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_shl1_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[TMP0:%.*]], -; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[CMP]] to <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %shl = shl <2 x i32> , %0 @@ -58,8 +58,8 @@ define i32 @icmp_eq_and_pow2_shl_pow2(i32 %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_shl_pow2( ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 3 -; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32 -; CHECK-NEXT: ret i32 [[TMP3]] +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] ; %shl = shl i32 2, %0 %and = and i32 %shl, 16 @@ -71,8 +71,8 @@ define <2 x i32> @icmp_eq_and_pow2_shl_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_shl_pow2_vec( ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], -; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[TMP3]] +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %shl = shl <2 x i32> , %0 %and = and <2 x i32> %shl, @@ -84,8 +84,8 @@ define i32 @icmp_ne_and_pow2_shl_pow2(i32 %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_shl_pow2( ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0:%.*]], 3 -; CHECK-NEXT: [[AND_LOBIT:%.*]] = zext i1 [[TMP2]] to i32 -; CHECK-NEXT: ret i32 [[AND_LOBIT]] +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] ; %shl = shl i32 2, %0 %and = and i32 %shl, 16 @@ -97,8 +97,8 @@ define <2 x i32> @icmp_ne_and_pow2_shl_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_shl_pow2_vec( ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP0:%.*]], -; CHECK-NEXT: [[AND_LOBIT:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[AND_LOBIT]] +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %shl = shl <2 x i32> , %0 %and = and <2 x i32> %shl, @@ -290,8 +290,8 @@ define i32 @icmp_eq_and1_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_eq_and1_lshr_pow2( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0:%.*]], 3 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 3 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; %lshr = lshr i32 8, %0 @@ -303,8 +303,8 @@ define <2 x i32> @icmp_eq_and1_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_eq_and1_lshr_pow2_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], -; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[CMP]] to <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %lshr = lshr <2 x i32> , %0 @@ -316,8 +316,8 @@ define i32 @icmp_ne_and1_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_ne_and1_lshr_pow2( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0:%.*]], 3 -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 3 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; %lshr = lshr i32 8, %0 @@ -329,9 +329,9 @@ define <2 x i32> @icmp_ne_and1_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and1_lshr_pow2_vec( -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], -; CHECK-NEXT: ret <2 x i32> [[AND_LOBIT]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %lshr = lshr <2 x i32> , %0 %and = and <2 x i32> %lshr, @@ -342,10 +342,9 @@ define i32 @icmp_eq_and_pow2_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2( -; CHECK-NEXT: [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]] -; CHECK-NEXT: [[AND_LOBIT:%.*]] = and i32 [[AND]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] ; %lshr = lshr i32 8, %0 %and = and i32 %lshr, 4 @@ -367,10 +366,9 @@ define <2 x i32> @icmp_eq_and_pow2_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2_vec( -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], -; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i32> [[AND_LOBIT]], -; CHECK-NEXT: ret <2 x i32> [[TMP2]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %lshr = lshr <2 x i32> , %0 %and = and <2 x i32> %lshr, @@ -381,10 +379,9 @@ define i32 @icmp_ne_and_pow2_lshr_pow2(i32 %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2( -; CHECK-NEXT: [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]] -; CHECK-NEXT: [[AND_LOBIT:%.*]] = and i32 [[AND]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP2]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] ; %lshr = lshr i32 8, %0 %and = and i32 %lshr, 4 @@ -406,9 +403,9 @@ define <2 x i32> @icmp_ne_and_pow2_lshr_pow2_vec(<2 x i32> %0) { ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2_vec( -; CHECK-NEXT: [[AND:%.*]] = lshr <2 x i32> , [[TMP0:%.*]] -; CHECK-NEXT: [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], -; CHECK-NEXT: ret <2 x i32> [[AND_LOBIT]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: [[CONV:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[CONV]] ; %lshr = lshr <2 x i32> , %0 %and = and <2 x i32> %lshr, Index: llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll =================================================================== --- llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll +++ llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll @@ -193,9 +193,8 @@ define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { ; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[LSHR]], -1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[Y:%.*]], 0 +; CHECK-NEXT: ret i1 [[TMP1]] ; %lshr = lshr i32 2147483648, %y %and = and i32 %lshr, 2147483648