[llvm] [SCCP] Refine trunc with nsw/nuw flags (PR #87926)

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 7 08:00:32 PDT 2024


https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/87926

>From d76f7960890a25b4d34e5a7fe351fdb2c85a2a36 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sun, 7 Apr 2024 21:47:30 +0800
Subject: [PATCH 1/3] [SCCP][NFC] Precommit tests

---
 .../Transforms/SCCP/trunc-nuw-nsw-flags.ll    | 179 ++++++++++++++++++
 1 file changed, 179 insertions(+)
 create mode 100644 llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll

diff --git a/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll b/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll
new file mode 100644
index 00000000000000..0447c82bb55421
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll
@@ -0,0 +1,179 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes=ipsccp -S %s | FileCheck %s
+
+define i16 @range_from_and_nuw(i32 %a) {
+; CHECK-LABEL: define i16 @range_from_and_nuw(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[A]], 65535
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[AND1]] to i16
+; CHECK-NEXT:    ret i16 [[TRUNC1]]
+;
+entry:
+  %and1 = and i32 %a, 65535
+  %trunc1 = trunc i32 %and1 to i16
+  ret i16 %trunc1
+}
+
+define i8 @range_from_or_nsw(i16 %a) {
+; CHECK-LABEL: define i8 @range_from_or_nsw(
+; CHECK-SAME: i16 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND1:%.*]] = or i16 [[A]], -128
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[AND1]] to i8
+; CHECK-NEXT:    ret i8 [[TRUNC1]]
+;
+entry:
+  %and1 = or i16 %a, 65408
+  %trunc1 = trunc i16 %and1 to i8
+  ret i8 %trunc1
+}
+
+define i16 @range_from_and_nuw_nsw(i32 %a) {
+; CHECK-LABEL: define i16 @range_from_and_nuw_nsw(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[A]], 32767
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[AND1]] to i16
+; CHECK-NEXT:    ret i16 [[TRUNC1]]
+;
+entry:
+  %and1 = and i32 %a, 32767
+  %trunc1 = trunc i32 %and1 to i16
+  ret i16 %trunc1
+}
+
+define <4 x i16> @range_from_and_nuw_vec(<4 x i32> %a) {
+; CHECK-LABEL: define <4 x i16> @range_from_and_nuw_vec(
+; CHECK-SAME: <4 x i32> [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[AND1:%.*]] = and <4 x i32> [[A]], <i32 65535, i32 65535, i32 65535, i32 65535>
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc <4 x i32> [[AND1]] to <4 x i16>
+; CHECK-NEXT:    ret <4 x i16> [[TRUNC1]]
+;
+entry:
+  %and1 = and <4 x i32> %a, <i32 65535, i32 65535, i32 65535, i32 65535>
+  %trunc1 = trunc <4 x i32> %and1 to <4 x i16>
+  ret <4 x i16> %trunc1
+}
+
+define i4 @range_from_sge_sle(i8 %a) {
+; CHECK-LABEL: define i4 @range_from_sge_sle(
+; CHECK-SAME: i8 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SGT:%.*]] = icmp sge i8 [[A]], 0
+; CHECK-NEXT:    [[SLT:%.*]] = icmp sle i8 [[A]], 15
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[SGT]], [[SLT]]
+; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[A]], 7
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i8 [[A]] to i4
+; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i8 [[AND1]] to i4
+; CHECK-NEXT:    [[XOR1:%.*]] = xor i4 [[TRUNC1]], [[TRUNC2]]
+; CHECK-NEXT:    ret i4 [[XOR1]]
+; CHECK:       else:
+; CHECK-NEXT:    [[TRUNC3:%.*]] = trunc i8 [[A]] to i4
+; CHECK-NEXT:    ret i4 [[TRUNC3]]
+;
+entry:
+  %sgt = icmp sge i8 %a, 0
+  %slt = icmp sle i8 %a, 15
+  %and = and i1 %sgt, %slt
+  br i1 %and, label %then, label %else
+
+then:
+  %and1 = and i8 %a, 7
+
+  %trunc1 = trunc i8 %a to i4
+  %trunc2 = trunc i8 %and1 to i4
+  %xor1 = xor i4 %trunc1, %trunc2
+  ret i4 %xor1
+
+else:
+  %trunc3 = trunc i8 %a to i4
+  ret i4 %trunc3
+}
+
+define i16 @range_from_sext(i16 %a) {
+; CHECK-LABEL: define i16 @range_from_sext(
+; CHECK-SAME: i16 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SEXT1:%.*]] = sext i16 [[A]] to i32
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[SEXT1]] to i16
+; CHECK-NEXT:    ret i16 [[TRUNC1]]
+;
+entry:
+  %sext1 = sext i16 %a to i32
+  %trunc1 = trunc i32 %sext1 to i16
+  ret i16 %trunc1
+}
+
+define i16 @range_from_zext(i16 %a) {
+; CHECK-LABEL: define i16 @range_from_zext(
+; CHECK-SAME: i16 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ZEXT1:%.*]] = zext i16 [[A]] to i32
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[ZEXT1]] to i16
+; CHECK-NEXT:    ret i16 [[TRUNC1]]
+;
+entry:
+  %zext1 = zext i16 %a to i32
+  %trunc1 = trunc i32 %zext1 to i16
+  ret i16 %trunc1
+}
+
+define i1 @range_from_select_i1_nuw(i1 %c) {
+; CHECK-LABEL: define i1 @range_from_select_i1_nuw(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 1
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
+; CHECK-NEXT:    ret i1 [[TRUNC1]]
+;
+entry:
+  %select1 = select i1 %c, i16 0, i16 1
+  %trunc1 = trunc i16 %select1 to i1
+  ret i1 %trunc1
+}
+
+define i1 @range_from_select_i1_nsw(i1 %c) {
+; CHECK-LABEL: define i1 @range_from_select_i1_nsw(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 -1
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
+; CHECK-NEXT:    ret i1 [[TRUNC1]]
+;
+entry:
+  %select1 = select i1 %c, i16 0, i16 -1
+  %trunc1 = trunc i16 %select1 to i1
+  ret i1 %trunc1
+}
+
+define i1 @range_from_select_i1_fail(i1 %c) {
+; CHECK-LABEL: define i1 @range_from_select_i1_fail(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[C]], i16 1, i16 -1
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
+; CHECK-NEXT:    ret i1 [[TRUNC1]]
+;
+entry:
+  %select1 = select i1 %c, i16 1, i16 -1
+  %trunc1 = trunc i16 %select1 to i1
+  ret i1 %trunc1
+}
+
+define i8 @range_from_trunc_fail(i32 %a) {
+; CHECK-LABEL: define i8 @range_from_trunc_fail(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[A]] to i16
+; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i16 [[TRUNC1]] to i8
+; CHECK-NEXT:    ret i8 [[TRUNC2]]
+;
+entry:
+  %trunc1 = trunc i32 %a to i16
+  %trunc2 = trunc i16 %trunc1 to i8
+  ret i8 %trunc2
+}

>From 333b33934a0f7f901a38e1f5fb44a12eeab95b9c Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sun, 7 Apr 2024 19:28:48 +0800
Subject: [PATCH 2/3] [SCCP] Refine trunc with nsw/nuw flags

---
 llvm/lib/Transforms/Utils/SCCPSolver.cpp      | 15 +++++
 .../PhaseOrdering/AArch64/quant_4x4.ll        | 64 +++++++++----------
 .../PhaseOrdering/ARM/arm_mult_q15.ll         |  2 +-
 .../test/Transforms/SCCP/conditions-ranges.ll |  6 +-
 llvm/test/Transforms/SCCP/ip-ranges-casts.ll  |  4 +-
 .../Transforms/SCCP/trunc-nuw-nsw-flags.ll    | 18 +++---
 llvm/test/Transforms/SCCP/widening.ll         | 24 +++----
 7 files changed, 74 insertions(+), 59 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 38fc7763c5b204..3cec6623df33ec 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -146,6 +146,21 @@ static bool refineInstruction(SCCPSolver &Solver,
       Inst.setNonNeg();
       Changed = true;
     }
+  } else if (TruncInst *TI = dyn_cast<TruncInst>(&Inst)) {
+    auto Range = GetRange(Inst.getOperand(0));
+    uint64_t DestWidth = TI->getDestTy()->getScalarSizeInBits();
+    if (!TI->hasNoUnsignedWrap()) {
+      if (Range.getActiveBits() <= DestWidth) {
+        TI->setHasNoUnsignedWrap(true);
+        Changed = true;
+      }
+    }
+    if (!TI->hasNoSignedWrap()) {
+      if (Range.getMinSignedBits() <= DestWidth) {
+        TI->setHasNoSignedWrap(true);
+        Changed = true;
+      }
+    }
   }
 
   return Changed;
diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/quant_4x4.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/quant_4x4.ll
index d18b207e87076b..488c700ff98ffd 100644
--- a/llvm/test/Transforms/PhaseOrdering/AArch64/quant_4x4.ll
+++ b/llvm/test/Transforms/PhaseOrdering/AArch64/quant_4x4.ll
@@ -83,13 +83,13 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[CONV5]], [[CONV]]
 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[ADD]], [[CONV11]]
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[MUL]], 16
-; CHECK-NEXT:    [[CONV12:%.*]] = trunc i32 [[SHR]] to i16
+; CHECK-NEXT:    [[CONV12:%.*]] = trunc nuw i32 [[SHR]] to i16
 ; CHECK-NEXT:    br label [[IF_END:%.*]]
 ; CHECK:       if.else:
 ; CHECK-NEXT:    [[ADD21:%.*]] = sub nsw i32 [[CONV5]], [[CONV]]
 ; CHECK-NEXT:    [[MUL25:%.*]] = mul i32 [[ADD21]], [[CONV11]]
 ; CHECK-NEXT:    [[SHR26:%.*]] = lshr i32 [[MUL25]], 16
