diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -501,6 +501,17 @@ isVolatile, TBAATag, TBAAStructTag, ScopeTag, NoAliasTag); } + CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, + MaybeAlign SrcAlign, uint64_t Size, + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemCpy(Dst, DstAlign ? DstAlign->value() : 0, Src, + SrcAlign ? SrcAlign->value() : 0, getInt64(Size), + isVolatile, TBAATag, TBAAStructTag, ScopeTag, + NoAliasTag); + } CallInst *CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size, @@ -508,6 +519,16 @@ MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); + CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, + MaybeAlign SrcAlign, Value *Size, + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemCpy(Dst, DstAlign ? DstAlign->value() : 0, Src, + SrcAlign ? SrcAlign->value() : 0, Size, isVolatile, + TBAATag, TBAAStructTag, ScopeTag, NoAliasTag); + } /// Create and insert an element unordered-atomic memcpy between the /// specified pointers. @@ -1627,12 +1648,21 @@ LI->setAlignment(MaybeAlign(Align)); return LI; } + LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, + const Twine &Name = "") { + return CreateAlignedLoad(Ty, Ptr, Align ? Align->value() : 0, Name); + } LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, unsigned Align, bool isVolatile, const Twine &Name = "") { LoadInst *LI = CreateLoad(Ty, Ptr, isVolatile, Name); LI->setAlignment(MaybeAlign(Align)); return LI; } + LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, + bool isVolatile, const Twine &Name = "") { + return CreateAlignedLoad(Ty, Ptr, Align ? Align->value() : 0, isVolatile, + Name); + } // Deprecated [opaque pointer types] LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { @@ -1658,7 +1688,10 @@ SI->setAlignment(MaybeAlign(Align)); return SI; } - + StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, + bool isVolatile = false) { + return CreateAlignedStore(Val, Ptr, Align ? Align->value() : 0, isVolatile); + } FenceInst *CreateFence(AtomicOrdering Ordering, SyncScope::ID SSID = SyncScope::System, const Twine &Name = "") { diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -363,6 +363,9 @@ addParamAttr(ARG_DEST, Attribute::getWithAlignment(getContext(), Align(Alignment))); } + void setDestAlignment(MaybeAlign Align) { + setDestAlignment(Align ? Align->value() : 0); + } void setLength(Value *L) { assert(getLength()->getType() == L->getType() && @@ -413,6 +416,9 @@ Attribute::getWithAlignment(BaseCL::getContext(), Align(Alignment))); } + void setSourceAlignment(MaybeAlign Align) { + setSourceAlignment(Align ? Align->value() : 0); + } }; /// Common base class for all memset intrinsics. Simply provides diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -2429,13 +2429,14 @@ /// /// You can optionally pass a type to this routine and if that type's ABI /// alignment is itself suitable, this will return zero. - unsigned getSliceAlign(Type *Ty = nullptr) { - unsigned NewAIAlign = NewAI.getAlignment(); - if (!NewAIAlign) - NewAIAlign = DL.getABITypeAlignment(NewAI.getAllocatedType()); - unsigned Align = - MinAlign(NewAIAlign, NewBeginOffset - NewAllocaBeginOffset); - return (Ty && Align == DL.getABITypeAlignment(Ty)) ? 0 : Align; + MaybeAlign getSliceAlign(Type *Ty = nullptr) { + const MaybeAlign NewAIAlign = DL.getValueOrABITypeAlignment( + MaybeAlign(NewAI.getAlignment()), NewAI.getAllocatedType()); + const MaybeAlign Align = + commonAlignment(NewAIAlign, NewBeginOffset - NewAllocaBeginOffset); + return (Ty && Align && Align->value() == DL.getABITypeAlignment(Ty)) + ? None + : Align; } unsigned getIndex(uint64_t Offset) { @@ -2883,7 +2884,7 @@ assert((IsDest && II.getRawDest() == OldPtr) || (!IsDest && II.getRawSource() == OldPtr)); - unsigned SliceAlign = getSliceAlign(); + MaybeAlign SliceAlign = getSliceAlign(); // For unsplit intrinsics, we simply modify the source and destination // pointers in place. This isn't just an optimization, it is a matter of @@ -2953,10 +2954,10 @@ // Compute the relative offset for the other pointer within the transfer. unsigned OffsetWidth = DL.getIndexSizeInBits(OtherAS); APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset); - unsigned OtherAlign = - IsDest ? II.getSourceAlignment() : II.getDestAlignment(); - OtherAlign = MinAlign(OtherAlign ? OtherAlign : 1, - OtherOffset.zextOrTrunc(64).getZExtValue()); + Align OtherAlign = + assumeAligned(IsDest ? II.getSourceAlignment() : II.getDestAlignment()); + OtherAlign = + commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue()); if (EmitMemCpy) { // Compute the other pointer, folding as much as possible to produce @@ -2969,7 +2970,7 @@ Constant *Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset); Value *DestPtr, *SrcPtr; - unsigned DestAlign, SrcAlign; + MaybeAlign DestAlign, SrcAlign; // Note: IsDest is true iff we're copying into the new alloca slice if (IsDest) { DestPtr = OurPtr; @@ -3016,9 +3017,9 @@ Value *SrcPtr = getAdjustedPtr(IRB, DL, OtherPtr, OtherOffset, OtherPtrTy, OtherPtr->getName() + "."); - unsigned SrcAlign = OtherAlign; + MaybeAlign SrcAlign = OtherAlign; Value *DstPtr = &NewAI; - unsigned DstAlign = SliceAlign; + MaybeAlign DstAlign = SliceAlign; if (!IsDest) { std::swap(SrcPtr, DstPtr); std::swap(SrcAlign, DstAlign); @@ -3114,20 +3115,17 @@ Instruction *I = Uses.pop_back_val(); if (LoadInst *LI = dyn_cast(I)) { - unsigned LoadAlign = LI->getAlignment(); - if (!LoadAlign) - LoadAlign = DL.getABITypeAlignment(LI->getType()); - LI->setAlignment(MaybeAlign(std::min(LoadAlign, getSliceAlign()))); + MaybeAlign LoadAlign = DL.getValueOrABITypeAlignment( + MaybeAlign(LI->getAlignment()), LI->getType()); + LI->setAlignment(std::min(LoadAlign, getSliceAlign())); continue; } if (StoreInst *SI = dyn_cast(I)) { - unsigned StoreAlign = SI->getAlignment(); - if (!StoreAlign) { Value *Op = SI->getOperand(0); - StoreAlign = DL.getABITypeAlignment(Op->getType()); - } - SI->setAlignment(MaybeAlign(std::min(StoreAlign, getSliceAlign()))); - continue; + MaybeAlign StoreAlign = DL.getValueOrABITypeAlignment( + MaybeAlign(SI->getAlignment()), Op->getType()); + SI->setAlignment(std::min(StoreAlign, getSliceAlign())); + continue; } assert(isa(I) || isa(I) ||