[llvm-commits] [llvm] r73632 - in /llvm/trunk: lib/Transforms/Scalar/GVN.cpp test/Transforms/GVN/2009-06-17-InvalidPRE.ll test/Transforms/GVN/pre-single-pred.ll

Dale Johannesen dalej at apple.com
Wed Jun 17 13:48:23 PDT 2009


Author: johannes
Date: Wed Jun 17 15:48:23 2009
New Revision: 73632

URL: http://llvm.org/viewvc/llvm-project?rev=73632&view=rev
Log:
This fixes a bug introduced in 72661, which can
move loads back past a check that the load address
is valid, see new testcase.  The test that went
in with 72661 has exactly this case, except that
the conditional it's moving past is checking
something else; I've settled for changing that
test to reference a global, not a pointer.  It
may be possible to scan all the tests you pass and
make sure none of them are checking any component
of the address, but it's not trivial and I'm not
trying to do that here.


Added:
    llvm/trunk/test/Transforms/GVN/2009-06-17-InvalidPRE.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp
    llvm/trunk/test/Transforms/GVN/pre-single-pred.ll

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Jun 17 15:48:23 2009
@@ -37,6 +37,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
 #include <cstdio>
 using namespace llvm;
 
@@ -1075,6 +1076,7 @@
   BasicBlock *TmpBB = LoadBB;
 
   bool isSinglePred = false;
+  bool allSingleSucc = true;
   while (TmpBB->getSinglePredecessor()) {
     isSinglePred = true;
     TmpBB = TmpBB->getSinglePredecessor();
@@ -1084,6 +1086,8 @@
       return false;
     if (Blockers.count(TmpBB))
       return false;
+    if (TmpBB->getTerminator()->getNumSuccessors() != 1)
+      allSingleSucc = false;
   }
   
   assert(TmpBB);
@@ -1160,7 +1164,20 @@
                 << UnavailablePred->getName() << "': " << *LI);
     return false;
   }
-  
+
+  // Make sure it is valid to move this load here.  We have to watch out for:
+  //  @1 = getelementptr (i8* p, ...
+  //  test p and branch if == 0
+  //  load @1
+  // It is valid to have the getelementptr before the test, even if p can be 0,
+  // as getelementptr only does address arithmetic.
+  // If we are not pushing the value through any multiple-successor blocks
+  // we do not have this case.  Otherwise, check that the load is safe to
+  // put anywhere; this can be improved, but should be conservatively safe.
+  if (!allSingleSucc &&
+      !isSafeToLoadUnconditionally(LoadPtr, UnavailablePred->getTerminator()))
+    return false;
+
   // Okay, we can eliminate this load by inserting a reload in the predecessor
   // and using PHI construction to get the value in the other predecessors, do
   // it.

