aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r--lib/Transforms/Scalar/ConstantProp.cpp239
-rw-r--r--lib/Transforms/Scalar/DCE.cpp193
-rw-r--r--lib/Transforms/Scalar/SymbolStripping.cpp55
3 files changed, 487 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/ConstantProp.cpp b/lib/Transforms/Scalar/ConstantProp.cpp
new file mode 100644
index 0000000..eef5a03
--- /dev/null
+++ b/lib/Transforms/Scalar/ConstantProp.cpp
@@ -0,0 +1,239 @@
+//===- ConstantProp.cpp - Code to perform Constant Propogation ------------===//
+//
+// This file implements constant propogation and merging:
+//
+// Specifically, this:
+// * Folds multiple identical constants in the constant pool together
+// Note that if one is named and the other is not, that the result gets the
+// original name.
+// * Converts instructions like "add int %1, %2" into a direct def of %3 in
+// the constant pool
+// * Converts conditional branches on a constant boolean value into direct
+// branches.
+// * Converts phi nodes with one incoming def to the incoming def directly
+// . Converts switch statements with one entry into a test & conditional
+// branch
+// . Converts switches on constant values into an unconditional branch.
+//
+// Notice that:
+// * This pass has a habit of making definitions be dead. It is a good idea
+// to to run a DCE pass sometime after running this pass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/iTerminators.h"
+#include "llvm/iOther.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/ConstantPool.h"
+#include "llvm/Opt/AllOpts.h"
+#include "llvm/Opt/ConstantHandling.h"
+
+// Merge identical constant values in the constant pool.
+//
+// TODO: We can do better than this simplistic N^2 algorithm...
+//
+static bool MergeConstantPoolReferences(ConstantPool &CP) {
+ bool Modified = false;
+ for (ConstantPool::plane_iterator PI = CP.begin(); PI != CP.end(); ++PI) {
+ for (ConstantPool::PlaneType::iterator I = (*PI)->begin();
+ I != (*PI)->end(); I++) {
+ ConstPoolVal *C = *I;
+
+ ConstantPool::PlaneType::iterator J = I;
+ for (++J; J != (*PI)->end(); J++) {
+ if (C->equals(*J)) {
+ Modified = true;
+ // Okay we know that *I == *J. So now we need to make all uses of *I
+ // point to *J.
+ //
+ C->replaceAllUsesWith(*J);
+
+ (*PI)->remove(I); // Remove C from constant pool...
+
+ if (C->hasName() && !(*J)->hasName()) // The merged constant inherits
+ (*J)->setName(C->getName()); // the old name...
+
+ delete C; // Delete the constant itself.
+ break; // Break out of inner for loop
+ }
+ }
+ }
+ }
+ return Modified;
+}
+
+inline static bool
+ConstantFoldUnaryInst(Method *M, Method::inst_iterator &DI,
+ UnaryOperator *Op, ConstPoolVal *D) {
+ ConstPoolVal *ReplaceWith = 0;
+
+ switch (Op->getInstType()) {
+ case Instruction::Not: ReplaceWith = !*D; break;
+ case Instruction::Neg: ReplaceWith = -*D; break;
+ }
+
+ if (!ReplaceWith) return false; // Nothing new to change...
+
+
+ // Add the new value to the constant pool...
+ M->getConstantPool().insert(ReplaceWith);
+
+ // Replaces all of the uses of a variable with uses of the constant.
+ Op->replaceAllUsesWith(ReplaceWith);
+
+ // Remove the operator from the list of definitions...
+ Op->getParent()->getInstList().remove(DI.getInstructionIterator());
+
+ // The new constant inherits the old name of the operator...
+ if (Op->hasName()) ReplaceWith->setName(Op->getName());
+
+ // Delete the operator now...
+ delete Op;
+ return true;
+}
+
+inline static bool
+ConstantFoldBinaryInst(Method *M, Method::inst_iterator &DI,
+ BinaryOperator *Op,
+ ConstPoolVal *D1, ConstPoolVal *D2) {
+ ConstPoolVal *ReplaceWith = 0;
+
+ switch (Op->getInstType()) {
+ case Instruction::Add: ReplaceWith = *D1 + *D2; break;
+ case Instruction::Sub: ReplaceWith = *D1 - *D2; break;
+
+ case Instruction::SetEQ: ReplaceWith = *D1 == *D2; break;
+ case Instruction::SetNE: ReplaceWith = *D1 != *D2; break;
+ case Instruction::SetLE: ReplaceWith = *D1 <= *D2; break;
+ case Instruction::SetGE: ReplaceWith = *D1 >= *D2; break;
+ case Instruction::SetLT: ReplaceWith = *D1 < *D2; break;
+ case Instruction::SetGT: ReplaceWith = *D1 > *D2; break;
+ }
+
+ if (!ReplaceWith) return false; // Nothing new to change...
+
+ // Add the new value to the constant pool...
+ M->getConstantPool().insert(ReplaceWith);
+
+ // Replaces all of the uses of a variable with uses of the constant.
+ Op->replaceAllUsesWith(ReplaceWith);
+
+ // Remove the operator from the list of definitions...
+ Op->getParent()->getInstList().remove(DI.getInstructionIterator());
+
+ // The new constant inherits the old name of the operator...
+ if (Op->hasName()) ReplaceWith->setName(Op->getName());
+
+ // Delete the operator now...
+ delete Op;
+ return true;
+}
+
+inline static bool ConstantFoldTerminator(TerminatorInst *T) {
+ // Branch - See if we are conditional jumping on constant
+ if (T->getInstType() == Instruction::Br) {
+ BranchInst *BI = (BranchInst*)T;
+ if (!BI->isUnconditional() && // Are we branching on constant?
+ BI->getOperand(2)->getValueType() == Value::ConstantVal) {
+ // YES. Change to unconditional branch...
+ ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
+ Value *Destination = BI->getOperand(Cond->getValue() ? 0 : 1);
+
+ BI->setOperand(0, Destination); // Set the unconditional destination
+ BI->setOperand(1, 0); // Clear the conditional destination
+ BI->setOperand(2, 0); // Clear the condition...
+ return true;
+ }
+ }
+ return false;
+}
+
+// ConstantFoldInstruction - If an instruction references constants, try to fold
+// them together...
+//
+inline static bool
+ConstantFoldInstruction(Method *M, Method::inst_iterator &II) {
+ Instruction *Inst = *II;
+ if (Inst->isBinaryOp()) {
+ Value *D1, *D2;
+ if (((D1 = Inst->getOperand(0))->getValueType() == Value::ConstantVal) &
+ ((D2 = Inst->getOperand(1))->getValueType() == Value::ConstantVal))
+ return ConstantFoldBinaryInst(M, II, (BinaryOperator*)Inst,
+ (ConstPoolVal*)D1, (ConstPoolVal*)D2);
+
+ } else if (Inst->isUnaryOp()) {
+ Value *D;
+ if ((D = Inst->getOperand(0))->getValueType() == Value::ConstantVal)
+ return ConstantFoldUnaryInst(M, II, (UnaryOperator*)Inst,
+ (ConstPoolVal*)D);
+ } else if (Inst->isTerminator()) {
+ return ConstantFoldTerminator((TerminatorInst*)Inst);
+
+ } else if (Inst->getInstType() == Instruction::PHINode) {
+ PHINode *PN = (PHINode*)Inst; // If it's a PHI node and only has one operand
+ // Then replace it directly with that operand.
+ assert(PN->getOperand(0) && "PHI Node must have at least one operand!");
+ if (PN->getOperand(1) == 0) { // If the PHI Node has exactly 1 operand
+ Value *V = PN->getOperand(0);
+ PN->replaceAllUsesWith(V); // Replace all uses of this PHI
+ // Unlink from basic block
+ PN->getParent()->getInstList().remove(II.getInstructionIterator());
+ if (PN->hasName()) V->setName(PN->getName()); // Inherit PHINode name
+ delete PN; // Finally, delete the node...
+ return true;
+ }
+ }
+ return false;
+}
+
+// DoConstPropPass - Propogate constants and do constant folding on instructions
+// this returns true if something was changed, false if nothing was changed.
+//
+static bool DoConstPropPass(Method *M) {
+ bool SomethingChanged = false;
+
+#if 1
+ Method::inst_iterator It = M->inst_begin();
+ while (It != M->inst_end())
+ if (ConstantFoldInstruction(M, It)) {
+ SomethingChanged = true; // If returned true, iter is already incremented
+
+ // Incrementing the iterator in an unchecked manner could mess up the
+ // internals of 'It'. To make sure everything is happy, tell it we might
+ // have broken it.
+ It.resyncInstructionIterator();
+ } else {
+ ++It;
+ }
+#else
+ Method::BasicBlocksType::iterator BBIt = M->getBasicBlocks().begin();
+ for (; BBIt != M->getBasicBlocks().end(); BBIt++) {
+ BasicBlock *BB = *BBIt;
+
+ BasicBlock::InstListType::iterator DI = BB->getInstList().begin();
+ for (; DI != BB->getInstList().end(); DI++)
+ SomethingChanged |= ConstantFoldInstruction(M, DI);
+ }
+#endif
+ return SomethingChanged;
+}
+
+
+// returns true on failure, false on success...
+//
+bool DoConstantPropogation(Method *M) {
+ bool Modified = false;
+
+ // Fold constants until we make no progress...
+ while (DoConstPropPass(M)) Modified = true;
+
+ // Merge identical constants last: this is important because we may have just
+ // introduced constants that already exist!
+ //
+ Modified |= MergeConstantPoolReferences(M->getConstantPool());
+
+ return Modified;
+}
diff --git a/lib/Transforms/Scalar/DCE.cpp b/lib/Transforms/Scalar/DCE.cpp
new file mode 100644
index 0000000..797edf5
--- /dev/null
+++ b/lib/Transforms/Scalar/DCE.cpp
@@ -0,0 +1,193 @@
+//===- DCE.cpp - Code to perform dead code elimination --------------------===//
+//
+// This file implements dead code elimination and basic block merging.
+//
+// Specifically, this:
+// * removes definitions with no uses (including unused constants)
+// * removes basic blocks with no predecessors
+// * merges a basic block into its predecessor if there is only one and the
+// predecessor only has one successor.
+//
+// TODO: This should REALLY be recursive instead of iterative. Right now, we
+// scan linearly through values, removing unused ones as we go. The problem is
+// that this may cause other earlier values to become unused. To make sure that
+// we get them all, we iterate until things stop changing. Instead, when
+// removing a value, recheck all of its operands to see if they are now unused.
+// Piece of cake, and more efficient as well.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/iTerminators.h"
+#include "llvm/Opt/AllOpts.h"
+
+struct ConstPoolDCE {
+ enum { EndOffs = 0 };
+ static bool isDCEable(const Value *) { return true; }
+};
+
+struct BasicBlockDCE {
+ enum { EndOffs = 1 };
+ static bool isDCEable(const Instruction *I) {
+ return !I->hasSideEffects();
+ }
+};
+
+template<class ValueSubclass, class ItemParentType, class DCEController>
+static bool RemoveUnusedDefs(ValueHolder<ValueSubclass, ItemParentType> &Vals,
+ DCEController DCEControl) {
+ bool Changed = false;
+ typedef ValueHolder<ValueSubclass, ItemParentType> Container;
+
+ int Offset = DCEController::EndOffs;
+ for (Container::iterator DI = Vals.begin(); DI != Vals.end()-Offset; ) {
+ // Look for un"used" definitions...
+ if ((*DI)->use_empty() && DCEController::isDCEable(*DI)) {
+ // Bye bye
+ delete Vals.remove(DI);
+ Changed = true;
+ } else {
+ DI++;
+ }
+ }
+ return Changed;
+}
+
+
+bool DoRemoveUnusedConstants(SymTabValue *S) {
+ bool Changed = false;
+ ConstantPool &CP = S->getConstantPool();
+ for (ConstantPool::plane_iterator PI = CP.begin(); PI != CP.end(); ++PI)
+ Changed |= RemoveUnusedDefs(**PI, ConstPoolDCE());
+ return Changed;
+}
+
+
+static void ReplaceUsesWithConstant(Instruction *I) {
+ // Get the method level constant pool
+ ConstantPool &CP = I->getParent()->getParent()->getConstantPool();
+
+ ConstPoolVal *CPV = 0;
+ ConstantPool::PlaneType *P;
+ if (!CP.getPlane(I->getType(), P)) { // Does plane exist?
+ // Yes, is it empty?
+ if (!P->empty()) CPV = P->front();
+ }
+
+ if (CPV == 0) { // We don't have an existing constant to reuse. Just add one.
+ CPV = ConstPoolVal::getNullConstant(I->getType()); // Create a new constant
+
+ // Add the new value to the constant pool...
+ CP.insert(CPV);
+ }
+
+ // Make all users of this instruction reference the constant instead
+ I->replaceAllUsesWith(CPV);
+}
+
+static bool DoDCEPass(Method *M) {
+ Method::BasicBlocksType::iterator BBIt;
+ Method::BasicBlocksType &BBs = M->getBasicBlocks();
+ bool Changed = false;
+
+ // Loop through now and remove instructions that have no uses...
+ for (BBIt = BBs.begin(); BBIt != BBs.end(); BBIt++)
+ Changed |= RemoveUnusedDefs((*BBIt)->getInstList(), BasicBlockDCE());
+
+ // Scan through and remove basic blocks that have no predecessors (except,
+ // of course, the first one. :) (so skip first block)
+ //
+ for (BBIt = BBs.begin(), ++BBIt; BBIt != BBs.end(); BBIt++) {
+ BasicBlock *BB = *BBIt;
+ assert(BB->getTerminator() &&
+ "Degenerate basic block encountered!"); // Empty bb???
+
+ if (BB->pred_begin() == BB->pred_end() &&
+ !BB->hasConstantPoolReferences()) {
+
+ while (!BB->getInstList().empty()) {
+ Instruction *I = BB->getInstList().front();
+ // If this instruction is used, replace uses with an arbitrary
+ // constant value. Because control flow can't get here, we don't care
+ // what we replace the value with.
+ if (!I->use_empty()) ReplaceUsesWithConstant(I);
+
+ // Remove the instruction from the basic block
+ BasicBlock::InstListType::iterator f = BB->getInstList().begin();
+ delete BB->getInstList().remove(f);
+ }
+
+ delete BBs.remove(BBIt);
+ ++BBIt; // remove puts use on the previous block, we want the next one
+ Changed = true;
+ }
+ }
+
+ // Loop through an merge basic blocks into their predecessor if there is only
+ // one, and if there is only one successor of the predecessor.
+ //
+ for (BBIt = BBs.begin(); BBIt != BBs.end(); BBIt++) {
+ BasicBlock *BB = *BBIt;
+
+ // Is there exactly one predecessor to this block?
+ BasicBlock::pred_iterator PI(BB->pred_begin());
+ if (PI != BB->pred_end() && ++PI == BB->pred_end() &&
+ !BB->hasConstantPoolReferences()) {
+ BasicBlock *Pred = *BB->pred_begin();
+ TerminatorInst *Term = Pred->getTerminator();
+ if (Term == 0) continue; // Err... malformed basic block!
+
+ // Is it an unconditional branch?
+ if (Term->getInstType() != Instruction::Br ||
+ !((BranchInst*)Term)->isUnconditional())
+ continue; // Nope, maybe next time...
+
+ Changed = true;
+
+ // Make all branches to the predecessor now point to the successor...
+ Pred->replaceAllUsesWith(BB);
+
+ // Move all definitions in the predecessor to the successor...
+ BasicBlock::InstListType::iterator DI = Pred->getInstList().end();
+ assert(Pred->getTerminator() &&
+ "Degenerate basic block encountered!"); // Empty bb???
+ delete Pred->getInstList().remove(--DI); // Remove terminator
+
+ while (Pred->getInstList().begin() != (DI = Pred->getInstList().end())) {
+ Instruction *Def = Pred->getInstList().remove(--DI); // Remove from end
+ BB->getInstList().push_front(Def); // Add to front...
+ }
+
+ // Remove basic block from the method...
+ BBs.remove(Pred);
+
+ // Always inherit predecessors name if it exists...
+ if (Pred->hasName()) BB->setName(Pred->getName());
+
+ // So long you waste of a basic block you...
+ delete Pred;
+ }
+ }
+
+ // Remove unused constants
+ Changed |= DoRemoveUnusedConstants(M);
+ return Changed;
+}
+
+
+// It is possible that we may require multiple passes over the code to fully
+// eliminate dead code. Iterate until we are done.
+//
+bool DoDeadCodeElimination(Method *M) {
+ bool Changed = false;
+ while (DoDCEPass(M)) Changed = true;
+ return Changed;
+}
+
+bool DoDeadCodeElimination(Module *C) {
+ bool Val = ApplyOptToAllMethods(C, DoDeadCodeElimination);
+ while (DoRemoveUnusedConstants(C)) Val = true;
+ return Val;
+}
diff --git a/lib/Transforms/Scalar/SymbolStripping.cpp b/lib/Transforms/Scalar/SymbolStripping.cpp
new file mode 100644
index 0000000..af5f18f
--- /dev/null
+++ b/lib/Transforms/Scalar/SymbolStripping.cpp
@@ -0,0 +1,55 @@
+//===- SymbolStripping.cpp - Code to string symbols for methods and modules -=//
+//
+// This file implements stripping symbols out of symbol tables.
+//
+// Specifically, this allows you to strip all of the symbols out of:
+// * A method
+// * All methods in a module
+// * All symbols in a module (all method symbols + all module scope symbols)
+//
+// Notice that:
+// * This pass makes code much less readable, so it should only be used in
+// situations where the 'strip' utility would be used (such as reducing
+// code size, and making it harder to reverse engineer code).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Module.h"
+#include "llvm/Method.h"
+#include "llvm/SymbolTable.h"
+#include "llvm/Opt/AllOpts.h"
+
+static bool StripSymbolTable(SymbolTable *SymTab) {
+ if (SymTab == 0) return false; // No symbol table? No problem.
+ bool RemovedSymbol = false;
+
+ for (SymbolTable::iterator I = SymTab->begin(); I != SymTab->end(); I++) {
+ map<const string, Value *> &Plane = I->second;
+
+ map<const string, Value *>::iterator B;
+ while ((B = Plane.begin()) != Plane.end()) { // Found nonempty type plane!
+ B->second->setName(""); // Set name to "", removing from symbol table!
+ RemovedSymbol = true;
+ assert(Plane.begin() != B);
+ }
+ }
+
+ return RemovedSymbol;
+}
+
+
+// DoSymbolStripping - Remove all symbolic information from a method
+//
+bool DoSymbolStripping(Method *M) {
+ return StripSymbolTable(M->getSymbolTable());
+}
+
+// DoFullSymbolStripping - Remove all symbolic information from all methods
+// in a module, and all module level symbols. (method names, etc...)
+//
+bool DoFullSymbolStripping(Module *M) {
+ // Remove all symbols from methods in this module... and then strip all of the
+ // symbols in this module...
+ //
+ return DoSymbolStripping(M) | StripSymbolTable(M->getSymbolTable());
+}