Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 1 | //===- ConstantProp.cpp - Code to perform Simple Constant Propogation -----===// |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 2 | // |
| 3 | // This file implements constant propogation and merging: |
| 4 | // |
| 5 | // Specifically, this: |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 6 | // * Converts instructions like "add int 1, 2" into 3 |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 7 | // |
| 8 | // Notice that: |
| 9 | // * This pass has a habit of making definitions be dead. It is a good idea |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 10 | // to to run a DIE pass sometime after running this pass. |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Chris Lattner | ee965ab | 2002-01-21 23:17:48 +0000 | [diff] [blame] | 14 | #include "llvm/Transforms/Scalar/ConstantProp.h" |
Chris Lattner | 65b529f | 2002-04-08 20:18:09 +0000 | [diff] [blame] | 15 | #include "llvm/ConstantHandling.h" |
Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 16 | #include "llvm/Function.h" |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 17 | #include "llvm/BasicBlock.h" |
| 18 | #include "llvm/iTerminators.h" |
Chris Lattner | 04805fa | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 19 | #include "llvm/Pass.h" |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 20 | #include "llvm/Support/InstIterator.h" |
| 21 | #include <set> |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 22 | |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 23 | // FIXME: ConstantFoldInstruction & ConstantFoldTerminator should be moved out |
| 24 | // to the Transformations library. |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 25 | |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 26 | // ConstantFoldInstruction - If an instruction references constants, try to fold |
| 27 | // them together... |
| 28 | // |
| 29 | bool doConstantPropogation(BasicBlock *BB, BasicBlock::iterator &II) { |
| 30 | Instruction *Inst = *II; |
| 31 | if (Constant *C = ConstantFoldInstruction(Inst)) { |
| 32 | // Replaces all of the uses of a variable with uses of the constant. |
| 33 | Inst->replaceAllUsesWith(C); |
| 34 | |
| 35 | // Remove the instruction from the basic block... |
| 36 | delete BB->getInstList().remove(II); |
| 37 | return true; |
| 38 | } |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 39 | |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 40 | return false; |
Chris Lattner | 940daed | 2002-05-06 03:01:37 +0000 | [diff] [blame] | 41 | } |
| 42 | |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 43 | // ConstantFoldTerminator - If a terminator instruction is predicated on a |
| 44 | // constant value, convert it into an unconditional branch to the constant |
| 45 | // destination. |
| 46 | // |
Chris Lattner | 477fe08 | 2002-03-11 22:11:07 +0000 | [diff] [blame] | 47 | bool ConstantFoldTerminator(BasicBlock *BB, BasicBlock::iterator &II, |
| 48 | TerminatorInst *T) { |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 49 | // Branch - See if we are conditional jumping on constant |
Chris Lattner | da55810 | 2001-10-02 03:41:24 +0000 | [diff] [blame] | 50 | if (BranchInst *BI = dyn_cast<BranchInst>(T)) { |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 51 | if (BI->isUnconditional()) return false; // Can't optimize uncond branch |
Chris Lattner | 4b717c0 | 2001-10-01 16:18:37 +0000 | [diff] [blame] | 52 | BasicBlock *Dest1 = cast<BasicBlock>(BI->getOperand(0)); |
| 53 | BasicBlock *Dest2 = cast<BasicBlock>(BI->getOperand(1)); |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 54 | |
Chris Lattner | 3462ae3 | 2001-12-03 22:26:30 +0000 | [diff] [blame] | 55 | if (ConstantBool *Cond = dyn_cast<ConstantBool>(BI->getCondition())) { |
Chris Lattner | 3856934 | 2001-10-01 20:11:19 +0000 | [diff] [blame] | 56 | // Are we branching on constant? |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 57 | // YES. Change to unconditional branch... |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 58 | BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2; |
| 59 | BasicBlock *OldDest = Cond->getValue() ? Dest2 : Dest1; |
Chris Lattner | e4abb60 | 2001-06-29 05:23:10 +0000 | [diff] [blame] | 60 | |
Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 61 | //cerr << "Function: " << T->getParent()->getParent() |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 62 | // << "\nRemoving branch from " << T->getParent() |
| 63 | // << "\n\nTo: " << OldDest << endl; |
Chris Lattner | e4abb60 | 2001-06-29 05:23:10 +0000 | [diff] [blame] | 64 | |
| 65 | // Let the basic block know that we are letting go of it. Based on this, |
| 66 | // it will adjust it's PHI nodes. |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 67 | assert(BI->getParent() && "Terminator not inserted in block!"); |
| 68 | OldDest->removePredecessor(BI->getParent()); |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 69 | |
Chris Lattner | a073acb | 2001-07-07 08:36:50 +0000 | [diff] [blame] | 70 | // Set the unconditional destination, and change the insn to be an |
| 71 | // unconditional branch. |
| 72 | BI->setUnconditionalDest(Destination); |
Chris Lattner | 477fe08 | 2002-03-11 22:11:07 +0000 | [diff] [blame] | 73 | II = BB->end()-1; // Update instruction iterator! |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 74 | return true; |
Chris Lattner | 030772d | 2001-09-07 16:41:30 +0000 | [diff] [blame] | 75 | } |
| 76 | #if 0 |
| 77 | // FIXME: TODO: This doesn't work if the destination has PHI nodes with |
| 78 | // different incoming values on each branch! |
| 79 | // |
| 80 | else if (Dest2 == Dest1) { // Conditional branch to same location? |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 81 | // This branch matches something like this: |
| 82 | // br bool %cond, label %Dest, label %Dest |
| 83 | // and changes it into: br label %Dest |
| 84 | |
| 85 | // Let the basic block know that we are letting go of one copy of it. |
| 86 | assert(BI->getParent() && "Terminator not inserted in block!"); |
| 87 | Dest1->removePredecessor(BI->getParent()); |
| 88 | |
Chris Lattner | a073acb | 2001-07-07 08:36:50 +0000 | [diff] [blame] | 89 | // Change a conditional branch to unconditional. |
| 90 | BI->setUnconditionalDest(Dest1); |
Chris Lattner | 7ce8b17 | 2001-06-29 23:56:58 +0000 | [diff] [blame] | 91 | return true; |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 92 | } |
Chris Lattner | 030772d | 2001-09-07 16:41:30 +0000 | [diff] [blame] | 93 | #endif |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 94 | } |
| 95 | return false; |
| 96 | } |
| 97 | |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 98 | |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 99 | |
Chris Lattner | 04805fa | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 100 | namespace { |
Chris Lattner | c8e6654 | 2002-04-27 06:56:12 +0000 | [diff] [blame] | 101 | struct ConstantPropogation : public FunctionPass { |
Chris Lattner | 37104aa | 2002-04-29 14:57:45 +0000 | [diff] [blame] | 102 | const char *getPassName() const { return "Simple Constant Propogation"; } |
| 103 | |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 104 | inline bool runOnFunction(Function *F); |
Chris Lattner | f12cc84 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 105 | |
| 106 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 107 | AU.preservesCFG(); |
Chris Lattner | f12cc84 | 2002-04-28 21:27:06 +0000 | [diff] [blame] | 108 | } |
Chris Lattner | 04805fa | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 109 | }; |
Chris Lattner | 2f7c963 | 2001-06-06 20:29:01 +0000 | [diff] [blame] | 110 | } |
Chris Lattner | 04805fa | 2002-02-26 21:46:54 +0000 | [diff] [blame] | 111 | |
| 112 | Pass *createConstantPropogationPass() { |
| 113 | return new ConstantPropogation(); |
| 114 | } |
| 115 | |
Chris Lattner | e548507 | 2002-05-06 18:21:31 +0000 | [diff] [blame^] | 116 | |
| 117 | bool ConstantPropogation::runOnFunction(Function *F) { |
| 118 | // Initialize the worklist to all of the instructions ready to process... |
| 119 | std::set<Instruction*> WorkList(inst_begin(F), inst_end(F)); |
| 120 | bool Changed = false; |
| 121 | |
| 122 | while (!WorkList.empty()) { |
| 123 | Instruction *I = *WorkList.begin(); |
| 124 | WorkList.erase(WorkList.begin()); // Get an element from the worklist... |
| 125 | |
| 126 | if (!I->use_empty()) // Don't muck with dead instructions... |
| 127 | if (Constant *C = ConstantFoldInstruction(I)) { |
| 128 | // Add all of the users of this instruction to the worklist, they might |
| 129 | // be constant propogatable now... |
| 130 | for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); |
| 131 | UI != UE; ++UI) |
| 132 | WorkList.insert(cast<Instruction>(*UI)); |
| 133 | |
| 134 | // Replace all of the uses of a variable with uses of the constant. |
| 135 | I->replaceAllUsesWith(C); |
| 136 | |
| 137 | // We made a change to the function... |
| 138 | Changed = true; |
| 139 | } |
| 140 | } |
| 141 | return Changed; |
| 142 | } |