-; CHECK-NEXT:    [[TMP33:%.*]] = trunc i32 [[SHR26]] to i16
+; CHECK-NEXT:    [[TMP33:%.*]] = trunc nuw i32 [[SHR26]] to i16
 ; CHECK-NEXT:    [[CONV28:%.*]] = sub i16 0, [[TMP33]]
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
@@ -110,14 +110,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_1:%.*]] = sub nsw i32 [[CONV5_1]], [[CONV_1]]
 ; CHECK-NEXT:    [[MUL25_1:%.*]] = mul i32 [[ADD21_1]], [[CONV11_1]]
 ; CHECK-NEXT:    [[SHR26_1:%.*]] = lshr i32 [[MUL25_1]], 16
-; CHECK-NEXT:    [[TMP37:%.*]] = trunc i32 [[SHR26_1]] to i16
+; CHECK-NEXT:    [[TMP37:%.*]] = trunc nuw i32 [[SHR26_1]] to i16
 ; CHECK-NEXT:    [[CONV28_1:%.*]] = sub i16 0, [[TMP37]]
 ; CHECK-NEXT:    br label [[IF_END_1:%.*]]
 ; CHECK:       if.then.1:
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i32 [[CONV5_1]], [[CONV_1]]
 ; CHECK-NEXT:    [[MUL_1:%.*]] = mul i32 [[ADD_1]], [[CONV11_1]]
 ; CHECK-NEXT:    [[SHR_1:%.*]] = lshr i32 [[MUL_1]], 16
-; CHECK-NEXT:    [[CONV12_1:%.*]] = trunc i32 [[SHR_1]] to i16
+; CHECK-NEXT:    [[CONV12_1:%.*]] = trunc nuw i32 [[SHR_1]] to i16
 ; CHECK-NEXT:    br label [[IF_END_1]]
 ; CHECK:       if.end.1:
 ; CHECK-NEXT:    [[STOREMERGE_1:%.*]] = phi i16 [ [[CONV28_1]], [[IF_ELSE_1]] ], [ [[CONV12_1]], [[IF_THEN_1]] ]
@@ -138,14 +138,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_2:%.*]] = sub nsw i32 [[CONV5_2]], [[CONV_2]]
 ; CHECK-NEXT:    [[MUL25_2:%.*]] = mul i32 [[ADD21_2]], [[CONV11_2]]
 ; CHECK-NEXT:    [[SHR26_2:%.*]] = lshr i32 [[MUL25_2]], 16
-; CHECK-NEXT:    [[TMP41:%.*]] = trunc i32 [[SHR26_2]] to i16
+; CHECK-NEXT:    [[TMP41:%.*]] = trunc nuw i32 [[SHR26_2]] to i16
 ; CHECK-NEXT:    [[CONV28_2:%.*]] = sub i16 0, [[TMP41]]
 ; CHECK-NEXT:    br label [[IF_END_2:%.*]]
 ; CHECK:       if.then.2:
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i32 [[CONV5_2]], [[CONV_2]]
 ; CHECK-NEXT:    [[MUL_2:%.*]] = mul i32 [[ADD_2]], [[CONV11_2]]
 ; CHECK-NEXT:    [[SHR_2:%.*]] = lshr i32 [[MUL_2]], 16
