[llvm] [SCEV] Propagate a recurrence's nuw flag to its exit value. (PR #217378)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 01:33:36 PDT 2026


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/217378

>From 4507da5907c99396b69b7338268d0b1a6deabf89 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 18 Aug 2026 21:39:15 +0100
Subject: [PATCH 1/2] [SCEV] Add more tests for

---
 .../exit-value-nowrap-flags.ll                | 324 +++++++++++++++
 .../IndVarSimplify/exit-value-nowrap-flags.ll | 379 ++++++++++++++++++
 2 files changed, 703 insertions(+)
 create mode 100644 llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
 create mode 100644 llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll

diff --git a/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll b/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
new file mode 100644
index 0000000000000..24e8fe5c163e7
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
@@ -0,0 +1,324 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s
+
+define void @dec_to_start_of_nuw_addrec(i64 %start) {
+; CHECK-LABEL: 'dec_to_start_of_nuw_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_addrec
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %x.next = add nuw i64 %x, 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<nw><%up> U: full-set S: full-set Exits: (10 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up ], [ %y.next, %down ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start),+,-1}<%down> U: full-set S: full-set Exits: (1 + ((8 + %start) umin %start)) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(8 + %start),+,-1}<%down> U: full-set S: full-set Exits: ((8 + %start) umin %start) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_addrec
+; CHECK-NEXT:  Loop %down: backedge-taken count is (8 + (-1 * ((8 + %start) umin %start)) + %start)
+; CHECK-NEXT:  Loop %down: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down: symbolic max backedge-taken count is (8 + (-1 * ((8 + %start) umin %start)) + %start)
+; CHECK-NEXT:  Loop %down: Trip multiple is 1
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  br label %up
+
+up:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %x.next = add nuw i64 %x, 1
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %down
+
+down:
+  %y = phi i64 [ %x, %up ], [ %y.next, %down ]
+  %y.next = add i64 %y, -1
+  %ec = icmp ugt i64 %y.next, %start
+  br i1 %ec, label %down, label %exit
+
+exit:
+  ret void
+}
+
+define void @dec_to_start_of_nuw_ptr_addrec(ptr %start) {
+; CHECK-LABEL: 'dec_to_start_of_nuw_ptr_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_ptr_addrec
+; CHECK-NEXT:    %p = phi ptr [ %start, %entry ], [ %p.next, %up ]
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %p.next = getelementptr nuw i8, ptr %p, i64 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<nw><%up> U: full-set S: full-set Exits: (10 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %q = phi ptr [ %p, %up ], [ %q.next, %down ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start),+,-1}<%down> U: full-set S: full-set Exits: (1 + (-1 * (ptrtoaddr ptr %start to i64)) + ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:    %q.next = getelementptr i8, ptr %q, i64 -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(8 + %start),+,-1}<%down> U: full-set S: full-set Exits: ((-1 * (ptrtoaddr ptr %start to i64)) + ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_ptr_addrec
+; CHECK-NEXT:  Loop %down: backedge-taken count is (8 + (-1 * ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64))) + (ptrtoaddr ptr %start to i64))
+; CHECK-NEXT:  Loop %down: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down: symbolic max backedge-taken count is (8 + (-1 * ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64))) + (ptrtoaddr ptr %start to i64))
+; CHECK-NEXT:  Loop %down: Trip multiple is 1
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  br label %up
+
+up:
+  %p = phi ptr [ %start, %entry ], [ %p.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %p.next = getelementptr nuw i8, ptr %p, i64 1
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %down
+
+down:
+  %q = phi ptr [ %p, %up ], [ %q.next, %down ]
+  %q.next = getelementptr i8, ptr %q, i64 -1
+  %ec = icmp ugt ptr %q.next, %start
+  br i1 %ec, label %down, label %exit
+
+exit:
+  ret void
+}
+
+define void @dec_to_start_of_wrapping_addrec(i64 %start) {
+; CHECK-LABEL: 'dec_to_start_of_wrapping_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_wrapping_addrec
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+; CHECK-NEXT:    --> {%start,+,1}<nw><%up> U: full-set S: full-set Exits: (9 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %x.next = add i64 %x, 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<nw><%up> U: full-set S: full-set Exits: (10 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up ], [ %y.next, %down ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start),+,-1}<%down> U: full-set S: full-set Exits: (1 + ((8 + %start) umin %start)) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(8 + %start),+,-1}<%down> U: full-set S: full-set Exits: ((8 + %start) umin %start) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_wrapping_addrec
+; CHECK-NEXT:  Loop %down: backedge-taken count is (8 + (-1 * ((8 + %start) umin %start)) + %start)
+; CHECK-NEXT:  Loop %down: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down: symbolic max backedge-taken count is (8 + (-1 * ((8 + %start) umin %start)) + %start)
+; CHECK-NEXT:  Loop %down: Trip multiple is 1
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  br label %up
+
+up:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %x.next = add i64 %x, 1
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %down
+
+down:
+  %y = phi i64 [ %x, %up ], [ %y.next, %down ]
+  %y.next = add i64 %y, -1
+  %ec = icmp ugt i64 %y.next, %start
+  br i1 %ec, label %down, label %exit
+
+exit:
+  ret void
+}
+
+; Both %start and %step are known non-negative.
+define void @exit_value_nsw_nonneg(i64 %start.raw, i64 %step.raw) {
+; CHECK-LABEL: 'exit_value_nsw_nonneg'
+; CHECK-NEXT:  Classifying expressions for: @exit_value_nsw_nonneg
+; CHECK-NEXT:    %start = and i64 %start.raw, 255
+; CHECK-NEXT:    --> (zext i8 (trunc i64 %start.raw to i8) to i64) U: [0,256) S: [0,256)
+; CHECK-NEXT:    %step = and i64 %step.raw, 7
+; CHECK-NEXT:    --> (zext i3 (trunc i64 %step.raw to i3) to i64) U: [0,8) S: [0,8)
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+; CHECK-NEXT:    --> {(zext i8 (trunc i64 %start.raw to i8) to i64),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nuw><nsw><%up> U: [0,319) S: [0,319) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (9 * (zext i3 (trunc i64 %step.raw to i3) to i64))<nuw><nsw>) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {((zext i3 (trunc i64 %step.raw to i3) to i64) + (zext i8 (trunc i64 %start.raw to i8) to i64)),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nw><%up> U: [0,326) S: [0,326) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (10 * (zext i3 (trunc i64 %step.raw to i3) to i64))<nuw><nsw>) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @exit_value_nsw_nonneg
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  %start = and i64 %start.raw, 255
+  %step = and i64 %step.raw, 7
+  br label %up
+up:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %x.next = add nsw i64 %x, %step
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %exit
+exit:
+  ret void
+}
+
+; The other half: both %start and %step known non-positive.
+define void @exit_value_nsw_nonpos(i64 %start.raw, i64 %step.raw) {
+; CHECK-LABEL: 'exit_value_nsw_nonpos'
+; CHECK-NEXT:  Classifying expressions for: @exit_value_nsw_nonpos
+; CHECK-NEXT:    %start = or i64 %start.raw, -256
+; CHECK-NEXT:    --> %start U: [-256,0) S: [-256,0)
+; CHECK-NEXT:    %step = or i64 %step.raw, -8
+; CHECK-NEXT:    --> %step U: [-8,0) S: [-8,0)
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+; CHECK-NEXT:    --> {%start,+,%step}<nsw><%up> U: [-328,0) S: [-328,0) Exits: ((9 * %step)<nsw> + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {(%start + %step),+,%step}<nw><%up> U: [-336,-1) S: [-336,-1) Exits: ((10 * %step)<nsw> + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @exit_value_nsw_nonpos
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  %start = or i64 %start.raw, -256
+  %step = or i64 %step.raw, -8
+  br label %up
+up:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %x.next = add nsw i64 %x, %step
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %exit
+exit:
+  ret void
+}
+
+; %start is non-negative and %step is non-positive, so Step * It is not bounded
+; by the recurrence's own range and nsw must not carry over. For example
+; i8 {-100,+,50} is nsw for four iterations while 4 * 50 = 200 is not representable.
+define void @exit_value_nsw_mixed_signs(i64 %start.raw, i64 %step.raw) {
+; CHECK-LABEL: 'exit_value_nsw_mixed_signs'
+; CHECK-NEXT:  Classifying expressions for: @exit_value_nsw_mixed_signs
+; CHECK-NEXT:    %start = and i64 %start.raw, 255
+; CHECK-NEXT:    --> (zext i8 (trunc i64 %start.raw to i8) to i64) U: [0,256) S: [0,256)
+; CHECK-NEXT:    %step = or i64 %step.raw, -8
+; CHECK-NEXT:    --> %step U: [-8,0) S: [-8,0)
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+; CHECK-NEXT:    --> {(zext i8 (trunc i64 %start.raw to i8) to i64),+,%step}<nsw><%up> U: [-72,256) S: [-72,256) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (9 * %step)<nsw>) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {((zext i8 (trunc i64 %start.raw to i8) to i64) + %step),+,%step}<nw><%up> U: [-80,255) S: [-80,255) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (10 * %step)<nsw>) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    %i.next = add i32 %i, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @exit_value_nsw_mixed_signs
+; CHECK-NEXT:  Loop %up: backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: constant max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: symbolic max backedge-taken count is i32 9
+; CHECK-NEXT:  Loop %up: Trip multiple is 10
+;
+entry:
+  %start = and i64 %start.raw, 255
+  %step = or i64 %step.raw, -8
+  br label %up
+up:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
+  %x.next = add nsw i64 %x, %step
+  %i.next = add i32 %i, 1
+  %c = icmp ult i32 %i.next, 10
+  br i1 %c, label %up, label %exit
+exit:
+  ret void
+}
+
+define void @exit_value_nsw_count_is_smin(i8 %t) {
+; CHECK-LABEL: 'exit_value_nsw_count_is_smin'
+; CHECK-NEXT:  Classifying expressions for: @exit_value_nsw_count_is_smin
+; CHECK-NEXT:    %s = or i8 %t, -128
+; CHECK-NEXT:    --> %s U: [-128,0) S: [-128,0)
+; CHECK-NEXT:    %iv = phi i8 [ 0, %entry ], [ %iv.next, %latch ]
+; CHECK-NEXT:    --> {0,+,%s}<nsw><%loop> U: [-128,1) S: [-128,1) Exits: (-128 * %s) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %j = phi i8 [ 0, %entry ], [ %j.next, %latch ]
+; CHECK-NEXT:    --> {0,+,1}<nuw><%loop> U: [0,-127) S: [0,-127) Exits: -128 LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %iv.next = add nsw i8 %iv, %s
+; CHECK-NEXT:    --> {%s,+,%s}<nw><%loop> U: full-set S: full-set Exits: (-127 * %s) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %j.next = add nuw i8 %j, 1
+; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,-126) S: [1,-126) Exits: -127 LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @exit_value_nsw_count_is_smin
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i8 -128
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i8 -128
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i8 -128
+; CHECK-NEXT:  Loop %loop: Trip multiple is 129
+;
+entry:
+  %s = or i8 %t, -128
+  br label %loop
+
+loop:
+  %iv = phi i8 [ 0, %entry ], [ %iv.next, %latch ]
+  %j = phi i8 [ 0, %entry ], [ %j.next, %latch ]
+  %ec = icmp eq i8 %j, -128
+  br i1 %ec, label %exit, label %latch
+
+latch:
+  %iv.next = add nsw i8 %iv, %s
+  %j.next = add nuw i8 %j, 1
+  br label %loop
+
+exit:
+  ret void
+}
+
+define ptr @exit_value_mul_drops_nuw(ptr %first, ptr %last) {
+; CHECK-LABEL: 'exit_value_mul_drops_nuw'
+; CHECK-NEXT:  Classifying expressions for: @exit_value_mul_drops_nuw
+; CHECK-NEXT:    %p = phi ptr [ %first, %entry ], [ %p.next, %loop ]
+; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set Exits: ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %p.next = getelementptr inbounds nuw i8, ptr %p, i64 24
+; CHECK-NEXT:    --> {(24 + %first),+,24}<nuw><%loop> U: full-set S: full-set Exits: (24 + (24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %lc = phi ptr [ %p, %loop ]
+; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set --> ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) U: full-set S: full-set
+; CHECK-NEXT:  Determining loop execution counts for: @exit_value_mul_drops_nuw
+; CHECK-NEXT:  Loop %loop: backedge-taken count is (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 768614336404564650
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  %c0 = icmp ult ptr %first, %last
+  br i1 %c0, label %loop, label %done
+
+loop:
+  %p = phi ptr [ %first, %entry ], [ %p.next, %loop ]
+  %p.next = getelementptr inbounds nuw i8, ptr %p, i64 24
+  %c = icmp ult ptr %p.next, %last
+  br i1 %c, label %loop, label %exit
+
+exit:
+  %lc = phi ptr [ %p, %loop ]
+  ret ptr %lc
+
+done:
+  ret ptr %first
+}
diff --git a/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll b/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll
new file mode 100644
index 0000000000000..fca16b8cfecb5
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll
@@ -0,0 +1,379 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=indvars -S %s | FileCheck %s
+
+target datalayout = "n8:16:32:64"
+
+define i32 @nuw_kept(i32 %start, i32 %step, i32 %n) {
+; CHECK-LABEL: define i32 @nuw_kept(
+; CHECK-SAME: i32 [[START:%.*]], i32 [[STEP:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LATCH:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[STEP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[START]], [[TMP0]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  br label %loop
+
+loop:
+  %v = phi i32 [ %start, %entry ], [ %v.next, %latch ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit, label %latch
+
+latch:
+  %v.next = add nuw i32 %v, %step
+  %i.next = add i32 %i, 1
+  br label %loop
+
+exit:
+  ret i32 %v
+}
+
+; Signed recurrence with %start and %step are both known non-negative.
+define i32 @nsw_kept_same_sign(i32 %start.in, i32 %step.in, i32 %n) {
+; CHECK-LABEL: define i32 @nsw_kept_same_sign(
+; CHECK-SAME: i32 [[START_IN:%.*]], i32 [[STEP_IN:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[START:%.*]] = and i32 [[START_IN]], 1023
+; CHECK-NEXT:    [[STEP:%.*]] = and i32 [[STEP_IN]], 1023
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LATCH:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[STEP]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], [[START]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  %start = and i32 %start.in, 1023
+  %step = and i32 %step.in, 1023
+  br label %loop
+
+loop:
+  %v = phi i32 [ %start, %entry ], [ %v.next, %latch ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit, label %latch
+
+latch:
+  %v.next = add nsw i32 %v, %step
+  %i.next = add i32 %i, 1
+  br label %loop
+
+exit:
+  ret i32 %v
+}
+
+; Start is non-negative but Step is negative.
+define i32 @nsw_dropped_mixed_signs(i32 %start.in, i32 %step.in, i32 %n) {
+; CHECK-LABEL: define i32 @nsw_dropped_mixed_signs(
+; CHECK-SAME: i32 [[START_IN:%.*]], i32 [[STEP_IN:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[START:%.*]] = and i32 [[START_IN]], 1023
+; CHECK-NEXT:    [[STEP_POS:%.*]] = and i32 [[STEP_IN]], 1023
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LATCH:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[STEP_POS]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[START]], [[TMP0]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  %start = and i32 %start.in, 1023
+  %step.pos = and i32 %step.in, 1023
+  %step = sub nsw i32 0, %step.pos
+  br label %loop
+
+loop:
+  %v = phi i32 [ %start, %entry ], [ %v.next, %latch ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit, label %latch
+
+latch:
+  %v.next = add nsw i32 %v, %step
+  %i.next = add i32 %i, 1
+  br label %loop
+
+exit:
+  ret i32 %v
+}
+
+; The exit count is (-1 + %n) and Start is 0, so the sum folds away completely.
+define i32 @nuw_dropped_sum_folded_away(i32 %n) {
+; CHECK-LABEL: define i32 @nuw_dropped_sum_folded_away(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
+; CHECK-NEXT:    ret i32 [[TMP0]]
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add nuw i32 %i, 1
+  %c = icmp eq i32 %i.next, %n
+  br i1 %c, label %exit, label %loop
+
+exit:
+  ret i32 %i
+}
+
+; Start is a sum, so computing the exit value inlines it into %start + BTC.
+define i32 @nuw_dropped_sum_flattened(i32 %a, i32 %b, i32 %n) {
+; CHECK-LABEL: define i32 @nuw_dropped_sum_flattened(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LATCH:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], [[A]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  %start = add i32 %a, %b
+  br label %loop
+
+loop:
+  %v = phi i32 [ %start, %entry ], [ %v.next, %latch ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit, label %latch
+
+latch:
+  %v.next = add nuw i32 %v, 1
+  %i.next = add i32 %i, 1
+  br label %loop
+
+exit:
+  ret i32 %v
+}
+
+; Step is a product, so computing the exit value inlines it into BTC * Step.
+define i32 @nuw_dropped_product_flattened(i32 %s1, i32 %s2, i32 %n) {
+; CHECK-LABEL: define i32 @nuw_dropped_product_flattened(
+; CHECK-SAME: i32 [[S1:%.*]], i32 [[S2:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[LATCH:.*]]
+; CHECK:       [[LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[S2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[TMP0]], [[S1]]
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  %step = mul i32 %s1, %s2
+  br label %loop
+
+loop:
+  %v = phi i32 [ 0, %entry ], [ %v.next, %latch ]
+  %i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit, label %latch
+
+latch:
+  %v.next = add nuw i32 %v, %step
+  %i.next = add i32 %i, 1
+  br label %loop
+
+exit:
+  ret i32 %v
+}
+
+ at A = external global i32
+
+; LFTR computes the limit for one exit of a multi-exit loop. %n is the count for
+; the latch exit alone; the loop can leave through the %iv2 == 20 exit first, so
+; that iteration is not necessarily reached.
+define void @lftr_limit_multi_exit(i32 %n) {
+; CHECK-LABEL: define void @lftr_limit_multi_exit(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT:    br label %[[OUTER:.*]]
+; CHECK:       [[OUTER]]:
+; CHECK-NEXT:    [[IV1:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV1_NEXT:%.*]], %[[OUTER_LATCH:.*]] ]
+; CHECK-NEXT:    store volatile i32 [[IV1]], ptr @A, align 4
+; CHECK-NEXT:    [[IV1_NEXT]] = add nuw nsw i32 [[IV1]], 1
+; CHECK-NEXT:    br label %[[INNER_HEADER:.*]]
+; CHECK:       [[INNER_HEADER]]:
+; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, %[[OUTER]] ], [ [[IV2_NEXT:%.*]], %[[INNER_LATCH:.*]] ]
+; CHECK-NEXT:    store volatile i32 [[IV2]], ptr @A, align 4
+; CHECK-NEXT:    [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], 20
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[INNER_LATCH]], label %[[EXIT_LOOPEXIT:.*]]
+; CHECK:       [[INNER_LATCH]]:
+; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp ne i32 [[IV2_NEXT]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[EXITCOND2]], label %[[INNER_HEADER]], label %[[OUTER_LATCH]]
+; CHECK:       [[OUTER_LATCH]]:
+; CHECK-NEXT:    [[EXITCOND3:%.*]] = icmp ne i32 [[IV1_NEXT]], 21
+; CHECK-NEXT:    br i1 [[EXITCOND3]], label %[[OUTER]], label %[[EXIT_LOOPEXIT1:.*]]
+; CHECK:       [[EXIT_LOOPEXIT]]:
+; CHECK-NEXT:    br label %[[EXIT:.*]]
+; CHECK:       [[EXIT_LOOPEXIT1]]:
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer.header
+
+outer.header:
+  %iv1 = phi i32 [ 0, %entry ], [ %iv1.next, %outer.latch ]
+  store volatile i32 %iv1, ptr @A
+  %iv1.next = add i32 %iv1, 1
+  br label %inner.header
+
+inner.header:
+  %iv2 = phi i32 [ 0, %outer.header ], [ %iv2.next, %inner.latch ]
+  store volatile i32 %iv2, ptr @A
+  %iv2.next = add i32 %iv2, 1
+  %inner.ec.1 = icmp ult i32 %iv2, 20
+  br i1 %inner.ec.1, label %inner.latch, label %exit
+
+inner.latch:
+  %inner.ec.2 = icmp ult i32 %iv2, %n
+  br i1 %inner.ec.2, label %inner.header, label %outer.latch
+
+outer.latch:
+  %outertest = icmp ult i32 %iv1, 20
+  br i1 %outertest, label %outer.header, label %exit
+
+exit:
+  ret void
+}
+
+define i32 @no_flag_leak_through_shared_udiv(i32 %start, i32 %n, i1 %c) {
+; CHECK-LABEL: define i32 @no_flag_leak_through_shared_udiv(
+; CHECK-SAME: i32 [[START:%.*]], i32 [[N:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[C]], label %[[PH_1:.*]], label %[[PH_2:.*]]
+; CHECK:       [[PH_1]]:
+; CHECK-NEXT:    br label %[[LOOP_1_HEADER:.*]]
+; CHECK:       [[LOOP_1_HEADER]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT_1:.*]], label %[[LOOP_1_LATCH:.*]]
+; CHECK:       [[LOOP_1_LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP_1_HEADER]]
+; CHECK:       [[EXIT_1]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], [[START]]
+; CHECK-NEXT:    [[TMP1:%.*]] = udiv i32 [[TMP0]], 3
+; CHECK-NEXT:    ret i32 [[TMP1]]
+; CHECK:       [[PH_2]]:
+; CHECK-NEXT:    br label %[[LOOP_2_HEADER:.*]]
+; CHECK:       [[LOOP_2_HEADER]]:
+; CHECK-NEXT:    br i1 true, label %[[EXIT_2:.*]], label %[[LOOP_2_LATCH:.*]]
+; CHECK:       [[LOOP_2_LATCH]]:
+; CHECK-NEXT:    br label %[[LOOP_2_HEADER]]
+; CHECK:       [[EXIT_2]]:
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[N]], [[START]]
+; CHECK-NEXT:    [[TMP3:%.*]] = udiv i32 [[TMP2]], 3
+; CHECK-NEXT:    ret i32 [[TMP3]]
+;
+entry:
+  br i1 %c, label %ph.1, label %ph.2
+
+ph.1:
+  br label %loop.1.header
+
+loop.1.header:
+  %v = phi i32 [ %start, %ph.1 ], [ %v.next, %loop.1.latch ]
+  %i = phi i32 [ 0, %ph.1 ], [ %i.next, %loop.1.latch ]
+  %dv = udiv i32 %v, 3
+  %done = icmp eq i32 %i, %n
+  br i1 %done, label %exit.1, label %loop.1.latch
+
+loop.1.latch:
+  %v.next = add i32 %v, 1
+  %i.next = add i32 %i, 1
+  br label %loop.1.header
+
+exit.1:
+  ret i32 %dv
+
+ph.2:
+  br label %loop.2.header
+
+loop.2.header:
+  %v2 = phi i32 [ %start, %ph.2 ], [ %v2.next, %loop.2.latch ]
+  %i2 = phi i32 [ 0, %ph.2 ], [ %i2.next, %loop.2.latch ]
+  %dv2 = udiv i32 %v2, 3
+  %done2 = icmp eq i32 %i2, %n
+  br i1 %done2, label %exit.2, label %loop.2.latch
+
+loop.2.latch:
+  %v2.next = add nuw i32 %v2, 1
+  %i2.next = add i32 %i2, 1
+  br label %loop.2.header
+
+exit.2:
+  ret i32 %dv2
+}
+
+
+define ptr @exit_value_mul(ptr %first, ptr %last) {
+; CHECK-LABEL: define ptr @exit_value_mul(
+; CHECK-SAME: ptr [[FIRST:%.*]], ptr [[LAST:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[FIRST2:%.*]] = ptrtoaddr ptr [[FIRST]] to i64
+; CHECK-NEXT:    [[LAST1:%.*]] = ptrtoaddr ptr [[LAST]] to i64
+; CHECK-NEXT:    [[C0:%.*]] = icmp ult ptr [[FIRST]], [[LAST]]
+; CHECK-NEXT:    br i1 [[C0]], label %[[LOOP_PREHEADER:.*]], label %[[DONE:.*]]
+; CHECK:       [[LOOP_PREHEADER]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[FIRST2]], 24
+; CHECK-NEXT:    [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[LAST1]], i64 [[TMP0]])
+; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[UMAX]], -24
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[TMP1]], [[FIRST2]]
+; CHECK-NEXT:    [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 1)
+; CHECK-NEXT:    [[TMP3:%.*]] = sub i64 [[TMP2]], [[UMIN]]
+; CHECK-NEXT:    [[TMP4:%.*]] = udiv i64 [[TMP3]], 24
+; CHECK-NEXT:    [[TMP5:%.*]] = add i64 [[UMIN]], [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = mul i64 [[TMP5]], 24
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP6]]
+; CHECK-NEXT:    ret ptr [[SCEVGEP]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret ptr [[FIRST]]
+;
+entry:
+  %c0 = icmp ult ptr %first, %last
+  br i1 %c0, label %loop, label %done
+
+loop:
+  %p = phi ptr [ %first, %entry ], [ %p.next, %loop ]
+  %p.next = getelementptr inbounds nuw i8, ptr %p, i64 24
+  %c = icmp ult ptr %p.next, %last
+  br i1 %c, label %loop, label %exit
+
+exit:
+  %lc = phi ptr [ %p, %loop ]
+  ret ptr %lc
+
+done:
+  ret ptr %first
+}

>From 455cf109e20a7058e92d4a2c73b4235dc084cc57 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 19 Aug 2026 10:26:12 +0100
Subject: [PATCH 2/2] [SCEV] Propagate a recurrence's nuw flag to its exit
 value.

A recurrence's exit value is its closed form Start + BTC * Step. The sum does
not wrap, if the recurrence does not wrap: the recurrence reached iteration BTC,
so the value it computes there is the value the recurrence had, and that did not wrap.

The flags are attached to the returned use, because they only apply to
this specific expression we evaluated for the exit value, no other,
equivalent SCEVs.

Alive2 Proof: https://alive2.llvm.org/ce/z/0vSRq-

This on its own has small impact on real world code (only retained some
additional flags in most cases):
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/962, but is
the first end-to-end use of SCEVUse.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h  |  11 +-
 .../Analysis/ScalarEvolutionExpressions.h     |  12 ++-
 llvm/lib/Analysis/ScalarEvolution.cpp         | 100 ++++++++++++------
 llvm/lib/Transforms/Utils/LoopUtils.cpp       |   8 +-
 .../ScalarEvolution/different-loops-recs.ll   |   2 +-
 .../exit-value-nowrap-flags.ll                |  14 +--
 .../flags-from-poison-noautogen.ll            |   4 +-
 .../ScalarEvolution/flags-from-poison.ll      |   4 +-
 .../increasing-or-decreasing-iv.ll            |   2 +-
 .../ScalarEvolution/infer-prestart-no-wrap.ll |   2 +-
 ...ge-taken-count-guard-info-operand-order.ll |  24 ++---
 ...en-count-guard-info-rewrite-expressions.ll |  24 ++---
 .../max-backedge-taken-count-guard-info.ll    |  30 +++---
 .../ScalarEvolution/nsw-offset-assume.ll      |   8 +-
 .../Analysis/ScalarEvolution/nsw-offset.ll    |   8 +-
 llvm/test/Analysis/ScalarEvolution/nsw.ll     |  10 +-
 .../ptrtoint-special-pointers.ll              |   2 +-
 .../test/Analysis/ScalarEvolution/ptrtoint.ll |   6 +-
 llvm/test/Analysis/ScalarEvolution/ranges.ll  |  10 +-
 llvm/test/Analysis/ScalarEvolution/sdiv.ll    |   2 +-
 .../ScalarEvolution/sext-add-inreg-loop.ll    |   2 +-
 llvm/test/Analysis/ScalarEvolution/srem.ll    |   2 +-
 .../trip-count-scalable-stride.ll             |  12 +--
 .../Analysis/ScalarEvolution/trip-count15.ll  |   9 ++
 .../IndVarSimplify/exit-value-nowrap-flags.ll |   8 +-
 25 files changed, 187 insertions(+), 129 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index b162036ffb46d..b3827aa8acc38 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -963,10 +963,13 @@ class ScalarEvolution {
   ///
   /// In the case that a relevant loop exit value cannot be computed, the
   /// original value V is returned.
-  LLVM_ABI const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L);
+  ///
+  /// The result may carry use-specific no-wrap flags. Those hold only in
+  /// contexts reached via \p L's exit.
+  LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L);
 
   /// This is a convenience function which does getSCEVAtScope(getSCEV(V), L).
-  LLVM_ABI const SCEV *getSCEVAtScope(Value *V, const Loop *L);
+  LLVM_ABI SCEVUse getSCEVAtScope(Value *V, const Loop *L);
 
   /// Test whether entry to the loop is protected by a conditional between LHS
   /// and RHS.  This is used to help avoid max expressions in loop trip
@@ -1924,7 +1927,7 @@ class ScalarEvolution {
   /// This map contains entries for all the expressions that we attempt to
   /// compute getSCEVAtScope information for, which can be expensive in
   /// extreme cases.
-  DenseMap<const SCEV *, SmallVector<std::pair<const Loop *, const SCEV *>, 2>>
+  DenseMap<const SCEV *, SmallVector<std::pair<const Loop *, SCEVUse>, 2>>
       ValuesAtScopes;
 
   /// Reverse map for invalidation purposes: Stores of which SCEV and which
@@ -2086,7 +2089,7 @@ class ScalarEvolution {
 
   /// Implementation code for getSCEVAtScope; called at most once for each
   /// SCEV+Loop pair.
-  const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L);
+  SCEVUse computeSCEVAtScope(const SCEV *S, const Loop *L);
 
   /// Return the BackedgeTakenInfo for the given loop, lazily computing new
   /// values if the loop hasn't been analyzed yet. The returned result is
diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 63c822d0c7c20..277f445b93a81 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -382,9 +382,15 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
 
   /// Return the value of this chain of recurrences at the specified iteration
   /// number. Takes an explicit list of operands to represent an AddRec.
-  LLVM_ABI static const SCEV *evaluateAtIteration(ArrayRef<SCEVUse> Operands,
-                                                  const SCEV *It,
-                                                  ScalarEvolution &SE);
+  LLVM_ABI static SCEVUse
+  evaluateAtIteration(ArrayRef<SCEVUse> Operands, const SCEV *It,
+                      ScalarEvolution &SE,
+                      SCEV::NoWrapFlags UseFlags = SCEV::FlagAnyWrap);
+
+  /// Return the value of this recurrences when its loop exits, i.e. its value
+  /// at the loop's exact backedge-taken count, or SCEVCouldNotCompute if that
+  /// count cannot be computed.
+  LLVM_ABI SCEVUse getExitValue(ScalarEvolution &SE) const;
 
   /// Return the number of iterations of this loop that produce
   /// values in the specified constant range.  Another way of
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 6b0951491a88a..46b89d71dd726 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -970,6 +970,27 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
                        SE.getTruncateOrZeroExtend(DivResult, ResultTy));
 }
 
+/// Attach \p UseFlags to \p Res as use-specific flags, but only if \p Res
+/// really is the two-operand \p ExprT over \p LHS and \p RHS - in either order,
+/// as operands get sorted by complexity.
+///
+/// Flags established for that operation say nothing about any other expression:
+/// a folded-away operand, a flattened nested expression or a distributed
+/// constant all give a different computation. They must not be attached to it,
+/// because an n-ary expression's no-wrap flags have to hold for all subsets and
+/// orders of its operands, and SCEVExpander relies on that when it stamps them
+/// on every partial sum or product it builds.
+template <typename ExprT>
+static SCEVUse withUseFlagsIfNotFolded(const SCEV *Res, SCEVUse LHS,
+                                       SCEVUse RHS,
+                                       SCEV::NoWrapFlags UseFlags) {
+  auto *E = dyn_cast<ExprT>(Res);
+  if (E && (equal(E->operands(), ArrayRef<SCEVUse>({LHS, RHS})) ||
+            equal(E->operands(), ArrayRef<SCEVUse>({RHS, LHS}))))
+    return {Res, UseFlags};
+  return Res;
+}
+
 /// Return the value of this chain of recurrences at the specified iteration
 /// number.  We can evaluate this recurrence by multiplying each element in the
 /// chain by the binomial coefficient corresponding to it.  In other words, we
@@ -983,11 +1004,13 @@ const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It,
   return evaluateAtIteration(operands(), It, SE);
 }
 
-const SCEV *SCEVAddRecExpr::evaluateAtIteration(ArrayRef<SCEVUse> Operands,
-                                                const SCEV *It,
-                                                ScalarEvolution &SE) {
+SCEVUse SCEVAddRecExpr::evaluateAtIteration(ArrayRef<SCEVUse> Operands,
+                                            const SCEV *It, ScalarEvolution &SE,
+                                            SCEV::NoWrapFlags UseFlags) {
   assert(Operands.size() > 0);
-  const SCEV *Result = Operands[0].getPointer();
+  assert((Operands.size() == 2 || UseFlags == SCEV::FlagAnyWrap) &&
+         "use-specific flags only supported for affine AddRecs");
+  SCEVUse Result = Operands[0].getPointer();
   for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
     // The computation is correct in the face of overflow provided that the
     // multiplication is performed _after_ the evaluation of the binomial
@@ -996,12 +1019,24 @@ const SCEV *SCEVAddRecExpr::evaluateAtIteration(ArrayRef<SCEVUse> Operands,
     if (isa<SCEVCouldNotCompute>(Coeff))
       return Coeff;
 
-    Result =
-        SE.getAddExpr(Result, SE.getMulExpr(Operands[i].getPointer(), Coeff));
+    const SCEV *Mul = SE.getMulExpr(Operands[i].getPointer(), Coeff);
+    Result = withUseFlagsIfNotFolded<SCEVAddExpr>(SE.getAddExpr(Result, Mul),
+                                                  Result, Mul, UseFlags);
   }
   return Result;
 }
 
+SCEVUse SCEVAddRecExpr::getExitValue(ScalarEvolution &SE) const {
+  const SCEV *BTC = SE.getBackedgeTakenCount(getLoop());
+  if (isa<SCEVCouldNotCompute>(BTC))
+    return BTC;
+  // The loop reaches iteration BTC, so the value this recurrence computes there
+  // is the value it had, and that did not wrap.
+  return evaluateAtIteration(operands(), BTC, SE,
+                             isAffine() ? getNoWrapFlags(SCEV::FlagNUW)
+                                        : SCEV::FlagAnyWrap);
+}
+
 //===----------------------------------------------------------------------===//
 //                    SCEV Expression folder implementations
 //===----------------------------------------------------------------------===//
@@ -10047,23 +10082,25 @@ const SCEV *ScalarEvolution::computeExitCountExhaustively(const Loop *L,
   return getCouldNotCompute();
 }
 
-const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
-  SmallVector<std::pair<const Loop *, const SCEV *>, 2> &Values =
-      ValuesAtScopes[V];
+SCEVUse ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
+  auto &Values = ValuesAtScopes[V];
   // Check to see if we've folded this expression at this loop before.
   for (auto &LS : Values)
     if (LS.first == L)
-      return LS.second ? LS.second : V;
+      return LS.second ? LS.second : SCEVUse(V);
 
   Values.emplace_back(L, nullptr);
 
   // Otherwise compute it.
-  const SCEV *C = computeSCEVAtScope(V, L);
+  SCEVUse C = computeSCEVAtScope(V, L);
   for (auto &LS : reverse(ValuesAtScopes[V]))
     if (LS.first == L) {
       LS.second = C;
+      // Record the dependency under the bare expression: invalidation walks
+      // expressions, and any use flags on C do not change which expression
+      // this is the value at scope of.
       if (!isa<SCEVConstant>(C))
-        ValuesAtScopesUsers[C].push_back({L, V});
+        ValuesAtScopesUsers[C.getPointer()].push_back({L, V});
       break;
     }
   return C;
@@ -10168,7 +10205,7 @@ const SCEV *ScalarEvolution::getWithOperands(const SCEV *S,
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
+SCEVUse ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
   switch (V->getSCEVType()) {
   case scConstant:
   case scVScale:
@@ -10181,8 +10218,8 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     // Avoid performing the look-up in the common case where the specified
     // expression has no loop-variant portions.
     for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
-      const SCEV *OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L);
-      if (OpAtScope == AddRec->getOperand(i))
+      SCEVUse OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L);
+      if (OpAtScope == AddRec->getOperand(i).getPointer())
         continue;
 
       // Okay, at least one of these operands is loop variant but might be
@@ -10208,14 +10245,10 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     // If the scope is outside the addrec's loop, evaluate it by using the
     // loop exit value of the addrec.
     if (!AddRec->getLoop()->contains(L)) {
-      // To evaluate this recurrence, we need to know how many times the AddRec
-      // loop iterates.  Compute this now.
-      const SCEV *BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop());
-      if (BackedgeTakenCount == getCouldNotCompute())
+      SCEVUse ExitValue = AddRec->getExitValue(*this);
+      if (isa<SCEVCouldNotCompute>(ExitValue))
         return AddRec;
-
-      // Then, evaluate the AddRec.
-      return AddRec->evaluateAtIteration(BackedgeTakenCount, *this);
+      return ExitValue;
     }
 
     return AddRec;
@@ -10236,7 +10269,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     // Avoid performing the look-up in the common case where the specified
     // expression has no loop-variant portions.
     for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
-      const SCEV *OpAtScope = getSCEVAtScope(Ops[i].getPointer(), L);
+      SCEVUse OpAtScope = getSCEVAtScope(Ops[i].getPointer(), L);
       if (OpAtScope != Ops[i].getPointer()) {
         // Okay, at least one of these operands is loop variant but might be
         // foldable.  Build a new instance of the folded commutative expression.
@@ -10367,7 +10400,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
   llvm_unreachable("Unknown SCEV type!");
 }
 
-const SCEV *ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) {
+SCEVUse ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) {
   return getSCEVAtScope(getSCEV(V), L);
 }
 
@@ -14658,7 +14691,7 @@ void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
   if (ScopeIt != ValuesAtScopes.end()) {
     for (const auto &Pair : ScopeIt->second)
       if (!isa_and_nonnull<SCEVConstant>(Pair.second))
-        llvm::erase(ValuesAtScopesUsers[Pair.second],
+        llvm::erase(ValuesAtScopesUsers[Pair.second.getPointer()],
                     std::make_pair(Pair.first, S));
     ValuesAtScopes.erase(ScopeIt);
   }
@@ -14666,7 +14699,11 @@ void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
   auto ScopeUserIt = ValuesAtScopesUsers.find(S);
   if (ScopeUserIt != ValuesAtScopesUsers.end()) {
     for (const auto &Pair : ScopeUserIt->second)
-      llvm::erase(ValuesAtScopes[Pair.second], std::make_pair(Pair.first, S));
+      // The recorded value at scope is a use of S, which may carry no-wrap
+      // flags that are not part of this key.
+      llvm::erase_if(ValuesAtScopes[Pair.second], [&](const auto &LS) {
+        return LS.first == Pair.first && LS.second.getPointer() == S;
+      });
     ValuesAtScopesUsers.erase(ScopeUserIt);
   }
 
@@ -14911,9 +14948,9 @@ void ScalarEvolution::verify() const {
     const SCEV *Value = ValueAndVec.first;
     for (const auto &LoopAndValueAtScope : ValueAndVec.second) {
       const Loop *L = LoopAndValueAtScope.first;
-      const SCEV *ValueAtScope = LoopAndValueAtScope.second;
+      SCEVUse ValueAtScope = LoopAndValueAtScope.second;
       if (!isa<SCEVConstant>(ValueAtScope)) {
-        auto It = ValuesAtScopesUsers.find(ValueAtScope);
+        auto It = ValuesAtScopesUsers.find(ValueAtScope.getPointer());
         if (It != ValuesAtScopesUsers.end() &&
             is_contained(It->second, std::make_pair(L, Value)))
           continue;
@@ -14931,8 +14968,11 @@ void ScalarEvolution::verify() const {
       const SCEV *Value = LoopAndValue.second;
       assert(!isa<SCEVConstant>(Value));
       auto It = ValuesAtScopes.find(Value);
-      if (It != ValuesAtScopes.end() &&
-          is_contained(It->second, std::make_pair(L, ValueAtScope)))
+      // The recorded value at scope may carry no-wrap flags that are not part
+      // of the key it is recorded under.
+      if (It != ValuesAtScopes.end() && any_of(It->second, [&](const auto &LS) {
+            return LS.first == L && LS.second.getPointer() == ValueAtScope;
+          }))
         continue;
       dbgs() << "Value: " << *Value << ", Loop: " << *L << ", ValueAtScope: "
              << *ValueAtScope << " missing in ValuesAtScopes\n";
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index e8aa421a270d4..d3f2f0beacc6a 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -1798,11 +1798,11 @@ static bool hasHardUserWithinLoop(const Loop *L, const Instruction *I) {
 struct RewritePhi {
   PHINode *PN;               // For which PHI node is this replacement?
   unsigned Ith;              // For which incoming value?
-  const SCEV *ExpansionSCEV; // The SCEV of the incoming value we are rewriting.
+  SCEVUse ExpansionSCEV;     // The SCEV of the incoming value we are rewriting.
   Instruction *ExpansionPoint; // Where we'd like to expand that SCEV?
   bool HighCost;               // Is this expansion a high-cost?
 
-  RewritePhi(PHINode *P, unsigned I, const SCEV *Val, Instruction *ExpansionPt,
+  RewritePhi(PHINode *P, unsigned I, SCEVUse Val, Instruction *ExpansionPt,
              bool H)
       : PN(P), Ith(I), ExpansionSCEV(Val), ExpansionPoint(ExpansionPt),
         HighCost(H) {}
@@ -1973,7 +1973,7 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
         // expressions which are true for all exits (so as to maximize
         // expression reuse by the SCEVExpander), but resort to per-exit
         // evaluation if that fails.
-        const SCEV *ExitValue = SE->getSCEVAtScope(Inst, L->getParentLoop());
+        SCEVUse ExitValue = SE->getSCEVAtScope(Inst, L->getParentLoop());
         if (isa<SCEVCouldNotCompute>(ExitValue) ||
             !SE->isLoopInvariant(ExitValue, L) ||
             !Rewriter.isSafeToExpand(ExitValue)) {
@@ -2004,7 +2004,7 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
 
         // Check if expansions of this SCEV would count as being high cost.
         bool HighCost = Rewriter.isHighCostExpansion(
-            ExitValue, L, SCEVCheapExpansionBudget, TTI, Inst);
+            ExitValue.getPointer(), L, SCEVCheapExpansionBudget, TTI, Inst);
 
         // Note that we must not perform expansions until after
         // we query *all* the costs, because if we perform temporary expansion
diff --git a/llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll b/llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll
index 9852456350c77..13f3660c2e782 100644
--- a/llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll
@@ -141,7 +141,7 @@ define void @test_01(i32 %a, i32 %b) {
 ; CHECK-NEXT:    %sum3 = add i32 %phi4, %phi5
 ; CHECK-NEXT:    --> {116,+,3}<%loop2> U: [116,618) S: [116,618) Exits: (116 + (3 * ((-160 + (-6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6)) + (-2 * %a) + (-2 * %b) + (1000 umax (165 + (2 * %a) + (2 * %b) + (6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6))<nuw>))) /u 6))<nuw><nsw>)<nuw> LoopDispositions: { %loop2: Computable }
 ; CHECK-NEXT:    %sum4 = add i32 %sum3, %phi6
-; CHECK-NEXT:    --> {159,+,6}<%loop2> U: [159,1162) S: [159,1162) Exits: (159 + (6 * ((-160 + (-6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6)) + (-2 * %a) + (-2 * %b) + (1000 umax (165 + (2 * %a) + (2 * %b) + (6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6))<nuw>))) /u 6))<nuw>) LoopDispositions: { %loop2: Computable }
+; CHECK-NEXT:    --> {159,+,6}<%loop2> U: [159,1162) S: [159,1162) Exits: (159 + (6 * ((-160 + (-6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6)) + (-2 * %a) + (-2 * %b) + (1000 umax (165 + (2 * %a) + (2 * %b) + (6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6))<nuw>))) /u 6))<nuw>)<u nuw> LoopDispositions: { %loop2: Computable }
 ; CHECK-NEXT:    %is2 = add i32 %sum4, %b
 ; CHECK-NEXT:    --> {(159 + %b),+,6}<nw><%loop2> U: full-set S: full-set Exits: (159 + (6 * ((-160 + (-6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6)) + (-2 * %a) + (-2 * %b) + (1000 umax (165 + (2 * %a) + (2 * %b) + (6 * ((-1 + (-2 * %a) + (-1 * %b) + (1000 umax (6 + (2 * %a) + %b))) /u 6))<nuw>))) /u 6))<nuw> + %b) LoopDispositions: { %loop2: Computable }
 ; CHECK-NEXT:    %ec2 = add i32 %is1, %is2
diff --git a/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll b/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
index 24e8fe5c163e7..92e1a3da73c85 100644
--- a/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exit-value-nowrap-flags.ll
@@ -5,7 +5,7 @@ define void @dec_to_start_of_nuw_addrec(i64 %start) {
 ; CHECK-LABEL: 'dec_to_start_of_nuw_addrec'
 ; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_addrec
 ; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
-; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start)<u nuw> LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %x.next = add nuw i64 %x, 1
@@ -13,7 +13,7 @@ define void @dec_to_start_of_nuw_addrec(i64 %start) {
 ; CHECK-NEXT:    %i.next = add i32 %i, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %y = phi i64 [ %x, %up ], [ %y.next, %down ]
-; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start),+,-1}<%down> U: full-set S: full-set Exits: (1 + ((8 + %start) umin %start)) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start)<u nuw>,+,-1}<%down> U: full-set S: full-set Exits: (1 + ((8 + %start) umin %start)) LoopDispositions: { %down: Computable }
 ; CHECK-NEXT:    %y.next = add i64 %y, -1
 ; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(8 + %start),+,-1}<%down> U: full-set S: full-set Exits: ((8 + %start) umin %start) LoopDispositions: { %down: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_addrec
@@ -51,7 +51,7 @@ define void @dec_to_start_of_nuw_ptr_addrec(ptr %start) {
 ; CHECK-LABEL: 'dec_to_start_of_nuw_ptr_addrec'
 ; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_ptr_addrec
 ; CHECK-NEXT:    %p = phi ptr [ %start, %entry ], [ %p.next, %up ]
-; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up> U: full-set S: full-set Exits: (9 + %start)<u nuw> LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %p.next = getelementptr nuw i8, ptr %p, i64 1
@@ -59,7 +59,7 @@ define void @dec_to_start_of_nuw_ptr_addrec(ptr %start) {
 ; CHECK-NEXT:    %i.next = add i32 %i, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%up> U: [1,11) S: [1,11) Exits: 10 LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %q = phi ptr [ %p, %up ], [ %q.next, %down ]
-; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start),+,-1}<%down> U: full-set S: full-set Exits: (1 + (-1 * (ptrtoaddr ptr %start to i64)) + ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down: Computable }
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up>,+,-1}<%down> U: full-set S: full-set --> {(9 + %start)<u nuw>,+,-1}<%down> U: full-set S: full-set Exits: (1 + (-1 * (ptrtoaddr ptr %start to i64)) + ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down: Computable }
 ; CHECK-NEXT:    %q.next = getelementptr i8, ptr %q, i64 -1
 ; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up>,+,-1}<%down> U: full-set S: full-set --> {(8 + %start),+,-1}<%down> U: full-set S: full-set Exits: ((-1 * (ptrtoaddr ptr %start to i64)) + ((8 + (ptrtoaddr ptr %start to i64)) umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_ptr_addrec
@@ -148,7 +148,7 @@ define void @exit_value_nsw_nonneg(i64 %start.raw, i64 %step.raw) {
 ; CHECK-NEXT:    %step = and i64 %step.raw, 7
 ; CHECK-NEXT:    --> (zext i3 (trunc i64 %step.raw to i3) to i64) U: [0,8) S: [0,8)
 ; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up ]
-; CHECK-NEXT:    --> {(zext i8 (trunc i64 %start.raw to i8) to i64),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nuw><nsw><%up> U: [0,319) S: [0,319) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (9 * (zext i3 (trunc i64 %step.raw to i3) to i64))<nuw><nsw>) LoopDispositions: { %up: Computable }
+; CHECK-NEXT:    --> {(zext i8 (trunc i64 %start.raw to i8) to i64),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nuw><nsw><%up> U: [0,319) S: [0,319) Exits: ((zext i8 (trunc i64 %start.raw to i8) to i64) + (9 * (zext i3 (trunc i64 %step.raw to i3) to i64))<nuw><nsw>)<u nuw> LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %i = phi i32 [ 0, %entry ], [ %i.next, %up ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%up> U: [0,10) S: [0,10) Exits: 9 LoopDispositions: { %up: Computable }
 ; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
@@ -294,11 +294,11 @@ define ptr @exit_value_mul_drops_nuw(ptr %first, ptr %last) {
 ; CHECK-LABEL: 'exit_value_mul_drops_nuw'
 ; CHECK-NEXT:  Classifying expressions for: @exit_value_mul_drops_nuw
 ; CHECK-NEXT:    %p = phi ptr [ %first, %entry ], [ %p.next, %loop ]
-; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set Exits: ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set Exits: ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %p.next = getelementptr inbounds nuw i8, ptr %p, i64 24
 ; CHECK-NEXT:    --> {(24 + %first),+,24}<nuw><%loop> U: full-set S: full-set Exits: (24 + (24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %lc = phi ptr [ %p, %loop ]
-; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set --> ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first) U: full-set S: full-set
+; CHECK-NEXT:    --> {%first,+,24}<nuw><%loop> U: full-set S: full-set --> ((24 * (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))) + %first)<u nuw> U: full-set S: full-set
 ; CHECK-NEXT:  Determining loop execution counts for: @exit_value_mul_drops_nuw
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is (((-24 + (-1 * (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))<nuw><nsw> + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64))) /u 24) + (1 umin (-24 + (-1 * (ptrtoaddr ptr %first to i64)) + ((24 + (ptrtoaddr ptr %first to i64)) umax (ptrtoaddr ptr %last to i64)))))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 768614336404564650
diff --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison-noautogen.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison-noautogen.ll
index 52843d6176a6f..35826d3de72f1 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison-noautogen.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison-noautogen.ll
@@ -13,11 +13,11 @@ define void @subrecurrences(i32 %outer_l, i32 %inner_l, i32 %val) {
 ; CHECK-NEXT:    %o_idx = phi i32 [ 0, %entry ], [ %o_idx.inc, %outer.be ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%outer> U: [0,-2147483648) S: [0,-2147483648) Exits: %outer_l LoopDispositions: { %outer: Computable, %inner: Invariant }
 ; CHECK-NEXT:    %o_idx.inc = add nsw i32 %o_idx, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%outer> U: [1,0) S: [1,0) Exits: (1 + %outer_l) LoopDispositions: { %outer: Computable, %inner: Invariant }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%outer> U: [1,0) S: [1,0) Exits: (1 + %outer_l)<u nuw> LoopDispositions: { %outer: Computable, %inner: Invariant }
 ; CHECK-NEXT:    %i_idx = phi i32 [ 0, %outer ], [ %i_idx.inc, %inner ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%inner> U: [0,-2147483648) S: [0,-2147483648) Exits: %inner_l LoopDispositions: { %inner: Computable, %outer: Uniform }
 ; CHECK-NEXT:    %i_idx.inc = add nsw i32 %i_idx, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%inner> U: [1,0) S: [1,0) Exits: (1 + %inner_l) LoopDispositions: { %inner: Computable, %outer: Uniform }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%inner> U: [1,0) S: [1,0) Exits: (1 + %inner_l)<u nuw> LoopDispositions: { %inner: Computable, %outer: Uniform }
 ; CHECK-NEXT:    %v = sub nsw i32 %i_idx, %o_idx.inc
 ; CHECK-NEXT:    --> {{\{\{}}-1,+,-1}<nw><%outer>,+,1}<nsw><%inner> U: full-set S: full-set Exits: {(-1 + %inner_l),+,-1}<nw><%outer> LoopDispositions: { %inner: Computable, %outer: Variant }
 ; CHECK-NEXT:    %forub = udiv i32 1, %v
diff --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
index ce899726d44cd..506e1f7998ba0 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -2044,7 +2044,7 @@ 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 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%p,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p)<u nuw> 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 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_inbounds_nneg
@@ -2092,7 +2092,7 @@ 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 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%p,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p)<u nuw> 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 * (ptrtoaddr ptr %p to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %p) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @addrec_gep_nusw_nneg
diff --git a/llvm/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll b/llvm/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll
index 0caa0a3f0f15c..7170645ccc659 100644
--- a/llvm/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll
+++ b/llvm/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll
@@ -177,7 +177,7 @@ define void @f3(i1 %c) {
 ; CHECK-NEXT:    %iv = phi i16 [ %start, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {%start,+,%step}<%loop> U: [0,-892) S: [0,-892) Exits: ((127 * %step)<nuw> + %start) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.zext = zext i16 %iv to i64
-; CHECK-NEXT:    --> {(zext i16 %start to i64),+,(zext i16 %step to i64)}<nuw><%loop> U: [0,64644) S: [0,64644) Exits: ((zext i16 %start to i64) + (127 * (zext i16 %step to i64))<nuw><nsw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {(zext i16 %start to i64),+,(zext i16 %step to i64)}<nuw><%loop> U: [0,64644) S: [0,64644) Exits: ((zext i16 %start to i64) + (127 * (zext i16 %step to i64))<nuw><nsw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add i16 %iv, %step
 ; CHECK-NEXT:    --> {(%step + %start),+,%step}<nw><%loop> U: full-set S: full-set Exits: ((128 * %step)<nuw> + %start) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %loop.iv.inc = add i16 %loop.iv, 1
diff --git a/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll b/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
index 677463ee63225..91fd7d32acf08 100644
--- a/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
+++ b/llvm/test/Analysis/ScalarEvolution/infer-prestart-no-wrap.ll
@@ -50,7 +50,7 @@ define void @infer.zext.0(ptr %c, i32 %start, ptr %buf) {
 ; CHECK-NEXT:    %counter = phi i32 [ 0, %entry ], [ %counter.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,2) S: [0,2) Exits: 1 LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = phi i32 [ %start, %entry ], [ %idx.inc, %loop ]
-; CHECK-NEXT:    --> {%start,+,1}<nuw><%loop> U: full-set S: full-set Exits: (1 + %start) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%loop> U: full-set S: full-set Exits: (1 + %start)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx.inc = add nuw i32 %idx, 1
 ; CHECK-NEXT:    --> {(1 + %start)<nuw>,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (2 + %start) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx.inc.sext = zext i32 %idx.inc to i64
diff --git a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-operand-order.ll b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-operand-order.ll
index 512c2a9e1f132..87ba0036b4eba 100644
--- a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-operand-order.ll
+++ b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-operand-order.ll
@@ -7,9 +7,9 @@ define void @test_multiple_const_guards_order1(ptr nocapture %a, i64 %i) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,10) S: [0,10) Exits: %i LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_multiple_const_guards_order1
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %i
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 9
@@ -42,9 +42,9 @@ define void @test_multiple_const_guards_order2(ptr nocapture %a, i64 %i) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,10) S: [0,10) Exits: %i LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_multiple_const_guards_order2
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %i
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 9
@@ -77,9 +77,9 @@ define void @test_multiple_var_guards_order1(ptr nocapture %a, i64 %i, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,11) S: [0,11) Exits: %i LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,12) S: [1,12) Exits: (1 + %i) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,12) S: [1,12) Exits: (1 + %i)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_multiple_var_guards_order1
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %i
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 10
@@ -112,9 +112,9 @@ define void @test_multiple_var_guards_order2(ptr nocapture %a, i64 %i, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,11) S: [0,11) Exits: %i LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,12) S: [1,12) Exits: (1 + %i) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,12) S: [1,12) Exits: (1 + %i)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_multiple_var_guards_order2
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %i
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 10
@@ -147,7 +147,7 @@ define i32 @sle_sgt_ult_umax_to_smax(i32 %num) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,25) S: [0,25) Exits: (4 * ((-4 + %num) /u 4))<nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw i32 %iv, 4
-; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,29) S: [4,29) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,29) S: [4,29) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @sle_sgt_ult_umax_to_smax
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + %num) /u 4)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 6
@@ -183,7 +183,7 @@ define i32 @ult_sle_sgt_umax_to_smax(i32 %num) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-2147483648,2147483645) Exits: (4 * ((-4 + %num) /u 4))<nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw i32 %iv, 4
-; CHECK-NEXT:    --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-2147483648,2147483645) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-2147483648,2147483645) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @ult_sle_sgt_umax_to_smax
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-4 + %num) /u 4)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 1073741823
@@ -220,7 +220,7 @@ define void @const_max_btc_32_or_order_1(i64 %n) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %ph ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,-9223372036854775808) Exits: %n LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,-9223372036854775807) S: [1,-9223372036854775807) Exits: (1 + %n) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,-9223372036854775807) S: [1,-9223372036854775807) Exits: (1 + %n)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @const_max_btc_32_or_order_1
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %n
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 9223372036854775807
@@ -257,7 +257,7 @@ define void @const_max_btc_32_or_order_2(i64 %n) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %ph ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,33) S: [0,33) Exits: %n LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,34) S: [1,34) Exits: (1 + %n) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,34) S: [1,34) Exits: (1 + %n)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @const_max_btc_32_or_order_2
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %n
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 32
diff --git a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll
index fac1e2a9e6986..ac5c217658c15 100644
--- a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll
+++ b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll
@@ -54,7 +54,7 @@ define i32 @rewrite_zext_min_max(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_min_max
@@ -100,7 +100,7 @@ define i32 @rewrite_min_max_zext(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_min_max_zext
@@ -146,7 +146,7 @@ define i32 @rewrite_sext_min_max(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nsw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_sext_min_max
@@ -192,7 +192,7 @@ define i32 @rewrite_min_max_sext(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nsw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_min_max_sext
@@ -458,7 +458,7 @@ define i32 @rewrite_sext_slt_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_sext_slt_narrow_check
@@ -502,7 +502,7 @@ define i32 @rewrite_zext_ult_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_ult_narrow_check
@@ -546,7 +546,7 @@ define i32 @rewrite_zext_ule_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_ule_narrow_check
@@ -590,7 +590,7 @@ define i32 @rewrite_zext_sle_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_sle_narrow_check
@@ -634,7 +634,7 @@ define i32 @rewrite_zext_uge_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_uge_narrow_check
@@ -678,7 +678,7 @@ define i32 @rewrite_sext_sge_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_sext_sge_narrow_check
@@ -722,7 +722,7 @@ define i32 @rewrite_zext_ugt_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_zext_ugt_narrow_check
@@ -766,7 +766,7 @@ define i32 @rewrite_sext_sgt_narrow_check(i32 %N, ptr %arr) {
 ; CHECK-NEXT:    %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,4}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i32, ptr %arr, i64 %index
-; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %index.next = add nuw i64 %index, 4
 ; CHECK-NEXT:    --> {4,+,4}<nuw><nsw><%loop> U: [4,17) S: [4,17) Exits: (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @rewrite_sext_sgt_narrow_check
diff --git a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
index 85cb371f6a3d3..11981448b97be 100644
--- a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
+++ b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
@@ -133,9 +133,9 @@ define void @test_guard_eq_12(ptr nocapture %a, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_guard_eq_12
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %N
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 12
@@ -164,9 +164,9 @@ define void @test_guard_ule_12(ptr nocapture %a, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_guard_ule_12
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %N
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 12
@@ -195,9 +195,9 @@ define void @test_guard_ule_12_step2(ptr nocapture %a, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (2 * (%N /u 2))<nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,8}<nuw><%loop> U: full-set S: full-set Exits: ((8 * (%N /u 2)) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,8}<nuw><%loop> U: full-set S: full-set Exits: ((8 * (%N /u 2)) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 2
-; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%loop> U: [2,15) S: [2,15) Exits: (2 + (2 * (%N /u 2))<nuw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%loop> U: [2,15) S: [2,15) Exits: (2 + (2 * (%N /u 2))<nuw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_guard_ule_12_step2
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is (%N /u 2)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 6
@@ -227,9 +227,9 @@ define void @test_multiple_var_guards_cycle(ptr nocapture %a, i64 %i, i64 %N) {
 ; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,-9223372036854775808) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %idx = getelementptr inbounds i32, ptr %a, i64 %iv
-; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,-1) S: [1,-1) Exits: (1 + %N) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,-1) S: [1,-1) Exits: (1 + %N)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_multiple_var_guards_cycle
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is %N
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 -3
@@ -738,7 +738,7 @@ define void @guard_pessimizes_analysis_step2(i1 %c, i32 %N) {
 ; CHECK-NEXT:    %init = phi i32 [ 2, %entry ], [ 3, %bb1 ]
 ; CHECK-NEXT:    --> %init U: [2,4) S: [2,4)
 ; CHECK-NEXT:    %iv = phi i32 [ %iv.next, %loop ], [ %init, %loop.ph ]
-; CHECK-NEXT:    --> {%init,+,2}<nuw><nsw><%loop> U: [2,10) S: [2,10) Exits: ((2 * ((8 + (-1 * %init)<nsw>)<nsw> /u 2))<nuw><nsw> + %init) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%init,+,2}<nuw><nsw><%loop> U: [2,10) S: [2,10) Exits: ((2 * ((8 + (-1 * %init)<nsw>)<nsw> /u 2))<nuw><nsw> + %init)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 2
 ; CHECK-NEXT:    --> {(2 + %init)<nuw><nsw>,+,2}<nuw><nsw><%loop> U: [4,12) S: [4,12) Exits: (2 + (2 * ((8 + (-1 * %init)<nsw>)<nsw> /u 2))<nuw><nsw> + %init) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @guard_pessimizes_analysis_step2
@@ -1121,7 +1121,7 @@ define void @optimized_range_check_unsigned(ptr %pred, i32 %N) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,7) S: [0,7) Exits: (-1 + %N) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i16, ptr %pred, i32 %iv
-; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,8) S: [1,8) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @optimized_range_check_unsigned
@@ -1156,7 +1156,7 @@ define void @optimized_range_check_unsigned_icmp_ops_swapped(ptr %pred, i32 %N)
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,7) S: [0,7) Exits: (-1 + %N) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i16, ptr %pred, i32 %iv
-; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,8) S: [1,8) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @optimized_range_check_unsigned_icmp_ops_swapped
@@ -1193,7 +1193,7 @@ define void @optimized_range_check_unsigned2(ptr %pred, i32 %N) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,21) S: [0,21) Exits: (-1 + %N) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i16, ptr %pred, i32 %iv
-; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,22) S: [1,22) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @optimized_range_check_unsigned2
@@ -1231,7 +1231,7 @@ define void @optimized_range_check_unsigned3(ptr %pred, i1 %c) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,3) S: [0,3) Exits: (-1 + %N)<nsw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i16, ptr %pred, i32 %iv
-; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((zext i32 (-2 + (2 * %N)<nuw><nsw>)<nsw> to i64) + %pred) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((zext i32 (-2 + (2 * %N)<nuw><nsw>)<nsw> to i64) + %pred)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,4) S: [1,4) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @optimized_range_check_unsigned3
@@ -1268,7 +1268,7 @@ define void @not_optimized_range_check_unsigned1(ptr %pred, i32 %N) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %N) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %gep = getelementptr inbounds i16, ptr %pred, i32 %iv
-; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %N LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @not_optimized_range_check_unsigned1
@@ -1361,7 +1361,7 @@ define void @ptr_induction_eq_1(ptr %a, ptr %b) {
 ; CHECK-LABEL: 'ptr_induction_eq_1'
 ; CHECK-NEXT:  Classifying expressions for: @ptr_induction_eq_1
 ; CHECK-NEXT:    %ptr.iv = phi ptr [ %ptr.iv.next, %loop ], [ %a, %entry ]
-; CHECK-NEXT:    --> {%a,+,8}<nuw><%loop> U: full-set S: full-set Exits: ((8 * ((-8 + (-1 * (ptrtoaddr ptr %a to i64)) + (ptrtoaddr ptr %b to i64)) /u 8))<nuw> + %a) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%a,+,8}<nuw><%loop> U: full-set S: full-set Exits: ((8 * ((-8 + (-1 * (ptrtoaddr ptr %a to i64)) + (ptrtoaddr ptr %b to i64)) /u 8))<nuw> + %a)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 8
 ; CHECK-NEXT:    --> {(8 + %a),+,8}<nuw><%loop> U: full-set S: full-set Exits: (8 + (8 * ((-8 + (-1 * (ptrtoaddr ptr %a to i64)) + (ptrtoaddr ptr %b to i64)) /u 8))<nuw> + %a) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @ptr_induction_eq_1
