1 ; RUN: llc < %s -mtriple=lanai | FileCheck %s 2 3 define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp { 4 entry: 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 14 define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp { 15 entry: 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 25 define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp { 26 entry: 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 36 define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp { 37 entry: 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. 47 define i32 @j(i32 inreg %a, i32 inreg %b) nounwind { 48 entry: 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 56 if.then: 57 %cmp2 = icmp sgt i32 %b, %a 58 %sel = select i1 %cmp2, i32 %sub, i32 %a 59 ret i32 %sel 60 61 if.else: 62 ret i32 %sub 63 } 64 65 declare void @abort() 66 declare 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. 71 define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 72 entry: 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 81 if.then: 82 call void @abort() 83 unreachable 84 85 if.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). 92 define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) { 93 entry: 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 102 if.then: 103 call void @abort() 104 unreachable 105 106 if.else: 107 call void @exit(i32 0) 108 unreachable 109 } 110