| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=sparc | FileCheck %s |
| ; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=CHECK64 |
| |
| define i32 @test(i32 %a) nounwind { |
| ; CHECK-LABEL: test: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: andcc %o0, 1, %g0 |
| ; CHECK-NEXT: bne .LBB0_2 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: ! %if.end |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 2, %o0 |
| ; CHECK-NEXT: .LBB0_2: ! %if.then |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 1, %o0 |
| ; |
| ; CHECK64-LABEL: test: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: andcc %o0, 1, %g0 |
| ; CHECK64-NEXT: bne %icc, .LBB0_2 |
| ; CHECK64-NEXT: nop |
| ; CHECK64-NEXT: ! %bb.1: ! %if.end |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 2, %o0 |
| ; CHECK64-NEXT: .LBB0_2: ! %if.then |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 1, %o0 |
| entry: |
| %and = and i32 %a, 1 |
| %tobool = icmp eq i32 %and, 0 |
| br i1 %tobool, label %if.end, label %if.then |
| |
| if.then: |
| ret i32 1 |
| |
| if.end: |
| ret i32 2 |
| } |
| |
| ; Same as above, with select. |
| define i32 @test_select(i32 %a) nounwind { |
| ; CHECK-LABEL: test_select: |
| ; CHECK: ! %bb.0: |
| ; CHECK-NEXT: andcc %o0, 1, %g0 |
| ; CHECK-NEXT: be .LBB1_2 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 2, %o0 |
| ; CHECK-NEXT: .LBB1_2: |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 1, %o0 |
| ; |
| ; CHECK64-LABEL: test_select: |
| ; CHECK64: ! %bb.0: |
| ; CHECK64-NEXT: andcc %o0, 1, %g0 |
| ; CHECK64-NEXT: mov 2, %o0 |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: move %icc, 1, %o0 |
| %and = and i32 %a, 1 |
| %tobool = icmp eq i32 %and, 0 |
| %ret = select i1 %tobool, i32 1, i32 2 |
| ret i32 %ret |
| } |
| |
| |
| ; No instruction can be changed to set ICC |
| define i32 @no_candidate(i32 %a) nounwind { |
| ; CHECK-LABEL: no_candidate: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: cmp %o0, 0 |
| ; CHECK-NEXT: be .LBB2_2 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: ! %if.then |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 1, %o0 |
| ; CHECK-NEXT: .LBB2_2: ! %if.end |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 2, %o0 |
| ; |
| ; CHECK64-LABEL: no_candidate: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: cmp %o0, 0 |
| ; CHECK64-NEXT: be %icc, .LBB2_2 |
| ; CHECK64-NEXT: nop |
| ; CHECK64-NEXT: ! %bb.1: ! %if.then |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 1, %o0 |
| ; CHECK64-NEXT: .LBB2_2: ! %if.end |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 2, %o0 |
| entry: |
| %tobool = icmp eq i32 %a, 0 |
| br i1 %tobool, label %if.end, label %if.then |
| |
| if.then: |
| ret i32 1 |
| |
| if.end: |
| ret i32 2 |
| } |
| |
| ; Defining instruction and compare not in same block |
| define i32 @not_same_block(i32 %a) nounwind { |
| ; CHECK-LABEL: not_same_block: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: and %o0, 1, %o0 |
| ; CHECK-NEXT: .LBB3_1: ! %if.then |
| ; CHECK-NEXT: ! =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: cmp %o0, 0 |
| ; CHECK-NEXT: bne .LBB3_1 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.2: ! %if.end |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 2, %o0 |
| ; |
| ; CHECK64-LABEL: not_same_block: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: and %o0, 1, %o0 |
| ; CHECK64-NEXT: .LBB3_1: ! %if.then |
| ; CHECK64-NEXT: ! =>This Inner Loop Header: Depth=1 |
| ; CHECK64-NEXT: cmp %o0, 0 |
| ; CHECK64-NEXT: bne %icc, .LBB3_1 |
| ; CHECK64-NEXT: nop |
| ; CHECK64-NEXT: ! %bb.2: ! %if.end |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 2, %o0 |
| entry: |
| %and = and i32 %a, 1 |
| br label %if.then |
| |
| if.then: |
| %tobool = icmp eq i32 %and, 0 |
| br i1 %tobool, label %if.end, label %if.then |
| ret i32 1 |
| |
| if.end: |
| ret i32 2 |
| } |
| |
| ; Compare instruction is not checking equality |
| define i32 @not_equality(i32 %a) nounwind { |
| ; CHECK-LABEL: not_equality: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: add %o0, -1, %o1 |
| ; CHECK-NEXT: cmp %o1, 0 |
| ; CHECK-NEXT: bl .LBB4_2 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: ! %entry |
| ; CHECK-NEXT: mov %o1, %o0 |
| ; CHECK-NEXT: .LBB4_2: ! %entry |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: nop |
| ; |
| ; CHECK64-LABEL: not_equality: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: add %o0, -1, %o1 |
| ; CHECK64-NEXT: cmp %o1, 0 |
| ; CHECK64-NEXT: movl %icc, %o0, %o1 |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov %o1, %o0 |
| entry: |
| %sub = sub i32 %a, 1 |
| %cmp = icmp slt i32 %sub, 0 |
| %cond = select i1 %cmp, i32 %a, i32 %sub |
| ret i32 %cond |
| } |
| |
| ; Instruction that modifies ICC (call) between defining |
| ; and compare instruction. |
| define i32 @call_between(i32 %a) nounwind { |
| ; CHECK-LABEL: call_between: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: save %sp, -96, %sp |
| ; CHECK-NEXT: and %i0, 1, %i1 |
| ; CHECK-NEXT: call not_equality |
| ; CHECK-NEXT: mov %i1, %o0 |
| ; CHECK-NEXT: cmp %i1, 0 |
| ; CHECK-NEXT: be .LBB5_2 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: ! %entry |
| ; CHECK-NEXT: mov %i1, %i0 |
| ; CHECK-NEXT: .LBB5_2: ! %entry |
| ; CHECK-NEXT: ret |
| ; CHECK-NEXT: restore |
| ; |
| ; CHECK64-LABEL: call_between: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: save %sp, -176, %sp |
| ; CHECK64-NEXT: and %i0, 1, %i1 |
| ; CHECK64-NEXT: call not_equality |
| ; CHECK64-NEXT: mov %i1, %o0 |
| ; CHECK64-NEXT: cmp %i1, 0 |
| ; CHECK64-NEXT: move %icc, %i0, %i1 |
| ; CHECK64-NEXT: ret |
| ; CHECK64-NEXT: restore %g0, %i1, %o0 |
| entry: |
| %and = and i32 %a, 1 |
| call i32 @not_equality(i32 %and) |
| %cmp = icmp eq i32 %and, 0 |
| %cond = select i1 %cmp, i32 %a, i32 %and |
| ret i32 %cond |
| } |
| |
| ; ICC is used in successor block. |
| define i32 @icc_live_out(i32 %a) nounwind { |
| ; CHECK-LABEL: icc_live_out: |
| ; CHECK: ! %bb.0: ! %entry |
| ; CHECK-NEXT: andcc %o0, 1, %o1 |
| ; CHECK-NEXT: bne .LBB6_4 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.1: ! %case1 |
| ; CHECK-NEXT: cmp %o1, 0 |
| ; CHECK-NEXT: be .LBB6_3 |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: ! %bb.2: ! %case1 |
| ; CHECK-NEXT: mov %o1, %o0 |
| ; CHECK-NEXT: .LBB6_3: ! %case1 |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: nop |
| ; CHECK-NEXT: .LBB6_4: ! %case2 |
| ; CHECK-NEXT: retl |
| ; CHECK-NEXT: mov 2, %o0 |
| ; |
| ; CHECK64-LABEL: icc_live_out: |
| ; CHECK64: ! %bb.0: ! %entry |
| ; CHECK64-NEXT: mov %o0, %o1 |
| ; CHECK64-NEXT: andcc %o0, 1, %o0 |
| ; CHECK64-NEXT: bne %icc, .LBB6_2 |
| ; CHECK64-NEXT: nop |
| ; CHECK64-NEXT: ! %bb.1: ! %case1 |
| ; CHECK64-NEXT: cmp %o0, 0 |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: move %icc, %o1, %o0 |
| ; CHECK64-NEXT: .LBB6_2: ! %case2 |
| ; CHECK64-NEXT: retl |
| ; CHECK64-NEXT: mov 2, %o0 |
| entry: |
| %and = and i32 %a, 1 |
| %cmp = icmp eq i32 %and, 0 |
| br i1 %cmp, label %case1, label %case2 |
| case1: |
| %cond = select i1 %cmp, i32 %a, i32 %and |
| ret i32 %cond |
| case2: |
| ret i32 2 |
| } |