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