1; RUN: llc < %s -mtriple=lanai | FileCheck %s 2 3define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp { 4entry: 5; CHECK-LABEL: f: 6; CHECK: sub.f %r6, %r7, [[IN:%.*]] 7; CHECK: sel.gt [[IN]], %r0, %rv 8 %cmp = icmp sgt i32 %a, %b 9 %sub = sub nsw i32 %a, %b 10 %sub. = select i1 %cmp, i32 %sub, i32 0 11 ret i32 %sub. 12} 13 14define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp { 15entry: 16; CHECK-LABEL: g: 17; CHECK: sub.f %r7, %r6, [[IN:%.*]] 18; CHECK: sel.lt [[IN]], %r0, %rv 19 %cmp = icmp slt i32 %a, %b 20 %sub = sub nsw i32 %b, %a 21 %sub. = select i1 %cmp, i32 %sub, i32 0 22 ret i32 %sub. 23} 24 25define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp { 26entry: 27; CHECK-LABEL: h: 28; CHECK: sub.f %r6, 0x3, [[IN:%.*]] 29; CHECK: sel.gt [[IN]], %r7, %rv 30 %cmp = icmp sgt i32 %a, 3 31 %sub = sub nsw i32 %a, 3 32 %sub. = select i1 %cmp, i32 %sub, i32 %b 33 ret i32 %sub. 34} 35 36define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp { 37entry: 38; CHECK-LABEL: i: 39; CHECK: sub.f %r7, %r6, [[IN:%.*]] 40; CHECK: sel.ult [[IN]], %r0, %rv 41 %cmp = icmp ult i32 %a, %b 42 %sub = sub i32 %b, %a 43 %sub. = select i1 %cmp, i32 %sub, i32 0 44 ret i32 %sub. 45} 46; If SR is live-out, we can't remove cmp if there exists a swapped sub. 47define i32 @j(i32 inreg %a, i32 inreg %b) nounwind { 48entry: 49; CHECK-LABEL: j: 50; CHECK: sub.f %r7, %r6, %r0 51; CHECK: sub %r6, %r7, %rv 52 %cmp = icmp eq i32 %b, %a 53 %sub = sub nsw i32 %a, %b 54 br i1 %cmp, label %if.then, label %if.else 55 56if.then: 57 %cmp2 = icmp sgt i32 %b, %a 58 %sel = select i1 %cmp2, i32 %sub, i32 %a 59 ret i32 %sel 60 61if.else: 62 ret i32 %sub 63} 64 65declare void @abort() 66declare void @exit(i32) 67@t = common global i32 0 68 69; If the comparison uses the C bit (signed overflow/underflow), we can't 70; omit the comparison. 71define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 72entry: 73; CHECK-LABEL: cmp_ult0 74; CHECK: sub {{.*}}, 0x11, [[IN:%.*]] 75; CHECK: sub.f [[IN]], 0x0, %r0 76 %load = load i32, i32* @t, align 4 77 %sub = sub i32 %load, 17 78 %cmp = icmp ult i32 %sub, 0 79 br i1 %cmp, label %if.then, label %if.else 80 81if.then: 82 call void @abort() 83 unreachable 84 85if.else: 86 call void @exit(i32 0) 87 unreachable 88} 89 90; Same for the V bit. 91; TODO: add test that exercises V bit individually (VC/VS). 92define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 93entry: 94; CHECK-LABEL: cmp_gt0 95; CHECK: sub {{.*}}, 0x11, [[IN:%.*]] 96; CHECK: sub.f [[IN]], 0x1, %r0 97 %load = load i32, i32* @t, align 4 98 %sub = sub i32 %load, 17 99 %cmp = icmp sgt i32 %sub, 0 100 br i1 %cmp, label %if.then, label %if.else 101 102if.then: 103 call void @abort() 104 unreachable 105 106if.else: 107 call void @exit(i32 0) 108 unreachable 109} 110