1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=arm64-eabi -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-SD 3; RUN: llc < %s -mtriple=arm64-eabi -global-isel -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-GI 4 5define zeroext i1 @saddo1.i32.unused(i32 %v1, i32 %v2, ptr %res) { 6; CHECK-LABEL: saddo1.i32.unused: 7; CHECK: // %bb.0: // %entry 8; CHECK-NEXT: add w8, w0, w1 9; CHECK-NEXT: mov w0, #1 // =0x1 10; CHECK-NEXT: str w8, [x2] 11; CHECK-NEXT: ret 12entry: 13 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 14 %obit = extractvalue {i32, i1} %t, 1 15 %val = extractvalue {i32, i1} %t, 0 16 store i32 %val, ptr %res 17 ret i1 1 18} 19 20define zeroext i1 @saddo1.i32.fold(i32 %v1, i32 %v2, ptr %res) { 21; CHECK-LABEL: saddo1.i32.fold: 22; CHECK: // %bb.0: // %entry 23; CHECK-NEXT: mov w8, #20 // =0x14 24; CHECK-NEXT: mov w0, wzr 25; CHECK-NEXT: str w8, [x2] 26; CHECK-NEXT: ret 27entry: 28 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 9, i32 11) 29 %val = extractvalue {i32, i1} %t, 0 30 %obit = extractvalue {i32, i1} %t, 1 31 store i32 %val, ptr %res 32 ret i1 %obit 33} 34 35define zeroext i1 @saddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) { 36; CHECK-LABEL: saddo1.i32.addzero: 37; CHECK: // %bb.0: // %entry 38; CHECK-NEXT: mov w8, w0 39; CHECK-NEXT: mov w0, wzr 40; CHECK-NEXT: str w8, [x2] 41; CHECK-NEXT: ret 42entry: 43 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 0) 44 %val = extractvalue {i32, i1} %t, 0 45 %obit = extractvalue {i32, i1} %t, 1 46 store i32 %val, ptr %res 47 ret i1 %obit 48} 49 50define zeroext i1 @uaddo1.i32.addzero(i32 %v1, i32 %v2, ptr %res) { 51; CHECK-LABEL: uaddo1.i32.addzero: 52; CHECK: // %bb.0: // %entry 53; CHECK-NEXT: mov w8, w0 54; CHECK-NEXT: mov w0, wzr 55; CHECK-NEXT: str w8, [x2] 56; CHECK-NEXT: ret 57entry: 58 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 0) 59 %val = extractvalue {i32, i1} %t, 0 60 %obit = extractvalue {i32, i1} %t, 1 61 store i32 %val, ptr %res 62 ret i1 %obit 63} 64 65define i32 @saddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) { 66; CHECK-LABEL: saddo.select.i64: 67; CHECK: // %bb.0: // %entry 68; CHECK-NEXT: mov w0, w1 69; CHECK-NEXT: ret 70entry: 71 %lhs = and i64 %v4, 12 72 %rhs = and i64 %v5, 13 73 %t = call {i64, i1} @llvm.sadd.with.overflow.64(i64 %lhs, i64 %rhs) 74 %obit = extractvalue {i64, i1} %t, 1 75 %ret = select i1 %obit, i32 %v1, i32 %v2 76 ret i32 %ret 77} 78 79define i32 @uaddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) { 80; CHECK-LABEL: uaddo.select.i64: 81; CHECK: // %bb.0: // %entry 82; CHECK-NEXT: mov w0, w1 83; CHECK-NEXT: ret 84entry: 85 %lhs = and i64 %v4, 9 86 %rhs = and i64 %v5, 10 87 %t = call {i64, i1} @llvm.uadd.with.overflow.64(i64 %lhs, i64 %rhs) 88 %obit = extractvalue {i64, i1} %t, 1 89 %ret = select i1 %obit, i32 %v1, i32 %v2 90 ret i32 %ret 91} 92 93define zeroext i1 @saddo.canon.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 94; CHECK-LABEL: saddo.canon.i32: 95; CHECK: // %bb.0: // %entry 96; CHECK-NEXT: mov w0, wzr 97; CHECK-NEXT: str w4, [x5] 98; CHECK-NEXT: ret 99entry: 100 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 0, i32 %v5) 101 %val = extractvalue {i32, i1} %t, 0 102 %obit = extractvalue {i32, i1} %t, 1 103 store i32 %val, ptr %res 104 ret i1 %obit 105} 106define zeroext i1 @saddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 107; CHECK-SD-LABEL: saddo.add.i32: 108; CHECK-SD: // %bb.0: // %entry 109; CHECK-SD-NEXT: add w8, w4, #100 110; CHECK-SD-NEXT: subs w8, w8, #100 111; CHECK-SD-NEXT: cset w0, vs 112; CHECK-SD-NEXT: str w8, [x5] 113; CHECK-SD-NEXT: ret 114; 115; CHECK-GI-LABEL: saddo.add.i32: 116; CHECK-GI: // %bb.0: // %entry 117; CHECK-GI-NEXT: mov w0, wzr 118; CHECK-GI-NEXT: str w4, [x5] 119; CHECK-GI-NEXT: ret 120entry: 121 %lhs = add nsw i32 %v5, 100 122 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %lhs, i32 -100) 123 %val = extractvalue {i32, i1} %t, 0 124 %obit = extractvalue {i32, i1} %t, 1 125 store i32 %val, ptr %res 126 ret i1 %obit 127} 128 129define zeroext i1 @uaddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 130; CHECK-SD-LABEL: uaddo.add.i32: 131; CHECK-SD: // %bb.0: // %entry 132; CHECK-SD-NEXT: add w8, w4, #5 133; CHECK-SD-NEXT: adds w8, w8, #5 134; CHECK-SD-NEXT: cset w0, hs 135; CHECK-SD-NEXT: str w8, [x5] 136; CHECK-SD-NEXT: ret 137; 138; CHECK-GI-LABEL: uaddo.add.i32: 139; CHECK-GI: // %bb.0: // %entry 140; CHECK-GI-NEXT: adds w8, w4, #10 141; CHECK-GI-NEXT: cset w0, hs 142; CHECK-GI-NEXT: str w8, [x5] 143; CHECK-GI-NEXT: ret 144entry: 145 %lhs = add nuw i32 %v5, 5 146 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %lhs, i32 5) 147 %val = extractvalue {i32, i1} %t, 0 148 %obit = extractvalue {i32, i1} %t, 1 149 store i32 %val, ptr %res 150 ret i1 %obit 151} 152 153define zeroext i1 @uaddo.negative.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 154; CHECK-LABEL: uaddo.negative.i32: 155; CHECK: // %bb.0: // %entry 156; CHECK-NEXT: adds w8, w3, #5 157; CHECK-NEXT: cset w0, hs 158; CHECK-NEXT: str w8, [x5] 159; CHECK-NEXT: ret 160entry: 161 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v4, i32 5) 162 %val = extractvalue {i32, i1} %t, 0 163 %obit = extractvalue {i32, i1} %t, 1 164 store i32 %val, ptr %res 165 ret i1 %obit 166} 167 168define i32 @saddo.always.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 169; CHECK-LABEL: saddo.always.i8: 170; CHECK: // %bb.0: // %entry 171; CHECK-NEXT: mov w0, w1 172; CHECK-NEXT: ret 173entry: 174 %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 255, i8 254) 175 %obit = extractvalue {i8, i1} %t, 1 176 %ret = select i1 %obit, i32 %v1, i32 %v2 177 ret i32 %ret 178} 179 180define i32 @uaddo.never.i8(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { 181; CHECK-LABEL: uaddo.never.i8: 182; CHECK: // %bb.0: // %entry 183; CHECK-NEXT: mov w0, w1 184; CHECK-NEXT: ret 185entry: 186 %t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 2, i8 1) 187 %obit = extractvalue {i8, i1} %t, 1 188 %ret = select i1 %obit, i32 %v1, i32 %v2 189 ret i32 %ret 190} 191 192 193declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone 194declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) nounwind readnone 195declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone 196declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone 197declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone 198declare {i16, i1} @llvm.uadd.with.overflow.i16(i16, i16) nounwind readnone 199declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone 200declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone 201declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone 202declare {i16, i1} @llvm.ssub.with.overflow.i16(i16, i16) nounwind readnone 203declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone 204declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone 205declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone 206declare {i16, i1} @llvm.usub.with.overflow.i16(i16, i16) nounwind readnone 207declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone 208declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone 209declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone 210declare {i16, i1} @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone 211declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone 212declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone 213declare {i8, i1} @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone 214declare {i16, i1} @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone 215declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone 216declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone 217