Expand IRBuilder interface for atomic memcpy to require pointer alignments. (NFC)

Summary:
 The specification of the @llvm.memcpy.element.unordered.atomic intrinsic requires
that the pointer arguments have alignments of at least the element size. The existing
IRBuilder interface to create a call to this intrinsic does not allow for providing
the alignment of these pointer args. Having an interface that makes it easy to
construct invalid intrinsic calls doesn't seem sensible, so this patch simply
adds the requirement that one provide the argument alignments when using IRBuilder
to create atomic memcpy calls.

llvm-svn: 317918
This commit is contained in:
Daniel Neilson 2017-11-10 19:38:12 +00:00
parent bfd6c1c016
commit 6e4aa1e481
3 changed files with 28 additions and 19 deletions

View File

@ -438,22 +438,26 @@ public:
/// \brief Create and insert an element unordered-atomic memcpy between the
/// specified pointers.
///
/// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
/// specified, it will be added to the instruction. Likewise with alias.scope
/// and noalias tags.
CallInst *CreateElementUnorderedAtomicMemCpy(
Value *Dst, Value *Src, uint64_t Size, uint32_t ElementSize,
MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr) {
Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
uint64_t Size, uint32_t ElementSize, MDNode *TBAATag = nullptr,
MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr) {
return CreateElementUnorderedAtomicMemCpy(
Dst, Src, getInt64(Size), ElementSize, TBAATag, TBAAStructTag, ScopeTag,
NoAliasTag);
Dst, DstAlign, Src, SrcAlign, getInt64(Size), ElementSize, TBAATag,
TBAAStructTag, ScopeTag, NoAliasTag);
}
CallInst *CreateElementUnorderedAtomicMemCpy(
Value *Dst, Value *Src, Value *Size, uint32_t ElementSize,
MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size,
uint32_t ElementSize, MDNode *TBAATag = nullptr,
MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memmove between the specified
/// pointers.

View File

@ -135,8 +135,13 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
}
CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
Value *Dst, Value *Src, Value *Size, uint32_t ElementSize, MDNode *TBAATag,
MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {
Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size,
uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag,
MDNode *ScopeTag, MDNode *NoAliasTag) {
assert(DstAlign >= ElementSize &&
"Pointer alignment must be at least element size");
assert(SrcAlign >= ElementSize &&
"Pointer alignment must be at least element size");
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
@ -148,6 +153,10 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
CallInst *CI = createCallHelper(TheFn, Ops, this);
// Set the alignment of the pointer args.
CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign));
CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign));
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);

View File

@ -1063,16 +1063,12 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
if (StoreSize > TTI->getAtomicMemIntrinsicMaxElementSize())
return false;
// Create the call.
// Note that unordered atomic loads/stores are *required* by the spec to
// have an alignment but non-atomic loads/stores may not.
NewCall = Builder.CreateElementUnorderedAtomicMemCpy(
StoreBasePtr, LoadBasePtr, NumBytes, StoreSize);
// Propagate alignment info onto the pointer args. Note that unordered
// atomic loads/stores are *required* by the spec to have an alignment
// but non-atomic loads/stores may not.
NewCall->addParamAttr(0, Attribute::getWithAlignment(NewCall->getContext(),
SI->getAlignment()));
NewCall->addParamAttr(1, Attribute::getWithAlignment(NewCall->getContext(),
LI->getAlignment()));
StoreBasePtr, SI->getAlignment(), LoadBasePtr, LI->getAlignment(),
NumBytes, StoreSize);
}
NewCall->setDebugLoc(SI->getDebugLoc());