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 @@ -3221,6 +3221,17 @@ PredR == CmpInst::ICMP_SGT && match(RHS1, m_AllOnes()))) return Builder.CreateIsNotNeg(Builder.CreateXor(LHS0, RHS0)); + // (X > C - 1) ^ (X < C + 1) --> X != C + // (X < C + 1) ^ (X > C - 1) --> X != C + const APInt *C1, *C2; + if ((PredL == CmpInst::ICMP_SGT && match(LHS1, m_APInt(C1)) && + PredR == CmpInst::ICMP_SLT && match(RHS1, m_APInt(C2)) && + *C1 + 2 == *C2) || + (PredL == CmpInst::ICMP_SLT && match(LHS1, m_APInt(C2)) && + PredR == CmpInst::ICMP_SGT && match(RHS1, m_APInt(C1)) && + *C1 + 2 == *C2)) + return Builder.CreateICmpNE(LHS0, + ConstantInt::get(LHS0->getType(), *C1 + 1)); } // Instead of trying to imitate the folds for and/or, decompose this 'xor' diff --git a/llvm/test/Transforms/InstCombine/set.ll b/llvm/test/Transforms/InstCombine/set.ll --- a/llvm/test/Transforms/InstCombine/set.ll +++ b/llvm/test/Transforms/InstCombine/set.ll @@ -220,14 +220,10 @@ ret i1 %xor } -; FIXME: This is (a != 5). - define i1 @xor_of_icmps_to_ne(i64 %a) { ; CHECK-LABEL: @xor_of_icmps_to_ne( -; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 [[A:%.*]], 4 -; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[A]], 6 -; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]] -; CHECK-NEXT: ret i1 [[XOR]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], 5 +; CHECK-NEXT: ret i1 [[TMP1]] ; %b = icmp sgt i64 %a, 4 %c = icmp slt i64 %a, 6 @@ -237,10 +233,8 @@ define i1 @xor_of_icmps_to_ne_commute(i64 %a) { ; CHECK-LABEL: @xor_of_icmps_to_ne_commute( -; CHECK-NEXT: [[C:%.*]] = icmp sgt i64 [[A:%.*]], 4 -; CHECK-NEXT: [[B:%.*]] = icmp slt i64 [[A]], 6 -; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]] -; CHECK-NEXT: ret i1 [[XOR]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], 5 +; CHECK-NEXT: ret i1 [[TMP1]] ; %c = icmp sgt i64 %a, 4 %b = icmp slt i64 %a, 6 @@ -250,10 +244,8 @@ define i1 @xor_of_icmps_neg_to_ne(i64 %a) { ; CHECK-LABEL: @xor_of_icmps_neg_to_ne( -; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 [[A:%.*]], -6 -; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[A]], -4 -; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]] -; CHECK-NEXT: ret i1 [[XOR]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], -5 +; CHECK-NEXT: ret i1 [[TMP1]] ; %b = icmp sgt i64 %a, -6 %c = icmp slt i64 %a, -4