Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1798,6 +1798,23 @@ } } + // (V0 & (signbit l>> V1)) ==/!= 0 -> (V0 << V1) s>=/s< 0 + // (V0 & (signbit << V1)) ==/!= 0 -> (V0 l>> V1) s>=/s< 0 + Value *V0, *V1, *Shift; + if (C.isNullValue() && + match(And, m_OneUse(m_c_And( + m_CombineAnd(m_LogicalShift(m_SignMask(), m_Value(V1)), + m_Value(Shift)), + m_Value(V0))))) { + Value *NewShift = cast(Shift)->getOpcode() == Instruction::LShr + ? Builder.CreateShl(V0, V1) + : Builder.CreateLShr(V0, V1); + return new ICmpInst(Cmp.getPredicate() == CmpInst::ICMP_EQ + ? ICmpInst::ICMP_SGE + : ICmpInst::ICMP_SLT, + NewShift, Cmp.getOperand(1)); + } + return nullptr; } Index: llvm/test/Transforms/InstCombine/onehot_merge.ll =================================================================== --- llvm/test/Transforms/InstCombine/onehot_merge.ll +++ llvm/test/Transforms/InstCombine/onehot_merge.ll @@ -114,11 +114,11 @@ define i1 @foo1_and_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_signbit_lshr( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] -; CHECK-NEXT: [[T4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] -; CHECK-NEXT: ret i1 [[TMP3]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 -2147483648, [[C2:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[T]], [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], [[K:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], [[TMP2]] +; CHECK-NEXT: ret i1 [[TMP4]] ; %t = shl i32 1, %c1 %t4 = lshr i32 -2147483648, %c2 @@ -133,11 +133,11 @@ define i1 @foo1_or_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_or_signbit_lshr( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] -; CHECK-NEXT: [[T4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[T]], [[T4]] -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] -; CHECK-NEXT: ret i1 [[TMP3]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 -2147483648, [[C2:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[T]], [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], [[K:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], [[TMP2]] +; CHECK-NEXT: ret i1 [[TMP4]] ; %t = shl i32 1, %c1 %t4 = lshr i32 -2147483648, %c2 Index: llvm/test/Transforms/InstCombine/signbit-lshr-and-icmpeq-zero.ll =================================================================== --- llvm/test/Transforms/InstCombine/signbit-lshr-and-icmpeq-zero.ll +++ llvm/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 @@ -187,9 +181,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: llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll =================================================================== --- llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll +++ llvm/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 @@ -187,10 +181,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 @@ -200,10 +191,7 @@ define i1 @scalar_i32_signbit_shl_and_eq_X_is_constant2(i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq_X_is_constant2( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], 1 -; 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, 1