diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1205,7 +1205,11 @@ // (X != 13 & X s< 14) -> X < 13 if (LHSC->getValue() == (RHSC->getValue() - 1)) return Builder.CreateICmpSLT(LHS0, LHSC); - break; // (X != 13 & X s< 15) -> no change + // (X != INT_MIN & X s< 14) -> X-(INT_MIN+1) u< (14-(INT_MIN+1)) + if (LHSC->isMinValue(true)) + return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(), + true, true); + break; // (X != 13 & X s< 15) -> no change case ICmpInst::ICMP_NE: // Potential folds for this case should already be handled. break; @@ -1219,6 +1223,10 @@ // (X u> 13 & X != 14) -> X u> 14 if (RHSC->getValue() == (LHSC->getValue() + 1)) return Builder.CreateICmp(PredL, LHS0, RHSC); + // X u> 13 & X != UINT_MAX -> (X-14) u< UINT_MAX-14 + if (RHSC->isMaxValue(false)) + return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(), + false, true); break; // (X u> 13 & X != 15) -> no change case ICmpInst::ICMP_ULT: // (X u> 13 & X u< 15) -> (X-14) getValue() + 1, RHSC->getValue(), @@ -1233,6 +1241,10 @@ // (X s> 13 & X != 14) -> X s> 14 if (RHSC->getValue() == (LHSC->getValue() + 1)) return Builder.CreateICmp(PredL, LHS0, RHSC); + // X s> 13 & X != INT_MAX -> (X-14) u< INT_MAX-14 + if (RHSC->isMaxValue(true)) + return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(), + true, true); break; // (X s> 13 & X != 15) -> no change case ICmpInst::ICMP_SLT: // (X s> 13 & X s< 15) -> (X-14) s< 1 return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue(), true, @@ -2253,8 +2265,19 @@ case ICmpInst::ICMP_EQ: // Potential folds for this case should already be handled. break; - case ICmpInst::ICMP_UGT: // (X == 13 | X u> 14) -> no change - case ICmpInst::ICMP_SGT: // (X == 13 | X s> 14) -> no change + case ICmpInst::ICMP_UGT: + // We can treat equality of UINT_MIN the same as ULE UINT_MIN. + if (LHSC->isMinValue(false)) + return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue() + 1, + false, false); + // (X == 13 | X u> 14) -> no change + break; + case ICmpInst::ICMP_SGT: + // We can treat equality of INT_MIN the same as SLE INT_MIN. + if (LHSC->isMinValue(true)) + return insertRangeTest(LHS0, LHSC->getValue() + 1, RHSC->getValue() + 1, + true, false); + // (X == 13 | X s> 14) -> no change break; } break; @@ -2263,6 +2286,10 @@ default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X u< 13 | X == 14) -> no change + // We can treat equality of UINT_MAX the same as UGE UINT_MAX. + if (RHSC->isMaxValue(false)) + return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue(), + false, false); break; case ICmpInst::ICMP_UGT: // (X u< 13 | X u> 15) -> (X-13) u> 2 assert(!RHSC->isMaxValue(false) && "Missed icmp simplification"); @@ -2274,7 +2301,12 @@ switch (PredR) { default: llvm_unreachable("Unknown integer condition code!"); - case ICmpInst::ICMP_EQ: // (X s< 13 | X == 14) -> no change + case ICmpInst::ICMP_EQ: + // We can treat equality of INT_MAX the same as SGE INT_MAX. + if (RHSC->isMaxValue(true)) + return insertRangeTest(LHS0, LHSC->getValue(), RHSC->getValue(), + true, false); + // (X s< 13 | X == 14) -> no change break; case ICmpInst::ICMP_SGT: // (X s< 13 | X s> 15) -> (X-13) s> 2 assert(!RHSC->isMaxValue(true) && "Missed icmp simplification"); diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -255,10 +255,8 @@ define i1 @PR42691_1(i32 %x) { ; CHECK-LABEL: @PR42691_1( -; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 %x, 0 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 %x, 2147483647 -; CHECK-NEXT: [[C:%.*]] = or i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 %x, 2147483646 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp slt i32 %x, 0 %c2 = icmp eq i32 %x, 2147483647 @@ -279,10 +277,8 @@ define i1 @PR42691_3(i32 %x) { ; CHECK-LABEL: @PR42691_3( -; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 %x, -1 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 %x, -2147483648 -; CHECK-NEXT: [[C:%.*]] = or i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 %x, -2147483647 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp sge i32 %x, 0 %c2 = icmp eq i32 %x, -2147483648 @@ -303,10 +299,9 @@ define i1 @PR42691_5(i32 %x) { ; CHECK-LABEL: @PR42691_5( -; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 %x, 1 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 %x, 2147483647 -; CHECK-NEXT: [[C:%.*]] = or i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp slt i32 %x, 1 %c2 = icmp eq i32 %x, 2147483647 @@ -316,10 +311,9 @@ define i1 @PR42691_6(i32 %x) { ; CHECK-LABEL: @PR42691_6( -; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 %x, -2147483647 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 %x, -1 -; CHECK-NEXT: [[C:%.*]] = or i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, 2147483647 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp ult i32 %x, 2147483649 %c2 = icmp eq i32 %x, 4294967295 @@ -341,10 +335,9 @@ define i1 @PR42691_8(i32 %x) { ; CHECK-LABEL: @PR42691_8( -; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 %x, 14 -; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 %x, -2147483648 -; CHECK-NEXT: [[C:%.*]] = and i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, 2147483647 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], -2147483635 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp slt i32 %x, 14 %c2 = icmp ne i32 %x, -2147483648 @@ -354,10 +347,9 @@ define i1 @PR42691_9(i32 %x) { ; CHECK-LABEL: @PR42691_9( -; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 %x, 13 -; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 %x, 2147483647 -; CHECK-NEXT: [[C:%.*]] = and i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, -14 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 2147483633 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp sgt i32 %x, 13 %c2 = icmp ne i32 %x, 2147483647 @@ -367,10 +359,9 @@ define i1 @PR42691_10(i32 %x) { ; CHECK-LABEL: @PR42691_10( -; CHECK-NEXT: [[C1:%.*]] = icmp ugt i32 %x, 13 -; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 %x, -1 -; CHECK-NEXT: [[C:%.*]] = and i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, -14 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], -15 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c1 = icmp ugt i32 %x, 13 %c2 = icmp ne i32 %x, 4294967295