[Inliner] Consistently apply callsite noalias metadata

Previously, !noalias and !alias.scope metadata on the call site was
applied as part of CloneAliasScopeMetadata(), which short-circuits
if the callee does not use any noalias metadata itself. However,
these two things have no relation to each other.

Consistently apply !noalias and !alias.scope metadata by integrating
this into an existing function that handled !llvm.access.group and
!llvm.mem.parallel_loop_access metadata. The handling for all of
these metadata kinds essentially the same.
This commit is contained in:
Nikita Popov 2020-10-31 10:51:12 +01:00
parent 61b1446a9e
commit 27f647d117
2 changed files with 48 additions and 57 deletions

View File

@ -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 (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 (NI->mayReadOrWriteMemory()) {
MDNode *UnitedAccGroups = uniteAccessGroups(
NI->getMetadata(LLVMContext::MD_access_group), CallAccessGroup);
NI->setMetadata(LLVMContext::MD_access_group, UnitedAccGroups);
}
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)

View File

@ -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: