[llvm] r213949 - Convert noalias parameter attributes into noalias metadata during inlining

Hal Finkel hfinkel at anl.gov
Fri Jul 25 09:07:27 PDT 2014


----- Original Message -----
> From: "Hal Finkel" <hfinkel at anl.gov>
> To: llvm-commits at cs.uiuc.edu
> Sent: Friday, July 25, 2014 10:50:09 AM
> Subject: [llvm] r213949 - Convert noalias parameter attributes into noalias	metadata during inlining
> 
> Author: hfinkel
> Date: Fri Jul 25 10:50:08 2014
> New Revision: 213949
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=213949&view=rev
> Log:
> Convert noalias parameter attributes into noalias metadata during
> inlining
> 
> This functionality is currently turned off by default.
> 
> Part of the motivation for introducing scoped-noalias metadata is to
> enable the
> preservation of noalias parameter attribute information after
> inlining.
> Sometimes this can be inferred from the code in the caller after
> inlining, but
> often we simply lose valuable information.
> 
> The overall process if fairly simple:
>  1. Create a new unqiue scope domain.
>  2. For each (used) noalias parameter, create a new alias scope.
>  3. For each pointer, collect the underlying objects. Add a noalias
>  scope for
>     each noalias parameter from which we're not derived (and has not
>     been
>     captured prior to that point).
>  4. Add an alias.scope for each noalias parameter from which we might
>  be
>     derived (or has been captured before that point).
> 
> Note that the capture checks apply only if one of the underlying
> objects is not
> an identified function-local object.
> 
> Added:
>     llvm/trunk/test/Transforms/Inline/noalias.ll
>     llvm/trunk/test/Transforms/Inline/noalias2.ll
> Removed:
>     llvm/trunk/test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll

To be clear, this test should have been removed in r213948 instead. Unfortunately, an error on my part associated this removal with the wrong commit.

 -Hal