-; CHECK-NEXT:    [[CONV12_2:%.*]] = trunc i32 [[SHR_2]] to i16
+; CHECK-NEXT:    [[CONV12_2:%.*]] = trunc nuw i32 [[SHR_2]] to i16
 ; CHECK-NEXT:    br label [[IF_END_2]]
 ; CHECK:       if.end.2:
 ; CHECK-NEXT:    [[STOREMERGE_2:%.*]] = phi i16 [ [[CONV28_2]], [[IF_ELSE_2]] ], [ [[CONV12_2]], [[IF_THEN_2]] ]
@@ -166,14 +166,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_3:%.*]] = sub nsw i32 [[CONV5_3]], [[CONV_3]]
 ; CHECK-NEXT:    [[MUL25_3:%.*]] = mul i32 [[ADD21_3]], [[CONV11_3]]
 ; CHECK-NEXT:    [[SHR26_3:%.*]] = lshr i32 [[MUL25_3]], 16
-; CHECK-NEXT:    [[TMP45:%.*]] = trunc i32 [[SHR26_3]] to i16
+; CHECK-NEXT:    [[TMP45:%.*]] = trunc nuw i32 [[SHR26_3]] to i16
 ; CHECK-NEXT:    [[CONV28_3:%.*]] = sub i16 0, [[TMP45]]
 ; CHECK-NEXT:    br label [[IF_END_3:%.*]]
 ; CHECK:       if.then.3:
 ; CHECK-NEXT:    [[ADD_3:%.*]] = add nuw nsw i32 [[CONV5_3]], [[CONV_3]]
 ; CHECK-NEXT:    [[MUL_3:%.*]] = mul i32 [[ADD_3]], [[CONV11_3]]
 ; CHECK-NEXT:    [[SHR_3:%.*]] = lshr i32 [[MUL_3]], 16
-; CHECK-NEXT:    [[CONV12_3:%.*]] = trunc i32 [[SHR_3]] to i16
+; CHECK-NEXT:    [[CONV12_3:%.*]] = trunc nuw i32 [[SHR_3]] to i16
 ; CHECK-NEXT:    br label [[IF_END_3]]
 ; CHECK:       if.end.3:
 ; CHECK-NEXT:    [[STOREMERGE_3:%.*]] = phi i16 [ [[CONV28_3]], [[IF_ELSE_3]] ], [ [[CONV12_3]], [[IF_THEN_3]] ]
@@ -194,14 +194,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_4:%.*]] = sub nsw i32 [[CONV5_4]], [[CONV_4]]
 ; CHECK-NEXT:    [[MUL25_4:%.*]] = mul i32 [[ADD21_4]], [[CONV11_4]]
 ; CHECK-NEXT:    [[SHR26_4:%.*]] = lshr i32 [[MUL25_4]], 16
-; CHECK-NEXT:    [[TMP49:%.*]] = trunc i32 [[SHR26_4]] to i16
+; CHECK-NEXT:    [[TMP49:%.*]] = trunc nuw i32 [[SHR26_4]] to i16
 ; CHECK-NEXT:    [[CONV28_4:%.*]] = sub i16 0, [[TMP49]]
 ; CHECK-NEXT:    br label [[IF_END_4:%.*]]
 ; CHECK:       if.then.4:
 ; CHECK-NEXT:    [[ADD_4:%.*]] = add nuw nsw i32 [[CONV5_4]], [[CONV_4]]
 ; CHECK-NEXT:    [[MUL_4:%.*]] = mul i32 [[ADD_4]], [[CONV11_4]]
 ; CHECK-NEXT:    [[SHR_4:%.*]] = lshr i32 [[MUL_4]], 16
-; CHECK-NEXT:    [[CONV12_4:%.*]] = trunc i32 [[SHR_4]] to i16
+; CHECK-NEXT:    [[CONV12_4:%.*]] = trunc nuw i32 [[SHR_4]] to i16
 ; CHECK-NEXT:    br label [[IF_END_4]]
 ; CHECK:       if.end.4:
 ; CHECK-NEXT:    [[STOREMERGE_4:%.*]] = phi i16 [ [[CONV28_4]], [[IF_ELSE_4]] ], [ [[CONV12_4]], [[IF_THEN_4]] ]
@@ -222,14 +222,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_5:%.*]] = sub nsw i32 [[CONV5_5]], [[CONV_5]]
 ; CHECK-NEXT:    [[MUL25_5:%.*]] = mul i32 [[ADD21_5]], [[CONV11_5]]
 ; CHECK-NEXT:    [[SHR26_5:%.*]] = lshr i32 [[MUL25_5]], 16
-; CHECK-NEXT:    [[TMP53:%.*]] = trunc i32 [[SHR26_5]] to i16
+; CHECK-NEXT:    [[TMP53:%.*]] = trunc nuw i32 [[SHR26_5]] to i16
 ; CHECK-NEXT:    [[CONV28_5:%.*]] = sub i16 0, [[TMP53]]
 ; CHECK-NEXT:    br label [[IF_END_5:%.*]]
 ; CHECK:       if.then.5:
 ; CHECK-NEXT:    [[ADD_5:%.*]] = add nuw nsw i32 [[CONV5_5]], [[CONV_5]]
 ; CHECK-NEXT:    [[MUL_5:%.*]] = mul i32 [[ADD_5]], [[CONV11_5]]
 ; CHECK-NEXT:    [[SHR_5:%.*]] = lshr i32 [[MUL_5]], 16
-; CHECK-NEXT:    [[CONV12_5:%.*]] = trunc i32 [[SHR_5]] to i16
+; CHECK-NEXT:    [[CONV12_5:%.*]] = trunc nuw i32 [[SHR_5]] to i16
 ; CHECK-NEXT:    br label [[IF_END_5]]
 ; CHECK:       if.end.5:
 ; CHECK-NEXT:    [[STOREMERGE_5:%.*]] = phi i16 [ [[CONV28_5]], [[IF_ELSE_5]] ], [ [[CONV12_5]], [[IF_THEN_5]] ]
