1 //===-- lib/Transforms/Scalar/LowerConstantExprs.cpp ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
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.
8 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
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"
32 class ConstantExpressionsLower : public FunctionPass {
33 private: // FunctionPass overrides
35 bool runOnFunction(Function& f);
37 private: // internal methods
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);
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);
52 RegisterOpt<ConstantExpressionsLower> X(
53 "lowerconstantexprs", "Lower constant expressions");
56 bool ConstantExpressionsLower::runOnFunction(Function& f)
58 bool modified = false;
59 for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e; ++i)
61 modified |= runOnInstruction(*i);
66 bool ConstantExpressionsLower::runOnInstruction(Instruction& instruction)
68 bool modified = false;
69 for (unsigned pos = 0; pos < instruction.getNumOperands(); ++pos)
72 = dyn_cast<ConstantExpr>(instruction.getOperand(pos))) {
74 // Decide where to insert the new instruction
75 Instruction* where = &instruction;
77 // For PHI nodes we can't insert new instruction before phi,
78 // since phi should always come at the beginning of the
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);
89 assert(predecessor && "could not find predecessor");
90 where = predecessor->getTerminator();
92 Instruction* n = convert(*ce, where);
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
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);
105 // The new instruction might have constant expressions in
106 // it. Extract them too.
107 runOnInstruction(*n);
115 ConstantExpressionsLower::convert(const ConstantExpr& c, Instruction* where)
117 Instruction* result = 0;
119 if (c.getOpcode() >= Instruction::BinaryOpsBegin &&
120 c.getOpcode() < Instruction::BinaryOpsEnd)
122 result = BinaryOperator::create(
123 static_cast<Instruction::BinaryOps>(c.getOpcode()),
124 c.getOperand(0), c.getOperand(1), "", where);
128 switch(c.getOpcode()) {
129 case Instruction::GetElementPtr:
132 for (unsigned i = 1; i < c.getNumOperands(); ++i)
133 idx.push_back(c.getOperand(i));
134 result = new GetElementPtrInst(c.getOperand(0),
139 case Instruction::Cast:
140 result = new CastInst(c.getOperand(0), c.getType(), "",
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);
152 case Instruction::Select:
153 result = new SelectInst(c.getOperand(0), c.getOperand(1),
154 c.getOperand(2), "", where);
158 std::cerr << "Offending expr: " << c << "\n";
159 assert(0 && "Constant expression not yet handled!\n");
168 FunctionPass* createLowerConstantExpressionsPass()
170 return new ConstantExpressionsLower;