[InstCombine] fix matching of or-of-icmps constants (PR32524)

Also, make the same change in and-of-icmps and remove a hack for detecting that case.

Finally, add some FIXME comments because the code duplication here is awful.

This should fix the remaining IR problem noted in:
https://bugs.llvm.org/show_bug.cgi?id=32524

llvm-svn: 299851
This commit is contained in:
Sanjay Patel 2017-04-10 16:55:57 +00:00
parent 08126372e3
commit 570e35c157
2 changed files with 19 additions and 16 deletions

View File

@ -807,6 +807,7 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
}
}
// FIXME: The code below is duplicated in FoldOrOfICmps.
// From here on, we only handle:
// (icmp1 A, C1) & (icmp2 A, C2) --> something simpler.
if (Val != Val2)
@ -825,11 +826,14 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
// Ensure that the larger constant is on the RHS.
bool ShouldSwap;
if (CmpInst::isSigned(PredL) ||
(ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR)))
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
else
if (CmpInst::isUnsigned(PredL) || CmpInst::isUnsigned(PredR)) {
// We have an unsigned compare (possibly with an equality compare), so treat
// the constants as unsigned.
ShouldSwap = LHSC->getValue().ugt(RHSC->getValue());
} else {
// Equality transforms treat the constants as signed.
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
}
if (ShouldSwap) {
std::swap(LHS, RHS);
@ -877,10 +881,6 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
case ICmpInst::ICMP_SGT: // (X != 13 & X s> 15) -> X s> 15
return RHS;
case ICmpInst::ICMP_NE:
// Special case to get the ordering right when the values wrap around
// zero.
if (LHSC->getValue() == 0 && RHSC->getValue().isAllOnesValue())
std::swap(LHSC, RHSC);
if (LHSC == SubOne(RHSC)) { // (X != 13 & X != 14) -> X-13 >u 1
Constant *AddC = ConstantExpr::getNeg(LHSC);
Value *Add = Builder->CreateAdd(Val, AddC, Val->getName() + ".off");
@ -1727,6 +1727,7 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
return Builder->CreateICmpULE(Val, LHSC);
}
// FIXME: The code below is duplicated in FoldAndOfICmps.
// From here on, we only handle:
// (icmp1 A, C1) | (icmp2 A, C2) --> something simpler.
if (Val != Val2)
@ -1745,11 +1746,14 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
// Ensure that the larger constant is on the RHS.
bool ShouldSwap;
if (CmpInst::isSigned(PredL) ||
(ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR)))
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
else
if (CmpInst::isUnsigned(PredL) || CmpInst::isUnsigned(PredR)) {
// We have an unsigned compare (possibly with an equality compare), so treat
// the constants as unsigned.
ShouldSwap = LHSC->getValue().ugt(RHSC->getValue());
} else {
// Equality transforms treat the constants as signed.
ShouldSwap = LHSC->getValue().sgt(RHSC->getValue());
}
if (ShouldSwap) {
std::swap(LHS, RHS);

View File

@ -223,10 +223,9 @@ define i1 @test19(i32 %A) {
define i1 @or_icmps_eq_diff1(i32 %x) {
; CHECK-LABEL: @or_icmps_eq_diff1(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 %x, -1
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 %x, 0
; CHECK-NEXT: [[LOGIC:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[LOGIC]]
; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, 1
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 2
; CHECK-NEXT: ret i1 [[TMP1]]
;
%cmp1 = icmp eq i32 %x, -1
%cmp2 = icmp eq i32 %x, 0