[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