[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LowerConstantExprs.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Jun 25 02:49:03 PDT 2004


Changes in directory llvm/lib/Transforms/Scalar:

LowerConstantExprs.cpp added (r1.1)

---
Log message:

New constant expression lowering pass to simplify your instruction selection needs.

Contributed by Vladimir Prus!



---
Diffs of the changes:  (+171 -0)

Index: llvm/lib/Transforms/Scalar/LowerConstantExprs.cpp
diff -c /dev/null llvm/lib/Transforms/Scalar/LowerConstantExprs.cpp:1.1
*** /dev/null	Fri Jun 25 02:48:19 2004
--- llvm/lib/Transforms/Scalar/LowerConstantExprs.cpp	Fri Jun 25 02:48:09 2004
***************
*** 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;
+     }
+ }





More information about the llvm-commits mailing list