Fix folding of icmp's of i1 where the comparison is signed. The code

was using the algorithm for folding unsigned comparisons which is
completely wrong.  This has been broken since the signless types change.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53444 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-07-11 04:20:58 +00:00
parent f299184565
commit 85b5eb0505
2 changed files with 33 additions and 12 deletions

View File

@ -5196,34 +5196,46 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
if (Ty == Type::Int1Ty) { if (Ty == Type::Int1Ty) {
switch (I.getPredicate()) { switch (I.getPredicate()) {
default: assert(0 && "Invalid icmp instruction!"); default: assert(0 && "Invalid icmp instruction!");
case ICmpInst::ICMP_EQ: { // icmp eq bool %A, %B -> ~(A^B) case ICmpInst::ICMP_EQ: { // icmp eq i1 A, B -> ~(A^B)
Instruction *Xor = BinaryOperator::CreateXor(Op0, Op1, I.getName()+"tmp"); Instruction *Xor = BinaryOperator::CreateXor(Op0, Op1, I.getName()+"tmp");
InsertNewInstBefore(Xor, I); InsertNewInstBefore(Xor, I);
return BinaryOperator::CreateNot(Xor); return BinaryOperator::CreateNot(Xor);
} }
case ICmpInst::ICMP_NE: // icmp eq bool %A, %B -> A^B case ICmpInst::ICMP_NE: // icmp eq i1 A, B -> A^B
return BinaryOperator::CreateXor(Op0, Op1); return BinaryOperator::CreateXor(Op0, Op1);
case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_SGT: std::swap(Op0, Op1); // Change icmp ugt -> icmp ult
std::swap(Op0, Op1); // Change icmp gt -> icmp lt
// FALL THROUGH // FALL THROUGH
case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULT:{ // icmp ult i1 A, B -> ~A & B
case ICmpInst::ICMP_SLT: { // icmp lt bool A, B -> ~X & Y
Instruction *Not = BinaryOperator::CreateNot(Op0, I.getName()+"tmp"); Instruction *Not = BinaryOperator::CreateNot(Op0, I.getName()+"tmp");
InsertNewInstBefore(Not, I); InsertNewInstBefore(Not, I);
return BinaryOperator::CreateAnd(Not, Op1); return BinaryOperator::CreateAnd(Not, Op1);
} }
case ICmpInst::ICMP_UGE: case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE: std::swap(Op0, Op1); // Change icmp sgt -> icmp slt
std::swap(Op0, Op1); // Change icmp ge -> icmp le
// FALL THROUGH // FALL THROUGH
case ICmpInst::ICMP_ULE: case ICmpInst::ICMP_SLT: { // icmp slt i1 A, B -> A & ~B
case ICmpInst::ICMP_SLE: { // icmp le bool %A, %B -> ~A | B Instruction *Not = BinaryOperator::CreateNot(Op1, I.getName()+"tmp");
InsertNewInstBefore(Not, I);
return BinaryOperator::CreateAnd(Not, Op0);
}
case ICmpInst::ICMP_UGE:
std::swap(Op0, Op1); // Change icmp uge -> icmp ule
// FALL THROUGH
case ICmpInst::ICMP_ULE: { // icmp ule i1 A, B -> ~A | B
Instruction *Not = BinaryOperator::CreateNot(Op0, I.getName()+"tmp"); Instruction *Not = BinaryOperator::CreateNot(Op0, I.getName()+"tmp");
InsertNewInstBefore(Not, I); InsertNewInstBefore(Not, I);
return BinaryOperator::CreateOr(Not, Op1); return BinaryOperator::CreateOr(Not, Op1);
} }
case ICmpInst::ICMP_SGE:
std::swap(Op0, Op1); // Change icmp sge -> icmp sle
// FALL THROUGH
case ICmpInst::ICMP_SLE: { // icmp sle i1 A, B -> A | ~B
Instruction *Not = BinaryOperator::CreateNot(Op1, I.getName()+"tmp");
InsertNewInstBefore(Not, I);
return BinaryOperator::CreateOr(Not, Op0);
}
} }
} }

View File

@ -1,8 +1,17 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {%C = xor i1 %A, true} ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {%C = xor i1 %A, true}
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i1 false}
; PR2539 ; PR2539
define i1 @test(i1 %A) { define i1 @test1(i1 %A) {
%B = zext i1 %A to i32 %B = zext i1 %A to i32
%C = icmp slt i32 %B, 1 %C = icmp slt i32 %B, 1
ret i1 %C ret i1 %C
} }
define i1 @test2(i1 zeroext %b) {
entry:
%cmptmp = icmp slt i1 %b, true ; <i1> [#uses=1]
ret i1 %cmptmp
}