[llvm] r232134 - When forming an addrec out of a phi don't just look at the last computation and steal its flags for our own, there may be other computations in the middle. Check whether the LHS of the computation is the phi itself and then we know it's safe to steal the flags. Fixes PR22795.

Nick Lewycky nicholas at mxc.ca
Thu Mar 12 18:37:52 PDT 2015


Author: nicholas
Date: Thu Mar 12 20:37:52 2015
New Revision: 232134

URL: http://llvm.org/viewvc/llvm-project?rev=232134&view=rev
Log:
When forming an addrec out of a phi don't just look at the last computation and steal its flags for our own, there may be other computations in the middle. Check whether the LHS of the computation is the phi itself and then we know it's safe to steal the flags. Fixes PR22795.

There's a missed optimization opportunity where we could look at the full chain of computation and take the intersection of the flags instead of only looking one instruction deep.

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/test/Analysis/ScalarEvolution/trip-count.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=232134&r1=232133&r2=232134&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Mar 12 20:37:52 2015
@@ -3591,10 +3591,12 @@ const SCEV *ScalarEvolution::createNodeF
               // If the increment doesn't overflow, then neither the addrec nor
               // the post-increment will overflow.
               if (const AddOperator *OBO = dyn_cast<AddOperator>(BEValueV)) {
-                if (OBO->hasNoUnsignedWrap())
-                  Flags = setFlags(Flags, SCEV::FlagNUW);
-                if (OBO->hasNoSignedWrap())
-                  Flags = setFlags(Flags, SCEV::FlagNSW);
+                if (OBO->getOperand(0) == PN) {
+                  if (OBO->hasNoUnsignedWrap())
+                    Flags = setFlags(Flags, SCEV::FlagNUW);
+                  if (OBO->hasNoSignedWrap())
+                    Flags = setFlags(Flags, SCEV::FlagNSW);
+                }
               } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(BEValueV)) {
                 // If the increment is an inbounds GEP, then we know the address
                 // space cannot be wrapped around. We cannot make any guarantee
@@ -3602,7 +3604,7 @@ const SCEV *ScalarEvolution::createNodeF
                 // unsigned but we may have a negative index from the base
                 // pointer. We can guarantee that no unsigned wrap occurs if the
                 // indices form a positive value.
-                if (GEP->isInBounds()) {
+                if (GEP->isInBounds() && GEP->getOperand(0) == PN) {
                   Flags = setFlags(Flags, SCEV::FlagNW);
 
                   const SCEV *Ptr = getSCEV(GEP->getPointerOperand());

Modified: llvm/trunk/test/Analysis/ScalarEvolution/trip-count.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/trip-count.ll?rev=232134&r1=232133&r2=232134&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/trip-count.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/trip-count.ll Thu Mar 12 20:37:52 2015
@@ -1,11 +1,15 @@
 ; RUN: opt < %s -analyze -scalar-evolution -scalar-evolution-max-iterations=0 | FileCheck %s
 ; PR1101
 
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
 @A = weak global [1000 x i32] zeroinitializer, align 32         
 
+; CHECK: Printing analysis 'Scalar Evolution Analysis' for function 'test1':
 ; CHECK: backedge-taken count is 10000
 
-define void @test(i32 %N) {
+define void @test1(i32 %N) {
 entry:
         br label %bb3
 
@@ -26,3 +30,61 @@ bb5:            ; preds = %bb3
 return:         ; preds = %bb5
         ret void
 }
+
+; PR22795
+; CHECK: Printing analysis 'Scalar Evolution Analysis' for function 'test2':
+; CHECK:   %iv = phi i32 [ -1, %entry ], [ %next.1, %for.inc.1 ]
+; CHECK-NEXT:  -->  {-1,+,2}<%preheader> U: full-set S: full-set             Exits: 13
+
+define i32 @test2() {
+entry:
+  %bins = alloca [16 x i64], align 16
+  %0 = bitcast [16 x i64]* %bins to i8*
+  call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 128, i32 16, i1 false)
+  br label %preheader
+
+preheader:                                        ; preds = %for.inc.1, %entry
+  %v11 = phi i64 [ 0, %entry ], [ %next12.1, %for.inc.1 ]
+  %iv = phi i32 [ -1, %entry ], [ %next.1, %for.inc.1 ]
+  %cmp = icmp sgt i64 %v11, 0
+  br i1 %cmp, label %for.body, label %for.inc
+
+for.body:                                         ; preds = %preheader
+  %zext = zext i32 %iv to i64
+  %arrayidx = getelementptr [16 x i64], [16 x i64]* %bins, i64 0, i64 %v11
+  %loaded = load i64, i64* %arrayidx, align 8
+  %add = add i64 %loaded, 1
+  %add2 = add i64 %add, %zext
+  store i64 %add2, i64* %arrayidx, align 8
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %preheader
+  %next12 = add nuw nsw i64 %v11, 1
+  %next = add nsw i32 %iv, 1
+  br i1 true, label %for.body.1, label %for.inc.1
+
+end:                                              ; preds = %for.inc.1
+  %arrayidx8 = getelementptr [16 x i64], [16 x i64]* %bins, i64 0, i64 2
+  %load = load i64, i64* %arrayidx8, align 16
+  %shr4 = lshr i64 %load, 32
+  %conv = trunc i64 %shr4 to i32
+  ret i32 %conv
+
+for.body.1:                                       ; preds = %for.inc
+  %zext.1 = zext i32 %next to i64
+  %arrayidx.1 = getelementptr [16 x i64], [16 x i64]* %bins, i64 0, i64 %next12
+  %loaded.1 = load i64, i64* %arrayidx.1, align 8
+  %add.1 = add i64 %loaded.1, 1
+  %add2.1 = add i64 %add.1, %zext.1
+  store i64 %add2.1, i64* %arrayidx.1, align 8
+  br label %for.inc.1
+
+for.inc.1:                                        ; preds = %for.body.1, %for.inc
+  %next12.1 = add nuw nsw i64 %next12, 1
+  %next.1 = add nuw nsw i32 %next, 1
+  %exitcond.1 = icmp eq i64 %next12.1, 16
+  br i1 %exitcond.1, label %end, label %preheader
+}
+
+; Function Attrs: nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) #0





More information about the llvm-commits mailing list