From c18e8bc0df80e4ec1660a9f44ac766426733d972 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 11 Sep 2017 19:42:41 +0000 Subject: [PATCH] [InstSimplify] add tests for possible sdiv/srem simplifications; NFC As noted in PR34517, the handling of signed div/rem is not on par with unsigned div/rem. Signed is harder to reason about, but it should be possible to handle at least some of these using the same technique that we use for unsigned: use icmp logic to see if there's a relationship between the quotient and divisor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312938 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Transforms/InstSimplify/signed-div-rem.ll | 354 ++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 test/Transforms/InstSimplify/signed-div-rem.ll diff --git a/test/Transforms/InstSimplify/signed-div-rem.ll b/test/Transforms/InstSimplify/signed-div-rem.ll new file mode 100644 index 00000000000..84c14757f8a --- /dev/null +++ b/test/Transforms/InstSimplify/signed-div-rem.ll @@ -0,0 +1,354 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +define i32 @sdiv_sext_big_divisor(i8 %x) { +; CHECK-LABEL: @sdiv_sext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 129 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = sext i8 %x to i32 + %div = sdiv i32 %conv, 129 + ret i32 %div +} + +define i32 @not_sdiv_sext_big_divisor(i8 %x) { +; CHECK-LABEL: @not_sdiv_sext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 128 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = sext i8 %x to i32 + %div = sdiv i32 %conv, 128 + ret i32 %div +} + +define i32 @sdiv_sext_small_divisor(i8 %x) { +; CHECK-LABEL: @sdiv_sext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -129 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = sext i8 %x to i32 + %div = sdiv i32 %conv, -129 + ret i32 %div +} + +define i32 @not_sdiv_sext_small_divisor(i8 %x) { +; CHECK-LABEL: @not_sdiv_sext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -128 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = sext i8 %x to i32 + %div = sdiv i32 %conv, -128 + ret i32 %div +} + +define i32 @sdiv_zext_big_divisor(i8 %x) { +; CHECK-LABEL: @sdiv_zext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 256 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = zext i8 %x to i32 + %div = sdiv i32 %conv, 256 + ret i32 %div +} + +define i32 @not_sdiv_zext_big_divisor(i8 %x) { +; CHECK-LABEL: @not_sdiv_zext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], 255 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = zext i8 %x to i32 + %div = sdiv i32 %conv, 255 + ret i32 %div +} + +define i32 @sdiv_zext_small_divisor(i8 %x) { +; CHECK-LABEL: @sdiv_zext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -256 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = zext i8 %x to i32 + %div = sdiv i32 %conv, -256 + ret i32 %div +} + +define i32 @not_sdiv_zext_small_divisor(i8 %x) { +; CHECK-LABEL: @not_sdiv_zext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[CONV]], -255 +; CHECK-NEXT: ret i32 [[DIV]] +; + %conv = zext i8 %x to i32 + %div = sdiv i32 %conv, -255 + ret i32 %div +} + +define i32 @sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @sdiv_quotient_known_smaller_than_pos_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], 254 +; CHECK-NEXT: ret i32 [[DIV]] +; + %and = and i32 %x, 253 + %div = sdiv i32 %and, 254 + ret i32 %div +} + +define i32 @not_sdiv_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_pos_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], 253 +; CHECK-NEXT: ret i32 [[DIV]] +; + %and = and i32 %x, 253 + %div = sdiv i32 %and, 253 + ret i32 %div +} + +define i32 @sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @sdiv_quotient_known_smaller_than_neg_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], -254 +; CHECK-NEXT: ret i32 [[DIV]] +; + %and = and i32 %x, 253 + %div = sdiv i32 %and, -254 + ret i32 %div +} + +define i32 @not_sdiv_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_neg_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[AND]], -253 +; CHECK-NEXT: ret i32 [[DIV]] +; + %and = and i32 %x, 253 + %div = sdiv i32 %and, -253 + ret i32 %div +} + +define i32 @sdiv_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @sdiv_quotient_known_smaller_than_pos_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], 254 +; CHECK-NEXT: ret i32 [[DIV]] +; + %or = or i32 %x, -253 + %div = sdiv i32 %or, 254 + ret i32 %div +} + +define i32 @not_sdiv_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_pos_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], 253 +; CHECK-NEXT: ret i32 [[DIV]] +; + %or = or i32 %x, -253 + %div = sdiv i32 %or, 253 + ret i32 %div +} + +define i32 @sdiv_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @sdiv_quotient_known_smaller_than_neg_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], -254 +; CHECK-NEXT: ret i32 [[DIV]] +; + %or = or i32 %x, -253 + %div = sdiv i32 %or, -254 + ret i32 %div +} + +define i32 @not_sdiv_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @not_sdiv_quotient_known_smaller_than_neg_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[OR]], -253 +; CHECK-NEXT: ret i32 [[DIV]] +; + %or = or i32 %x, -253 + %div = sdiv i32 %or, -253 + ret i32 %div +} + +define i32 @srem_sext_big_divisor(i8 %x) { +; CHECK-LABEL: @srem_sext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 129 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = sext i8 %x to i32 + %rem = srem i32 %conv, 129 + ret i32 %rem +} + +define i32 @not_srem_sext_big_divisor(i8 %x) { +; CHECK-LABEL: @not_srem_sext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 128 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = sext i8 %x to i32 + %rem = srem i32 %conv, 128 + ret i32 %rem +} + +define i32 @srem_sext_small_divisor(i8 %x) { +; CHECK-LABEL: @srem_sext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -129 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = sext i8 %x to i32 + %rem = srem i32 %conv, -129 + ret i32 %rem +} + +define i32 @not_srem_sext_small_divisor(i8 %x) { +; CHECK-LABEL: @not_srem_sext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = sext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -128 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = sext i8 %x to i32 + %rem = srem i32 %conv, -128 + ret i32 %rem +} + +define i32 @srem_zext_big_divisor(i8 %x) { +; CHECK-LABEL: @srem_zext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 256 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = zext i8 %x to i32 + %rem = srem i32 %conv, 256 + ret i32 %rem +} + +define i32 @not_srem_zext_big_divisor(i8 %x) { +; CHECK-LABEL: @not_srem_zext_big_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], 255 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = zext i8 %x to i32 + %rem = srem i32 %conv, 255 + ret i32 %rem +} + +define i32 @srem_zext_small_divisor(i8 %x) { +; CHECK-LABEL: @srem_zext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -256 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = zext i8 %x to i32 + %rem = srem i32 %conv, -256 + ret i32 %rem +} + +define i32 @not_srem_zext_small_divisor(i8 %x) { +; CHECK-LABEL: @not_srem_zext_small_divisor( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[CONV]], -255 +; CHECK-NEXT: ret i32 [[REM]] +; + %conv = zext i8 %x to i32 + %rem = srem i32 %conv, -255 + ret i32 %rem +} + +define i32 @srem_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @srem_quotient_known_smaller_than_pos_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], 254 +; CHECK-NEXT: ret i32 [[REM]] +; + %and = and i32 %x, 253 + %rem = srem i32 %and, 254 + ret i32 %rem +} + +define i32 @not_srem_quotient_known_smaller_than_pos_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @not_srem_quotient_known_smaller_than_pos_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], 253 +; CHECK-NEXT: ret i32 [[REM]] +; + %and = and i32 %x, 253 + %rem = srem i32 %and, 253 + ret i32 %rem +} + +define i32 @srem_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @srem_quotient_known_smaller_than_neg_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], -254 +; CHECK-NEXT: ret i32 [[REM]] +; + %and = and i32 %x, 253 + %rem = srem i32 %and, -254 + ret i32 %rem +} + +define i32 @not_srem_quotient_known_smaller_than_neg_divisor_clear_bits(i32 %x) { +; CHECK-LABEL: @not_srem_quotient_known_smaller_than_neg_divisor_clear_bits( +; CHECK-NEXT: [[AND:%.*]] = and i32 %x, 253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[AND]], -253 +; CHECK-NEXT: ret i32 [[REM]] +; + %and = and i32 %x, 253 + %rem = srem i32 %and, -253 + ret i32 %rem +} + +define i32 @srem_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @srem_quotient_known_smaller_than_pos_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], 254 +; CHECK-NEXT: ret i32 [[REM]] +; + %or = or i32 %x, -253 + %rem = srem i32 %or, 254 + ret i32 %rem +} + +define i32 @not_srem_quotient_known_smaller_than_pos_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @not_srem_quotient_known_smaller_than_pos_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], 253 +; CHECK-NEXT: ret i32 [[REM]] +; + %or = or i32 %x, -253 + %rem = srem i32 %or, 253 + ret i32 %rem +} + +define i32 @srem_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @srem_quotient_known_smaller_than_neg_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], -254 +; CHECK-NEXT: ret i32 [[REM]] +; + %or = or i32 %x, -253 + %rem = srem i32 %or, -254 + ret i32 %rem +} + +define i32 @not_srem_quotient_known_smaller_than_neg_divisor_set_bits(i32 %x) { +; CHECK-LABEL: @not_srem_quotient_known_smaller_than_neg_divisor_set_bits( +; CHECK-NEXT: [[OR:%.*]] = or i32 %x, -253 +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[OR]], -253 +; CHECK-NEXT: ret i32 [[REM]] +; + %or = or i32 %x, -253 + %rem = srem i32 %or, -253 + ret i32 %rem +} + -- 2.40.0