From c99e17fef5f34ac536192fa7b915641f1962c7b9 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 13 Jul 2021 13:48:04 +0100 Subject: [PATCH] [InstCombine] Pre-commit ashr(or(neg(x),x),bw-1) --> sext(icmp_ne(x,0)) tests from D105764 Added 'thwart complexity-based canonicalization' hacks and the lshr(or(neg(x),x),bw-1) --> zext(icmp_ne(x,0)) variants suggested by Sanjay. --- .../InstCombine/sub-ashr-or-to-icmp-select.ll | 86 ++++++++++++++++ .../InstCombine/sub-lshr-or-to-icmp-select.ll | 98 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/sub-lshr-or-to-icmp-select.ll diff --git a/llvm/test/Transforms/InstCombine/sub-ashr-or-to-icmp-select.ll b/llvm/test/Transforms/InstCombine/sub-ashr-or-to-icmp-select.ll index fa5a8f693819..21d7c8a62119 100644 --- a/llvm/test/Transforms/InstCombine/sub-ashr-or-to-icmp-select.ll +++ b/llvm/test/Transforms/InstCombine/sub-ashr-or-to-icmp-select.ll @@ -72,6 +72,19 @@ define i64 @sub_ashr_or_i64(i64 %x, i64 %y) { ret i64 %or } +define i32 @neg_or_ashr_i32(i32 %x) { +; CHECK-LABEL: @neg_or_ashr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[OR]], 31 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = ashr i32 %or, 31 + ret i32 %shr +} + ; nuw nsw define i32 @sub_ashr_or_i32_nuw_nsw(i32 %x, i32 %y) { @@ -100,6 +113,21 @@ define i32 @sub_ashr_or_i32_commute(i32 %x, i32 %y) { ret i32 %or } +define i32 @neg_or_ashr_i32_commute(i32 %x0) { +; CHECK-LABEL: @neg_or_ashr_i32_commute( +; CHECK-NEXT: [[X:%.*]] = sdiv i32 42, [[X0:%.*]] +; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[X]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[NEG]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[OR]], 31 +; CHECK-NEXT: ret i32 [[SHR]] +; + %x = sdiv i32 42, %x0 ; thwart complexity-based canonicalization + %neg = sub i32 0, %x + %or = or i32 %x, %neg + %shr = ashr i32 %or, 31 + ret i32 %shr +} + ; Vector Types define <4 x i32> @sub_ashr_or_i32_vec(<4 x i32> %x, <4 x i32> %y) { @@ -126,6 +154,19 @@ define <4 x i32> @sub_ashr_or_i32_vec_nuw_nsw(<4 x i32> %x, <4 x i32> %y) { ret <4 x i32> %or } +define <4 x i32> @neg_or_ashr_i32_vec(<4 x i32> %x) { +; CHECK-LABEL: @neg_or_ashr_i32_vec( +; CHECK-NEXT: [[NEG:%.*]] = sub <4 x i32> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[OR]], +; CHECK-NEXT: ret <4 x i32> [[SHR]] +; + %neg = sub <4 x i32> zeroinitializer, %x + %or = or <4 x i32> %neg, %x + %shr = ashr <4 x i32> %or, + ret <4 x i32> %shr +} + define <4 x i32> @sub_ashr_or_i32_vec_commute(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @sub_ashr_or_i32_vec_commute( ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <4 x i32> [[Y:%.*]], [[X:%.*]] @@ -138,6 +179,21 @@ define <4 x i32> @sub_ashr_or_i32_vec_commute(<4 x i32> %x, <4 x i32> %y) { ret <4 x i32> %or } +define <4 x i32> @neg_or_ashr_i32_vec_commute(<4 x i32> %x0) { +; CHECK-LABEL: @neg_or_ashr_i32_vec_commute( +; CHECK-NEXT: [[X:%.*]] = sdiv <4 x i32> , [[X0:%.*]] +; CHECK-NEXT: [[NEG:%.*]] = sub nsw <4 x i32> zeroinitializer, [[X]] +; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[X]], [[NEG]] +; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[OR]], +; CHECK-NEXT: ret <4 x i32> [[SHR]] +; + %x = sdiv <4 x i32> , %x0 ; thwart complexity-based canonicalization + %neg = sub <4 x i32> zeroinitializer, %x + %or = or <4 x i32> %x, %neg + %shr = ashr <4 x i32> %or, + ret <4 x i32> %shr +} + ; Extra uses define i32 @sub_ashr_or_i32_extra_use_sub(i32 %x, i32 %y, i32* %p) { @@ -169,6 +225,21 @@ define i32 @sub_ashr_or_i32_extra_use_or(i32 %x, i32 %y, i32* %p) { ret i32 %or } +define i32 @neg_extra_use_or_ashr_i32(i32 %x, i32* %p) { +; CHECK-LABEL: @neg_extra_use_or_ashr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[OR]], 31 +; CHECK-NEXT: store i32 [[NEG]], i32* [[P:%.*]], align 4 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = ashr i32 %or, 31 + store i32 %neg, i32* %p + ret i32 %shr +} + ; Negative Tests define i32 @sub_ashr_or_i32_extra_use_ashr(i32 %x, i32 %y, i32* %p) { @@ -199,6 +270,21 @@ define i32 @sub_ashr_or_i32_no_nsw_nuw(i32 %x, i32 %y) { ret i32 %or } +define i32 @neg_or_extra_use_ashr_i32(i32 %x, i32* %p) { +; CHECK-LABEL: @neg_or_extra_use_ashr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[OR]], 31 +; CHECK-NEXT: store i32 [[OR]], i32* [[P:%.*]], align 4 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = ashr i32 %or, 31 + store i32 %or, i32* %p + ret i32 %shr +} + define <4 x i32> @sub_ashr_or_i32_vec_undef1(<4 x i32> %x) { ; CHECK-LABEL: @sub_ashr_or_i32_vec_undef1( ; CHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> , [[X:%.*]] diff --git a/llvm/test/Transforms/InstCombine/sub-lshr-or-to-icmp-select.ll b/llvm/test/Transforms/InstCombine/sub-lshr-or-to-icmp-select.ll new file mode 100644 index 000000000000..830b9f99b8eb --- /dev/null +++ b/llvm/test/Transforms/InstCombine/sub-lshr-or-to-icmp-select.ll @@ -0,0 +1,98 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine %s -S -o - | FileCheck %s + +; Scalar Types + +define i32 @neg_or_lshr_i32(i32 %x) { +; CHECK-LABEL: @neg_or_lshr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[OR]], 31 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = lshr i32 %or, 31 + ret i32 %shr +} + +; Commute + +define i32 @neg_or_lshr_i32_commute(i32 %x0) { +; CHECK-LABEL: @neg_or_lshr_i32_commute( +; CHECK-NEXT: [[X:%.*]] = sdiv i32 42, [[X0:%.*]] +; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[X]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], [[NEG]] +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[OR]], 31 +; CHECK-NEXT: ret i32 [[SHR]] +; + %x = sdiv i32 42, %x0 ; thwart complexity-based canonicalization + %neg = sub i32 0, %x + %or = or i32 %x, %neg + %shr = lshr i32 %or, 31 + ret i32 %shr +} + +; Vector Types + +define <4 x i32> @neg_or_lshr_i32_vec(<4 x i32> %x) { +; CHECK-LABEL: @neg_or_lshr_i32_vec( +; CHECK-NEXT: [[NEG:%.*]] = sub <4 x i32> zeroinitializer, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[OR]], +; CHECK-NEXT: ret <4 x i32> [[SHR]] +; + %neg = sub <4 x i32> zeroinitializer, %x + %or = or <4 x i32> %neg, %x + %shr = lshr <4 x i32> %or, + ret <4 x i32> %shr +} + +define <4 x i32> @neg_or_lshr_i32_vec_commute(<4 x i32> %x0) { +; CHECK-LABEL: @neg_or_lshr_i32_vec_commute( +; CHECK-NEXT: [[X:%.*]] = sdiv <4 x i32> , [[X0:%.*]] +; CHECK-NEXT: [[NEG:%.*]] = sub nsw <4 x i32> zeroinitializer, [[X]] +; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[X]], [[NEG]] +; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[OR]], +; CHECK-NEXT: ret <4 x i32> [[SHR]] +; + %x = sdiv <4 x i32> , %x0 ; thwart complexity-based canonicalization + %neg = sub <4 x i32> zeroinitializer, %x + %or = or <4 x i32> %x, %neg + %shr = lshr <4 x i32> %or, + ret <4 x i32> %shr +} + +; Extra uses + +define i32 @neg_extra_use_or_lshr_i32(i32 %x, i32* %p) { +; CHECK-LABEL: @neg_extra_use_or_lshr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[OR]], 31 +; CHECK-NEXT: store i32 [[NEG]], i32* [[P:%.*]], align 4 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = lshr i32 %or, 31 + store i32 %neg, i32* %p + ret i32 %shr +} + +; Negative Tests + +define i32 @neg_or_extra_use_lshr_i32(i32 %x, i32* %p) { +; CHECK-LABEL: @neg_or_extra_use_lshr_i32( +; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i32 [[NEG]], [[X]] +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[OR]], 31 +; CHECK-NEXT: store i32 [[OR]], i32* [[P:%.*]], align 4 +; CHECK-NEXT: ret i32 [[SHR]] +; + %neg = sub i32 0, %x + %or = or i32 %neg, %x + %shr = lshr i32 %or, 31 + store i32 %or, i32* %p + ret i32 %shr +}