1; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 -disable-post-ra -verify-machineinstrs < %s | FileCheck %s 2; RUN: llc -march=arm64 -aarch64-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort=1 -disable-post-ra -verify-machineinstrs < %s | FileCheck %s 3 4; 5; Get the actual value of the overflow bit. 6; 7define zeroext i1 @saddo1.i32(i32 %v1, i32 %v2, i32* %res) { 8entry: 9; CHECK-LABEL: saddo1.i32 10; CHECK: adds {{w[0-9]+}}, w0, w1 11; CHECK-NEXT: cset {{w[0-9]+}}, vs 12 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 13 %val = extractvalue {i32, i1} %t, 0 14 %obit = extractvalue {i32, i1} %t, 1 15 store i32 %val, i32* %res 16 ret i1 %obit 17} 18 19; Test the immediate version. 20define zeroext i1 @saddo2.i32(i32 %v1, i32* %res) { 21entry: 22; CHECK-LABEL: saddo2.i32 23; CHECK: adds {{w[0-9]+}}, w0, #4 24; CHECK-NEXT: cset {{w[0-9]+}}, vs 25 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 4) 26 %val = extractvalue {i32, i1} %t, 0 27 %obit = extractvalue {i32, i1} %t, 1 28 store i32 %val, i32* %res 29 ret i1 %obit 30} 31 32; Test negative immediates. 33define zeroext i1 @saddo3.i32(i32 %v1, i32* %res) { 34entry: 35; CHECK-LABEL: saddo3.i32 36; CHECK: subs {{w[0-9]+}}, w0, #4 37; CHECK-NEXT: cset {{w[0-9]+}}, vs 38 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 -4) 39 %val = extractvalue {i32, i1} %t, 0 40 %obit = extractvalue {i32, i1} %t, 1 41 store i32 %val, i32* %res 42 ret i1 %obit 43} 44 45; Test immediates that are too large to be encoded. 46define zeroext i1 @saddo4.i32(i32 %v1, i32* %res) { 47entry: 48; CHECK-LABEL: saddo4.i32 49; CHECK: adds {{w[0-9]+}}, w0, {{w[0-9]+}} 50; CHECK-NEXT: cset {{w[0-9]+}}, vs 51 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 16777215) 52 %val = extractvalue {i32, i1} %t, 0 53 %obit = extractvalue {i32, i1} %t, 1 54 store i32 %val, i32* %res 55 ret i1 %obit 56} 57 58; Test shift folding. 59define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, i32* %res) { 60entry: 61; CHECK-LABEL: saddo5.i32 62; CHECK: adds {{w[0-9]+}}, w0, w1 63; CHECK-NEXT: cset {{w[0-9]+}}, vs 64 %lsl = shl i32 %v2, 16 65 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %lsl) 66 %val = extractvalue {i32, i1} %t, 0 67 %obit = extractvalue {i32, i1} %t, 1 68 store i32 %val, i32* %res 69 ret i1 %obit 70} 71 72define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, i64* %res) { 73entry: 74; CHECK-LABEL: saddo1.i64 75; CHECK: adds {{x[0-9]+}}, x0, x1 76; CHECK-NEXT: cset {{w[0-9]+}}, vs 77 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 78 %val = extractvalue {i64, i1} %t, 0 79 %obit = extractvalue {i64, i1} %t, 1 80 store i64 %val, i64* %res 81 ret i1 %obit 82} 83 84define zeroext i1 @saddo2.i64(i64 %v1, i64* %res) { 85entry: 86; CHECK-LABEL: saddo2.i64 87; CHECK: adds {{x[0-9]+}}, x0, #4 88; CHECK-NEXT: cset {{w[0-9]+}}, vs 89 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 4) 90 %val = extractvalue {i64, i1} %t, 0 91 %obit = extractvalue {i64, i1} %t, 1 92 store i64 %val, i64* %res 93 ret i1 %obit 94} 95 96define zeroext i1 @saddo3.i64(i64 %v1, i64* %res) { 97entry: 98; CHECK-LABEL: saddo3.i64 99; CHECK: subs {{x[0-9]+}}, x0, #4 100; CHECK-NEXT: cset {{w[0-9]+}}, vs 101 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -4) 102 %val = extractvalue {i64, i1} %t, 0 103 %obit = extractvalue {i64, i1} %t, 1 104 store i64 %val, i64* %res 105 ret i1 %obit 106} 107 108define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) { 109entry: 110; CHECK-LABEL: uaddo.i32 111; CHECK: adds {{w[0-9]+}}, w0, w1 112; CHECK-NEXT: cset {{w[0-9]+}}, hs 113 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 114 %val = extractvalue {i32, i1} %t, 0 115 %obit = extractvalue {i32, i1} %t, 1 116 store i32 %val, i32* %res 117 ret i1 %obit 118} 119 120define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) { 121entry: 122; CHECK-LABEL: uaddo.i64 123; CHECK: adds {{x[0-9]+}}, x0, x1 124; CHECK-NEXT: cset {{w[0-9]+}}, hs 125 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 126 %val = extractvalue {i64, i1} %t, 0 127 %obit = extractvalue {i64, i1} %t, 1 128 store i64 %val, i64* %res 129 ret i1 %obit 130} 131 132define zeroext i1 @ssubo1.i32(i32 %v1, i32 %v2, i32* %res) { 133entry: 134; CHECK-LABEL: ssubo1.i32 135; CHECK: subs {{w[0-9]+}}, w0, w1 136; CHECK-NEXT: cset {{w[0-9]+}}, vs 137 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 138 %val = extractvalue {i32, i1} %t, 0 139 %obit = extractvalue {i32, i1} %t, 1 140 store i32 %val, i32* %res 141 ret i1 %obit 142} 143 144define zeroext i1 @ssubo2.i32(i32 %v1, i32* %res) { 145entry: 146; CHECK-LABEL: ssubo2.i32 147; CHECK: adds {{w[0-9]+}}, w0, #4 148; CHECK-NEXT: cset {{w[0-9]+}}, vs 149 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 -4) 150 %val = extractvalue {i32, i1} %t, 0 151 %obit = extractvalue {i32, i1} %t, 1 152 store i32 %val, i32* %res 153 ret i1 %obit 154} 155 156define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) { 157entry: 158; CHECK-LABEL: ssubo.i64 159; CHECK: subs {{x[0-9]+}}, x0, x1 160; CHECK-NEXT: cset {{w[0-9]+}}, vs 161 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 162 %val = extractvalue {i64, i1} %t, 0 163 %obit = extractvalue {i64, i1} %t, 1 164 store i64 %val, i64* %res 165 ret i1 %obit 166} 167 168define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) { 169entry: 170; CHECK-LABEL: usubo.i32 171; CHECK: subs {{w[0-9]+}}, w0, w1 172; CHECK-NEXT: cset {{w[0-9]+}}, lo 173 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 174 %val = extractvalue {i32, i1} %t, 0 175 %obit = extractvalue {i32, i1} %t, 1 176 store i32 %val, i32* %res 177 ret i1 %obit 178} 179 180define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) { 181entry: 182; CHECK-LABEL: usubo.i64 183; CHECK: subs {{x[0-9]+}}, x0, x1 184; CHECK-NEXT: cset {{w[0-9]+}}, lo 185 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 186 %val = extractvalue {i64, i1} %t, 0 187 %obit = extractvalue {i64, i1} %t, 1 188 store i64 %val, i64* %res 189 ret i1 %obit 190} 191 192define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) { 193entry: 194; CHECK-LABEL: smulo.i32 195; CHECK: smull x[[MREG:[0-9]+]], w0, w1 196; CHECK-NEXT: lsr x[[SREG:[0-9]+]], x[[MREG]], #32 197; CHECK-NEXT: cmp w[[SREG]], w[[MREG]], asr #31 198; CHECK-NEXT: cset {{w[0-9]+}}, ne 199 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 200 %val = extractvalue {i32, i1} %t, 0 201 %obit = extractvalue {i32, i1} %t, 1 202 store i32 %val, i32* %res 203 ret i1 %obit 204} 205 206define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) { 207entry: 208; CHECK-LABEL: smulo.i64 209; CHECK: mul [[MREG:x[0-9]+]], x0, x1 210; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 211; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 212; CHECK-NEXT: cset {{w[0-9]+}}, ne 213 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 214 %val = extractvalue {i64, i1} %t, 0 215 %obit = extractvalue {i64, i1} %t, 1 216 store i64 %val, i64* %res 217 ret i1 %obit 218} 219 220define zeroext i1 @smulo2.i64(i64 %v1, i64* %res) { 221entry: 222; CHECK-LABEL: smulo2.i64 223; CHECK: adds [[MREG:x[0-9]+]], x0, x0 224; CHECK-NEXT: cset {{w[0-9]+}}, vs 225 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2) 226 %val = extractvalue {i64, i1} %t, 0 227 %obit = extractvalue {i64, i1} %t, 1 228 store i64 %val, i64* %res 229 ret i1 %obit 230} 231 232define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) { 233entry: 234; CHECK-LABEL: umulo.i32 235; CHECK: umull [[MREG:x[0-9]+]], w0, w1 236; CHECK-NEXT: cmp xzr, [[MREG]], lsr #32 237; CHECK-NEXT: cset {{w[0-9]+}}, ne 238 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 239 %val = extractvalue {i32, i1} %t, 0 240 %obit = extractvalue {i32, i1} %t, 1 241 store i32 %val, i32* %res 242 ret i1 %obit 243} 244 245define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) { 246entry: 247; CHECK-LABEL: umulo.i64 248; CHECK: umulh [[MREG:x[0-9]+]], x0, x1 249; CHECK-NEXT: cmp xzr, [[MREG]] 250; CHECK-NEXT: cset {{w[0-9]+}}, ne 251 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 252 %val = extractvalue {i64, i1} %t, 0 253 %obit = extractvalue {i64, i1} %t, 1 254 store i64 %val, i64* %res 255 ret i1 %obit 256} 257 258define zeroext i1 @umulo2.i64(i64 %v1, i64* %res) { 259entry: 260; CHECK-LABEL: umulo2.i64 261; CHECK: adds [[MREG:x[0-9]+]], x0, x0 262; CHECK-NEXT: cset {{w[0-9]+}}, hs 263 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2) 264 %val = extractvalue {i64, i1} %t, 0 265 %obit = extractvalue {i64, i1} %t, 1 266 store i64 %val, i64* %res 267 ret i1 %obit 268} 269 270 271; 272; Check the use of the overflow bit in combination with a select instruction. 273; 274define i32 @saddo.select.i32(i32 %v1, i32 %v2) { 275entry: 276; CHECK-LABEL: saddo.select.i32 277; CHECK: cmn w0, w1 278; CHECK-NEXT: csel w0, w0, w1, vs 279 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 280 %obit = extractvalue {i32, i1} %t, 1 281 %ret = select i1 %obit, i32 %v1, i32 %v2 282 ret i32 %ret 283} 284 285define i64 @saddo.select.i64(i64 %v1, i64 %v2) { 286entry: 287; CHECK-LABEL: saddo.select.i64 288; CHECK: cmn x0, x1 289; CHECK-NEXT: csel x0, x0, x1, vs 290 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 291 %obit = extractvalue {i64, i1} %t, 1 292 %ret = select i1 %obit, i64 %v1, i64 %v2 293 ret i64 %ret 294} 295 296define i32 @uaddo.select.i32(i32 %v1, i32 %v2) { 297entry: 298; CHECK-LABEL: uaddo.select.i32 299; CHECK: cmn w0, w1 300; CHECK-NEXT: csel w0, w0, w1, hs 301 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 302 %obit = extractvalue {i32, i1} %t, 1 303 %ret = select i1 %obit, i32 %v1, i32 %v2 304 ret i32 %ret 305} 306 307define i64 @uaddo.select.i64(i64 %v1, i64 %v2) { 308entry: 309; CHECK-LABEL: uaddo.select.i64 310; CHECK: cmn x0, x1 311; CHECK-NEXT: csel x0, x0, x1, hs 312 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 313 %obit = extractvalue {i64, i1} %t, 1 314 %ret = select i1 %obit, i64 %v1, i64 %v2 315 ret i64 %ret 316} 317 318define i32 @ssubo.select.i32(i32 %v1, i32 %v2) { 319entry: 320; CHECK-LABEL: ssubo.select.i32 321; CHECK: cmp w0, w1 322; CHECK-NEXT: csel w0, w0, w1, vs 323 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 324 %obit = extractvalue {i32, i1} %t, 1 325 %ret = select i1 %obit, i32 %v1, i32 %v2 326 ret i32 %ret 327} 328 329define i64 @ssubo.select.i64(i64 %v1, i64 %v2) { 330entry: 331; CHECK-LABEL: ssubo.select.i64 332; CHECK: cmp x0, x1 333; CHECK-NEXT: csel x0, x0, x1, vs 334 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 335 %obit = extractvalue {i64, i1} %t, 1 336 %ret = select i1 %obit, i64 %v1, i64 %v2 337 ret i64 %ret 338} 339 340define i32 @usubo.select.i32(i32 %v1, i32 %v2) { 341entry: 342; CHECK-LABEL: usubo.select.i32 343; CHECK: cmp w0, w1 344; CHECK-NEXT: csel w0, w0, w1, lo 345 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 346 %obit = extractvalue {i32, i1} %t, 1 347 %ret = select i1 %obit, i32 %v1, i32 %v2 348 ret i32 %ret 349} 350 351define i64 @usubo.select.i64(i64 %v1, i64 %v2) { 352entry: 353; CHECK-LABEL: usubo.select.i64 354; CHECK: cmp x0, x1 355; CHECK-NEXT: csel x0, x0, x1, lo 356 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 357 %obit = extractvalue {i64, i1} %t, 1 358 %ret = select i1 %obit, i64 %v1, i64 %v2 359 ret i64 %ret 360} 361 362define i32 @smulo.select.i32(i32 %v1, i32 %v2) { 363entry: 364; CHECK-LABEL: smulo.select.i32 365; CHECK: smull x[[MREG:[0-9]+]], w0, w1 366; CHECK-NEXT: lsr x[[SREG:[0-9]+]], x[[MREG]], #32 367; CHECK-NEXT: cmp w[[SREG]], w[[MREG]], asr #31 368; CHECK-NEXT: csel w0, w0, w1, ne 369 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 370 %obit = extractvalue {i32, i1} %t, 1 371 %ret = select i1 %obit, i32 %v1, i32 %v2 372 ret i32 %ret 373} 374 375define i64 @smulo.select.i64(i64 %v1, i64 %v2) { 376entry: 377; CHECK-LABEL: smulo.select.i64 378; CHECK: mul [[MREG:x[0-9]+]], x0, x1 379; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 380; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 381; CHECK-NEXT: csel x0, x0, x1, ne 382 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 383 %obit = extractvalue {i64, i1} %t, 1 384 %ret = select i1 %obit, i64 %v1, i64 %v2 385 ret i64 %ret 386} 387 388define i32 @umulo.select.i32(i32 %v1, i32 %v2) { 389entry: 390; CHECK-LABEL: umulo.select.i32 391; CHECK: umull [[MREG:x[0-9]+]], w0, w1 392; CHECK-NEXT: cmp xzr, [[MREG]], lsr #32 393; CHECK-NEXT: csel w0, w0, w1, ne 394 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 395 %obit = extractvalue {i32, i1} %t, 1 396 %ret = select i1 %obit, i32 %v1, i32 %v2 397 ret i32 %ret 398} 399 400define i64 @umulo.select.i64(i64 %v1, i64 %v2) { 401entry: 402; CHECK-LABEL: umulo.select.i64 403; CHECK: umulh [[MREG:x[0-9]+]], x0, x1 404; CHECK-NEXT: cmp xzr, [[MREG]] 405; CHECK-NEXT: csel x0, x0, x1, ne 406 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 407 %obit = extractvalue {i64, i1} %t, 1 408 %ret = select i1 %obit, i64 %v1, i64 %v2 409 ret i64 %ret 410} 411 412 413; 414; Check the use of the overflow bit in combination with a branch instruction. 415; 416define zeroext i1 @saddo.br.i32(i32 %v1, i32 %v2) { 417entry: 418; CHECK-LABEL: saddo.br.i32 419; CHECK: cmn w0, w1 420; CHECK-NEXT: b.vc 421 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) 422 %val = extractvalue {i32, i1} %t, 0 423 %obit = extractvalue {i32, i1} %t, 1 424 br i1 %obit, label %overflow, label %continue 425 426overflow: 427 ret i1 false 428 429continue: 430 ret i1 true 431} 432 433define zeroext i1 @saddo.br.i64(i64 %v1, i64 %v2) { 434entry: 435; CHECK-LABEL: saddo.br.i64 436; CHECK: cmn x0, x1 437; CHECK-NEXT: b.vc 438 %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) 439 %val = extractvalue {i64, i1} %t, 0 440 %obit = extractvalue {i64, i1} %t, 1 441 br i1 %obit, label %overflow, label %continue 442 443overflow: 444 ret i1 false 445 446continue: 447 ret i1 true 448} 449 450define zeroext i1 @uaddo.br.i32(i32 %v1, i32 %v2) { 451entry: 452; CHECK-LABEL: uaddo.br.i32 453; CHECK: cmn w0, w1 454; CHECK-NEXT: b.lo 455 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) 456 %val = extractvalue {i32, i1} %t, 0 457 %obit = extractvalue {i32, i1} %t, 1 458 br i1 %obit, label %overflow, label %continue 459 460overflow: 461 ret i1 false 462 463continue: 464 ret i1 true 465} 466 467define zeroext i1 @uaddo.br.i64(i64 %v1, i64 %v2) { 468entry: 469; CHECK-LABEL: uaddo.br.i64 470; CHECK: cmn x0, x1 471; CHECK-NEXT: b.lo 472 %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) 473 %val = extractvalue {i64, i1} %t, 0 474 %obit = extractvalue {i64, i1} %t, 1 475 br i1 %obit, label %overflow, label %continue 476 477overflow: 478 ret i1 false 479 480continue: 481 ret i1 true 482} 483 484define zeroext i1 @ssubo.br.i32(i32 %v1, i32 %v2) { 485entry: 486; CHECK-LABEL: ssubo.br.i32 487; CHECK: cmp w0, w1 488; CHECK-NEXT: b.vc 489 %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) 490 %val = extractvalue {i32, i1} %t, 0 491 %obit = extractvalue {i32, i1} %t, 1 492 br i1 %obit, label %overflow, label %continue 493 494overflow: 495 ret i1 false 496 497continue: 498 ret i1 true 499} 500 501define zeroext i1 @ssubo.br.i64(i64 %v1, i64 %v2) { 502entry: 503; CHECK-LABEL: ssubo.br.i64 504; CHECK: cmp x0, x1 505; CHECK-NEXT: b.vc 506 %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) 507 %val = extractvalue {i64, i1} %t, 0 508 %obit = extractvalue {i64, i1} %t, 1 509 br i1 %obit, label %overflow, label %continue 510 511overflow: 512 ret i1 false 513 514continue: 515 ret i1 true 516} 517 518define zeroext i1 @usubo.br.i32(i32 %v1, i32 %v2) { 519entry: 520; CHECK-LABEL: usubo.br.i32 521; CHECK: cmp w0, w1 522; CHECK-NEXT: b.hs 523 %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) 524 %val = extractvalue {i32, i1} %t, 0 525 %obit = extractvalue {i32, i1} %t, 1 526 br i1 %obit, label %overflow, label %continue 527 528overflow: 529 ret i1 false 530 531continue: 532 ret i1 true 533} 534 535define zeroext i1 @usubo.br.i64(i64 %v1, i64 %v2) { 536entry: 537; CHECK-LABEL: usubo.br.i64 538; CHECK: cmp x0, x1 539; CHECK-NEXT: b.hs 540 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) 541 %val = extractvalue {i64, i1} %t, 0 542 %obit = extractvalue {i64, i1} %t, 1 543 br i1 %obit, label %overflow, label %continue 544 545overflow: 546 ret i1 false 547 548continue: 549 ret i1 true 550} 551 552define zeroext i1 @smulo.br.i32(i32 %v1, i32 %v2) { 553entry: 554; CHECK-LABEL: smulo.br.i32 555; CHECK: smull x[[MREG:[0-9]+]], w0, w1 556; CHECK-NEXT: lsr x[[SREG:[0-9]+]], x8, #32 557; CHECK-NEXT: cmp w[[SREG]], w[[MREG]], asr #31 558; CHECK-NEXT: b.eq 559 %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) 560 %val = extractvalue {i32, i1} %t, 0 561 %obit = extractvalue {i32, i1} %t, 1 562 br i1 %obit, label %overflow, label %continue 563 564overflow: 565 ret i1 false 566 567continue: 568 ret i1 true 569} 570 571define zeroext i1 @smulo.br.i64(i64 %v1, i64 %v2) { 572entry: 573; CHECK-LABEL: smulo.br.i64 574; CHECK: mul [[MREG:x[0-9]+]], x0, x1 575; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 576; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 577; CHECK-NEXT: b.eq 578 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) 579 %val = extractvalue {i64, i1} %t, 0 580 %obit = extractvalue {i64, i1} %t, 1 581 br i1 %obit, label %overflow, label %continue 582 583overflow: 584 ret i1 false 585 586continue: 587 ret i1 true 588} 589 590define zeroext i1 @smulo2.br.i64(i64 %v1) { 591entry: 592; CHECK-LABEL: smulo2.br.i64 593; CHECK: cmn x0, x0 594; CHECK-NEXT: b.vc 595 %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2) 596 %val = extractvalue {i64, i1} %t, 0 597 %obit = extractvalue {i64, i1} %t, 1 598 br i1 %obit, label %overflow, label %continue 599 600overflow: 601 ret i1 false 602 603continue: 604 ret i1 true 605} 606 607define zeroext i1 @umulo.br.i32(i32 %v1, i32 %v2) { 608entry: 609; CHECK-LABEL: umulo.br.i32 610; CHECK: umull [[MREG:x[0-9]+]], w0, w1 611; CHECK-NEXT: cmp xzr, [[MREG]], lsr #32 612; CHECK-NEXT: b.eq 613 %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) 614 %val = extractvalue {i32, i1} %t, 0 615 %obit = extractvalue {i32, i1} %t, 1 616 br i1 %obit, label %overflow, label %continue 617 618overflow: 619 ret i1 false 620 621continue: 622 ret i1 true 623} 624 625define zeroext i1 @umulo.br.i64(i64 %v1, i64 %v2) { 626entry: 627; CHECK-LABEL: umulo.br.i64 628; CHECK: umulh [[REG:x[0-9]+]], x0, x1 629; CHECK-NEXT: {{cbz|cmp}} 630 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) 631 %val = extractvalue {i64, i1} %t, 0 632 %obit = extractvalue {i64, i1} %t, 1 633 br i1 %obit, label %overflow, label %continue 634 635overflow: 636 ret i1 false 637 638continue: 639 ret i1 true 640} 641 642define zeroext i1 @umulo2.br.i64(i64 %v1) { 643entry: 644; CHECK-LABEL: umulo2.br.i64 645; CHECK: cmn x0, x0 646; CHECK-NEXT: b.lo 647 %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2) 648 %val = extractvalue {i64, i1} %t, 0 649 %obit = extractvalue {i64, i1} %t, 1 650 br i1 %obit, label %overflow, label %continue 651 652overflow: 653 ret i1 false 654 655continue: 656 ret i1 true 657} 658 659declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone 660declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone 661declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone 662declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone 663declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone 664declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone 665declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone 666declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone 667declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone 668declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone 669declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone 670declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone 671 672