diff options
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index bd85b4a..9ba0512 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3788,9 +3788,6 @@ Instruction *InstCombiner::PromoteCastOfAllocation(CastInst &CI, } } - // Finally, if the instruction now has one use, delete it. - if (!AI.hasOneUse()) return 0; - // Get the type really allocated and the type casted to. const Type *AllocElTy = AI.getAllocatedType(); const Type *CastElTy = PTy->getElementType(); @@ -3800,6 +3797,11 @@ Instruction *InstCombiner::PromoteCastOfAllocation(CastInst &CI, unsigned CastElTyAlign = TD->getTypeSize(CastElTy); if (CastElTyAlign < AllocElTyAlign) return 0; + // If the allocation has multiple uses, only promote it if we are strictly + // increasing the alignment of the resultant allocation. If we keep it the + // same, we open the door to infinite loops of various kinds. + if (!AI.hasOneUse() && CastElTyAlign == AllocElTyAlign) return 0; + uint64_t AllocElTySize = TD->getTypeSize(AllocElTy); uint64_t CastElTySize = TD->getTypeSize(CastElTy); @@ -3815,6 +3817,16 @@ Instruction *InstCombiner::PromoteCastOfAllocation(CastInst &CI, else New = new AllocaInst(CastElTy, Amt, Name); InsertNewInstBefore(New, AI); + + // If the allocation has multiple uses, insert a cast and change all things + // that used it to use the new cast. This will also hack on CI, but it will + // die soon. + if (!AI.hasOneUse()) { + AddUsesToWorkList(AI); + CastInst *NewCast = new CastInst(New, AI.getType(), "tmpcast"); + InsertNewInstBefore(NewCast, AI); + AI.replaceAllUsesWith(NewCast); + } return ReplaceInstUsesWith(CI, New); } |