[llvm-commits] [llvm] r94875 - in /llvm/trunk: include/llvm/Transforms/Utils/Local.h lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp lib/Transforms/Scalar/GVN.cpp lib/Transforms/Scalar/TailRecursionElimination.cpp lib/Transforms/Utils/Local.cpp test/Transforms/GVN/load-pre-align.ll

Bob Wilson bob.wilson at apple.com
Fri Jan 29 20:42:41 PST 2010


Author: bwilson
Date: Fri Jan 29 22:42:39 2010
New Revision: 94875

URL: http://llvm.org/viewvc/llvm-project?rev=94875&view=rev
Log:
Check alignment of loads when deciding whether it is safe to execute them
unconditionally.  Besides checking the offset, also check that the underlying
object is aligned as much as the load itself.

Added:
    llvm/trunk/test/Transforms/GVN/load-pre-align.ll
Modified:
    llvm/trunk/include/llvm/Transforms/Utils/Local.h
    llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp
    llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
    llvm/trunk/lib/Transforms/Utils/Local.cpp

Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=94875&r1=94874&r2=94875&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Fri Jan 29 22:42:39 2010
@@ -39,7 +39,7 @@
 /// specified pointer, we do a quick local scan of the basic block containing
 /// ScanFrom, to determine if the address is already accessed.
 bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
-                                 const TargetData *TD = 0);
+                                 unsigned Align, const TargetData *TD = 0);
 
 //===----------------------------------------------------------------------===//
 //  Local constant propagation.

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp?rev=94875&r1=94874&r2=94875&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp Fri Jan 29 22:42:39 2010
@@ -200,14 +200,15 @@
     //
     if (SelectInst *SI = dyn_cast<SelectInst>(Op)) {
       // load (select (Cond, &V1, &V2))  --> select(Cond, load &V1, load &V2).
-      if (isSafeToLoadUnconditionally(SI->getOperand(1), SI, TD) &&
-          isSafeToLoadUnconditionally(SI->getOperand(2), SI, TD)) {
+      unsigned Align = LI.getAlignment();
+      if (isSafeToLoadUnconditionally(SI->getOperand(1), SI, Align, TD) &&
+          isSafeToLoadUnconditionally(SI->getOperand(2), SI, Align, TD)) {
         LoadInst *V1 = Builder->CreateLoad(SI->getOperand(1),
-                                        SI->getOperand(1)->getName()+".val");
+                                           SI->getOperand(1)->getName()+".val");
         LoadInst *V2 = Builder->CreateLoad(SI->getOperand(2),
-                                        SI->getOperand(2)->getName()+".val");
-        V1->setAlignment(LI.getAlignment());
-        V2->setAlignment(LI.getAlignment());
+                                           SI->getOperand(2)->getName()+".val");
+        V1->setAlignment(Align);
+        V2->setAlignment(Align);
         return SelectInst::Create(SI->getCondition(), V1, V2);
       }
 

Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=94875&r1=94874&r2=94875&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Fri Jan 29 22:42:39 2010
@@ -1651,7 +1651,8 @@
   if (!allSingleSucc &&
       // FIXME: REEVALUTE THIS.
       !isSafeToLoadUnconditionally(LoadPtr,
-                                   UnavailablePred->getTerminator(), TD)) {
+                                   UnavailablePred->getTerminator(),
+                                   LI->getAlignment(), TD)) {
     assert(NewInsts.empty() && "Should not have inserted instructions");
     return false;
   }

Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=94875&r1=94874&r2=94875&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Fri Jan 29 22:42:39 2010
@@ -211,7 +211,8 @@
       // FIXME: Writes to memory only matter if they may alias the pointer
       // being loaded from.
       if (CI->mayWriteToMemory() ||
-          !isSafeToLoadUnconditionally(L->getPointerOperand(), L))
+          !isSafeToLoadUnconditionally(L->getPointerOperand(), L,
+                                       L->getAlignment()))
         return false;
     }
   }

Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=94875&r1=94874&r2=94875&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Fri Jan 29 22:42:39 2010
@@ -75,31 +75,38 @@
 /// specified pointer, we do a quick local scan of the basic block containing
 /// ScanFrom, to determine if the address is already accessed.
 bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
-                                       const TargetData *TD) {
+                                       unsigned Align, const TargetData *TD) {
   uint64_t ByteOffset = 0;
   Value *Base = V;
   if (TD)
     Base = getUnderlyingObjectWithOffset(V, TD, ByteOffset);
 
   const Type *BaseType = 0;
-  if (const AllocaInst *AI = dyn_cast<AllocaInst>(Base))
-    // If it is an alloca it is always safe to load from.
+  unsigned BaseAlign = 0;
+  if (const AllocaInst *AI = dyn_cast<AllocaInst>(Base)) {
+    // An alloca is safe to load from as load as it is suitably aligned.
     BaseType = AI->getAllocatedType();
-  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(Base)) {
+    BaseAlign = AI->getAlignment();
+  } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(Base)) {
     // Global variables are safe to load from but their size cannot be
     // guaranteed if they are overridden.
-    if (!isa<GlobalAlias>(GV) && !GV->mayBeOverridden())
+    if (!isa<GlobalAlias>(GV) && !GV->mayBeOverridden()) {
       BaseType = GV->getType()->getElementType();
+      BaseAlign = GV->getAlignment();
+    }
   }
+  if (TD && BaseType && BaseAlign == 0)
+    BaseAlign = TD->getPrefTypeAlignment(BaseType);
 
-  if (BaseType) {
+  if (BaseType && Align <= BaseAlign) {
     if (!TD)
       return true; // Loading directly from an alloca or global is OK.
     if (BaseType->isSized()) {
       // Check if the load is within the bounds of the underlying object.
       const PointerType *AddrTy = cast<PointerType>(V->getType());
       uint64_t LoadSize = TD->getTypeStoreSize(AddrTy->getElementType());
-      if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType))
+      if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType) &&
+          (Align == 0 || (ByteOffset % Align) == 0))
         return true;
     }
   }

Added: llvm/trunk/test/Transforms/GVN/load-pre-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/load-pre-align.ll?rev=94875&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/GVN/load-pre-align.ll (added)
+++ llvm/trunk/test/Transforms/GVN/load-pre-align.ll Fri Jan 29 22:42:39 2010
@@ -0,0 +1,44 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32"
+
+ at p = external global i32
+
+define arm_apcscc i32 @test(i32 %n) nounwind {
+; CHECK: @test
+entry:
+  br label %for.cond
+
+; loads aligned greater than the memory should not be moved past conditionals
+; CHECK-NOT: load
+; CHECK: br i1
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %indvar.next, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:
+; ...but PRE can still move the load out of for.end to here.
+; CHECK: for.cond.for.end_crit_edge:
+; CHECK-NEXT: load
+  br label %for.end
+
+for.body:
+  %tmp3 = load i32* @p, align 8
+  %dec = add i32 %tmp3, -1
+  store i32 %dec, i32* @p
+  %cmp6 = icmp slt i32 %dec, 0
+  br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc
+
+for.body.for.end_crit_edge:
+  br label %for.end
+
+for.inc:
+  %indvar.next = add i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  %tmp9 = load i32* @p, align 8
+  ret i32 %tmp9
+}





More information about the llvm-commits mailing list