[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
leo-ard wrote: @nikic ping:) https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -5587,11 +5587,20 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) { return new ICmpInst(ICmp.getPredicate(), Builder.CreateOr(X, Y), Constant::getNullValue(X->getType())); + // Treat "zext nneg" as "sext" + auto *NonNegInst0 = dyn_cast(ICmp.getOperand(0)); + auto *NonNegInst1 = dyn_cast(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 && 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))) || dtcxzyw wrote: Why not check the `nneg` flag in `isKnownNonNegative`? https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw edited https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,126 @@ +; RUN: opt < %s --O3 -S | FileCheck %s + +define signext i16 @vecreduce_smax_v2i16(i32 noundef %0, ptr noundef %1) #0 { dtcxzyw wrote: Could you please reduce the test case and move it into `InstCombine`? https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
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 Date: Mon, 30 Oct 2023 18:01:27 -0400 Subject: [PATCH 01/12] 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(ICmp.getOperand(0)); + bool IsNonNeg1 = isa(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 Date: Mon, 30 Oct 2023 18:03:44 -0400 Subject: [PATCH 02/12] 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 000..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 000..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:
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,175 @@ +; 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.t
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -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( leo-ard wrote: Every test in this test-file has an `known_nonneg` variant for mismatched zext/sext. I was wondering on the relevance of this variant as we now have the nneg flag on zext. It would make more sense to have specialized tests for zext -> zext nneg folding with value-tracking and another test for icmp with zext nneg/sext folding into icmp (what I just added). FYI, this test dates from this PR, when there where no nneg flag : https://reviews.llvm.org/D124419. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,175 @@ +; 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) { leo-ard wrote: The technique of commenting and seeing which tests crashed worked really well. Thanks for the trick https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 3f906f513edea5c21867586d92151c4268230fe4 3f2ad99f9a6d177ea2747bfc0e559aad1faf8639 -- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp `` View the diff from clang-format here. ``diff diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index b003b65955ac..03bc0f16c893 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(ICmp.getOperand(0)); auto *NonNegInst1 = dyn_cast(ICmp.getOperand(1)); `` https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw edited https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s dtcxzyw wrote: Could you please: 1. Convert this IR into SSA form as @nikic mentioned. 2. Drop unused attributes. 3. Re-generate tests with `llvm/utils/update_test_checks.py`. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s dtcxzyw wrote: ```suggestion ; RUN: opt < %s -O3 -S | FileCheck %s ``` https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw requested changes to this pull request. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s dtcxzyw wrote: ``` define i16 @vecreduce_smin_v2i16(i32 %n, ptr %v) { entry: br label %for.cond for.cond: %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: %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: %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: %conv7 = sext i16 %p.0 to i32 br label %cond.end cond.end: %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ] %conv8 = trunc i32 %cond to i16 br label %for.inc for.inc: %inc = add nsw i32 %i.0, 1 br label %for.cond for.end: ret i16 %p.0 } define i16 @vecreduce_smax_v2i16(i32 %n, ptr %v) { entry: br label %for.cond for.cond: %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: %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: %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: %conv7 = sext i16 %p.0 to i32 br label %cond.end cond.end: %cond = phi i32 [ %conv6, %cond.true ], [ %conv7, %cond.false ] %conv8 = trunc i32 %cond to i16 br label %for.inc for.inc: %inc = add nsw i32 %i.0, 1 br label %for.cond for.end: ret i16 %p.0 } ``` https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -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( nikic wrote: Yeah, these tests are largely redundant now. We could delete them, but I think it's also okay to keep them to show the combination of nneg inference and this fold. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -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( leo-ard wrote: Ok I'll leave them then https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s leo-ard wrote: How did you get the SSA form ? I wasn't able to do it on my side. Here are the commands that I did : ```bash > build_release/bin/clang -S -emit-llvm min_max.c -fno-discard-value-names -o > min_max.ll > build_release/bin/opt -S -passes=sroa min_max.ll > min_max2.ll > head -n 20 min_max2.ll ; ModuleID = 'min_max.ll' source_filename = "min_max.c" target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" target triple = "arm64-apple-macosx14.0.0" ; Function Attrs: noinline nounwind optnone ssp uwtable(sync) define signext i16 @vecreduce_smin_v2i16(i32 noundef %n, ptr noundef %v) #0 { 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 ``` https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s nikic wrote: You need to use `-O2 -Xclang -disable-llvm-optzns`, or manually drop the `optnone` attributes. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,112 @@ +; 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 +; +;; 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 i16 @vecreduce_smin_v2i16(i32 %n, ptr %v) { +; CHECK-LABEL: define i16 @vecreduce_smin_v2i16( +; CHECK:@llvm.smin.v2i16 dtcxzyw wrote: Oh, it makes sense. Just checking `smin/smax` intrinsics is OK. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw edited https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,111 @@ +; 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 +; +;; 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 i16 @vecreduce_smin_v2i16(i32 %n, ptr %v) { +; CHECK-LABEL: define i16 @vecreduce_smin_v2i16( +; CHECK:@llvm.smin.v2i16 + +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %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 + %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 + %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 + %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 + br label %for.inc + +for.inc: ; preds = %cond.end + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret i16 %p.0 +} + +define signext i16 @vecreduce_smax_v2i16(i32 noundef %n, ptr noundef %v) { dtcxzyw wrote: ```suggestion define i16 @vecreduce_smax_v2i16(i32 %n, ptr %v) { ``` https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw commented: LGTM https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,145 @@ +; RUN: opt < %s --O3 -S | FileCheck %s dtcxzyw wrote: My command: `bin/opt -S -O3 -print-changed min_max.ll` Then I got IR after the SROA pass :) https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
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 Date: Mon, 30 Oct 2023 18:01:27 -0400 Subject: [PATCH 01/16] 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(ICmp.getOperand(0)); + bool IsNonNeg1 = isa(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 Date: Mon, 30 Oct 2023 18:03:44 -0400 Subject: [PATCH 02/16] 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 000..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 000..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:
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,111 @@ +; 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 +; +;; 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 i16 @vecreduce_smin_v2i16(i32 %n, ptr %v) { +; CHECK-LABEL: define i16 @vecreduce_smin_v2i16( +; CHECK:@llvm.smin.v2i16 + +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %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 + %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 + %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 + %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 + br label %for.inc + +for.inc: ; preds = %cond.end + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: ; preds = %for.cond + ret i16 %p.0 +} + +define signext i16 @vecreduce_smax_v2i16(i32 noundef %n, ptr noundef %v) { leo-ard wrote: oups, I missed those. Just fixed it:) https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [InstCombine] Use zext's nneg flag for icmp folding (PR #70845)
leo-ard wrote: > Do you have the access to merge PR? No I don't. Thanks for the time and insightful comments ! https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [InstCombine] Use zext's nneg flag for icmp folding (PR #70845)
https://github.com/dtcxzyw closed https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -5587,11 +5587,17 @@ 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(ICmp.getOperand(0)); + bool IsNonNeg1 = isa(ICmp.getOperand(1)); nikic wrote: This only checks whether the instruction *can* have an nneg flag, not whether it has it. You need to check `isNonNeg()` for that. https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -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-./bin/opt: opt < %s -S -passes=ipsccp | FileCheck %s nikic wrote: This is an ipsccp test in the InstCombine directory? https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
@@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -O2 -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s leo-ard wrote: Out of curiosity, why is end-to-end codegen with clang not used ? Is it too unstable ? https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
leo-ard wrote: Thanks for taking the time to review the PR. I just added another test in PhaseOrdering to make sure that the min/max intrinsics are generated https://github.com/llvm/llvm-project/pull/70845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[llvm] [clang] [Instcombine] use zext's nneg flag for icmp folding (PR #70845)
https://github.com/leo-ard updated https://github.com/llvm/llvm-project/pull/70845 From 6bb97fd48d59b7f79fdf90a2b27e9220f417fac7 Mon Sep 17 00:00:00 2001 From: leo-ard Date: Mon, 30 Oct 2023 18:01:27 -0400 Subject: [PATCH 1/9] 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 7574987d0e23141..4751d870da7a777 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5587,11 +5587,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(ICmp.getOperand(0)); + bool IsNonNeg1 = isa(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 6570c0a864805408928a0d7a54dd0098f2d58419 Mon Sep 17 00:00:00 2001 From: leo-ard Date: Mon, 30 Oct 2023 18:03:44 -0400 Subject: [PATCH 2/9] 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 000..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 000..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: