Throttle back indvar substitution from creating multiplies in loops. This is bad...
[oota-llvm.git] / lib / Transforms / Scalar / LowerConstantExprs.cpp
1 //===-- lib/Transforms/Scalar/LowerConstantExprs.cpp ------------*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was written by Vladimir Prus and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the LowerConstantExpression pass, which converts all
11 // constant expressions into instructions. This is primarily usefull for 
12 // code generators which don't yet want or don't have a need to handle
13 // constant expressions themself.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "llvm/Pass.h"
18 #include "llvm/Function.h"
19 #include "llvm/Constants.h"
20 #include "llvm/iMemory.h"
21 #include "llvm/iPHINode.h"
22 #include "llvm/iOther.h"
23 #include "llvm/Support/InstIterator.h"
24 #include <vector>
25 #include <iostream>
26
27 using namespace llvm;
28 using namespace std;
29
30 namespace {
31
32     class ConstantExpressionsLower : public FunctionPass {
33     private: // FunctionPass overrides
34         
35         bool runOnFunction(Function& f);
36
37     private: // internal methods
38
39         /// For all operands of 'insn' which are constant expressions, generates
40         /// an appropriate instruction and replaces the use of constant 
41         /// expression with the use of the generated instruction.
42         bool runOnInstruction(Instruction& insn);
43
44         /// Given an constant expression 'c' which occures in 'instruction',
45         /// at position 'pos', 
46         /// generates instruction to compute 'c' and replaces the use of 'c'
47         /// with the use of that instruction. This handles only top-level
48         /// expression in 'c', any subexpressions are not handled.
49         Instruction* convert(const ConstantExpr& c, Instruction* where);
50     };
51
52     RegisterOpt<ConstantExpressionsLower> X(
53         "lowerconstantexprs", "Lower constant expressions");    
54 }
55
56 bool ConstantExpressionsLower::runOnFunction(Function& f)
57 {
58     bool modified = false;
59     for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e; ++i)
60     {
61         modified |= runOnInstruction(*i);
62     }
63     return modified;
64 }
65
66 bool ConstantExpressionsLower::runOnInstruction(Instruction& instruction)
67 {
68     bool modified = false;
69     for (unsigned pos = 0; pos < instruction.getNumOperands(); ++pos)
70     {
71         if (ConstantExpr* ce 
72             = dyn_cast<ConstantExpr>(instruction.getOperand(pos))) {
73
74             // Decide where to insert the new instruction
75             Instruction* where = &instruction;
76
77             // For PHI nodes we can't insert new instruction before phi, 
78             // since phi should always come at the beginning of the 
79             // basic block.
80             // So, we need to insert it in the predecessor, right before
81             // the terminating instruction.
82             if (PHINode* p = dyn_cast<PHINode>(&instruction)) {
83                 BasicBlock* predecessor = 0;
84                 for(unsigned i = 0; i < p->getNumIncomingValues(); ++i)
85                     if (p->getIncomingValue(i) == ce) {
86                         predecessor = p->getIncomingBlock(i);
87                         break;
88                     }
89                 assert(predecessor && "could not find predecessor");
90                 where = predecessor->getTerminator();
91             }
92             Instruction* n = convert(*ce, where);
93
94             // Note: we can't call replaceAllUsesWith, since
95             // that might replace uses in another functions,
96             // where the instruction(s) we've generated are not
97             // available. 
98                     
99             // Moreover, we can't replace all the users in the same 
100             // function, because we can't be sure the definition 
101             // made in this block will be available in other
102             // places where the constant is used.                                       
103             instruction.setOperand(pos, n);
104
105             // The new instruction might have constant expressions in
106             // it. Extract them too.
107             runOnInstruction(*n);
108             modified = true;
109         }
110     }            
111     return modified;
112 }
113
114 Instruction* 
115 ConstantExpressionsLower::convert(const ConstantExpr& c, Instruction* where)
116 {
117     Instruction* result = 0;
118
119     if (c.getOpcode() >= Instruction::BinaryOpsBegin &&
120         c.getOpcode() < Instruction::BinaryOpsEnd)
121     {
122         result = BinaryOperator::create(
123             static_cast<Instruction::BinaryOps>(c.getOpcode()), 
124             c.getOperand(0), c.getOperand(1), "", where);
125     }
126     else
127     {
128         switch(c.getOpcode()) {
129         case Instruction::GetElementPtr: 
130         {
131             vector<Value*> idx;
132             for (unsigned i = 1; i < c.getNumOperands(); ++i)
133                 idx.push_back(c.getOperand(i));
134             result = new GetElementPtrInst(c.getOperand(0),
135                                            idx, "", where);
136             break;
137         }
138
139         case Instruction::Cast:
140             result = new CastInst(c.getOperand(0), c.getType(), "", 
141                                   where);
142             break;
143
144
145         case Instruction::Shl:
146         case Instruction::Shr:
147             result = new ShiftInst(
148                 static_cast<Instruction::OtherOps>(c.getOpcode()), 
149                 c.getOperand(0), c.getOperand(1), "", where);
150             break;
151                     
152         case Instruction::Select:
153             result = new SelectInst(c.getOperand(0), c.getOperand(1),
154                                     c.getOperand(2), "", where);
155             break;
156                  
157         default:
158             std::cerr << "Offending expr: " << c << "\n";
159             assert(0 && "Constant expression not yet handled!\n");
160         }
161     }
162     return result;
163 }
164
165
166
167 namespace llvm {
168     FunctionPass* createLowerConstantExpressionsPass()
169     {
170         return new ConstantExpressionsLower;
171     }
172 }