mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
99f589780c
This adds a simple fold into codegenprepare that converts comparison of branches towards comparison with zero if possible. For example: %c = icmp ult %x, 8 br %c, bla, blb %tc = lshr %x, 3 becomes %tc = lshr %x, 3 %c = icmp eq %tc, 0 br %c, bla, blb As a first order approximation, this can reduce the number of instructions needed to perform the branch as the shift is (often) needed anyway. At the moment this does not effect very much, as llvm tends to prefer the opposite form. But it can protect against regressions from commits like rG9423f78240a2. Simple cases of Add and Sub are added along with Shift, equally as the comparison to zero can often be folded with cpsr flags. Differential Revision: https://reviews.llvm.org/D101778
188 lines
7.1 KiB
LLVM
188 lines
7.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple thumbv6m-none-eabi -o - %s | FileCheck %s --check-prefix=CHECK-V6M
|
|
; RUN: llc -mtriple thumbv7m-none-eabi -o - %s | FileCheck %s --check-prefix=CHECK-V7M
|
|
; RUN: llc -mtriple thumbv8.1m.main-none-eabi -mattr=+mve,+lob -o - %s | FileCheck %s --check-prefix=CHECK-V81M
|
|
; RUN: llc -mtriple armv7a-none-eabi -o - %s | FileCheck %s --check-prefix=CHECK-V7A
|
|
|
|
define i32 @test_lshr(i32* nocapture %x, i32* nocapture readonly %y, i32 %n) {
|
|
; CHECK-V6M-LABEL: test_lshr:
|
|
; CHECK-V6M: @ %bb.0: @ %entry
|
|
; CHECK-V6M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V6M-NEXT: beq .LBB0_2
|
|
; CHECK-V6M-NEXT: .LBB0_1: @ %while.body
|
|
; CHECK-V6M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V6M-NEXT: ldm r1!, {r3}
|
|
; CHECK-V6M-NEXT: lsls r3, r3, #1
|
|
; CHECK-V6M-NEXT: stm r0!, {r3}
|
|
; CHECK-V6M-NEXT: subs r2, r2, #1
|
|
; CHECK-V6M-NEXT: bne .LBB0_1
|
|
; CHECK-V6M-NEXT: .LBB0_2: @ %while.end
|
|
; CHECK-V6M-NEXT: movs r0, #0
|
|
; CHECK-V6M-NEXT: bx lr
|
|
;
|
|
; CHECK-V7M-LABEL: test_lshr:
|
|
; CHECK-V7M: @ %bb.0: @ %entry
|
|
; CHECK-V7M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V7M-NEXT: beq .LBB0_3
|
|
; CHECK-V7M-NEXT: @ %bb.1: @ %while.body.preheader
|
|
; CHECK-V7M-NEXT: subs r1, #4
|
|
; CHECK-V7M-NEXT: subs r0, #4
|
|
; CHECK-V7M-NEXT: .LBB0_2: @ %while.body
|
|
; CHECK-V7M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V7M-NEXT: ldr r3, [r1, #4]!
|
|
; CHECK-V7M-NEXT: subs r2, #1
|
|
; CHECK-V7M-NEXT: lsl.w r3, r3, #1
|
|
; CHECK-V7M-NEXT: str r3, [r0, #4]!
|
|
; CHECK-V7M-NEXT: bne .LBB0_2
|
|
; CHECK-V7M-NEXT: .LBB0_3: @ %while.end
|
|
; CHECK-V7M-NEXT: movs r0, #0
|
|
; CHECK-V7M-NEXT: bx lr
|
|
;
|
|
; CHECK-V81M-LABEL: test_lshr:
|
|
; CHECK-V81M: @ %bb.0: @ %entry
|
|
; CHECK-V81M-NEXT: .save {r7, lr}
|
|
; CHECK-V81M-NEXT: push {r7, lr}
|
|
; CHECK-V81M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V81M-NEXT: wls lr, r2, .LBB0_2
|
|
; CHECK-V81M-NEXT: .LBB0_1: @ %while.body
|
|
; CHECK-V81M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V81M-NEXT: ldr r2, [r1], #4
|
|
; CHECK-V81M-NEXT: lsls r2, r2, #1
|
|
; CHECK-V81M-NEXT: str r2, [r0], #4
|
|
; CHECK-V81M-NEXT: le lr, .LBB0_1
|
|
; CHECK-V81M-NEXT: .LBB0_2: @ %while.end
|
|
; CHECK-V81M-NEXT: movs r0, #0
|
|
; CHECK-V81M-NEXT: pop {r7, pc}
|
|
;
|
|
; CHECK-V7A-LABEL: test_lshr:
|
|
; CHECK-V7A: @ %bb.0: @ %entry
|
|
; CHECK-V7A-NEXT: mov r3, #0
|
|
; CHECK-V7A-NEXT: cmp r3, r2, lsr #2
|
|
; CHECK-V7A-NEXT: beq .LBB0_3
|
|
; CHECK-V7A-NEXT: @ %bb.1: @ %while.body.preheader
|
|
; CHECK-V7A-NEXT: lsr r2, r2, #2
|
|
; CHECK-V7A-NEXT: .LBB0_2: @ %while.body
|
|
; CHECK-V7A-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V7A-NEXT: ldr r3, [r1], #4
|
|
; CHECK-V7A-NEXT: subs r2, r2, #1
|
|
; CHECK-V7A-NEXT: lsl r3, r3, #1
|
|
; CHECK-V7A-NEXT: str r3, [r0], #4
|
|
; CHECK-V7A-NEXT: bne .LBB0_2
|
|
; CHECK-V7A-NEXT: .LBB0_3: @ %while.end
|
|
; CHECK-V7A-NEXT: mov r0, #0
|
|
; CHECK-V7A-NEXT: bx lr
|
|
entry:
|
|
%shr = lshr i32 %n, 2
|
|
%tobool.not4 = icmp eq i32 %shr, 0
|
|
br i1 %tobool.not4, label %while.end, label %while.body
|
|
|
|
while.body: ; preds = %entry, %while.body
|
|
%c.07 = phi i32 [ %dec, %while.body ], [ %shr, %entry ]
|
|
%x.addr.06 = phi i32* [ %incdec.ptr1, %while.body ], [ %x, %entry ]
|
|
%y.addr.05 = phi i32* [ %incdec.ptr, %while.body ], [ %y, %entry ]
|
|
%incdec.ptr = getelementptr inbounds i32, i32* %y.addr.05, i32 1
|
|
%0 = load i32, i32* %y.addr.05, align 4
|
|
%mul = shl nsw i32 %0, 1
|
|
%incdec.ptr1 = getelementptr inbounds i32, i32* %x.addr.06, i32 1
|
|
store i32 %mul, i32* %x.addr.06, align 4
|
|
%dec = add nsw i32 %c.07, -1
|
|
%tobool.not = icmp eq i32 %dec, 0
|
|
br i1 %tobool.not, label %while.end, label %while.body
|
|
|
|
while.end: ; preds = %while.body, %entry
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @test_lshr2(i32* nocapture %x, i32* nocapture readonly %y, i32 %n) {
|
|
; CHECK-V6M-LABEL: test_lshr2:
|
|
; CHECK-V6M: @ %bb.0: @ %entry
|
|
; CHECK-V6M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V6M-NEXT: beq .LBB1_2
|
|
; CHECK-V6M-NEXT: .LBB1_1: @ %while.body
|
|
; CHECK-V6M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V6M-NEXT: ldm r1!, {r3}
|
|
; CHECK-V6M-NEXT: lsls r3, r3, #1
|
|
; CHECK-V6M-NEXT: stm r0!, {r3}
|
|
; CHECK-V6M-NEXT: subs r2, r2, #1
|
|
; CHECK-V6M-NEXT: bne .LBB1_1
|
|
; CHECK-V6M-NEXT: .LBB1_2: @ %while.end
|
|
; CHECK-V6M-NEXT: movs r0, #0
|
|
; CHECK-V6M-NEXT: bx lr
|
|
;
|
|
; CHECK-V7M-LABEL: test_lshr2:
|
|
; CHECK-V7M: @ %bb.0: @ %entry
|
|
; CHECK-V7M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V7M-NEXT: beq .LBB1_3
|
|
; CHECK-V7M-NEXT: @ %bb.1: @ %while.body.preheader
|
|
; CHECK-V7M-NEXT: subs r1, #4
|
|
; CHECK-V7M-NEXT: subs r0, #4
|
|
; CHECK-V7M-NEXT: .LBB1_2: @ %while.body
|
|
; CHECK-V7M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V7M-NEXT: ldr r3, [r1, #4]!
|
|
; CHECK-V7M-NEXT: subs r2, #1
|
|
; CHECK-V7M-NEXT: lsl.w r3, r3, #1
|
|
; CHECK-V7M-NEXT: str r3, [r0, #4]!
|
|
; CHECK-V7M-NEXT: bne .LBB1_2
|
|
; CHECK-V7M-NEXT: .LBB1_3: @ %while.end
|
|
; CHECK-V7M-NEXT: movs r0, #0
|
|
; CHECK-V7M-NEXT: bx lr
|
|
;
|
|
; CHECK-V81M-LABEL: test_lshr2:
|
|
; CHECK-V81M: @ %bb.0: @ %entry
|
|
; CHECK-V81M-NEXT: .save {r7, lr}
|
|
; CHECK-V81M-NEXT: push {r7, lr}
|
|
; CHECK-V81M-NEXT: lsrs r2, r2, #2
|
|
; CHECK-V81M-NEXT: wls lr, r2, .LBB1_2
|
|
; CHECK-V81M-NEXT: .LBB1_1: @ %while.body
|
|
; CHECK-V81M-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V81M-NEXT: ldr r2, [r1], #4
|
|
; CHECK-V81M-NEXT: lsls r2, r2, #1
|
|
; CHECK-V81M-NEXT: str r2, [r0], #4
|
|
; CHECK-V81M-NEXT: le lr, .LBB1_1
|
|
; CHECK-V81M-NEXT: .LBB1_2: @ %while.end
|
|
; CHECK-V81M-NEXT: movs r0, #0
|
|
; CHECK-V81M-NEXT: pop {r7, pc}
|
|
;
|
|
; CHECK-V7A-LABEL: test_lshr2:
|
|
; CHECK-V7A: @ %bb.0: @ %entry
|
|
; CHECK-V7A-NEXT: mov r3, #0
|
|
; CHECK-V7A-NEXT: cmp r3, r2, lsr #2
|
|
; CHECK-V7A-NEXT: beq .LBB1_3
|
|
; CHECK-V7A-NEXT: @ %bb.1: @ %while.body.preheader
|
|
; CHECK-V7A-NEXT: lsr r2, r2, #2
|
|
; CHECK-V7A-NEXT: .LBB1_2: @ %while.body
|
|
; CHECK-V7A-NEXT: @ =>This Inner Loop Header: Depth=1
|
|
; CHECK-V7A-NEXT: ldr r3, [r1], #4
|
|
; CHECK-V7A-NEXT: subs r2, r2, #1
|
|
; CHECK-V7A-NEXT: lsl r3, r3, #1
|
|
; CHECK-V7A-NEXT: str r3, [r0], #4
|
|
; CHECK-V7A-NEXT: bne .LBB1_2
|
|
; CHECK-V7A-NEXT: .LBB1_3: @ %while.end
|
|
; CHECK-V7A-NEXT: mov r0, #0
|
|
; CHECK-V7A-NEXT: bx lr
|
|
entry:
|
|
%tobool.not4 = icmp ult i32 %n, 4
|
|
br i1 %tobool.not4, label %while.end, label %while.body.preheader
|
|
|
|
while.body.preheader: ; preds = %entry
|
|
%shr = lshr i32 %n, 2
|
|
br label %while.body
|
|
|
|
while.body: ; preds = %while.body.preheader, %while.body
|
|
%c.07 = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ]
|
|
%x.addr.06 = phi i32* [ %incdec.ptr1, %while.body ], [ %x, %while.body.preheader ]
|
|
%y.addr.05 = phi i32* [ %incdec.ptr, %while.body ], [ %y, %while.body.preheader ]
|
|
%incdec.ptr = getelementptr inbounds i32, i32* %y.addr.05, i32 1
|
|
%0 = load i32, i32* %y.addr.05, align 4
|
|
%mul = shl nsw i32 %0, 1
|
|
%incdec.ptr1 = getelementptr inbounds i32, i32* %x.addr.06, i32 1
|
|
store i32 %mul, i32* %x.addr.06, align 4
|
|
%dec = add nsw i32 %c.07, -1
|
|
%tobool.not = icmp eq i32 %dec, 0
|
|
br i1 %tobool.not, label %while.end, label %while.body
|
|
|
|
while.end: ; preds = %while.body, %entry
|
|
ret i32 0
|
|
}
|
|
|