When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; RUN: llc < %s -march=arm | FileCheck -check-prefix=ARM %s
|
|
|
|
; RUN: llc < %s -march=thumb | FileCheck -check-prefix=THUMB %s
|
|
|
|
; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck -check-prefix=T2 %s
|
2013-09-09 22:21:49 +08:00
|
|
|
; RUN: llc < %s -mtriple=thumbv8 | FileCheck -check-prefix=V8 %s
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
|
|
|
|
; FIXME: The -march=thumb test doesn't change if -disable-peephole is specified.
|
2010-09-14 16:50:43 +08:00
|
|
|
|
|
|
|
%struct.Foo = type { i8* }
|
|
|
|
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; ARM: foo
|
|
|
|
; THUMB: foo
|
|
|
|
; T2: foo
|
|
|
|
define %struct.Foo* @foo(%struct.Foo* %this, i32 %acc) nounwind readonly align 2 {
|
2010-09-14 16:50:43 +08:00
|
|
|
entry:
|
|
|
|
%scevgep = getelementptr %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** %lsr.iv24, i32 -1
|
|
|
|
%tmp2 = load i8** %scevgep5
|
|
|
|
%0 = ptrtoint i8* %tmp2 to i32
|
|
|
|
|
2011-04-30 09:37:52 +08:00
|
|
|
; ARM: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; ARM-NEXT: beq
|
2010-09-14 16:50:43 +08:00
|
|
|
|
2011-04-01 06:14:03 +08:00
|
|
|
; THUMB: movs r[[R0:[0-9]+]], #3
|
|
|
|
; THUMB-NEXT: ands r[[R0]], r
|
|
|
|
; THUMB-NEXT: cmp r[[R0]], #0
|
2010-09-29 18:45:43 +08:00
|
|
|
; THUMB-NEXT: beq
|
2010-09-29 18:12:08 +08:00
|
|
|
|
2011-04-30 09:37:52 +08:00
|
|
|
; T2: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
2010-09-29 18:45:43 +08:00
|
|
|
; T2-NEXT: beq
|
2010-09-14 16:50:43 +08:00
|
|
|
|
|
|
|
%and = and i32 %0, 3
|
|
|
|
%tst = icmp eq i32 %and, 0
|
|
|
|
br i1 %tst, label %sw.bb, label %tailrecurse.switch
|
|
|
|
|
|
|
|
tailrecurse.switch: ; preds = %tailrecurse
|
2013-09-09 22:21:49 +08:00
|
|
|
; 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: b
|
|
|
|
; The trailing space in the last line checks that the branch is unconditional
|
2010-09-14 16:50:43 +08:00
|
|
|
switch i32 %and, label %sw.epilog [
|
|
|
|
i32 1, label %sw.bb
|
|
|
|
i32 3, label %sw.bb6
|
|
|
|
i32 2, label %sw.bb8
|
|
|
|
]
|
|
|
|
|
|
|
|
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* %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* %this, i32 %tmp1
|
|
|
|
ret %struct.Foo* %add.ptr11
|
|
|
|
|
|
|
|
sw.epilog: ; preds = %tailrecurse.switch
|
|
|
|
ret %struct.Foo* undef
|
|
|
|
}
|
2010-10-15 11:23:44 +08:00
|
|
|
|
|
|
|
; 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] }
|
|
|
|
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; ARM: bar
|
2010-10-15 11:23:44 +08:00
|
|
|
; THUMB: bar
|
|
|
|
; T2: bar
|
2013-09-09 22:21:49 +08:00
|
|
|
; V8-LABEL: bar:
|
2010-10-15 11:23:44 +08:00
|
|
|
define internal zeroext i8 @bar(%struct.S* %x, %struct.S* nocapture %y) nounwind readonly {
|
|
|
|
entry:
|
|
|
|
%0 = getelementptr inbounds %struct.S* %x, i32 0, i32 1, i32 0
|
|
|
|
%1 = load i8* %0, align 1
|
|
|
|
%2 = zext i8 %1 to i32
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; ARM: ands
|
2010-10-15 11:23:44 +08:00
|
|
|
; THUMB: ands
|
|
|
|
; T2: ands
|
2013-09-09 22:21:49 +08:00
|
|
|
; V8: ands
|
|
|
|
; V8-NEXT: beq
|
2010-10-15 11:23:44 +08:00
|
|
|
%3 = and i32 %2, 112
|
|
|
|
%4 = icmp eq i32 %3, 0
|
|
|
|
br i1 %4, label %return, label %bb
|
|
|
|
|
|
|
|
bb: ; preds = %entry
|
2013-09-09 22:21:49 +08:00
|
|
|
; V8-NEXT: %bb
|
2010-10-15 11:23:44 +08:00
|
|
|
%5 = getelementptr inbounds %struct.S* %y, i32 0, i32 1, i32 0
|
|
|
|
%6 = load i8* %5, align 1
|
|
|
|
%7 = zext i8 %6 to i32
|
When we look at instructions to convert to setting the 's' flag, we need to look
at more than those which define CPSR. You can have this situation:
(1) subs ...
(2) sub r6, r5, r4
(3) movge ...
(4) cmp r6, 0
(5) movge ...
We cannot convert (2) to "subs" because (3) is using the CPSR set by
(1). There's an analogous situation here:
(1) sub r1, r2, r3
(2) sub r4, r5, r6
(3) cmp r4, ...
(5) movge ...
(6) cmp r1, ...
(7) movge ...
We cannot convert (1) to "subs" because of the intervening use of CPSR.
llvm-svn: 117950
2010-11-02 04:41:43 +08:00
|
|
|
; ARM: andsne
|
2010-10-15 11:23:44 +08:00
|
|
|
; THUMB: ands
|
|
|
|
; T2: andsne
|
2013-09-09 22:21:49 +08:00
|
|
|
; V8: ands
|
|
|
|
; V8-NEXT: beq
|
2010-10-15 11:23:44 +08:00
|
|
|
%8 = and i32 %7, 112
|
|
|
|
%9 = icmp eq i32 %8, 0
|
|
|
|
br i1 %9, label %return, label %bb2
|
|
|
|
|
|
|
|
bb2: ; preds = %bb
|
2013-09-09 22:21:49 +08:00
|
|
|
; V8-NEXT: %bb2
|
|
|
|
; V8-NEXT: cmp
|
|
|
|
; V8-NEXT: it ne
|
|
|
|
; V8-NEXT: cmpne
|
|
|
|
; V8-NEXT: bne
|
2010-10-15 11:23:44 +08:00
|
|
|
%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
|
|
|
|
}
|