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 ; 7 define zeroext i1 @saddo1.i32(i32 %v1, i32 %v2, i32* %res) { 8 entry: 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. 20 define zeroext i1 @saddo2.i32(i32 %v1, i32* %res) { 21 entry: 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. 33 define zeroext i1 @saddo3.i32(i32 %v1, i32* %res) { 34 entry: 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. 46 define zeroext i1 @saddo4.i32(i32 %v1, i32* %res) { 47 entry: 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. 59 define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, i32* %res) { 60 entry: 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 72 define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, i64* %res) { 73 entry: 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 84 define zeroext i1 @saddo2.i64(i64 %v1, i64* %res) { 85 entry: 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 96 define zeroext i1 @saddo3.i64(i64 %v1, i64* %res) { 97 entry: 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 108 define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) { 109 entry: 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 120 define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) { 121 entry: 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 132 define zeroext i1 @ssubo1.i32(i32 %v1, i32 %v2, i32* %res) { 133 entry: 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 144 define zeroext i1 @ssubo2.i32(i32 %v1, i32* %res) { 145 entry: 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 156 define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) { 157 entry: 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 168 define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) { 169 entry: 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 180 define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) { 181 entry: 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 192 define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) { 193 entry: 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 206 define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) { 207 entry: 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 220 define zeroext i1 @smulo2.i64(i64 %v1, i64* %res) { 221 entry: 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 232 define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) { 233 entry: 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 245 define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) { 246 entry: 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 258 define zeroext i1 @umulo2.i64(i64 %v1, i64* %res) { 259 entry: 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 ; 274 define i32 @saddo.select.i32(i32 %v1, i32 %v2) { 275 entry: 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 285 define i64 @saddo.select.i64(i64 %v1, i64 %v2) { 286 entry: 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 296 define i32 @uaddo.select.i32(i32 %v1, i32 %v2) { 297 entry: 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 307 define i64 @uaddo.select.i64(i64 %v1, i64 %v2) { 308 entry: 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 318 define i32 @ssubo.select.i32(i32 %v1, i32 %v2) { 319 entry: 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 329 define i64 @ssubo.select.i64(i64 %v1, i64 %v2) { 330 entry: 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 340 define i32 @usubo.select.i32(i32 %v1, i32 %v2) { 341 entry: 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 351 define i64 @usubo.select.i64(i64 %v1, i64 %v2) { 352 entry: 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 362 define i32 @smulo.select.i32(i32 %v1, i32 %v2) { 363 entry: 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 375 define i64 @smulo.select.i64(i64 %v1, i64 %v2) { 376 entry: 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 388 define i32 @umulo.select.i32(i32 %v1, i32 %v2) { 389 entry: 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 400 define i64 @umulo.select.i64(i64 %v1, i64 %v2) { 401 entry: 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 ; 416 define zeroext i1 @saddo.br.i32(i32 %v1, i32 %v2) { 417 entry: 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 426 overflow: 427 ret i1 false 428 429 continue: 430 ret i1 true 431 } 432 433 define zeroext i1 @saddo.br.i64(i64 %v1, i64 %v2) { 434 entry: 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 443 overflow: 444 ret i1 false 445 446 continue: 447 ret i1 true 448 } 449 450 define zeroext i1 @uaddo.br.i32(i32 %v1, i32 %v2) { 451 entry: 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 460 overflow: 461 ret i1 false 462 463 continue: 464 ret i1 true 465 } 466 467 define zeroext i1 @uaddo.br.i64(i64 %v1, i64 %v2) { 468 entry: 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 477 overflow: 478 ret i1 false 479 480 continue: 481 ret i1 true 482 } 483 484 define zeroext i1 @ssubo.br.i32(i32 %v1, i32 %v2) { 485 entry: 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 494 overflow: 495 ret i1 false 496 497 continue: 498 ret i1 true 499 } 500 501 define zeroext i1 @ssubo.br.i64(i64 %v1, i64 %v2) { 502 entry: 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 511 overflow: 512 ret i1 false 513 514 continue: 515 ret i1 true 516 } 517 518 define zeroext i1 @usubo.br.i32(i32 %v1, i32 %v2) { 519 entry: 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 528 overflow: 529 ret i1 false 530 531 continue: 532 ret i1 true 533 } 534 535 define zeroext i1 @usubo.br.i64(i64 %v1, i64 %v2) { 536 entry: 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 545 overflow: 546 ret i1 false 547 548 continue: 549 ret i1 true 550 } 551 552 define zeroext i1 @smulo.br.i32(i32 %v1, i32 %v2) { 553 entry: 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 564 overflow: 565 ret i1 false 566 567 continue: 568 ret i1 true 569 } 570 571 define zeroext i1 @smulo.br.i64(i64 %v1, i64 %v2) { 572 entry: 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 583 overflow: 584 ret i1 false 585 586 continue: 587 ret i1 true 588 } 589 590 define zeroext i1 @smulo2.br.i64(i64 %v1) { 591 entry: 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 600 overflow: 601 ret i1 false 602 603 continue: 604 ret i1 true 605 } 606 607 define zeroext i1 @umulo.br.i32(i32 %v1, i32 %v2) { 608 entry: 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 618 overflow: 619 ret i1 false 620 621 continue: 622 ret i1 true 623 } 624 625 define zeroext i1 @umulo.br.i64(i64 %v1, i64 %v2) { 626 entry: 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 635 overflow: 636 ret i1 false 637 638 continue: 639 ret i1 true 640 } 641 642 define zeroext i1 @umulo2.br.i64(i64 %v1) { 643 entry: 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 652 overflow: 653 ret i1 false 654 655 continue: 656 ret i1 true 657 } 658 659 declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone 660 declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone 661 declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone 662 declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone 663 declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone 664 declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone 665 declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone 666 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone 667 declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone 668 declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone 669 declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone 670 declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone 671 672