1; RUN: llc < %s -march=arm64 -aarch64-atomic-cfg-tidy=0 | FileCheck %s 2 3; 4; Get the actual value of the overflow bit. 5; 6define i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) { 7entry: 8; CHECK-LABEL: saddo.i32 9; CHECK: adds w8, w0, w1 10; CHECK-NEXT: cset w0, vs 11 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 12 %val = extractvalue {i32, i1} %t, 0 13 %obit = extractvalue {i32, i1} %t, 1 14 store i32 %val, i32* %res 15 ret i1 %obit 16} 17 18define i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) { 19entry: 20; CHECK-LABEL: saddo.i64 21; CHECK: adds x8, x0, x1 22; CHECK-NEXT: cset w0, vs 23 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 24 %val = extractvalue {i64, i1} %t, 0 25 %obit = extractvalue {i64, i1} %t, 1 26 store i64 %val, i64* %res 27 ret i1 %obit 28} 29 30define i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) { 31entry: 32; CHECK-LABEL: uaddo.i32 33; CHECK: adds w8, w0, w1 34; CHECK-NEXT: cset w0, hs 35 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 36 %val = extractvalue {i32, i1} %t, 0 37 %obit = extractvalue {i32, i1} %t, 1 38 store i32 %val, i32* %res 39 ret i1 %obit 40} 41 42define i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) { 43entry: 44; CHECK-LABEL: uaddo.i64 45; CHECK: adds x8, x0, x1 46; CHECK-NEXT: cset w0, hs 47 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 48 %val = extractvalue {i64, i1} %t, 0 49 %obit = extractvalue {i64, i1} %t, 1 50 store i64 %val, i64* %res 51 ret i1 %obit 52} 53 54define i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) { 55entry: 56; CHECK-LABEL: ssubo.i32 57; CHECK: subs w8, w0, w1 58; CHECK-NEXT: cset w0, vs 59 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 60 %val = extractvalue {i32, i1} %t, 0 61 %obit = extractvalue {i32, i1} %t, 1 62 store i32 %val, i32* %res 63 ret i1 %obit 64} 65 66define i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) { 67entry: 68; CHECK-LABEL: ssubo.i64 69; CHECK: subs x8, x0, x1 70; CHECK-NEXT: cset w0, vs 71 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 72 %val = extractvalue {i64, i1} %t, 0 73 %obit = extractvalue {i64, i1} %t, 1 74 store i64 %val, i64* %res 75 ret i1 %obit 76} 77 78define i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) { 79entry: 80; CHECK-LABEL: usubo.i32 81; CHECK: subs w8, w0, w1 82; CHECK-NEXT: cset w0, lo 83 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 84 %val = extractvalue {i32, i1} %t, 0 85 %obit = extractvalue {i32, i1} %t, 1 86 store i32 %val, i32* %res 87 ret i1 %obit 88} 89 90define i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) { 91entry: 92; CHECK-LABEL: usubo.i64 93; CHECK: subs x8, x0, x1 94; CHECK-NEXT: cset w0, lo 95 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 96 %val = extractvalue {i64, i1} %t, 0 97 %obit = extractvalue {i64, i1} %t, 1 98 store i64 %val, i64* %res 99 ret i1 %obit 100} 101 102define i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) { 103entry: 104; CHECK-LABEL: smulo.i32 105; CHECK: smull x8, w0, w1 106; CHECK-NEXT: lsr x9, x8, #32 107; CHECK-NEXT: cmp w9, w8, asr #31 108; CHECK-NEXT: cset w0, ne 109 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 110 %val = extractvalue {i32, i1} %t, 0 111 %obit = extractvalue {i32, i1} %t, 1 112 store i32 %val, i32* %res 113 ret i1 %obit 114} 115 116define i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) { 117entry: 118; CHECK-LABEL: smulo.i64 119; CHECK: mul x8, x0, x1 120; CHECK-NEXT: smulh x9, x0, x1 121; CHECK-NEXT: cmp x9, x8, asr #63 122; CHECK-NEXT: cset w0, ne 123 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 124 %val = extractvalue {i64, i1} %t, 0 125 %obit = extractvalue {i64, i1} %t, 1 126 store i64 %val, i64* %res 127 ret i1 %obit 128} 129 130define i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) { 131entry: 132; CHECK-LABEL: umulo.i32 133; CHECK: umull x8, w0, w1 134; CHECK-NEXT: cmp xzr, x8, lsr #32 135; CHECK-NEXT: cset w0, ne 136 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 137 %val = extractvalue {i32, i1} %t, 0 138 %obit = extractvalue {i32, i1} %t, 1 139 store i32 %val, i32* %res 140 ret i1 %obit 141} 142 143define i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) { 144entry: 145; CHECK-LABEL: umulo.i64 146; CHECK: umulh x8, x0, x1 147; CHECK-NEXT: cmp xzr, x8 148; CHECK-NEXT: cset w8, ne 149; CHECK-NEXT: mul x9, x0, x1 150 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 151 %val = extractvalue {i64, i1} %t, 0 152 %obit = extractvalue {i64, i1} %t, 1 153 store i64 %val, i64* %res 154 ret i1 %obit 155} 156 157 158; 159; Check the use of the overflow bit in combination with a select instruction. 160; 161define i32 @saddo.select.i32(i32 %v1, i32 %v2) { 162entry: 163; CHECK-LABEL: saddo.select.i32 164; CHECK: cmn w0, w1 165; CHECK-NEXT: csel w0, w0, w1, vs 166 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 167 %obit = extractvalue {i32, i1} %t, 1 168 %ret = select i1 %obit, i32 %v1, i32 %v2 169 ret i32 %ret 170} 171 172define i64 @saddo.select.i64(i64 %v1, i64 %v2) { 173entry: 174; CHECK-LABEL: saddo.select.i64 175; CHECK: cmn x0, x1 176; CHECK-NEXT: csel x0, x0, x1, vs 177 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 178 %obit = extractvalue {i64, i1} %t, 1 179 %ret = select i1 %obit, i64 %v1, i64 %v2 180 ret i64 %ret 181} 182 183define i32 @uaddo.select.i32(i32 %v1, i32 %v2) { 184entry: 185; CHECK-LABEL: uaddo.select.i32 186; CHECK: cmn w0, w1 187; CHECK-NEXT: csel w0, w0, w1, hs 188 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 189 %obit = extractvalue {i32, i1} %t, 1 190 %ret = select i1 %obit, i32 %v1, i32 %v2 191 ret i32 %ret 192} 193 194define i64 @uaddo.select.i64(i64 %v1, i64 %v2) { 195entry: 196; CHECK-LABEL: uaddo.select.i64 197; CHECK: cmn x0, x1 198; CHECK-NEXT: csel x0, x0, x1, hs 199 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 200 %obit = extractvalue {i64, i1} %t, 1 201 %ret = select i1 %obit, i64 %v1, i64 %v2 202 ret i64 %ret 203} 204 205define i32 @ssubo.select.i32(i32 %v1, i32 %v2) { 206entry: 207; CHECK-LABEL: ssubo.select.i32 208; CHECK: cmp w0, w1 209; CHECK-NEXT: csel w0, w0, w1, vs 210 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 211 %obit = extractvalue {i32, i1} %t, 1 212 %ret = select i1 %obit, i32 %v1, i32 %v2 213 ret i32 %ret 214} 215 216define i64 @ssubo.select.i64(i64 %v1, i64 %v2) { 217entry: 218; CHECK-LABEL: ssubo.select.i64 219; CHECK: cmp x0, x1 220; CHECK-NEXT: csel x0, x0, x1, vs 221 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 222 %obit = extractvalue {i64, i1} %t, 1 223 %ret = select i1 %obit, i64 %v1, i64 %v2 224 ret i64 %ret 225} 226 227define i32 @usubo.select.i32(i32 %v1, i32 %v2) { 228entry: 229; CHECK-LABEL: usubo.select.i32 230; CHECK: cmp w0, w1 231; CHECK-NEXT: csel w0, w0, w1, lo 232 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 233 %obit = extractvalue {i32, i1} %t, 1 234 %ret = select i1 %obit, i32 %v1, i32 %v2 235 ret i32 %ret 236} 237 238define i64 @usubo.select.i64(i64 %v1, i64 %v2) { 239entry: 240; CHECK-LABEL: usubo.select.i64 241; CHECK: cmp x0, x1 242; CHECK-NEXT: csel x0, x0, x1, lo 243 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 244 %obit = extractvalue {i64, i1} %t, 1 245 %ret = select i1 %obit, i64 %v1, i64 %v2 246 ret i64 %ret 247} 248 249define i32 @smulo.select.i32(i32 %v1, i32 %v2) { 250entry: 251; CHECK-LABEL: smulo.select.i32 252; CHECK: smull x8, w0, w1 253; CHECK-NEXT: lsr x9, x8, #32 254; CHECK-NEXT: cmp w9, w8, asr #31 255; CHECK-NEXT: csel w0, w0, w1, ne 256 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 257 %obit = extractvalue {i32, i1} %t, 1 258 %ret = select i1 %obit, i32 %v1, i32 %v2 259 ret i32 %ret 260} 261 262define i64 @smulo.select.i64(i64 %v1, i64 %v2) { 263entry: 264; CHECK-LABEL: smulo.select.i64 265; CHECK: mul x8, x0, x1 266; CHECK-NEXT: smulh x9, x0, x1 267; CHECK-NEXT: cmp x9, x8, asr #63 268; CHECK-NEXT: csel x0, x0, x1, ne 269 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 270 %obit = extractvalue {i64, i1} %t, 1 271 %ret = select i1 %obit, i64 %v1, i64 %v2 272 ret i64 %ret 273} 274 275define i32 @umulo.select.i32(i32 %v1, i32 %v2) { 276entry: 277; CHECK-LABEL: umulo.select.i32 278; CHECK: umull x8, w0, w1 279; CHECK-NEXT: cmp xzr, x8, lsr #32 280; CHECK-NEXT: csel w0, w0, w1, ne 281 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 282 %obit = extractvalue {i32, i1} %t, 1 283 %ret = select i1 %obit, i32 %v1, i32 %v2 284 ret i32 %ret 285} 286 287define i64 @umulo.select.i64(i64 %v1, i64 %v2) { 288entry: 289; CHECK-LABEL: umulo.select.i64 290; CHECK: umulh x8, x0, x1 291; CHECK-NEXT: cmp xzr, x8 292; CHECK-NEXT: csel x0, x0, x1, ne 293 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 294 %obit = extractvalue {i64, i1} %t, 1 295 %ret = select i1 %obit, i64 %v1, i64 %v2 296 ret i64 %ret 297} 298 299 300; 301; Check the use of the overflow bit in combination with a branch instruction. 302; 303define i1 @saddo.br.i32(i32 %v1, i32 %v2) { 304entry: 305; CHECK-LABEL: saddo.br.i32 306; CHECK: cmn w0, w1 307; CHECK-NEXT: b.vc 308 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 309 %val = extractvalue {i32, i1} %t, 0 310 %obit = extractvalue {i32, i1} %t, 1 311 br i1 %obit, label %overflow, label %continue 312 313overflow: 314 ret i1 false 315 316continue: 317 ret i1 true 318} 319 320define i1 @saddo.br.i64(i64 %v1, i64 %v2) { 321entry: 322; CHECK-LABEL: saddo.br.i64 323; CHECK: cmn x0, x1 324; CHECK-NEXT: b.vc 325 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 326 %val = extractvalue {i64, i1} %t, 0 327 %obit = extractvalue {i64, i1} %t, 1 328 br i1 %obit, label %overflow, label %continue 329 330overflow: 331 ret i1 false 332 333continue: 334 ret i1 true 335} 336 337define i1 @uaddo.br.i32(i32 %v1, i32 %v2) { 338entry: 339; CHECK-LABEL: uaddo.br.i32 340; CHECK: cmn w0, w1 341; CHECK-NEXT: b.lo 342 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 343 %val = extractvalue {i32, i1} %t, 0 344 %obit = extractvalue {i32, i1} %t, 1 345 br i1 %obit, label %overflow, label %continue 346 347overflow: 348 ret i1 false 349 350continue: 351 ret i1 true 352} 353 354define i1 @uaddo.br.i64(i64 %v1, i64 %v2) { 355entry: 356; CHECK-LABEL: uaddo.br.i64 357; CHECK: cmn x0, x1 358; CHECK-NEXT: b.lo 359 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 360 %val = extractvalue {i64, i1} %t, 0 361 %obit = extractvalue {i64, i1} %t, 1 362 br i1 %obit, label %overflow, label %continue 363 364overflow: 365 ret i1 false 366 367continue: 368 ret i1 true 369} 370 371define i1 @ssubo.br.i32(i32 %v1, i32 %v2) { 372entry: 373; CHECK-LABEL: ssubo.br.i32 374; CHECK: cmp w0, w1 375; CHECK-NEXT: b.vc 376 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 377 %val = extractvalue {i32, i1} %t, 0 378 %obit = extractvalue {i32, i1} %t, 1 379 br i1 %obit, label %overflow, label %continue 380 381overflow: 382 ret i1 false 383 384continue: 385 ret i1 true 386} 387 388define i1 @ssubo.br.i64(i64 %v1, i64 %v2) { 389entry: 390; CHECK-LABEL: ssubo.br.i64 391; CHECK: cmp x0, x1 392; CHECK-NEXT: b.vc 393 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 394 %val = extractvalue {i64, i1} %t, 0 395 %obit = extractvalue {i64, i1} %t, 1 396 br i1 %obit, label %overflow, label %continue 397 398overflow: 399 ret i1 false 400 401continue: 402 ret i1 true 403} 404 405define i1 @usubo.br.i32(i32 %v1, i32 %v2) { 406entry: 407; CHECK-LABEL: usubo.br.i32 408; CHECK: cmp w0, w1 409; CHECK-NEXT: b.hs 410 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 411 %val = extractvalue {i32, i1} %t, 0 412 %obit = extractvalue {i32, i1} %t, 1 413 br i1 %obit, label %overflow, label %continue 414 415overflow: 416 ret i1 false 417 418continue: 419 ret i1 true 420} 421 422define i1 @usubo.br.i64(i64 %v1, i64 %v2) { 423entry: 424; CHECK-LABEL: usubo.br.i64 425; CHECK: cmp x0, x1 426; CHECK-NEXT: b.hs 427 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 428 %val = extractvalue {i64, i1} %t, 0 429 %obit = extractvalue {i64, i1} %t, 1 430 br i1 %obit, label %overflow, label %continue 431 432overflow: 433 ret i1 false 434 435continue: 436 ret i1 true 437} 438 439define i1 @smulo.br.i32(i32 %v1, i32 %v2) { 440entry: 441; CHECK-LABEL: smulo.br.i32 442; CHECK: smull x8, w0, w1 443; CHECK-NEXT: lsr x9, x8, #32 444; CHECK-NEXT: cmp w9, w8, asr #31 445; CHECK-NEXT: b.eq 446 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 447 %val = extractvalue {i32, i1} %t, 0 448 %obit = extractvalue {i32, i1} %t, 1 449 br i1 %obit, label %overflow, label %continue 450 451overflow: 452 ret i1 false 453 454continue: 455 ret i1 true 456} 457 458define i1 @smulo.br.i64(i64 %v1, i64 %v2) { 459entry: 460; CHECK-LABEL: smulo.br.i64 461; CHECK: mul x8, x0, x1 462; CHECK-NEXT: smulh x9, x0, x1 463; CHECK-NEXT: cmp x9, x8, asr #63 464; CHECK-NEXT: b.eq 465 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 466 %val = extractvalue {i64, i1} %t, 0 467 %obit = extractvalue {i64, i1} %t, 1 468 br i1 %obit, label %overflow, label %continue 469 470overflow: 471 ret i1 false 472 473continue: 474 ret i1 true 475} 476 477define i1 @umulo.br.i32(i32 %v1, i32 %v2) { 478entry: 479; CHECK-LABEL: umulo.br.i32 480; CHECK: umull x8, w0, w1 481; CHECK-NEXT: cmp xzr, x8, lsr #32 482; CHECK-NEXT: b.eq 483 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 484 %val = extractvalue {i32, i1} %t, 0 485 %obit = extractvalue {i32, i1} %t, 1 486 br i1 %obit, label %overflow, label %continue 487 488overflow: 489 ret i1 false 490 491continue: 492 ret i1 true 493} 494 495define i1 @umulo.br.i64(i64 %v1, i64 %v2) { 496entry: 497; CHECK-LABEL: umulo.br.i64 498; CHECK: umulh x8, x0, x1 499; CHECK-NEXT: cbz 500 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 501 %val = extractvalue {i64, i1} %t, 0 502 %obit = extractvalue {i64, i1} %t, 1 503 br i1 %obit, label %overflow, label %continue 504 505overflow: 506 ret i1 false 507 508continue: 509 ret i1 true 510} 511 512declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone 513declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone 514declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone 515declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone 516declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone 517declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone 518declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone 519declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone 520declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone 521declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone 522declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone 523declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone 524 525