2017-04-17 09:51:21 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
2013-05-11 17:01:28 +08:00
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
2002-05-06 13:43:36 +08:00
|
|
|
|
2017-03-15 00:27:46 +08:00
|
|
|
define i64 @rem_signed(i64 %x1, i64 %y2) {
|
|
|
|
; CHECK-LABEL: @rem_signed(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = srem i64 [[X1:%.*]], [[Y2:%.*]]
|
|
|
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
;
|
|
|
|
%r = sdiv i64 %x1, %y2
|
|
|
|
%r7 = mul i64 %r, %y2
|
|
|
|
%r8 = sub i64 %x1, %r7
|
|
|
|
ret i64 %r8
|
|
|
|
}
|
|
|
|
|
|
|
|
define <4 x i32> @rem_signed_vec(<4 x i32> %t, <4 x i32> %u) {
|
|
|
|
; CHECK-LABEL: @rem_signed_vec(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = srem <4 x i32> [[T:%.*]], [[U:%.*]]
|
|
|
|
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
;
|
|
|
|
%k = sdiv <4 x i32> %t, %u
|
|
|
|
%l = mul <4 x i32> %k, %u
|
|
|
|
%m = sub <4 x i32> %t, %l
|
|
|
|
ret <4 x i32> %m
|
|
|
|
}
|
|
|
|
|
|
|
|
define i64 @rem_unsigned(i64 %x1, i64 %y2) {
|
|
|
|
; CHECK-LABEL: @rem_unsigned(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = urem i64 [[X1:%.*]], [[Y2:%.*]]
|
|
|
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
;
|
|
|
|
%r = udiv i64 %x1, %y2
|
|
|
|
%r7 = mul i64 %r, %y2
|
|
|
|
%r8 = sub i64 %x1, %r7
|
|
|
|
ret i64 %r8
|
|
|
|
}
|
|
|
|
|
|
|
|
; PR28672 - https://llvm.org/bugs/show_bug.cgi?id=28672
|
|
|
|
|
|
|
|
define i8 @big_divisor(i8 %x) {
|
|
|
|
; CHECK-LABEL: @big_divisor(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], -127
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X]], 127
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[TMP2]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i8 [[REM]]
|
|
|
|
;
|
|
|
|
%rem = urem i8 %x, 129
|
|
|
|
ret i8 %rem
|
|
|
|
}
|
|
|
|
|
|
|
|
define i5 @biggest_divisor(i5 %x) {
|
|
|
|
; CHECK-LABEL: @biggest_divisor(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i5 [[X:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i5
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = add i5 [[TMP2]], [[X]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i5 [[REM]]
|
|
|
|
;
|
|
|
|
%rem = urem i5 %x, -1
|
|
|
|
ret i5 %rem
|
|
|
|
}
|
|
|
|
|
2018-06-27 00:01:24 +08:00
|
|
|
define i8 @urem_with_sext_bool_divisor(i1 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @urem_with_sext_bool_divisor(
|
2018-06-27 00:30:00 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], -1
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = select i1 [[TMP1]], i8 0, i8 [[Y]]
|
2018-06-27 00:01:24 +08:00
|
|
|
; CHECK-NEXT: ret i8 [[REM]]
|
|
|
|
;
|
|
|
|
%s = sext i1 %x to i8
|
|
|
|
%rem = urem i8 %y, %s
|
|
|
|
ret i8 %rem
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i8> @urem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i8> %y) {
|
|
|
|
; CHECK-LABEL: @urem_with_sext_bool_divisor_vec(
|
2018-06-27 00:30:00 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> zeroinitializer, <2 x i8> [[Y]]
|
2018-06-27 00:01:24 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i8> [[REM]]
|
|
|
|
;
|
|
|
|
%s = sext <2 x i1> %x to <2 x i8>
|
|
|
|
%rem = urem <2 x i8> %y, %s
|
|
|
|
ret <2 x i8> %rem
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:27:46 +08:00
|
|
|
define <2 x i4> @big_divisor_vec(<2 x i4> %x) {
|
|
|
|
; CHECK-LABEL: @big_divisor_vec(
|
2017-04-11 13:42:47 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i4> [[X:%.*]], <i4 -3, i4 -3>
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i4> [[X]], <i4 3, i4 3>
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = select <2 x i1> [[TMP1]], <2 x i4> [[X]], <2 x i4> [[TMP2]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i4> [[REM]]
|
|
|
|
;
|
|
|
|
%rem = urem <2 x i4> %x, <i4 13, i4 13>
|
|
|
|
ret <2 x i4> %rem
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @urem1(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @urem1(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
;
|
|
|
|
%A = udiv i8 %x, %y
|
|
|
|
%B = mul i8 %A, %y
|
|
|
|
%C = sub i8 %x, %B
|
|
|
|
ret i8 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @srem1(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @srem1(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i8 [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
;
|
|
|
|
%A = sdiv i8 %x, %y
|
|
|
|
%B = mul i8 %A, %y
|
|
|
|
%C = sub i8 %x, %B
|
|
|
|
ret i8 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @urem2(i8 %x, i8 %y) {
|
|
|
|
; CHECK-LABEL: @urem2(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = sub i8 0, [[TMP1]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i8 [[C]]
|
|
|
|
;
|
|
|
|
%A = udiv i8 %x, %y
|
|
|
|
%B = mul i8 %A, %y
|
|
|
|
%C = sub i8 %B, %x
|
|
|
|
ret i8 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @urem3(i8 %x) {
|
|
|
|
; CHECK-LABEL: @urem3(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X:%.*]], 3
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = sub i8 [[X]], [[TMP1]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = add i8 [[B1]], [[X]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i8 [[C]]
|
|
|
|
;
|
|
|
|
%A = udiv i8 %x, 3
|
|
|
|
%B = mul i8 %A, -3
|
|
|
|
%C = sub i8 %x, %B
|
|
|
|
ret i8 %C
|
|
|
|
}
|
|
|
|
|
|
|
|
; (((X / Y) * Y) / Y) -> X / Y
|
|
|
|
|
|
|
|
define i32 @sdiv_mul_sdiv(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @sdiv_mul_sdiv(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%div = sdiv i32 %x, %y
|
|
|
|
%mul = mul i32 %div, %y
|
|
|
|
%r = sdiv i32 %mul, %y
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
|
|
|
; (((X / Y) * Y) / Y) -> X / Y
|
|
|
|
|
|
|
|
define i32 @udiv_mul_udiv(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @udiv_mul_udiv(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[R:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
|
2017-03-15 00:27:46 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%div = udiv i32 %x, %y
|
|
|
|
%mul = mul i32 %div, %y
|
|
|
|
%r = udiv i32 %mul, %y
|
|
|
|
ret i32 %r
|
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test1(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test1(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%B = srem i32 %A, 1 ; ISA constant 0
|
|
|
|
ret i32 %B
|
2002-05-06 13:43:36 +08:00
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test3(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test3(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i32 [[A:%.*]], 7
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[B]]
|
|
|
|
;
|
|
|
|
%B = urem i32 %A, 8
|
|
|
|
ret i32 %B
|
2003-02-19 03:28:47 +08:00
|
|
|
}
|
2004-07-06 15:38:00 +08:00
|
|
|
|
2016-05-21 04:55:17 +08:00
|
|
|
define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) {
|
|
|
|
; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7>
|
2016-05-21 04:55:17 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i32> [[B]]
|
|
|
|
;
|
|
|
|
%B = urem <2 x i32> %A, <i32 8, i32 8>
|
|
|
|
ret <2 x i32> %B
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) {
|
|
|
|
; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[B:%.*]] = and <2 x i19> [[A:%.*]], <i19 7, i19 7>
|
2016-05-21 04:55:17 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i19> [[B]]
|
|
|
|
;
|
|
|
|
%B = urem <2 x i19> %A, <i19 8, i19 8>
|
|
|
|
ret <2 x i19> %B
|
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i1 @test3a(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test3a(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and i32 [[A:%.*]], 7
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B1]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = srem i32 %A, -8
|
|
|
|
%C = icmp ne i32 %B, 0
|
|
|
|
ret i1 %C
|
2004-07-06 15:38:00 +08:00
|
|
|
}
|
2004-12-13 05:40:22 +08:00
|
|
|
|
2016-07-23 04:11:08 +08:00
|
|
|
define <2 x i1> @test3a_vec(<2 x i32> %A) {
|
|
|
|
; CHECK-LABEL: @test3a_vec(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[B1:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7>
|
2016-08-04 03:48:40 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[B1]], zeroinitializer
|
2016-07-23 04:11:08 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%B = srem <2 x i32> %A, <i32 -8, i32 -8>
|
|
|
|
%C = icmp ne <2 x i32> %B, zeroinitializer
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test4(i32 %X, i1 %C) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test4(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i32 0, i32 7
|
|
|
|
; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], [[X:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
|
|
;
|
|
|
|
%V = select i1 %C, i32 1, i32 8
|
|
|
|
%R = urem i32 %X, %V
|
|
|
|
ret i32 %R
|
2004-12-13 05:40:22 +08:00
|
|
|
}
|
2006-02-05 15:52:47 +08:00
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test5(i32 %X, i8 %B) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test5(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[SHIFT_UPGRD_1:%.*]] = zext i8 [[B:%.*]] to i32
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[AMT:%.*]] = shl nuw i32 32, [[SHIFT_UPGRD_1]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[AMT]], -1
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = and i32 [[TMP1]], [[X:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[V]]
|
|
|
|
;
|
|
|
|
%shift.upgrd.1 = zext i8 %B to i32
|
|
|
|
%Amt = shl i32 32, %shift.upgrd.1
|
|
|
|
%V = urem i32 %X, %Amt
|
|
|
|
ret i32 %V
|
2006-02-05 15:52:47 +08:00
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test6(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test6(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 undef
|
|
|
|
;
|
|
|
|
%B = srem i32 %A, 0 ;; undef
|
|
|
|
ret i32 %B
|
2006-02-28 13:30:48 +08:00
|
|
|
}
|
2006-02-28 13:48:56 +08:00
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test7(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test7(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%B = mul i32 %A, 8
|
|
|
|
%C = srem i32 %B, 4
|
|
|
|
ret i32 %C
|
2006-02-28 13:48:56 +08:00
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test8(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test8(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%B = shl i32 %A, 4
|
|
|
|
%C = srem i32 %B, 8
|
|
|
|
ret i32 %C
|
2006-02-28 13:48:56 +08:00
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test9(i32 %A) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test9(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%B = mul i32 %A, 64
|
|
|
|
%C = urem i32 %B, 32
|
|
|
|
ret i32 %C
|
2006-02-28 13:48:56 +08:00
|
|
|
}
|
2006-03-02 14:50:04 +08:00
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test10(i8 %c) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test10(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%tmp.1 = zext i8 %c to i32
|
|
|
|
%tmp.2 = mul i32 %tmp.1, 4
|
|
|
|
%tmp.3 = sext i32 %tmp.2 to i64
|
|
|
|
%tmp.5 = urem i64 %tmp.3, 4
|
|
|
|
%tmp.6 = trunc i64 %tmp.5 to i32
|
|
|
|
ret i32 %tmp.6
|
2006-03-02 14:50:04 +08:00
|
|
|
}
|
|
|
|
|
2008-03-01 17:15:35 +08:00
|
|
|
define i32 @test11(i32 %i) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test11(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%tmp.1 = and i32 %i, -2
|
|
|
|
%tmp.3 = mul i32 %tmp.1, 2
|
|
|
|
%tmp.5 = urem i32 %tmp.3, 4
|
|
|
|
ret i32 %tmp.5
|
2008-03-06 14:48:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test12(i32 %i) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test12(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%tmp.1 = and i32 %i, -4
|
|
|
|
%tmp.5 = srem i32 %tmp.1, 2
|
|
|
|
ret i32 %tmp.5
|
2006-03-02 14:50:04 +08:00
|
|
|
}
|
2010-11-18 03:11:46 +08:00
|
|
|
|
|
|
|
define i32 @test13(i32 %i) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test13(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
|
|
|
%x = srem i32 %i, %i
|
|
|
|
ret i32 %x
|
2010-11-18 03:11:46 +08:00
|
|
|
}
|
2013-05-11 17:01:28 +08:00
|
|
|
|
|
|
|
define i64 @test14(i64 %x, i32 %y) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test14(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[Y:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL]] to i64
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[ZEXT]], -1
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[UREM:%.*]] = and i64 [[TMP1]], [[X:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i64 [[UREM]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %y
|
|
|
|
%zext = zext i32 %shl to i64
|
|
|
|
%urem = urem i64 %x, %zext
|
|
|
|
ret i64 %urem
|
2013-05-11 17:01:28 +08:00
|
|
|
}
|
2013-05-12 08:07:05 +08:00
|
|
|
|
|
|
|
define i64 @test15(i32 %x, i32 %y) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test15(
|
[InstCombine] PR37603: low bit mask canonicalization
Summary:
This is [[ https://bugs.llvm.org/show_bug.cgi?id=37603 | PR37603 ]].
https://godbolt.org/g/VCMNpS
https://rise4fun.com/Alive/idM
When doing bit manipulations, it is quite common to calculate some bit mask,
and apply it to some value via `and`.
The typical C code looks like:
```
int mask_signed_add(int nbits) {
return (1 << nbits) - 1;
}
```
which is translated into (with `-O3`)
```
define dso_local i32 @mask_signed_add(int)(i32) local_unnamed_addr #0 {
%2 = shl i32 1, %0
%3 = add nsw i32 %2, -1
ret i32 %3
}
```
But there is a second, less readable variant:
```
int mask_signed_xor(int nbits) {
return ~(-(1 << nbits));
}
```
which is translated into (with `-O3`)
```
define dso_local i32 @mask_signed_xor(int)(i32) local_unnamed_addr #0 {
%2 = shl i32 -1, %0
%3 = xor i32 %2, -1
ret i32 %3
}
```
Since we created such a mask, it is quite likely that we will use it in `and` next.
And then we may get rid of `not` op by folding into `andn`.
But now that i have actually looked:
https://godbolt.org/g/VTUDmU
_some_ backend changes will be needed too.
We clearly loose `bzhi` recognition.
Reviewers: spatel, craig.topper, RKSimon
Reviewed By: spatel
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D47428
llvm-svn: 334127
2018-06-07 03:38:27 +08:00
|
|
|
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[UREM:%.*]] = zext i32 [[TMP2]] to i64
|
|
|
|
; CHECK-NEXT: ret i64 [[UREM]]
|
|
|
|
;
|
|
|
|
%shl = shl i32 1, %y
|
|
|
|
%zext0 = zext i32 %shl to i64
|
|
|
|
%zext1 = zext i32 %x to i64
|
|
|
|
%urem = urem i64 %zext1, %zext0
|
|
|
|
ret i64 %urem
|
2013-05-12 08:07:05 +08:00
|
|
|
}
|
2013-05-19 03:30:37 +08:00
|
|
|
|
|
|
|
define i32 @test16(i32 %x, i32 %y) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test16(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[Y:%.*]], 11
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], 3
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[REM:%.*]] = and i32 [[TMP1]], [[X:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[REM]]
|
|
|
|
;
|
|
|
|
%shr = lshr i32 %y, 11
|
|
|
|
%and = and i32 %shr, 4
|
|
|
|
%add = add i32 %and, 4
|
|
|
|
%rem = urem i32 %x, %add
|
|
|
|
ret i32 %rem
|
2013-05-19 03:30:37 +08:00
|
|
|
}
|
2013-07-13 09:16:47 +08:00
|
|
|
|
|
|
|
define i32 @test17(i32 %X) {
|
2013-07-14 09:42:54 +08:00
|
|
|
; CHECK-LABEL: @test17(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 1
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i32
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP2]]
|
|
|
|
;
|
2013-07-13 09:16:47 +08:00
|
|
|
%A = urem i32 1, %X
|
|
|
|
ret i32 %A
|
|
|
|
}
|
2013-07-31 05:01:36 +08:00
|
|
|
|
|
|
|
define i32 @test18(i16 %x, i32 %y) {
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-LABEL: @test18(
|
[InstCombine] refine select-of-constants to bitwise ops
Add logic for the special case when a cmp+select can clearly be
reduced to just a bitwise logic instruction, and remove an
over-reaching chunk of general purpose bit magic. The primary goal
is to remove cases where we are not improving the IR instruction
count when doing these select transforms, and in all cases here that
is true.
In the motivating 3-way compare tests, there are further improvements
because we can combine/propagate select values (not sure if that
belongs in instcombine, but it's there for now).
DAGCombiner has folds to turn some of these selects into bit magic,
so there should be no difference in the end result in those cases.
Not all constant combinations are handled there yet, however, so it
is possible that some targets will see more cmov/csel codegen with
this change in IR canonicalization.
Ideally, we'll go further to *not* turn selects into multiple
logic/math ops in instcombine, and we'll canonicalize to selects.
But we should make sure that this step does not result in regressions
first (and if it does, we should fix those in the backend).
The general direction for this change was discussed here:
http://lists.llvm.org/pipermail/llvm-dev/2016-September/105373.html
http://lists.llvm.org/pipermail/llvm-dev/2017-July/114885.html
Alive proofs for the new bit magic:
https://rise4fun.com/Alive/XG7
Differential Revision: https://reviews.llvm.org/D46086
llvm-svn: 331486
2018-05-04 05:58:44 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], 4
|
|
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i16 [[TMP1]], 0
|
|
|
|
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 63, i32 31
|
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: ret i32 [[TMP4]]
|
2017-03-15 00:16:40 +08:00
|
|
|
;
|
|
|
|
%1 = and i16 %x, 4
|
|
|
|
%2 = icmp ne i16 %1, 0
|
|
|
|
%3 = select i1 %2, i32 32, i32 64
|
|
|
|
%4 = urem i32 %y, %3
|
|
|
|
ret i32 %4
|
2013-07-31 05:01:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test19(i32 %x, i32 %y) {
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-LABEL: @test19(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]]
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[E]]
|
|
|
|
;
|
|
|
|
%A = shl i32 1, %x
|
|
|
|
%B = shl i32 1, %y
|
|
|
|
%C = and i32 %A, %B
|
|
|
|
%D = add i32 %C, %A
|
|
|
|
%E = urem i32 %y, %D
|
|
|
|
ret i32 %E
|
2013-07-31 05:01:36 +08:00
|
|
|
}
|
2014-01-19 23:24:22 +08:00
|
|
|
|
2018-04-27 02:44:37 +08:00
|
|
|
define i32 @test19_commutative0(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test19_commutative0(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]]
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = add i32 [[C]], [[A]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1
|
|
|
|
; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]]
|
|
|
|
; CHECK-NEXT: ret i32 [[E]]
|
|
|
|
;
|
|
|
|
%A = shl i32 1, %x
|
|
|
|
%B = shl i32 1, %y
|
|
|
|
%C = and i32 %B, %A ; swapped
|
|
|
|
%D = add i32 %C, %A
|
|
|
|
%E = urem i32 %y, %D
|
|
|
|
ret i32 %E
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test19_commutative1(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test19_commutative1(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i32 [[A]], [[B]]
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1
|
|
|
|
; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]]
|
|
|
|
; CHECK-NEXT: ret i32 [[E]]
|
|
|
|
;
|
|
|
|
%A = shl i32 1, %x
|
|
|
|
%B = shl i32 1, %y
|
|
|
|
%C = and i32 %A, %B
|
|
|
|
%D = add i32 %A, %C ; swapped
|
|
|
|
%E = urem i32 %y, %D
|
|
|
|
ret i32 %E
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test19_commutative2(i32 %x, i32 %y) {
|
|
|
|
; CHECK-LABEL: @test19_commutative2(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = shl i32 1, [[X:%.*]]
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl i32 1, [[Y:%.*]]
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i32 [[B]], [[A]]
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = add i32 [[A]], [[C]]
|
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[D]], -1
|
|
|
|
; CHECK-NEXT: [[E:%.*]] = and i32 [[TMP1]], [[Y]]
|
|
|
|
; CHECK-NEXT: ret i32 [[E]]
|
|
|
|
;
|
|
|
|
%A = shl i32 1, %x
|
|
|
|
%B = shl i32 1, %y
|
|
|
|
%C = and i32 %B, %A ; swapped
|
|
|
|
%D = add i32 %A, %C ; swapped
|
|
|
|
%E = urem i32 %y, %D
|
|
|
|
ret i32 %E
|
|
|
|
}
|
|
|
|
|
2014-01-19 23:24:22 +08:00
|
|
|
define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) {
|
|
|
|
; CHECK-LABEL: @test20(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i64> [[R]]
|
|
|
|
;
|
|
|
|
%V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9>
|
|
|
|
%R = urem <2 x i64> %V, <i64 2, i64 3>
|
|
|
|
ret <2 x i64> %R
|
2014-01-19 23:24:22 +08:00
|
|
|
}
|
2016-06-06 05:17:00 +08:00
|
|
|
|
2017-03-15 00:16:40 +08:00
|
|
|
define i32 @test21(i1 %c0, i32* %p) {
|
2016-06-06 05:17:00 +08:00
|
|
|
; CHECK-LABEL: @test21(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: entry:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.then:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[PHITMP:%.*]] = srem i32 [[V]], 5
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br label [[IF_END]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.end:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[PHITMP]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: ret i32 [[LHS]]
|
|
|
|
;
|
2016-06-06 05:17:00 +08:00
|
|
|
entry:
|
|
|
|
br i1 %c0, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
2017-03-15 00:16:40 +08:00
|
|
|
%v = load volatile i32, i32* %p
|
2016-06-06 05:17:00 +08:00
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
|
|
|
|
%rem = srem i32 %lhs, 5
|
|
|
|
ret i32 %rem
|
|
|
|
}
|
2016-06-06 05:17:04 +08:00
|
|
|
|
|
|
|
@a = common global [5 x i16] zeroinitializer, align 2
|
|
|
|
@b = common global i16 0, align 2
|
|
|
|
|
2017-03-15 00:16:40 +08:00
|
|
|
define i32 @pr27968_0(i1 %c0, i32* %p) {
|
2016-06-06 05:17:04 +08:00
|
|
|
; CHECK-LABEL: @pr27968_0(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: entry:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.then:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
|
|
|
|
; CHECK-NEXT: br label [[IF_END]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.end:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.safe:
|
2018-06-26 02:51:21 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.unsafe:
|
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
2016-06-06 05:17:04 +08:00
|
|
|
entry:
|
|
|
|
br i1 %c0, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
2017-03-15 00:16:40 +08:00
|
|
|
%v = load volatile i32, i32* %p
|
2016-06-06 05:17:04 +08:00
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
|
|
|
|
br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe
|
|
|
|
|
|
|
|
rem.is.safe:
|
|
|
|
%rem = srem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32)
|
|
|
|
ret i32 %rem
|
|
|
|
|
|
|
|
rem.is.unsafe:
|
|
|
|
ret i32 0
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:16:40 +08:00
|
|
|
define i32 @pr27968_1(i1 %c0, i1 %always_false, i32* %p) {
|
2016-06-06 05:17:04 +08:00
|
|
|
; CHECK-LABEL: @pr27968_1(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: entry:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.then:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
|
|
|
|
; CHECK-NEXT: br label [[IF_END]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.end:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[V]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ]
|
|
|
|
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.safe:
|
|
|
|
; CHECK-NEXT: [[REM:%.*]] = srem i32 [[LHS]], -2147483648
|
|
|
|
; CHECK-NEXT: ret i32 [[REM]]
|
|
|
|
; CHECK: rem.is.unsafe:
|
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
2016-06-06 05:17:04 +08:00
|
|
|
entry:
|
|
|
|
br i1 %c0, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
2017-03-15 00:16:40 +08:00
|
|
|
%v = load volatile i32, i32* %p
|
2016-06-06 05:17:04 +08:00
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
|
|
|
|
br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe
|
|
|
|
|
|
|
|
rem.is.safe:
|
|
|
|
%rem = srem i32 %lhs, -2147483648
|
|
|
|
ret i32 %rem
|
|
|
|
|
|
|
|
rem.is.unsafe:
|
|
|
|
ret i32 0
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:16:40 +08:00
|
|
|
define i32 @pr27968_2(i1 %c0, i32* %p) {
|
2016-06-06 05:17:04 +08:00
|
|
|
; CHECK-LABEL: @pr27968_2(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: entry:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.then:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
|
|
|
|
; CHECK-NEXT: br label [[IF_END]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.end:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.safe:
|
2018-06-26 02:51:21 +08:00
|
|
|
; CHECK-NEXT: ret i32 0
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.unsafe:
|
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
2016-06-06 05:17:04 +08:00
|
|
|
entry:
|
|
|
|
br i1 %c0, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
2017-03-15 00:16:40 +08:00
|
|
|
%v = load volatile i32, i32* %p
|
2016-06-06 05:17:04 +08:00
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
|
|
|
|
br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe
|
|
|
|
|
|
|
|
rem.is.safe:
|
|
|
|
%rem = urem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32)
|
|
|
|
ret i32 %rem
|
|
|
|
|
|
|
|
rem.is.unsafe:
|
|
|
|
ret i32 0
|
|
|
|
}
|
|
|
|
|
2017-03-15 00:16:40 +08:00
|
|
|
define i32 @pr27968_3(i1 %c0, i1 %always_false, i32* %p) {
|
2016-06-06 05:17:04 +08:00
|
|
|
; CHECK-LABEL: @pr27968_3(
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: entry:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.then:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[V:%.*]] = load volatile i32, i32* [[P:%.*]], align 4
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK-NEXT: [[PHITMP:%.*]] = and i32 [[V]], 2147483647
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: br label [[IF_END]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: if.end:
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[LHS:%.*]] = phi i32 [ [[PHITMP]], [[IF_THEN]] ], [ 5, [[ENTRY:%.*]] ]
|
|
|
|
; CHECK-NEXT: br i1 [[ALWAYS_FALSE:%.*]], label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]]
|
2017-03-15 00:16:40 +08:00
|
|
|
; CHECK: rem.is.safe:
|
|
|
|
; CHECK-NEXT: ret i32 [[LHS]]
|
|
|
|
; CHECK: rem.is.unsafe:
|
|
|
|
; CHECK-NEXT: ret i32 0
|
|
|
|
;
|
2016-06-06 05:17:04 +08:00
|
|
|
entry:
|
|
|
|
br i1 %c0, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then:
|
2017-03-15 00:16:40 +08:00
|
|
|
%v = load volatile i32, i32* %p
|
2016-06-06 05:17:04 +08:00
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end:
|
|
|
|
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
|
|
|
|
br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe
|
|
|
|
|
|
|
|
rem.is.safe:
|
|
|
|
%rem = urem i32 %lhs, -2147483648
|
|
|
|
ret i32 %rem
|
|
|
|
|
|
|
|
rem.is.unsafe:
|
|
|
|
ret i32 0
|
|
|
|
}
|
2017-03-15 00:27:46 +08:00
|
|
|
|
2017-04-17 09:51:21 +08:00
|
|
|
define i32 @test22(i32 %A) {
|
|
|
|
; CHECK-LABEL: @test22(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 2147483647
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = urem i32 [[AND]], 2147483647
|
|
|
|
; CHECK-NEXT: ret i32 [[MUL]]
|
|
|
|
;
|
|
|
|
%and = and i32 %A, 2147483647
|
|
|
|
%mul = srem i32 %and, 2147483647
|
|
|
|
ret i32 %mul
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i32> @test23(<2 x i32> %A) {
|
|
|
|
; CHECK-LABEL: @test23(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[A:%.*]], <i32 2147483647, i32 2147483647>
|
2017-04-17 09:51:24 +08:00
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = urem <2 x i32> [[AND]], <i32 2147483647, i32 2147483647>
|
2017-04-17 09:51:21 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i32> [[MUL]]
|
|
|
|
;
|
|
|
|
%and = and <2 x i32> %A, <i32 2147483647, i32 2147483647>
|
|
|
|
%mul = srem <2 x i32> %and, <i32 2147483647, i32 2147483647>
|
|
|
|
ret <2 x i32> %mul
|
|
|
|
}
|
2017-12-27 06:06:57 +08:00
|
|
|
|
2017-12-27 06:12:20 +08:00
|
|
|
; FP division-by-zero is not UB.
|
2017-12-27 06:06:57 +08:00
|
|
|
|
|
|
|
define double @PR34870(i1 %cond, double %x, double %y) {
|
|
|
|
; CHECK-LABEL: @PR34870(
|
2018-04-27 02:44:32 +08:00
|
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double 0.000000e+00
|
|
|
|
; CHECK-NEXT: [[FMOD:%.*]] = frem double [[X:%.*]], [[SEL]]
|
2017-12-27 06:06:57 +08:00
|
|
|
; CHECK-NEXT: ret double [[FMOD]]
|
|
|
|
;
|
|
|
|
%sel = select i1 %cond, double %y, double 0.0
|
|
|
|
%fmod = frem double %x, %sel
|
|
|
|
ret double %fmod
|
|
|
|
}
|
|
|
|
|