@@ -250,14 +250,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_6:%.*]] = sub nsw i32 [[CONV5_6]], [[CONV_6]]
 ; CHECK-NEXT:    [[MUL25_6:%.*]] = mul i32 [[ADD21_6]], [[CONV11_6]]
 ; CHECK-NEXT:    [[SHR26_6:%.*]] = lshr i32 [[MUL25_6]], 16
-; CHECK-NEXT:    [[TMP57:%.*]] = trunc i32 [[SHR26_6]] to i16
+; CHECK-NEXT:    [[TMP57:%.*]] = trunc nuw i32 [[SHR26_6]] to i16
 ; CHECK-NEXT:    [[CONV28_6:%.*]] = sub i16 0, [[TMP57]]
 ; CHECK-NEXT:    br label [[IF_END_6:%.*]]
 ; CHECK:       if.then.6:
 ; CHECK-NEXT:    [[ADD_6:%.*]] = add nuw nsw i32 [[CONV5_6]], [[CONV_6]]
 ; CHECK-NEXT:    [[MUL_6:%.*]] = mul i32 [[ADD_6]], [[CONV11_6]]
 ; CHECK-NEXT:    [[SHR_6:%.*]] = lshr i32 [[MUL_6]], 16
-; CHECK-NEXT:    [[CONV12_6:%.*]] = trunc i32 [[SHR_6]] to i16
+; CHECK-NEXT:    [[CONV12_6:%.*]] = trunc nuw i32 [[SHR_6]] to i16
 ; CHECK-NEXT:    br label [[IF_END_6]]
 ; CHECK:       if.end.6:
 ; CHECK-NEXT:    [[STOREMERGE_6:%.*]] = phi i16 [ [[CONV28_6]], [[IF_ELSE_6]] ], [ [[CONV12_6]], [[IF_THEN_6]] ]
@@ -278,14 +278,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_7:%.*]] = sub nsw i32 [[CONV5_7]], [[CONV_7]]
 ; CHECK-NEXT:    [[MUL25_7:%.*]] = mul i32 [[ADD21_7]], [[CONV11_7]]
 ; CHECK-NEXT:    [[SHR26_7:%.*]] = lshr i32 [[MUL25_7]], 16
-; CHECK-NEXT:    [[TMP61:%.*]] = trunc i32 [[SHR26_7]] to i16
+; CHECK-NEXT:    [[TMP61:%.*]] = trunc nuw i32 [[SHR26_7]] to i16
 ; CHECK-NEXT:    [[CONV28_7:%.*]] = sub i16 0, [[TMP61]]
 ; CHECK-NEXT:    br label [[IF_END_7:%.*]]
 ; CHECK:       if.then.7:
 ; CHECK-NEXT:    [[ADD_7:%.*]] = add nuw nsw i32 [[CONV5_7]], [[CONV_7]]
 ; CHECK-NEXT:    [[MUL_7:%.*]] = mul i32 [[ADD_7]], [[CONV11_7]]
 ; CHECK-NEXT:    [[SHR_7:%.*]] = lshr i32 [[MUL_7]], 16
-; CHECK-NEXT:    [[CONV12_7:%.*]] = trunc i32 [[SHR_7]] to i16
+; CHECK-NEXT:    [[CONV12_7:%.*]] = trunc nuw i32 [[SHR_7]] to i16
 ; CHECK-NEXT:    br label [[IF_END_7]]
 ; CHECK:       if.end.7:
 ; CHECK-NEXT:    [[STOREMERGE_7:%.*]] = phi i16 [ [[CONV28_7]], [[IF_ELSE_7]] ], [ [[CONV12_7]], [[IF_THEN_7]] ]
@@ -306,14 +306,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_8:%.*]] = sub nsw i32 [[CONV5_8]], [[CONV_8]]
 ; CHECK-NEXT:    [[MUL25_8:%.*]] = mul i32 [[ADD21_8]], [[CONV11_8]]
 ; CHECK-NEXT:    [[SHR26_8:%.*]] = lshr i32 [[MUL25_8]], 16
-; CHECK-NEXT:    [[TMP65:%.*]] = trunc i32 [[SHR26_8]] to i16
+; CHECK-NEXT:    [[TMP65:%.*]] = trunc nuw i32 [[SHR26_8]] to i16
 ; CHECK-NEXT:    [[CONV28_8:%.*]] = sub i16 0, [[TMP65]]
 ; CHECK-NEXT:    br label [[IF_END_8:%.*]]
 ; CHECK:       if.then.8:
 ; CHECK-NEXT:    [[ADD_8:%.*]] = add nuw nsw i32 [[CONV5_8]], [[CONV_8]]
 ; CHECK-NEXT:    [[MUL_8:%.*]] = mul i32 [[ADD_8]], [[CONV11_8]]
 ; CHECK-NEXT:    [[SHR_8:%.*]] = lshr i32 [[MUL_8]], 16
-; CHECK-NEXT:    [[CONV12_8:%.*]] = trunc i32 [[SHR_8]] to i16
+; CHECK-NEXT:    [[CONV12_8:%.*]] = trunc nuw i32 [[SHR_8]] to i16
 ; CHECK-NEXT:    br label [[IF_END_8]]
 ; CHECK:       if.end.8:
 ; CHECK-NEXT:    [[STOREMERGE_8:%.*]] = phi i16 [ [[CONV28_8]], [[IF_ELSE_8]] ], [ [[CONV12_8]], [[IF_THEN_8]] ]
@@ -334,14 +334,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_9:%.*]] = sub nsw i32 [[CONV5_9]], [[CONV_9]]
 ; CHECK-NEXT:    [[MUL25_9:%.*]] = mul i32 [[ADD21_9]], [[CONV11_9]]
 ; CHECK-NEXT:    [[SHR26_9:%.*]] = lshr i32 [[MUL25_9]], 16
-; CHECK-NEXT:    [[TMP69:%.*]] = trunc i32 [[SHR26_9]] to i16
+; CHECK-NEXT:    [[TMP69:%.*]] = trunc nuw i32 [[SHR26_9]] to i16
 ; CHECK-NEXT:    [[CONV28_9:%.*]] = sub i16 0, [[TMP69]]
 ; CHECK-NEXT:    br label [[IF_END_9:%.*]]
 ; CHECK:       if.then.9:
 ; CHECK-NEXT:    [[ADD_9:%.*]] = add nuw nsw i32 [[CONV5_9]], [[CONV_9]]
 ; CHECK-NEXT:    [[MUL_9:%.*]] = mul i32 [[ADD_9]], [[CONV11_9]]
 ; CHECK-NEXT:    [[SHR_9:%.*]] = lshr i32 [[MUL_9]], 16
