; 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: and %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: and %o0, 1, %o1 ; CHECK64-NEXT: cmp %o1, 0 ; CHECK64-NEXT: movl %icc, %o0, %o1 ; CHECK64-NEXT: retl ; CHECK64-NEXT: mov %o1, %o0 entry: %and = and i32 %a, 1 %cmp = icmp slt i32 %and, 0 %cond = select i1 %cmp, i32 %a, i32 %and 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 }