mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 23:48:49 +00:00
New constant expression lowering pass to simplify your instruction selection needs.
Contributed by Vladimir Prus! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14399 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dfde14ef5a
commit
9dc1b2ae9b
171
lib/Transforms/Scalar/LowerConstantExprs.cpp
Normal file
171
lib/Transforms/Scalar/LowerConstantExprs.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
//===-- lib/Transforms/Scalar/LowerConstantExprs.cpp ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was written by Vladimir Prus and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the LowerConstantExpression pass, which converts all
|
||||
// constant expressions into instructions. This is primarily usefull for
|
||||
// code generators which don't yet want or don't have a need to handle
|
||||
// constant expressions themself.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/iMemory.h"
|
||||
#include "llvm/iPHINode.h"
|
||||
#include "llvm/iOther.h"
|
||||
#include "llvm/Support/InstIterator.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class ConstantExpressionsLower : public FunctionPass {
|
||||
private: // FunctionPass overrides
|
||||
|
||||
bool runOnFunction(Function& f);
|
||||
|
||||
private: // internal methods
|
||||
|
||||
/// For all operands of 'insn' which are constant expressions, generates
|
||||
/// an appropriate instruction and replaces the use of constant
|
||||
/// expression with the use of the generated instruction.
|
||||
bool runOnInstruction(Instruction& insn);
|
||||
|
||||
/// Given an constant expression 'c' which occures in 'instruction',
|
||||
/// at position 'pos',
|
||||
/// generates instruction to compute 'c' and replaces the use of 'c'
|
||||
/// with the use of that instruction. This handles only top-level
|
||||
/// expression in 'c', any subexpressions are not handled.
|
||||
Instruction* convert(const ConstantExpr& c, Instruction* where);
|
||||
};
|
||||
|
||||
RegisterOpt<ConstantExpressionsLower> X(
|
||||
"lowerconstantexprs", "Lower constant expressions");
|
||||
}
|
||||
|
||||
bool ConstantExpressionsLower::runOnFunction(Function& f)
|
||||
{
|
||||
bool modified = false;
|
||||
for (inst_iterator i = inst_begin(f), e = inst_end(f); i != e; ++i)
|
||||
{
|
||||
modified |= runOnInstruction(*i);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool ConstantExpressionsLower::runOnInstruction(Instruction& instruction)
|
||||
{
|
||||
bool modified = false;
|
||||
for (unsigned pos = 0; pos < instruction.getNumOperands(); ++pos)
|
||||
{
|
||||
if (ConstantExpr* ce
|
||||
= dyn_cast<ConstantExpr>(instruction.getOperand(pos))) {
|
||||
|
||||
// Decide where to insert the new instruction
|
||||
Instruction* where = &instruction;
|
||||
|
||||
// For PHI nodes we can't insert new instruction before phi,
|
||||
// since phi should always come at the beginning of the
|
||||
// basic block.
|
||||
// So, we need to insert it in the predecessor, right before
|
||||
// the terminating instruction.
|
||||
if (PHINode* p = dyn_cast<PHINode>(&instruction)) {
|
||||
BasicBlock* predecessor = 0;
|
||||
for(unsigned i = 0; i < p->getNumIncomingValues(); ++i)
|
||||
if (p->getIncomingValue(i) == ce) {
|
||||
predecessor = p->getIncomingBlock(i);
|
||||
break;
|
||||
}
|
||||
assert(predecessor && "could not find predecessor");
|
||||
where = predecessor->getTerminator();
|
||||
}
|
||||
Instruction* n = convert(*ce, where);
|
||||
|
||||
// Note: we can't call replaceAllUsesWith, since
|
||||
// that might replace uses in another functions,
|
||||
// where the instruction(s) we've generated are not
|
||||
// available.
|
||||
|
||||
// Moreover, we can't replace all the users in the same
|
||||
// function, because we can't be sure the definition
|
||||
// made in this block will be available in other
|
||||
// places where the constant is used.
|
||||
instruction.setOperand(pos, n);
|
||||
|
||||
// The new instruction might have constant expressions in
|
||||
// it. Extract them too.
|
||||
runOnInstruction(*n);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
Instruction*
|
||||
ConstantExpressionsLower::convert(const ConstantExpr& c, Instruction* where)
|
||||
{
|
||||
Instruction* result = 0;
|
||||
|
||||
if (c.getOpcode() >= Instruction::BinaryOpsBegin &&
|
||||
c.getOpcode() < Instruction::BinaryOpsEnd)
|
||||
{
|
||||
result = BinaryOperator::create(
|
||||
static_cast<Instruction::BinaryOps>(c.getOpcode()),
|
||||
c.getOperand(0), c.getOperand(1), "", where);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(c.getOpcode()) {
|
||||
case Instruction::GetElementPtr:
|
||||
{
|
||||
vector<Value*> idx;
|
||||
for (unsigned i = 1; i < c.getNumOperands(); ++i)
|
||||
idx.push_back(c.getOperand(i));
|
||||
result = new GetElementPtrInst(c.getOperand(0),
|
||||
idx, "", where);
|
||||
break;
|
||||
}
|
||||
|
||||
case Instruction::Cast:
|
||||
result = new CastInst(c.getOperand(0), c.getType(), "",
|
||||
where);
|
||||
break;
|
||||
|
||||
|
||||
case Instruction::Shl:
|
||||
case Instruction::Shr:
|
||||
result = new ShiftInst(
|
||||
static_cast<Instruction::OtherOps>(c.getOpcode()),
|
||||
c.getOperand(0), c.getOperand(1), "", where);
|
||||
break;
|
||||
|
||||
case Instruction::Select:
|
||||
result = new SelectInst(c.getOperand(0), c.getOperand(1),
|
||||
c.getOperand(2), "", where);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "Offending expr: " << c << "\n";
|
||||
assert(0 && "Constant expression not yet handled!\n");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace llvm {
|
||||
FunctionPass* createLowerConstantExpressionsPass()
|
||||
{
|
||||
return new ConstantExpressionsLower;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user