-; CHECK-NEXT:    [[CONV12_9:%.*]] = trunc i32 [[SHR_9]] to i16
+; CHECK-NEXT:    [[CONV12_9:%.*]] = trunc nuw i32 [[SHR_9]] to i16
 ; CHECK-NEXT:    br label [[IF_END_9]]
 ; CHECK:       if.end.9:
 ; CHECK-NEXT:    [[STOREMERGE_9:%.*]] = phi i16 [ [[CONV28_9]], [[IF_ELSE_9]] ], [ [[CONV12_9]], [[IF_THEN_9]] ]
@@ -362,14 +362,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_10:%.*]] = sub nsw i32 [[CONV5_10]], [[CONV_10]]
 ; CHECK-NEXT:    [[MUL25_10:%.*]] = mul i32 [[ADD21_10]], [[CONV11_10]]
 ; CHECK-NEXT:    [[SHR26_10:%.*]] = lshr i32 [[MUL25_10]], 16
-; CHECK-NEXT:    [[TMP73:%.*]] = trunc i32 [[SHR26_10]] to i16
+; CHECK-NEXT:    [[TMP73:%.*]] = trunc nuw i32 [[SHR26_10]] to i16
 ; CHECK-NEXT:    [[CONV28_10:%.*]] = sub i16 0, [[TMP73]]
 ; CHECK-NEXT:    br label [[IF_END_10:%.*]]
 ; CHECK:       if.then.10:
 ; CHECK-NEXT:    [[ADD_10:%.*]] = add nuw nsw i32 [[CONV5_10]], [[CONV_10]]
 ; CHECK-NEXT:    [[MUL_10:%.*]] = mul i32 [[ADD_10]], [[CONV11_10]]
 ; CHECK-NEXT:    [[SHR_10:%.*]] = lshr i32 [[MUL_10]], 16
-; CHECK-NEXT:    [[CONV12_10:%.*]] = trunc i32 [[SHR_10]] to i16
+; CHECK-NEXT:    [[CONV12_10:%.*]] = trunc nuw i32 [[SHR_10]] to i16
 ; CHECK-NEXT:    br label [[IF_END_10]]
 ; CHECK:       if.end.10:
 ; CHECK-NEXT:    [[STOREMERGE_10:%.*]] = phi i16 [ [[CONV28_10]], [[IF_ELSE_10]] ], [ [[CONV12_10]], [[IF_THEN_10]] ]
@@ -390,14 +390,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_11:%.*]] = sub nsw i32 [[CONV5_11]], [[CONV_11]]
 ; CHECK-NEXT:    [[MUL25_11:%.*]] = mul i32 [[ADD21_11]], [[CONV11_11]]
 ; CHECK-NEXT:    [[SHR26_11:%.*]] = lshr i32 [[MUL25_11]], 16
-; CHECK-NEXT:    [[TMP77:%.*]] = trunc i32 [[SHR26_11]] to i16
+; CHECK-NEXT:    [[TMP77:%.*]] = trunc nuw i32 [[SHR26_11]] to i16
 ; CHECK-NEXT:    [[CONV28_11:%.*]] = sub i16 0, [[TMP77]]
 ; CHECK-NEXT:    br label [[IF_END_11:%.*]]
 ; CHECK:       if.then.11:
 ; CHECK-NEXT:    [[ADD_11:%.*]] = add nuw nsw i32 [[CONV5_11]], [[CONV_11]]
 ; CHECK-NEXT:    [[MUL_11:%.*]] = mul i32 [[ADD_11]], [[CONV11_11]]
 ; CHECK-NEXT:    [[SHR_11:%.*]] = lshr i32 [[MUL_11]], 16
-; CHECK-NEXT:    [[CONV12_11:%.*]] = trunc i32 [[SHR_11]] to i16
+; CHECK-NEXT:    [[CONV12_11:%.*]] = trunc nuw i32 [[SHR_11]] to i16
 ; CHECK-NEXT:    br label [[IF_END_11]]
 ; CHECK:       if.end.11:
 ; CHECK-NEXT:    [[STOREMERGE_11:%.*]] = phi i16 [ [[CONV28_11]], [[IF_ELSE_11]] ], [ [[CONV12_11]], [[IF_THEN_11]] ]
@@ -418,14 +418,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_12:%.*]] = sub nsw i32 [[CONV5_12]], [[CONV_12]]
 ; CHECK-NEXT:    [[MUL25_12:%.*]] = mul i32 [[ADD21_12]], [[CONV11_12]]
 ; CHECK-NEXT:    [[SHR26_12:%.*]] = lshr i32 [[MUL25_12]], 16
-; CHECK-NEXT:    [[TMP81:%.*]] = trunc i32 [[SHR26_12]] to i16
+; CHECK-NEXT:    [[TMP81:%.*]] = trunc nuw i32 [[SHR26_12]] to i16
 ; CHECK-NEXT:    [[CONV28_12:%.*]] = sub i16 0, [[TMP81]]
 ; CHECK-NEXT:    br label [[IF_END_12:%.*]]
 ; CHECK:       if.then.12:
 ; CHECK-NEXT:    [[ADD_12:%.*]] = add nuw nsw i32 [[CONV5_12]], [[CONV_12]]
 ; CHECK-NEXT:    [[MUL_12:%.*]] = mul i32 [[ADD_12]], [[CONV11_12]]
 ; CHECK-NEXT:    [[SHR_12:%.*]] = lshr i32 [[MUL_12]], 16
-; CHECK-NEXT:    [[CONV12_12:%.*]] = trunc i32 [[SHR_12]] to i16
+; CHECK-NEXT:    [[CONV12_12:%.*]] = trunc nuw i32 [[SHR_12]] to i16
 ; CHECK-NEXT:    br label [[IF_END_12]]
 ; CHECK:       if.end.12:
 ; CHECK-NEXT:    [[STOREMERGE_12:%.*]] = phi i16 [ [[CONV28_12]], [[IF_ELSE_12]] ], [ [[CONV12_12]], [[IF_THEN_12]] ]
