llvm-6502/test/Transforms/InstCombine/or.ll
David Majnemer 024d943bca Reorders two transforms that collide with each other
One performs: (X == 13 | X == 14) -> X-13 <u 2
The other: (A == C1 || A == C2) -> (A & ~(C1 ^ C2)) == C1

The problem is that there are certain values of C1 and C2 that
trigger both transforms but the first one blocks out the second,
this generates suboptimal code.

Reordering the transforms should be better in every case and
allows us to do interesting stuff like turn:
  %shr = lshr i32 %X, 4
  %and = and i32 %shr, 15
  %add = add i32 %and, -14
  %tobool = icmp ne i32 %add, 0

into:
  %and = and i32 %X, 240
  %tobool = icmp ne i32 %and, 224


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179493 91177308-0d34-0410-b5e6-96231b3b80d8
2013-04-14 21:15:43 +00:00

411 lines
8.8 KiB
LLVM

; This test makes sure that these instructions are properly eliminated.
; RUN: opt < %s -instcombine -S | FileCheck %s
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
define i32 @test1(i32 %A) {
%B = or i32 %A, 0
ret i32 %B
; CHECK: @test1
; CHECK: ret i32 %A
}
define i32 @test2(i32 %A) {
%B = or i32 %A, -1
ret i32 %B
; CHECK: @test2
; CHECK: ret i32 -1
}
define i8 @test2a(i8 %A) {
%B = or i8 %A, -1
ret i8 %B
; CHECK: @test2a
; CHECK: ret i8 -1
}
define i1 @test3(i1 %A) {
%B = or i1 %A, false
ret i1 %B
; CHECK: @test3
; CHECK: ret i1 %A
}
define i1 @test4(i1 %A) {
%B = or i1 %A, true
ret i1 %B
; CHECK: @test4
; CHECK: ret i1 true
}
define i1 @test5(i1 %A) {
%B = or i1 %A, %A
ret i1 %B
; CHECK: @test5
; CHECK: ret i1 %A
}
define i32 @test6(i32 %A) {
%B = or i32 %A, %A
ret i32 %B
; CHECK: @test6
; CHECK: ret i32 %A
}
; A | ~A == -1
define i32 @test7(i32 %A) {
%NotA = xor i32 -1, %A
%B = or i32 %A, %NotA
ret i32 %B
; CHECK: @test7
; CHECK: ret i32 -1
}
define i8 @test8(i8 %A) {
%B = or i8 %A, -2
%C = or i8 %B, 1
ret i8 %C
; CHECK: @test8
; CHECK: ret i8 -1
}
; Test that (A|c1)|(B|c2) == (A|B)|(c1|c2)
define i8 @test9(i8 %A, i8 %B) {
%C = or i8 %A, 1
%D = or i8 %B, -2
%E = or i8 %C, %D
ret i8 %E
; CHECK: @test9
; CHECK: ret i8 -1
}
define i8 @test10(i8 %A) {
%B = or i8 %A, 1
%C = and i8 %B, -2
; (X & C1) | C2 --> (X | C2) & (C1|C2)
%D = or i8 %C, -2
ret i8 %D
; CHECK: @test10
; CHECK: ret i8 -2
}
define i8 @test11(i8 %A) {
%B = or i8 %A, -2
%C = xor i8 %B, 13
; (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
%D = or i8 %C, 1
%E = xor i8 %D, 12
ret i8 %E
; CHECK: @test11
; CHECK: ret i8 -1
}
define i32 @test12(i32 %A) {
; Should be eliminated
%B = or i32 %A, 4
%C = and i32 %B, 8
ret i32 %C
; CHECK: @test12
; CHECK: %C = and i32 %A, 8
; CHECK: ret i32 %C
}
define i32 @test13(i32 %A) {
%B = or i32 %A, 12
; Always equal to 8
%C = and i32 %B, 8
ret i32 %C
; CHECK: @test13
; CHECK: ret i32 8
}
define i1 @test14(i32 %A, i32 %B) {
%C1 = icmp ult i32 %A, %B
%C2 = icmp ugt i32 %A, %B
; (A < B) | (A > B) === A != B
%D = or i1 %C1, %C2
ret i1 %D
; CHECK: @test14
; CHECK: icmp ne i32 %A, %B
; CHECK: ret i1
}
define i1 @test15(i32 %A, i32 %B) {
%C1 = icmp ult i32 %A, %B
%C2 = icmp eq i32 %A, %B
; (A < B) | (A == B) === A <= B
%D = or i1 %C1, %C2
ret i1 %D
; CHECK: @test15
; CHECK: icmp ule i32 %A, %B
; CHECK: ret i1
}
define i32 @test16(i32 %A) {
%B = and i32 %A, 1
; -2 = ~1
%C = and i32 %A, -2
; %D = and int %B, -1 == %B
%D = or i32 %B, %C
ret i32 %D
; CHECK: @test16
; CHECK: ret i32 %A
}
define i32 @test17(i32 %A) {
%B = and i32 %A, 1
%C = and i32 %A, 4
; %D = and int %B, 5
%D = or i32 %B, %C
ret i32 %D
; CHECK: @test17
; CHECK: %D = and i32 %A, 5
; CHECK: ret i32 %D
}
define i1 @test18(i32 %A) {
%B = icmp sge i32 %A, 100
%C = icmp slt i32 %A, 50
;; (A-50) >u 50
%D = or i1 %B, %C
ret i1 %D
; CHECK: @test18
; CHECK: add i32
; CHECK: icmp ugt
; CHECK: ret i1
}
define i1 @test19(i32 %A) {
%B = icmp eq i32 %A, 50
%C = icmp eq i32 %A, 51
;; (A&-2) == 50
%D = or i1 %B, %C
ret i1 %D
; CHECK: @test19
; CHECK: and i32
; CHECK: icmp eq
; CHECK: ret i1
}
define i32 @test20(i32 %x) {
%y = and i32 %x, 123
%z = or i32 %y, %x
ret i32 %z
; CHECK: @test20
; CHECK: ret i32 %x
}
define i32 @test21(i32 %tmp.1) {
%tmp.1.mask1 = add i32 %tmp.1, 2
%tmp.3 = and i32 %tmp.1.mask1, -2
%tmp.5 = and i32 %tmp.1, 1
;; add tmp.1, 2
%tmp.6 = or i32 %tmp.5, %tmp.3
ret i32 %tmp.6
; CHECK: @test21
; CHECK: add i32 %{{[^,]*}}, 2
; CHECK: ret i32
}
define i32 @test22(i32 %B) {
%ELIM41 = and i32 %B, 1
%ELIM7 = and i32 %B, -2
%ELIM5 = or i32 %ELIM41, %ELIM7
ret i32 %ELIM5
; CHECK: @test22
; CHECK: ret i32 %B
}
define i16 @test23(i16 %A) {
%B = lshr i16 %A, 1
;; fold or into xor
%C = or i16 %B, -32768
%D = xor i16 %C, 8193
ret i16 %D
; CHECK: @test23
; CHECK: %B = lshr i16 %A, 1
; CHECK: %D = xor i16 %B, -24575
; CHECK: ret i16 %D
}
; PR1738
define i1 @test24(double %X, double %Y) {
%tmp9 = fcmp uno double %X, 0.000000e+00 ; <i1> [#uses=1]
%tmp13 = fcmp uno double %Y, 0.000000e+00 ; <i1> [#uses=1]
%bothcond = or i1 %tmp13, %tmp9 ; <i1> [#uses=1]
ret i1 %bothcond
; CHECK: @test24
; CHECK: = fcmp uno double %Y, %X
; CHECK: ret i1
}
; PR3266 & PR5276
define i1 @test25(i32 %A, i32 %B) {
%C = icmp eq i32 %A, 0
%D = icmp eq i32 %B, 57
%E = or i1 %C, %D
%F = xor i1 %E, -1
ret i1 %F
; CHECK: @test25
; CHECK: icmp ne i32 %A, 0
; CHECK-NEXT: icmp ne i32 %B, 57
; CHECK-NEXT: %F = and i1
; CHECK-NEXT: ret i1 %F
}
; PR5634
define i1 @test26(i32 %A, i32 %B) {
%C1 = icmp eq i32 %A, 0
%C2 = icmp eq i32 %B, 0
; (A == 0) & (A == 0) --> (A|B) == 0
%D = and i1 %C1, %C2
ret i1 %D
; CHECK: @test26
; CHECK: or i32 %A, %B
; CHECK: icmp eq i32 {{.*}}, 0
; CHECK: ret i1
}
define i1 @test27(i32* %A, i32* %B) {
%C1 = ptrtoint i32* %A to i32
%C2 = ptrtoint i32* %B to i32
%D = or i32 %C1, %C2
%E = icmp eq i32 %D, 0
ret i1 %E
; CHECK: @test27
; CHECK: icmp eq i32* %A, null
; CHECK: icmp eq i32* %B, null
; CHECK: and i1
; CHECK: ret i1
}
; PR5634
define i1 @test28(i32 %A, i32 %B) {
%C1 = icmp ne i32 %A, 0
%C2 = icmp ne i32 %B, 0
; (A != 0) | (A != 0) --> (A|B) != 0
%D = or i1 %C1, %C2
ret i1 %D
; CHECK: @test28
; CHECK: or i32 %A, %B
; CHECK: icmp ne i32 {{.*}}, 0
; CHECK: ret i1
}
define i1 @test29(i32* %A, i32* %B) {
%C1 = ptrtoint i32* %A to i32
%C2 = ptrtoint i32* %B to i32
%D = or i32 %C1, %C2
%E = icmp ne i32 %D, 0
ret i1 %E
; CHECK: @test29
; CHECK: icmp ne i32* %A, null
; CHECK: icmp ne i32* %B, null
; CHECK: or i1
; CHECK: ret i1
}
; PR4216
define i32 @test30(i32 %A) {
entry:
%B = or i32 %A, 32962
%C = and i32 %A, -65536
%D = and i32 %B, 40186
%E = or i32 %D, %C
ret i32 %E
; CHECK: @test30
; CHECK: %D = and i32 %A, -58312
; CHECK: %E = or i32 %D, 32962
; CHECK: ret i32 %E
}
; PR4216
define i64 @test31(i64 %A) nounwind readnone ssp noredzone {
%B = or i64 %A, 194
%D = and i64 %B, 250
%C = or i64 %A, 32768
%E = and i64 %C, 4294941696
%F = or i64 %D, %E
ret i64 %F
; CHECK: @test31
; CHECK-NEXT: %E = and i64 %A, 4294908984
; CHECK-NEXT: %F = or i64 %E, 32962
; CHECK-NEXT: ret i64 %F
}
define <4 x i32> @test32(<4 x i1> %and.i1352, <4 x i32> %vecinit6.i176, <4 x i32> %vecinit6.i191) {
%and.i135 = sext <4 x i1> %and.i1352 to <4 x i32> ; <<4 x i32>> [#uses=2]
%and.i129 = and <4 x i32> %vecinit6.i176, %and.i135 ; <<4 x i32>> [#uses=1]
%neg.i = xor <4 x i32> %and.i135, <i32 -1, i32 -1, i32 -1, i32 -1> ; <<4 x i32>> [#uses=1]
%and.i = and <4 x i32> %vecinit6.i191, %neg.i ; <<4 x i32>> [#uses=1]
%or.i = or <4 x i32> %and.i, %and.i129 ; <<4 x i32>> [#uses=1]
ret <4 x i32> %or.i
; codegen is mature enough to handle vector selects.
; CHECK: @test32
; CHECK: select <4 x i1> %and.i1352, <4 x i32> %vecinit6.i176, <4 x i32> %vecinit6.i191
}
define i1 @test33(i1 %X, i1 %Y) {
%a = or i1 %X, %Y
%b = or i1 %a, %X
ret i1 %b
; CHECK: @test33
; CHECK-NEXT: or i1 %X, %Y
; CHECK-NEXT: ret
}
define i32 @test34(i32 %X, i32 %Y) {
%a = or i32 %X, %Y
%b = or i32 %Y, %a
ret i32 %b
; CHECK: @test34
; CHECK-NEXT: or i32 %X, %Y
; CHECK-NEXT: ret
}
define i32 @test35(i32 %a, i32 %b) {
%1 = or i32 %a, 1135
%2 = or i32 %1, %b
ret i32 %2
; CHECK: @test35
; CHECK-NEXT: or i32 %a, %b
; CHECK-NEXT: or i32 %1, 1135
}
define i1 @test36(i32 %x) {
%cmp1 = icmp eq i32 %x, 23
%cmp2 = icmp eq i32 %x, 24
%ret1 = or i1 %cmp1, %cmp2
%cmp3 = icmp eq i32 %x, 25
%ret2 = or i1 %ret1, %cmp3
ret i1 %ret2
; CHECK: @test36
; CHECK-NEXT: %x.off = add i32 %x, -23
; CHECK-NEXT: icmp ult i32 %x.off, 3
; CHECK-NEXT: ret i1
}
define i32 @test37(i32* %xp, i32 %y) {
; CHECK: @test37
; CHECK: select i1 %tobool, i32 -1, i32 %x
%tobool = icmp ne i32 %y, 0
%sext = sext i1 %tobool to i32
%x = load i32* %xp
%or = or i32 %sext, %x
ret i32 %or
}
define i32 @test38(i32* %xp, i32 %y) {
; CHECK: @test38
; CHECK: select i1 %tobool, i32 -1, i32 %x
%tobool = icmp ne i32 %y, 0
%sext = sext i1 %tobool to i32
%x = load i32* %xp
%or = or i32 %x, %sext
ret i32 %or
}