Added: llvm/trunk/test/Transforms/GVN/2009-06-17-InvalidPRE.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-06-17-InvalidPRE.ll?rev=73632&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-06-17-InvalidPRE.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-06-17-InvalidPRE.ll Wed Jun 17 15:48:23 2009
@@ -0,0 +1,72 @@
+; RUN: llvm-as < %s | opt -gvn -enable-load-pre | llvm-dis | not grep pre1
+; GVN load pre was hoisting the loads at %13 and %16 up to bb4.outer.  
+; This is invalid as it bypasses the check for %m.0.ph==null in bb4. 
+; ModuleID = 'mbuf.c'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.6"
+  %struct.mbuf = type { %struct.mbuf*, %struct.mbuf*, i32, i8*, i16, i16, i32 }
+
+define void @m_adj(%struct.mbuf* %mp, i32 %req_len) nounwind optsize {
+entry:
+  %0 = icmp eq %struct.mbuf* %mp, null    ; <i1> [#uses=1]
+  %1 = icmp slt i32 %req_len, 0   ; <i1> [#uses=1]
+  %or.cond = or i1 %1, %0   ; <i1> [#uses=1]
+  br i1 %or.cond, label %return, label %bb4.preheader
+
+bb4.preheader:    ; preds = %entry
+  br label %bb4.outer
+
+bb2:    ; preds = %bb1
+  %2 = sub i32 %len.0, %13   ; <i32> [#uses=1]
+  %3 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2    ; <i32*> [#uses=1]
+  store i32 0, i32* %3, align 4
+  %4 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 0    ; <%struct.mbuf**> [#uses=1]
+  %5 = load %struct.mbuf** %4, align 4    ; <%struct.mbuf*> [#uses=1]
+  br label %bb4.outer
+
+bb4.outer:    ; preds = %bb4.preheader, %bb2
+  %m.0.ph = phi %struct.mbuf* [ %5, %bb2 ], [ %mp, %bb4.preheader ]   ; <%struct.mbuf*> [#uses=7]
+  %len.0.ph = phi i32 [ %2, %bb2 ], [ %req_len, %bb4.preheader ]    ; <i32> [#uses=1]
+  %6 = icmp ne %struct.mbuf* %m.0.ph, null    ; <i1> [#uses=1]
+  %7 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2    ; <i32*> [#uses=1]
+  %8 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 2   ; <i32*> [#uses=1]
+  %9 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 3   ; <i8**> [#uses=1]
+  %10 = getelementptr %struct.mbuf* %m.0.ph, i32 0, i32 3   ; <i8**> [#uses=1]
+  br label %bb4
+
+bb4:    ; preds = %bb4.outer, %bb3
+  %len.0 = phi i32 [ 0, %bb3 ], [ %len.0.ph, %bb4.outer ]   ; <i32> [#uses=6]
+  %11 = icmp sgt i32 %len.0, 0    ; <i1> [#uses=1]
+  %12 = and i1 %11, %6    ; <i1> [#uses=1]
+  br i1 %12, label %bb1, label %bb7
+
+bb1:    ; preds = %bb4
+  %13 = load i32* %7, align 4    ; <i32> [#uses=3]
+  %14 = icmp sgt i32 %13, %len.0    ; <i1> [#uses=1]
+  br i1 %14, label %bb3, label %bb2
+
+bb3:    ; preds = %bb1
+  %15 = sub i32 %13, %len.0    ; <i32> [#uses=1]
+  store i32 %15, i32* %8, align 4
+  %16 = load i8** %9, align 4    ; <i8*> [#uses=1]
+  %17 = getelementptr i8* %16, i32 %len.0   ; <i8*> [#uses=1]
+  store i8* %17, i8** %10, align 4
+  br label %bb4
+
+bb7:    ; preds = %bb4
+  %18 = getelementptr %struct.mbuf* %mp, i32 0, i32 5   ; <i16*> [#uses=1]
+  %19 = load i16* %18, align 2    ; <i16> [#uses=1]
+  %20 = zext i16 %19 to i32   ; <i32> [#uses=1]
+  %21 = and i32 %20, 2    ; <i32> [#uses=1]
+  %22 = icmp eq i32 %21, 0    ; <i1> [#uses=1]
+  br i1 %22, label %return, label %bb8
+
+bb8:    ; preds = %bb7
+  %23 = sub i32 %req_len, %len.0    ; <i32> [#uses=1]
+  %24 = getelementptr %struct.mbuf* %mp, i32 0, i32 6   ; <i32*> [#uses=1]
+  store i32 %23, i32* %24, align 4
+  ret void
+
+return:   ; preds = %bb7, %entry
+  ret void
+}

Modified: llvm/trunk/test/Transforms/GVN/pre-single-pred.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pre-single-pred.ll?rev=73632&r1=73631&r2=73632&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/GVN/pre-single-pred.ll (original)
+++ llvm/trunk/test/Transforms/GVN/pre-single-pred.ll Wed Jun 17 15:48:23 2009
@@ -1,6 +1,7 @@
 ; RUN: llvm-as < %s | opt -gvn -enable-load-pre | llvm-dis | not grep {tmp3 = load}
 
-define i32 @f(i32* nocapture %p, i32 %n) nounwind {
+ at p = external global i32
+define i32 @f(i32 %n) nounwind {
 entry:
 	br label %for.cond
 
@@ -13,9 +14,9 @@
 	br label %for.end
 
 for.body:		; preds = %for.cond
-	%tmp3 = load i32* %p		; <i32> [#uses=1]
+	%tmp3 = load i32* @p		; <i32> [#uses=1]
 	%dec = add i32 %tmp3, -1		; <i32> [#uses=2]
-	store i32 %dec, i32* %p
+	store i32 %dec, i32* @p
 	%cmp6 = icmp slt i32 %dec, 0		; <i1> [#uses=1]
 	br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc
 
@@ -27,6 +28,6 @@
 	br label %for.cond
 
 for.end:		; preds = %for.body.for.end_crit_edge, %for.cond.for.end_crit_edge
-	%tmp9 = load i32* %p		; <i32> [#uses=1]
+	%tmp9 = load i32* @p		; <i32> [#uses=1]
 	ret i32 %tmp9
 }





More information about the llvm-commits mailing list