diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 340fe61aa84d0e..75ffb4016674dd 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -771,14 +771,16 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock, UnwindDest->removePredecessor(InvokeBB); } -/// When inlining a call site that has !llvm.mem.parallel_loop_access or -/// llvm.access.group metadata, that metadata should be propagated to all -/// memory-accessing cloned instructions. -static void PropagateParallelLoopAccessMetadata(CallBase &CB, - ValueToValueMapTy &VMap) { - MDNode *M = CB.getMetadata(LLVMContext::MD_mem_parallel_loop_access); - MDNode *CallAccessGroup = CB.getMetadata(LLVMContext::MD_access_group); - if (!M && !CallAccessGroup) +/// When inlining a call site that has !llvm.mem.parallel_loop_access, +/// !llvm.access.group, !alias.scope or !noalias metadata, that metadata should +/// be propagated to all memory-accessing cloned instructions. +static void PropagateCallSiteMetadata(CallBase &CB, ValueToValueMapTy &VMap) { + MDNode *MemParallelLoopAccess = + CB.getMetadata(LLVMContext::MD_mem_parallel_loop_access); + MDNode *AccessGroup = CB.getMetadata(LLVMContext::MD_access_group); + MDNode *AliasScope = CB.getMetadata(LLVMContext::MD_alias_scope); + MDNode *NoAlias = CB.getMetadata(LLVMContext::MD_noalias); + if (!MemParallelLoopAccess && !AccessGroup && !AliasScope && !NoAlias) return; for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE = VMap.end(); @@ -790,21 +792,30 @@ static void PropagateParallelLoopAccessMetadata(CallBase &CB, if (!NI) continue; - if (M) { - if (MDNode *PM = - NI->getMetadata(LLVMContext::MD_mem_parallel_loop_access)) { - M = MDNode::concatenate(PM, M); - NI->setMetadata(LLVMContext::MD_mem_parallel_loop_access, M); - } else if (NI->mayReadOrWriteMemory()) { - NI->setMetadata(LLVMContext::MD_mem_parallel_loop_access, M); - } - } + // This metadata is only relevant for instructions that access memory. + if (!NI->mayReadOrWriteMemory()) + continue; - if (NI->mayReadOrWriteMemory()) { - MDNode *UnitedAccGroups = uniteAccessGroups( - NI->getMetadata(LLVMContext::MD_access_group), CallAccessGroup); - NI->setMetadata(LLVMContext::MD_access_group, UnitedAccGroups); + if (MemParallelLoopAccess) { + // TODO: This probably should not overwrite MemParalleLoopAccess. + MemParallelLoopAccess = MDNode::concatenate( + NI->getMetadata(LLVMContext::MD_mem_parallel_loop_access), + MemParallelLoopAccess); + NI->setMetadata(LLVMContext::MD_mem_parallel_loop_access, + MemParallelLoopAccess); } + + if (AccessGroup) + NI->setMetadata(LLVMContext::MD_access_group, uniteAccessGroups( + NI->getMetadata(LLVMContext::MD_access_group), AccessGroup)); + + if (AliasScope) + NI->setMetadata(LLVMContext::MD_alias_scope, MDNode::concatenate( + NI->getMetadata(LLVMContext::MD_alias_scope), AliasScope)); + + if (NoAlias) + NI->setMetadata(LLVMContext::MD_noalias, MDNode::concatenate( + NI->getMetadata(LLVMContext::MD_noalias), NoAlias)); } } @@ -886,31 +897,11 @@ static void CloneAliasScopeMetadata(CallBase &CB, ValueToValueMapTy &VMap) { if (!NI) continue; - if (MDNode *M = NI->getMetadata(LLVMContext::MD_alias_scope)) { - MDNode *NewMD = MDMap[M]; - // If the call site also had alias scope metadata (a list of scopes to - // which instructions inside it might belong), propagate those scopes to - // the inlined instructions. - if (MDNode *CSM = CB.getMetadata(LLVMContext::MD_alias_scope)) - NewMD = MDNode::concatenate(NewMD, CSM); - NI->setMetadata(LLVMContext::MD_alias_scope, NewMD); - } else if (NI->mayReadOrWriteMemory()) { - if (MDNode *M = CB.getMetadata(LLVMContext::MD_alias_scope)) - NI->setMetadata(LLVMContext::MD_alias_scope, M); - } + if (MDNode *M = NI->getMetadata(LLVMContext::MD_alias_scope)) + NI->setMetadata(LLVMContext::MD_alias_scope, MDMap[M]); - if (MDNode *M = NI->getMetadata(LLVMContext::MD_noalias)) { - MDNode *NewMD = MDMap[M]; - // If the call site also had noalias metadata (a list of scopes with - // which instructions inside it don't alias), propagate those scopes to - // the inlined instructions. - if (MDNode *CSM = CB.getMetadata(LLVMContext::MD_noalias)) - NewMD = MDNode::concatenate(NewMD, CSM); - NI->setMetadata(LLVMContext::MD_noalias, NewMD); - } else if (NI->mayReadOrWriteMemory()) { - if (MDNode *M = CB.getMetadata(LLVMContext::MD_noalias)) - NI->setMetadata(LLVMContext::MD_noalias, M); - } + if (MDNode *M = NI->getMetadata(LLVMContext::MD_noalias)) + NI->setMetadata(LLVMContext::MD_noalias, MDMap[M]); } } @@ -1911,8 +1902,8 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, // function which feed into its return value. AddReturnAttributes(CB, VMap); - // Propagate llvm.mem.parallel_loop_access if necessary. - PropagateParallelLoopAccessMetadata(CB, VMap); + // Propagate metadata on the callsite if necessary. + PropagateCallSiteMetadata(CB, VMap); // Register any cloned assumptions. if (IFI.GetAssumptionCache) diff --git a/llvm/test/Transforms/Inline/noalias-cs.ll b/llvm/test/Transforms/Inline/noalias-cs.ll index 20fffac24c47df..7c09bfb3a65bea 100644 --- a/llvm/test/Transforms/Inline/noalias-cs.ll +++ b/llvm/test/Transforms/Inline/noalias-cs.ll @@ -50,22 +50,22 @@ define void @caller(float* nocapture %a, float* nocapture %b, float* nocapture r ; CHECK-NEXT: [[TMP3:%.*]] = load float, float* [[A]], align 4, !alias.scope !16 ; CHECK-NEXT: [[ARRAYIDX_I9:%.*]] = getelementptr inbounds float, float* [[B]], i64 7 ; CHECK-NEXT: store float [[TMP3]], float* [[ARRAYIDX_I9]], align 4, !alias.scope !16 -; CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[C]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load float, float* [[C]], align 4, !noalias !16 ; CHECK-NEXT: [[ARRAYIDX_I_I4:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 -; CHECK-NEXT: store float [[TMP4]], float* [[ARRAYIDX_I_I4]], align 4 +; CHECK-NEXT: store float [[TMP4]], float* [[ARRAYIDX_I_I4]], align 4, !noalias !16 ; CHECK-NEXT: [[ARRAYIDX1_I_I5:%.*]] = getelementptr inbounds float, float* [[B]], i64 8 -; CHECK-NEXT: store float [[TMP4]], float* [[ARRAYIDX1_I_I5]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[C]], align 4 +; CHECK-NEXT: store float [[TMP4]], float* [[ARRAYIDX1_I_I5]], align 4, !noalias !16 +; CHECK-NEXT: [[TMP5:%.*]] = load float, float* [[C]], align 4, !noalias !16 ; CHECK-NEXT: [[ARRAYIDX_I6:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 -; CHECK-NEXT: store float [[TMP5]], float* [[ARRAYIDX_I6]], align 4 -; CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[A]], align 4 +; CHECK-NEXT: store float [[TMP5]], float* [[ARRAYIDX_I6]], align 4, !noalias !16 +; CHECK-NEXT: [[TMP6:%.*]] = load float, float* [[A]], align 4, !alias.scope !16 ; CHECK-NEXT: [[ARRAYIDX_I_I1:%.*]] = getelementptr inbounds float, float* [[B]], i64 5 -; CHECK-NEXT: store float [[TMP6]], float* [[ARRAYIDX_I_I1]], align 4 +; CHECK-NEXT: store float [[TMP6]], float* [[ARRAYIDX_I_I1]], align 4, !alias.scope !16 ; CHECK-NEXT: [[ARRAYIDX1_I_I2:%.*]] = getelementptr inbounds float, float* [[B]], i64 8 -; CHECK-NEXT: store float [[TMP6]], float* [[ARRAYIDX1_I_I2]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[A]], align 4 +; CHECK-NEXT: store float [[TMP6]], float* [[ARRAYIDX1_I_I2]], align 4, !alias.scope !16 +; CHECK-NEXT: [[TMP7:%.*]] = load float, float* [[A]], align 4, !alias.scope !16 ; CHECK-NEXT: [[ARRAYIDX_I3:%.*]] = getelementptr inbounds float, float* [[B]], i64 7 -; CHECK-NEXT: store float [[TMP7]], float* [[ARRAYIDX_I3]], align 4 +; CHECK-NEXT: store float [[TMP7]], float* [[ARRAYIDX_I3]], align 4, !alias.scope !16 ; CHECK-NEXT: ret void ; entry: