diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp | 238 | 
1 files changed, 111 insertions, 127 deletions
| diff --git a/llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp b/llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp index f901a29015d..f4bb51a02d1 100644 --- a/llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp +++ b/llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp @@ -1,4 +1,4 @@ -//===- llvm/Transforms/DecomposeMultiDimRefs.cpp - Lower array refs to 1D ---=// +//===- llvm/Transforms/DecomposeMultiDimRefs.cpp - Lower array refs to 1D -===//  //  // DecomposeMultiDimRefs -   // Convert multi-dimensional references consisting of any combination @@ -17,6 +17,41 @@  #include "llvm/Function.h"  #include "llvm/Pass.h" +namespace { +  struct DecomposePass : public BasicBlockPass { +    virtual bool runOnBasicBlock(BasicBlock *BB); + +  private: +    static void decomposeArrayRef(BasicBlock::iterator &BBI); +  }; +} + +Pass *createDecomposeMultiDimRefsPass() { +  return new DecomposePass(); +} + + +// runOnBasicBlock - Entry point for array or structure references with multiple +// indices. +// +bool DecomposePass::runOnBasicBlock(BasicBlock *BB) { +  bool Changed = false; +   +  for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ) { +    if (MemAccessInst *MAI = dyn_cast<MemAccessInst>(*II)) { +      if (MAI->getNumOperands() > MAI->getFirstIndexOperandNumber()+1) { +        decomposeArrayRef(II); +        Changed = true; +      } else { +        ++II; +      } +    } else { +      ++II; +    } +  } +   +  return Changed; +}  //   // For any combination of 2 or more array and structure indices, @@ -28,160 +63,109 @@  // uses the last ptr2 generated in the loop and a single index.  // If any index is (uint) 0, we omit the getElementPtr instruction.  //  -static BasicBlock::iterator -decomposeArrayRef(BasicBlock::iterator& BBI) -{ +void DecomposePass::decomposeArrayRef(BasicBlock::iterator &BBI){    MemAccessInst *memI = cast<MemAccessInst>(*BBI);    BasicBlock* BB = memI->getParent();    Value* lastPtr = memI->getPointerOperand(); + +  // Remove the instruction from the stream +  BB->getInstList().remove(BBI); +    vector<Instruction*> newIvec;    // Process each index except the last one.    //  -  MemAccessInst::const_op_iterator OI = memI->idx_begin(); -  MemAccessInst::const_op_iterator OE = memI->idx_end(); -  for ( ; OI != OE; ++OI) -    { -      assert(isa<PointerType>(lastPtr->getType())); -       -      if (OI+1 == OE)                   // stop before the last operand -        break; +  User::const_op_iterator OI = memI->idx_begin(), OE = memI->idx_end(); +  for (; OI != OE && OI+1 != OE; ++OI) { +    assert(isa<PointerType>(lastPtr->getType())); -      // Check for a zero index.  This will need a cast instead of -      // a getElementPtr, or it may need neither. -      bool indexIsZero = bool(isa<ConstantUInt>(*OI) &&  -                              cast<ConstantUInt>(*OI)->getValue() == 0); +    // Check for a zero index.  This will need a cast instead of +    // a getElementPtr, or it may need neither. +    bool indexIsZero = isa<ConstantUInt>(*OI) &&  +                       cast<Constant>(*OI)->isNullValue(); -      // Extract the first index.  If the ptr is a pointer to a structure -      // and the next index is a structure offset (i.e., not an array offset),  -      // we need to include an initial [0] to index into the pointer. -      vector<Value*> idxVec(1, *OI); -      PointerType* ptrType = cast<PointerType>(lastPtr->getType()); -      if (isa<StructType>(ptrType->getElementType()) -          && ! ptrType->indexValid(*OI)) -        idxVec.insert(idxVec.begin(), ConstantUInt::get(Type::UIntTy, 0)); +    // Extract the first index.  If the ptr is a pointer to a structure +    // and the next index is a structure offset (i.e., not an array offset),  +    // we need to include an initial [0] to index into the pointer. +    vector<Value*> idxVec(1, *OI); +    PointerType* ptrType = cast<PointerType>(lastPtr->getType()); +    if (isa<StructType>(ptrType->getElementType()) +        && ! ptrType->indexValid(*OI)) +      idxVec.insert(idxVec.begin(), ConstantUInt::get(Type::UIntTy, 0)); +     +    // Get the type obtained by applying the first index. +    // It must be a structure or array. +    const Type* nextType = MemAccessInst::getIndexedType(lastPtr->getType(), +                                                         idxVec, true); +    assert(isa<StructType>(nextType) || isa<ArrayType>(nextType)); +     +    // Get a pointer to the structure or to the elements of the array. +    const Type* nextPtrType = +      PointerType::get(isa<StructType>(nextType) ? nextType +                       : cast<ArrayType>(nextType)->getElementType()); -      // Get the type obtained by applying the first index. -      // It must be a structure or array. -      const Type* nextType = MemAccessInst::getIndexedType(lastPtr->getType(), -                                                           idxVec, true); -      assert(isa<StructType>(nextType) || isa<ArrayType>(nextType)); -       -      // Get a pointer to the structure or to the elements of the array. -      const Type* nextPtrType = -        PointerType::get(isa<StructType>(nextType)? nextType -                         : cast<ArrayType>(nextType)->getElementType()); -       -      // Instruction 1: nextPtr1 = GetElementPtr lastPtr, idxVec -      // This is not needed if the index is zero. -      Value* gepValue; -      if (indexIsZero) -        gepValue = lastPtr; -      else -        { -          gepValue = new GetElementPtrInst(lastPtr, idxVec,"ptr1"); -          newIvec.push_back(cast<Instruction>(gepValue)); -        } -       -      // Instruction 2: nextPtr2 = cast nextPtr1 to nextPtrType -      // This is not needed if the two types are identical. -      Value* castInst; -      if (gepValue->getType() == nextPtrType) -        castInst = gepValue; -      else -        { -          castInst = new CastInst(gepValue, nextPtrType, "ptr2"); -          newIvec.push_back(cast<Instruction>(castInst)); -        } +    // Instruction 1: nextPtr1 = GetElementPtr lastPtr, idxVec +    // This is not needed if the index is zero. +    Value *gepValue; +    if (indexIsZero) +      gepValue = lastPtr; +    else { +      gepValue = new GetElementPtrInst(lastPtr, idxVec,"ptr1"); +      newIvec.push_back(cast<Instruction>(gepValue)); +    } -      lastPtr = castInst; +    // Instruction 2: nextPtr2 = cast nextPtr1 to nextPtrType +    // This is not needed if the two types are identical. +    Value *castInst; +    if (gepValue->getType() == nextPtrType) +      castInst = gepValue; +    else { +      castInst = new CastInst(gepValue, nextPtrType, "ptr2"); +      newIvec.push_back(cast<Instruction>(castInst));      } +       +    lastPtr = castInst; +  }    //     // Now create a new instruction to replace the original one    // -  PointerType* ptrType = cast<PointerType>(lastPtr->getType()); -  assert(ptrType); +  PointerType *ptrType = cast<PointerType>(lastPtr->getType());    // First, get the final index vector.  As above, we may need an initial [0].    vector<Value*> idxVec(1, *OI);    if (isa<StructType>(ptrType->getElementType()) -      && ! ptrType->indexValid(*OI)) -    idxVec.insert(idxVec.begin(), ConstantUInt::get(Type::UIntTy, 0)); +      && !ptrType->indexValid(*OI)) +    idxVec.insert(idxVec.begin(), Constant::getNullValue(Type::UIntTy)); -  const std::string newInstName = memI->hasName()? memI->getName() -                                                 : string("finalRef");    Instruction* newInst = NULL; -   -  switch(memI->getOpcode()) -    { -    case Instruction::Load: -      newInst = new LoadInst(lastPtr, idxVec /*, newInstName */); break; -    case Instruction::Store: -      newInst = new StoreInst(memI->getOperand(0), -                              lastPtr, idxVec /*, newInstName */); break; -      break; -    case Instruction::GetElementPtr: -      newInst = new GetElementPtrInst(lastPtr, idxVec /*, newInstName */); break; -    default: -      assert(0 && "Unrecognized memory access instruction"); break; -    } -   +  switch(memI->getOpcode()) { +  case Instruction::Load: +    newInst = new LoadInst(lastPtr, idxVec, memI->getName()); +    break; +  case Instruction::Store: +    newInst = new StoreInst(memI->getOperand(0), lastPtr, idxVec); +    break; +  case Instruction::GetElementPtr: +    newInst = new GetElementPtrInst(lastPtr, idxVec, memI->getName()); +    break; +  default: +    assert(0 && "Unrecognized memory access instruction"); +  }    newIvec.push_back(newInst);    // Replace all uses of the old instruction with the new    memI->replaceAllUsesWith(newInst); -   -  BasicBlock::iterator newI = BBI;; -  for (int i = newIvec.size()-1; i >= 0; i--) -    newI = BB->getInstList().insert(newI, newIvec[i]); -   -  // Now delete the old instruction and return a pointer to the last new one -  BB->getInstList().remove(memI); -  delete memI; -   -  return newI + newIvec.size() - 1;           // pointer to last new instr -} +  // Now delete the old instruction... +  delete memI; -//--------------------------------------------------------------------------- -// Entry point for array or  structure references with multiple indices. -//--------------------------------------------------------------------------- +  // Convert our iterator into an index... that cannot get invalidated +  unsigned ItOffs = BBI-BB->begin(); -static bool -doDecomposeMultiDimRefs(Function *F) -{ -  bool changed = false; -   -  for (Function::iterator BI = F->begin(), BE = F->end(); BI != BE; ++BI) -    for (BasicBlock::iterator newI, II = (*BI)->begin(); -         II != (*BI)->end(); II = ++newI) -      { -        newI = II; -        if (MemAccessInst *memI = dyn_cast<MemAccessInst>(*II)) -          if (memI->getNumOperands() > 1 + memI->getFirstIndexOperandNumber()) -            { -              newI = decomposeArrayRef(II); -              changed = true; -            } -      } +  // Insert all of the new instructions... +  BB->getInstList().insert(BBI, newIvec.begin(), newIvec.end()); -  return changed; -} - - -namespace { -  struct DecomposeMultiDimRefsPass : public FunctionPass { -    virtual bool runOnFunction(Function *F) { -      return doDecomposeMultiDimRefs(F); -    } - -    virtual void getAnalysisUsage(AnalysisUsage &AU) const { -      AU.preservesCFG(); -    } -  }; -} - -Pass *createDecomposeMultiDimRefsPass() { -  return new DecomposeMultiDimRefsPass(); +  // Advance the iterator to the instruction following the one just inserted... +  BBI = BB->begin() + (ItOffs+newIvec.size());  } | 

