1; RUN: llc -debugify-and-strip-all-safe < %s -O3 -mtriple=aarch64-eabi -verify-machineinstrs | FileCheck %s 2 3target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 4target triple = "aarch64-linaro-linux-gnueabi" 5 6; CMN is an alias of ADDS. 7; CHECK-LABEL: test_add_cbz: 8; CHECK: cmn w0, w1 9; CHECK: b.eq 10; CHECK: ret 11define void @test_add_cbz(i32 %a, i32 %b, i32* %ptr) { 12 %c = add nsw i32 %a, %b 13 %d = icmp ne i32 %c, 0 14 br i1 %d, label %L1, label %L2 15L1: 16 store i32 0, i32* %ptr, align 4 17 ret void 18L2: 19 store i32 1, i32* %ptr, align 4 20 ret void 21} 22 23; CHECK-LABEL: test_add_cbz_multiple_use: 24; CHECK: adds 25; CHECK: b.eq 26; CHECK: ret 27define void @test_add_cbz_multiple_use(i32 %a, i32 %b, i32* %ptr) { 28 %c = add nsw i32 %a, %b 29 %d = icmp ne i32 %c, 0 30 br i1 %d, label %L1, label %L2 31L1: 32 store i32 0, i32* %ptr, align 4 33 ret void 34L2: 35 store i32 %c, i32* %ptr, align 4 36 ret void 37} 38 39; CHECK-LABEL: test_add_cbz_64: 40; CHECK: cmn x0, x1 41; CHECK: b.eq 42define void @test_add_cbz_64(i64 %a, i64 %b, i64* %ptr) { 43 %c = add nsw i64 %a, %b 44 %d = icmp ne i64 %c, 0 45 br i1 %d, label %L1, label %L2 46L1: 47 store i64 0, i64* %ptr, align 4 48 ret void 49L2: 50 store i64 1, i64* %ptr, align 4 51 ret void 52} 53 54; CHECK-LABEL: test_and_cbz: 55; CHECK: tst w0, #0x6 56; CHECK: b.eq 57define void @test_and_cbz(i32 %a, i32* %ptr) { 58 %c = and i32 %a, 6 59 %d = icmp ne i32 %c, 0 60 br i1 %d, label %L1, label %L2 61L1: 62 store i32 0, i32* %ptr, align 4 63 ret void 64L2: 65 store i32 1, i32* %ptr, align 4 66 ret void 67} 68 69; CHECK-LABEL: test_bic_cbnz: 70; CHECK: bics wzr, w1, w0 71; CHECK: b.ne 72define void @test_bic_cbnz(i32 %a, i32 %b, i32* %ptr) { 73 %c = and i32 %a, %b 74 %d = icmp eq i32 %c, %b 75 br i1 %d, label %L1, label %L2 76L1: 77 store i32 0, i32* %ptr, align 4 78 ret void 79L2: 80 store i32 1, i32* %ptr, align 4 81 ret void 82} 83 84; CHECK-LABEL: test_add_tbz: 85; CHECK: adds 86; CHECK: b.pl 87; CHECK: ret 88define void @test_add_tbz(i32 %a, i32 %b, i32* %ptr) { 89entry: 90 %add = add nsw i32 %a, %b 91 %cmp36 = icmp sge i32 %add, 0 92 br i1 %cmp36, label %L2, label %L1 93L1: 94 store i32 %add, i32* %ptr, align 8 95 br label %L2 96L2: 97 ret void 98} 99 100; CHECK-LABEL: test_subs_tbz: 101; CHECK: subs 102; CHECK: b.pl 103; CHECK: ret 104define void @test_subs_tbz(i32 %a, i32 %b, i32* %ptr) { 105entry: 106 %sub = sub nsw i32 %a, %b 107 %cmp36 = icmp sge i32 %sub, 0 108 br i1 %cmp36, label %L2, label %L1 109L1: 110 store i32 %sub, i32* %ptr, align 8 111 br label %L2 112L2: 113 ret void 114} 115 116; CHECK-LABEL: test_add_tbnz 117; CHECK: adds 118; CHECK: b.mi 119; CHECK: ret 120define void @test_add_tbnz(i32 %a, i32 %b, i32* %ptr) { 121entry: 122 %add = add nsw i32 %a, %b 123 %cmp36 = icmp slt i32 %add, 0 124 br i1 %cmp36, label %L2, label %L1 125L1: 126 store i32 %add, i32* %ptr, align 8 127 br label %L2 128L2: 129 ret void 130} 131 132; CHECK-LABEL: test_subs_tbnz 133; CHECK: subs 134; CHECK: b.mi 135; CHECK: ret 136define void @test_subs_tbnz(i32 %a, i32 %b, i32* %ptr) { 137entry: 138 %sub = sub nsw i32 %a, %b 139 %cmp36 = icmp slt i32 %sub, 0 140 br i1 %cmp36, label %L2, label %L1 141L1: 142 store i32 %sub, i32* %ptr, align 8 143 br label %L2 144L2: 145 ret void 146} 147 148declare void @foo() 149declare void @bar(i32) 150 151; Don't transform since the call will clobber the NZCV bits. 152; CHECK-LABEL: test_call_clobber: 153; CHECK: and w[[DST:[0-9]+]], w1, #0x6 154; CHECK: bl bar 155; CHECK: cbnz w[[DST]] 156define void @test_call_clobber(i32 %unused, i32 %a) { 157entry: 158 %c = and i32 %a, 6 159 call void @bar(i32 %c) 160 %tobool = icmp eq i32 %c, 0 161 br i1 %tobool, label %if.end, label %if.then 162 163if.then: 164 tail call void @foo() 165 unreachable 166 167if.end: 168 ret void 169} 170