1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-24 05:23:45 +02:00
llvm-mirror/test/Transforms/InstCombine/rem.ll
Sanjoy Das 7a0f514448 Add safety check to InstCombiner::commonIRemTransforms
Since FoldOpIntoPhi speculates the binary operation to potentially each
of the predecessors of the PHI node (pulling it out of arbitrary control
dependence in the process), we can FoldOpIntoPhi only if we know the
operation doesn't have UB.

This also brings up an interesting profitability question -- the way it
is written today, commonIRemTransforms will hoist out work from
dynamically dead code into code that will execute at runtime.  Perhaps
that isn't the best canonicalization?

Fixes PR27968.

llvm-svn: 271857
2016-06-05 21:17:04 +00:00

373 lines
9.1 KiB
LLVM

; This test makes sure that rem instructions are properly eliminated.
;
; RUN: opt < %s -instcombine -S | FileCheck %s
; END.
define i32 @test1(i32 %A) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret i32 0
%B = srem i32 %A, 1 ; ISA constant 0
ret i32 %B
}
define i32 @test2(i32 %A) { ; 0 % X = 0, we don't need to preserve traps
; CHECK-LABEL: @test2(
; CHECK-NEXT: ret i32 0
%B = srem i32 0, %A
ret i32 %B
}
define i32 @test3(i32 %A) {
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[AND:%.*]] = and i32 %A, 7
; CHECK-NEXT: ret i32 [[AND]]
%B = urem i32 %A, 8
ret i32 %B
}
define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) {
; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor(
; CHECK-NEXT: [[B:%.*]] = and <2 x i32> %A, <i32 7, i32 7>
; 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(
; CHECK-NEXT: [[B:%.*]] = and <2 x i19> %A, <i19 7, i19 7>
; CHECK-NEXT: ret <2 x i19> [[B]]
;
%B = urem <2 x i19> %A, <i19 8, i19 8>
ret <2 x i19> %B
}
define i1 @test3a(i32 %A) {
; CHECK-LABEL: @test3a(
; CHECK-NEXT: [[AND:%.*]] = and i32 %A, 7
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
; CHECK-NEXT: ret i1 [[CMP]]
%B = srem i32 %A, -8
%C = icmp ne i32 %B, 0
ret i1 %C
}
define i32 @test4(i32 %X, i1 %C) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: [[SEL:%.*]] = select i1 %C, i32 0, i32 7
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SEL]], %X
%V = select i1 %C, i32 1, i32 8
%R = urem i32 %X, %V
ret i32 %R
}
define i32 @test5(i32 %X, i8 %B) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 %B to i32
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 32, [[ZEXT]]
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], -1
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], %X
; CHECK-NEXT: ret i32 [[AND]]
%shift.upgrd.1 = zext i8 %B to i32
%Amt = shl i32 32, %shift.upgrd.1
%V = urem i32 %X, %Amt
ret i32 %V
}
define i32 @test6(i32 %A) {
; CHECK-LABEL: @test6(
; CHECK-NEXT: ret i32 undef
%B = srem i32 %A, 0 ;; undef
ret i32 %B
}
define i32 @test7(i32 %A) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: ret i32 0
%B = mul i32 %A, 8
%C = srem i32 %B, 4
ret i32 %C
}
define i32 @test8(i32 %A) {
; CHECK-LABEL: @test8(
; CHECK-NEXT: ret i32 0
%B = shl i32 %A, 4
%C = srem i32 %B, 8
ret i32 %C
}
define i32 @test9(i32 %A) {
; CHECK-LABEL: @test9(
; CHECK-NEXT: ret i32 0
%B = mul i32 %A, 64
%C = urem i32 %B, 32
ret i32 %C
}
define i32 @test10(i8 %c) {
; CHECK-LABEL: @test10(
; 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
}
define i32 @test11(i32 %i) {
; CHECK-LABEL: @test11(
; 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
}
define i32 @test12(i32 %i) {
; CHECK-LABEL: @test12(
; CHECK-NEXT: ret i32 0
%tmp.1 = and i32 %i, -4
%tmp.5 = srem i32 %tmp.1, 2
ret i32 %tmp.5
}
define i32 @test13(i32 %i) {
; CHECK-LABEL: @test13(
; CHECK-NEXT: ret i32 0
%x = srem i32 %i, %i
ret i32 %x
}
define i64 @test14(i64 %x, i32 %y) {
; CHECK-LABEL: @test14(
; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, %y
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL]] to i64
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[ZEXT]], -1
; CHECK-NEXT: [[AND:%.*]] = and i64 [[ADD]], %x
; CHECK-NEXT: ret i64 [[AND]]
%shl = shl i32 1, %y
%zext = zext i32 %shl to i64
%urem = urem i64 %x, %zext
ret i64 %urem
}
define i64 @test15(i32 %x, i32 %y) {
; CHECK-LABEL: @test15(
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, %y
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], -1
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], %x
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[AND]] to i64
; CHECK-NEXT: ret i64 [[ZEXT]]
%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
}
define i32 @test16(i32 %x, i32 %y) {
; CHECK-LABEL: @test16(
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %y, 11
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4
; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], 3
; CHECK-NEXT: [[REM:%.*]] = and i32 [[OR]], %x
; 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
}
define i32 @test17(i32 %X) {
; CHECK-LABEL: @test17(
; CHECK-NEXT: icmp ne i32 %X, 1
; CHECK-NEXT: zext i1
; CHECK-NEXT: ret
%A = urem i32 1, %X
ret i32 %A
}
define i32 @test18(i16 %x, i32 %y) {
; CHECK: @test18
; CHECK-NEXT: [[AND:%.*]] = and i16 %x, 4
; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[AND]] to i32
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[EXT]], 3
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], 63
; CHECK-NEXT: [[REM:%.*]] = and i32 [[XOR]], %y
; CHECK-NEXT: ret i32 [[REM]]
%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
}
define i32 @test19(i32 %x, i32 %y) {
; CHECK: @test19
; CHECK-NEXT: [[SHL1:%.*]] = shl i32 1, %x
; CHECK-NEXT: [[SHL2:%.*]] = shl i32 1, %y
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL1]], [[SHL2]]
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[AND]], [[SHL1]]
; CHECK-NEXT: [[SUB:%.*]] = add i32 [[ADD]], -1
; CHECK-NEXT: [[REM:%.*]] = and i32 [[SUB]], %y
; CHECK-NEXT: ret i32 [[REM]]
%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
}
define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) {
; CHECK-LABEL: @test20(
; CHECK-NEXT: select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer
; CHECK-NEXT: ret <2 x i64>
%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
}
define i32 @test21(i1 %c0, i32* %val) {
; CHECK-LABEL: @test21(
entry:
br i1 %c0, label %if.then, label %if.end
if.then:
; CHECK: if.then:
; CHECK-NEXT: %v = load volatile i32, i32* %val, align 4
; CHECK-NEXT: %phitmp = srem i32 %v, 5
%v = load volatile i32, i32* %val
br label %if.end
if.end:
; CHECK: if.end:
; CHECK-NEXT: %lhs = phi i32 [ %phitmp, %if.then ], [ 0, %entry ]
; CHECK-NEXT: ret i32 %lhs
%lhs = phi i32 [ %v, %if.then ], [ 5, %entry ]
%rem = srem i32 %lhs, 5
ret i32 %rem
}
@a = common global [5 x i16] zeroinitializer, align 2
@b = common global i16 0, align 2
define i32 @pr27968_0(i1 %c0, i32* %val) {
; CHECK-LABEL: @pr27968_0(
entry:
br i1 %c0, label %if.then, label %if.end
if.then:
%v = load volatile i32, i32* %val
br label %if.end
; CHECK: if.then:
; CHECK-NOT: srem
; CHECK: 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:
; CHECK: rem.is.safe:
; CHECK-NEXT: %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)
; CHECK-NEXT: ret i32 %rem
%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
}
define i32 @pr27968_1(i1 %c0, i1 %always_false, i32* %val) {
; CHECK-LABEL: @pr27968_1(
entry:
br i1 %c0, label %if.then, label %if.end
if.then:
%v = load volatile i32, i32* %val
br label %if.end
; CHECK: if.then:
; CHECK-NOT: srem
; CHECK: 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
; CHECK: rem.is.safe:
; CHECK-NEXT: %rem = srem i32 %lhs, -2147483648
; CHECK-NEXT: ret i32 %rem
rem.is.unsafe:
ret i32 0
}
define i32 @pr27968_2(i1 %c0, i32* %val) {
; CHECK-LABEL: @pr27968_2(
entry:
br i1 %c0, label %if.then, label %if.end
if.then:
%v = load volatile i32, i32* %val
br label %if.end
; CHECK: if.then:
; CHECK-NOT: urem
; CHECK: 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:
; CHECK: rem.is.safe:
; CHECK-NEXT: %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)
; CHECK-NEXT: ret i32 %rem
%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
}
define i32 @pr27968_3(i1 %c0, i1 %always_false, i32* %val) {
; CHECK-LABEL: @pr27968_3(
entry:
br i1 %c0, label %if.then, label %if.end
if.then:
%v = load volatile i32, i32* %val
br label %if.end
; CHECK: if.then:
; CHECK-NEXT: %v = load volatile i32, i32* %val, align 4
; CHECK-NEXT: %phitmp = and i32 %v, 2147483647
; CHECK-NEXT: 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
}