1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=lanai | FileCheck %s 3 4define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp { 5; CHECK-LABEL: f: 6; CHECK: ! %bb.0: 7; CHECK-NEXT: st %fp, [--%sp] 8; CHECK-NEXT: add %sp, 0x8, %fp 9; CHECK-NEXT: sub %sp, 0x8, %sp 10; CHECK-NEXT: sub.f %r6, %r7, %r3 11; CHECK-NEXT: sel.gt %r3, %r0, %rv 12; CHECK-NEXT: ld -4[%fp], %pc ! return 13; CHECK-NEXT: add %fp, 0x0, %sp 14; CHECK-NEXT: ld -8[%fp], %fp 15 %cmp = icmp sgt i32 %a, %b 16 %sub = sub nsw i32 %a, %b 17 %sub. = select i1 %cmp, i32 %sub, i32 0 18 ret i32 %sub. 19} 20 21define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp { 22; CHECK-LABEL: g: 23; CHECK: ! %bb.0: 24; CHECK-NEXT: st %fp, [--%sp] 25; CHECK-NEXT: add %sp, 0x8, %fp 26; CHECK-NEXT: sub %sp, 0x8, %sp 27; CHECK-NEXT: sub.f %r7, %r6, %r3 28; CHECK-NEXT: sel.gt %r3, %r0, %rv 29; CHECK-NEXT: ld -4[%fp], %pc ! return 30; CHECK-NEXT: add %fp, 0x0, %sp 31; CHECK-NEXT: ld -8[%fp], %fp 32 %cmp = icmp slt i32 %a, %b 33 %sub = sub nsw i32 %b, %a 34 %sub. = select i1 %cmp, i32 %sub, i32 0 35 ret i32 %sub. 36} 37 38define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp { 39; CHECK-LABEL: h: 40; CHECK: ! %bb.0: 41; CHECK-NEXT: st %fp, [--%sp] 42; CHECK-NEXT: add %sp, 0x8, %fp 43; CHECK-NEXT: sub %sp, 0x8, %sp 44; CHECK-NEXT: sub.f %r6, 0x3, %r3 45; CHECK-NEXT: sel.gt %r3, %r7, %rv 46; CHECK-NEXT: ld -4[%fp], %pc ! return 47; CHECK-NEXT: add %fp, 0x0, %sp 48; CHECK-NEXT: ld -8[%fp], %fp 49 %cmp = icmp sgt i32 %a, 3 50 %sub = sub nsw i32 %a, 3 51 %sub. = select i1 %cmp, i32 %sub, i32 %b 52 ret i32 %sub. 53} 54 55define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp { 56; CHECK-LABEL: i: 57; CHECK: ! %bb.0: 58; CHECK-NEXT: st %fp, [--%sp] 59; CHECK-NEXT: add %sp, 0x8, %fp 60; CHECK-NEXT: sub %sp, 0x8, %sp 61; CHECK-NEXT: sub.f %r7, %r6, %r3 62; CHECK-NEXT: sel.ugt %r3, %r0, %rv 63; CHECK-NEXT: ld -4[%fp], %pc ! return 64; CHECK-NEXT: add %fp, 0x0, %sp 65; CHECK-NEXT: ld -8[%fp], %fp 66 %cmp = icmp ult i32 %a, %b 67 %sub = sub i32 %b, %a 68 %sub. = select i1 %cmp, i32 %sub, i32 0 69 ret i32 %sub. 70} 71 72; If SR is live-out, we can't remove cmp if there exists a swapped sub. 73define i32 @j(i32 inreg %a, i32 inreg %b) nounwind { 74; CHECK-LABEL: j: 75; CHECK: ! %bb.0: ! %entry 76; CHECK-NEXT: st %fp, [--%sp] 77; CHECK-NEXT: add %sp, 0x8, %fp 78; CHECK-NEXT: sub.f %r6, %r7, %rv 79; CHECK-NEXT: bne .LBB4_2 80; CHECK-NEXT: sub %sp, 0x8, %sp 81; CHECK-NEXT: .LBB4_1: ! %if.then 82; CHECK-NEXT: sub.f %r7, %r6, %r0 83; CHECK-NEXT: sel.gt %rv, %r6, %rv 84; CHECK-NEXT: .LBB4_2: ! %if.else 85; CHECK-NEXT: ld -4[%fp], %pc ! return 86; CHECK-NEXT: add %fp, 0x0, %sp 87; CHECK-NEXT: ld -8[%fp], %fp 88entry: 89 %cmp = icmp eq i32 %b, %a 90 %sub = sub nsw i32 %a, %b 91 br i1 %cmp, label %if.then, label %if.else 92 93if.then: 94 %cmp2 = icmp sgt i32 %b, %a 95 %sel = select i1 %cmp2, i32 %sub, i32 %a 96 ret i32 %sel 97 98if.else: 99 ret i32 %sub 100} 101 102declare void @abort() 103declare void @exit(i32) 104@t = common global i32 0 105 106; If the comparison uses the C bit (signed overflow/underflow), we can't 107; omit the comparison. 108define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 109; CHECK-LABEL: cmp_ult0: 110; CHECK: ! %bb.0: ! %entry 111; CHECK-NEXT: st %fp, [--%sp] 112; CHECK-NEXT: add %sp, 0x8, %fp 113; CHECK-NEXT: mov hi(t), %r3 114; CHECK-NEXT: or %r3, lo(t), %r3 115; CHECK-NEXT: ld 0[%r3], %r3 116; CHECK-NEXT: sub %r3, 0x11, %r3 117; CHECK-NEXT: sub.f %r3, 0x0, %r0 118; CHECK-NEXT: buge .LBB5_2 119; CHECK-NEXT: sub %sp, 0x10, %sp 120; CHECK-NEXT: .LBB5_1: ! %if.then 121; CHECK-NEXT: add %pc, 0x10, %rca 122; CHECK-NEXT: st %rca, [--%sp] 123; CHECK-NEXT: bt abort 124; CHECK-NEXT: nop 125; CHECK-NEXT: .LBB5_2: ! %if.else 126; CHECK-NEXT: st %r0, 0[%sp] 127; CHECK-NEXT: add %pc, 0x10, %rca 128; CHECK-NEXT: st %rca, [--%sp] 129; CHECK-NEXT: bt exit 130; CHECK-NEXT: nop 131entry: 132 %load = load i32, i32* @t, align 4 133 %sub = sub i32 %load, 17 134 %cmp = icmp ult i32 %sub, 0 135 br i1 %cmp, label %if.then, label %if.else 136 137if.then: 138 call void @abort() 139 unreachable 140 141if.else: 142 call void @exit(i32 0) 143 unreachable 144} 145 146; Same for the V bit. 147; TODO: add test that exercises V bit individually (VC/VS). 148define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 149; CHECK-LABEL: cmp_gt0: 150; CHECK: ! %bb.0: ! %entry 151; CHECK-NEXT: st %fp, [--%sp] 152; CHECK-NEXT: add %sp, 0x8, %fp 153; CHECK-NEXT: mov hi(t), %r3 154; CHECK-NEXT: or %r3, lo(t), %r3 155; CHECK-NEXT: ld 0[%r3], %r3 156; CHECK-NEXT: sub %r3, 0x11, %r3 157; CHECK-NEXT: sub.f %r3, 0x1, %r0 158; CHECK-NEXT: blt .LBB6_2 159; CHECK-NEXT: sub %sp, 0x10, %sp 160; CHECK-NEXT: .LBB6_1: ! %if.then 161; CHECK-NEXT: add %pc, 0x10, %rca 162; CHECK-NEXT: st %rca, [--%sp] 163; CHECK-NEXT: bt abort 164; CHECK-NEXT: nop 165; CHECK-NEXT: .LBB6_2: ! %if.else 166; CHECK-NEXT: st %r0, 0[%sp] 167; CHECK-NEXT: add %pc, 0x10, %rca 168; CHECK-NEXT: st %rca, [--%sp] 169; CHECK-NEXT: bt exit 170; CHECK-NEXT: nop 171entry: 172 %load = load i32, i32* @t, align 4 173 %sub = sub i32 %load, 17 174 %cmp = icmp sgt i32 %sub, 0 175 br i1 %cmp, label %if.then, label %if.else 176 177if.then: 178 call void @abort() 179 unreachable 180 181if.else: 182 call void @exit(i32 0) 183 unreachable 184} 185