diff --git a/llvm/test/Analysis/ScalarEvolution/nsw-offset-assume.ll b/llvm/test/Analysis/ScalarEvolution/nsw-offset-assume.ll
index 305a2bfca2b66..81e2c0008e758 100644
--- a/llvm/test/Analysis/ScalarEvolution/nsw-offset-assume.ll
+++ b/llvm/test/Analysis/ScalarEvolution/nsw-offset-assume.ll
@@ -20,11 +20,11 @@ define void @foo(i32 %no, ptr nocapture %d, ptr nocapture %q) nounwind {
 ; CHECK-NEXT:    %1 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %2 = getelementptr inbounds double, ptr %d, i64 %1
-; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %4 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %5 = getelementptr inbounds double, ptr %q, i64 %4
-; CHECK-NEXT:    --> {%q,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %q) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%q,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %q)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %7 = or disjoint i32 %i.01, 1
 ; CHECK-NEXT:    --> {1,+,2}<nuw><nsw><%bb> U: [1,2147483646) S: [1,2147483646) Exits: (1 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>)<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %8 = sext i32 %7 to i64
@@ -40,9 +40,9 @@ define void @foo(i32 %no, ptr nocapture %d, ptr nocapture %q) nounwind {
 ; CHECK-NEXT:    %14 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %15 = getelementptr inbounds double, ptr %d, i64 %14
-; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %16 = add nsw i32 %i.01, 2
-; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%bb> U: [2,2147483647) S: [2,2147483647) Exits: (2 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%bb> U: [2,2147483647) S: [2,2147483647) Exits: (2 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @foo
 ; CHECK-NEXT:  Loop %bb: backedge-taken count is ((-1 + (2 * (%no /u 2))<nuw>) /u 2)
 ; CHECK-NEXT:  Loop %bb: constant max backedge-taken count is i32 1073741822
diff --git a/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll b/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll
index d6e78eca398ea..9f3d7a28328f8 100644
--- a/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll
+++ b/llvm/test/Analysis/ScalarEvolution/nsw-offset.ll
@@ -17,11 +17,11 @@ define void @foo(i32 %no, ptr nocapture %d, ptr nocapture %q) nounwind {
 ; CHECK-NEXT:    %1 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %2 = getelementptr inbounds double, ptr %d, i64 %1
-; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %4 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %5 = getelementptr inbounds double, ptr %q, i64 %4
-; CHECK-NEXT:    --> {%q,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %q) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%q,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %q)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %7 = or disjoint i32 %i.01, 1
 ; CHECK-NEXT:    --> {1,+,2}<nuw><nsw><%bb> U: [1,2147483646) S: [1,2147483646) Exits: (1 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>)<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %8 = sext i32 %7 to i64
@@ -37,9 +37,9 @@ define void @foo(i32 %no, ptr nocapture %d, ptr nocapture %q) nounwind {
 ; CHECK-NEXT:    %14 = sext i32 %i.01 to i64
 ; CHECK-NEXT:    --> {0,+,2}<nuw><nsw><%bb> U: [0,2147483645) S: [0,2147483645) Exits: (2 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %15 = getelementptr inbounds double, ptr %d, i64 %14
-; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {%d,+,16}<nuw><%bb> U: full-set S: full-set Exits: ((16 * ((1 + (zext i32 (-2 + (2 * (%no /u 2))<nuw>) to i64))<nuw><nsw> /u 2))<nuw><nsw> + %d)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:    %16 = add nsw i32 %i.01, 2
-; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%bb> U: [2,2147483647) S: [2,2147483647) Exits: (2 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>) LoopDispositions: { %bb: Computable }
+; CHECK-NEXT:    --> {2,+,2}<nuw><nsw><%bb> U: [2,2147483647) S: [2,2147483647) Exits: (2 + (2 * ((-1 + (2 * (%no /u 2))<nuw>) /u 2))<nuw>)<u nuw> LoopDispositions: { %bb: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @foo
 ; CHECK-NEXT:  Loop %bb: backedge-taken count is ((-1 + (2 * (%no /u 2))<nuw>) /u 2)
 ; CHECK-NEXT:  Loop %bb: constant max backedge-taken count is i32 1073741822
diff --git a/llvm/test/Analysis/ScalarEvolution/nsw.ll b/llvm/test/Analysis/ScalarEvolution/nsw.ll
index c529f9e39a13d..eabd590c590c5 100644
--- a/llvm/test/Analysis/ScalarEvolution/nsw.ll
+++ b/llvm/test/Analysis/ScalarEvolution/nsw.ll
@@ -71,7 +71,7 @@ define void @test2(ptr %begin, ptr %end) ssp {
 ; CHECK-LABEL: 'test2'
 ; CHECK-NEXT:  Classifying expressions for: @test2
 ; CHECK-NEXT:    %__first.addr.02.i.i = phi ptr [ %begin, %for.body.lr.ph.i.i ], [ %ptrincdec.i.i, %for.body.i.i ]
-; CHECK-NEXT:    --> {%begin,+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin) LoopDispositions: { %for.body.i.i: Computable }
+; CHECK-NEXT:    --> {%begin,+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin)<u nuw> LoopDispositions: { %for.body.i.i: Computable }
 ; CHECK-NEXT:    %ptrincdec.i.i = getelementptr inbounds i32, ptr %__first.addr.02.i.i, i64 1
 ; CHECK-NEXT:    --> {(4 + %begin),+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: (4 + (4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin) LoopDispositions: { %for.body.i.i: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test2
@@ -112,7 +112,7 @@ define void @test3(ptr %begin, ptr %end) nounwind ssp {
 ; CHECK-NEXT:    %ptrincdec.i.i = getelementptr inbounds i32, ptr %begin, i64 %tmp
 ; CHECK-NEXT:    --> {(4 + %begin),+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: (4 + (4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin) LoopDispositions: { %for.body.i.i: Computable }
 ; CHECK-NEXT:    %__first.addr.08.i.i = getelementptr inbounds i32, ptr %begin, i64 %indvar.i.i
-; CHECK-NEXT:    --> {%begin,+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin) LoopDispositions: { %for.body.i.i: Computable }
+; CHECK-NEXT:    --> {%begin,+,4}<nuw><%for.body.i.i> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4))<nuw> + %begin)<u nuw> LoopDispositions: { %for.body.i.i: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test3
 ; CHECK-NEXT:  Loop %for.body.i.i: backedge-taken count is ((-4 + (-1 * (ptrtoaddr ptr %begin to i64)) + (ptrtoaddr ptr %end to i64)) /u 4)
 ; CHECK-NEXT:  Loop %for.body.i.i: constant max backedge-taken count is i64 4611686018427387903
@@ -200,7 +200,7 @@ define void @PR12376(ptr nocapture %arg, ptr nocapture %arg1)  {
 ; CHECK-LABEL: 'PR12376'
 ; CHECK-NEXT:  Classifying expressions for: @PR12376
 ; CHECK-NEXT:    %tmp = phi ptr [ %arg, %bb ], [ %tmp4, %bb2 ]
-; CHECK-NEXT:    --> {%arg,+,4}<nuw><%bb2> U: full-set S: full-set Exits: ((4 * ((-1 + (-1 * (ptrtoaddr ptr %arg to i64)) + ((4 + (ptrtoaddr ptr %arg to i64))<nuw> umax (ptrtoaddr ptr %arg1 to i64))) /u 4))<nuw> + %arg) LoopDispositions: { %bb2: Computable }
+; CHECK-NEXT:    --> {%arg,+,4}<nuw><%bb2> U: full-set S: full-set Exits: ((4 * ((-1 + (-1 * (ptrtoaddr ptr %arg to i64)) + ((4 + (ptrtoaddr ptr %arg to i64))<nuw> umax (ptrtoaddr ptr %arg1 to i64))) /u 4))<nuw> + %arg)<u nuw> LoopDispositions: { %bb2: Computable }
 ; CHECK-NEXT:    %tmp4 = getelementptr inbounds i32, ptr %tmp, i64 1
 ; CHECK-NEXT:    --> {(4 + %arg)<nuw>,+,4}<nuw><%bb2> U: [4,0) S: [4,0) Exits: (4 + (4 * ((-1 + (-1 * (ptrtoaddr ptr %arg to i64)) + ((4 + (ptrtoaddr ptr %arg to i64))<nuw> umax (ptrtoaddr ptr %arg1 to i64))) /u 4))<nuw> + %arg) LoopDispositions: { %bb2: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @PR12376
@@ -309,7 +309,7 @@ define void @bad_postinc_nsw_a(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,7}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 7
-; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,0) Exits: (7 + (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n)))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,0) Exits: (7 + (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))))<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @bad_postinc_nsw_a
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 613566756
@@ -367,7 +367,7 @@ define void @pr28012(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,7}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (7 * ((-1 + (7 umax %n)) /u 7))<nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 7
-; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,-3) Exits: (7 + (7 * ((-1 + (7 umax %n)) /u 7))<nuw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,-3) Exits: (7 + (7 * ((-1 + (7 umax %n)) /u 7))<nuw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @pr28012
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-1 + (7 umax %n)) /u 7)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 613566755
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint-special-pointers.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint-special-pointers.ll
index b9877f46189d8..7d4acb383f295 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint-special-pointers.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint-special-pointers.ll
@@ -169,7 +169,7 @@ define void @fat_ptr_ult_backedge_count(ptr addrspace(1) %start, ptr addrspace(1
 ; CHECK-LABEL: 'fat_ptr_ult_backedge_count'
 ; CHECK-NEXT:  Classifying expressions for: @fat_ptr_ult_backedge_count
 ; CHECK-NEXT:    %iv = phi ptr addrspace(1) [ %start, %entry ], [ %iv.next, %loop ]
-; CHECK-NEXT:    --> {%start,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4))<nuw> + %start) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {%start,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4))<nuw> + %start)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = getelementptr inbounds i32, ptr addrspace(1) %iv, i64 1
 ; CHECK-NEXT:    --> {(4 + %start)<nuw>,+,4}<nuw><%loop> U: [4,0) S: [4,0) Exits: (4 + (4 * ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4))<nuw> + %start) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @fat_ptr_ult_backedge_count
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index 1589e7cd540b5..83c82cfe0372c 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -531,11 +531,11 @@ define void @pr46786_c26_int(ptr %arg, ptr %arg1, ptr %arg2) {
 ; X64-NEXT:    %i4 = ptrtoint ptr %arg to i64
 ; X64-NEXT:    --> %i4 U: full-set S: full-set
 ; X64-NEXT:    %i7 = phi ptr [ %arg, %bb3 ], [ %i15, %bb6 ]
-; X64-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i64)) + (ptrtoaddr ptr %arg1 to i64)) /u 4))<nuw> + %arg) LoopDispositions: { %bb6: Computable }
+; X64-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i64)) + (ptrtoaddr ptr %arg1 to i64)) /u 4))<nuw> + %arg)<u nuw> LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i8 = load i32, ptr %i7, align 4
 ; X64-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X64-NEXT:    %i9 = ptrtoint ptr %i7 to i64
