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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 <lool4...@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 +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits