New constant expression lowering pass to simplify your instruction selection needs.
authorChris Lattner <sabre@nondot.org>
Fri, 25 Jun 2004 07:48:09 +0000 (07:48 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 25 Jun 2004 07:48:09 +0000 (07:48 +0000)
Contributed by Vladimir Prus!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14399 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/LowerConstantExprs.cpp [new file with mode: 0644]

diff --git a/lib/Transforms/Scalar/LowerConstantExprs.cpp b/lib/Transforms/Scalar/LowerConstantExprs.cpp
new file mode 100644 (file)
index 0000000..9eeef5e
--- /dev/null
@@ -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;
+    }
+}