-; X64-NEXT:    --> {(ptrtoaddr ptr %arg to i64),+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i64)) + (ptrtoaddr ptr %arg1 to i64)) /u 4))<nuw> + (ptrtoaddr ptr %arg to i64)) LoopDispositions: { %bb6: Computable }
+; X64-NEXT:    --> {(ptrtoaddr ptr %arg to i64),+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i64)) + (ptrtoaddr ptr %arg1 to i64)) /u 4))<nuw> + (ptrtoaddr ptr %arg to i64))<u nuw> LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i10 = sub i64 %i9, %i4
 ; X64-NEXT:    --> {0,+,4}<nuw><%bb6> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i64)) + (ptrtoaddr ptr %arg1 to i64)) /u 4))<nuw> LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i11 = ashr exact i64 %i10, 2
@@ -559,7 +559,7 @@ define void @pr46786_c26_int(ptr %arg, ptr %arg1, ptr %arg2) {
 ; X32-NEXT:    %i4 = ptrtoint ptr %arg to i64
 ; X32-NEXT:    --> %i4 U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %i7 = phi ptr [ %arg, %bb3 ], [ %i15, %bb6 ]
-; X32-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i32)) + (ptrtoaddr ptr %arg1 to i32)) /u 4))<nuw> + %arg) LoopDispositions: { %bb6: Computable }
+; X32-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * (ptrtoaddr ptr %arg to i32)) + (ptrtoaddr ptr %arg1 to i32)) /u 4))<nuw> + %arg)<u nuw> LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i8 = load i32, ptr %i7, align 4
 ; X32-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X32-NEXT:    %i9 = ptrtoint ptr %i7 to i64
