When forming an addrec out of a phi don't just look at the last computation and steal...
authorNick Lewycky <nicholas@mxc.ca>
Fri, 13 Mar 2015 01:37:52 +0000 (01:37 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Fri, 13 Mar 2015 01:37:52 +0000 (01:37 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232134 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/trip-count.ll

index dcff7b60fb738703066b60b65cc314bb560bd6f8..dfef72968485d48990aa7c8fce053df62904bbeb 100644 (file)
@@ -3591,10 +3591,12 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
               // 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::createNodeForPHI(PHINode *PN) {
                 // 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());
index f705be60fada79271bb2b322b7da7773eeb94387..1b75c88c753c2662796d5e7af31080e9def5f97b 100644 (file)
@@ -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