[llvm-commits] [llvm] r149847 - in /llvm/trunk: lib/Transforms/IPO/GlobalOpt.cpp test/Transforms/GlobalOpt/atomic.ll

Nick Lewycky nicholas at mxc.ca
Sun Feb 5 12:03:12 PST 2012


Nick Lewycky wrote:
> Author: nicholas
> Date: Sun Feb  5 13:56:38 2012
> New Revision: 149847
>
> URL: http://llvm.org/viewvc/llvm-project?rev=149847&view=rev
> Log:
> Teach GlobalOpt to handle atomic accesses to globals.
>
>   * Most of the transforms come through intact by having each transformed load or
> store copy the ordering and synchronization scope of the original.
>   * The transform that turns a global only accessed in main() into an alloca
> (since main is non-recursive) with a store of the initial value uses an
> unordered store

Doh, I meant NotAtomic, as nothing can race on this store. The code in 
the commit uses NotAtomic here.

, since it's guaranteed to be the first thing to happen in main.
> (Threads may have started before main (!) but they can't have the address of a
> function local before the point in the entry block we insert our code.)
>   * The heap-SRoA transforms are disabled in the face of atomic operations. This
> can probably be improved; it seems odd to have atomic accesses to an alloca
> that doesn't have its address taken.
>
> AnalyzeGlobal keeps track of the strongest ordering found in any use of the
> global. This is more information than we need right now, but it's cheap to
> compute and likely to be useful.
>
> Added:
>      llvm/trunk/test/Transforms/GlobalOpt/atomic.ll
> Modified:
>      llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
>
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=149847&r1=149846&r2=149847&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Sun Feb  5 13:56:38 2012
> @@ -148,14 +148,27 @@
>     /// HasPHIUser - Set to true if this global has a user that is a PHI node.
>     bool HasPHIUser;
>
> +  /// AtomicOrdering - Set to the strongest atomic ordering requirement.
> +  AtomicOrdering Ordering;
> +
>     GlobalStatus() : isCompared(false), isLoaded(false), StoredType(NotStored),
>                      StoredOnceValue(0), AccessingFunction(0),
> -                   HasMultipleAccessingFunctions(false), HasNonInstructionUser(false),
> -                   HasPHIUser(false) {}
> +                   HasMultipleAccessingFunctions(false),
> +                   HasNonInstructionUser(false), HasPHIUser(false),
> +                   Ordering(NotAtomic) {}
>   };
>
>   }
>
> +/// StrongerOrdering - Return the stronger of the two ordering. If the two
> +/// orderings are acquire and release, then return AcquireRelease.
> +///
> +static AtomicOrdering StrongerOrdering(AtomicOrdering X, AtomicOrdering Y) {
> +  if (X == Acquire&&  Y == Release) return AcquireRelease;
> +  if (Y == Acquire&&  X == Release) return AcquireRelease;
> +  return (AtomicOrdering)std::max(X, Y);
> +}
> +
>   /// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used
>   /// by constants itself.  Note that constants cannot be cyclic, so this test is
>   /// pretty easy to implement recursively.
> @@ -200,14 +213,16 @@
>         }
>         if (const LoadInst *LI = dyn_cast<LoadInst>(I)) {
>           GS.isLoaded = true;
> -        // Don't hack on volatile/atomic loads.
> -        if (!LI->isSimple()) return true;
> +        // Don't hack on volatile loads.
> +        if (LI->isVolatile()) return true;
> +        GS.Ordering = StrongerOrdering(GS.Ordering, LI->getOrdering());
>         } else if (const StoreInst *SI = dyn_cast<StoreInst>(I)) {
>           // Don't allow a store OF the address, only stores TO the address.
>           if (SI->getOperand(0) == V) return true;
>
> -        // Don't hack on volatile/atomic stores.
> -        if (!SI->isSimple()) return true;
> +        // Don't hack on volatile stores.
> +        if (SI->isVolatile()) return true;
> +        GS.Ordering = StrongerOrdering(GS.Ordering, SI->getOrdering());
>
>           // If this is a direct store to the global (i.e., the global is a scalar
>           // value, not an aggregate), keep more specific information about
> @@ -879,7 +894,8 @@
>     while (!GV->use_empty()) {
>       if (StoreInst *SI = dyn_cast<StoreInst>(GV->use_back())) {
>         // The global is initialized when the store to it occurs.
> -      new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, SI);
> +      new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, false, 0,
> +                    SI->getOrdering(), SI->getSynchScope(), SI);
>         SI->eraseFromParent();
>         continue;
>       }
> @@ -894,7 +910,10 @@
>
>         ICmpInst *ICI = cast<ICmpInst>(LoadUse.getUser());
>         // Replace the cmp X, 0 with a use of the bool value.
> -      Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI);
> +      // Sink the load to where the compare was, if atomic rules allow us to.
> +      Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", false, 0,
> +                               LI->getOrdering(), LI->getSynchScope(),
> +                               LI->isUnordered() ? (Instruction*)ICI : LI);
>         InitBoolUsed = true;
>         switch (ICI->getPredicate()) {
>         default: llvm_unreachable("Unknown ICmp Predicate!");
> @@ -1454,6 +1473,7 @@
>   static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
>                                                  CallInst *CI,
>                                                  Type *AllocTy,
> +                                               AtomicOrdering Ordering,
>                                                  Module::global_iterator&GVI,
>                                                  TargetData *TD) {
>     if (!TD)
> @@ -1503,6 +1523,9 @@
>     // into multiple malloc'd arrays, one for each field.  This is basically
>     // SRoA for malloc'd memory.
>
> +  if (Ordering != NotAtomic)
> +    return false;
> +
>     // If this is an allocation of a fixed size array of structs, analyze as a
>     // variable size array.  malloc [100 x struct],1 ->  malloc struct, 100
>     if (NElems == ConstantInt::get(CI->getArgOperand(0)->getType(), 1))
> @@ -1545,6 +1568,7 @@
>   // OptimizeOnceStoredGlobal - Try to optimize globals based on the knowledge
>   // that only one value (besides its initializer) is ever stored to the global.
>   static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
> +                                     AtomicOrdering Ordering,
>                                        Module::global_iterator&GVI,
>                                        TargetData *TD) {
>     // Ignore no-op GEPs and bitcasts.
> @@ -1566,7 +1590,7 @@
>       } else if (CallInst *CI = extractMallocCall(StoredOnceVal)) {
>         Type *MallocType = getMallocAllocatedType(CI);
>         if (MallocType&&  TryToOptimizeStoreOfMallocToGlobal(GV, CI, MallocType,
> -                                                           GVI, TD))
> +                                                           Ordering, GVI, TD))
>           return true;
>       }
>     }
> @@ -1642,7 +1666,8 @@
>           if (LoadInst *LI = dyn_cast<LoadInst>(StoredVal)) {
>             assert(LI->getOperand(0) == GV&&  "Not a copy!");
>             // Insert a new load, to preserve the saved value.
> -          StoreVal = new LoadInst(NewGV, LI->getName()+".b", LI);
> +          StoreVal = new LoadInst(NewGV, LI->getName()+".b", false, 0,
> +                                  LI->getOrdering(), LI->getSynchScope(), LI);
>           } else {
>             assert((isa<CastInst>(StoredVal) || isa<SelectInst>(StoredVal))&&
>                    "This is not a form that we understand!");
> @@ -1650,11 +1675,13 @@
>             assert(isa<LoadInst>(StoreVal)&&  "Not a load of NewGV!");
>           }
>         }
> -      new StoreInst(StoreVal, NewGV, SI);
> +      new StoreInst(StoreVal, NewGV, false, 0,
> +                    SI->getOrdering(), SI->getSynchScope(), SI);
>       } else {
>         // Change the load into a load of bool then a select.
>         LoadInst *LI = cast<LoadInst>(UI);
> -      LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", LI);
> +      LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", false, 0,
> +                                   LI->getOrdering(), LI->getSynchScope(), LI);
>         Value *NSI;
>         if (IsOneZero)
>           NSI = new ZExtInst(NLI, LI->getType(), "", LI);
> @@ -1808,7 +1835,7 @@
>
>       // Try to optimize globals based on the knowledge that only one value
>       // (besides its initializer) is ever stored to the global.
> -    if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GVI,
> +    if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GS.Ordering, GVI,
>                                    getAnalysisIfAvailable<TargetData>()))
>         return true;
>
>
> Added: llvm/trunk/test/Transforms/GlobalOpt/atomic.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/atomic.ll?rev=149847&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/GlobalOpt/atomic.ll (added)
> +++ llvm/trunk/test/Transforms/GlobalOpt/atomic.ll Sun Feb  5 13:56:38 2012
> @@ -0,0 +1,10 @@
> +; RUN: opt -globalopt<  %s -S -o - | FileCheck %s
> +
> + at GV1 = internal global i64 1
> +; CHECK: @GV1 = internal unnamed_addr constant i64 1
> +
> +define void @test1() {
> +entry:
> +  %0 = load atomic i8* bitcast (i64* @GV1 to i8*) acquire, align 8
> +  ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list