diff --git a/llvm/test/Analysis/ScalarEvolution/ranges.ll b/llvm/test/Analysis/ScalarEvolution/ranges.ll
index cf54b1e63ad39..830375558b1c7 100644
--- a/llvm/test/Analysis/ScalarEvolution/ranges.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ranges.ll
@@ -132,7 +132,7 @@ define void @add_6(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,6}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,2147483647) Exits: (6 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 6) + (1 umin %n))) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 6
-; CHECK-NEXT:    --> {6,+,6}<nuw><%loop> U: [6,-3) S: [-2147483648,2147483647) Exits: (6 + (6 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 6) + (1 umin %n)))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {6,+,6}<nuw><%loop> U: [6,-3) S: [-2147483648,2147483647) Exits: (6 + (6 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 6) + (1 umin %n))))<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @add_6
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 6) + (1 umin %n))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 715827882
@@ -157,7 +157,7 @@ define void @add_7(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,7}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 7
-; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,0) Exits: (7 + (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n)))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {7,+,7}<nuw><%loop> U: [7,-3) S: [7,0) Exits: (7 + (7 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))))<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @add_7
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 7) + (1 umin %n))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 613566756
@@ -182,7 +182,7 @@ define void @add_8(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,8}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,2147483641) Exits: (8 * ((7 + %n) /u 8))<nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 8
-; CHECK-NEXT:    --> {8,+,8}<nuw><%loop> U: [8,-7) S: [-2147483648,2147483641) Exits: (8 + (8 * ((7 + %n) /u 8))<nuw>) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {8,+,8}<nuw><%loop> U: [8,-7) S: [-2147483648,2147483641) Exits: (8 + (8 * ((7 + %n) /u 8))<nuw>)<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @add_8
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((7 + %n) /u 8)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 536870911
@@ -208,7 +208,7 @@ define void @add_9(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,9}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (9 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 9) + (1 umin %n))) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 9
-; CHECK-NEXT:    --> {9,+,9}<nuw><%loop> U: [9,-3) S: [9,0) Exits: (9 + (9 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 9) + (1 umin %n)))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {9,+,9}<nuw><%loop> U: [9,-3) S: [9,0) Exits: (9 + (9 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 9) + (1 umin %n))))<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @add_9
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 9) + (1 umin %n))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 477218588
@@ -234,7 +234,7 @@ define void @add_10(i32 %n) {
 ; CHECK-NEXT:    %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
 ; CHECK-NEXT:    --> {0,+,10}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,2147483647) Exits: (10 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 10) + (1 umin %n))) LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.inc = add nsw i32 %iv, 10
