[clang] [llvm] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)

LĂ©onard Oest O'Leary via cfe-commits cfe-commits at lists.llvm.org
Sat Nov 11 08:54:36 PST 2023


https://github.com/leo-ard updated https://github.com/llvm/llvm-project/pull/70845

>From 00d0c18b5414ffe7222e1ee0ad5ecfdb8783704e Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Mon, 30 Oct 2023 18:01:27 -0400
Subject: [PATCH 01/14] Add NonNeg check for InstCombine

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 7c2ad92f919a3cc..cd287d757fdfd23 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5554,11 +5554,15 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
         return new ICmpInst(ICmp.getPredicate(), Builder.CreateOr(X, Y),
                             Constant::getNullValue(X->getType()));
 
+      // Treat "zext nneg" as "sext"
+      bool IsNonNeg0 = isa<PossiblyNonNegInst>(ICmp.getOperand(0));
+      bool IsNonNeg1 = isa<PossiblyNonNegInst>(ICmp.getOperand(1));
+
       // If we have mismatched casts, treat the zext of a non-negative source as
       // a sext to simulate matching casts. Otherwise, we are done.
       // TODO: Can we handle some predicates (equality) without non-negative?
-      if ((IsZext0 && isKnownNonNegative(X, DL, 0, &AC, &ICmp, &DT)) ||
-          (IsZext1 && isKnownNonNegative(Y, DL, 0, &AC, &ICmp, &DT)))
+      if ((IsZext0 && (IsNonNeg0 || isKnownNonNegative(X, DL, 0, &AC, &ICmp, &DT))) ||
+          (IsZext1 && (IsNonNeg1 || isKnownNonNegative(Y, DL, 0, &AC, &ICmp, &DT))))
         IsSignedExt = true;
       else
         return nullptr;

>From ee1978946530e28ff79f924bcc5ffd73dc590549 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Mon, 30 Oct 2023 18:03:44 -0400
Subject: [PATCH 02/14] Add tests for min/max

---
 clang/test/CodeGen/X86/min_max.c              |  19 ++
 .../Transforms/SCCP/icmp-fold-with-cast.ll    | 185 ++++++++++++++++++
 2 files changed, 204 insertions(+)
 create mode 100644 clang/test/CodeGen/X86/min_max.c
 create mode 100644 llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll

