| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=arm64-eabi -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,SDAG |
| ; RUN: llc < %s -mtriple=arm64-eabi -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,FAST |
| ; RUN: llc < %s -mtriple=arm64-eabi -global-isel -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,GISEL |
| |
| ; |
| ; Get the actual value of the overflow bit. |
| ; |
| define zeroext i1 @saddo1.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: saddo1.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds w8, w0, w1 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo1.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds w8, w0, w1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo1.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w8, w0, w1 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| ; Test the immediate version. |
| define zeroext i1 @saddo2.i32(i32 %v1, ptr %res) { |
| ; SDAG-LABEL: saddo2.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds w8, w0, #4 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo2.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds w8, w0, #4 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo2.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w8, w0, #4 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 4) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| ; Test negative immediates. |
| define zeroext i1 @saddo3.i32(i32 %v1, ptr %res) { |
| ; SDAG-LABEL: saddo3.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs w8, w0, #4 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo3.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs w8, w0, #4 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo3.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs w8, w0, #4 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 -4) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| ; Test immediates that are too large to be encoded. |
| define zeroext i1 @saddo4.i32(i32 %v1, ptr %res) { |
| ; SDAG-LABEL: saddo4.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #16777215 // =0xffffff |
| ; SDAG-NEXT: adds w8, w0, w8 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo4.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov w8, #16777215 // =0xffffff |
| ; FAST-NEXT: adds w8, w0, w8 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo4.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: mov w8, #16777215 // =0xffffff |
| ; GISEL-NEXT: adds w8, w0, w8 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 16777215) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| ; Test shift folding. |
| define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: saddo5.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds w8, w0, w1, lsl #16 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo5.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds w8, w0, w1, lsl #16 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo5.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w8, w0, w1, lsl #16 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %lsl = shl i32 %v2, 16 |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %lsl) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: saddo1.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds x8, x0, x1 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str x8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo1.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds x8, x0, x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str x8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo1.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x8, x0, x1 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str x8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @saddo2.i64(i64 %v1, ptr %res) { |
| ; SDAG-LABEL: saddo2.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds x8, x0, #4 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str x8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo2.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds x8, x0, #4 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str x8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo2.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x8, x0, #4 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str x8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 4) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @saddo3.i64(i64 %v1, ptr %res) { |
| ; SDAG-LABEL: saddo3.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs x8, x0, #4 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str x8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo3.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs x8, x0, #4 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str x8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo3.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs x8, x0, #4 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str x8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -4) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: uaddo.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds w8, w0, w1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds w8, w0, w1 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w8, w0, w1 |
| ; GISEL-NEXT: cset w0, hs |
| ; GISEL-NEXT: str w8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: uaddo.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds x8, x0, x1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: str x8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds x8, x0, x1 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: str x8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x8, x0, x1 |
| ; GISEL-NEXT: cset w0, hs |
| ; GISEL-NEXT: str x8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @ssubo1.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: ssubo1.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs w8, w0, w1 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo1.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs w8, w0, w1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo1.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs w8, w0, w1 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @ssubo2.i32(i32 %v1, ptr %res) { |
| ; SDAG-LABEL: ssubo2.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds w8, w0, #4 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str w8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo2.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds w8, w0, #4 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str w8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo2.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w8, w0, #4 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str w8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 -4) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: ssubo.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs x8, x0, x1 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str x8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs x8, x0, x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str x8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs x8, x0, x1 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str x8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: usubo.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs w8, w0, w1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs w8, w0, w1 |
| ; FAST-NEXT: cset w9, lo |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs w8, w0, w1 |
| ; GISEL-NEXT: cset w0, lo |
| ; GISEL-NEXT: str w8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: usubo.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: subs x8, x0, x1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: str x8, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: subs x8, x0, x1 |
| ; FAST-NEXT: cset w9, lo |
| ; FAST-NEXT: str x8, [x2] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs x8, x0, x1 |
| ; GISEL-NEXT: cset w0, lo |
| ; GISEL-NEXT: str x8, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: smulo.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: smull x8, w0, w1 |
| ; SDAG-NEXT: cmp x8, w8, sxtw |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: cset w0, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: smull x8, w0, w1 |
| ; FAST-NEXT: cmp x8, w8, sxtw |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smull x8, w0, w1 |
| ; GISEL-NEXT: mul w9, w0, w1 |
| ; GISEL-NEXT: asr x8, x8, #32 |
| ; GISEL-NEXT: str w9, [x2] |
| ; GISEL-NEXT: cmp w8, w9, asr #31 |
| ; GISEL-NEXT: cset w0, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: smulo.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mul x8, x0, x1 |
| ; SDAG-NEXT: smulh x9, x0, x1 |
| ; SDAG-NEXT: str x8, [x2] |
| ; SDAG-NEXT: cmp x9, x8, asr #63 |
| ; SDAG-NEXT: cset w0, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mul x8, x0, x1 |
| ; FAST-NEXT: smulh x9, x0, x1 |
| ; FAST-NEXT: str x8, [x2] |
| ; FAST-NEXT: cmp x9, x8, asr #63 |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smulh x8, x0, x1 |
| ; GISEL-NEXT: mul x9, x0, x1 |
| ; GISEL-NEXT: cmp x8, x9, asr #63 |
| ; GISEL-NEXT: str x9, [x2] |
| ; GISEL-NEXT: cset w0, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @smulo2.i64(i64 %v1, ptr %res) { |
| ; SDAG-LABEL: smulo2.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds x8, x0, x0 |
| ; SDAG-NEXT: cset w0, vs |
| ; SDAG-NEXT: str x8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo2.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds x8, x0, x0 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: str x8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo2.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x8, x0, x0 |
| ; GISEL-NEXT: cset w0, vs |
| ; GISEL-NEXT: str x8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, ptr %res) { |
| ; SDAG-LABEL: umulo.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umull x8, w0, w1 |
| ; SDAG-NEXT: tst x8, #0xffffffff00000000 |
| ; SDAG-NEXT: str w8, [x2] |
| ; SDAG-NEXT: cset w0, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umull x8, w0, w1 |
| ; FAST-NEXT: tst x8, #0xffffffff00000000 |
| ; FAST-NEXT: str w8, [x2] |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umull x8, w0, w1 |
| ; GISEL-NEXT: mul w9, w0, w1 |
| ; GISEL-NEXT: lsr x8, x8, #32 |
| ; GISEL-NEXT: str w9, [x2] |
| ; GISEL-NEXT: cmp w8, #0 |
| ; GISEL-NEXT: cset w0, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| store i32 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, ptr %res) { |
| ; SDAG-LABEL: umulo.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umulh x8, x0, x1 |
| ; SDAG-NEXT: mul x9, x0, x1 |
| ; SDAG-NEXT: cmp xzr, x8 |
| ; SDAG-NEXT: cset w0, ne |
| ; SDAG-NEXT: str x9, [x2] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umulh x8, x0, x1 |
| ; FAST-NEXT: mul x9, x0, x1 |
| ; FAST-NEXT: cmp xzr, x8 |
| ; FAST-NEXT: cset w8, ne |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: str x9, [x2] |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umulh x8, x0, x1 |
| ; GISEL-NEXT: mul x9, x0, x1 |
| ; GISEL-NEXT: cmp x8, #0 |
| ; GISEL-NEXT: cset w0, ne |
| ; GISEL-NEXT: str x9, [x2] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| define zeroext i1 @umulo2.i64(i64 %v1, ptr %res) { |
| ; SDAG-LABEL: umulo2.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: adds x8, x0, x0 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: str x8, [x1] |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo2.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: adds x8, x0, x0 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: str x8, [x1] |
| ; FAST-NEXT: and w0, w9, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo2.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x8, x0, x0 |
| ; GISEL-NEXT: cset w0, hs |
| ; GISEL-NEXT: str x8, [x1] |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| store i64 %val, ptr %res |
| ret i1 %obit |
| } |
| |
| |
| ; |
| ; Check the use of the overflow bit in combination with a select instruction. |
| ; |
| define i32 @saddo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: saddo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: csel w0, w0, w1, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: csel w0, w0, w1, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @saddo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: saddo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: cset w0, vc |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @saddo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: saddo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: csel x0, x0, x1, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: csel x0, x0, x1, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @saddo.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: saddo.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: cset w0, vc |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i32 @uaddo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: uaddo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: csel w0, w0, w1, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: csel w0, w0, w1, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @uaddo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: uaddo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: cset w0, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @uaddo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: uaddo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: csel x0, x0, x1, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: csel x0, x0, x1, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @uaddo.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: uaddo.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: cset w0, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i32 @ssubo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: ssubo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: csel w0, w0, w1, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: csel w0, w0, w1, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @ssubo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: ssubo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: cset w0, vc |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @ssubo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: ssubo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: csel x0, x0, x1, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: csel x0, x0, x1, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @ssub.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: ssub.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssub.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: cset w0, vc |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssub.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i32 @usubo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: usubo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: csel w0, w0, w1, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: csel w0, w0, w1, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @usubo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: usubo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: cset w0, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @usubo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: usubo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: csel x0, x0, x1, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: csel x0, x0, x1, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: tst w8, #0x1 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @usubo.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: usubo.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: cset w0, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i32 @smulo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: smulo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: smull x8, w0, w1 |
| ; SDAG-NEXT: cmp x8, w8, sxtw |
| ; SDAG-NEXT: csel w0, w0, w1, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: smull x8, w0, w1 |
| ; FAST-NEXT: cmp x8, w8, sxtw |
| ; FAST-NEXT: csel w0, w0, w1, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smull x8, w0, w1 |
| ; GISEL-NEXT: mul w9, w0, w1 |
| ; GISEL-NEXT: asr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, w9, asr #31 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @smulo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: smulo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: smull x8, w0, w1 |
| ; SDAG-NEXT: cmp x8, w8, sxtw |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: smull x8, w0, w1 |
| ; FAST-NEXT: cmp x8, w8, sxtw |
| ; FAST-NEXT: cset w0, eq |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smull x8, w0, w1 |
| ; GISEL-NEXT: mul w9, w0, w1 |
| ; GISEL-NEXT: asr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, w9, asr #31 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @smulo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: smulo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mul x8, x0, x1 |
| ; SDAG-NEXT: smulh x9, x0, x1 |
| ; SDAG-NEXT: cmp x9, x8, asr #63 |
| ; SDAG-NEXT: csel x0, x0, x1, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mul x8, x0, x1 |
| ; FAST-NEXT: smulh x9, x0, x1 |
| ; FAST-NEXT: cmp x9, x8, asr #63 |
| ; FAST-NEXT: csel x0, x0, x1, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smulh x8, x0, x1 |
| ; GISEL-NEXT: mul x9, x0, x1 |
| ; GISEL-NEXT: cmp x8, x9, asr #63 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @smulo.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: smulo.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mul x8, x0, x1 |
| ; SDAG-NEXT: smulh x9, x0, x1 |
| ; SDAG-NEXT: cmp x9, x8, asr #63 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mul x8, x0, x1 |
| ; FAST-NEXT: smulh x9, x0, x1 |
| ; FAST-NEXT: cmp x9, x8, asr #63 |
| ; FAST-NEXT: cset w0, eq |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smulh x8, x0, x1 |
| ; GISEL-NEXT: mul x9, x0, x1 |
| ; GISEL-NEXT: cmp x8, x9, asr #63 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i32 @umulo.select.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: umulo.select.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umull x8, w0, w1 |
| ; SDAG-NEXT: tst x8, #0xffffffff00000000 |
| ; SDAG-NEXT: csel w0, w0, w1, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.select.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umull x8, w0, w1 |
| ; FAST-NEXT: tst x8, #0xffffffff00000000 |
| ; FAST-NEXT: csel w0, w0, w1, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.select.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umull x8, w0, w1 |
| ; GISEL-NEXT: lsr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, #0 |
| ; GISEL-NEXT: csel w0, w0, w1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = select i1 %obit, i32 %v1, i32 %v2 |
| ret i32 %ret |
| } |
| |
| define i1 @umulo.not.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: umulo.not.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umull x8, w0, w1 |
| ; SDAG-NEXT: tst x8, #0xffffffff00000000 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.not.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umull x8, w0, w1 |
| ; FAST-NEXT: tst x8, #0xffffffff00000000 |
| ; FAST-NEXT: cset w0, eq |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.not.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umull x8, w0, w1 |
| ; GISEL-NEXT: lsr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, #0 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) |
| %obit = extractvalue {i32, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| define i64 @umulo.select.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: umulo.select.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umulh x8, x0, x1 |
| ; SDAG-NEXT: cmp xzr, x8 |
| ; SDAG-NEXT: csel x0, x0, x1, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.select.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umulh x8, x0, x1 |
| ; FAST-NEXT: cmp xzr, x8 |
| ; FAST-NEXT: csel x0, x0, x1, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.select.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umulh x8, x0, x1 |
| ; GISEL-NEXT: cmp x8, #0 |
| ; GISEL-NEXT: csel x0, x0, x1, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = select i1 %obit, i64 %v1, i64 %v2 |
| ret i64 %ret |
| } |
| |
| define i1 @umulo.not.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: umulo.not.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umulh x8, x0, x1 |
| ; SDAG-NEXT: cmp xzr, x8 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.not.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umulh x8, x0, x1 |
| ; FAST-NEXT: cmp xzr, x8 |
| ; FAST-NEXT: cset w0, eq |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.not.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umulh x8, x0, x1 |
| ; GISEL-NEXT: cmp x8, #0 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) |
| %obit = extractvalue {i64, i1} %t, 1 |
| %ret = xor i1 %obit, true |
| ret i1 %ret |
| } |
| |
| |
| define i8 @uaddo.selectboth.i8(i8 %a, i8 %b) { |
| ; SDAG-LABEL: uaddo.selectboth.i8: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w0, #0xff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: add w9, w9, w1, uxtb |
| ; SDAG-NEXT: tst w9, #0x100 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.selectboth.i8: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w0, #0xff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: add w9, w9, w1, uxtb |
| ; FAST-NEXT: tst w9, #0x100 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.selectboth.i8: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w1, #0xff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: add w9, w9, w0, uxtb |
| ; GISEL-NEXT: cmp w9, w9, uxtb |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i8 @saddo.selectboth.i8(i8 %a, i8 %b) { |
| ; SDAG-LABEL: saddo.selectboth.i8: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: sxtb w9, w0 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: add w9, w9, w1, sxtb |
| ; SDAG-NEXT: cmp w9, w9, sxtb |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.selectboth.i8: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: sxtb w9, w0 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: add w9, w9, w1, sxtb |
| ; FAST-NEXT: cmp w9, w9, sxtb |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.selectboth.i8: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: sxtb w9, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: add w9, w9, w0, sxtb |
| ; GISEL-NEXT: cmp w9, w9, sxtb |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i16 @uaddo.selectboth.i16(i16 %a, i16 %b) { |
| ; SDAG-LABEL: uaddo.selectboth.i16: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w0, #0xffff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: add w9, w9, w1, uxth |
| ; SDAG-NEXT: tst w9, #0x10000 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.selectboth.i16: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w0, #0xffff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: add w9, w9, w1, uxth |
| ; FAST-NEXT: tst w9, #0x10000 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.selectboth.i16: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w1, #0xffff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: add w9, w9, w0, uxth |
| ; GISEL-NEXT: cmp w9, w9, uxth |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i16 @saddo.selectboth.i16(i16 %a, i16 %b) { |
| ; SDAG-LABEL: saddo.selectboth.i16: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: sxth w9, w0 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: add w9, w9, w1, sxth |
| ; SDAG-NEXT: cmp w9, w9, sxth |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.selectboth.i16: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: sxth w9, w0 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: add w9, w9, w1, sxth |
| ; FAST-NEXT: cmp w9, w9, sxth |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.selectboth.i16: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: sxth w9, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: add w9, w9, w0, sxth |
| ; GISEL-NEXT: cmp w9, w9, sxth |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.sadd.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i32 @uaddo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: uaddo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: adds w9, w0, w1 |
| ; SDAG-NEXT: csel w0, w9, w8, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: adds w9, w0, w1 |
| ; FAST-NEXT: csel w0, w9, w8, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, hs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i32 @saddo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: saddo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: adds w9, w0, w1 |
| ; SDAG-NEXT: csel w0, w9, w8, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: adds w9, w0, w1 |
| ; FAST-NEXT: csel w0, w9, w8, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds w9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, vs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i64 @uaddo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: uaddo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: adds x9, x0, x1 |
| ; SDAG-NEXT: csel x0, x9, x8, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: adds x9, x0, x1 |
| ; FAST-NEXT: csel x0, x9, x8, hs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, hs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel x0, x9, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| define i64 @saddo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: saddo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: adds x9, x0, x1 |
| ; SDAG-NEXT: csel x0, x9, x8, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: adds x9, x0, x1 |
| ; FAST-NEXT: csel x0, x9, x8, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: adds x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, vs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel x0, x9, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| define i8 @usubo.selectboth.i8(i8 %a, i8 %b) { |
| ; SDAG-LABEL: usubo.selectboth.i8: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w0, #0xff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: sub w9, w9, w1, uxtb |
| ; SDAG-NEXT: tst w9, #0xffffff00 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.selectboth.i8: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w0, #0xff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: sub w9, w9, w1, uxtb |
| ; FAST-NEXT: tst w9, #0xffffff00 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.selectboth.i8: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w0, #0xff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: sub w9, w9, w1, uxtb |
| ; GISEL-NEXT: cmp w9, w9, uxtb |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i8 @ssubo.selectboth.i8(i8 %a, i8 %b) { |
| ; CHECK-LABEL: ssubo.selectboth.i8: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: sxtb w9, w0 |
| ; CHECK-NEXT: mov w8, #10 // =0xa |
| ; CHECK-NEXT: sub w9, w9, w1, sxtb |
| ; CHECK-NEXT: cmp w9, w9, sxtb |
| ; CHECK-NEXT: csel w0, w9, w8, ne |
| ; CHECK-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i16 @usubo.selectboth.i16(i16 %a, i16 %b) { |
| ; SDAG-LABEL: usubo.selectboth.i16: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w0, #0xffff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: sub w9, w9, w1, uxth |
| ; SDAG-NEXT: tst w9, #0xffff0000 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.selectboth.i16: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w0, #0xffff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: sub w9, w9, w1, uxth |
| ; FAST-NEXT: tst w9, #0xffff0000 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.selectboth.i16: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w0, #0xffff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: sub w9, w9, w1, uxth |
| ; GISEL-NEXT: cmp w9, w9, uxth |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i16 @ssubo.selectboth.i16(i16 %a, i16 %b) { |
| ; CHECK-LABEL: ssubo.selectboth.i16: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: sxth w9, w0 |
| ; CHECK-NEXT: mov w8, #10 // =0xa |
| ; CHECK-NEXT: sub w9, w9, w1, sxth |
| ; CHECK-NEXT: cmp w9, w9, sxth |
| ; CHECK-NEXT: csel w0, w9, w8, ne |
| ; CHECK-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.ssub.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i32 @usubo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: usubo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: subs w9, w0, w1 |
| ; SDAG-NEXT: csel w0, w9, w8, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: subs w9, w0, w1 |
| ; FAST-NEXT: csel w0, w9, w8, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs w9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, lo |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i32 @ssubo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: ssubo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: subs w9, w0, w1 |
| ; SDAG-NEXT: csel w0, w9, w8, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: subs w9, w0, w1 |
| ; FAST-NEXT: csel w0, w9, w8, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs w9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, vs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i64 @usubo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: usubo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: subs x9, x0, x1 |
| ; SDAG-NEXT: csel x0, x9, x8, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: subs x9, x0, x1 |
| ; FAST-NEXT: csel x0, x9, x8, lo |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, lo |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel x0, x9, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| define i64 @ssubo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: ssubo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: subs x9, x0, x1 |
| ; SDAG-NEXT: csel x0, x9, x8, vs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: subs x9, x0, x1 |
| ; FAST-NEXT: csel x0, x9, x8, vs |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: subs x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: cset w10, vs |
| ; GISEL-NEXT: tst w10, #0x1 |
| ; GISEL-NEXT: csel x0, x9, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| |
| define i8 @umulo.selectboth.i8(i8 %a, i8 %b) { |
| ; SDAG-LABEL: umulo.selectboth.i8: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w1, #0xff |
| ; SDAG-NEXT: and w10, w0, #0xff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: mul w9, w10, w9 |
| ; SDAG-NEXT: tst w9, #0xff00 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.selectboth.i8: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w1, #0xff |
| ; FAST-NEXT: and w10, w0, #0xff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: mul w9, w10, w9 |
| ; FAST-NEXT: tst w9, #0xff00 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.selectboth.i8: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w0, #0xff |
| ; GISEL-NEXT: and w10, w1, #0xff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w9, w9, w10 |
| ; GISEL-NEXT: cmp w9, w9, uxtb |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i8 @smulo.selectboth.i8(i8 %a, i8 %b) { |
| ; SDAG-LABEL: smulo.selectboth.i8: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: sxtb w9, w1 |
| ; SDAG-NEXT: sxtb w10, w0 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: mul w9, w10, w9 |
| ; SDAG-NEXT: cmp w9, w9, sxtb |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.selectboth.i8: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: sxtb w9, w1 |
| ; FAST-NEXT: sxtb w10, w0 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: mul w9, w10, w9 |
| ; FAST-NEXT: cmp w9, w9, sxtb |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.selectboth.i8: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: sxtb w9, w0 |
| ; GISEL-NEXT: sxtb w10, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w9, w9, w10 |
| ; GISEL-NEXT: cmp w9, w9, sxtb |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b) |
| %m1 = extractvalue { i8, i1 } %m, 0 |
| %m2 = extractvalue { i8, i1 } %m, 1 |
| %r = select i1 %m2, i8 %m1, i8 10 |
| ret i8 %r |
| } |
| |
| define i16 @umulo.selectboth.i16(i16 %a, i16 %b) { |
| ; SDAG-LABEL: umulo.selectboth.i16: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: and w9, w1, #0xffff |
| ; SDAG-NEXT: and w10, w0, #0xffff |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: mul w9, w10, w9 |
| ; SDAG-NEXT: tst w9, #0xffff0000 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.selectboth.i16: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: and w9, w1, #0xffff |
| ; FAST-NEXT: and w10, w0, #0xffff |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: mul w9, w10, w9 |
| ; FAST-NEXT: tst w9, #0xffff0000 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.selectboth.i16: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: and w9, w0, #0xffff |
| ; GISEL-NEXT: and w10, w1, #0xffff |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w9, w9, w10 |
| ; GISEL-NEXT: cmp w9, w9, uxth |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i16 @smulo.selectboth.i16(i16 %a, i16 %b) { |
| ; SDAG-LABEL: smulo.selectboth.i16: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: sxth w9, w1 |
| ; SDAG-NEXT: sxth w10, w0 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: mul w9, w10, w9 |
| ; SDAG-NEXT: cmp w9, w9, sxth |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.selectboth.i16: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: sxth w9, w1 |
| ; FAST-NEXT: sxth w10, w0 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: mul w9, w10, w9 |
| ; FAST-NEXT: cmp w9, w9, sxth |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.selectboth.i16: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: sxth w9, w0 |
| ; GISEL-NEXT: sxth w10, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w9, w9, w10 |
| ; GISEL-NEXT: cmp w9, w9, sxth |
| ; GISEL-NEXT: csel w0, w9, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i16, i1 } @llvm.smul.with.overflow.i16(i16 %a, i16 %b) |
| %m1 = extractvalue { i16, i1 } %m, 0 |
| %m2 = extractvalue { i16, i1 } %m, 1 |
| %r = select i1 %m2, i16 %m1, i16 10 |
| ret i16 %r |
| } |
| |
| define i32 @umulo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: umulo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umull x9, w0, w1 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: tst x9, #0xffffffff00000000 |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umull x9, w0, w1 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: tst x9, #0xffffffff00000000 |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umull x9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w10, w0, w1 |
| ; GISEL-NEXT: lsr x9, x9, #32 |
| ; GISEL-NEXT: cmp w9, #0 |
| ; GISEL-NEXT: csel w0, w10, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i32 @smulo.selectboth.i32(i32 %a, i32 %b) { |
| ; SDAG-LABEL: smulo.selectboth.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: smull x9, w0, w1 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: cmp x9, w9, sxtw |
| ; SDAG-NEXT: csel w0, w9, w8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.selectboth.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: smull x9, w0, w1 |
| ; FAST-NEXT: mov w8, #10 // =0xa |
| ; FAST-NEXT: cmp x9, w9, sxtw |
| ; FAST-NEXT: csel w0, w9, w8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.selectboth.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smull x9, w0, w1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul w10, w0, w1 |
| ; GISEL-NEXT: asr x9, x9, #32 |
| ; GISEL-NEXT: cmp w9, w10, asr #31 |
| ; GISEL-NEXT: csel w0, w10, w8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %a, i32 %b) |
| %m1 = extractvalue { i32, i1 } %m, 0 |
| %m2 = extractvalue { i32, i1 } %m, 1 |
| %r = select i1 %m2, i32 %m1, i32 10 |
| ret i32 %r |
| } |
| |
| define i64 @umulo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: umulo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umulh x9, x0, x1 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: mul x10, x0, x1 |
| ; SDAG-NEXT: cmp xzr, x9 |
| ; SDAG-NEXT: csel x0, x10, x8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umulh x9, x0, x1 |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: mul x10, x0, x1 |
| ; FAST-NEXT: cmp xzr, x9 |
| ; FAST-NEXT: csel x0, x10, x8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umulh x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul x10, x0, x1 |
| ; GISEL-NEXT: cmp x9, #0 |
| ; GISEL-NEXT: csel x0, x10, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| define i64 @smulo.selectboth.i64(i64 %a, i64 %b) { |
| ; SDAG-LABEL: smulo.selectboth.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mul x9, x0, x1 |
| ; SDAG-NEXT: mov w8, #10 // =0xa |
| ; SDAG-NEXT: smulh x10, x0, x1 |
| ; SDAG-NEXT: cmp x10, x9, asr #63 |
| ; SDAG-NEXT: csel x0, x9, x8, ne |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.selectboth.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mul x9, x0, x1 |
| ; FAST-NEXT: mov x8, #10 // =0xa |
| ; FAST-NEXT: smulh x10, x0, x1 |
| ; FAST-NEXT: cmp x10, x9, asr #63 |
| ; FAST-NEXT: csel x0, x9, x8, ne |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.selectboth.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smulh x9, x0, x1 |
| ; GISEL-NEXT: mov w8, #10 // =0xa |
| ; GISEL-NEXT: mul x10, x0, x1 |
| ; GISEL-NEXT: cmp x9, x10, asr #63 |
| ; GISEL-NEXT: csel x0, x10, x8, ne |
| ; GISEL-NEXT: ret |
| entry: |
| %m = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %a, i64 %b) |
| %m1 = extractvalue { i64, i1 } %m, 0 |
| %m2 = extractvalue { i64, i1 } %m, 1 |
| %r = select i1 %m2, i64 %m1, i64 10 |
| ret i64 %r |
| } |
| |
| |
| ; |
| ; Check the use of the overflow bit in combination with a branch instruction. |
| ; |
| define zeroext i1 @saddo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: saddo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @saddo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: saddo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: saddo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: saddo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @uaddo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: uaddo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn w0, w1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn w0, w1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @uaddo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: uaddo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x1 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: uaddo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: uaddo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x1 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @ssubo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: ssubo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @ssubo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: ssubo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: ssubo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: ssubo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @usubo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: usubo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp w0, w1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, lo |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp w0, w1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @usubo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: usubo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmp x0, x1 |
| ; SDAG-NEXT: cset w0, hs |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: usubo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmp x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, lo |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: usubo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmp x0, x1 |
| ; GISEL-NEXT: cset w8, lo |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @smulo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: smulo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: smull x8, w0, w1 |
| ; SDAG-NEXT: cmp x8, w8, sxtw |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: smull x9, w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cmp x9, w9, sxtw |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smull x8, w0, w1 |
| ; GISEL-NEXT: mul w9, w0, w1 |
| ; GISEL-NEXT: asr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, w9, asr #31 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @smulo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: smulo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: mul x8, x0, x1 |
| ; SDAG-NEXT: smulh x9, x0, x1 |
| ; SDAG-NEXT: cmp x9, x8, asr #63 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: mul x9, x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: smulh x10, x0, x1 |
| ; FAST-NEXT: cmp x10, x9, asr #63 |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: smulh x8, x0, x1 |
| ; GISEL-NEXT: mul x9, x0, x1 |
| ; GISEL-NEXT: cmp x8, x9, asr #63 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @smulo2.br.i64(i64 %v1) { |
| ; SDAG-LABEL: smulo2.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x0 |
| ; SDAG-NEXT: cset w0, vc |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: smulo2.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x0 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, vs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: smulo2.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x0 |
| ; GISEL-NEXT: cset w8, vs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @umulo.br.i32(i32 %v1, i32 %v2) { |
| ; SDAG-LABEL: umulo.br.i32: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umull x8, w0, w1 |
| ; SDAG-NEXT: tst x8, #0xffffffff00000000 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.br.i32: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umull x9, w0, w1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: tst x9, #0xffffffff00000000 |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.br.i32: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umull x8, w0, w1 |
| ; GISEL-NEXT: lsr x8, x8, #32 |
| ; GISEL-NEXT: cmp w8, #0 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) |
| %val = extractvalue {i32, i1} %t, 0 |
| %obit = extractvalue {i32, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @umulo.br.i64(i64 %v1, i64 %v2) { |
| ; SDAG-LABEL: umulo.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: umulh x8, x0, x1 |
| ; SDAG-NEXT: cmp xzr, x8 |
| ; SDAG-NEXT: cset w0, eq |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: umulh x9, x0, x1 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cmp xzr, x9 |
| ; FAST-NEXT: cset w9, ne |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: umulh x8, x0, x1 |
| ; GISEL-NEXT: cmp x8, #0 |
| ; GISEL-NEXT: cset w8, ne |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define zeroext i1 @umulo2.br.i64(i64 %v1) { |
| ; SDAG-LABEL: umulo2.br.i64: |
| ; SDAG: // %bb.0: // %entry |
| ; SDAG-NEXT: cmn x0, x0 |
| ; SDAG-NEXT: cset w0, lo |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: umulo2.br.i64: |
| ; FAST: // %bb.0: // %entry |
| ; FAST-NEXT: cmn x0, x0 |
| ; FAST-NEXT: mov w8, #1 // =0x1 |
| ; FAST-NEXT: cset w9, hs |
| ; FAST-NEXT: bic w8, w8, w9 |
| ; FAST-NEXT: and w0, w8, #0x1 |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: umulo2.br.i64: |
| ; GISEL: // %bb.0: // %entry |
| ; GISEL-NEXT: cmn x0, x0 |
| ; GISEL-NEXT: cset w8, hs |
| ; GISEL-NEXT: eor w0, w8, #0x1 |
| ; GISEL-NEXT: ret |
| entry: |
| %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 2) |
| %val = extractvalue {i64, i1} %t, 0 |
| %obit = extractvalue {i64, i1} %t, 1 |
| br i1 %obit, label %overflow, label %continue |
| |
| overflow: |
| ret i1 false |
| |
| continue: |
| ret i1 true |
| } |
| |
| define i8 @pr60530() { |
| ; SDAG-LABEL: pr60530: |
| ; SDAG: // %bb.0: |
| ; SDAG-NEXT: mov w0, #-1 // =0xffffffff |
| ; SDAG-NEXT: ret |
| ; |
| ; FAST-LABEL: pr60530: |
| ; FAST: // %bb.0: |
| ; FAST-NEXT: mov w0, #-1 // =0xffffffff |
| ; FAST-NEXT: ret |
| ; |
| ; GISEL-LABEL: pr60530: |
| ; GISEL: // %bb.0: |
| ; GISEL-NEXT: mov w0, #255 // =0xff |
| ; GISEL-NEXT: ret |
| %1 = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 0, i8 1) |
| %2 = extractvalue { i8, i1 } %1, 1 |
| %3 = zext i1 %2 to i8 |
| %4 = shl i8 -1, %3 |
| %5 = lshr i8 1, %4 |
| %6 = icmp uge i8 %5, 1 |
| %7 = sext i1 %6 to i8 |
| %8 = zext i1 %2 to i8 |
| %9 = icmp uge i8 %7, %8 |
| %10 = sext i1 %9 to i8 |
| ret i8 %10 |
| } |
| |
| declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone |
| declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.uadd.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone |
| declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.ssub.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone |
| declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.usub.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone |
| declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone |
| declare {i8, i1} @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone |
| declare {i16, i1} @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone |
| declare {i32, i1} @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone |
| declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone |
| |