mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
ee40bb98a6
D104868 removed an (incorrect) fold for distributing BFI instructions in a chain, combining them into a single instruction. BFIs like that are hard to test, as the patterns are often destroyed before they become BFIs. But it can come up in places, with chains of BFIs that can be combined. This patch adds a replacement, which reassociates BFI instructions with non-overlapping insertion masks so that low bits are inserted first. This can end up sorting the nodes so that adjacent inserts are next to one another, allowing the existing folds to combine into a single BFI. Differential Revision: https://reviews.llvm.org/D105096
442 lines
12 KiB
LLVM
442 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=arm -mattr=+v6t2 | FileCheck %s
|
|
|
|
%struct.F = type { [3 x i8], i8 }
|
|
|
|
@X = common global %struct.F zeroinitializer, align 4 ; <%struct.F*> [#uses=1]
|
|
|
|
define void @f1([1 x i32] %f.coerce0) nounwind {
|
|
; CHECK-LABEL: f1:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: movw r0, :lower16:X
|
|
; CHECK-NEXT: mov r2, #10
|
|
; CHECK-NEXT: movt r0, :upper16:X
|
|
; CHECK-NEXT: ldr r1, [r0]
|
|
; CHECK-NEXT: bfi r1, r2, #22, #4
|
|
; CHECK-NEXT: str r1, [r0]
|
|
; CHECK-NEXT: bx lr
|
|
entry:
|
|
%0 = load i32, i32* bitcast (%struct.F* @X to i32*), align 4 ; <i32> [#uses=1]
|
|
%1 = and i32 %0, -62914561 ; <i32> [#uses=1]
|
|
%2 = or i32 %1, 41943040 ; <i32> [#uses=1]
|
|
store i32 %2, i32* bitcast (%struct.F* @X to i32*), align 4
|
|
ret void
|
|
}
|
|
|
|
define i32 @f2(i32 %A, i32 %B) nounwind {
|
|
; CHECK-LABEL: f2:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: lsr r1, r1, #7
|
|
; CHECK-NEXT: bfi r0, r1, #7, #16
|
|
; CHECK-NEXT: bx lr
|
|
entry:
|
|
%and = and i32 %A, -8388481 ; <i32> [#uses=1]
|
|
%and2 = and i32 %B, 8388480 ; <i32> [#uses=1]
|
|
%or = or i32 %and2, %and ; <i32> [#uses=1]
|
|
ret i32 %or
|
|
}
|
|
|
|
define i32 @f3(i32 %A, i32 %B) nounwind {
|
|
; CHECK-LABEL: f3:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: lsr r0, r0, #7
|
|
; CHECK-NEXT: bfi r1, r0, #7, #16
|
|
; CHECK-NEXT: mov r0, r1
|
|
; CHECK-NEXT: bx lr
|
|
entry:
|
|
%and = and i32 %A, 8388480 ; <i32> [#uses=1]
|
|
%and2 = and i32 %B, -8388481 ; <i32> [#uses=1]
|
|
%or = or i32 %and2, %and ; <i32> [#uses=1]
|
|
ret i32 %or
|
|
}
|
|
|
|
; rdar://8752056
|
|
define i32 @f4(i32 %a) nounwind {
|
|
; CHECK-LABEL: f4:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: movw r1, #3137
|
|
; CHECK-NEXT: bfi r1, r0, #15, #5
|
|
; CHECK-NEXT: mov r0, r1
|
|
; CHECK-NEXT: bx lr
|
|
%1 = shl i32 %a, 15
|
|
%ins7 = and i32 %1, 1015808
|
|
%ins12 = or i32 %ins7, 3137
|
|
ret i32 %ins12
|
|
}
|
|
|
|
; rdar://8458663
|
|
define i32 @f5(i32 %a, i32 %b) nounwind {
|
|
; CHECK-LABEL: f5:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: bfi r0, r1, #20, #4
|
|
; CHECK-NEXT: bx lr
|
|
entry:
|
|
%0 = and i32 %a, -15728641
|
|
%1 = shl i32 %b, 20
|
|
%2 = and i32 %1, 15728640
|
|
%3 = or i32 %2, %0
|
|
ret i32 %3
|
|
}
|
|
|
|
; rdar://9609030
|
|
define i32 @f6(i32 %a, i32 %b) nounwind readnone {
|
|
; CHECK-LABEL: f6:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: bfi r0, r1, #8, #9
|
|
; CHECK-NEXT: bx lr
|
|
entry:
|
|
%and = and i32 %a, -130817
|
|
%and2 = shl i32 %b, 8
|
|
%shl = and i32 %and2, 130816
|
|
%or = or i32 %shl, %and
|
|
ret i32 %or
|
|
}
|
|
|
|
define i32 @f7(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f7:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: lsr r2, r0, #2
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: bfi r0, r2, #4, #1
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 16
|
|
%cmp = icmp ne i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %or, i32 %y2
|
|
ret i32 %sel
|
|
}
|
|
|
|
define i32 @f8(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f8:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: lsr r2, r0, #2
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: bfi r0, r2, #4, #1
|
|
; CHECK-NEXT: bfi r0, r2, #5, #1
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 48
|
|
%cmp = icmp ne i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %or, i32 %y2
|
|
ret i32 %sel
|
|
}
|
|
|
|
define i32 @f9(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f9:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: bic r1, r1, #255
|
|
; CHECK-NEXT: tst r0, #4
|
|
; CHECK-NEXT: orreq r1, r1, #48
|
|
; CHECK-NEXT: mov r0, r1
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 48
|
|
%cmp = icmp ne i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %y2, i32 %or
|
|
ret i32 %sel
|
|
}
|
|
|
|
define i32 @f10(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f10:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: lsr r2, r0, #1
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: bfi r0, r2, #4, #2
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 32
|
|
%cmp = icmp ne i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %or, i32 %y2
|
|
|
|
%aand = and i32 %x, 2
|
|
%aor = or i32 %sel, 16
|
|
%acmp = icmp ne i32 %aand, 0
|
|
%asel = select i1 %acmp, i32 %aor, i32 %sel
|
|
|
|
ret i32 %asel
|
|
}
|
|
|
|
define i32 @f11(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f11:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: lsr r2, r0, #1
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: bfi r0, r2, #4, #3
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 32
|
|
%cmp = icmp ne i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %or, i32 %y2
|
|
|
|
%aand = and i32 %x, 2
|
|
%aor = or i32 %sel, 16
|
|
%acmp = icmp ne i32 %aand, 0
|
|
%asel = select i1 %acmp, i32 %aor, i32 %sel
|
|
|
|
%band = and i32 %x, 8
|
|
%bor = or i32 %asel, 64
|
|
%bcmp = icmp ne i32 %band, 0
|
|
%bsel = select i1 %bcmp, i32 %bor, i32 %asel
|
|
|
|
ret i32 %bsel
|
|
}
|
|
|
|
define i32 @f12(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f12:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: lsr r2, r0, #2
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: bfi r0, r2, #4, #1
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 16
|
|
%cmp = icmp eq i32 %and, 0
|
|
%sel = select i1 %cmp, i32 %y2, i32 %or
|
|
ret i32 %sel
|
|
}
|
|
|
|
define i32 @f13(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: f13:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: and r2, r0, #4
|
|
; CHECK-NEXT: bic r0, r1, #255
|
|
; CHECK-NEXT: cmp r2, #42
|
|
; CHECK-NEXT: orrne r0, r0, #16
|
|
; CHECK-NEXT: bx lr
|
|
%y2 = and i32 %y, 4294967040 ; 0xFFFFFF00
|
|
%and = and i32 %x, 4
|
|
%or = or i32 %y2, 16
|
|
%cmp = icmp eq i32 %and, 42 ; Not comparing against zero!
|
|
%sel = select i1 %cmp, i32 %y2, i32 %or
|
|
ret i32 %sel
|
|
}
|
|
|
|
define i32 @bfi1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi1:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: and r2, r0, #1
|
|
; CHECK-NEXT: bic r1, r1, #19
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #16
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r0, r0, #2
|
|
; CHECK-NEXT: orr r0, r1, r0
|
|
; CHECK-NEXT: bx lr
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 16
|
|
%y2 = and i32 %z1, 4294967279
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 2
|
|
%y3 = and i32 %z2, 4294967293
|
|
%z3 = or i32 %y3, %x3
|
|
ret i32 %z3
|
|
}
|
|
|
|
define void @bfi1_use(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi1_use:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: push {r11, lr}
|
|
; CHECK-NEXT: mov r2, r1
|
|
; CHECK-NEXT: lsr r3, r0, #4
|
|
; CHECK-NEXT: bfi r2, r0, #0, #1
|
|
; CHECK-NEXT: lsr r0, r0, #1
|
|
; CHECK-NEXT: mov r1, r2
|
|
; CHECK-NEXT: bfi r1, r3, #4, #1
|
|
; CHECK-NEXT: mov r3, r1
|
|
; CHECK-NEXT: bfi r3, r0, #1, #1
|
|
; CHECK-NEXT: mov r0, r2
|
|
; CHECK-NEXT: mov r2, r3
|
|
; CHECK-NEXT: bl use
|
|
; CHECK-NEXT: pop {r11, pc}
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 16
|
|
%y2 = and i32 %z1, 4294967279
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 2
|
|
%y3 = and i32 %z2, 4294967293
|
|
%z3 = or i32 %y3, %x3
|
|
call void @use(i32 %z1, i32 %z2, i32 %z3, i32 %z3)
|
|
ret void
|
|
}
|
|
|
|
define i32 @bfi2(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi2:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: movw r2, #65148
|
|
; CHECK-NEXT: movt r2, #65535
|
|
; CHECK-NEXT: and r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #1
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #2
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #128
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r0, r0, #256
|
|
; CHECK-NEXT: orr r0, r1, r0
|
|
; CHECK-NEXT: bx lr
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 2
|
|
%y2 = and i32 %z1, 4294967293
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 128
|
|
%y3 = and i32 %z2, 4294967167
|
|
%z3 = or i32 %y3, %x3
|
|
%x4 = and i32 %a, 256
|
|
%y4 = and i32 %z3, 4294967039
|
|
%z4 = or i32 %y4, %x4
|
|
ret i32 %z4
|
|
}
|
|
|
|
define void @bfi2_uses(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi2_uses:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: push {r11, lr}
|
|
; CHECK-NEXT: mov r12, r1
|
|
; CHECK-NEXT: bfi r1, r0, #0, #2
|
|
; CHECK-NEXT: bfi r12, r0, #0, #1
|
|
; CHECK-NEXT: lsr r0, r0, #7
|
|
; CHECK-NEXT: mov r2, r1
|
|
; CHECK-NEXT: mov r3, r1
|
|
; CHECK-NEXT: bfi r2, r0, #7, #1
|
|
; CHECK-NEXT: bfi r3, r0, #7, #2
|
|
; CHECK-NEXT: mov r0, r12
|
|
; CHECK-NEXT: bl use
|
|
; CHECK-NEXT: pop {r11, pc}
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 2
|
|
%y2 = and i32 %z1, 4294967293
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 128
|
|
%y3 = and i32 %z2, 4294967167
|
|
%z3 = or i32 %y3, %x3
|
|
%x4 = and i32 %a, 256
|
|
%y4 = and i32 %z3, 4294967039
|
|
%z4 = or i32 %y4, %x4
|
|
call void @use(i32 %z1, i32 %z2, i32 %z3, i32 %z4)
|
|
ret void
|
|
}
|
|
|
|
define i32 @bfi3(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi3:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: movw r2, #65148
|
|
; CHECK-NEXT: movt r2, #65535
|
|
; CHECK-NEXT: and r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #1
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #128
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r2, r0, #2
|
|
; CHECK-NEXT: orr r1, r1, r2
|
|
; CHECK-NEXT: and r0, r0, #256
|
|
; CHECK-NEXT: orr r0, r1, r0
|
|
; CHECK-NEXT: bx lr
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 128
|
|
%y2 = and i32 %z1, 4294967167
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 2
|
|
%y3 = and i32 %z2, 4294967293
|
|
%z3 = or i32 %y3, %x3
|
|
%x4 = and i32 %a, 256
|
|
%y4 = and i32 %z3, 4294967039
|
|
%z4 = or i32 %y4, %x4
|
|
ret i32 %z4
|
|
}
|
|
|
|
define void @bfi3_uses(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: bfi3_uses:
|
|
; CHECK: @ %bb.0:
|
|
; CHECK-NEXT: push {r11, lr}
|
|
; CHECK-NEXT: mov r12, r1
|
|
; CHECK-NEXT: lsr r2, r0, #7
|
|
; CHECK-NEXT: bfi r12, r0, #0, #1
|
|
; CHECK-NEXT: lsr r3, r0, #1
|
|
; CHECK-NEXT: lsr r0, r0, #8
|
|
; CHECK-NEXT: mov r1, r12
|
|
; CHECK-NEXT: bfi r1, r2, #7, #1
|
|
; CHECK-NEXT: mov r2, r1
|
|
; CHECK-NEXT: bfi r2, r3, #1, #1
|
|
; CHECK-NEXT: mov r3, r2
|
|
; CHECK-NEXT: bfi r3, r0, #8, #1
|
|
; CHECK-NEXT: mov r0, r12
|
|
; CHECK-NEXT: bl use
|
|
; CHECK-NEXT: pop {r11, pc}
|
|
%x1 = and i32 %a, 1
|
|
%y1 = and i32 %b, 4294967294
|
|
%z1 = or i32 %y1, %x1
|
|
%x2 = and i32 %a, 128
|
|
%y2 = and i32 %z1, 4294967167
|
|
%z2 = or i32 %y2, %x2
|
|
%x3 = and i32 %a, 2
|
|
%y3 = and i32 %z2, 4294967293
|
|
%z3 = or i32 %y3, %x3
|
|
%x4 = and i32 %a, 256
|
|
%y4 = and i32 %z3, 4294967039
|
|
%z4 = or i32 %y4, %x4
|
|
call void @use(i32 %z1, i32 %z2, i32 %z3, i32 %z4)
|
|
ret void
|
|
}
|
|
|
|
define i32 @bfi4(i32 %A, i2 zeroext %BB, i32* %d) {
|
|
; CHECK-LABEL: bfi4:
|
|
; CHECK: @ %bb.0: @ %entry
|
|
; CHECK-NEXT: push {r11, lr}
|
|
; CHECK-NEXT: lsr r12, r0, #1
|
|
; CHECK-NEXT: and r3, r0, #8
|
|
; CHECK-NEXT: bfi r1, r12, #2, #2
|
|
; CHECK-NEXT: mov lr, #96
|
|
; CHECK-NEXT: tst r0, #32
|
|
; CHECK-NEXT: bfi r1, r12, #9, #2
|
|
; CHECK-NEXT: movweq lr, #32
|
|
; CHECK-NEXT: orr r1, r1, r3, lsl #8
|
|
; CHECK-NEXT: and r3, r0, #64
|
|
; CHECK-NEXT: and r0, r0, #128
|
|
; CHECK-NEXT: orr r1, r1, lr
|
|
; CHECK-NEXT: orr r1, r1, r3, lsl #1
|
|
; CHECK-NEXT: str r1, [r2]
|
|
; CHECK-NEXT: pop {r11, pc}
|
|
entry:
|
|
%B = zext i2 %BB to i32
|
|
%and = and i32 %A, 2
|
|
%tobool12.not = icmp eq i32 %and, 0
|
|
%or17 = or i32 %B, 516
|
|
%spec.select112 = select i1 %tobool12.not, i32 %B, i32 %or17
|
|
%and20 = and i32 %A, 4
|
|
%tobool21.not = icmp eq i32 %and20, 0
|
|
%or26 = or i32 %spec.select112, 1032
|
|
%spec.select114 = select i1 %tobool21.not, i32 %spec.select112, i32 %or26
|
|
store i32 %spec.select114, i32* %d, align 4
|
|
%and29 = shl i32 %A, 8
|
|
%l2 = and i32 %and29, 2048
|
|
%l3 = or i32 %l2, %spec.select114
|
|
%and38 = and i32 %A, 32
|
|
%tobool39.not = icmp eq i32 %and38, 0
|
|
%spec.select.v = select i1 %tobool39.not, i32 32, i32 96
|
|
%spec.select = or i32 %l3, %spec.select.v
|
|
%and45 = shl i32 %A, 1
|
|
%l4 = and i32 %and45, 128
|
|
%l5 = or i32 %l4, %spec.select
|
|
store i32 %l5, i32* %d, align 4
|
|
%and52 = and i32 %A, 128
|
|
ret i32 %and52
|
|
}
|
|
|
|
declare void @use(i32, i32, i32, i32)
|