@@ -446,14 +446,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_13:%.*]] = sub nsw i32 [[CONV5_13]], [[CONV_13]]
 ; CHECK-NEXT:    [[MUL25_13:%.*]] = mul i32 [[ADD21_13]], [[CONV11_13]]
 ; CHECK-NEXT:    [[SHR26_13:%.*]] = lshr i32 [[MUL25_13]], 16
-; CHECK-NEXT:    [[TMP85:%.*]] = trunc i32 [[SHR26_13]] to i16
+; CHECK-NEXT:    [[TMP85:%.*]] = trunc nuw i32 [[SHR26_13]] to i16
 ; CHECK-NEXT:    [[CONV28_13:%.*]] = sub i16 0, [[TMP85]]
 ; CHECK-NEXT:    br label [[IF_END_13:%.*]]
 ; CHECK:       if.then.13:
 ; CHECK-NEXT:    [[ADD_13:%.*]] = add nuw nsw i32 [[CONV5_13]], [[CONV_13]]
 ; CHECK-NEXT:    [[MUL_13:%.*]] = mul i32 [[ADD_13]], [[CONV11_13]]
 ; CHECK-NEXT:    [[SHR_13:%.*]] = lshr i32 [[MUL_13]], 16
-; CHECK-NEXT:    [[CONV12_13:%.*]] = trunc i32 [[SHR_13]] to i16
+; CHECK-NEXT:    [[CONV12_13:%.*]] = trunc nuw i32 [[SHR_13]] to i16
 ; CHECK-NEXT:    br label [[IF_END_13]]
 ; CHECK:       if.end.13:
 ; CHECK-NEXT:    [[STOREMERGE_13:%.*]] = phi i16 [ [[CONV28_13]], [[IF_ELSE_13]] ], [ [[CONV12_13]], [[IF_THEN_13]] ]
@@ -474,14 +474,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_14:%.*]] = sub nsw i32 [[CONV5_14]], [[CONV_14]]
 ; CHECK-NEXT:    [[MUL25_14:%.*]] = mul i32 [[ADD21_14]], [[CONV11_14]]
 ; CHECK-NEXT:    [[SHR26_14:%.*]] = lshr i32 [[MUL25_14]], 16
-; CHECK-NEXT:    [[TMP89:%.*]] = trunc i32 [[SHR26_14]] to i16
+; CHECK-NEXT:    [[TMP89:%.*]] = trunc nuw i32 [[SHR26_14]] to i16
 ; CHECK-NEXT:    [[CONV28_14:%.*]] = sub i16 0, [[TMP89]]
 ; CHECK-NEXT:    br label [[IF_END_14:%.*]]
 ; CHECK:       if.then.14:
 ; CHECK-NEXT:    [[ADD_14:%.*]] = add nuw nsw i32 [[CONV5_14]], [[CONV_14]]
 ; CHECK-NEXT:    [[MUL_14:%.*]] = mul i32 [[ADD_14]], [[CONV11_14]]
 ; CHECK-NEXT:    [[SHR_14:%.*]] = lshr i32 [[MUL_14]], 16
-; CHECK-NEXT:    [[CONV12_14:%.*]] = trunc i32 [[SHR_14]] to i16
+; CHECK-NEXT:    [[CONV12_14:%.*]] = trunc nuw i32 [[SHR_14]] to i16
 ; CHECK-NEXT:    br label [[IF_END_14]]
 ; CHECK:       if.end.14:
 ; CHECK-NEXT:    [[STOREMERGE_14:%.*]] = phi i16 [ [[CONV28_14]], [[IF_ELSE_14]] ], [ [[CONV12_14]], [[IF_THEN_14]] ]
@@ -502,14 +502,14 @@ define i32 @quant_4x4(ptr noundef %dct, ptr noundef %mf, ptr noundef %bias) {
 ; CHECK-NEXT:    [[ADD21_15:%.*]] = sub nsw i32 [[CONV5_15]], [[CONV_15]]
 ; CHECK-NEXT:    [[MUL25_15:%.*]] = mul i32 [[ADD21_15]], [[CONV11_15]]
 ; CHECK-NEXT:    [[SHR26_15:%.*]] = lshr i32 [[MUL25_15]], 16
-; CHECK-NEXT:    [[TMP93:%.*]] = trunc i32 [[SHR26_15]] to i16
+; CHECK-NEXT:    [[TMP93:%.*]] = trunc nuw i32 [[SHR26_15]] to i16
 ; CHECK-NEXT:    [[CONV28_15:%.*]] = sub i16 0, [[TMP93]]
 ; CHECK-NEXT:    br label [[IF_END_15]]
 ; CHECK:       if.then.15:
 ; CHECK-NEXT:    [[ADD_15:%.*]] = add nuw nsw i32 [[CONV5_15]], [[CONV_15]]
 ; CHECK-NEXT:    [[MUL_15:%.*]] = mul i32 [[ADD_15]], [[CONV11_15]]
 ; CHECK-NEXT:    [[SHR_15:%.*]] = lshr i32 [[MUL_15]], 16
-; CHECK-NEXT:    [[CONV12_15:%.*]] = trunc i32 [[SHR_15]] to i16
+; CHECK-NEXT:    [[CONV12_15:%.*]] = trunc nuw i32 [[SHR_15]] to i16
 ; CHECK-NEXT:    br label [[IF_END_15]]
 ; CHECK:       if.end.15:
 ; CHECK-NEXT:    [[STOREMERGE_15:%.*]] = phi i16 [ [[CONV28_15]], [[IF_ELSE_15]] ], [ [[CONV12_15]], [[IF_THEN_15]] ]
diff --git a/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll b/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll
index 36bcda4c43ca9b..c6126727598ef2 100644
--- a/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll
+++ b/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll
@@ -69,7 +69,7 @@ define void @arm_mult_q15(ptr %pSrcA, ptr %pSrcB, ptr noalias %pDst, i32 %blockS
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]]
 ; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[MUL]], 15
 ; CHECK-NEXT:    [[SPEC_SELECT_I:%.*]] = tail call i32 @llvm.smin.i32(i32 [[SHR]], i32 32767)
-; CHECK-NEXT:    [[CONV3:%.*]] = trunc i32 [[SPEC_SELECT_I]] to i16
+; CHECK-NEXT:    [[CONV3:%.*]] = trunc nsw i32 [[SPEC_SELECT_I]] to i16
 ; CHECK-NEXT:    [[INCDEC_PTR4]] = getelementptr inbounds i8, ptr [[PDST_ADDR_04]], i32 2
 ; CHECK-NEXT:    store i16 [[CONV3]], ptr [[PDST_ADDR_04]], align 2
 ; CHECK-NEXT:    [[DEC]] = add i32 [[BLKCNT_06]], -1
diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll
index f17b6c1317263b..25719d2bee521c 100644
--- a/llvm/test/Transforms/SCCP/conditions-ranges.ll
+++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll
@@ -178,7 +178,7 @@ define i32 @f5(i64 %sz) {
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[COND]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
 ; CHECK-NEXT:    ret i32 [[CONV]]
 ;
 entry:
@@ -759,7 +759,7 @@ define i32 @udiv_1(i64 %sz) {
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[COND]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
 ; CHECK-NEXT:    ret i32 [[CONV]]
 ;
 entry:
@@ -786,7 +786,7 @@ define i32 @udiv_2(i64 %sz) {
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
 ; CHECK-NEXT:    [[COND:%.*]] = phi i64 [ 0, [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[COND]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = trunc nuw nsw i64 [[COND]] to i32
 ; CHECK-NEXT:    ret i32 [[CONV]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SCCP/ip-ranges-casts.ll b/llvm/test/Transforms/SCCP/ip-ranges-casts.ll
index b97b3a0c458168..80d90922c2fbdb 100644
--- a/llvm/test/Transforms/SCCP/ip-ranges-casts.ll
+++ b/llvm/test/Transforms/SCCP/ip-ranges-casts.ll
@@ -4,7 +4,7 @@
 ; x = [100, 301)
 define internal i1 @f.trunc(i32 %x) {
 ; CHECK-LABEL: @f.trunc(
-; CHECK-NEXT:    [[T_1:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT:    [[T_1:%.*]] = trunc nuw nsw i32 [[X:%.*]] to i16
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i16 [[T_1]], 299
 ; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i16 [[T_1]], 101
 ; CHECK-NEXT:    [[RES_1:%.*]] = add nuw nsw i1 false, [[C_2]]
@@ -329,7 +329,7 @@ define i64 @caller.sext_to_zext(i32 %i) {
 ; CHECK-LABEL: @caller.sext_to_zext(
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[I:%.*]], 9
 ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
-; CHECK-NEXT:    [[T:%.*]] = call i64 @f.sext_to_zext(i32 [[CONV]])
+; CHECK-NEXT:    [[T:%.*]] = call i64 @f.sext_to_zext(i32 [[CONV]]), !range [[RNG0:![0-9]+]]
 ; CHECK-NEXT:    ret i64 [[T]]
 ;
   %cmp = icmp sle i32 %i, 9
diff --git a/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll b/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll
index 0447c82bb55421..fc3e56011d46cd 100644
--- a/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll
+++ b/llvm/test/Transforms/SCCP/trunc-nuw-nsw-flags.ll
@@ -6,7 +6,7 @@ define i16 @range_from_and_nuw(i32 %a) {
 ; CHECK-SAME: i32 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[A]], 65535
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[AND1]] to i16
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nuw i32 [[AND1]] to i16
 ; CHECK-NEXT:    ret i16 [[TRUNC1]]
 ;
 entry:
@@ -20,7 +20,7 @@ define i8 @range_from_or_nsw(i16 %a) {
 ; CHECK-SAME: i16 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AND1:%.*]] = or i16 [[A]], -128
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[AND1]] to i8
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nsw i16 [[AND1]] to i8
 ; CHECK-NEXT:    ret i8 [[TRUNC1]]
 ;
 entry:
@@ -34,7 +34,7 @@ define i16 @range_from_and_nuw_nsw(i32 %a) {
 ; CHECK-SAME: i32 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[A]], 32767
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[AND1]] to i16
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nuw nsw i32 [[AND1]] to i16
 ; CHECK-NEXT:    ret i16 [[TRUNC1]]
 ;
 entry:
@@ -67,8 +67,8 @@ define i4 @range_from_sge_sle(i8 %a) {
 ; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
 ; CHECK-NEXT:    [[AND1:%.*]] = and i8 [[A]], 7
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i8 [[A]] to i4
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i8 [[AND1]] to i4
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nuw i8 [[A]] to i4
+; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc nuw nsw i8 [[AND1]] to i4
 ; CHECK-NEXT:    [[XOR1:%.*]] = xor i4 [[TRUNC1]], [[TRUNC2]]
 ; CHECK-NEXT:    ret i4 [[XOR1]]
 ; CHECK:       else:
@@ -99,7 +99,7 @@ define i16 @range_from_sext(i16 %a) {
 ; CHECK-SAME: i16 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SEXT1:%.*]] = sext i16 [[A]] to i32
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[SEXT1]] to i16
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nsw i32 [[SEXT1]] to i16
 ; CHECK-NEXT:    ret i16 [[TRUNC1]]
 ;
 entry:
@@ -113,7 +113,7 @@ define i16 @range_from_zext(i16 %a) {
 ; CHECK-SAME: i16 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[ZEXT1:%.*]] = zext i16 [[A]] to i32
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i32 [[ZEXT1]] to i16
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nuw i32 [[ZEXT1]] to i16
 ; CHECK-NEXT:    ret i16 [[TRUNC1]]
 ;
 entry:
@@ -127,7 +127,7 @@ define i1 @range_from_select_i1_nuw(i1 %c) {
 ; CHECK-SAME: i1 [[C:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 1
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nuw i16 [[SELECT1]] to i1
 ; CHECK-NEXT:    ret i1 [[TRUNC1]]
 ;
 entry:
@@ -141,7 +141,7 @@ define i1 @range_from_select_i1_nsw(i1 %c) {
 ; CHECK-SAME: i1 [[C:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[C]], i16 0, i16 -1
-; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc i16 [[SELECT1]] to i1
+; CHECK-NEXT:    [[TRUNC1:%.*]] = trunc nsw i16 [[SELECT1]] to i1
 ; CHECK-NEXT:    ret i1 [[TRUNC1]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SCCP/widening.ll b/llvm/test/Transforms/SCCP/widening.ll
index 2223ca44bccdbb..473594eb988da3 100644
--- a/llvm/test/Transforms/SCCP/widening.ll
+++ b/llvm/test/Transforms/SCCP/widening.ll
@@ -438,9 +438,9 @@ define void @foo(ptr %arg) {
 ; SCCP-NEXT:    [[TMP:%.*]] = zext i8 undef to i32
 ; SCCP-NEXT:    [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 8
 ; SCCP-NEXT:    switch i32 [[TMP]], label [[BB20:%.*]] [
-; SCCP-NEXT:    i32 1, label [[BB3:%.*]]
-; SCCP-NEXT:    i32 2, label [[BB4:%.*]]
-; SCCP-NEXT:    i32 4, label [[BB19:%.*]]
+; SCCP-NEXT:      i32 1, label [[BB3:%.*]]
+; SCCP-NEXT:      i32 2, label [[BB4:%.*]]
+; SCCP-NEXT:      i32 4, label [[BB19:%.*]]
 ; SCCP-NEXT:    ]
 ; SCCP:       bb3:
 ; SCCP-NEXT:    unreachable
@@ -449,7 +449,7 @@ define void @foo(ptr %arg) {
 ; SCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
 ; SCCP-NEXT:    [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
 ; SCCP-NEXT:    [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
-; SCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
+; SCCP-NEXT:    [[TMP9:%.*]] = trunc nuw nsw i64 [[TMP8]] to i32
 ; SCCP-NEXT:    [[TMP10:%.*]] = zext nneg i32 [[TMP9]] to i64
 ; SCCP-NEXT:    br label [[BB11:%.*]]
 ; SCCP:       bb11:
@@ -475,9 +475,9 @@ define void @foo(ptr %arg) {
 ; IPSCCP-NEXT:    [[TMP:%.*]] = zext i8 undef to i32
 ; IPSCCP-NEXT:    [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 8
 ; IPSCCP-NEXT:    switch i32 [[TMP]], label [[BB20:%.*]] [
-; IPSCCP-NEXT:    i32 1, label [[BB3:%.*]]
-; IPSCCP-NEXT:    i32 2, label [[BB4:%.*]]
-; IPSCCP-NEXT:    i32 4, label [[BB19:%.*]]
+; IPSCCP-NEXT:      i32 1, label [[BB3:%.*]]
+; IPSCCP-NEXT:      i32 2, label [[BB4:%.*]]
+; IPSCCP-NEXT:      i32 4, label [[BB19:%.*]]
 ; IPSCCP-NEXT:    ]
 ; IPSCCP:       bb3:
 ; IPSCCP-NEXT:    unreachable
@@ -486,7 +486,7 @@ define void @foo(ptr %arg) {
 ; IPSCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
 ; IPSCCP-NEXT:    [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
 ; IPSCCP-NEXT:    [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
-; IPSCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
+; IPSCCP-NEXT:    [[TMP9:%.*]] = trunc nuw nsw i64 [[TMP8]] to i32
 ; IPSCCP-NEXT:    [[TMP10:%.*]] = zext nneg i32 [[TMP9]] to i64
 ; IPSCCP-NEXT:    br label [[BB11:%.*]]
 ; IPSCCP:       bb11:
@@ -615,7 +615,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
 ; SCCP-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
 ; SCCP-NEXT:    br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
 ; SCCP:       bb23:
-; SCCP-NEXT:    [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
+; SCCP-NEXT:    [[TMP24:%.*]] = trunc nuw i32 [[TMP3]] to i16
 ; SCCP-NEXT:    store i16 [[TMP24]], ptr [[TMP17]], align 2
 ; SCCP-NEXT:    br label [[BB31]]
 ; SCCP:       bb25:
@@ -639,7 +639,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
 ; SCCP-NEXT:    br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
 ; SCCP:       bb39:
 ; SCCP-NEXT:    [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1
-; SCCP-NEXT:    [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
+; SCCP-NEXT:    [[TMP41:%.*]] = trunc nuw i32 [[TMP3]] to i16
 ; SCCP-NEXT:    store i16 [[TMP41]], ptr @global.11, align 1
 ; SCCP-NEXT:    [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]]
 ; SCCP-NEXT:    [[TMP44:%.*]] = mul i32 [[TMP43]], 4
@@ -697,7 +697,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
 ; IPSCCP-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0
 ; IPSCCP-NEXT:    br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]]
 ; IPSCCP:       bb23:
-; IPSCCP-NEXT:    [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16
+; IPSCCP-NEXT:    [[TMP24:%.*]] = trunc nuw i32 [[TMP3]] to i16
 ; IPSCCP-NEXT:    store i16 [[TMP24]], ptr [[TMP17]], align 2
 ; IPSCCP-NEXT:    br label [[BB31]]
 ; IPSCCP:       bb25:
@@ -720,7 +720,7 @@ define ptr @wobble(ptr %arg, i32 %arg1) align 2 {
 ; IPSCCP-NEXT:    [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8
 ; IPSCCP-NEXT:    br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]]
 ; IPSCCP:       bb39:
-; IPSCCP-NEXT:    [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16
+; IPSCCP-NEXT:    [[TMP41:%.*]] = trunc nuw i32 [[TMP3]] to i16
 ; IPSCCP-NEXT:    store i16 [[TMP41]], ptr @global.11, align 1
 ; IPSCCP-NEXT:    [[TMP43:%.*]] = add i32 [[TMP7]], 7
 ; IPSCCP-NEXT:    [[TMP44:%.*]] = mul i32 [[TMP43]], 4

>From 6567424180489a0fc1c423b90c8c40cfa5399b2a Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Sun, 7 Apr 2024 23:00:04 +0800
Subject: [PATCH 3/3] [SCCP] Avoid computing range if the instructions are
 already refined.

---
 llvm/lib/Transforms/Utils/SCCPSolver.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 3cec6623df33ec..ec50375b5d136e 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -120,6 +120,9 @@ static bool refineInstruction(SCCPSolver &Solver,
   };
 
   if (isa<OverflowingBinaryOperator>(Inst)) {
+    if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
+      return false;
+
     auto RangeA = GetRange(Inst.getOperand(0));
     auto RangeB = GetRange(Inst.getOperand(1));
     if (!Inst.hasNoUnsignedWrap()) {
@@ -147,6 +150,9 @@ static bool refineInstruction(SCCPSolver &Solver,
       Changed = true;
     }
   } else if (TruncInst *TI = dyn_cast<TruncInst>(&Inst)) {
+    if (TI->hasNoSignedWrap() && TI->hasNoUnsignedWrap())
+      return false;
+
     auto Range = GetRange(Inst.getOperand(0));
     uint64_t DestWidth = TI->getDestTy()->getScalarSizeInBits();
     if (!TI->hasNoUnsignedWrap()) {



More information about the llvm-commits mailing list