llvm/llvm/test/CodeGen/AArch64/arm64-xaluo.ll

; 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