mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
329a30125b
The SchedModel allows the addition of ReadAdvances to express that certain operands of the instructions are needed at a later point than the others. RegAlloc may add pseudo operands that are not part of the instruction descriptor, and therefore cannot have any read advance entries. This meant that in some cases the desired read advance was nullified by such a pseudo operand, which still had the original latency. This patch fixes this by making sure that such pseudo operands get a zero latency during DAG construction. Review: Matthias Braun, Ulrich Weigand. https://reviews.llvm.org/D49671 llvm-svn: 345606
187 lines
5.5 KiB
LLVM
187 lines
5.5 KiB
LLVM
; RUN: llc -mtriple=arm-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=ARM %s
|
|
; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=THUMB %s
|
|
; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck -check-prefix=T2 %s
|
|
; RUN: llc -mtriple=thumbv8-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=V8 %s
|
|
|
|
; FIXME: The -mtriple=thumb test doesn't change if -disable-peephole is specified.
|
|
|
|
%struct.Foo = type { i8* }
|
|
|
|
; ARM-LABEL: foo:
|
|
; THUMB-LABEL: foo:
|
|
; T2-LABEL: foo:
|
|
define %struct.Foo* @foo(%struct.Foo* %this, i32 %acc) nounwind readonly align 2 {
|
|
entry:
|
|
%scevgep = getelementptr %struct.Foo, %struct.Foo* %this, i32 1
|
|
br label %tailrecurse
|
|
|
|
tailrecurse: ; preds = %sw.bb, %entry
|
|
%lsr.iv2 = phi %struct.Foo* [ %scevgep3, %sw.bb ], [ %scevgep, %entry ]
|
|
%lsr.iv = phi i32 [ %lsr.iv.next, %sw.bb ], [ 1, %entry ]
|
|
%acc.tr = phi i32 [ %or, %sw.bb ], [ %acc, %entry ]
|
|
%lsr.iv24 = bitcast %struct.Foo* %lsr.iv2 to i8**
|
|
%scevgep5 = getelementptr i8*, i8** %lsr.iv24, i32 -1
|
|
%tmp2 = load i8*, i8** %scevgep5
|
|
%0 = ptrtoint i8* %tmp2 to i32
|
|
|
|
; ARM: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
|
; ARM-NEXT: beq
|
|
|
|
; THUMB: movs r[[R0:[0-9]+]], #3
|
|
; THUMB-NEXT: ands r[[R0]], r
|
|
; THUMB-NEXT: cmp r[[R0]], #0
|
|
; THUMB-NEXT: beq
|
|
|
|
; T2: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
|
; T2-NEXT: beq
|
|
|
|
%and = and i32 %0, 3
|
|
%tst = icmp eq i32 %and, 0
|
|
br i1 %tst, label %sw.bb, label %tailrecurse.switch
|
|
|
|
tailrecurse.switch: ; preds = %tailrecurse
|
|
; V8-LABEL: %tailrecurse.switch
|
|
; V8: cmp
|
|
; V8-NEXT: beq
|
|
; V8-NEXT: %tailrecurse.switch
|
|
; V8: cmp
|
|
; V8-NEXT: beq
|
|
; V8-NEXT: %tailrecurse.switch
|
|
; V8: cmp
|
|
; V8-NEXT: beq
|
|
; V8-NEXT: %sw.epilog
|
|
; V8-NEXT: bx lr
|
|
switch i32 %and, label %sw.epilog [
|
|
i32 1, label %sw.bb
|
|
i32 3, label %sw.bb6
|
|
i32 2, label %sw.bb8
|
|
], !prof !1
|
|
|
|
sw.bb: ; preds = %tailrecurse.switch, %tailrecurse
|
|
%shl = shl i32 %acc.tr, 1
|
|
%or = or i32 %and, %shl
|
|
%lsr.iv.next = add i32 %lsr.iv, 1
|
|
%scevgep3 = getelementptr %struct.Foo, %struct.Foo* %lsr.iv2, i32 1
|
|
br label %tailrecurse
|
|
|
|
sw.bb6: ; preds = %tailrecurse.switch
|
|
ret %struct.Foo* %lsr.iv2
|
|
|
|
sw.bb8: ; preds = %tailrecurse.switch
|
|
%tmp1 = add i32 %acc.tr, %lsr.iv
|
|
%add.ptr11 = getelementptr inbounds %struct.Foo, %struct.Foo* %this, i32 %tmp1
|
|
ret %struct.Foo* %add.ptr11
|
|
|
|
sw.epilog: ; preds = %tailrecurse.switch
|
|
ret %struct.Foo* undef
|
|
}
|
|
|
|
; Another test that exercises the AND/TST peephole optimization and also
|
|
; generates a predicated ANDS instruction. Check that the predicate is printed
|
|
; after the "S" modifier on the instruction.
|
|
|
|
%struct.S = type { i8* (i8*)*, [1 x i8] }
|
|
|
|
; ARM-LABEL: bar:
|
|
; THUMB-LABEL: bar:
|
|
; T2-LABEL: bar:
|
|
; V8-LABEL: bar:
|
|
define internal zeroext i8 @bar(%struct.S* %x, %struct.S* nocapture %y) nounwind readonly {
|
|
entry:
|
|
%0 = getelementptr inbounds %struct.S, %struct.S* %x, i32 0, i32 1, i32 0
|
|
%1 = load i8, i8* %0, align 1
|
|
%2 = zext i8 %1 to i32
|
|
; ARM: ands
|
|
; THUMB: ands
|
|
; T2: ands
|
|
; V8: ands
|
|
; V8-NEXT: beq
|
|
%3 = and i32 %2, 112
|
|
%4 = icmp eq i32 %3, 0
|
|
br i1 %4, label %return, label %bb
|
|
|
|
bb: ; preds = %entry
|
|
; V8-NEXT: %bb
|
|
%5 = getelementptr inbounds %struct.S, %struct.S* %y, i32 0, i32 1, i32 0
|
|
%6 = load i8, i8* %5, align 1
|
|
%7 = zext i8 %6 to i32
|
|
; ARM: andsne
|
|
; THUMB: ands
|
|
; T2: andsne
|
|
; V8: ands
|
|
; V8-NEXT: beq
|
|
%8 = and i32 %7, 112
|
|
%9 = icmp eq i32 %8, 0
|
|
br i1 %9, label %return, label %bb2
|
|
|
|
bb2: ; preds = %bb
|
|
; V8-NEXT: %bb2
|
|
; V8-NEXT: cmp
|
|
; V8-NEXT: it ne
|
|
; V8-NEXT: cmpne
|
|
; V8-NEXT: bne
|
|
%10 = icmp eq i32 %3, 16
|
|
%11 = icmp eq i32 %8, 16
|
|
%or.cond = or i1 %10, %11
|
|
br i1 %or.cond, label %bb4, label %return
|
|
|
|
bb4: ; preds = %bb2
|
|
%12 = ptrtoint %struct.S* %x to i32
|
|
%phitmp = trunc i32 %12 to i8
|
|
ret i8 %phitmp
|
|
|
|
return: ; preds = %bb2, %bb, %entry
|
|
ret i8 1
|
|
}
|
|
|
|
|
|
; We were looking through multiple COPY instructions to find an AND we might
|
|
; fold into a TST, but in doing so we changed the register being tested allowing
|
|
; folding of unrelated tests (in this case, a TST against r1 was eliminated in
|
|
; favour of an AND of r0).
|
|
|
|
define i32 @test_tst_assessment(i32 %a, i32 %b) {
|
|
; ARM-LABEL: test_tst_assessment:
|
|
; ARM: @ %bb.0:
|
|
; ARM-NEXT: and r0, r0, #1
|
|
; ARM-NEXT: tst r1, #1
|
|
; ARM-NEXT: subne r0, r0, #1
|
|
; ARM-NEXT: mov pc, lr
|
|
;
|
|
; THUMB-LABEL: test_tst_assessment:
|
|
; THUMB: @ %bb.0:
|
|
; THUMB-NEXT: movs r2, r0
|
|
; THUMB-NEXT: movs r0, #1
|
|
; THUMB-NEXT: ands r0, r2
|
|
; THUMB-NEXT: lsls r1, r1, #31
|
|
; THUMB-NEXT: beq .LBB2_2
|
|
; THUMB-NEXT: @ %bb.1:
|
|
; THUMB-NEXT: subs r0, r0, #1
|
|
; THUMB-NEXT: .LBB2_2:
|
|
; THUMB-NEXT: bx lr
|
|
;
|
|
; T2-LABEL: test_tst_assessment:
|
|
; T2: @ %bb.0:
|
|
; T2-NEXT: and r0, r0, #1
|
|
; T2-NEXT: lsls r1, r1, #31
|
|
; T2-NEXT: it ne
|
|
; T2-NEXT: subne r0, #1
|
|
; T2-NEXT: bx lr
|
|
;
|
|
; V8-LABEL: test_tst_assessment:
|
|
; V8: @ %bb.0:
|
|
; V8-NEXT: and r0, r0, #1
|
|
; V8-NEXT: lsls r1, r1, #31
|
|
; V8-NEXT: it ne
|
|
; V8-NEXT: subne r0, #1
|
|
; V8-NEXT: bx lr
|
|
%and1 = and i32 %a, 1
|
|
%sub = sub i32 %and1, 1
|
|
%and2 = and i32 %b, 1
|
|
%cmp = icmp eq i32 %and2, 0
|
|
%sel = select i1 %cmp, i32 %and1, i32 %sub
|
|
ret i32 %sel
|
|
}
|
|
|
|
!1 = !{!"branch_weights", i32 1, i32 1, i32 3, i32 2 }
|