1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s 3 4declare { i256, i1 } @llvm.uadd.with.overflow.i256(i256, i256) 5declare i256 @llvm.uadd.sat.i256(i256, i256) 6 7declare { i256, i1 } @llvm.usub.with.overflow.i256(i256, i256) 8declare i256 @llvm.usub.sat.i256(i256, i256) 9 10declare { i256, i1 } @llvm.sadd.with.overflow.i256(i256, i256) 11declare i256 @llvm.sadd.sat.i256(i256, i256) 12 13declare { i256, i1 } @llvm.ssub.with.overflow.i256(i256, i256) 14declare i256 @llvm.ssub.sat.i256(i256, i256) 15 16define i256 @u256_add(i256 %x, i256 %y) { 17; CHECK-LABEL: u256_add: 18; CHECK: // %bb.0: 19; CHECK-NEXT: adds x0, x0, x4 20; CHECK-NEXT: adcs x1, x1, x5 21; CHECK-NEXT: adcs x2, x2, x6 22; CHECK-NEXT: adcs x3, x3, x7 23; CHECK-NEXT: ret 24 %1 = add i256 %x, %y 25 ret i256 %1 26} 27 28define { i256, i8 } @u256_checked_add(i256 %x, i256 %y) { 29; CHECK-LABEL: u256_checked_add: 30; CHECK: // %bb.0: 31; CHECK-NEXT: adds x0, x0, x4 32; CHECK-NEXT: adcs x1, x1, x5 33; CHECK-NEXT: adcs x2, x2, x6 34; CHECK-NEXT: adcs x3, x3, x7 35; CHECK-NEXT: cset w8, hs 36; CHECK-NEXT: eor w4, w8, #0x1 37; CHECK-NEXT: ret 38 %1 = tail call { i256, i1 } @llvm.uadd.with.overflow.i256(i256 %x, i256 %y) 39 %2 = extractvalue { i256, i1 } %1, 0 40 %3 = extractvalue { i256, i1 } %1, 1 41 %4 = xor i1 %3, true 42 %5 = zext i1 %4 to i8 43 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 44 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 45 ret { i256, i8 } %7 46} 47 48define { i256, i8 } @u256_overflowing_add(i256 %x, i256 %y) { 49; CHECK-LABEL: u256_overflowing_add: 50; CHECK: // %bb.0: 51; CHECK-NEXT: adds x0, x0, x4 52; CHECK-NEXT: adcs x1, x1, x5 53; CHECK-NEXT: adcs x2, x2, x6 54; CHECK-NEXT: adcs x3, x3, x7 55; CHECK-NEXT: cset w4, hs 56; CHECK-NEXT: ret 57 %1 = tail call { i256, i1 } @llvm.uadd.with.overflow.i256(i256 %x, i256 %y) 58 %2 = extractvalue { i256, i1 } %1, 0 59 %3 = extractvalue { i256, i1 } %1, 1 60 %4 = zext i1 %3 to i8 61 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 62 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 63 ret { i256, i8 } %6 64} 65 66define i256 @u256_saturating_add(i256 %x, i256 %y) { 67; CHECK-LABEL: u256_saturating_add: 68; CHECK: // %bb.0: 69; CHECK-NEXT: adds x8, x0, x4 70; CHECK-NEXT: adcs x9, x1, x5 71; CHECK-NEXT: adcs x10, x2, x6 72; CHECK-NEXT: adcs x11, x3, x7 73; CHECK-NEXT: cset w12, hs 74; CHECK-NEXT: cmp w12, #0 75; CHECK-NEXT: csinv x0, x8, xzr, eq 76; CHECK-NEXT: csinv x1, x9, xzr, eq 77; CHECK-NEXT: csinv x2, x10, xzr, eq 78; CHECK-NEXT: csinv x3, x11, xzr, eq 79; CHECK-NEXT: ret 80 %1 = tail call i256 @llvm.uadd.sat.i256(i256 %x, i256 %y) 81 ret i256 %1 82} 83 84define i256 @u256_sub(i256 %x, i256 %y) { 85; CHECK-LABEL: u256_sub: 86; CHECK: // %bb.0: 87; CHECK-NEXT: subs x0, x0, x4 88; CHECK-NEXT: sbcs x1, x1, x5 89; CHECK-NEXT: sbcs x2, x2, x6 90; CHECK-NEXT: sbcs x3, x3, x7 91; CHECK-NEXT: ret 92 %1 = sub i256 %x, %y 93 ret i256 %1 94} 95 96define { i256, i8 } @u256_checked_sub(i256 %x, i256 %y) { 97; CHECK-LABEL: u256_checked_sub: 98; CHECK: // %bb.0: 99; CHECK-NEXT: subs x0, x0, x4 100; CHECK-NEXT: sbcs x1, x1, x5 101; CHECK-NEXT: cset w8, lo 102; CHECK-NEXT: cmp wzr, w8 103; CHECK-NEXT: sbcs x2, x2, x6 104; CHECK-NEXT: cset w8, lo 105; CHECK-NEXT: cmp wzr, w8 106; CHECK-NEXT: sbcs x3, x3, x7 107; CHECK-NEXT: cset w8, lo 108; CHECK-NEXT: eor w4, w8, #0x1 109; CHECK-NEXT: ret 110 %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y) 111 %2 = extractvalue { i256, i1 } %1, 0 112 %3 = extractvalue { i256, i1 } %1, 1 113 %4 = xor i1 %3, true 114 %5 = zext i1 %4 to i8 115 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 116 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 117 ret { i256, i8 } %7 118} 119 120define { i256, i8 } @u256_overflowing_sub(i256 %x, i256 %y) { 121; CHECK-LABEL: u256_overflowing_sub: 122; CHECK: // %bb.0: 123; CHECK-NEXT: subs x0, x0, x4 124; CHECK-NEXT: sbcs x1, x1, x5 125; CHECK-NEXT: cset w8, lo 126; CHECK-NEXT: cmp wzr, w8 127; CHECK-NEXT: sbcs x2, x2, x6 128; CHECK-NEXT: cset w8, lo 129; CHECK-NEXT: cmp wzr, w8 130; CHECK-NEXT: sbcs x3, x3, x7 131; CHECK-NEXT: cset w4, lo 132; CHECK-NEXT: ret 133 %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y) 134 %2 = extractvalue { i256, i1 } %1, 0 135 %3 = extractvalue { i256, i1 } %1, 1 136 %4 = zext i1 %3 to i8 137 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 138 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 139 ret { i256, i8 } %6 140} 141 142define i256 @u256_saturating_sub(i256 %x, i256 %y) { 143; CHECK-LABEL: u256_saturating_sub: 144; CHECK: // %bb.0: 145; CHECK-NEXT: subs x8, x0, x4 146; CHECK-NEXT: sbcs x9, x1, x5 147; CHECK-NEXT: sbcs x10, x2, x6 148; CHECK-NEXT: sbcs x11, x3, x7 149; CHECK-NEXT: cset w12, lo 150; CHECK-NEXT: cmp w12, #0 151; CHECK-NEXT: csel x0, xzr, x8, ne 152; CHECK-NEXT: csel x1, xzr, x9, ne 153; CHECK-NEXT: csel x2, xzr, x10, ne 154; CHECK-NEXT: csel x3, xzr, x11, ne 155; CHECK-NEXT: ret 156 %1 = tail call i256 @llvm.usub.sat.i256(i256 %x, i256 %y) 157 ret i256 %1 158} 159 160define i256 @i256_add(i256 %x, i256 %y) { 161; CHECK-LABEL: i256_add: 162; CHECK: // %bb.0: 163; CHECK-NEXT: adds x0, x0, x4 164; CHECK-NEXT: adcs x1, x1, x5 165; CHECK-NEXT: adcs x2, x2, x6 166; CHECK-NEXT: adcs x3, x3, x7 167; CHECK-NEXT: ret 168 %1 = add i256 %x, %y 169 ret i256 %1 170} 171 172define { i256, i8 } @i256_checked_add(i256 %x, i256 %y) { 173; CHECK-LABEL: i256_checked_add: 174; CHECK: // %bb.0: 175; CHECK-NEXT: adds x0, x0, x4 176; CHECK-NEXT: adcs x1, x1, x5 177; CHECK-NEXT: adcs x2, x2, x6 178; CHECK-NEXT: adcs x3, x3, x7 179; CHECK-NEXT: cset w8, vs 180; CHECK-NEXT: eor w4, w8, #0x1 181; CHECK-NEXT: ret 182 %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y) 183 %2 = extractvalue { i256, i1 } %1, 0 184 %3 = extractvalue { i256, i1 } %1, 1 185 %4 = xor i1 %3, true 186 %5 = zext i1 %4 to i8 187 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 188 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 189 ret { i256, i8 } %7 190} 191 192define { i256, i8 } @i256_overflowing_add(i256 %x, i256 %y) { 193; CHECK-LABEL: i256_overflowing_add: 194; CHECK: // %bb.0: 195; CHECK-NEXT: adds x0, x0, x4 196; CHECK-NEXT: adcs x1, x1, x5 197; CHECK-NEXT: adcs x2, x2, x6 198; CHECK-NEXT: adcs x3, x3, x7 199; CHECK-NEXT: cset w4, vs 200; CHECK-NEXT: ret 201 %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y) 202 %2 = extractvalue { i256, i1 } %1, 0 203 %3 = extractvalue { i256, i1 } %1, 1 204 %4 = zext i1 %3 to i8 205 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 206 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 207 ret { i256, i8 } %6 208} 209 210define i256 @i256_saturating_add(i256 %x, i256 %y) { 211; CHECK-LABEL: i256_saturating_add: 212; CHECK: // %bb.0: 213; CHECK-NEXT: adds x8, x0, x4 214; CHECK-NEXT: adcs x9, x1, x5 215; CHECK-NEXT: adcs x10, x2, x6 216; CHECK-NEXT: adcs x11, x3, x7 217; CHECK-NEXT: cset w12, vs 218; CHECK-NEXT: asr x13, x11, #63 219; CHECK-NEXT: cmp w12, #0 220; CHECK-NEXT: csel x0, x13, x8, ne 221; CHECK-NEXT: eor x8, x13, #0x8000000000000000 222; CHECK-NEXT: csel x1, x13, x9, ne 223; CHECK-NEXT: csel x2, x13, x10, ne 224; CHECK-NEXT: csel x3, x8, x11, ne 225; CHECK-NEXT: ret 226 %1 = tail call i256 @llvm.sadd.sat.i256(i256 %x, i256 %y) 227 ret i256 %1 228} 229 230define i256 @i256_sub(i256 %x, i256 %y) { 231; CHECK-LABEL: i256_sub: 232; CHECK: // %bb.0: 233; CHECK-NEXT: subs x0, x0, x4 234; CHECK-NEXT: sbcs x1, x1, x5 235; CHECK-NEXT: sbcs x2, x2, x6 236; CHECK-NEXT: sbcs x3, x3, x7 237; CHECK-NEXT: ret 238 %1 = sub i256 %x, %y 239 ret i256 %1 240} 241 242define { i256, i8 } @i256_checked_sub(i256 %x, i256 %y) { 243; CHECK-LABEL: i256_checked_sub: 244; CHECK: // %bb.0: 245; CHECK-NEXT: subs x0, x0, x4 246; CHECK-NEXT: sbcs x1, x1, x5 247; CHECK-NEXT: cset w8, lo 248; CHECK-NEXT: cmp wzr, w8 249; CHECK-NEXT: sbcs x2, x2, x6 250; CHECK-NEXT: cset w8, lo 251; CHECK-NEXT: cmp wzr, w8 252; CHECK-NEXT: sbcs x3, x3, x7 253; CHECK-NEXT: cset w8, vs 254; CHECK-NEXT: eor w4, w8, #0x1 255; CHECK-NEXT: ret 256 %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y) 257 %2 = extractvalue { i256, i1 } %1, 0 258 %3 = extractvalue { i256, i1 } %1, 1 259 %4 = xor i1 %3, true 260 %5 = zext i1 %4 to i8 261 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 262 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 263 ret { i256, i8 } %7 264} 265 266define { i256, i8 } @i256_overflowing_sub(i256 %x, i256 %y) { 267; CHECK-LABEL: i256_overflowing_sub: 268; CHECK: // %bb.0: 269; CHECK-NEXT: subs x0, x0, x4 270; CHECK-NEXT: sbcs x1, x1, x5 271; CHECK-NEXT: cset w8, lo 272; CHECK-NEXT: cmp wzr, w8 273; CHECK-NEXT: sbcs x2, x2, x6 274; CHECK-NEXT: cset w8, lo 275; CHECK-NEXT: cmp wzr, w8 276; CHECK-NEXT: sbcs x3, x3, x7 277; CHECK-NEXT: cset w4, vs 278; CHECK-NEXT: ret 279 %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y) 280 %2 = extractvalue { i256, i1 } %1, 0 281 %3 = extractvalue { i256, i1 } %1, 1 282 %4 = zext i1 %3 to i8 283 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 284 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 285 ret { i256, i8 } %6 286} 287 288define i256 @i256_saturating_sub(i256 %x, i256 %y) { 289; CHECK-LABEL: i256_saturating_sub: 290; CHECK: // %bb.0: 291; CHECK-NEXT: subs x8, x0, x4 292; CHECK-NEXT: sbcs x9, x1, x5 293; CHECK-NEXT: sbcs x10, x2, x6 294; CHECK-NEXT: sbcs x11, x3, x7 295; CHECK-NEXT: cset w12, vs 296; CHECK-NEXT: asr x13, x11, #63 297; CHECK-NEXT: cmp w12, #0 298; CHECK-NEXT: csel x0, x13, x8, ne 299; CHECK-NEXT: eor x8, x13, #0x8000000000000000 300; CHECK-NEXT: csel x1, x13, x9, ne 301; CHECK-NEXT: csel x2, x13, x10, ne 302; CHECK-NEXT: csel x3, x8, x11, ne 303; CHECK-NEXT: ret 304 %1 = tail call i256 @llvm.ssub.sat.i256(i256 %x, i256 %y) 305 ret i256 %1 306} 307