llvm.org GIT mirror llvm / 66c5fd6 lib / Transforms / Scalar / LowerConstantExprs.cpp
66c5fd6

Tree @66c5fd6 (Download .tar.gz)

LowerConstantExprs.cpp @66c5fd6raw · history · blame

//===-- 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/Instructions.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;
    }
}