From e1e7862f6e671b60e83476a09b9a1a27aceecfb9 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Thu, 14 Aug 2014 21:09:37 +0000 Subject: [PATCH] Copy noalias metadata from call sites to inlined instructions When a call site with noalias metadata is inlined, that metadata can be propagated directly to the inlined instructions (only those that might access memory because it is not useful on the others). Prior to inlining, the noalias metadata could express that a call would not alias with some other memory access, which implies that no instruction within that called function would alias. By propagating the metadata to the inlined instructions, we preserve that knowledge. This should complete the enhancements requested in PR20500. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215676 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/InlineFunction.cpp | 32 ++++++++-- test/Transforms/Inline/noalias-cs.ll | 84 +++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/Inline/noalias-cs.ll diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index f6289b5c891..a3535cb47cc 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -356,11 +356,35 @@ static void CloneAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap) { if (!NI) continue; - if (MDNode *M = NI->getMetadata(LLVMContext::MD_alias_scope)) - NI->setMetadata(LLVMContext::MD_alias_scope, MDMap[M]); + 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 = + CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope)) + NewMD = MDNode::concatenate(NewMD, CSM); + NI->setMetadata(LLVMContext::MD_alias_scope, NewMD); + } else if (NI->mayReadOrWriteMemory()) { + if (MDNode *M = + CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope)) + NI->setMetadata(LLVMContext::MD_alias_scope, M); + } - if (MDNode *M = NI->getMetadata(LLVMContext::MD_noalias)) - NI->setMetadata(LLVMContext::MD_noalias, 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 = + CS.getInstruction()->getMetadata(LLVMContext::MD_noalias)) + NewMD = MDNode::concatenate(NewMD, CSM); + NI->setMetadata(LLVMContext::MD_noalias, NewMD); + } else if (NI->mayReadOrWriteMemory()) { + if (MDNode *M = + CS.getInstruction()->getMetadata(LLVMContext::MD_noalias)) + NI->setMetadata(LLVMContext::MD_noalias, M); + } } // Now that everything has been replaced, delete the dummy nodes. diff --git a/test/Transforms/Inline/noalias-cs.ll b/test/Transforms/Inline/noalias-cs.ll new file mode 100644 index 00000000000..acd90214bc9 --- /dev/null +++ b/test/Transforms/Inline/noalias-cs.ll @@ -0,0 +1,84 @@ +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind uwtable +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4, !noalias !3 + %arrayidx.i = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx.i, align 4, !alias.scope !7, !noalias !8 + %arrayidx1.i = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1.i, align 4, !alias.scope !8, !noalias !7 + %1 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %1, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + call void @foo2(float* %a, float* %b, float* %c), !noalias !0 + call void @foo2(float* %b, float* %b, float* %a), !alias.scope !0 + ret void +} + +; CHECK: define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !noalias !6 +; CHECK: %arrayidx.i.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !12, !noalias !13 +; CHECK: %arrayidx1.i.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %0, float* %arrayidx1.i.i, align 4, !alias.scope !14, !noalias !15 +; CHECK: %1 = load float* %c, align 4, !noalias !16 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx.i, align 4, !noalias !16 +; CHECK: %2 = load float* %a, align 4, !alias.scope !16, !noalias !17 +; CHECK: %arrayidx.i.i1 = getelementptr inbounds float* %b, i64 5 +; CHECK: store float %2, float* %arrayidx.i.i1, align 4, !alias.scope !21, !noalias !22 +; CHECK: %arrayidx1.i.i2 = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %2, float* %arrayidx1.i.i2, align 4, !alias.scope !23, !noalias !24 +; CHECK: %3 = load float* %a, align 4, !alias.scope !16 +; CHECK: %arrayidx.i3 = getelementptr inbounds float* %b, i64 7 +; CHECK: store float %3, float* %arrayidx.i3, align 4, !alias.scope !16 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind uwtable } + +!0 = metadata !{metadata !1} +!1 = metadata !{metadata !1, metadata !2, metadata !"hello: %a"} +!2 = metadata !{metadata !2, metadata !"hello"} +!3 = metadata !{metadata !4, metadata !6} +!4 = metadata !{metadata !4, metadata !5, metadata !"hello2: %a"} +!5 = metadata !{metadata !5, metadata !"hello2"} +!6 = metadata !{metadata !6, metadata !5, metadata !"hello2: %b"} +!7 = metadata !{metadata !4} +!8 = metadata !{metadata !6} + +; CHECK: !0 = metadata !{metadata !1, metadata !3} +; CHECK: !1 = metadata !{metadata !1, metadata !2, metadata !"hello2: %a"} +; CHECK: !2 = metadata !{metadata !2, metadata !"hello2"} +; CHECK: !3 = metadata !{metadata !3, metadata !2, metadata !"hello2: %b"} +; CHECK: !4 = metadata !{metadata !1} +; CHECK: !5 = metadata !{metadata !3} +; CHECK: !6 = metadata !{metadata !7, metadata !9, metadata !10} +; CHECK: !7 = metadata !{metadata !7, metadata !8, metadata !"hello2: %a"} +; CHECK: !8 = metadata !{metadata !8, metadata !"hello2"} +; CHECK: !9 = metadata !{metadata !9, metadata !8, metadata !"hello2: %b"} +; CHECK: !10 = metadata !{metadata !10, metadata !11, metadata !"hello: %a"} +; CHECK: !11 = metadata !{metadata !11, metadata !"hello"} +; CHECK: !12 = metadata !{metadata !7} +; CHECK: !13 = metadata !{metadata !9, metadata !10} +; CHECK: !14 = metadata !{metadata !9} +; CHECK: !15 = metadata !{metadata !7, metadata !10} +; CHECK: !16 = metadata !{metadata !10} +; CHECK: !17 = metadata !{metadata !18, metadata !20} +; CHECK: !18 = metadata !{metadata !18, metadata !19, metadata !"hello2: %a"} +; CHECK: !19 = metadata !{metadata !19, metadata !"hello2"} +; CHECK: !20 = metadata !{metadata !20, metadata !19, metadata !"hello2: %b"} +; CHECK: !21 = metadata !{metadata !18, metadata !10} +; CHECK: !22 = metadata !{metadata !20} +; CHECK: !23 = metadata !{metadata !20, metadata !10} +; CHECK: !24 = metadata !{metadata !18} +