[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Aug 13 15:17:01 PDT 2003
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.116 -> 1.117
---
Log message:
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
---
Diffs of the changes:
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.116 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.117
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.116 Wed Aug 13 14:01:45 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Aug 13 15:16:26 2003
@@ -112,6 +112,7 @@
WorkList.push_back(New); // Add to worklist
}
+ public:
// ReplaceInstUsesWith - This method is to be used when an instruction is
// 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
@@ -123,7 +124,7 @@
I.replaceAllUsesWith(V);
return &I;
}
-
+ private:
/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
/// InsertBefore instruction. This is specialized a bit to avoid inserting
/// casts that are known to not do anything...
@@ -638,6 +639,86 @@
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) {
bool Changed = SimplifyCommutative(I);
@@ -704,6 +785,11 @@
if (Op0NotVal == Op1 || Op1NotVal == Op0) // A & ~A == ~A & A == 0
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;
}
@@ -776,6 +862,11 @@
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;
}
@@ -852,6 +943,11 @@
if (Constant *C2 = dyn_castMaskingAnd(Op1))
if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue())
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;
}
More information about the llvm-commits
mailing list