-; CHECK-NEXT:    --> {10,+,10}<nuw><%loop> U: [10,-5) S: [-2147483648,2147483647) Exits: (10 + (10 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 10) + (1 umin %n)))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> {10,+,10}<nuw><%loop> U: [10,-5) S: [-2147483648,2147483647) Exits: (10 + (10 * ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 10) + (1 umin %n))))<u nuw> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @add_10
 ; CHECK-NEXT:  Loop %loop: backedge-taken count is ((((-1 * (1 umin %n))<nuw><nsw> + %n) /u 10) + (1 umin %n))
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 429496729
diff --git a/llvm/test/Analysis/ScalarEvolution/sdiv.ll b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
index acc6ab01978f8..e98112ed44c63 100644
--- a/llvm/test/Analysis/ScalarEvolution/sdiv.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
@@ -28,7 +28,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
 ; CHECK-NEXT:    %add = add nsw i32 %2, %call
 ; CHECK-NEXT:    --> (%2 + %call) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %inc = add nsw i32 %i.0, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%for.cond> U: [1,0) S: [1,0) Exits: (1 + %width) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%for.cond> U: [1,0) S: [1,0) Exits: (1 + %width)<u nuw> LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @_Z4loopi
 ; CHECK-NEXT:  Loop %for.cond: backedge-taken count is %width
 ; CHECK-NEXT:  Loop %for.cond: constant max backedge-taken count is i32 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/sext-add-inreg-loop.ll b/llvm/test/Analysis/ScalarEvolution/sext-add-inreg-loop.ll