> Modified:
>     llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> 
> Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=213949&r1=213948&r2=213949&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Fri Jul 25
> 10:50:08 2014
> @@ -17,7 +17,9 @@
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/SetVector.h"
>  #include "llvm/ADT/StringExtras.h"
> +#include "llvm/Analysis/AliasAnalysis.h"
>  #include "llvm/Analysis/CallGraph.h"
> +#include "llvm/Analysis/CaptureTracking.h"
>  #include "llvm/Analysis/InstructionSimplify.h"
>  #include "llvm/Analysis/ValueTracking.h"
>  #include "llvm/IR/Attributes.h"
> @@ -27,6 +29,7 @@
>  #include "llvm/IR/DataLayout.h"
>  #include "llvm/IR/DebugInfo.h"
>  #include "llvm/IR/DerivedTypes.h"
> +#include "llvm/IR/Dominators.h"
>  #include "llvm/IR/IRBuilder.h"
>  #include "llvm/IR/Instructions.h"
>  #include "llvm/IR/IntrinsicInst.h"
> @@ -34,8 +37,15 @@
>  #include "llvm/IR/MDBuilder.h"
>  #include "llvm/IR/Module.h"
>  #include "llvm/Transforms/Utils/Local.h"
> +#include "llvm/Support/CommandLine.h"
> +#include <algorithm>
>  using namespace llvm;
>  
> +static cl::opt<bool>
> +EnableNoAliasConversion("enable-noalias-to-md-conversion",
> cl::init(false),
> +  cl::Hidden,
> +  cl::desc("Convert noalias attributes to metadata during
> inlining."));
> +
>  bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
>                            bool InsertLifetime) {
>    return InlineFunction(CallSite(CI), IFI, InsertLifetime);
> @@ -358,6 +368,167 @@ static void CloneAliasScopeMetadata(Call
>      MDNode::deleteTemporary(DummyNodes[i]);
>  }
>  
> +/// AddAliasScopeMetadata - If the inlined function has noalias
> arguments, then
> +/// add new alias scopes for each noalias argument, tag the mapped
> noalias
> +/// parameters with noalias metadata specifying the new scope, and
> tag all
> +/// non-derived loads, stores and memory intrinsics with the new
> alias scopes.
> +static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy
> &VMap,
> +                                  const DataLayout *DL) {
> +  if (!EnableNoAliasConversion)
> +    return;
> +
> +  const Function *CalledFunc = CS.getCalledFunction();
> +  SmallVector<const Argument *, 4> NoAliasArgs;
> +
> +  for (Function::const_arg_iterator I = CalledFunc->arg_begin(),
> +       E = CalledFunc->arg_end(); I != E; ++I) {
> +    if (I->hasNoAliasAttr() && !I->hasNUses(0))
> +      NoAliasArgs.push_back(I);
> +  }
> +
> +  if (NoAliasArgs.empty())
> +    return;
> +
> +  // To do a good job, if a noalias variable is captured, we need to
> know if
> +  // the capture point dominates the particular use we're
> considering.
> +  DominatorTree DT;
> +  DT.recalculate(const_cast<Function&>(*CalledFunc));
> +
> +  // noalias indicates that pointer values based on the argument do
> not alias
> +  // pointer values which are not based on it. So we add a new
> "scope" for each
> +  // noalias function argument. Accesses using pointers based on
> that argument
> +  // become part of that alias scope, accesses using pointers not
> based on that
> +  // argument are tagged as noalias with that scope.
> +
> +  DenseMap<const Argument *, MDNode *> NewScopes;
> +  MDBuilder MDB(CalledFunc->getContext());
> +
> +  // Create a new scope domain for this function.
> +  MDNode *NewDomain =
> +    MDB.createAnonymousAliasScopeDomain(CalledFunc->getName());
> +  for (unsigned i = 0, e = NoAliasArgs.size(); i != e; ++i) {
> +    const Argument *A = NoAliasArgs[i];
> +
> +    std::string Name = CalledFunc->getName();
> +    if (A->hasName()) {
> +      Name += ": %";
> +      Name += A->getName();
> +    } else {
> +      Name += ": argument ";
> +      Name += utostr(i);
> +    }
> +
> +    // Note: We always create a new anonymous root here. This is
> true regardless
> +    // of the linkage of the callee because the aliasing "scope" is
> not just a
> +    // property of the callee, but also all control dependencies in
> the caller.
> +    MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain,
> Name);
> +    NewScopes.insert(std::make_pair(A, NewScope));
> +  }
> +
> +  // Iterate over all new instructions in the map; for all
> memory-access
> +  // instructions, add the alias scope metadata.
> +  for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE =
> VMap.end();
> +       VMI != VMIE; ++VMI) {
> +    if (const Instruction *I = dyn_cast<Instruction>(VMI->first)) {
> +      if (!VMI->second)
> +        continue;
> +
> +      Instruction *NI = dyn_cast<Instruction>(VMI->second);
> +      if (!NI)
> +        continue;
> +
> +      SmallVector<const Value *, 2> PtrArgs;
> +
> +      if (const LoadInst *LI = dyn_cast<LoadInst>(I))
> +        PtrArgs.push_back(LI->getPointerOperand());
> +      else if (const StoreInst *SI = dyn_cast<StoreInst>(I))
> +        PtrArgs.push_back(SI->getPointerOperand());
> +      else if (const VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
> +        PtrArgs.push_back(VAAI->getPointerOperand());
> +      else if (const AtomicCmpXchgInst *CXI =
> dyn_cast<AtomicCmpXchgInst>(I))
> +        PtrArgs.push_back(CXI->getPointerOperand());
> +      else if (const AtomicRMWInst *RMWI =
> dyn_cast<AtomicRMWInst>(I))
> +        PtrArgs.push_back(RMWI->getPointerOperand());
> +      else if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) {
> +        PtrArgs.push_back(MI->getRawDest());
> +        if (const MemTransferInst *MTI =
> dyn_cast<MemTransferInst>(MI))
> +          PtrArgs.push_back(MTI->getRawSource());
> +      }
> +
> +      // If we found no pointers, then this instruction is not
> suitable for
> +      // pairing with an instruction to receive aliasing metadata.
> +      // Simplification during cloning could make this happen, and
> skip these
> +      // cases for now.
> +      if (PtrArgs.empty())
> +        continue;
> +
> +      // It is possible that there is only one underlying object,
> but you
> +      // need to go through several PHIs to see it, and thus could
> be
> +      // repeated in the Objects list.
> +      SmallPtrSet<const Value *, 4> ObjSet;
> +      SmallVector<Value *, 4> Scopes, NoAliases;
> +
> +      SmallSetVector<const Argument *, 4> NAPtrArgs;
> +      for (unsigned i = 0, ie = PtrArgs.size(); i != ie; ++i) {
> +        SmallVector<Value *, 4> Objects;
> +        GetUnderlyingObjects(const_cast<Value*>(PtrArgs[i]),
> +                             Objects, DL, /* MaxLookup = */ 0);
> +
> +        for (Value *O : Objects)
> +          ObjSet.insert(O);
> +      }
> +
> +      // Figure out if we're derived from anyhing that is not a
> noalias
> +      // argument.
> +      bool CanDeriveViaCapture = false;
> +      for (const Value *V : ObjSet)
> +        if (!isIdentifiedFunctionLocal(const_cast<Value*>(V))) {
> +          CanDeriveViaCapture = true;
> +          break;
> +        }
> +
> +      // First, we want to figure out all of the sets with which we
> definitely
> +      // don't alias. Iterate over all noalias set, and add those
> for which:
> +      //   1. The noalias argument is not in the set of objects from
> which we
> +      //      definitely derive.
> +      //   2. The noalias argument has not yet been captured.
> +      for (const Argument *A : NoAliasArgs) {
> +        if (!ObjSet.count(A) && (!CanDeriveViaCapture ||
> +                                 A->hasNoCaptureAttr() ||
> +                                 !PointerMayBeCapturedBefore(A,
> +                                   /* ReturnCaptures */ false,
> +                                   /* StoreCaptures */ false, I,
> &DT)))
> +          NoAliases.push_back(NewScopes[A]);
> +      }
> +
> +      if (!NoAliases.empty())
> +        NI->setMetadata(LLVMContext::MD_noalias,
> MDNode::concatenate(
> +          NI->getMetadata(LLVMContext::MD_noalias),
> +            MDNode::get(CalledFunc->getContext(), NoAliases)));
> +      // Next, we want to figure out all of the sets to which we
> might belong.
> +      // We might below to a set if:
> +      //  1. The noalias argument is in the set of underlying
> objects
> +      // or
> +      //  2. There is some non-noalias argument in our list and the
> no-alias
> +      //     argument has been captured.
> +
> +      for (const Argument *A : NoAliasArgs) {
> +        if (ObjSet.count(A) || (CanDeriveViaCapture &&
> +                                PointerMayBeCapturedBefore(A,
> +                                  /* ReturnCaptures */ false,
> +                                  /* StoreCaptures */ false,
> +                                  I, &DT)))
> +          Scopes.push_back(NewScopes[A]);
> +      }
> +
> +      if (!Scopes.empty())
> +        NI->setMetadata(LLVMContext::MD_alias_scope,
> MDNode::concatenate(
> +          NI->getMetadata(LLVMContext::MD_alias_scope),
> +            MDNode::get(CalledFunc->getContext(), Scopes)));
> +    }
> +  }
> +}
> +
>  /// UpdateCallGraphAfterInlining - Once we have cloned code over
>  from a callee
>  /// into the caller, update the specified callgraph to reflect the
>  changes we
>  /// made.  Note that it's possible that not all code was copied
>  over, so only
> @@ -749,6 +920,9 @@ bool llvm::InlineFunction(CallSite CS, I
>  
>      // Clone existing noalias metadata if necessary.
>      CloneAliasScopeMetadata(CS, VMap);
> +
> +    // Add noalias metadata if necessary.
> +    AddAliasScopeMetadata(CS, VMap, IFI.DL);
>    }
>  
>    // If there are any alloca instructions in the block that used to
>    be the entry
> 
> Removed: llvm/trunk/test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll?rev=213948&view=auto
> ==============================================================================
> --- llvm/trunk/test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll
> (original)
> +++ llvm/trunk/test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll
> (removed)
> @@ -1,80 +0,0 @@
> -; RUN: opt < %s -basicaa -scoped-noalias -aa-eval
> -evaluate-aa-metadata -print-all-alias-modref-info -disable-output
> 2>&1 | FileCheck %s
> -target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> -target triple = "x86_64-unknown-linux-gnu"
> -
> -define void @foo1(float* nocapture %a, float* nocapture readonly %c)
> #0 {
> -entry:
> -; CHECK-LABEL: Function: foo1
> -  %0 = load float* %c, align 4, !alias.scope !0
> -  %arrayidx.i = getelementptr inbounds float* %a, i64 5
> -  store float %0, float* %arrayidx.i, align 4, !noalias !0
> -
> -  %1 = load float* %c, align 4
> -  %arrayidx = getelementptr inbounds float* %a, i64 7
> -  store float %1, float* %arrayidx, align 4
> -
> -  %2 = load float* %c, align 4, !alias.scope !1
> -  %arrayidx.i2 = getelementptr inbounds float* %a, i64 15
> -  store float %2, float* %arrayidx.i2, align 4, !noalias !3
> -
> -  %3 = load float* %c, align 4, !alias.scope !3
> -  %arrayidx.i3 = getelementptr inbounds float* %a, i64 16
> -  store float %3, float* %arrayidx.i3, align 4, !noalias !0
> -
> -  %4 = load float* %c, align 4, !alias.scope !5
> -  %arrayidx.i4 = getelementptr inbounds float* %a, i64 17
> -  store float %4, float* %arrayidx.i4, align 4, !noalias !3
> -  ret void
> -}
> -
> -attributes #0 = { nounwind uwtable }
> -
> -; A root scope (which doubles as a list of itself):
> -!0 = metadata !{metadata !0}
> -
> -; Two child scopes (which must be self-referential to avoid being
> "uniqued"):
> -!1 = metadata !{metadata !2}
> -!2 = metadata !{metadata !2, metadata !0}
> -
> -!3 = metadata !{metadata !4}
> -!4 = metadata !{metadata !4, metadata !0}
> -
> -; A list of the two children:
> -!5 = metadata !{metadata !2, metadata !4}
> -
> -; CHECK: NoAlias:   %0 = load float* %c, align 4, !alias.scope !0
> <->   store float %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: MayAlias:   %0 = load float* %c, align 4, !alias.scope !0
> <->   store float %1, float* %arrayidx, align 4
> -; CHECK: MayAlias:   %0 = load float* %c, align 4, !alias.scope !0
> <->   store float %2, float* %arrayidx.i2, align 4, !noalias !3
> -; CHECK: NoAlias:   %0 = load float* %c, align 4, !alias.scope !0
> <->   store float %3, float* %arrayidx.i3, align 4, !noalias !0
> -; CHECK: MayAlias:   %0 = load float* %c, align 4, !alias.scope !0
> <->   store float %4, float* %arrayidx.i4, align 4, !noalias !3
> -; CHECK: MayAlias:   %1 = load float* %c, align 4 <->   store float
> %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: MayAlias:   %1 = load float* %c, align 4 <->   store float
> %1, float* %arrayidx, align 4
> -; CHECK: MayAlias:   %1 = load float* %c, align 4 <->   store float
> %2, float* %arrayidx.i2, align 4, !noalias !3
> -; CHECK: MayAlias:   %1 = load float* %c, align 4 <->   store float
> %3, float* %arrayidx.i3, align 4, !noalias !0
> -; CHECK: MayAlias:   %1 = load float* %c, align 4 <->   store float
> %4, float* %arrayidx.i4, align 4, !noalias !3
> -; CHECK: NoAlias:   %2 = load float* %c, align 4, !alias.scope !1
> <->   store float %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: MayAlias:   %2 = load float* %c, align 4, !alias.scope !1
> <->   store float %1, float* %arrayidx, align 4
> -; CHECK: MayAlias:   %2 = load float* %c, align 4, !alias.scope !1
> <->   store float %2, float* %arrayidx.i2, align 4, !noalias !3
> -; CHECK: NoAlias:   %2 = load float* %c, align 4, !alias.scope !1
> <->   store float %3, float* %arrayidx.i3, align 4, !noalias !0
> -; CHECK: MayAlias:   %2 = load float* %c, align 4, !alias.scope !1
> <->   store float %4, float* %arrayidx.i4, align 4, !noalias !3
> -; CHECK: NoAlias:   %3 = load float* %c, align 4, !alias.scope !3
> <->   store float %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: MayAlias:   %3 = load float* %c, align 4, !alias.scope !3
> <->   store float %1, float* %arrayidx, align 4
> -; CHECK: NoAlias:   %3 = load float* %c, align 4, !alias.scope !3
> <->   store float %2, float* %arrayidx.i2, align 4, !noalias !3
> -; CHECK: NoAlias:   %3 = load float* %c, align 4, !alias.scope !3
> <->   store float %3, float* %arrayidx.i3, align 4, !noalias !0
> -; CHECK: NoAlias:   %3 = load float* %c, align 4, !alias.scope !3
> <->   store float %4, float* %arrayidx.i4, align 4, !noalias !3
> -; CHECK: NoAlias:   %4 = load float* %c, align 4, !alias.scope !5
> <->   store float %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: MayAlias:   %4 = load float* %c, align 4, !alias.scope !5
> <->   store float %1, float* %arrayidx, align 4
> -; CHECK: NoAlias:   %4 = load float* %c, align 4, !alias.scope !5
> <->   store float %2, float* %arrayidx.i2, align 4, !noalias !3
> -; CHECK: NoAlias:   %4 = load float* %c, align 4, !alias.scope !5
> <->   store float %3, float* %arrayidx.i3, align 4, !noalias !0
> -; CHECK: NoAlias:   %4 = load float* %c, align 4, !alias.scope !5
> <->   store float %4, float* %arrayidx.i4, align 4, !noalias !3
> -; CHECK: NoAlias:   store float %1, float* %arrayidx, align 4 <->
>   store float %0, float* %arrayidx.i, align 4, !noalias !0
> -; CHECK: NoAlias:   store float %2, float* %arrayidx.i2, align 4,
> !noalias !3 <->   store float %0, float* %arrayidx.i, align 4,
> !noalias !0
> -; CHECK: NoAlias:   store float %2, float* %arrayidx.i2, align 4,
> !noalias !3 <->   store float %1, float* %arrayidx, align 4
> -; CHECK: NoAlias:   store float %3, float* %arrayidx.i3, align 4,
> !noalias !0 <->   store float %0, float* %arrayidx.i, align 4,
> !noalias !0
> -; CHECK: NoAlias:   store float %3, float* %arrayidx.i3, align 4,
> !noalias !0 <->   store float %1, float* %arrayidx, align 4
> -; CHECK: NoAlias:   store float %3, float* %arrayidx.i3, align 4,
> !noalias !0 <->   store float %2, float* %arrayidx.i2, align 4,
> !noalias !3
> -; CHECK: NoAlias:   store float %4, float* %arrayidx.i4, align 4,
> !noalias !3 <->   store float %0, float* %arrayidx.i, align 4,
> !noalias !0
> -; CHECK: NoAlias:   store float %4, float* %arrayidx.i4, align 4,
> !noalias !3 <->   store float %1, float* %arrayidx, align 4
> -; CHECK: NoAlias:   store float %4, float* %arrayidx.i4, align 4,
> !noalias !3 <->   store float %2, float* %arrayidx.i2, align 4,
> !noalias !3
> -; CHECK: NoAlias:   store float %4, float* %arrayidx.i4, align 4,
> !noalias !3 <->   store float %3, float* %arrayidx.i3, align 4,
> !noalias !0
> -
> 
> Added: llvm/trunk/test/Transforms/Inline/noalias.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias.ll?rev=213949&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/Inline/noalias.ll (added)
> +++ llvm/trunk/test/Transforms/Inline/noalias.ll Fri Jul 25 10:50:08
> 2014
> @@ -0,0 +1,76 @@
> +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s |
> FileCheck %s
> +target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +define void @hello(float* noalias nocapture %a, float* nocapture
> readonly %c) #0 {
> +entry:
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 5
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +define void @foo(float* nocapture %a, float* nocapture readonly %c)
> #0 {
> +entry:
> +  tail call void @hello(float* %a, float* %c)
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 7
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +; CHECK: define void @foo(float* nocapture %a, float* nocapture
> readonly %c) #0 {
> +; CHECK: entry:
> +; CHECK:   %0 = load float* %c, align 4, !noalias !0
> +; CHECK:   %arrayidx.i = getelementptr inbounds float* %a, i64 5
> +; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope
> !0
> +; CHECK:   %1 = load float* %c, align 4
> +; CHECK:   %arrayidx = getelementptr inbounds float* %a, i64 7
> +; CHECK:   store float %1, float* %arrayidx, align 4
> +; CHECK:   ret void
> +; CHECK: }
> +
> +define void @hello2(float* noalias nocapture %a, float* noalias
> nocapture %b, float* nocapture readonly %c) #0 {
> +entry:
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 5
> +  store float %0, float* %arrayidx, align 4
> +  %arrayidx1 = getelementptr inbounds float* %b, i64 8
> +  store float %0, float* %arrayidx1, align 4
> +  ret void
> +}
> +
> +define void @foo2(float* nocapture %a, float* nocapture %b, float*
> nocapture readonly %c) #0 {
> +entry:
> +  tail call void @hello2(float* %a, float* %b, float* %c)
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 7
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b,
> float* nocapture readonly %c) #0 {
> +; CHECK: entry:
> +; CHECK:   %0 = load float* %c, align 4, !noalias !3
> +; CHECK:   %arrayidx.i = getelementptr inbounds float* %a, i64 5
> +; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope
> !7, !noalias !8
> +; CHECK:   %arrayidx1.i = getelementptr inbounds float* %b, i64 8
> +; CHECK:   store float %0, float* %arrayidx1.i, align 4,
> !alias.scope !8, !noalias !7
> +; CHECK:   %1 = load float* %c, align 4
> +; CHECK:   %arrayidx = getelementptr inbounds float* %a, i64 7
> +; CHECK:   store float %1, float* %arrayidx, align 4
> +; CHECK:   ret void
> +; CHECK: }
> +
> +attributes #0 = { nounwind uwtable }
> +
> +; CHECK: !0 = metadata !{metadata !1}
> +; CHECK: !1 = metadata !{metadata !1, metadata !2, metadata !"hello:
> %a"}
> +; CHECK: !2 = metadata !{metadata !2, metadata !"hello"}
> +; CHECK: !3 = metadata !{metadata !4, metadata !6}
> +; CHECK: !4 = metadata !{metadata !4, metadata !5, metadata
> !"hello2: %a"}
> +; CHECK: !5 = metadata !{metadata !5, metadata !"hello2"}
> +; CHECK: !6 = metadata !{metadata !6, metadata !5, metadata
> !"hello2: %b"}
> +; CHECK: !7 = metadata !{metadata !4}
> +; CHECK: !8 = metadata !{metadata !6}
> +
> 
> Added: llvm/trunk/test/Transforms/Inline/noalias2.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias2.ll?rev=213949&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/Inline/noalias2.ll (added)
> +++ llvm/trunk/test/Transforms/Inline/noalias2.ll Fri Jul 25 10:50:08
> 2014
> @@ -0,0 +1,97 @@
> +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s |
> FileCheck %s
> +target datalayout =
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +define void @hello(float* noalias nocapture %a, float* noalias
> nocapture readonly %c) #0 {
> +entry:
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 5
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +define void @foo(float* noalias nocapture %a, float* noalias
> nocapture readonly %c) #0 {
> +entry:
> +  tail call void @hello(float* %a, float* %c)
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 7
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +; CHECK: define void @foo(float* noalias nocapture %a, float*
> noalias nocapture readonly %c) #0 {
> +; CHECK: entry:
> +; CHECK:   %0 = load float* %c, align 4, !alias.scope !0, !noalias
> !3
> +; CHECK:   %arrayidx.i = getelementptr inbounds float* %a, i64 5
> +; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope
> !3, !noalias !0
> +; CHECK:   %1 = load float* %c, align 4
> +; CHECK:   %arrayidx = getelementptr inbounds float* %a, i64 7
> +; CHECK:   store float %1, float* %arrayidx, align 4
> +; CHECK:   ret void
> +; CHECK: }
> +
> +define void @hello2(float* noalias nocapture %a, float* noalias
> nocapture %b, float* nocapture readonly %c) #0 {
> +entry:
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 6
> +  store float %0, float* %arrayidx, align 4
> +  %arrayidx1 = getelementptr inbounds float* %b, i64 8
> +  store float %0, float* %arrayidx1, align 4
> +  ret void
> +}
> +
> +; Check that when hello() is inlined into foo(), and then foo() is
> inlined into
> +; foo2(), the noalias scopes are properly concatenated.
> +define void @foo2(float* nocapture %a, float* nocapture %b, float*
> nocapture readonly %c) #0 {
> +entry:
> +  tail call void @foo(float* %a, float* %c)
> +  tail call void @hello2(float* %a, float* %b, float* %c)
> +  %0 = load float* %c, align 4
> +  %arrayidx = getelementptr inbounds float* %a, i64 7
> +  store float %0, float* %arrayidx, align 4
> +  ret void
> +}
> +
> +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b,
> float* nocapture readonly %c) #0 {
> +; CHECK: entry:
> +; CHECK:   %0 = load float* %c, align 4, !alias.scope !5, !noalias
> !10
> +; CHECK:   %arrayidx.i.i = getelementptr inbounds float* %a, i64 5
> +; CHECK:   store float %0, float* %arrayidx.i.i, align 4,
> !alias.scope !10, !noalias !5
> +; CHECK:   %1 = load float* %c, align 4, !alias.scope !13, !noalias
> !14
> +; CHECK:   %arrayidx.i = getelementptr inbounds float* %a, i64 7
> +; CHECK:   store float %1, float* %arrayidx.i, align 4, !alias.scope
> !14, !noalias !13
> +; CHECK:   %2 = load float* %c, align 4, !noalias !15
> +; CHECK:   %arrayidx.i1 = getelementptr inbounds float* %a, i64 6
> +; CHECK:   store float %2, float* %arrayidx.i1, align 4,
> !alias.scope !19, !noalias !20
> +; CHECK:   %arrayidx1.i = getelementptr inbounds float* %b, i64 8
> +; CHECK:   store float %2, float* %arrayidx1.i, align 4,
> !alias.scope !20, !noalias !19
> +; CHECK:   %3 = load float* %c, align 4
> +; CHECK:   %arrayidx = getelementptr inbounds float* %a, i64 7
> +; CHECK:   store float %3, float* %arrayidx, align 4
> +; CHECK:   ret void
> +; CHECK: }
> +
> +; CHECK: !0 = metadata !{metadata !1}
> +; CHECK: !1 = metadata !{metadata !1, metadata !2, metadata !"hello:
> %c"}
> +; CHECK: !2 = metadata !{metadata !2, metadata !"hello"}
> +; CHECK: !3 = metadata !{metadata !4}
> +; CHECK: !4 = metadata !{metadata !4, metadata !2, metadata !"hello:
> %a"}
> +; CHECK: !5 = metadata !{metadata !6, metadata !8}
> +; CHECK: !6 = metadata !{metadata !6, metadata !7, metadata !"hello:
> %c"}
> +; CHECK: !7 = metadata !{metadata !7, metadata !"hello"}
> +; CHECK: !8 = metadata !{metadata !8, metadata !9, metadata !"foo:
> %c"}
> +; CHECK: !9 = metadata !{metadata !9, metadata !"foo"}
> +; CHECK: !10 = metadata !{metadata !11, metadata !12}
> +; CHECK: !11 = metadata !{metadata !11, metadata !7, metadata
> !"hello: %a"}
> +; CHECK: !12 = metadata !{metadata !12, metadata !9, metadata !"foo:
> %a"}
> +; CHECK: !13 = metadata !{metadata !8}
> +; CHECK: !14 = metadata !{metadata !12}
> +; CHECK: !15 = metadata !{metadata !16, metadata !18}
> +; CHECK: !16 = metadata !{metadata !16, metadata !17, metadata
> !"hello2: %a"}
> +; CHECK: !17 = metadata !{metadata !17, metadata !"hello2"}
> +; CHECK: !18 = metadata !{metadata !18, metadata !17, metadata
> !"hello2: %b"}
> +; CHECK: !19 = metadata !{metadata !16}
> +; CHECK: !20 = metadata !{metadata !18}
> +
> +attributes #0 = { nounwind uwtable }
> +
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list