mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 07:31:47 +00:00
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons: 1. Benchmarks have lots of code that looks like this (perlbmk in particular): %tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1] %tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1] %tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1] we now fold away the setne, a clear improvement. 2. In the more important cases, such as (X >= 10) & (X < 20), we now produce smaller code: (X-10) < 10. 3. Perhaps the nicest effect of this patch is that it really helps out the code generators. In particular, for a 'range test' like the above, instead of generating this on X86 (the difference on PPC is even more pronounced): cmp %EAX, 50 setge %CL cmp %EAX, 100 setl %AL and %CL, %AL cmp %CL, 0 we now generate this: add %EAX, -50 cmp %EAX, 50 Furthermore, this causes setcc's to be folded into branches more often. These combinations trigger dozens of times in the spec benchmarks, particularly in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16559 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7f12bbbc92
commit
955f331a77
@ -137,7 +137,7 @@ namespace {
|
||||
// InsertNewInstBefore - insert an instruction New before instruction Old
|
||||
// in the program. Add the new instruction to the worklist.
|
||||
//
|
||||
Value *InsertNewInstBefore(Instruction *New, Instruction &Old) {
|
||||
Instruction *InsertNewInstBefore(Instruction *New, Instruction &Old) {
|
||||
assert(New && New->getParent() == 0 &&
|
||||
"New instruction already inserted into a basic block!");
|
||||
BasicBlock *BB = Old.getParent();
|
||||
@ -334,6 +334,22 @@ static unsigned Log2(uint64_t Val) {
|
||||
return Count;
|
||||
}
|
||||
|
||||
// AddOne, SubOne - Add or subtract a constant one from an integer constant...
|
||||
static Constant *AddOne(ConstantInt *C) {
|
||||
return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
|
||||
}
|
||||
static Constant *SubOne(ConstantInt *C) {
|
||||
return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
|
||||
}
|
||||
|
||||
// isTrueWhenEqual - Return true if the specified setcondinst instruction is
|
||||
// true when both operands are equal...
|
||||
//
|
||||
static bool isTrueWhenEqual(Instruction &I) {
|
||||
return I.getOpcode() == Instruction::SetEQ ||
|
||||
I.getOpcode() == Instruction::SetGE ||
|
||||
I.getOpcode() == Instruction::SetLE;
|
||||
}
|
||||
|
||||
/// AssociativeOpt - Perform an optimization on an associative operator. This
|
||||
/// function is designed to check a chain of associative operators for a
|
||||
@ -1203,11 +1219,113 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||
return BinaryOperator::createNot(Or);
|
||||
}
|
||||
|
||||
// (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
||||
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
|
||||
if (SetCondInst *RHS = dyn_cast<SetCondInst>(Op1)) {
|
||||
// (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
||||
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
||||
return R;
|
||||
|
||||
Value *LHSVal, *RHSVal;
|
||||
ConstantInt *LHSCst, *RHSCst;
|
||||
Instruction::BinaryOps LHSCC, RHSCC;
|
||||
if (match(Op0, m_SetCond(LHSCC, m_Value(LHSVal), m_ConstantInt(LHSCst))))
|
||||
if (match(RHS, m_SetCond(RHSCC, m_Value(RHSVal), m_ConstantInt(RHSCst))))
|
||||
if (LHSVal == RHSVal && // Found (X setcc C1) & (X setcc C2)
|
||||
// Set[GL]E X, CST is folded to Set[GL]T elsewhere.
|
||||
LHSCC != Instruction::SetGE && LHSCC != Instruction::SetLE &&
|
||||
RHSCC != Instruction::SetGE && RHSCC != Instruction::SetLE) {
|
||||
// Ensure that the larger constant is on the RHS.
|
||||
Constant *Cmp = ConstantExpr::getSetGT(LHSCst, RHSCst);
|
||||
SetCondInst *LHS = cast<SetCondInst>(Op0);
|
||||
if (cast<ConstantBool>(Cmp)->getValue()) {
|
||||
std::swap(LHS, RHS);
|
||||
std::swap(LHSCst, RHSCst);
|
||||
std::swap(LHSCC, RHSCC);
|
||||
}
|
||||
|
||||
// At this point, we know we have have two setcc instructions
|
||||
// comparing a value against two constants and and'ing the result
|
||||
// together. Because of the above check, we know that we only have
|
||||
// SetEQ, SetNE, SetLT, and SetGT here. We also know (from the
|
||||
// FoldSetCCLogical check above), that the two constants are not
|
||||
// equal.
|
||||
assert(LHSCst != RHSCst && "Compares not folded above?");
|
||||
|
||||
switch (LHSCC) {
|
||||
default: assert(0 && "Unknown integer condition code!");
|
||||
case Instruction::SetEQ:
|
||||
switch (RHSCC) {
|
||||
default: assert(0 && "Unknown integer condition code!");
|
||||
case Instruction::SetEQ: // (X == 13 & X == 15) -> false
|
||||
case Instruction::SetGT: // (X == 13 & X > 15) -> false
|
||||
return ReplaceInstUsesWith(I, ConstantBool::False);
|
||||
case Instruction::SetNE: // (X == 13 & X != 15) -> X == 13
|
||||
case Instruction::SetLT: // (X == 13 & X < 15) -> X == 13
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
}
|
||||
case Instruction::SetNE:
|
||||
switch (RHSCC) {
|
||||
default: assert(0 && "Unknown integer condition code!");
|
||||
case Instruction::SetLT:
|
||||
if (LHSCst == SubOne(RHSCst)) // (X != 13 & X < 14) -> X < 13
|
||||
return new SetCondInst(Instruction::SetLT, LHSVal, LHSCst);
|
||||
break; // (X != 13 & X < 15) -> no change
|
||||
case Instruction::SetEQ: // (X != 13 & X == 15) -> X == 15
|
||||
case Instruction::SetGT: // (X != 13 & X > 15) -> X > 15
|
||||
return ReplaceInstUsesWith(I, RHS);
|
||||
case Instruction::SetNE:
|
||||
if (LHSCst == SubOne(RHSCst)) {// (X != 13 & X != 14) -> X-13 >u 1
|
||||
Constant *AddCST = ConstantExpr::getNeg(LHSCst);
|
||||
Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
|
||||
LHSVal->getName()+".off");
|
||||
InsertNewInstBefore(Add, I);
|
||||
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
||||
Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
|
||||
AddCST = ConstantExpr::getSub(RHSCst, LHSCst);
|
||||
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
||||
return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
|
||||
}
|
||||
break; // (X != 13 & X != 15) -> no change
|
||||
}
|
||||
break;
|
||||
case Instruction::SetLT:
|
||||
switch (RHSCC) {
|
||||
default: assert(0 && "Unknown integer condition code!");
|
||||
case Instruction::SetEQ: // (X < 13 & X == 15) -> false
|
||||
case Instruction::SetGT: // (X < 13 & X > 15) -> false
|
||||
return ReplaceInstUsesWith(I, ConstantBool::False);
|
||||
case Instruction::SetNE: // (X < 13 & X != 15) -> X < 13
|
||||
case Instruction::SetLT: // (X < 13 & X < 15) -> X < 13
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
}
|
||||
case Instruction::SetGT:
|
||||
switch (RHSCC) {
|
||||
default: assert(0 && "Unknown integer condition code!");
|
||||
case Instruction::SetEQ: // (X > 13 & X == 15) -> X > 13
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
case Instruction::SetGT: // (X > 13 & X > 15) -> X > 15
|
||||
return ReplaceInstUsesWith(I, RHS);
|
||||
case Instruction::SetNE:
|
||||
if (RHSCst == AddOne(LHSCst)) // (X > 13 & X != 14) -> X > 14
|
||||
return new SetCondInst(Instruction::SetGT, LHSVal, RHSCst);
|
||||
break; // (X > 13 & X != 15) -> no change
|
||||
case Instruction::SetLT: { // (X > 13 & X < 15) -> (X-14) <u 1
|
||||
Constant *AddCST = ConstantExpr::getNeg(AddOne(LHSCst));
|
||||
Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
|
||||
LHSVal->getName()+".off");
|
||||
InsertNewInstBefore(Add, I);
|
||||
// Convert to unsigned for the comparison.
|
||||
const Type *UnsType = Add->getType()->getUnsignedVersion();
|
||||
Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
|
||||
AddCST = ConstantExpr::getAdd(AddCST, RHSCst);
|
||||
AddCST = ConstantExpr::getCast(AddCST, UnsType);
|
||||
return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Changed ? &I : 0;
|
||||
}
|
||||
|
||||
@ -1429,23 +1547,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
return Changed ? &I : 0;
|
||||
}
|
||||
|
||||
// AddOne, SubOne - Add or subtract a constant one from an integer constant...
|
||||
static Constant *AddOne(ConstantInt *C) {
|
||||
return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
|
||||
}
|
||||
static Constant *SubOne(ConstantInt *C) {
|
||||
return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
|
||||
}
|
||||
|
||||
// isTrueWhenEqual - Return true if the specified setcondinst instruction is
|
||||
// true when both operands are equal...
|
||||
//
|
||||
static bool isTrueWhenEqual(Instruction &I) {
|
||||
return I.getOpcode() == Instruction::SetEQ ||
|
||||
I.getOpcode() == Instruction::SetGE ||
|
||||
I.getOpcode() == Instruction::SetLE;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
|
||||
bool Changed = SimplifyCommutative(I);
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
Loading…
Reference in New Issue
Block a user