mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
Implement instcombine optimizations:
(A <setcc1> B) logicalop (A <setcc2> B) -> (A <setcc3> B) or true or false Where setcc[123] is one of the 6 setcc instructions, and logicalop is one of: And, Or, Xor llvm-svn: 7828
This commit is contained in:
parent
b4a93eef33
commit
2b7babcc41
@ -112,6 +112,7 @@ namespace {
|
|||||||
WorkList.push_back(New); // Add to worklist
|
WorkList.push_back(New); // Add to worklist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
// ReplaceInstUsesWith - This method is to be used when an instruction is
|
// ReplaceInstUsesWith - This method is to be used when an instruction is
|
||||||
// found to be dead, replacable with another preexisting expression. Here
|
// found to be dead, replacable with another preexisting expression. Here
|
||||||
// we add all uses of I to the worklist, replace all uses of I with the new
|
// we add all uses of I to the worklist, replace all uses of I with the new
|
||||||
@ -123,7 +124,7 @@ namespace {
|
|||||||
I.replaceAllUsesWith(V);
|
I.replaceAllUsesWith(V);
|
||||||
return &I;
|
return &I;
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
|
||||||
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
/// InsertBefore instruction. This is specialized a bit to avoid inserting
|
||||||
/// casts that are known to not do anything...
|
/// casts that are known to not do anything...
|
||||||
@ -638,6 +639,86 @@ static bool isMinValuePlusOne(const ConstantInt *C) {
|
|||||||
return CS->getValue() == Val+1;
|
return CS->getValue() == Val+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getSetCondCode - Encode a setcc opcode into a three bit mask. These bits
|
||||||
|
/// are carefully arranged to allow folding of expressions such as:
|
||||||
|
///
|
||||||
|
/// (A < B) | (A > B) --> (A != B)
|
||||||
|
///
|
||||||
|
/// Bit value '4' represents that the comparison is true if A > B, bit value '2'
|
||||||
|
/// represents that the comparison is true if A == B, and bit value '1' is true
|
||||||
|
/// if A < B.
|
||||||
|
///
|
||||||
|
static unsigned getSetCondCode(const SetCondInst *SCI) {
|
||||||
|
switch (SCI->getOpcode()) {
|
||||||
|
// False -> 0
|
||||||
|
case Instruction::SetGT: return 1;
|
||||||
|
case Instruction::SetEQ: return 2;
|
||||||
|
case Instruction::SetGE: return 3;
|
||||||
|
case Instruction::SetLT: return 4;
|
||||||
|
case Instruction::SetNE: return 5;
|
||||||
|
case Instruction::SetLE: return 6;
|
||||||
|
// True -> 7
|
||||||
|
default:
|
||||||
|
assert(0 && "Invalid SetCC opcode!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getSetCCValue - This is the complement of getSetCondCode, which turns an
|
||||||
|
/// opcode and two operands into either a constant true or false, or a brand new
|
||||||
|
/// SetCC instruction.
|
||||||
|
static Value *getSetCCValue(unsigned Opcode, Value *LHS, Value *RHS) {
|
||||||
|
switch (Opcode) {
|
||||||
|
case 0: return ConstantBool::False;
|
||||||
|
case 1: return new SetCondInst(Instruction::SetGT, LHS, RHS);
|
||||||
|
case 2: return new SetCondInst(Instruction::SetEQ, LHS, RHS);
|
||||||
|
case 3: return new SetCondInst(Instruction::SetGE, LHS, RHS);
|
||||||
|
case 4: return new SetCondInst(Instruction::SetLT, LHS, RHS);
|
||||||
|
case 5: return new SetCondInst(Instruction::SetNE, LHS, RHS);
|
||||||
|
case 6: return new SetCondInst(Instruction::SetLE, LHS, RHS);
|
||||||
|
case 7: return ConstantBool::True;
|
||||||
|
default: assert(0 && "Illegal SetCCCode!"); return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FoldSetCCLogical - Implements (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
||||||
|
struct FoldSetCCLogical {
|
||||||
|
InstCombiner &IC;
|
||||||
|
Value *LHS, *RHS;
|
||||||
|
FoldSetCCLogical(InstCombiner &ic, SetCondInst *SCI)
|
||||||
|
: IC(ic), LHS(SCI->getOperand(0)), RHS(SCI->getOperand(1)) {}
|
||||||
|
bool shouldApply(Value *V) const {
|
||||||
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
|
||||||
|
return (SCI->getOperand(0) == LHS && SCI->getOperand(1) == RHS ||
|
||||||
|
SCI->getOperand(0) == RHS && SCI->getOperand(1) == LHS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Instruction *apply(BinaryOperator &Log) const {
|
||||||
|
SetCondInst *SCI = cast<SetCondInst>(Log.getOperand(0));
|
||||||
|
if (SCI->getOperand(0) != LHS) {
|
||||||
|
assert(SCI->getOperand(1) == LHS);
|
||||||
|
SCI->swapOperands(); // Swap the LHS and RHS of the SetCC
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned LHSCode = getSetCondCode(SCI);
|
||||||
|
unsigned RHSCode = getSetCondCode(cast<SetCondInst>(Log.getOperand(1)));
|
||||||
|
unsigned Code;
|
||||||
|
switch (Log.getOpcode()) {
|
||||||
|
case Instruction::And: Code = LHSCode & RHSCode; break;
|
||||||
|
case Instruction::Or: Code = LHSCode | RHSCode; break;
|
||||||
|
case Instruction::Xor: Code = LHSCode ^ RHSCode; break;
|
||||||
|
default: assert(0 && "Illegal logical opcode!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *RV = getSetCCValue(Code, LHS, RHS);
|
||||||
|
if (Instruction *I = dyn_cast<Instruction>(RV))
|
||||||
|
return I;
|
||||||
|
// Otherwise, it's a constant boolean value...
|
||||||
|
return IC.ReplaceInstUsesWith(Log, RV);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||||
bool Changed = SimplifyCommutative(I);
|
bool Changed = SimplifyCommutative(I);
|
||||||
@ -704,6 +785,11 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
|||||||
if (Op0NotVal == Op1 || Op1NotVal == Op0) // A & ~A == ~A & A == 0
|
if (Op0NotVal == Op1 || Op1NotVal == Op0) // A & ~A == ~A & A == 0
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||||
|
|
||||||
|
// (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
|
||||||
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
|
||||||
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
||||||
|
return R;
|
||||||
|
|
||||||
return Changed ? &I : 0;
|
return Changed ? &I : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,6 +862,11 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
|||||||
return BinaryOperator::createNot(And);
|
return BinaryOperator::createNot(And);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (setcc1 A, B) | (setcc2 A, B) --> (setcc3 A, B)
|
||||||
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
|
||||||
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
||||||
|
return R;
|
||||||
|
|
||||||
return Changed ? &I : 0;
|
return Changed ? &I : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,6 +944,11 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
|||||||
if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue())
|
if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue())
|
||||||
return BinaryOperator::create(Instruction::Or, Op0, Op1);
|
return BinaryOperator::create(Instruction::Or, Op0, Op1);
|
||||||
|
|
||||||
|
// (setcc1 A, B) ^ (setcc2 A, B) --> (setcc3 A, B)
|
||||||
|
if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
|
||||||
|
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
|
||||||
|
return R;
|
||||||
|
|
||||||
return Changed ? &I : 0;
|
return Changed ? &I : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user