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: adc 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: sbc 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: sbcs x2, x2, x6 102; CHECK-NEXT: sbcs x3, x3, x7 103; CHECK-NEXT: cset w8, lo 104; CHECK-NEXT: eor w4, w8, #0x1 105; CHECK-NEXT: ret 106 %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y) 107 %2 = extractvalue { i256, i1 } %1, 0 108 %3 = extractvalue { i256, i1 } %1, 1 109 %4 = xor i1 %3, true 110 %5 = zext i1 %4 to i8 111 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 112 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 113 ret { i256, i8 } %7 114} 115 116define { i256, i8 } @u256_overflowing_sub(i256 %x, i256 %y) { 117; CHECK-LABEL: u256_overflowing_sub: 118; CHECK: // %bb.0: 119; CHECK-NEXT: subs x0, x0, x4 120; CHECK-NEXT: sbcs x1, x1, x5 121; CHECK-NEXT: sbcs x2, x2, x6 122; CHECK-NEXT: sbcs x3, x3, x7 123; CHECK-NEXT: cset w4, lo 124; CHECK-NEXT: ret 125 %1 = tail call { i256, i1 } @llvm.usub.with.overflow.i256(i256 %x, i256 %y) 126 %2 = extractvalue { i256, i1 } %1, 0 127 %3 = extractvalue { i256, i1 } %1, 1 128 %4 = zext i1 %3 to i8 129 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 130 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 131 ret { i256, i8 } %6 132} 133 134define i256 @u256_saturating_sub(i256 %x, i256 %y) { 135; CHECK-LABEL: u256_saturating_sub: 136; CHECK: // %bb.0: 137; CHECK-NEXT: subs x8, x0, x4 138; CHECK-NEXT: sbcs x9, x1, x5 139; CHECK-NEXT: sbcs x10, x2, x6 140; CHECK-NEXT: sbcs x11, x3, x7 141; CHECK-NEXT: cset w12, lo 142; CHECK-NEXT: cmp w12, #0 143; CHECK-NEXT: csel x0, xzr, x8, ne 144; CHECK-NEXT: csel x1, xzr, x9, ne 145; CHECK-NEXT: csel x2, xzr, x10, ne 146; CHECK-NEXT: csel x3, xzr, x11, ne 147; CHECK-NEXT: ret 148 %1 = tail call i256 @llvm.usub.sat.i256(i256 %x, i256 %y) 149 ret i256 %1 150} 151 152define i256 @i256_add(i256 %x, i256 %y) { 153; CHECK-LABEL: i256_add: 154; CHECK: // %bb.0: 155; CHECK-NEXT: adds x0, x0, x4 156; CHECK-NEXT: adcs x1, x1, x5 157; CHECK-NEXT: adcs x2, x2, x6 158; CHECK-NEXT: adc x3, x3, x7 159; CHECK-NEXT: ret 160 %1 = add i256 %x, %y 161 ret i256 %1 162} 163 164define { i256, i8 } @i256_checked_add(i256 %x, i256 %y) { 165; CHECK-LABEL: i256_checked_add: 166; CHECK: // %bb.0: 167; CHECK-NEXT: adds x0, x0, x4 168; CHECK-NEXT: adcs x1, x1, x5 169; CHECK-NEXT: adcs x2, x2, x6 170; CHECK-NEXT: adcs x3, x3, x7 171; CHECK-NEXT: cset w8, vs 172; CHECK-NEXT: eor w4, w8, #0x1 173; CHECK-NEXT: ret 174 %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y) 175 %2 = extractvalue { i256, i1 } %1, 0 176 %3 = extractvalue { i256, i1 } %1, 1 177 %4 = xor i1 %3, true 178 %5 = zext i1 %4 to i8 179 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 180 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 181 ret { i256, i8 } %7 182} 183 184define { i256, i8 } @i256_overflowing_add(i256 %x, i256 %y) { 185; CHECK-LABEL: i256_overflowing_add: 186; CHECK: // %bb.0: 187; CHECK-NEXT: adds x0, x0, x4 188; CHECK-NEXT: adcs x1, x1, x5 189; CHECK-NEXT: adcs x2, x2, x6 190; CHECK-NEXT: adcs x3, x3, x7 191; CHECK-NEXT: cset w4, vs 192; CHECK-NEXT: ret 193 %1 = tail call { i256, i1 } @llvm.sadd.with.overflow.i256(i256 %x, i256 %y) 194 %2 = extractvalue { i256, i1 } %1, 0 195 %3 = extractvalue { i256, i1 } %1, 1 196 %4 = zext i1 %3 to i8 197 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 198 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 199 ret { i256, i8 } %6 200} 201 202define i256 @i256_saturating_add(i256 %x, i256 %y) { 203; CHECK-LABEL: i256_saturating_add: 204; CHECK: // %bb.0: 205; CHECK-NEXT: adds x8, x0, x4 206; CHECK-NEXT: adcs x9, x1, x5 207; CHECK-NEXT: adcs x10, x2, x6 208; CHECK-NEXT: adcs x11, x3, x7 209; CHECK-NEXT: cset w12, vs 210; CHECK-NEXT: asr x13, x11, #63 211; CHECK-NEXT: cmp w12, #0 212; CHECK-NEXT: csel x0, x13, x8, ne 213; CHECK-NEXT: eor x8, x13, #0x8000000000000000 214; CHECK-NEXT: csel x1, x13, x9, ne 215; CHECK-NEXT: csel x2, x13, x10, ne 216; CHECK-NEXT: csel x3, x8, x11, ne 217; CHECK-NEXT: ret 218 %1 = tail call i256 @llvm.sadd.sat.i256(i256 %x, i256 %y) 219 ret i256 %1 220} 221 222define i256 @i256_sub(i256 %x, i256 %y) { 223; CHECK-LABEL: i256_sub: 224; CHECK: // %bb.0: 225; CHECK-NEXT: subs x0, x0, x4 226; CHECK-NEXT: sbcs x1, x1, x5 227; CHECK-NEXT: sbcs x2, x2, x6 228; CHECK-NEXT: sbc x3, x3, x7 229; CHECK-NEXT: ret 230 %1 = sub i256 %x, %y 231 ret i256 %1 232} 233 234define { i256, i8 } @i256_checked_sub(i256 %x, i256 %y) { 235; CHECK-LABEL: i256_checked_sub: 236; CHECK: // %bb.0: 237; CHECK-NEXT: subs x0, x0, x4 238; CHECK-NEXT: sbcs x1, x1, x5 239; CHECK-NEXT: sbcs x2, x2, x6 240; CHECK-NEXT: sbcs x3, x3, x7 241; CHECK-NEXT: cset w8, vs 242; CHECK-NEXT: eor w4, w8, #0x1 243; CHECK-NEXT: ret 244 %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y) 245 %2 = extractvalue { i256, i1 } %1, 0 246 %3 = extractvalue { i256, i1 } %1, 1 247 %4 = xor i1 %3, true 248 %5 = zext i1 %4 to i8 249 %6 = insertvalue { i256, i8 } undef, i256 %2, 0 250 %7 = insertvalue { i256, i8 } %6, i8 %5, 1 251 ret { i256, i8 } %7 252} 253 254define { i256, i8 } @i256_overflowing_sub(i256 %x, i256 %y) { 255; CHECK-LABEL: i256_overflowing_sub: 256; CHECK: // %bb.0: 257; CHECK-NEXT: subs x0, x0, x4 258; CHECK-NEXT: sbcs x1, x1, x5 259; CHECK-NEXT: sbcs x2, x2, x6 260; CHECK-NEXT: sbcs x3, x3, x7 261; CHECK-NEXT: cset w4, vs 262; CHECK-NEXT: ret 263 %1 = tail call { i256, i1 } @llvm.ssub.with.overflow.i256(i256 %x, i256 %y) 264 %2 = extractvalue { i256, i1 } %1, 0 265 %3 = extractvalue { i256, i1 } %1, 1 266 %4 = zext i1 %3 to i8 267 %5 = insertvalue { i256, i8 } undef, i256 %2, 0 268 %6 = insertvalue { i256, i8 } %5, i8 %4, 1 269 ret { i256, i8 } %6 270} 271 272define i256 @i256_saturating_sub(i256 %x, i256 %y) { 273; CHECK-LABEL: i256_saturating_sub: 274; CHECK: // %bb.0: 275; CHECK-NEXT: subs x8, x0, x4 276; CHECK-NEXT: sbcs x9, x1, x5 277; CHECK-NEXT: sbcs x10, x2, x6 278; CHECK-NEXT: sbcs x11, x3, x7 279; CHECK-NEXT: cset w12, vs 280; CHECK-NEXT: asr x13, x11, #63 281; CHECK-NEXT: cmp w12, #0 282; CHECK-NEXT: csel x0, x13, x8, ne 283; CHECK-NEXT: eor x8, x13, #0x8000000000000000 284; CHECK-NEXT: csel x1, x13, x9, ne 285; CHECK-NEXT: csel x2, x13, x10, ne 286; CHECK-NEXT: csel x3, x8, x11, ne 287; CHECK-NEXT: ret 288 %1 = tail call i256 @llvm.ssub.sat.i256(i256 %x, i256 %y) 289 ret i256 %1 290} 291