Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1781,6 +1781,29 @@ } } + // (V0 & (signbit l>> V1)) ==/!= 0 -> (V0 << V1) >=/< 0 + // (V0 & (signbit << V1)) ==/!= 0 -> (V0 l>> V1) >=/< 0 + Value *V0, *V1, *Shift, *Zero; + ICmpInst::Predicate Pred; + if (match(&Cmp, + m_ICmp(Pred, + m_OneUse(m_c_And( + m_CombineAnd( + m_CombineAnd(m_Shift(m_SignMask(), m_Value(V1)), + m_Value(Shift)), + m_CombineOr(m_Shl(m_Value(), m_Value()), + m_LShr(m_Value(), m_Value()))), + m_OneUse(m_Value(V0)))), + m_CombineAnd(m_Zero(), m_Value(Zero)))) && + Cmp.isEquality(Pred)) { + Value *NewShift = cast(Shift)->getOpcode() == Instruction::LShr + ? Builder.CreateShl(V0, V1) + : Builder.CreateLShr(V0, V1); + ICmpInst::Predicate NewPred = + Pred == CmpInst::ICMP_EQ ? CmpInst::ICMP_SGE : CmpInst::ICMP_SLT; + return new ICmpInst(NewPred, NewShift, Zero); + } + return nullptr; } Index: test/Transforms/InstCombine/signbit-lshr-and-icmpeq-zero.ll =================================================================== --- test/Transforms/InstCombine/signbit-lshr-and-icmpeq-zero.ll +++ test/Transforms/InstCombine/signbit-lshr-and-icmpeq-zero.ll @@ -8,9 +8,8 @@ define i1 @scalar_i8_signbit_lshr_and_eq(i8 %x, i8 %y) { ; CHECK-LABEL: @scalar_i8_signbit_lshr_and_eq( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -128, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i8 128, %y @@ -21,9 +20,8 @@ define i1 @scalar_i16_signbit_lshr_and_eq(i16 %x, i16 %y) { ; CHECK-LABEL: @scalar_i16_signbit_lshr_and_eq( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i16 -32768, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i16 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i16 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i16 32768, %y @@ -34,9 +32,8 @@ define i1 @scalar_i32_signbit_lshr_and_eq(i32 %x, i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_lshr_and_eq( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 2147483648, %y @@ -47,9 +44,8 @@ define i1 @scalar_i64_signbit_lshr_and_eq(i64 %x, i64 %y) { ; CHECK-LABEL: @scalar_i64_signbit_lshr_and_eq( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i64 -9223372036854775808, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i64 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i64 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i64 9223372036854775808, %y @@ -60,9 +56,8 @@ define i1 @scalar_i32_signbit_lshr_and_ne(i32 %x, i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_lshr_and_ne( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 2147483648, %y @@ -75,9 +70,8 @@ define <4 x i1> @vec_4xi32_signbit_lshr_and_eq(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_signbit_lshr_and_eq( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> , [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> , %y @@ -133,8 +127,8 @@ ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2147483648, [[Y:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[LSHR]], [[Z:%.*]] ; CHECK-NEXT: store i32 [[XOR]], i32* [[P:%.*]], align 4 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 2147483648, %y @@ -189,9 +183,8 @@ define i1 @scalar_i32_signbit_lshr_and_eq_X_is_constant1(i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_lshr_and_eq_X_is_constant1( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 12345 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 12345, [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 2147483648, %y Index: test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll =================================================================== --- test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll +++ test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll @@ -8,9 +8,8 @@ define i1 @scalar_i8_signbit_shl_and_eq(i8 %x, i8 %y) { ; CHECK-LABEL: @scalar_i8_signbit_shl_and_eq( -; CHECK-NEXT: [[SHL:%.*]] = shl i8 -128, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i8 128, %y @@ -21,9 +20,8 @@ define i1 @scalar_i16_signbit_shl_and_eq(i16 %x, i16 %y) { ; CHECK-LABEL: @scalar_i16_signbit_shl_and_eq( -; CHECK-NEXT: [[SHL:%.*]] = shl i16 -32768, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i16 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i16 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i16 32768, %y @@ -34,9 +32,8 @@ define i1 @scalar_i32_signbit_shl_and_eq(i32 %x, i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2147483648, %y @@ -47,9 +44,8 @@ define i1 @scalar_i64_signbit_shl_and_eq(i64 %x, i64 %y) { ; CHECK-LABEL: @scalar_i64_signbit_shl_and_eq( -; CHECK-NEXT: [[SHL:%.*]] = shl i64 -9223372036854775808, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i64 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i64 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i64 9223372036854775808, %y @@ -60,9 +56,8 @@ define i1 @scalar_i32_signbit_shl_and_ne(i32 %x, i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_ne( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2147483648, %y @@ -75,9 +70,8 @@ define <4 x i1> @vec_4xi32_signbit_shl_and_eq(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_signbit_shl_and_eq( -; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> , [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> , %y @@ -133,8 +127,8 @@ ; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], [[Z:%.*]] ; CHECK-NEXT: store i32 [[XOR]], i32* [[P:%.*]], align 4 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2147483648, %y @@ -189,10 +183,7 @@ define i1 @scalar_i32_signbit_shl_and_eq_X_is_constant1(i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq_X_is_constant1( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], 12345 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %shl = shl i32 2147483648, %y %and = and i32 %shl, 12345