From: Sanjay Patel Date: Fri, 6 Jan 2017 18:57:54 +0000 (+0000) Subject: [InstCombine] move and add tests for icmp + shl nsw; NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6435c8a3b0276dd597e35b57786390e93737bbe3;p=llvm [InstCombine] move and add tests for icmp + shl nsw; NFC As discussed here: http://lists.llvm.org/pipermail/llvm-dev/2017-January/108749.html ...we should be able to better optimize this pattern. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291262 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Transforms/InstCombine/icmp-shl-nsw.ll b/test/Transforms/InstCombine/icmp-shl-nsw.ll new file mode 100644 index 00000000000..85e397ec241 --- /dev/null +++ b/test/Transforms/InstCombine/icmp-shl-nsw.ll @@ -0,0 +1,205 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; If the (shl x, C) preserved the sign and this is a sign test, +; compare the LHS operand instead + +define i1 @icmp_shl_nsw_sgt(i32 %x) { +; CHECK-LABEL: @icmp_shl_nsw_sgt( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i32 %x, 21 + %cmp = icmp sgt i32 %shl, 0 + ret i1 %cmp +} + +define i1 @icmp_shl_nsw_sge0(i32 %x) { +; CHECK-LABEL: @icmp_shl_nsw_sge0( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i32 %x, 21 + %cmp = icmp sge i32 %shl, 0 + ret i1 %cmp +} + +define i1 @icmp_shl_nsw_sge1(i32 %x) { +; CHECK-LABEL: @icmp_shl_nsw_sge1( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i32 %x, 21 + %cmp = icmp sge i32 %shl, 1 + ret i1 %cmp +} + +define <2 x i1> @icmp_shl_nsw_sge1_vec(<2 x i32> %x) { +; CHECK-LABEL: @icmp_shl_nsw_sge1_vec( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %x, zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %shl = shl nsw <2 x i32> %x, + %cmp = icmp sge <2 x i32> %shl, + ret <2 x i1> %cmp +} + +; Checks for icmp (eq|ne) (shl x, C), 0 + +define i1 @icmp_shl_nsw_eq(i32 %x) { +; CHECK-LABEL: @icmp_shl_nsw_eq( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %x, 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %mul = shl nsw i32 %x, 5 + %cmp = icmp eq i32 %mul, 0 + ret i1 %cmp +} + +define <2 x i1> @icmp_shl_nsw_eq_vec(<2 x i32> %x) { +; CHECK-LABEL: @icmp_shl_nsw_eq_vec( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> %x, zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %mul = shl nsw <2 x i32> %x, + %cmp = icmp eq <2 x i32> %mul, zeroinitializer + ret <2 x i1> %cmp +} + +; icmp sgt with shl nsw with a constant compare operand and constant +; shift amount can always be reduced to icmp sgt alone. + +; Known bits analysis turns this into an equality predicate. + +define i1 @icmp_sgt1(i8 %x) { +; CHECK-LABEL: @icmp_sgt1( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i8 %x, 127 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[SHL_MASK]], 64 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, -128 + ret i1 %cmp +} + +define i1 @icmp_sgt2(i8 %x) { +; CHECK-LABEL: @icmp_sgt2( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], -127 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, -127 + ret i1 %cmp +} + +define i1 @icmp_sgt3(i8 %x) { +; CHECK-LABEL: @icmp_sgt3( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], -16 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, -16 + ret i1 %cmp +} + +define i1 @icmp_sgt4(i8 %x) { +; CHECK-LABEL: @icmp_sgt4( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], -2 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, -2 + ret i1 %cmp +} + +; x >s -1 is a sign bit test. +; x >s 0 is a sign bit test. + +define i1 @icmp_sgt5(i8 %x) { +; CHECK-LABEL: @icmp_sgt5( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], 1 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, 1 + ret i1 %cmp +} + +define i1 @icmp_sgt6(i8 %x) { +; CHECK-LABEL: @icmp_sgt6( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], 16 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, 16 + ret i1 %cmp +} + +define i1 @icmp_sgt7(i8 %x) { +; CHECK-LABEL: @icmp_sgt7( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], 124 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, 124 + ret i1 %cmp +} + +; Known bits analysis turns this into an equality predicate. + +define i1 @icmp_sgt8(i8 %x) { +; CHECK-LABEL: @icmp_sgt8( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i8 %x, 127 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 63 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 1 + %cmp = icmp sgt i8 %shl, 125 + ret i1 %cmp +} + +; Compares with 126 and 127 are recognized as always false. + +; Known bits analysis turns this into an equality predicate. + +define i1 @icmp_sgt9(i8 %x) { +; CHECK-LABEL: @icmp_sgt9( +; CHECK-NEXT: [[SHL_MASK:%.*]] = and i8 %x, 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[SHL_MASK]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 7 + %cmp = icmp sgt i8 %shl, -128 + ret i1 %cmp +} + +define i1 @icmp_sgt10(i8 %x) { +; CHECK-LABEL: @icmp_sgt10( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 7 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], -127 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 7 + %cmp = icmp sgt i8 %shl, -127 + ret i1 %cmp +} + +define i1 @icmp_sgt11(i8 %x) { +; CHECK-LABEL: @icmp_sgt11( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 %x, 7 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SHL]], -2 +; CHECK-NEXT: ret i1 [[CMP]] +; + %shl = shl nsw i8 %x, 7 + %cmp = icmp sgt i8 %shl, -2 + ret i1 %cmp +} + +; Known bits analysis returns false for compares with >=0. + diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 099aaca5f7d..32fe050bf83 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1243,69 +1243,6 @@ define i1 @icmp_shl24(i32 %x) { ret i1 %cmp } -; If the (shl x, C) preserved the sign and this is a sign test, -; compare the LHS operand instead -define i1 @icmp_shl_nsw_sgt(i32 %x) { -; CHECK-LABEL: @icmp_shl_nsw_sgt( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 -; CHECK-NEXT: ret i1 [[CMP]] -; - %shl = shl nsw i32 %x, 21 - %cmp = icmp sgt i32 %shl, 0 - ret i1 %cmp -} - -define i1 @icmp_shl_nsw_sge0(i32 %x) { -; CHECK-LABEL: @icmp_shl_nsw_sge0( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, -1 -; CHECK-NEXT: ret i1 [[CMP]] -; - %shl = shl nsw i32 %x, 21 - %cmp = icmp sge i32 %shl, 0 - ret i1 %cmp -} - -define i1 @icmp_shl_nsw_sge1(i32 %x) { -; CHECK-LABEL: @icmp_shl_nsw_sge1( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 -; CHECK-NEXT: ret i1 [[CMP]] -; - %shl = shl nsw i32 %x, 21 - %cmp = icmp sge i32 %shl, 1 - ret i1 %cmp -} - -define <2 x i1> @icmp_shl_nsw_sge1_vec(<2 x i32> %x) { -; CHECK-LABEL: @icmp_shl_nsw_sge1_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %x, zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[CMP]] -; - %shl = shl nsw <2 x i32> %x, - %cmp = icmp sge <2 x i32> %shl, - ret <2 x i1> %cmp -} - -; Checks for icmp (eq|ne) (shl x, C), 0 -define i1 @icmp_shl_nsw_eq(i32 %x) { -; CHECK-LABEL: @icmp_shl_nsw_eq( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %x, 0 -; CHECK-NEXT: ret i1 [[CMP]] -; - %mul = shl nsw i32 %x, 5 - %cmp = icmp eq i32 %mul, 0 - ret i1 %cmp -} - -define <2 x i1> @icmp_shl_nsw_eq_vec(<2 x i32> %x) { -; CHECK-LABEL: @icmp_shl_nsw_eq_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> %x, zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[CMP]] -; - %mul = shl nsw <2 x i32> %x, - %cmp = icmp eq <2 x i32> %mul, zeroinitializer - ret <2 x i1> %cmp -} - define i1 @icmp_shl_eq(i32 %x) { ; CHECK-LABEL: @icmp_shl_eq( ; CHECK-NEXT: [[MUL_MASK:%.*]] = and i32 %x, 134217727