diff options
-rw-r--r-- | lib/Transforms/Scalar/SROA.cpp | 152 |
1 files changed, 84 insertions, 68 deletions
diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index 929f1b5c07a..377a6250de9 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -2208,6 +2208,48 @@ static bool isIntegerWideningViable(const DataLayout &TD, return WholeAllocaOp; } +static Value *extractInteger(const DataLayout &DL, IRBuilder<> &IRB, Value *V, + IntegerType *Ty, uint64_t Offset, + const Twine &Name) { + IntegerType *IntTy = cast<IntegerType>(V->getType()); + assert(DL.getTypeStoreSize(Ty) + Offset <= DL.getTypeStoreSize(IntTy) && + "Element extends past full value"); + uint64_t ShAmt = 8*Offset; + if (DL.isBigEndian()) + ShAmt = 8*(DL.getTypeStoreSize(IntTy) - DL.getTypeStoreSize(Ty) - Offset); + if (ShAmt) + V = IRB.CreateLShr(V, ShAmt, Name + ".shift"); + assert(Ty->getBitWidth() <= IntTy->getBitWidth() && + "Cannot extract to a larger integer!"); + if (Ty != IntTy) + V = IRB.CreateTrunc(V, Ty, Name + ".trunc"); + return V; +} + +static Value *insertInteger(const DataLayout &DL, IRBuilder<> &IRB, Value *Old, + Value *V, uint64_t Offset, const Twine &Name) { + IntegerType *IntTy = cast<IntegerType>(Old->getType()); + IntegerType *Ty = cast<IntegerType>(V->getType()); + assert(Ty->getBitWidth() <= IntTy->getBitWidth() && + "Cannot insert a larger integer!"); + if (Ty != IntTy) + V = IRB.CreateZExt(V, IntTy, Name + ".ext"); + assert(DL.getTypeStoreSize(Ty) + Offset <= DL.getTypeStoreSize(IntTy) && + "Element store outside of alloca store"); + uint64_t ShAmt = 8*Offset; + if (DL.isBigEndian()) + ShAmt = 8*(DL.getTypeStoreSize(IntTy) - DL.getTypeStoreSize(Ty) - Offset); + if (ShAmt) + V = IRB.CreateShl(V, ShAmt, Name + ".shift"); + + if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) { + APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt); + Old = IRB.CreateAnd(Old, Mask, Name + ".mask"); + V = IRB.CreateOr(Old, V, Name + ".insert"); + } + return V; +} + namespace { /// \brief Visitor to rewrite instructions using a partition of an alloca to /// use a new alloca. @@ -2368,60 +2410,6 @@ private: return IRB.getInt32(Index); } - Value *extractInteger(IRBuilder<> &IRB, IntegerType *TargetTy, - uint64_t Offset) { - assert(IntTy && "We cannot extract an integer from the alloca"); - Value *V = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), - getName(".load")); - V = convertValue(TD, IRB, V, IntTy); - assert(Offset >= NewAllocaBeginOffset && "Out of bounds offset"); - uint64_t RelOffset = Offset - NewAllocaBeginOffset; - assert(TD.getTypeStoreSize(TargetTy) + RelOffset <= - TD.getTypeStoreSize(IntTy) && - "Element load outside of alloca store"); - uint64_t ShAmt = 8*RelOffset; - if (TD.isBigEndian()) - ShAmt = 8*(TD.getTypeStoreSize(IntTy) - - TD.getTypeStoreSize(TargetTy) - RelOffset); - if (ShAmt) - V = IRB.CreateLShr(V, ShAmt, getName(".shift")); - assert(TargetTy->getBitWidth() <= IntTy->getBitWidth() && - "Cannot extract to a larger integer!"); - if (TargetTy != IntTy) - V = IRB.CreateTrunc(V, TargetTy, getName(".trunc")); - return V; - } - - StoreInst *insertInteger(IRBuilder<> &IRB, Value *V, uint64_t Offset) { - IntegerType *Ty = cast<IntegerType>(V->getType()); - assert(Ty->getBitWidth() <= IntTy->getBitWidth() && - "Cannot insert a larger integer!"); - if (Ty != IntTy) - V = IRB.CreateZExt(V, IntTy, getName(".ext")); - assert(Offset >= NewAllocaBeginOffset && "Out of bounds offset"); - uint64_t RelOffset = Offset - NewAllocaBeginOffset; - assert(TD.getTypeStoreSize(Ty) + RelOffset <= - TD.getTypeStoreSize(IntTy) && - "Element store outside of alloca store"); - uint64_t ShAmt = 8*RelOffset; - if (TD.isBigEndian()) - ShAmt = 8*(TD.getTypeStoreSize(IntTy) - TD.getTypeStoreSize(Ty) - - RelOffset); - if (ShAmt) - V = IRB.CreateShl(V, ShAmt, getName(".shift")); - - if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) { - APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt); - Value *Old = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), - getName(".oldload")); - Old = convertValue(TD, IRB, Old, IntTy); - Old = IRB.CreateAnd(Old, Mask, getName(".mask")); - V = IRB.CreateOr(Old, V, getName(".insert")); - } - V = convertValue(TD, IRB, V, NewAllocaTy); - return IRB.CreateAlignedStore(V, &NewAI, NewAI.getAlignment()); - } - void deleteIfTriviallyDead(Value *V) { Instruction *I = cast<Instruction>(V); if (isInstructionTriviallyDead(I)) @@ -2449,12 +2437,18 @@ private: } bool rewriteIntegerLoad(IRBuilder<> &IRB, LoadInst &LI) { + assert(IntTy && "We cannot insert an integer to the alloca"); assert(!LI.isVolatile()); - Value *Result = extractInteger(IRB, cast<IntegerType>(LI.getType()), - BeginOffset); - LI.replaceAllUsesWith(Result); + Value *V = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), + getName(".load")); + V = convertValue(TD, IRB, V, IntTy); + assert(BeginOffset >= NewAllocaBeginOffset && "Out of bounds offset"); + uint64_t Offset = BeginOffset - NewAllocaBeginOffset; + V = extractInteger(TD, IRB, V, cast<IntegerType>(LI.getType()), Offset, + getName(".extract")); + LI.replaceAllUsesWith(V); Pass.DeadInsts.push_back(&LI); - DEBUG(dbgs() << " to: " << *Result << "\n"); + DEBUG(dbgs() << " to: " << *V << "\n"); return true; } @@ -2516,8 +2510,20 @@ private: } bool rewriteIntegerStore(IRBuilder<> &IRB, StoreInst &SI) { + assert(IntTy && "We cannot extract an integer from the alloca"); assert(!SI.isVolatile()); - StoreInst *Store = insertInteger(IRB, SI.getValueOperand(), BeginOffset); + Value *V = SI.getValueOperand(); + if (TD.getTypeSizeInBits(V->getType()) != IntTy->getBitWidth()) { + Value *Old = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), + getName(".oldload")); + Old = convertValue(TD, IRB, Old, IntTy); + assert(BeginOffset >= NewAllocaBeginOffset && "Out of bounds offset"); + uint64_t Offset = BeginOffset - NewAllocaBeginOffset; + V = insertInteger(TD, IRB, Old, SI.getValueOperand(), Offset, + getName(".insert")); + } + V = convertValue(TD, IRB, V, NewAllocaTy); + StoreInst *Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.getAlignment()); Pass.DeadInsts.push_back(&SI); (void)Store; DEBUG(dbgs() << " to: " << *Store << "\n"); @@ -2649,10 +2655,12 @@ private: if (IntTy && (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)) { assert(!II.isVolatile()); - StoreInst *Store = insertInteger(IRB, V, BeginOffset); - (void)Store; - DEBUG(dbgs() << " to: " << *Store << "\n"); - return true; + Value *Old = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), + getName(".oldload")); + Old = convertValue(TD, IRB, Old, IntTy); + assert(BeginOffset >= NewAllocaBeginOffset && "Out of bounds offset"); + uint64_t Offset = BeginOffset - NewAllocaBeginOffset; + V = insertInteger(TD, IRB, Old, V, Offset, getName(".insert")); } if (V->getType() != AllocaTy) @@ -2808,17 +2816,25 @@ private: getIndex(IRB, BeginOffset), getName(".copyextract")); } else if (IntTy && !IsWholeAlloca && !IsDest) { - Src = extractInteger(IRB, SubIntTy, BeginOffset); + Src = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), + getName(".load")); + Src = convertValue(TD, IRB, Src, IntTy); + assert(BeginOffset >= NewAllocaBeginOffset && "Out of bounds offset"); + uint64_t Offset = BeginOffset - NewAllocaBeginOffset; + Src = extractInteger(TD, IRB, Src, SubIntTy, Offset, getName(".extract")); } else { Src = IRB.CreateAlignedLoad(SrcPtr, Align, II.isVolatile(), getName(".copyload")); } if (IntTy && !IsWholeAlloca && IsDest) { - StoreInst *Store = insertInteger(IRB, Src, BeginOffset); - (void)Store; - DEBUG(dbgs() << " to: " << *Store << "\n"); - return true; + Value *Old = IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), + getName(".oldload")); + Old = convertValue(TD, IRB, Old, IntTy); + assert(BeginOffset >= NewAllocaBeginOffset && "Out of bounds offset"); + uint64_t Offset = BeginOffset - NewAllocaBeginOffset; + Src = insertInteger(TD, IRB, Old, Src, Offset, getName(".insert")); + Src = convertValue(TD, IRB, Src, NewAllocaTy); } if (IsVectorElement && IsDest) { |