[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Aug 13 14:02:08 PDT 2003
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.115 -> 1.116
---
Log message:
Generalize some of the add tests to allow for reassociation to take place
---
Diffs of the changes:
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.115 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.116
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.115 Wed Aug 13 00:38:46 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Aug 13 14:01:45 2003
@@ -267,18 +267,140 @@
return Count;
}
+
+/// AssociativeOpt - Perform an optimization on an associative operator. This
+/// function is designed to check a chain of associative operators for a
+/// potential to apply a certain optimization. Since the optimization may be
+/// applicable if the expression was reassociated, this checks the chain, then
+/// reassociates the expression as necessary to expose the optimization
+/// opportunity. This makes use of a special Functor, which must define
+/// 'shouldApply' and 'apply' methods.
+///
+template<typename Functor>
+Instruction *AssociativeOpt(BinaryOperator &Root, const Functor &F) {
+ unsigned Opcode = Root.getOpcode();
+ Value *LHS = Root.getOperand(0);
+
+ // Quick check, see if the immediate LHS matches...
+ if (F.shouldApply(LHS))
+ return F.apply(Root);
+
+ // Otherwise, if the LHS is not of the same opcode as the root, return.
+ Instruction *LHSI = dyn_cast<Instruction>(LHS);
+ while (LHSI && LHSI->getOpcode() == Opcode && LHSI->use_size() == 1) {
+ // Should we apply this transform to the RHS?
+ bool ShouldApply = F.shouldApply(LHSI->getOperand(1));
+
+ // If not to the RHS, check to see if we should apply to the LHS...
+ if (!ShouldApply && F.shouldApply(LHSI->getOperand(0))) {
+ cast<BinaryOperator>(LHSI)->swapOperands(); // Make the LHS the RHS
+ ShouldApply = true;
+ }
+
+ // If the functor wants to apply the optimization to the RHS of LHSI,
+ // reassociate the expression from ((? op A) op B) to (? op (A op B))
+ if (ShouldApply) {
+ BasicBlock *BB = Root.getParent();
+ // All of the instructions have a single use and have no side-effects,
+ // because of this, we can pull them all into the current basic block.
+ if (LHSI->getParent() != BB) {
+ // Move all of the instructions from root to LHSI into the current
+ // block.
+ Instruction *TmpLHSI = cast<Instruction>(Root.getOperand(0));
+ Instruction *LastUse = &Root;
+ while (TmpLHSI->getParent() == BB) {
+ LastUse = TmpLHSI;
+ TmpLHSI = cast<Instruction>(TmpLHSI->getOperand(0));
+ }
+
+ // Loop over all of the instructions in other blocks, moving them into
+ // the current one.
+ Value *TmpLHS = TmpLHSI;
+ do {
+ TmpLHSI = cast<Instruction>(TmpLHS);
+ // Remove from current block...
+ TmpLHSI->getParent()->getInstList().remove(TmpLHSI);
+ // Insert before the last instruction...
+ BB->getInstList().insert(LastUse, TmpLHSI);
+ TmpLHS = TmpLHSI->getOperand(0);
+ } while (TmpLHSI != LHSI);
+ }
+
+ // Now all of the instructions are in the current basic block, go ahead
+ // and perform the reassociation.
+ Instruction *TmpLHSI = cast<Instruction>(Root.getOperand(0));
+
+ // First move the selected RHS to the LHS of the root...
+ Root.setOperand(0, LHSI->getOperand(1));
+
+ // Make what used to be the LHS of the root be the user of the root...
+ Value *ExtraOperand = TmpLHSI->getOperand(1);
+ Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI
+ TmpLHSI->setOperand(1, &Root); // TmpLHSI now uses the root
+ BB->getInstList().remove(&Root); // Remove root from the BB
+ BB->getInstList().insert(TmpLHSI, &Root); // Insert root before TmpLHSI
+
+ // Now propagate the ExtraOperand down the chain of instructions until we
+ // get to LHSI.
+ while (TmpLHSI != LHSI) {
+ Instruction *NextLHSI = cast<Instruction>(TmpLHSI->getOperand(0));
+ Value *NextOp = NextLHSI->getOperand(1);
+ NextLHSI->setOperand(1, ExtraOperand);
+ TmpLHSI = NextLHSI;
+ ExtraOperand = NextOp;
+ }
+
+ // Now that the instructions are reassociated, have the functor perform
+ // the transformation...
+ return F.apply(Root);
+ }
+
+ LHSI = dyn_cast<Instruction>(LHSI->getOperand(0));
+ }
+ return 0;
+}
+
+
+// AddRHS - Implements: X + X --> X << 1
+struct AddRHS {
+ Value *RHS;
+ AddRHS(Value *rhs) : RHS(rhs) {}
+ bool shouldApply(Value *LHS) const { return LHS == RHS; }
+ Instruction *apply(BinaryOperator &Add) const {
+ return new ShiftInst(Instruction::Shl, Add.getOperand(0),
+ ConstantInt::get(Type::UByteTy, 1));
+ }
+};
+
+// AddMaskingAnd - Implements (A & C1)+(B & C2) --> (A & C1)|(B & C2)
+// iff C1&C2 == 0
+struct AddMaskingAnd {
+ Constant *C2;
+ AddMaskingAnd(Constant *c) : C2(c) {}
+ bool shouldApply(Value *LHS) const {
+ if (Constant *C1 = dyn_castMaskingAnd(LHS))
+ return ConstantExpr::get(Instruction::And, C1, C2)->isNullValue();
+ return false;
+ }
+ Instruction *apply(BinaryOperator &Add) const {
+ return BinaryOperator::create(Instruction::Or, Add.getOperand(0),
+ Add.getOperand(1));
+ }
+};
+
+
+
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
bool Changed = SimplifyCommutative(I);
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
- // Eliminate 'add int %X, 0'
+ // X + 0 --> X
if (RHS == Constant::getNullValue(I.getType()))
return ReplaceInstUsesWith(I, LHS);
- // Convert 'add X, X' to 'shl X, 1'
- if (LHS == RHS && I.getType()->isInteger())
- return new ShiftInst(Instruction::Shl, LHS,
- ConstantInt::get(Type::UByteTy, 1));
+ // X + X --> X << 1
+ if (I.getType()->isInteger())
+ if (Instruction *Result = AssociativeOpt(I, AddRHS(RHS))) return Result;
// -A + B --> B - A
if (Value *V = dyn_castNegVal(LHS))
@@ -307,11 +429,9 @@
return BinaryOperator::create(Instruction::Mul, LHS, CP1);
}
- // (A & C1)+(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
- if (Constant *C1 = dyn_castMaskingAnd(LHS))
- if (Constant *C2 = dyn_castMaskingAnd(RHS))
- if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue())
- return BinaryOperator::create(Instruction::Or, LHS, RHS);
+ // (A & C1)+(B & C2) --> (A & C1)|(B & C2) iff C1&C2 == 0
+ if (Constant *C2 = dyn_castMaskingAnd(RHS))
+ if (Instruction *R = AssociativeOpt(I, AddMaskingAnd(C2))) return R;
return Changed ? &I : 0;
}
More information about the llvm-commits
mailing list