[llvm] 290a939 - [SCEV] Handle nusw/nuw gep flags for addrecs

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 20 06:59:51 PDT 2024


Author: Nikita Popov
Date: 2024-06-20T15:59:42+02:00
New Revision: 290a939fc3a09b00fbda1dc655bb6373d878e18d

URL: https://github.com/llvm/llvm-project/commit/290a939fc3a09b00fbda1dc655bb6373d878e18d
DIFF: https://github.com/llvm/llvm-project/commit/290a939fc3a09b00fbda1dc655bb6373d878e18d.diff

LOG: [SCEV] Handle nusw/nuw gep flags for addrecs

Set the nw flag is gep has any nowrap flags. Transfer the nuw
flag. Also set nuw for the nusw + nneg combination.

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 8d90530906bb8..08cca6261f674 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -5882,15 +5882,17 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
               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
-          // about signed or unsigned overflow because pointers are
-          // 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() && GEP->getOperand(0) == PN) {
-            Flags = setFlags(Flags, SCEV::FlagNW);
-            if (isKnownPositive(Accum))
+          if (GEP->getOperand(0) == PN) {
+            GEPNoWrapFlags NW = GEP->getNoWrapFlags();
+            // If the increment has any nowrap flags, then we know the address
+            // space cannot be wrapped around.
+            if (NW != GEPNoWrapFlags::none())
+              Flags = setFlags(Flags, SCEV::FlagNW);
+            // If the GEP is nuw or nusw with non-negative offset, we know that
+            // no unsigned wrap occurs. We cannot set the nsw flag as only the
+            // offset is treated as signed, while the base is unsigned.
+            if (NW.hasNoUnsignedWrap() ||
+                (NW.hasNoUnsignedSignedWrap() && isKnownNonNegative(Accum)))
               Flags = setFlags(Flags, SCEV::FlagNUW);
           }
 

diff  --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
index a52352655cb92..593888f5f7bd5 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -2039,3 +2039,145 @@ define ptr @gep_nusw_nuw_missing_noundef(ptr %p, i64 %index) {
   %gep = getelementptr nusw nuw i32, ptr %p, i64 %index
   ret ptr %gep
 }
+
+define void @addrec_gep_inbounds_nneg(ptr %p, ptr %end) {
+; CHECK-LABEL: 'addrec_gep_inbounds_nneg'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_inbounds_nneg
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr inbounds i32, ptr %iv, i64 1
+; CHECK-NEXT:    --> {(4 + %p)<nuw>,+,4}<nuw><%loop> U: [4,0) S: [4,0) Exits: (4 + (4 * ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_inbounds_nneg
+; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 4611686018427387903
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr inbounds i32, ptr %iv, i64 1
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+define void @addrec_gep_inbounds_neg(ptr %p, ptr %end) {
+; CHECK-LABEL: 'addrec_gep_inbounds_neg'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_inbounds_neg
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,-4}<nw><%loop> U: full-set S: full-set Exits: ((-4 * ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)) + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr inbounds i32, ptr %iv, i64 -1
+; CHECK-NEXT:    --> {(-4 + %p),+,-4}<nw><%loop> U: full-set S: full-set Exits: (-4 + (-4 * ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)) + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_inbounds_neg
+; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 4611686018427387903
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr inbounds i32, ptr %iv, i64 -1
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+define void @addrec_gep_nusw_nneg(ptr %p, ptr %end) {
+; CHECK-LABEL: 'addrec_gep_nusw_nneg'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_nusw_nneg
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr nusw i32, ptr %iv, i64 1
+; CHECK-NEXT:    --> {(4 + %p)<nuw>,+,4}<nuw><%loop> U: [4,0) S: [4,0) Exits: (4 + (4 * ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_nusw_nneg
+; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 4611686018427387903
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %p to i64)) + (ptrtoint ptr %end to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr nusw i32, ptr %iv, i64 1
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+define void @addrec_gep_nusw_neg(ptr %p, ptr %end) {
+; CHECK-LABEL: 'addrec_gep_nusw_neg'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_nusw_neg
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,-4}<nw><%loop> U: full-set S: full-set Exits: ((-4 * ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)) + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr nusw i32, ptr %iv, i64 -1
+; CHECK-NEXT:    --> {(-4 + %p),+,-4}<nw><%loop> U: full-set S: full-set Exits: (-4 + (-4 * ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)) + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_nusw_neg
+; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 4611686018427387903
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is ((-4 + (-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %p to i64)) /u 4)
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr nusw i32, ptr %iv, i64 -1
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+define void @addrec_gep_nuw(ptr %p, ptr %end, i64 %step) {
+; CHECK-LABEL: 'addrec_gep_nuw'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_nuw
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,(4 * %step)<nuw>}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr nuw i32, ptr %iv, i64 %step
+; CHECK-NEXT:    --> {((4 * %step)<nuw> + %p)<nuw>,+,(4 * %step)<nuw>}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_nuw
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr nuw i32, ptr %iv, i64 %step
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+define void @addrec_gep_nusw_nuw(ptr %p, ptr %end, i64 %step) {
+; CHECK-LABEL: 'addrec_gep_nusw_nuw'
+; CHECK-NEXT:  Classifying expressions for: @addrec_gep_nusw_nuw
+; CHECK-NEXT:    %iv = phi ptr [ %p, %entry ], [ %iv.next, %loop ]
+; CHECK-NEXT:    --> {%p,+,(4 * %step)<nuw><nsw>}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = getelementptr nusw nuw i32, ptr %iv, i64 %step
+; CHECK-NEXT:    --> {((4 * %step)<nuw><nsw> + %p)<nuw>,+,(4 * %step)<nuw><nsw>}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_nusw_nuw
+; CHECK-NEXT:  Loop %loop: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %loop: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %loop
+loop:
+  %iv = phi ptr [ %p, %entry], [ %iv.next, %loop ]
+  %iv.next = getelementptr nusw nuw i32, ptr %iv, i64 %step
+  %cmp = icmp ne ptr %iv.next, %end
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list