mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14622 91177308-0d34-0410-b5e6-96231b3b80d8
173 lines
5.8 KiB
C++
173 lines
5.8 KiB
C++
//===-- 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>
|
|
#include <iostream>
|
|
|
|
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;
|
|
}
|
|
}
|