Skip to content

Commit 4eb7b15

Browse files
nikictstellar
authored andcommitted
[Inliner] Fix noalias metadata handling for instructions simplified during cloning (PR50270)
Instead of using VMap, which may include instructions from the caller as a result of simplification, iterate over the (FirstNewBlock, Caller->end()) range, which will only include new instructions. Fixes https://bugs.llvm.org/show_bug.cgi?id=50270. Differential Revision: https://reviews.llvm.org/D102110 (cherry picked from commit aa9b02a)
1 parent 4e46ff4 commit 4eb7b15

File tree

2 files changed

+117
-60
lines changed

2 files changed

+117
-60
lines changed

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 46 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,8 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
780780
/// When inlining a call site that has !llvm.mem.parallel_loop_access,
781781
/// !llvm.access.group, !alias.scope or !noalias metadata, that metadata should
782782
/// be propagated to all memory-accessing cloned instructions.
783-
static void PropagateCallSiteMetadata(CallBase &CB, ValueToValueMapTy &VMap) {
783+
static void PropagateCallSiteMetadata(CallBase &CB, Function::iterator FStart,
784+
Function::iterator FEnd) {
784785
MDNode *MemParallelLoopAccess =
785786
CB.getMetadata(LLVMContext::MD_mem_parallel_loop_access);
786787
MDNode *AccessGroup = CB.getMetadata(LLVMContext::MD_access_group);
@@ -789,41 +790,33 @@ static void PropagateCallSiteMetadata(CallBase &CB, ValueToValueMapTy &VMap) {
789790
if (!MemParallelLoopAccess && !AccessGroup && !AliasScope && !NoAlias)
790791
return;
791792

792-
for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE = VMap.end();
793-
VMI != VMIE; ++VMI) {
794-
// Check that key is an instruction, to skip the Argument mapping, which
795-
// points to an instruction in the original function, not the inlined one.
796-
if (!VMI->second || !isa<Instruction>(VMI->first))
797-
continue;
798-
799-
Instruction *NI = dyn_cast<Instruction>(VMI->second);
800-
if (!NI)
801-
continue;
802-
803-
// This metadata is only relevant for instructions that access memory.
804-
if (!NI->mayReadOrWriteMemory())
805-
continue;
793+
for (BasicBlock &BB : make_range(FStart, FEnd)) {
794+
for (Instruction &I : BB) {
795+
// This metadata is only relevant for instructions that access memory.
796+
if (!I.mayReadOrWriteMemory())
797+
continue;
806798

807-
if (MemParallelLoopAccess) {
808-
// TODO: This probably should not overwrite MemParalleLoopAccess.
809-
MemParallelLoopAccess = MDNode::concatenate(
810-
NI->getMetadata(LLVMContext::MD_mem_parallel_loop_access),
811-
MemParallelLoopAccess);
812-
NI->setMetadata(LLVMContext::MD_mem_parallel_loop_access,
799+
if (MemParallelLoopAccess) {
800+
// TODO: This probably should not overwrite MemParalleLoopAccess.
801+
MemParallelLoopAccess = MDNode::concatenate(
802+
I.getMetadata(LLVMContext::MD_mem_parallel_loop_access),
803+
MemParallelLoopAccess);
804+
I.setMetadata(LLVMContext::MD_mem_parallel_loop_access,
813805
MemParallelLoopAccess);
814-
}
806+
}
815807

816-
if (AccessGroup)
817-
NI->setMetadata(LLVMContext::MD_access_group, uniteAccessGroups(
818-
NI->getMetadata(LLVMContext::MD_access_group), AccessGroup));
808+
if (AccessGroup)
809+
I.setMetadata(LLVMContext::MD_access_group, uniteAccessGroups(
810+
I.getMetadata(LLVMContext::MD_access_group), AccessGroup));
819811

820-
if (AliasScope)
821-
NI->setMetadata(LLVMContext::MD_alias_scope, MDNode::concatenate(
822-
NI->getMetadata(LLVMContext::MD_alias_scope), AliasScope));
812+
if (AliasScope)
813+
I.setMetadata(LLVMContext::MD_alias_scope, MDNode::concatenate(
814+
I.getMetadata(LLVMContext::MD_alias_scope), AliasScope));
823815

824-
if (NoAlias)
825-
NI->setMetadata(LLVMContext::MD_noalias, MDNode::concatenate(
826-
NI->getMetadata(LLVMContext::MD_noalias), NoAlias));
816+
if (NoAlias)
817+
I.setMetadata(LLVMContext::MD_noalias, MDNode::concatenate(
818+
I.getMetadata(LLVMContext::MD_noalias), NoAlias));
819+
}
827820
}
828821
}
829822

@@ -844,9 +837,9 @@ class ScopedAliasMetadataDeepCloner {
844837
/// subsequent remap() calls.
845838
void clone();
846839

847-
/// Remap instructions in the given VMap from the original to the cloned
840+
/// Remap instructions in the given range from the original to the cloned
848841
/// metadata.
849-
void remap(ValueToValueMapTy &VMap);
842+
void remap(Function::iterator FStart, Function::iterator FEnd);
850843
};
851844

852845
ScopedAliasMetadataDeepCloner::ScopedAliasMetadataDeepCloner(
@@ -907,34 +900,27 @@ void ScopedAliasMetadataDeepCloner::clone() {
907900
}
908901
}
909902

910-
void ScopedAliasMetadataDeepCloner::remap(ValueToValueMapTy &VMap) {
903+
void ScopedAliasMetadataDeepCloner::remap(Function::iterator FStart,
904+
Function::iterator FEnd) {
911905
if (MDMap.empty())
912906
return; // Nothing to do.
913907

914-
for (auto Entry : VMap) {
915-
// Check that key is an instruction, to skip the Argument mapping, which
916-
// points to an instruction in the original function, not the inlined one.
917-
if (!Entry->second || !isa<Instruction>(Entry->first))
918-
continue;
919-
920-
Instruction *I = dyn_cast<Instruction>(Entry->second);
921-
if (!I)
922-
continue;
923-
924-
// Only update scopes when we find them in the map. If they are not, it is
925-
// because we already handled that instruction before. This is faster than
926-
// tracking which instructions we already updated.
927-
if (MDNode *M = I->getMetadata(LLVMContext::MD_alias_scope))
928-
if (MDNode *MNew = MDMap.lookup(M))
929-
I->setMetadata(LLVMContext::MD_alias_scope, MNew);
930-
931-
if (MDNode *M = I->getMetadata(LLVMContext::MD_noalias))
932-
if (MDNode *MNew = MDMap.lookup(M))
933-
I->setMetadata(LLVMContext::MD_noalias, MNew);
934-
935-
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(I))
936-
if (MDNode *MNew = MDMap.lookup(Decl->getScopeList()))
937-
Decl->setScopeList(MNew);
908+
for (BasicBlock &BB : make_range(FStart, FEnd)) {
909+
for (Instruction &I : BB) {
910+
// TODO: The null checks for the MDMap.lookup() results should no longer
911+
// be necessary.
912+
if (MDNode *M = I.getMetadata(LLVMContext::MD_alias_scope))
913+
if (MDNode *MNew = MDMap.lookup(M))
914+
I.setMetadata(LLVMContext::MD_alias_scope, MNew);
915+
916+
if (MDNode *M = I.getMetadata(LLVMContext::MD_noalias))
917+
if (MDNode *MNew = MDMap.lookup(M))
918+
I.setMetadata(LLVMContext::MD_noalias, MNew);
919+
920+
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
921+
if (MDNode *MNew = MDMap.lookup(Decl->getScopeList()))
922+
Decl->setScopeList(MNew);
923+
}
938924
}
939925
}
940926

@@ -1926,7 +1912,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
19261912

19271913
// Now clone the inlined noalias scope metadata.
19281914
SAMetadataCloner.clone();
1929-
SAMetadataCloner.remap(VMap);
1915+
SAMetadataCloner.remap(FirstNewBlock, Caller->end());
19301916

19311917
// Add noalias metadata if necessary.
19321918
AddAliasScopeMetadata(CB, VMap, DL, CalleeAAR);
@@ -1936,7 +1922,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
19361922
AddReturnAttributes(CB, VMap);
19371923

19381924
// Propagate metadata on the callsite if necessary.
1939-
PropagateCallSiteMetadata(CB, VMap);
1925+
PropagateCallSiteMetadata(CB, FirstNewBlock, Caller->end());
19401926

19411927
// Register any cloned assumptions.
19421928
if (IFI.GetAssumptionCache)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -inline < %s | FileCheck %s
3+
4+
; This tests cases where instructions in the callee are simplified to
5+
; instructions in the caller, thus making VMap contain instructions from
6+
; the caller. We should not be assigning incorrect noalias metadata in
7+
; that case.
8+
9+
declare { i64* } @opaque_callee()
10+
11+
define { i64* } @callee(i64* %x) {
12+
; CHECK-LABEL: @callee(
13+
; CHECK-NEXT: [[RES:%.*]] = insertvalue { i64* } undef, i64* [[X:%.*]], 0
14+
; CHECK-NEXT: ret { i64* } [[RES]]
15+
;
16+
%res = insertvalue { i64* } undef, i64* %x, 0
17+
ret { i64* } %res
18+
}
19+
20+
; @opaque_callee() should not receive noalias metadata here.
21+
define void @caller() {
22+
; CHECK-LABEL: @caller(
23+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !0)
24+
; CHECK-NEXT: [[S:%.*]] = call { i64* } @opaque_callee()
25+
; CHECK-NEXT: [[X:%.*]] = extractvalue { i64* } [[S]], 0
26+
; CHECK-NEXT: ret void
27+
;
28+
call void @llvm.experimental.noalias.scope.decl(metadata !0)
29+
%s = call { i64* } @opaque_callee()
30+
%x = extractvalue { i64* } %s, 0
31+
call { i64* } @callee(i64* %x), !noalias !0
32+
ret void
33+
}
34+
35+
; @opaque_callee() should no the same noalias metadata as the load from the
36+
; else branch, not as the load in the if branch.
37+
define { i64* } @self_caller(i1 %c, i64* %a) {
38+
; CHECK-LABEL: @self_caller(
39+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !0)
40+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
41+
; CHECK: if:
42+
; CHECK-NEXT: [[S:%.*]] = call { i64* } @opaque_callee(), !noalias !0
43+
; CHECK-NEXT: [[X:%.*]] = extractvalue { i64* } [[S]], 0
44+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !3)
45+
; CHECK-NEXT: [[TMP1:%.*]] = load volatile i64, i64* [[X]], align 4, !alias.scope !3
46+
; CHECK-NEXT: ret { i64* } [[S]]
47+
; CHECK: else:
48+
; CHECK-NEXT: [[R2:%.*]] = insertvalue { i64* } undef, i64* [[A:%.*]], 0
49+
; CHECK-NEXT: [[TMP2:%.*]] = load volatile i64, i64* [[A]], align 4, !alias.scope !0
50+
; CHECK-NEXT: ret { i64* } [[R2]]
51+
;
52+
call void @llvm.experimental.noalias.scope.decl(metadata !0)
53+
br i1 %c, label %if, label %else
54+
55+
if:
56+
%s = call { i64* } @opaque_callee(), !noalias !0
57+
%x = extractvalue { i64* } %s, 0
58+
%r = call { i64* } @self_caller(i1 false, i64* %x)
59+
ret { i64* } %r
60+
61+
else:
62+
%r2 = insertvalue { i64* } undef, i64* %a, 0
63+
load volatile i64, i64* %a, !alias.scope !0
64+
ret { i64* } %r2
65+
}
66+
67+
declare void @llvm.experimental.noalias.scope.decl(metadata)
68+
69+
!0 = !{!1}
70+
!1 = !{!1, !2, !"scope"}
71+
!2 = !{!2, !"domain"}

0 commit comments

Comments
 (0)