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