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/Instructions.h"
21 #include "llvm/Support/InstIterator.h"
30 class ConstantExpressionsLower : public FunctionPass {
31 private: // FunctionPass overrides
33 bool runOnFunction(Function& f);
35 private: // internal methods
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);
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);
50 RegisterOpt<ConstantExpressionsLower> X(
51 "lowerconstantexprs", "Lower constant expressions");
54 bool ConstantExpressionsLower::runOnFunction(Function& f)
56 bool modified = false;
57 for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e; ++i)
59 modified |= runOnInstruction(*i);
64 bool ConstantExpressionsLower::runOnInstruction(Instruction& instruction)
66 bool modified = false;
67 for (unsigned pos = 0; pos < instruction.getNumOperands(); ++pos)
70 = dyn_cast<ConstantExpr>(instruction.getOperand(pos))) {
72 // Decide where to insert the new instruction
73 Instruction* where = &instruction;
75 // For PHI nodes we can't insert new instruction before phi,
76 // since phi should always come at the beginning of the
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);
87 assert(predecessor && "could not find predecessor");
88 where = predecessor->getTerminator();
90 Instruction* n = convert(*ce, where);
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
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);
103 // The new instruction might have constant expressions in
104 // it. Extract them too.
105 runOnInstruction(*n);
113 ConstantExpressionsLower::convert(const ConstantExpr& c, Instruction* where)
115 Instruction* result = 0;
117 if (c.getOpcode() >= Instruction::BinaryOpsBegin &&
118 c.getOpcode() < Instruction::BinaryOpsEnd)
120 result = BinaryOperator::create(
121 static_cast<Instruction::BinaryOps>(c.getOpcode()),
122 c.getOperand(0), c.getOperand(1), "", where);
126 switch(c.getOpcode()) {
127 case Instruction::GetElementPtr:
130 for (unsigned i = 1; i < c.getNumOperands(); ++i)
131 idx.push_back(c.getOperand(i));
132 result = new GetElementPtrInst(c.getOperand(0),
137 case Instruction::Cast:
138 result = new CastInst(c.getOperand(0), c.getType(), "",
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);
150 case Instruction::Select:
151 result = new SelectInst(c.getOperand(0), c.getOperand(1),
152 c.getOperand(2), "", where);
156 std::cerr << "Offending expr: " << c << "\n";
157 assert(0 && "Constant expression not yet handled!\n");
166 FunctionPass* createLowerConstantExpressionsPass()
168 return new ConstantExpressionsLower;