index 1971f668a5e29..608ed32e6e877 100644
--- a/llvm/test/Analysis/ScalarEvolution/sext-add-inreg-loop.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sext-add-inreg-loop.ll
@@ -15,7 +15,7 @@ define dso_local i32 @test_loop(ptr nocapture noundef readonly %x) {
 ; CHECK-NEXT:    %idxprom = ashr exact i64 %sext, 32
 ; CHECK-NEXT:    --> {0,+,1}<nuw><nsw><%for.body> U: [0,9) S: [0,9) Exits: 8 LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %x, i64 %idxprom
-; CHECK-NEXT:    --> {%x,+,4}<nuw><%for.body> U: full-set S: full-set Exits: (32 + %x) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%x,+,4}<nuw><%for.body> U: full-set S: full-set Exits: (32 + %x)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %0 = load i32, ptr %arrayidx, align 4
 ; CHECK-NEXT:    --> %0 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.body: Variant }
 ; CHECK-NEXT:    %call = tail call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str, i32 noundef %0)
diff --git a/llvm/test/Analysis/ScalarEvolution/srem.ll b/llvm/test/Analysis/ScalarEvolution/srem.ll
index 9d4538f381728..f2c6ab18acd97 100644
--- a/llvm/test/Analysis/ScalarEvolution/srem.ll
+++ b/llvm/test/Analysis/ScalarEvolution/srem.ll
@@ -28,7 +28,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
 ; CHECK-NEXT:    %add = add nsw i32 %2, %call
 ; CHECK-NEXT:    --> (%2 + %call) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %inc = add nsw i32 %i.0, 1
