mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
48e2671cb6
Canonicalizing 'x [+-] (-Constant * y)' is not a win if we don't *know* we will open up CSE opportunities. If the multiply was 'nsw', then negating 'y' requires us to clear the 'nsw' flag. If this is actually worth pursuing, it is probably more appropriate to do so in GVN or EarlyCSE. This fixes PR23675. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238397 91177308-0d34-0410-b5e6-96231b3b80d8
220 lines
4.4 KiB
LLVM
220 lines
4.4 KiB
LLVM
; RUN: opt < %s -reassociate -gvn -instcombine -S | FileCheck %s
|
|
|
|
define i32 @test1(i32 %arg) {
|
|
%tmp1 = sub i32 -12, %arg
|
|
%tmp2 = add i32 %tmp1, 12
|
|
ret i32 %tmp2
|
|
|
|
; CHECK-LABEL: @test1
|
|
; CHECK-NEXT: sub i32 0, %arg
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test2(i32 %reg109, i32 %reg1111) {
|
|
%reg115 = add i32 %reg109, -30
|
|
%reg116 = add i32 %reg115, %reg1111
|
|
%reg117 = add i32 %reg116, 30
|
|
ret i32 %reg117
|
|
|
|
; CHECK-LABEL: @test2
|
|
; CHECK-NEXT: %reg117 = add i32 %reg1111, %reg109
|
|
; CHECK-NEXT: ret i32 %reg117
|
|
}
|
|
|
|
@e = external global i32
|
|
@a = external global i32
|
|
@b = external global i32
|
|
@c = external global i32
|
|
@f = external global i32
|
|
|
|
define void @test3() {
|
|
%A = load i32, i32* @a
|
|
%B = load i32, i32* @b
|
|
%C = load i32, i32* @c
|
|
%t1 = add i32 %A, %B
|
|
%t2 = add i32 %t1, %C
|
|
%t3 = add i32 %C, %A
|
|
%t4 = add i32 %t3, %B
|
|
; e = (a+b)+c;
|
|
store i32 %t2, i32* @e
|
|
; f = (a+c)+b
|
|
store i32 %t4, i32* @f
|
|
ret void
|
|
|
|
; CHECK-LABEL: @test3
|
|
; CHECK: add i32
|
|
; CHECK: add i32
|
|
; CHECK-NOT: add i32
|
|
; CHECK: ret void
|
|
}
|
|
|
|
define void @test4() {
|
|
%A = load i32, i32* @a
|
|
%B = load i32, i32* @b
|
|
%C = load i32, i32* @c
|
|
%t1 = add i32 %A, %B
|
|
%t2 = add i32 %t1, %C
|
|
%t3 = add i32 %C, %A
|
|
%t4 = add i32 %t3, %B
|
|
; e = c+(a+b)
|
|
store i32 %t2, i32* @e
|
|
; f = (c+a)+b
|
|
store i32 %t4, i32* @f
|
|
ret void
|
|
|
|
; CHECK-LABEL: @test4
|
|
; CHECK: add i32
|
|
; CHECK: add i32
|
|
; CHECK-NOT: add i32
|
|
; CHECK: ret void
|
|
}
|
|
|
|
define void @test5() {
|
|
%A = load i32, i32* @a
|
|
%B = load i32, i32* @b
|
|
%C = load i32, i32* @c
|
|
%t1 = add i32 %B, %A
|
|
%t2 = add i32 %t1, %C
|
|
%t3 = add i32 %C, %A
|
|
%t4 = add i32 %t3, %B
|
|
; e = c+(b+a)
|
|
store i32 %t2, i32* @e
|
|
; f = (c+a)+b
|
|
store i32 %t4, i32* @f
|
|
ret void
|
|
|
|
; CHECK-LABEL: @test5
|
|
; CHECK: add i32
|
|
; CHECK: add i32
|
|
; CHECK-NOT: add i32
|
|
; CHECK: ret void
|
|
}
|
|
|
|
define i32 @test6() {
|
|
%tmp.0 = load i32, i32* @a
|
|
%tmp.1 = load i32, i32* @b
|
|
; (a+b)
|
|
%tmp.2 = add i32 %tmp.0, %tmp.1
|
|
%tmp.4 = load i32, i32* @c
|
|
; (a+b)+c
|
|
%tmp.5 = add i32 %tmp.2, %tmp.4
|
|
; (a+c)
|
|
%tmp.8 = add i32 %tmp.0, %tmp.4
|
|
; (a+c)+b
|
|
%tmp.11 = add i32 %tmp.8, %tmp.1
|
|
; X ^ X = 0
|
|
%RV = xor i32 %tmp.5, %tmp.11
|
|
ret i32 %RV
|
|
|
|
; CHECK-LABEL: @test6
|
|
; CHECK: ret i32 0
|
|
}
|
|
|
|
; This should be one add and two multiplies.
|
|
define i32 @test7(i32 %A, i32 %B, i32 %C) {
|
|
; A*A*B + A*C*A
|
|
%aa = mul i32 %A, %A
|
|
%aab = mul i32 %aa, %B
|
|
%ac = mul i32 %A, %C
|
|
%aac = mul i32 %ac, %A
|
|
%r = add i32 %aab, %aac
|
|
ret i32 %r
|
|
|
|
; CHECK-LABEL: @test7
|
|
; CHECK-NEXT: add i32 %C, %B
|
|
; CHECK-NEXT: mul i32
|
|
; CHECK-NEXT: mul i32
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test8(i32 %X, i32 %Y, i32 %Z) {
|
|
%A = sub i32 0, %X
|
|
%B = mul i32 %A, %Y
|
|
; (-X)*Y + Z -> Z-X*Y
|
|
%C = add i32 %B, %Z
|
|
ret i32 %C
|
|
|
|
; CHECK-LABEL: @test8
|
|
; CHECK-NEXT: %A = mul i32 %Y, %X
|
|
; CHECK-NEXT: %C = sub i32 %Z, %A
|
|
; CHECK-NEXT: ret i32 %C
|
|
}
|
|
|
|
; PR5458
|
|
define i32 @test9(i32 %X) {
|
|
%Y = mul i32 %X, 47
|
|
%Z = add i32 %Y, %Y
|
|
ret i32 %Z
|
|
; CHECK-LABEL: @test9
|
|
; CHECK-NEXT: mul i32 %X, 94
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test10(i32 %X) {
|
|
%Y = add i32 %X ,%X
|
|
%Z = add i32 %Y, %X
|
|
ret i32 %Z
|
|
; CHECK-LABEL: @test10
|
|
; CHECK-NEXT: mul i32 %X, 3
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test11(i32 %W) {
|
|
%X = mul i32 %W, 127
|
|
%Y = add i32 %X ,%X
|
|
%Z = add i32 %Y, %X
|
|
ret i32 %Z
|
|
; CHECK-LABEL: @test11
|
|
; CHECK-NEXT: mul i32 %W, 381
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test12(i32 %X) {
|
|
%A = sub i32 1, %X
|
|
%B = sub i32 2, %X
|
|
%C = sub i32 3, %X
|
|
%Y = add i32 %A ,%B
|
|
%Z = add i32 %Y, %C
|
|
ret i32 %Z
|
|
; CHECK-LABEL: @test12
|
|
; CHECK-NEXT: mul i32 %X, -3
|
|
; CHECK-NEXT: add i32{{.*}}, 6
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define i32 @test13(i32 %X1, i32 %X2, i32 %X3) {
|
|
%A = sub i32 0, %X1
|
|
%B = mul i32 %A, %X2 ; -X1*X2
|
|
%C = mul i32 %X1, %X3 ; X1*X3
|
|
%D = add i32 %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2)
|
|
ret i32 %D
|
|
; CHECK-LABEL: @test13
|
|
; CHECK-NEXT: sub i32 %X3, %X2
|
|
; CHECK-NEXT: mul i32 {{.*}}, %X1
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
; PR5359
|
|
define i32 @test14(i32 %X1, i32 %X2) {
|
|
%B = mul i32 %X1, 47 ; X1*47
|
|
%C = mul i32 %X2, -47 ; X2*-47
|
|
%D = add i32 %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2)
|
|
ret i32 %D
|
|
|
|
; CHECK-LABEL: @test14
|
|
; CHECK-NEXT: %[[SUB:.*]] = sub i32 %X1, %X2
|
|
; CHECK-NEXT: mul i32 %[[SUB]], 47
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
; Do not reassociate expressions of type i1
|
|
define i32 @test15(i32 %X1, i32 %X2, i32 %X3) {
|
|
%A = icmp ne i32 %X1, 0
|
|
%B = icmp slt i32 %X2, %X3
|
|
%C = and i1 %A, %B
|
|
%D = select i1 %C, i32 %X1, i32 0
|
|
ret i32 %D
|
|
; CHECK-LABEL: @test15
|
|
; CHECK: and i1 %A, %B
|
|
}
|