mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15328 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			171 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/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;
 | 
						|
    }
 | 
						|
}
 |