-; CHECK-NEXT:    --> {1,+,1}<nuw><%for.cond> U: [1,0) S: [1,0) Exits: (1 + %width) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT:    --> {1,+,1}<nuw><%for.cond> U: [1,0) S: [1,0) Exits: (1 + %width)<u nuw> LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @_Z4loopi
 ; CHECK-NEXT:  Loop %for.cond: backedge-taken count is %width
 ; CHECK-NEXT:  Loop %for.cond: constant max backedge-taken count is i32 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count-scalable-stride.ll b/llvm/test/Analysis/ScalarEvolution/trip-count-scalable-stride.ll
index 8ba8bde322d44..1f425dcc03b83 100644
--- a/llvm/test/Analysis/ScalarEvolution/trip-count-scalable-stride.ll
+++ b/llvm/test/Analysis/ScalarEvolution/trip-count-scalable-stride.ll
@@ -11,7 +11,7 @@ define void @vscale_slt(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,10
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,vscale}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,-2147483648) Exits: (vscale * ((-1 + %n) /u vscale))<nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * ((-1 + %n) /u vscale)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * ((-1 + %n) /u vscale)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %vscale
 ; CHECK-NEXT:    --> {vscale,+,vscale}<nuw><nsw><%for.body> U: [2,-2147483648) S: [2,-2147483648) Exits: (vscale * (1 + ((-1 + %n) /u vscale))<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscale_slt
@@ -47,7 +47,7 @@ define void @vscale_ult(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,10
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,vscale}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,-2147483648) Exits: (vscale * ((-1 + %n) /u vscale))<nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * ((-1 + %n) /u vscale)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * ((-1 + %n) /u vscale)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %vscale
 ; CHECK-NEXT:    --> {vscale,+,vscale}<nuw><nsw><%for.body> U: [2,-2147483648) S: [2,-2147483648) Exits: (vscale * (1 + ((-1 + %n) /u vscale))<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscale_ult
@@ -83,7 +83,7 @@ define void @vscale_ule(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,10
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,vscale}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,-2147483648) Exits: (vscale * (((-1 + vscale)<nsw> umax %n) /u vscale))<nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * (((-1 + vscale)<nsw> umax %n) /u vscale)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * (((-1 + vscale)<nsw> umax %n) /u vscale)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %vscale
 ; CHECK-NEXT:    --> {vscale,+,vscale}<nuw><nsw><%for.body> U: [2,-2147483648) S: [2,-2147483648) Exits: (vscale * (1 + (((-1 + vscale)<nsw> umax %n) /u vscale))<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscale_ule
@@ -119,7 +119,7 @@ define void @vscale_ne(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,102
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,vscale}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,-2147483648) Exits: (vscale * (((-1 * vscale)<nsw> + %n) /u vscale))<nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * (((-1 * vscale)<nsw> + %n) /u vscale)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(4 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((4 * vscale * (((-1 * vscale)<nsw> + %n) /u vscale)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %vscale
 ; CHECK-NEXT:    --> {vscale,+,vscale}<nuw><nsw><%for.body> U: [2,-2147483648) S: [2,-2147483648) Exits: (vscale * (1 + (((-1 * vscale)<nsw> + %n) /u vscale))<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscale_ne
@@ -158,7 +158,7 @@ define void @vscalex4_slt(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,(4 * vscale)<nuw><nsw>}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,2147483645) Exits: (4 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(16 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((16 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(16 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((16 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %VF
 ; CHECK-NEXT:    --> {(4 * vscale)<nuw><nsw>,+,(4 * vscale)<nuw><nsw>}<nuw><nsw><%for.body> U: [8,-2147483648) S: [8,2147483645) Exits: (vscale * (4 + (4 * ((-1 + %n) /u (4 * vscale)<nuw><nsw>))<nuw><nsw>)<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscalex4_slt
@@ -197,7 +197,7 @@ define void @vscalex4_ult(ptr nocapture %A, i32 %n) mustprogress vscale_range(2,
 ; CHECK-NEXT:    %i.05 = phi i32 [ %add, %for.body ], [ 0, %entry ]
 ; CHECK-NEXT:    --> {0,+,(4 * vscale)<nuw><nsw>}<nuw><nsw><%for.body> U: [0,-2147483648) S: [0,2147483645) Exits: (4 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.05
-; CHECK-NEXT:    --> {%A,+,(16 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((16 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) + %A) LoopDispositions: { %for.body: Computable }
+; CHECK-NEXT:    --> {%A,+,(16 * vscale)<nuw><nsw>}<nuw><%for.body> U: full-set S: full-set Exits: ((16 * vscale * ((-1 + %n) /u (4 * vscale)<nuw><nsw>)) + %A)<u nuw> LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:    %add = add nsw i32 %i.05, %VF
 ; CHECK-NEXT:    --> {(4 * vscale)<nuw><nsw>,+,(4 * vscale)<nuw><nsw>}<nuw><nsw><%for.body> U: [8,-2147483648) S: [8,2147483645) Exits: (vscale * (4 + (4 * ((-1 + %n) /u (4 * vscale)<nuw><nsw>))<nuw><nsw>)<nuw>) LoopDispositions: { %for.body: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @vscalex4_ult
diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count15.ll b/llvm/test/Analysis/ScalarEvolution/trip-count15.ll
index ad96576b12f49..ca5bd5a978023 100644
--- a/llvm/test/Analysis/ScalarEvolution/trip-count15.ll
+++ b/llvm/test/Analysis/ScalarEvolution/trip-count15.ll
@@ -101,6 +101,15 @@ define void @smin_unsigned_check(i64 %n) {
 ; 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.
+; CHECK-NEXT:  Loop %loop: Predicated backedge-taken count is (1 + (zext i64 (4096 smin %n) to i128))<nuw><nsw>
+; CHECK-NEXT:   Predicates:
+; CHECK-NEXT:      {0,+,1}<%loop> Added Flags: <nusw>
+; CHECK-NEXT:  Loop %loop: Predicated constant max backedge-taken count is i128 18446744073709551616
+; CHECK-NEXT:   Predicates:
+; CHECK-NEXT:      {0,+,1}<%loop> Added Flags: <nusw>
+; CHECK-NEXT:  Loop %loop: Predicated symbolic max backedge-taken count is (1 + (zext i64 (4096 smin %n) to i128))<nuw><nsw>
+; CHECK-NEXT:   Predicates:
+; CHECK-NEXT:      {0,+,1}<%loop> Added Flags: <nusw>
 ;
 entry:
   %min.cmp = icmp slt i64 4096, %n
diff --git a/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll b/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll
index fca16b8cfecb5..c2470b2298c2a 100644
--- a/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll
+++ b/llvm/test/Transforms/IndVarSimplify/exit-value-nowrap-flags.ll
@@ -14,7 +14,7 @@ define i32 @nuw_kept(i32 %start, i32 %step, i32 %n) {
 ; CHECK-NEXT:    br label %[[LOOP]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[STEP]]
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[START]], [[TMP0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[START]], [[TMP0]]
 ; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
 entry:
@@ -49,7 +49,7 @@ define i32 @nsw_kept_same_sign(i32 %start.in, i32 %step.in, i32 %n) {
 ; CHECK-NEXT:    br label %[[LOOP]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[N]], [[STEP]]
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], [[START]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i32 [[TMP0]], [[START]]
 ; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
 entry:
@@ -288,7 +288,7 @@ define i32 @no_flag_leak_through_shared_udiv(i32 %start, i32 %n, i1 %c) {
 ; CHECK:       [[LOOP_2_LATCH]]:
 ; CHECK-NEXT:    br label %[[LOOP_2_HEADER]]
 ; CHECK:       [[EXIT_2]]:
-; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[N]], [[START]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add nuw i32 [[N]], [[START]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = udiv i32 [[TMP2]], 3
 ; CHECK-NEXT:    ret i32 [[TMP3]]
 ;
@@ -355,7 +355,7 @@ define ptr @exit_value_mul(ptr %first, ptr %last) {
 ; CHECK-NEXT:    [[TMP4:%.*]] = udiv i64 [[TMP3]], 24
 ; CHECK-NEXT:    [[TMP5:%.*]] = add i64 [[UMIN]], [[TMP4]]
 ; CHECK-NEXT:    [[TMP6:%.*]] = mul i64 [[TMP5]], 24
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP6]]
+; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[FIRST]], i64 [[TMP6]]
 ; CHECK-NEXT:    ret ptr [[SCEVGEP]]
 ; CHECK:       [[DONE]]:
 ; CHECK-NEXT:    ret ptr [[FIRST]]



More information about the llvm-commits mailing list