diff --git a/clang/test/CodeGen/X86/min_max.c b/clang/test/CodeGen/X86/min_max.c
new file mode 100644
index 000000000000000..7af8181cc9ff367
--- /dev/null
+++ b/clang/test/CodeGen/X86/min_max.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -O2 -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
+
+short vecreduce_smax_v2i16(int n, short* v)
+{
+  // CHECK: @llvm.smax
+  short p = 0;
+  for (int i = 0; i < n; ++i)
+    p = p < v[i] ? v[i] : p;
+  return p;
+}
+
+short vecreduce_smin_v2i16(int n, short* v)
+{
+  // CHECK: @llvm.smin
+  short p = 0;
+  for (int i = 0; i < n; ++i)
+    p = p > v[i] ? v[i] : p;
+  return p;
+}
\ No newline at end of file
diff --git a/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll b/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
new file mode 100644
index 000000000000000..90b2c123081fb49
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
@@ -0,0 +1,185 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./bin/opt --version 3
+; See PRXXX for more details
+; RUN: opt < %s -S -passes=ipsccp | FileCheck %s
+
+
+define signext i32 @sext_sext(i16 %x, i16 %y) {
+; CHECK-LABEL: define signext i32 @sext_sext(
+; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[Y]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    br label [[COND_END:%.*]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ 1, [[COND_FALSE]] ]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+entry:
+  %conv = sext i16 %x to i32
+  %conv1 = sext i16 %y to i32
+  %cmp2 = icmp sgt i32 %conv, %conv1
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ 0, %cond.true ], [ 1, %cond.false ]
+  ret i32 %cond
+}
+
+
+define signext i32 @zext_zext(i16 %x, i16 %y) {
+; CHECK-LABEL: define signext i32 @zext_zext(
+; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[X]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[Y]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    br label [[COND_END:%.*]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ 1, [[COND_FALSE]] ]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+entry:
+  %conv = zext i16 %x to i32
+  %conv1 = zext i16 %y to i32
+  %cmp2 = icmp sgt i32 %conv, %conv1
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ 0, %cond.true ], [ 1, %cond.false ]
+  ret i32 %cond
+}
+
+
+define signext i16 @zext_positive_and_sext(i32 noundef %n, ptr noundef %v) {
+; CHECK-LABEL: define signext i16 @zext_positive_and_sext(
+; CHECK-SAME: i32 noundef [[N:%.*]], ptr noundef [[V:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[P_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[CONV8:%.*]], [[COND_END:%.*]] ]
+; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[COND_END]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[P_0]] to i32
+; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i16, ptr [[V]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
+; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[TMP0]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[P_0]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    ret i16 [[P_0]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[CONV1]], [[COND_TRUE]] ], [ [[CONV]], [[COND_FALSE]] ]
+; CHECK-NEXT:    [[CONV8]] = trunc i32 [[COND]] to i16
+; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
+; CHECK-NEXT:    br label [[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %cond.end, %entry
+  %p.0 = phi i16 [ 0, %entry ], [ %conv8, %cond.end ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %cond.end ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.body:                                         ; preds = %for.cond
+  %conv = zext i16 %p.0 to i32                    ;; %p.0 is always positive here
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr i16, ptr %v, i64 %idxprom
+  %0 = load i16, ptr %arrayidx, align 2
+  %conv1 = sext i16 %0 to i32
+  %cmp2 = icmp slt i32 %conv, %conv1
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  br label %cond.end
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  ret i16 %p.0
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %conv1, %cond.true ], [ %conv, %cond.false ]
+  %conv8 = trunc i32 %cond to i16
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+}
+
+
+
+define signext i16 @sext_and_zext_positive(i16 %x) {
+; CHECK-LABEL: define signext i16 @sext_and_zext_positive(
+; CHECK-SAME: i16 [[X:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[V:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ]
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[V]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[X]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[X]], [[V]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[A:%.*]] = phi i16 [ 10, [[COND_TRUE]] ], [ 20, [[COND_FALSE]] ]
+; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[A]], 1
+; CHECK-NEXT:    br label [[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %cond.end, %entry
+  %v = phi i16 [ 0, %entry ], [ %inc, %cond.end ] ;; always positive
+  br label %for.body
+
+for.body:                                         ; preds = %for.cond
+  %conv = zext i16 %v to i32                    ;; %p.0 is always positive here
+  %conv1 = sext i16 %x to i32                    ;; %p.0 is always positive here
+  %cmp2 = icmp slt i32 %conv1, %conv ;; positive/positive
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %a = phi i16 [ 10, %cond.true ],  [ 20, %cond.false ]
+  %inc = add i16 %a, 1
+  br label %for.cond
+}

>From 0fc4460e2ed01f1d8ef867ad0d81caa52344f13c Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Tue, 31 Oct 2023 13:24:49 -0400
Subject: [PATCH 03/14] Regenerate tests

---
 ...004-11-27-SetCCForCastLargerAndConstant.ll |  5 +-
 .../Transforms/InstCombine/icmp-ext-ext.ll    | 49 ++++++-------------
 .../Transforms/SCCP/icmp-fold-with-cast.ll    |  2 +-
 3 files changed, 19 insertions(+), 37 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll b/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
index 68444db15d12a7d..f72b6e8609eccd0 100644
--- a/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
+++ b/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
@@ -404,9 +404,8 @@ define i1 @different_size_sext_sext_ule(i7 %x, i4 %y) {
 
 define i1 @different_size_sext_zext_ne(i7 %x, i4 %y) {
 ; CHECK-LABEL: @different_size_sext_zext_ne(
-; CHECK-NEXT:    [[SX:%.*]] = sext i7 [[X:%.*]] to i25
-; CHECK-NEXT:    [[ZY:%.*]] = zext i4 [[Y:%.*]] to i25
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i25 [[SX]], [[ZY]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i7 [[TMP1]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %sx = sext i7 %x to i25
diff --git a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
index f70e48e27384619..87532c1faff1526 100644
--- a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
@@ -119,9 +119,7 @@ define <2 x i1> @sext_sext_uge_op0_wide(<2 x i16> %x, <2 x i8> %y) {
 
 define i1 @zext_sext_sgt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_sgt(
-; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -132,9 +130,7 @@ define i1 @zext_sext_sgt(i8 %x, i8 %y) {
 
 define i1 @zext_sext_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ugt(
-; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp ugt i32 [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -145,9 +141,7 @@ define i1 @zext_sext_ugt(i8 %x, i8 %y) {
 
 define i1 @zext_sext_eq(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_eq(
-; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -158,9 +152,8 @@ define i1 @zext_sext_eq(i8 %x, i8 %y) {
 
 define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
 ; CHECK-LABEL: @zext_sext_sle_op0_narrow(
-; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = sext i16 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp sle i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16
+; CHECK-NEXT:    [[C:%.*]] = icmp sle i16 [[TMP1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -171,9 +164,8 @@ define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
 
 define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ule_op0_wide(
-; CHECK-NEXT:    [[A:%.*]] = zext i9 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp ule i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i9
+; CHECK-NEXT:    [[C:%.*]] = icmp uge i9 [[TMP1]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i9 %x to i32
@@ -184,9 +176,7 @@ define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
 
 define i1 @sext_zext_slt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_slt(
-; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i8 %x to i32
@@ -197,9 +187,7 @@ define i1 @sext_zext_slt(i8 %x, i8 %y) {
 
 define i1 @sext_zext_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_ult(
-; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i8 %x to i32
@@ -210,9 +198,7 @@ define i1 @sext_zext_ult(i8 %x, i8 %y) {
 
 define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @sext_zext_ne(
-; CHECK-NEXT:    [[A:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[B:%.*]] = zext <2 x i8> [[Y:%.*]] to <2 x i32>
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[A]], [[B]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %a = sext <2 x i8> %x to <2 x i32>
@@ -223,9 +209,8 @@ define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
 
 define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_sge_op0_narrow(
-; CHECK-NEXT:    [[A:%.*]] = sext i5 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp sge i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i5 [[X:%.*]] to i8
+; CHECK-NEXT:    [[C:%.*]] = icmp sge i8 [[TMP1]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i5 %x to i32
@@ -236,9 +221,8 @@ define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
 
 define i1 @sext_zext_uge_op0_wide(i16 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_uge_op0_wide(
-; CHECK-NEXT:    [[A:%.*]] = sext i16 [[X:%.*]] to i32
-; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
-; CHECK-NEXT:    [[C:%.*]] = icmp uge i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i16
+; CHECK-NEXT:    [[C:%.*]] = icmp ule i16 [[TMP1]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i16 %x to i32
@@ -396,9 +380,8 @@ define i1 @zext_eq_sext(i1 %a, i1 %b) {
 
 define i1 @zext_eq_sext_fail_not_i1(i1 %a, i8 %b) {
 ; CHECK-LABEL: @zext_eq_sext_fail_not_i1(
-; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[A:%.*]] to i32
-; CHECK-NEXT:    [[CONV3_NEG:%.*]] = sext i8 [[B:%.*]] to i32
-; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[CONV]], [[CONV3_NEG]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i1 [[A:%.*]] to i8
+; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i8 [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret i1 [[TOBOOL4]]
 ;
   %conv = zext i1 %a to i32
diff --git a/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll b/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
index 90b2c123081fb49..4e9597f7e70daaa 100644
--- a/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
+++ b/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./bin/opt --version 3
 ; See PRXXX for more details
-; RUN: opt < %s -S -passes=ipsccp | FileCheck %s
+; RUN-./bin/opt: opt < %s -S -passes=ipsccp | FileCheck %s
 
 
 define signext i32 @sext_sext(i16 %x, i16 %y) {

>From 78c4c449173b49818f146a0a1138683477b53c04 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Tue, 31 Oct 2023 13:54:29 -0400
Subject: [PATCH 04/14] Move test to InstCombine

---
 llvm/test/Transforms/{SCCP => InstCombine}/icmp-fold-with-cast.ll | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename llvm/test/Transforms/{SCCP => InstCombine}/icmp-fold-with-cast.ll (100%)

diff --git a/llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
similarity index 100%
rename from llvm/test/Transforms/SCCP/icmp-fold-with-cast.ll
rename to llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll

>From 20612e22012291840643722c03874e7a64d98329 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Tue, 31 Oct 2023 13:58:55 -0400
Subject: [PATCH 05/14] Reformat according to git clang format

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index cd287d757fdfd23..95dd2d270f2f9b0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5561,8 +5561,10 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
       // If we have mismatched casts, treat the zext of a non-negative source as
       // a sext to simulate matching casts. Otherwise, we are done.
       // TODO: Can we handle some predicates (equality) without non-negative?
-      if ((IsZext0 && (IsNonNeg0 || isKnownNonNegative(X, DL, 0, &AC, &ICmp, &DT))) ||
-          (IsZext1 && (IsNonNeg1 || isKnownNonNegative(Y, DL, 0, &AC, &ICmp, &DT))))
+      if ((IsZext0 &&
+           (IsNonNeg0 || isKnownNonNegative(X, DL, 0, &AC, &ICmp, &DT))) ||
+          (IsZext1 &&
+           (IsNonNeg1 || isKnownNonNegative(Y, DL, 0, &AC, &ICmp, &DT))))
         IsSignedExt = true;
       else
         return nullptr;

>From a3a3082d3b5bcf7a746c89f28984cfac9d0d0209 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Wed, 1 Nov 2023 13:16:20 -0400
Subject: [PATCH 06/14] check with hasNonNeg (comment 2)

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 95dd2d270f2f9b0..5a789648f684a9a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5555,8 +5555,11 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
                             Constant::getNullValue(X->getType()));
 
       // Treat "zext nneg" as "sext"
-      bool IsNonNeg0 = isa<PossiblyNonNegInst>(ICmp.getOperand(0));
-      bool IsNonNeg1 = isa<PossiblyNonNegInst>(ICmp.getOperand(1));
+      auto *NonNegInst0 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(0));
+      auto *NonNegInst1 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(1));
+
+      bool IsNonNeg0 = NonNegInst0 && NonNegInst0->hasNonNeg();
+      bool IsNonNeg1 = NonNegInst1 && NonNegInst1->hasNonNeg();
 
       // If we have mismatched casts, treat the zext of a non-negative source as
       // a sext to simulate matching casts. Otherwise, we are done.

>From 5fc147630f31718ee60a4ca27b32084e0a73839e Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Wed, 1 Nov 2023 13:17:33 -0400
Subject: [PATCH 07/14] change test to instcombine (comment 3)

---
 .../InstCombine/icmp-fold-with-cast.ll        | 32 +++++++------------
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
index 4e9597f7e70daaa..119eb6faca7ca41 100644
--- a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
@@ -1,14 +1,12 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./bin/opt --version 3
-; See PRXXX for more details
-; RUN-./bin/opt: opt < %s -S -passes=ipsccp | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; See PR-70845 for more details
+; RUN: opt < %s -S -passes=instcombine | FileCheck %s
 
 
 define signext i32 @sext_sext(i16 %x, i16 %y) {
 ; CHECK-LABEL: define signext i32 @sext_sext(
 ; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X]] to i32
-; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[Y]] to i32
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], [[Y]]
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
 ; CHECK:       cond.true:
@@ -41,9 +39,7 @@ define signext i32 @zext_zext(i16 %x, i16 %y) {
 ; CHECK-LABEL: define signext i32 @zext_zext(
 ; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[X]] to i32
-; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[Y]] to i32
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i16 [[X]], [[Y]]
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
 ; CHECK:       cond.true:
 ; CHECK-NEXT:    br label [[COND_END:%.*]]
@@ -77,16 +73,14 @@ define signext i16 @zext_positive_and_sext(i32 noundef %n, ptr noundef %v) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
 ; CHECK:       for.cond:
-; CHECK-NEXT:    [[P_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[CONV8:%.*]], [[COND_END:%.*]] ]
+; CHECK-NEXT:    [[P_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[COND_OFF0:%.*]], [[COND_END:%.*]] ]
 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[COND_END]] ]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N]]
 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[P_0]] to i32
-; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
+; CHECK-NEXT:    [[IDXPROM:%.*]] = zext nneg i32 [[I_0]] to i64
 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i16, ptr [[V]], i64 [[IDXPROM]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
-; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[TMP0]] to i32
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[P_0]], [[TMP0]]
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
 ; CHECK:       cond.true:
@@ -96,9 +90,8 @@ define signext i16 @zext_positive_and_sext(i32 noundef %n, ptr noundef %v) {
 ; CHECK:       for.cond.cleanup:
 ; CHECK-NEXT:    ret i16 [[P_0]]
 ; CHECK:       cond.end:
-; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[CONV1]], [[COND_TRUE]] ], [ [[CONV]], [[COND_FALSE]] ]
-; CHECK-NEXT:    [[CONV8]] = trunc i32 [[COND]] to i16
-; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
+; CHECK-NEXT:    [[COND_OFF0]] = phi i16 [ [[TMP0]], [[COND_TRUE]] ], [ [[P_0]], [[COND_FALSE]] ]
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_0]], 1
 ; CHECK-NEXT:    br label [[FOR_COND]]
 ;
 entry:
@@ -143,20 +136,17 @@ define signext i16 @sext_and_zext_positive(i16 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
 ; CHECK:       for.cond:
-; CHECK-NEXT:    [[V:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ]
+; CHECK-NEXT:    [[V:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[A:%.*]], [[COND_END:%.*]] ]
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[V]] to i32
-; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[X]] to i32
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[X]], [[V]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[V]], [[X]]
 ; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
 ; CHECK:       cond.true:
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.false:
 ; CHECK-NEXT:    br label [[COND_END]]
 ; CHECK:       cond.end:
-; CHECK-NEXT:    [[A:%.*]] = phi i16 [ 10, [[COND_TRUE]] ], [ 20, [[COND_FALSE]] ]
-; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[A]], 1
+; CHECK-NEXT:    [[A]] = phi i16 [ 11, [[COND_TRUE]] ], [ 21, [[COND_FALSE]] ]
 ; CHECK-NEXT:    br label [[FOR_COND]]
 ;
 entry:

>From 9d004e137979ee58db54e56e433e878253fd2291 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Wed, 1 Nov 2023 15:04:55 -0400
Subject: [PATCH 08/14] Moving end-to-end test to PhaseOrdering (comment 3)

---
 clang/test/CodeGen/X86/min_max.c              |  19 ---
 .../Transforms/PhaseOrdering/min_max_loop.ll  | 126 ++++++++++++++++++
 2 files changed, 126 insertions(+), 19 deletions(-)
 delete mode 100644 clang/test/CodeGen/X86/min_max.c
 create mode 100644 llvm/test/Transforms/PhaseOrdering/min_max_loop.ll

diff --git a/clang/test/CodeGen/X86/min_max.c b/clang/test/CodeGen/X86/min_max.c
deleted file mode 100644
index 7af8181cc9ff367..000000000000000
--- a/clang/test/CodeGen/X86/min_max.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: %clang_cc1 %s -O2 -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
-
-short vecreduce_smax_v2i16(int n, short* v)
-{
-  // CHECK: @llvm.smax
-  short p = 0;
-  for (int i = 0; i < n; ++i)
-    p = p < v[i] ? v[i] : p;
-  return p;
-}
-
-short vecreduce_smin_v2i16(int n, short* v)
-{
-  // CHECK: @llvm.smin
-  short p = 0;
-  for (int i = 0; i < n; ++i)
-    p = p > v[i] ? v[i] : p;
-  return p;
-}
\ No newline at end of file
diff --git a/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
new file mode 100644
index 000000000000000..7ea389dfafce68b
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
@@ -0,0 +1,126 @@
+; RUN: opt < %s --O3 -S | FileCheck %s
+
+define signext i16 @vecreduce_smax_v2i16(i32 noundef %0, ptr noundef %1) #0 {
+   ;; CHECK: @llvm.smax
+   %3 = alloca i32, align 4
+   %4 = alloca ptr, align 8
+   %5 = alloca i16, align 2
+   %6 = alloca i32, align 4
+   store i32 %0, ptr %3, align 4
+   store ptr %1, ptr %4, align 8
+   store i16 0, ptr %5, align 2
+   store i32 0, ptr %6, align 4
+   br label %7
+ 
+ 7:                                                ; preds = %34, %2
+   %8 = load i32, ptr %6, align 4
+   %9 = load i32, ptr %3, align 4
+   %10 = icmp slt i32 %8, %9
+   br i1 %10, label %11, label %37
+ 
+ 11:                                               ; preds = %7
+   %12 = load i16, ptr %5, align 2
+   %13 = sext i16 %12 to i32
+   %14 = load ptr, ptr %4, align 8
+   %15 = load i32, ptr %6, align 4
+   %16 = sext i32 %15 to i64
+   %17 = getelementptr inbounds i16, ptr %14, i64 %16
+   %18 = load i16, ptr %17, align 2
+   %19 = sext i16 %18 to i32
+   %20 = icmp slt i32 %13, %19
+   br i1 %20, label %21, label %28
+ 
+ 21:                                               ; preds = %11
+   %22 = load ptr, ptr %4, align 8
+   %23 = load i32, ptr %6, align 4
+   %24 = sext i32 %23 to i64
+   %25 = getelementptr inbounds i16, ptr %22, i64 %24
+   %26 = load i16, ptr %25, align 2
+   %27 = sext i16 %26 to i32
+   br label %31
+ 
+ 28:                                               ; preds = %11
+   %29 = load i16, ptr %5, align 2
+   %30 = sext i16 %29 to i32
+   br label %31
+ 
+ 31:                                               ; preds = %28, %21
+   %32 = phi i32 [ %27, %21 ], [ %30, %28 ]
+   %33 = trunc i32 %32 to i16
+   store i16 %33, ptr %5, align 2
+   br label %34
+ 
+ 34:                                               ; preds = %31
+   %35 = load i32, ptr %6, align 4
+   %36 = add nsw i32 %35, 1
+   store i32 %36, ptr %6, align 4
+   br label %7
+ 
+ 37:                                               ; preds = %7
+   %38 = load i16, ptr %5, align 2
+   ret i16 %38
+ }
+
+define signext i16 @vecreduce_smin_v2i16(i32 noundef %0, ptr noundef %1) #0 {
+; CHECK: @llvm.smin
+  %3 = alloca i32, align 4
+  %4 = alloca ptr, align 8
+  %5 = alloca i16, align 2
+  %6 = alloca i32, align 4
+  store i32 %0, ptr %3, align 4
+  store ptr %1, ptr %4, align 8
+  store i16 0, ptr %5, align 2
+  store i32 0, ptr %6, align 4
+  br label %7
+
+7:                                                ; preds = %34, %2
+  %8 = load i32, ptr %6, align 4
+  %9 = load i32, ptr %3, align 4
+  %10 = icmp slt i32 %8, %9
+  br i1 %10, label %11, label %37
+
+11:                                               ; preds = %7
+  %12 = load i16, ptr %5, align 2
+  %13 = sext i16 %12 to i32
+  %14 = load ptr, ptr %4, align 8
+  %15 = load i32, ptr %6, align 4
+  %16 = sext i32 %15 to i64
+  %17 = getelementptr inbounds i16, ptr %14, i64 %16
+  %18 = load i16, ptr %17, align 2
+  %19 = sext i16 %18 to i32
+  %20 = icmp sgt i32 %13, %19
+  br i1 %20, label %21, label %28
+
+21:                                               ; preds = %11
+  %22 = load ptr, ptr %4, align 8
+  %23 = load i32, ptr %6, align 4
+  %24 = sext i32 %23 to i64
+  %25 = getelementptr inbounds i16, ptr %22, i64 %24
+  %26 = load i16, ptr %25, align 2
+  %27 = sext i16 %26 to i32
+  br label %31
+
+28:                                               ; preds = %11
+  %29 = load i16, ptr %5, align 2
+  %30 = sext i16 %29 to i32
+  br label %31
+
+31:                                               ; preds = %28, %21
+  %32 = phi i32 [ %27, %21 ], [ %30, %28 ]
+  %33 = trunc i32 %32 to i16
+  store i16 %33, ptr %5, align 2
+  br label %34
+
+34:                                               ; preds = %31
+  %35 = load i32, ptr %6, align 4
+  %36 = add nsw i32 %35, 1
+  store i32 %36, ptr %6, align 4
+  br label %7 
+
+37:                                               ; preds = %7
+  %38 = load i16, ptr %5, align 2
+  ret i16 %38
+}
+
+
+

>From 77476a6da485525b7a68035e4e7d296a13683b47 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Wed, 1 Nov 2023 16:02:28 -0400
Subject: [PATCH 09/14] Fixing failing reg tests

---
 ...004-11-27-SetCCForCastLargerAndConstant.ll |  5 +-
 .../Transforms/InstCombine/icmp-ext-ext.ll    | 49 +++++++++++++------
 .../InstCombine/icmp-fold-with-cast.ll        |  4 +-
 3 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll b/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
index f72b6e8609eccd0..68444db15d12a7d 100644
--- a/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
+++ b/llvm/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
@@ -404,8 +404,9 @@ define i1 @different_size_sext_sext_ule(i7 %x, i4 %y) {
 
 define i1 @different_size_sext_zext_ne(i7 %x, i4 %y) {
 ; CHECK-LABEL: @different_size_sext_zext_ne(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y:%.*]] to i7
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i7 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    [[SX:%.*]] = sext i7 [[X:%.*]] to i25
+; CHECK-NEXT:    [[ZY:%.*]] = zext i4 [[Y:%.*]] to i25
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i25 [[SX]], [[ZY]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %sx = sext i7 %x to i25
diff --git a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
index 87532c1faff1526..f70e48e27384619 100644
--- a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
@@ -119,7 +119,9 @@ define <2 x i1> @sext_sext_uge_op0_wide(<2 x i16> %x, <2 x i8> %y) {
 
 define i1 @zext_sext_sgt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_sgt(
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -130,7 +132,9 @@ define i1 @zext_sext_sgt(i8 %x, i8 %y) {
 
 define i1 @zext_sext_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ugt(
-; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -141,7 +145,9 @@ define i1 @zext_sext_ugt(i8 %x, i8 %y) {
 
 define i1 @zext_sext_eq(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_eq(
-; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -152,8 +158,9 @@ define i1 @zext_sext_eq(i8 %x, i8 %y) {
 
 define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
 ; CHECK-LABEL: @zext_sext_sle_op0_narrow(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16
-; CHECK-NEXT:    [[C:%.*]] = icmp sle i16 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = sext i16 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp sle i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i8 %x to i32
@@ -164,8 +171,9 @@ define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
 
 define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ule_op0_wide(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i9
-; CHECK-NEXT:    [[C:%.*]] = icmp uge i9 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = zext i9 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = sext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp ule i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = zext i9 %x to i32
@@ -176,7 +184,9 @@ define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
 
 define i1 @sext_zext_slt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_slt(
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i8 %x to i32
@@ -187,7 +197,9 @@ define i1 @sext_zext_slt(i8 %x, i8 %y) {
 
 define i1 @sext_zext_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_ult(
-; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i8 %x to i32
@@ -198,7 +210,9 @@ define i1 @sext_zext_ult(i8 %x, i8 %y) {
 
 define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @sext_zext_ne(
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[B:%.*]] = zext <2 x i8> [[Y:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[A]], [[B]]
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %a = sext <2 x i8> %x to <2 x i32>
@@ -209,8 +223,9 @@ define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
 
 define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_sge_op0_narrow(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT:    [[C:%.*]] = icmp sge i8 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = sext i5 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp sge i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i5 %x to i32
@@ -221,8 +236,9 @@ define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
 
 define i1 @sext_zext_uge_op0_wide(i16 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_uge_op0_wide(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i16
-; CHECK-NEXT:    [[C:%.*]] = icmp ule i16 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = sext i16 [[X:%.*]] to i32
+; CHECK-NEXT:    [[B:%.*]] = zext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[C:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %a = sext i16 %x to i32
@@ -380,8 +396,9 @@ define i1 @zext_eq_sext(i1 %a, i1 %b) {
 
 define i1 @zext_eq_sext_fail_not_i1(i1 %a, i8 %b) {
 ; CHECK-LABEL: @zext_eq_sext_fail_not_i1(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i1 [[A:%.*]] to i8
-; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i8 [[TMP1]], [[B:%.*]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[A:%.*]] to i32
+; CHECK-NEXT:    [[CONV3_NEG:%.*]] = sext i8 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[CONV]], [[CONV3_NEG]]
 ; CHECK-NEXT:    ret i1 [[TOBOOL4]]
 ;
   %conv = zext i1 %a to i32
diff --git a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
index 119eb6faca7ca41..f9933c7f3aff228 100644
--- a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
@@ -104,7 +104,7 @@ for.cond:                                         ; preds = %cond.end, %entry
   br i1 %cmp, label %for.body, label %for.cond.cleanup
 
 for.body:                                         ; preds = %for.cond
-  %conv = zext i16 %p.0 to i32                    ;; %p.0 is always positive here
+  %conv = zext nneg i16 %p.0 to i32                    ;; %p.0 is always positive here
   %idxprom = sext i32 %i.0 to i64
   %arrayidx = getelementptr i16, ptr %v, i64 %idxprom
   %0 = load i16, ptr %arrayidx, align 2
@@ -157,7 +157,7 @@ for.cond:                                         ; preds = %cond.end, %entry
   br label %for.body
 
 for.body:                                         ; preds = %for.cond
-  %conv = zext i16 %v to i32                    ;; %p.0 is always positive here
+  %conv = zext nneg i16 %v to i32                    ;; %p.0 is always positive here
   %conv1 = sext i16 %x to i32                    ;; %p.0 is always positive here
   %cmp2 = icmp slt i32 %conv1, %conv ;; positive/positive
   br i1 %cmp2, label %cond.true, label %cond.false

>From 6b044c0eec4b78bab94a6ee8c4060613c4c12f11 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Fri, 10 Nov 2023 14:34:53 -0500
Subject: [PATCH 10/14] Drop isKnownNonNegative() call

---
 .../Transforms/InstCombine/InstCombineCompares.cpp   | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 5a789648f684a9a..b003b65955ac293 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5554,20 +5554,16 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
         return new ICmpInst(ICmp.getPredicate(), Builder.CreateOr(X, Y),
                             Constant::getNullValue(X->getType()));
 
-      // Treat "zext nneg" as "sext"
+      // If we have mismatched casts and zext has the nneg flag, we can 
+      //  treat the "zext nneg" as "sext". Otherwise, we cannot fold and quit. 
+
       auto *NonNegInst0 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(0));
       auto *NonNegInst1 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(1));
 
       bool IsNonNeg0 = NonNegInst0 && NonNegInst0->hasNonNeg();
       bool IsNonNeg1 = NonNegInst1 && NonNegInst1->hasNonNeg();
 
-      // If we have mismatched casts, treat the zext of a non-negative source as
-      // a sext to simulate matching casts. Otherwise, we are done.
-      // TODO: Can we handle some predicates (equality) without non-negative?
-      if ((IsZext0 &&
-           (IsNonNeg0 || isKnownNonNegative(X, DL, 0, &AC, &ICmp, &DT))) ||
-          (IsZext1 &&
-           (IsNonNeg1 || isKnownNonNegative(Y, DL, 0, &AC, &ICmp, &DT))))
+      if ((IsZext0 && IsNonNeg0) || (IsZext1 && IsNonNeg1))
         IsSignedExt = true;
       else
         return nullptr;

>From 1adba3e89daef0dc0d11d6c4e7f0c6b60429e282 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Fri, 10 Nov 2023 14:35:52 -0500
Subject: [PATCH 11/14] Regenerate min/max test for readability

---
 .../Transforms/PhaseOrdering/min_max_loop.ll  | 259 ++++++++++--------
 1 file changed, 139 insertions(+), 120 deletions(-)

diff --git a/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
index 7ea389dfafce68b..67176280abb1bb4 100644
--- a/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
+++ b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
@@ -1,126 +1,145 @@
 ; RUN: opt < %s --O3 -S | FileCheck %s
+; See issue #55013 and PR #70845 for more details.
+; This test comes from the following C program, compiled with : 
+;   > clang -O0 -S -emit-llvm -fno-discard-value-names
+; 
+;; short vecreduce_smin_v2i16(int n, short* v)
+;; {
+;;   short p = 0;
+;;   for (int i = 0; i < n; ++i)
+;;     p = p > v[i] ? v[i] : p;
+;;   return p;
+;; }
+;
+;; short vecreduce_smax_v2i16(int n, short* v)
+;; {
+;;   short p = 0;
+;;   for (int i = 0; i < n; ++i)
+;;     p = p < v[i] ? v[i] : p;
+;;   return p;
+;; }
 
-define signext i16 @vecreduce_smax_v2i16(i32 noundef %0, ptr noundef %1) #0 {
-   ;; CHECK: @llvm.smax
-   %3 = alloca i32, align 4
-   %4 = alloca ptr, align 8
-   %5 = alloca i16, align 2
-   %6 = alloca i32, align 4
-   store i32 %0, ptr %3, align 4
-   store ptr %1, ptr %4, align 8
-   store i16 0, ptr %5, align 2
-   store i32 0, ptr %6, align 4
-   br label %7
- 
- 7:                                                ; preds = %34, %2
-   %8 = load i32, ptr %6, align 4
-   %9 = load i32, ptr %3, align 4
-   %10 = icmp slt i32 %8, %9
-   br i1 %10, label %11, label %37
- 
- 11:                                               ; preds = %7
-   %12 = load i16, ptr %5, align 2
-   %13 = sext i16 %12 to i32
-   %14 = load ptr, ptr %4, align 8
-   %15 = load i32, ptr %6, align 4
-   %16 = sext i32 %15 to i64
-   %17 = getelementptr inbounds i16, ptr %14, i64 %16
-   %18 = load i16, ptr %17, align 2
-   %19 = sext i16 %18 to i32
-   %20 = icmp slt i32 %13, %19
-   br i1 %20, label %21, label %28
- 
- 21:                                               ; preds = %11
-   %22 = load ptr, ptr %4, align 8
-   %23 = load i32, ptr %6, align 4
-   %24 = sext i32 %23 to i64
-   %25 = getelementptr inbounds i16, ptr %22, i64 %24
-   %26 = load i16, ptr %25, align 2
-   %27 = sext i16 %26 to i32
-   br label %31
- 
- 28:                                               ; preds = %11
-   %29 = load i16, ptr %5, align 2
-   %30 = sext i16 %29 to i32
-   br label %31
- 
- 31:                                               ; preds = %28, %21
-   %32 = phi i32 [ %27, %21 ], [ %30, %28 ]
-   %33 = trunc i32 %32 to i16
-   store i16 %33, ptr %5, align 2
-   br label %34
- 
- 34:                                               ; preds = %31
-   %35 = load i32, ptr %6, align 4
-   %36 = add nsw i32 %35, 1
-   store i32 %36, ptr %6, align 4
-   br label %7
- 
- 37:                                               ; preds = %7
-   %38 = load i16, ptr %5, align 2
-   ret i16 %38
- }
-
-define signext i16 @vecreduce_smin_v2i16(i32 noundef %0, ptr noundef %1) #0 {
-; CHECK: @llvm.smin
-  %3 = alloca i32, align 4
-  %4 = alloca ptr, align 8
-  %5 = alloca i16, align 2
-  %6 = alloca i32, align 4
-  store i32 %0, ptr %3, align 4
-  store ptr %1, ptr %4, align 8
-  store i16 0, ptr %5, align 2
-  store i32 0, ptr %6, align 4
-  br label %7
-
-7:                                                ; preds = %34, %2
-  %8 = load i32, ptr %6, align 4
-  %9 = load i32, ptr %3, align 4
-  %10 = icmp slt i32 %8, %9
-  br i1 %10, label %11, label %37
-
-11:                                               ; preds = %7
-  %12 = load i16, ptr %5, align 2
-  %13 = sext i16 %12 to i32
-  %14 = load ptr, ptr %4, align 8
-  %15 = load i32, ptr %6, align 4
-  %16 = sext i32 %15 to i64
-  %17 = getelementptr inbounds i16, ptr %14, i64 %16
-  %18 = load i16, ptr %17, align 2
-  %19 = sext i16 %18 to i32
-  %20 = icmp sgt i32 %13, %19
-  br i1 %20, label %21, label %28
-
-21:                                               ; preds = %11
-  %22 = load ptr, ptr %4, align 8
-  %23 = load i32, ptr %6, align 4
-  %24 = sext i32 %23 to i64
-  %25 = getelementptr inbounds i16, ptr %22, i64 %24
-  %26 = load i16, ptr %25, align 2
-  %27 = sext i16 %26 to i32
-  br label %31
-
-28:                                               ; preds = %11
-  %29 = load i16, ptr %5, align 2
-  %30 = sext i16 %29 to i32
-  br label %31
-
-31:                                               ; preds = %28, %21
-  %32 = phi i32 [ %27, %21 ], [ %30, %28 ]
-  %33 = trunc i32 %32 to i16
-  store i16 %33, ptr %5, align 2
-  br label %34
-
-34:                                               ; preds = %31
-  %35 = load i32, ptr %6, align 4
-  %36 = add nsw i32 %35, 1
-  store i32 %36, ptr %6, align 4
-  br label %7 
-
-37:                                               ; preds = %7
-  %38 = load i16, ptr %5, align 2
-  ret i16 %38
+define signext i16 @vecreduce_smin_v2i16(i32 noundef %n, ptr noundef %v) {
+  ;; CHECK: @llvm.smin
+entry:
+  %n.addr = alloca i32, align 4
+  %v.addr = alloca ptr, align 8
+  %p = alloca i16, align 2
+  %i = alloca i32, align 4
+  store i32 %n, ptr %n.addr, align 4
+  store ptr %v, ptr %v.addr, align 8
+  store i16 0, ptr %p, align 2
+  store i32 0, ptr %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i32, ptr %i, align 4
+  %1 = load i32, ptr %n.addr, align 4
+  %cmp = icmp slt i32 %0, %1
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %2 = load i16, ptr %p, align 2
+  %conv = sext i16 %2 to i32
+  %3 = load ptr, ptr %v.addr, align 8
+  %4 = load i32, ptr %i, align 4
+  %idxprom = sext i32 %4 to i64
+  %arrayidx = getelementptr inbounds i16, ptr %3, i64 %idxprom
+  %5 = load i16, ptr %arrayidx, align 2
+  %conv1 = sext i16 %5 to i32
+  %cmp2 = icmp sgt i32 %conv, %conv1
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  %6 = load ptr, ptr %v.addr, align 8
+  %7 = load i32, ptr %i, align 4
+  %idxprom4 = sext i32 %7 to i64
+  %arrayidx5 = getelementptr inbounds i16, ptr %6, i64 %idxprom4
+  %8 = load i16, ptr %arrayidx5, align 2
+  %conv6 = sext i16 %8 to i32
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  %9 = load i16, ptr %p, align 2
+  %conv7 = sext i16 %9 to i32
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ]
+  %conv8 = trunc i32 %cond to i16
+  store i16 %conv8, ptr %p, align 2
+  br label %for.inc
+
+for.inc:                                          ; preds = %cond.end
+  %10 = load i32, ptr %i, align 4
+  %inc = add nsw i32 %10, 1
+  store i32 %inc, ptr %i, align 4
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  %11 = load i16, ptr %p, align 2
+  ret i16 %11
 }
 
+; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
+define signext i16 @vecreduce_smax_v2i16(i32 noundef %n, ptr noundef %v) {
+  ;; CHECK: @llvm.smax
+entry:
+  %n.addr = alloca i32, align 4
+  %v.addr = alloca ptr, align 8
+  %p = alloca i16, align 2
+  %i = alloca i32, align 4
+  store i32 %n, ptr %n.addr, align 4
+  store ptr %v, ptr %v.addr, align 8
+  store i16 0, ptr %p, align 2
+  store i32 0, ptr %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i32, ptr %i, align 4
+  %1 = load i32, ptr %n.addr, align 4
+  %cmp = icmp slt i32 %0, %1
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %2 = load i16, ptr %p, align 2
+  %conv = sext i16 %2 to i32
+  %3 = load ptr, ptr %v.addr, align 8
+  %4 = load i32, ptr %i, align 4
+  %idxprom = sext i32 %4 to i64
+  %arrayidx = getelementptr inbounds i16, ptr %3, i64 %idxprom
+  %5 = load i16, ptr %arrayidx, align 2
+  %conv1 = sext i16 %5 to i32
+  %cmp2 = icmp slt i32 %conv, %conv1
+  br i1 %cmp2, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %for.body
+  %6 = load ptr, ptr %v.addr, align 8
+  %7 = load i32, ptr %i, align 4
+  %idxprom4 = sext i32 %7 to i64
+  %arrayidx5 = getelementptr inbounds i16, ptr %6, i64 %idxprom4
+  %8 = load i16, ptr %arrayidx5, align 2
+  %conv6 = sext i16 %8 to i32
+  br label %cond.end
+
+cond.false:                                       ; preds = %for.body
+  %9 = load i16, ptr %p, align 2
+  %conv7 = sext i16 %9 to i32
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ]
+  %conv8 = trunc i32 %cond to i16
+  store i16 %conv8, ptr %p, align 2
+  br label %for.inc
 
+for.inc:                                          ; preds = %cond.end
+  %10 = load i32, ptr %i, align 4
+  %inc = add nsw i32 %10, 1
+  store i32 %inc, ptr %i, align 4
+  br label %for.cond
 
+for.end:                                          ; preds = %for.cond
+  %11 = load i16, ptr %p, align 2
+  ret i16 %11
+}
\ No newline at end of file

>From 3f2ad99f9a6d177ea2747bfc0e559aad1faf8639 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Fri, 10 Nov 2023 14:36:46 -0500
Subject: [PATCH 12/14] Change instcombine icmp folding tests

---
 .../Transforms/InstCombine/icmp-ext-ext.ll    | 121 ++++++++++++
 .../InstCombine/icmp-fold-with-cast.ll        | 175 ------------------
 2 files changed, 121 insertions(+), 175 deletions(-)
 delete mode 100644 llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll

diff --git a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
index f70e48e27384619..7fc42c65d758b3e 100644
--- a/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-ext-ext.ll
@@ -130,6 +130,17 @@ define i1 @zext_sext_sgt(i8 %x, i8 %y) {
   ret i1 %c
 }
 
+define i1 @zext_nneg_sext_sgt(i8 %x, i8 %y) {
+; CHECK-LABEL: @zext_nneg_sext_sgt(
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = zext nneg i8 %x to i32
+  %b = sext i8 %y to i32
+  %c = icmp sgt i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @zext_sext_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ugt(
 ; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
@@ -143,6 +154,18 @@ define i1 @zext_sext_ugt(i8 %x, i8 %y) {
   ret i1 %c
 }
 
+
+define i1 @zext_nneg_sext_ugt(i8 %x, i8 %y) {
+; CHECK-LABEL: @zext_nneg_sext_ugt(
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = zext nneg i8 %x to i32
+  %b = sext i8 %y to i32
+  %c = icmp ugt i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @zext_sext_eq(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_eq(
 ; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
@@ -156,6 +179,18 @@ define i1 @zext_sext_eq(i8 %x, i8 %y) {
   ret i1 %c
 }
 
+define i1 @zext_nneg_sext_eq(i8 %x, i8 %y) {
+; CHECK-LABEL: @zext_nneg_sext_eq(
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = zext nneg i8 %x to i32
+  %b = sext i8 %y to i32
+  %c = icmp eq i32 %a, %b
+  ret i1 %c
+}
+
+
 define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
 ; CHECK-LABEL: @zext_sext_sle_op0_narrow(
 ; CHECK-NEXT:    [[A:%.*]] = zext i8 [[X:%.*]] to i32
@@ -169,6 +204,19 @@ define i1 @zext_sext_sle_op0_narrow(i8 %x, i16 %y) {
   ret i1 %c
 }
 
+
+define i1 @zext_nneg_sext_sle_op0_narrow(i8 %x, i16 %y) {
+; CHECK-LABEL: @zext_nneg_sext_sle_op0_narrow(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[X:%.*]] to i16
+; CHECK-NEXT:    [[C:%.*]] = icmp sle i16 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = zext nneg i8 %x to i32
+  %b = sext i16 %y to i32
+  %c = icmp sle i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_ule_op0_wide(
 ; CHECK-NEXT:    [[A:%.*]] = zext i9 [[X:%.*]] to i32
@@ -182,6 +230,18 @@ define i1 @zext_sext_ule_op0_wide(i9 %x, i8 %y) {
   ret i1 %c
 }
 
+define i1 @zext_nneg_sext_ule_op0_wide(i9 %x, i8 %y) {
+; CHECK-LABEL: @zext_nneg_sext_ule_op0_wide(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i9
+; CHECK-NEXT:    [[C:%.*]] = icmp uge i9 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = zext nneg i9 %x to i32
+  %b = sext i8 %y to i32
+  %c = icmp ule i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @sext_zext_slt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_slt(
 ; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
@@ -195,6 +255,18 @@ define i1 @sext_zext_slt(i8 %x, i8 %y) {
   ret i1 %c
 }
 
+
+define i1 @sext_zext_nneg_slt(i8 %x, i8 %y) {
+; CHECK-LABEL: @sext_zext_nneg_slt(
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = sext i8 %x to i32
+  %b = zext nneg i8 %y to i32
+  %c = icmp slt i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @sext_zext_ult(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_ult(
 ; CHECK-NEXT:    [[A:%.*]] = sext i8 [[X:%.*]] to i32
@@ -208,6 +280,17 @@ define i1 @sext_zext_ult(i8 %x, i8 %y) {
   ret i1 %c
 }
 
+define i1 @sext_zext_nneg_ult(i8 %x, i8 %y) {
+; CHECK-LABEL: @sext_zext_nneg_ult(
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = sext i8 %x to i32
+  %b = zext nneg i8 %y to i32
+  %c = icmp ult i32 %a, %b
+  ret i1 %c
+}
+
 define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @sext_zext_ne(
 ; CHECK-NEXT:    [[A:%.*]] = sext <2 x i8> [[X:%.*]] to <2 x i32>
@@ -221,6 +304,18 @@ define <2 x i1> @sext_zext_ne(<2 x i8> %x, <2 x i8> %y) {
   ret <2 x i1> %c
 }
 
+
+define <2 x i1> @sext_zext_nneg_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @sext_zext_nneg_ne(
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret <2 x i1> [[C]]
+;
+  %a = sext <2 x i8> %x to <2 x i32>
+  %b = zext nneg <2 x i8> %y to <2 x i32>
+  %c = icmp ne <2 x i32> %a, %b
+  ret <2 x i1> %c
+}
+
 define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_sge_op0_narrow(
 ; CHECK-NEXT:    [[A:%.*]] = sext i5 [[X:%.*]] to i32
@@ -234,6 +329,19 @@ define i1 @sext_zext_sge_op0_narrow(i5 %x, i8 %y) {
   ret i1 %c
 }
 
+
+define i1 @sext_zext_nneg_sge_op0_narrow(i5 %x, i8 %y) {
+; CHECK-LABEL: @sext_zext_nneg_sge_op0_narrow(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i5 [[X:%.*]] to i8
+; CHECK-NEXT:    [[C:%.*]] = icmp sge i8 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = sext i5 %x to i32
+  %b = zext nneg i8 %y to i32
+  %c = icmp sge i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @sext_zext_uge_op0_wide(i16 %x, i8 %y) {
 ; CHECK-LABEL: @sext_zext_uge_op0_wide(
 ; CHECK-NEXT:    [[A:%.*]] = sext i16 [[X:%.*]] to i32
@@ -247,6 +355,19 @@ define i1 @sext_zext_uge_op0_wide(i16 %x, i8 %y) {
   ret i1 %c
 }
 
+
+define i1 @sext_zext_nneg_uge_op0_wide(i16 %x, i8 %y) {
+; CHECK-LABEL: @sext_zext_nneg_uge_op0_wide(
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i8 [[Y:%.*]] to i16
+; CHECK-NEXT:    [[C:%.*]] = icmp ule i16 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %a = sext i16 %x to i32
+  %b = zext nneg i8 %y to i32
+  %c = icmp uge i32 %a, %b
+  ret i1 %c
+}
+
 define i1 @zext_sext_sgt_known_nonneg(i8 %x, i8 %y) {
 ; CHECK-LABEL: @zext_sext_sgt_known_nonneg(
 ; CHECK-NEXT:    [[N:%.*]] = udiv i8 127, [[X:%.*]]
diff --git a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll b/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
deleted file mode 100644
index f9933c7f3aff228..000000000000000
--- a/llvm/test/Transforms/InstCombine/icmp-fold-with-cast.ll
+++ /dev/null
@@ -1,175 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
-; See PR-70845 for more details
-; RUN: opt < %s -S -passes=instcombine | FileCheck %s
-
-
-define signext i32 @sext_sext(i16 %x, i16 %y) {
-; CHECK-LABEL: define signext i32 @sext_sext(
-; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[X]], [[Y]]
-; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
-; CHECK:       cond.true:
-; CHECK-NEXT:    br label [[COND_END:%.*]]
-; CHECK:       cond.false:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       cond.end:
-; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ 1, [[COND_FALSE]] ]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-entry:
-  %conv = sext i16 %x to i32
-  %conv1 = sext i16 %y to i32
-  %cmp2 = icmp sgt i32 %conv, %conv1
-  br i1 %cmp2, label %cond.true, label %cond.false
-
-cond.true:                                        ; preds = %for.body
-  br label %cond.end
-
-cond.false:                                       ; preds = %for.body
-  br label %cond.end
-
-cond.end:                                         ; preds = %cond.false, %cond.true
-  %cond = phi i32 [ 0, %cond.true ], [ 1, %cond.false ]
-  ret i32 %cond
-}
-
-
-define signext i32 @zext_zext(i16 %x, i16 %y) {
-; CHECK-LABEL: define signext i32 @zext_zext(
-; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i16 [[X]], [[Y]]
-; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
-; CHECK:       cond.true:
-; CHECK-NEXT:    br label [[COND_END:%.*]]
-; CHECK:       cond.false:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       cond.end:
-; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ 1, [[COND_FALSE]] ]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-entry:
-  %conv = zext i16 %x to i32
-  %conv1 = zext i16 %y to i32
-  %cmp2 = icmp sgt i32 %conv, %conv1
-  br i1 %cmp2, label %cond.true, label %cond.false
-
-cond.true:                                        ; preds = %for.body
-  br label %cond.end
-
-cond.false:                                       ; preds = %for.body
-  br label %cond.end
-
-cond.end:                                         ; preds = %cond.false, %cond.true
-  %cond = phi i32 [ 0, %cond.true ], [ 1, %cond.false ]
-  ret i32 %cond
-}
-
-
-define signext i16 @zext_positive_and_sext(i32 noundef %n, ptr noundef %v) {
-; CHECK-LABEL: define signext i16 @zext_positive_and_sext(
-; CHECK-SAME: i32 noundef [[N:%.*]], ptr noundef [[V:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[FOR_COND:%.*]]
-; CHECK:       for.cond:
-; CHECK-NEXT:    [[P_0:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[COND_OFF0:%.*]], [[COND_END:%.*]] ]
-; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[COND_END]] ]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N]]
-; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[IDXPROM:%.*]] = zext nneg i32 [[I_0]] to i64
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i16, ptr [[V]], i64 [[IDXPROM]]
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[P_0]], [[TMP0]]
-; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
-; CHECK:       cond.true:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       cond.false:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       for.cond.cleanup:
-; CHECK-NEXT:    ret i16 [[P_0]]
-; CHECK:       cond.end:
-; CHECK-NEXT:    [[COND_OFF0]] = phi i16 [ [[TMP0]], [[COND_TRUE]] ], [ [[P_0]], [[COND_FALSE]] ]
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_0]], 1
-; CHECK-NEXT:    br label [[FOR_COND]]
-;
-entry:
-  br label %for.cond
-
-for.cond:                                         ; preds = %cond.end, %entry
-  %p.0 = phi i16 [ 0, %entry ], [ %conv8, %cond.end ]
-  %i.0 = phi i32 [ 0, %entry ], [ %inc, %cond.end ]
-  %cmp = icmp slt i32 %i.0, %n
-  br i1 %cmp, label %for.body, label %for.cond.cleanup
-
-for.body:                                         ; preds = %for.cond
-  %conv = zext nneg i16 %p.0 to i32                    ;; %p.0 is always positive here
-  %idxprom = sext i32 %i.0 to i64
-  %arrayidx = getelementptr i16, ptr %v, i64 %idxprom
-  %0 = load i16, ptr %arrayidx, align 2
-  %conv1 = sext i16 %0 to i32
-  %cmp2 = icmp slt i32 %conv, %conv1
-  br i1 %cmp2, label %cond.true, label %cond.false
-
-cond.true:                                        ; preds = %for.body
-  br label %cond.end
-
-cond.false:                                       ; preds = %for.body
-  br label %cond.end
-
-for.cond.cleanup:                                 ; preds = %for.cond
-  ret i16 %p.0
-
-cond.end:                                         ; preds = %cond.false, %cond.true
-  %cond = phi i32 [ %conv1, %cond.true ], [ %conv, %cond.false ]
-  %conv8 = trunc i32 %cond to i16
-  %inc = add nsw i32 %i.0, 1
-  br label %for.cond
-}
-
-
-
-define signext i16 @sext_and_zext_positive(i16 %x) {
-; CHECK-LABEL: define signext i16 @sext_and_zext_positive(
-; CHECK-SAME: i16 [[X:%.*]]) {
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[FOR_COND:%.*]]
-; CHECK:       for.cond:
-; CHECK-NEXT:    [[V:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[A:%.*]], [[COND_END:%.*]] ]
-; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i16 [[V]], [[X]]
-; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
-; CHECK:       cond.true:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       cond.false:
-; CHECK-NEXT:    br label [[COND_END]]
-; CHECK:       cond.end:
-; CHECK-NEXT:    [[A]] = phi i16 [ 11, [[COND_TRUE]] ], [ 21, [[COND_FALSE]] ]
-; CHECK-NEXT:    br label [[FOR_COND]]
-;
-entry:
-  br label %for.cond
-
-for.cond:                                         ; preds = %cond.end, %entry
-  %v = phi i16 [ 0, %entry ], [ %inc, %cond.end ] ;; always positive
-  br label %for.body
-
-for.body:                                         ; preds = %for.cond
-  %conv = zext nneg i16 %v to i32                    ;; %p.0 is always positive here
-  %conv1 = sext i16 %x to i32                    ;; %p.0 is always positive here
-  %cmp2 = icmp slt i32 %conv1, %conv ;; positive/positive
-  br i1 %cmp2, label %cond.true, label %cond.false
-
-cond.true:                                        ; preds = %for.body
-  br label %cond.end
-
-cond.false:                                       ; preds = %for.body
-  br label %cond.end
-
-cond.end:                                         ; preds = %cond.false, %cond.true
-  %a = phi i16 [ 10, %cond.true ],  [ 20, %cond.false ]
-  %inc = add i16 %a, 1
-  br label %for.cond
-}

>From b6f51feb4cd3d0bcbf4e3ed20bed50bbe95d43d7 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Fri, 10 Nov 2023 14:53:52 -0500
Subject: [PATCH 13/14] Remove whitespace at the end of comment lines

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index b003b65955ac293..03bc0f16c8938ae 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5554,8 +5554,8 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
         return new ICmpInst(ICmp.getPredicate(), Builder.CreateOr(X, Y),
                             Constant::getNullValue(X->getType()));
 
-      // If we have mismatched casts and zext has the nneg flag, we can 
-      //  treat the "zext nneg" as "sext". Otherwise, we cannot fold and quit. 
+      // If we have mismatched casts and zext has the nneg flag, we can
+      //  treat the "zext nneg" as "sext". Otherwise, we cannot fold and quit.
 
       auto *NonNegInst0 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(0));
       auto *NonNegInst1 = dyn_cast<PossiblyNonNegInst>(ICmp.getOperand(1));

>From b6d000765971cdd65dd8b7626117fa9a171da364 Mon Sep 17 00:00:00 2001
From: leo-ard <lool4516 at gmail.com>
Date: Sat, 11 Nov 2023 11:53:41 -0500
Subject: [PATCH 14/14] Update min_max_loop test

---
 .../Transforms/PhaseOrdering/min_max_loop.ll  | 117 +++++++-----------
 1 file changed, 42 insertions(+), 75 deletions(-)

diff --git a/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
index 67176280abb1bb4..9981d663dbe2bcd 100644
--- a/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
+++ b/llvm/test/Transforms/PhaseOrdering/min_max_loop.ll
@@ -1,8 +1,8 @@
-; RUN: opt < %s --O3 -S | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt < %s -O3 -S | FileCheck %s
 ; See issue #55013 and PR #70845 for more details.
-; This test comes from the following C program, compiled with : 
-;   > clang -O0 -S -emit-llvm -fno-discard-value-names
-; 
+; This test comes from the following C program, compiled with clang
+;
 ;; short vecreduce_smin_v2i16(int n, short* v)
 ;; {
 ;;   short p = 0;
@@ -19,127 +19,94 @@
 ;;   return p;
 ;; }
 
-define signext i16 @vecreduce_smin_v2i16(i32 noundef %n, ptr noundef %v) {
-  ;; CHECK: @llvm.smin
+define i16 @vecreduce_smin_v2i16(i32 %n, ptr %v) {
+; CHECK-LABEL: define i16 @vecreduce_smin_v2i16(
+; CHECK:    @llvm.smin.v2i16
+
 entry:
-  %n.addr = alloca i32, align 4
-  %v.addr = alloca ptr, align 8
-  %p = alloca i16, align 2
-  %i = alloca i32, align 4
-  store i32 %n, ptr %n.addr, align 4
-  store ptr %v, ptr %v.addr, align 8
-  store i16 0, ptr %p, align 2
-  store i32 0, ptr %i, align 4
   br label %for.cond
 
 for.cond:                                         ; preds = %for.inc, %entry
-  %0 = load i32, ptr %i, align 4
-  %1 = load i32, ptr %n.addr, align 4
-  %cmp = icmp slt i32 %0, %1
+  %p.0 = phi i16 [ 0, %entry ], [ %conv8, %for.inc ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %n
   br i1 %cmp, label %for.body, label %for.end
 
 for.body:                                         ; preds = %for.cond
-  %2 = load i16, ptr %p, align 2
-  %conv = sext i16 %2 to i32
-  %3 = load ptr, ptr %v.addr, align 8
-  %4 = load i32, ptr %i, align 4
-  %idxprom = sext i32 %4 to i64
-  %arrayidx = getelementptr inbounds i16, ptr %3, i64 %idxprom
-  %5 = load i16, ptr %arrayidx, align 2
-  %conv1 = sext i16 %5 to i32
+  %conv = sext i16 %p.0 to i32
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i16, ptr %v, i64 %idxprom
+  %0 = load i16, ptr %arrayidx, align 2
+  %conv1 = sext i16 %0 to i32
   %cmp2 = icmp sgt i32 %conv, %conv1
   br i1 %cmp2, label %cond.true, label %cond.false
 
 cond.true:                                        ; preds = %for.body
-  %6 = load ptr, ptr %v.addr, align 8
-  %7 = load i32, ptr %i, align 4
-  %idxprom4 = sext i32 %7 to i64
-  %arrayidx5 = getelementptr inbounds i16, ptr %6, i64 %idxprom4
-  %8 = load i16, ptr %arrayidx5, align 2
-  %conv6 = sext i16 %8 to i32
+  %idxprom4 = sext i32 %i.0 to i64
+  %arrayidx5 = getelementptr inbounds i16, ptr %v, i64 %idxprom4
+  %1 = load i16, ptr %arrayidx5, align 2
+  %conv6 = sext i16 %1 to i32
   br label %cond.end
 
 cond.false:                                       ; preds = %for.body
-  %9 = load i16, ptr %p, align 2
-  %conv7 = sext i16 %9 to i32
+  %conv7 = sext i16 %p.0 to i32
   br label %cond.end
 
 cond.end:                                         ; preds = %cond.false, %cond.true
   %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ]
   %conv8 = trunc i32 %cond to i16
-  store i16 %conv8, ptr %p, align 2
   br label %for.inc
 
 for.inc:                                          ; preds = %cond.end
-  %10 = load i32, ptr %i, align 4
-  %inc = add nsw i32 %10, 1
-  store i32 %inc, ptr %i, align 4
+  %inc = add nsw i32 %i.0, 1
   br label %for.cond
 
 for.end:                                          ; preds = %for.cond
-  %11 = load i16, ptr %p, align 2
-  ret i16 %11
+  ret i16 %p.0
 }
 
-; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
 define signext i16 @vecreduce_smax_v2i16(i32 noundef %n, ptr noundef %v) {
-  ;; CHECK: @llvm.smax
+; CHECK-LABEL: define signext i16 @vecreduce_smax_v2i16(
+; CHECK:  @llvm.smax.v2i16
+
 entry:
-  %n.addr = alloca i32, align 4
-  %v.addr = alloca ptr, align 8
-  %p = alloca i16, align 2
-  %i = alloca i32, align 4
-  store i32 %n, ptr %n.addr, align 4
-  store ptr %v, ptr %v.addr, align 8
-  store i16 0, ptr %p, align 2
-  store i32 0, ptr %i, align 4
   br label %for.cond
 
 for.cond:                                         ; preds = %for.inc, %entry
-  %0 = load i32, ptr %i, align 4
-  %1 = load i32, ptr %n.addr, align 4
-  %cmp = icmp slt i32 %0, %1
+  %p.0 = phi i16 [ 0, %entry ], [ %conv8, %for.inc ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %n
   br i1 %cmp, label %for.body, label %for.end
 
 for.body:                                         ; preds = %for.cond
-  %2 = load i16, ptr %p, align 2
-  %conv = sext i16 %2 to i32
-  %3 = load ptr, ptr %v.addr, align 8
-  %4 = load i32, ptr %i, align 4
-  %idxprom = sext i32 %4 to i64
-  %arrayidx = getelementptr inbounds i16, ptr %3, i64 %idxprom
-  %5 = load i16, ptr %arrayidx, align 2
-  %conv1 = sext i16 %5 to i32
+  %conv = sext i16 %p.0 to i32
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i16, ptr %v, i64 %idxprom
+  %0 = load i16, ptr %arrayidx, align 2
+  %conv1 = sext i16 %0 to i32
   %cmp2 = icmp slt i32 %conv, %conv1
   br i1 %cmp2, label %cond.true, label %cond.false
 
 cond.true:                                        ; preds = %for.body
-  %6 = load ptr, ptr %v.addr, align 8
-  %7 = load i32, ptr %i, align 4
-  %idxprom4 = sext i32 %7 to i64
-  %arrayidx5 = getelementptr inbounds i16, ptr %6, i64 %idxprom4
-  %8 = load i16, ptr %arrayidx5, align 2
-  %conv6 = sext i16 %8 to i32
+  %idxprom4 = sext i32 %i.0 to i64
+  %arrayidx5 = getelementptr inbounds i16, ptr %v, i64 %idxprom4
+  %1 = load i16, ptr %arrayidx5, align 2
+  %conv6 = sext i16 %1 to i32
   br label %cond.end
 
 cond.false:                                       ; preds = %for.body
-  %9 = load i16, ptr %p, align 2
-  %conv7 = sext i16 %9 to i32
+  %conv7 = sext i16 %p.0 to i32
   br label %cond.end
 
 cond.end:                                         ; preds = %cond.false, %cond.true
   %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ]
   %conv8 = trunc i32 %cond to i16
-  store i16 %conv8, ptr %p, align 2
   br label %for.inc
 
 for.inc:                                          ; preds = %cond.end
-  %10 = load i32, ptr %i, align 4
-  %inc = add nsw i32 %10, 1
-  store i32 %inc, ptr %i, align 4
+  %inc = add nsw i32 %i.0, 1
   br label %for.cond
 
 for.end:                                          ; preds = %for.cond
-  %11 = load i16, ptr %p, align 2
-  ret i16 %11
-}
\ No newline at end of file
+  ret i16 %p.0
+}



More information about the cfe-commits mailing list