1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -debugify-and-strip-all-safe < %s -O3 -mtriple=aarch64 -verify-machineinstrs | FileCheck %s 3 4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5target triple = "aarch64" 6 7; CMN is an alias of ADDS. 8 9define void @test_add_cbz(i32 %a, i32 %b, ptr %ptr) { 10; CHECK-LABEL: test_add_cbz: 11; CHECK: // %bb.0: // %common.ret 12; CHECK-NEXT: cmn w0, w1 13; CHECK-NEXT: cset w8, eq 14; CHECK-NEXT: str w8, [x2] 15; CHECK-NEXT: ret 16 %c = add nsw i32 %a, %b 17 %d = icmp ne i32 %c, 0 18 br i1 %d, label %L1, label %L2 19L1: 20 store i32 0, ptr %ptr, align 4 21 ret void 22L2: 23 store i32 1, ptr %ptr, align 4 24 ret void 25} 26 27define void @test_add_cbz_multiple_use(i32 %a, i32 %b, ptr %ptr) { 28; CHECK-LABEL: test_add_cbz_multiple_use: 29; CHECK: // %bb.0: // %common.ret 30; CHECK-NEXT: adds w8, w0, w1 31; CHECK-NEXT: mov w9, #10 // =0xa 32; CHECK-NEXT: csel w8, w9, w8, ne 33; CHECK-NEXT: str w8, [x2] 34; CHECK-NEXT: ret 35 %c = add nsw i32 %a, %b 36 %d = icmp ne i32 %c, 0 37 br i1 %d, label %L1, label %L2 38L1: 39 store i32 10, ptr %ptr, align 4 40 ret void 41L2: 42 store i32 %c, ptr %ptr, align 4 43 ret void 44} 45 46define void @test_add_cbz_64(i64 %a, i64 %b, ptr %ptr) { 47; CHECK-LABEL: test_add_cbz_64: 48; CHECK: // %bb.0: // %common.ret 49; CHECK-NEXT: cmn x0, x1 50; CHECK-NEXT: cset w8, eq 51; CHECK-NEXT: str x8, [x2] 52; CHECK-NEXT: ret 53 %c = add nsw i64 %a, %b 54 %d = icmp ne i64 %c, 0 55 br i1 %d, label %L1, label %L2 56L1: 57 store i64 0, ptr %ptr, align 4 58 ret void 59L2: 60 store i64 1, ptr %ptr, align 4 61 ret void 62} 63 64define void @test_and_cbz(i32 %a, ptr %ptr) { 65; CHECK-LABEL: test_and_cbz: 66; CHECK: // %bb.0: // %common.ret 67; CHECK-NEXT: tst w0, #0x6 68; CHECK-NEXT: cset w8, eq 69; CHECK-NEXT: str w8, [x1] 70; CHECK-NEXT: ret 71 %c = and i32 %a, 6 72 %d = icmp ne i32 %c, 0 73 br i1 %d, label %L1, label %L2 74L1: 75 store i32 0, ptr %ptr, align 4 76 ret void 77L2: 78 store i32 1, ptr %ptr, align 4 79 ret void 80} 81 82define void @test_bic_cbnz(i32 %a, i32 %b, ptr %ptr) { 83; CHECK-LABEL: test_bic_cbnz: 84; CHECK: // %bb.0: // %common.ret 85; CHECK-NEXT: bics wzr, w1, w0 86; CHECK-NEXT: cset w8, ne 87; CHECK-NEXT: str w8, [x2] 88; CHECK-NEXT: ret 89 %c = and i32 %a, %b 90 %d = icmp eq i32 %c, %b 91 br i1 %d, label %L1, label %L2 92L1: 93 store i32 0, ptr %ptr, align 4 94 ret void 95L2: 96 store i32 1, ptr %ptr, align 4 97 ret void 98} 99 100define void @test_add_tbz(i32 %a, i32 %b, ptr %ptr) { 101; CHECK-LABEL: test_add_tbz: 102; CHECK: // %bb.0: // %entry 103; CHECK-NEXT: adds w8, w0, w1 104; CHECK-NEXT: b.pl .LBB5_2 105; CHECK-NEXT: // %bb.1: // %L1 106; CHECK-NEXT: str w8, [x2] 107; CHECK-NEXT: .LBB5_2: // %L2 108; CHECK-NEXT: ret 109entry: 110 %add = add nsw i32 %a, %b 111 %cmp36 = icmp sge i32 %add, 0 112 br i1 %cmp36, label %L2, label %L1 113L1: 114 store i32 %add, ptr %ptr, align 8 115 br label %L2 116L2: 117 ret void 118} 119 120define void @test_subs_tbz(i32 %a, i32 %b, ptr %ptr) { 121; CHECK-LABEL: test_subs_tbz: 122; CHECK: // %bb.0: // %entry 123; CHECK-NEXT: subs w8, w0, w1 124; CHECK-NEXT: b.pl .LBB6_2 125; CHECK-NEXT: // %bb.1: // %L1 126; CHECK-NEXT: str w8, [x2] 127; CHECK-NEXT: .LBB6_2: // %L2 128; CHECK-NEXT: ret 129entry: 130 %sub = sub nsw i32 %a, %b 131 %cmp36 = icmp sge i32 %sub, 0 132 br i1 %cmp36, label %L2, label %L1 133L1: 134 store i32 %sub, ptr %ptr, align 8 135 br label %L2 136L2: 137 ret void 138} 139 140define void @test_add_tbnz(i32 %a, i32 %b, ptr %ptr) { 141; CHECK-LABEL: test_add_tbnz: 142; CHECK: // %bb.0: // %entry 143; CHECK-NEXT: adds w8, w0, w1 144; CHECK-NEXT: b.mi .LBB7_2 145; CHECK-NEXT: // %bb.1: // %L1 146; CHECK-NEXT: str w8, [x2] 147; CHECK-NEXT: .LBB7_2: // %L2 148; CHECK-NEXT: ret 149entry: 150 %add = add nsw i32 %a, %b 151 %cmp36 = icmp slt i32 %add, 0 152 br i1 %cmp36, label %L2, label %L1 153L1: 154 store i32 %add, ptr %ptr, align 8 155 br label %L2 156L2: 157 ret void 158} 159 160define void @test_subs_tbnz(i32 %a, i32 %b, ptr %ptr) { 161; CHECK-LABEL: test_subs_tbnz: 162; CHECK: // %bb.0: // %entry 163; CHECK-NEXT: subs w8, w0, w1 164; CHECK-NEXT: b.mi .LBB8_2 165; CHECK-NEXT: // %bb.1: // %L1 166; CHECK-NEXT: str w8, [x2] 167; CHECK-NEXT: .LBB8_2: // %L2 168; CHECK-NEXT: ret 169entry: 170 %sub = sub nsw i32 %a, %b 171 %cmp36 = icmp slt i32 %sub, 0 172 br i1 %cmp36, label %L2, label %L1 173L1: 174 store i32 %sub, ptr %ptr, align 8 175 br label %L2 176L2: 177 ret void 178} 179 180declare void @foo() 181declare void @bar(i32) 182 183; Don't transform since the call will clobber the NZCV bits. 184define void @test_call_clobber(i32 %unused, i32 %a) uwtable { 185; CHECK-LABEL: test_call_clobber: 186; CHECK: // %bb.0: // %entry 187; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill 188; CHECK-NEXT: .cfi_def_cfa_offset 16 189; CHECK-NEXT: .cfi_offset w19, -8 190; CHECK-NEXT: .cfi_offset w30, -16 191; CHECK-NEXT: .cfi_remember_state 192; CHECK-NEXT: and w19, w1, #0x6 193; CHECK-NEXT: mov w0, w19 194; CHECK-NEXT: bl bar 195; CHECK-NEXT: cbnz w19, .LBB9_2 196; CHECK-NEXT: // %bb.1: // %if.end 197; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload 198; CHECK-NEXT: .cfi_def_cfa_offset 0 199; CHECK-NEXT: .cfi_restore w19 200; CHECK-NEXT: .cfi_restore w30 201; CHECK-NEXT: ret 202; CHECK-NEXT: .LBB9_2: // %if.then 203; CHECK-NEXT: .cfi_restore_state 204; CHECK-NEXT: bl foo 205entry: 206 %c = and i32 %a, 6 207 call void @bar(i32 %c) 208 %tobool = icmp eq i32 %c, 0 209 br i1 %tobool, label %if.end, label %if.then 210 211if.then: 212 tail call void @foo() 213 unreachable 214 215if.end: 216 ret void 217} 218