diff --git a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll b/llvm/test/CodeGen/AArch64/arm64-xaluo.ll index d8f5db89954f6d..0ce5b8ab8e400d 100644 --- a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll +++ b/llvm/test/CodeGen/AArch64/arm64-xaluo.ll @@ -1,15 +1,35 @@ -; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -fast-isel -fast-isel-abort=1 -disable-post-ra -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -mtriple=arm64-eabi -aarch64-enable-atomic-cfg-tidy=0 -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -disable-post-ra -verify-machineinstrs | FileCheck %s --check-prefixes=GISEL,FALLBACK +; 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, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo1.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, w1 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo1.i32 -; CHECK: adds {{w[0-9]+}}, w0, w1 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -19,10 +39,29 @@ entry: ; Test the immediate version. define zeroext i1 @saddo2.i32(i32 %v1, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo2.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, #4 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo2.i32 -; CHECK: adds {{w[0-9]+}}, w0, #4 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -32,10 +71,29 @@ entry: ; Test negative immediates. define zeroext i1 @saddo3.i32(i32 %v1, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo3.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs w8, w0, #4 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo3.i32 -; CHECK: subs {{w[0-9]+}}, w0, #4 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -45,10 +103,32 @@ entry: ; Test immediates that are too large to be encoded. define zeroext i1 @saddo4.i32(i32 %v1, i32* %res) { +; SDAG-LABEL: saddo4.i32: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: mov w8, #16777215 +; 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 +; FAST-NEXT: adds w8, w0, w8 +; FAST-NEXT: cset w9, vs +; FAST-NEXT: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo4.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: mov w8, #16777215 +; GISEL-NEXT: adds w8, w0, w8 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo4.i32 -; CHECK: adds {{w[0-9]+}}, w0, {{w[0-9]+}} -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -58,10 +138,29 @@ entry: ; Test shift folding. define zeroext i1 @saddo5.i32(i32 %v1, i32 %v2, i32* %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 w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo5.i32 -; CHECK: adds {{w[0-9]+}}, w0, w1 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %lsl = shl i32 %v2, 16 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %lsl) %val = extractvalue {i32, i1} %t, 0 @@ -71,10 +170,29 @@ entry: } define zeroext i1 @saddo1.i64(i64 %v1, i64 %v2, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo1.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x1 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo1.i64 -; CHECK: adds {{x[0-9]+}}, x0, x1 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -83,10 +201,29 @@ entry: } define zeroext i1 @saddo2.i64(i64 %v1, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo2.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, #4 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo2.i64 -; CHECK: adds {{x[0-9]+}}, x0, #4 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -95,10 +232,29 @@ entry: } define zeroext i1 @saddo3.i64(i64 %v1, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo3.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs x8, x0, #4 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo3.i64 -; CHECK: subs {{x[0-9]+}}, x0, #4 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -106,15 +262,30 @@ entry: ret i1 %obit } -; FALLBACK-NOT: remark{{.*}}uaddo.i32 define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, w1 +; GISEL-NEXT: cset w9, hs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.i32 -; CHECK: adds {{w[0-9]+}}, w0, w1 -; CHECK-NEXT: cset {{w[0-9]+}}, hs -; GISEL-LABEL: uaddo.i32 -; GISEL: adds {{w[0-9]+}}, w0, w1 -; GISEL-NEXT: cset {{w[0-9]+}}, hs %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 @@ -122,15 +293,30 @@ entry: ret i1 %obit } -; FALLBACK-NOT: remark{{.*}}uaddo.i64 define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x1 +; GISEL-NEXT: cset w9, hs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.i64 -; CHECK: adds {{x[0-9]+}}, x0, x1 -; CHECK-NEXT: cset {{w[0-9]+}}, hs -; GISEL-LABEL: uaddo.i64 -; GISEL: adds {{x[0-9]+}}, x0, x1 -; GISEL-NEXT: cset {{w[0-9]+}}, hs %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 @@ -139,10 +325,29 @@ entry: } define zeroext i1 @ssubo1.i32(i32 %v1, i32 %v2, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: ssubo1.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs w8, w0, w1 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo1.i32 -; CHECK: subs {{w[0-9]+}}, w0, w1 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -151,10 +356,29 @@ entry: } define zeroext i1 @ssubo2.i32(i32 %v1, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: ssubo2.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, #4 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo2.i32 -; CHECK: adds {{w[0-9]+}}, w0, #4 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -163,10 +387,29 @@ entry: } define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: ssubo.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs x8, x0, x1 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo.i64 -; CHECK: subs {{x[0-9]+}}, x0, x1 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -175,10 +418,29 @@ entry: } define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %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: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs w8, w0, w1 +; GISEL-NEXT: cset w9, lo +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str w8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.i32 -; CHECK: subs {{w[0-9]+}}, w0, w1 -; CHECK-NEXT: cset {{w[0-9]+}}, lo %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 @@ -187,10 +449,29 @@ entry: } define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x2] +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs x8, x0, x1 +; GISEL-NEXT: cset w9, lo +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.i64 -; CHECK: subs {{x[0-9]+}}, x0, x1 -; CHECK-NEXT: cset {{w[0-9]+}}, lo %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 @@ -199,11 +480,33 @@ entry: } define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: smulo.i32: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: smull x8, w0, w1 +; SDAG-NEXT: cmp x8, w8, sxtw +; SDAG-NEXT: cset w0, ne +; SDAG-NEXT: str w8, [x2] +; 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: cset w9, ne +; FAST-NEXT: str w8, [x2] +; 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: cmp w8, w9, asr #31 +; GISEL-NEXT: cset w0, ne +; GISEL-NEXT: str w9, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo.i32 -; CHECK: smull x[[MREG:[0-9]+]], w0, w1 -; CHECK-NEXT: cmp x[[MREG]], w[[MREG]], sxtw -; CHECK-NEXT: cset {{w[0-9]+}}, ne %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 @@ -212,12 +515,34 @@ entry: } define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: smulo.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, ne +; SDAG-NEXT: str x8, [x2] +; 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: cmp x9, x8, asr #63 +; FAST-NEXT: cset w9, ne +; FAST-NEXT: str x8, [x2] +; FAST-NEXT: and w0, w9, #0x1 +; FAST-NEXT: ret +; +; GISEL-LABEL: smulo.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: mul x8, x0, x1 +; GISEL-NEXT: smulh x9, x0, x1 +; GISEL-NEXT: cmp x9, x8, asr #63 +; GISEL-NEXT: cset w0, ne +; GISEL-NEXT: str x8, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo.i64 -; CHECK: mul [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 -; CHECK-NEXT: cset {{w[0-9]+}}, ne %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 @@ -226,10 +551,29 @@ entry: } define zeroext i1 @smulo2.i64(i64 %v1, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: smulo2.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x0 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo2.i64 -; CHECK: adds [[MREG:x[0-9]+]], x0, x0 -; CHECK-NEXT: cset {{w[0-9]+}}, vs %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 @@ -238,11 +582,34 @@ entry: } define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: umulo.i32: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: umull x8, w0, w1 +; SDAG-NEXT: tst x8, #0xffffffff00000000 +; SDAG-NEXT: cset w0, ne +; SDAG-NEXT: str w8, [x2] +; SDAG-NEXT: ret +; +; FAST-LABEL: umulo.i32: +; FAST: // %bb.0: // %entry +; FAST-NEXT: umull x8, w0, w1 +; FAST-NEXT: tst x8, #0xffffffff00000000 +; FAST-NEXT: cset w9, ne +; FAST-NEXT: and w0, w9, #0x1 +; FAST-NEXT: str w8, [x2] +; 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: cmp w8, #0 +; GISEL-NEXT: cset w8, ne +; GISEL-NEXT: mov w0, w8 +; GISEL-NEXT: str w9, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo.i32 -; CHECK: umull [[MREG:x[0-9]+]], w0, w1 -; CHECK-NEXT: tst [[MREG]], #0xffffffff00000000 -; CHECK-NEXT: cset {{w[0-9]+}}, ne %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 @@ -251,11 +618,37 @@ entry: } define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %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 w8, ne +; SDAG-NEXT: mov w0, w8 +; 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 w8, w8, #0x1 +; FAST-NEXT: mov w0, w8 +; 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 w8, ne +; GISEL-NEXT: mov w0, w8 +; GISEL-NEXT: str x9, [x2] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo.i64 -; CHECK: umulh [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp xzr, [[MREG]] -; CHECK-NEXT: cset {{w[0-9]+}}, ne %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 @@ -264,10 +657,29 @@ entry: } define zeroext i1 @umulo2.i64(i64 %v1, i64* %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: and w0, w9, #0x1 +; FAST-NEXT: str x8, [x1] +; FAST-NEXT: ret +; +; GISEL-LABEL: umulo2.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x0 +; GISEL-NEXT: cset w9, hs +; GISEL-NEXT: ubfx w0, w9, #0, #1 +; GISEL-NEXT: str x8, [x1] +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo2.i64 -; CHECK: adds [[MREG:x[0-9]+]], x0, x0 -; CHECK-NEXT: cset {{w[0-9]+}}, hs %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 @@ -280,10 +692,26 @@ entry: ; 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: -; CHECK-LABEL: saddo.select.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: csel w0, w0, w1, vs %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 @@ -291,10 +719,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo.not.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: cset w0, vc %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -302,10 +746,26 @@ entry: } 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: -; CHECK-LABEL: saddo.select.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: csel x0, x0, x1, vs %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 @@ -313,10 +773,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo.not.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: cset w0, vc %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -324,10 +800,26 @@ entry: } 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: -; CHECK-LABEL: uaddo.select.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: csel w0, w0, w1, hs %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 @@ -335,10 +827,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.not.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: cset w0, lo %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -346,10 +854,26 @@ entry: } 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: -; CHECK-LABEL: uaddo.select.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: csel x0, x0, x1, hs %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 @@ -357,10 +881,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.not.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: cset w0, lo %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -368,10 +908,26 @@ entry: } 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: -; CHECK-LABEL: ssubo.select.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: csel w0, w0, w1, vs %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 @@ -379,10 +935,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo.not.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: cset w0, vc %t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -390,10 +962,26 @@ entry: } 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: -; CHECK-LABEL: ssubo.select.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: csel x0, x0, x1, vs %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 @@ -401,10 +989,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssub.not.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: cset w0, vc %t = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -412,10 +1016,26 @@ entry: } 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: -; CHECK-LABEL: usubo.select.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: csel w0, w0, w1, lo %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 @@ -423,10 +1043,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.not.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: cset w0, hs %t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -434,10 +1070,26 @@ entry: } 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: -; CHECK-LABEL: usubo.select.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: csel x0, x0, x1, lo %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 @@ -445,10 +1097,26 @@ entry: } 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 w8, w8, #0x1 +; GISEL-NEXT: and w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.not.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: cset w0, hs %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -456,11 +1124,29 @@ entry: } 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: -; CHECK-LABEL: smulo.select.i32 -; CHECK: smull x[[MREG:[0-9]+]], w0, w1 -; CHECK-NEXT: cmp x[[MREG]], w[[MREG]], sxtw -; CHECK-NEXT: csel w0, w0, w1, ne %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 @@ -468,11 +1154,30 @@ entry: } 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: -; CHECK-LABEL: smulo.not.i32 -; CHECK: smull x[[MREG:[0-9]+]], w0, w1 -; CHECK-NEXT: cmp x[[MREG]], w[[MREG]], sxtw -; CHECK-NEXT: cset w0, eq %t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -480,12 +1185,14 @@ entry: } define i64 @smulo.select.i64(i64 %v1, i64 %v2) { +; CHECK-LABEL: smulo.select.i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mul x8, x0, x1 +; CHECK-NEXT: smulh x9, x0, x1 +; CHECK-NEXT: cmp x9, x8, asr #63 +; CHECK-NEXT: csel x0, x0, x1, ne +; CHECK-NEXT: ret entry: -; CHECK-LABEL: smulo.select.i64 -; CHECK: mul [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 -; CHECK-NEXT: csel x0, x0, x1, ne %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 @@ -493,12 +1200,31 @@ entry: } 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: mul x8, x0, x1 +; GISEL-NEXT: smulh x9, x0, x1 +; GISEL-NEXT: cmp x9, x8, asr #63 +; GISEL-NEXT: cset w8, ne +; GISEL-NEXT: eor w0, w8, #0x1 +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo.not.i64 -; CHECK: mul [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 -; CHECK-NEXT: cset w0, eq %t = call {i64, i1} @llvm.smul.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -506,11 +1232,28 @@ entry: } 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: -; CHECK-LABEL: umulo.select.i32 -; CHECK: umull [[MREG:x[0-9]+]], w0, w1 -; CHECK-NEXT: tst [[MREG]], #0xffffffff00000000 -; CHECK-NEXT: csel w0, w0, w1, ne %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 @@ -518,11 +1261,29 @@ entry: } 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: -; CHECK-LABEL: umulo.not.i32 -; CHECK: umull [[MREG:x[0-9]+]], w0, w1 -; CHECK-NEXT: tst [[MREG]], #0xffffffff00000000 -; CHECK-NEXT: cset w0, eq %t = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %v1, i32 %v2) %obit = extractvalue {i32, i1} %t, 1 %ret = xor i1 %obit, true @@ -530,11 +1291,27 @@ entry: } 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: -; CHECK-LABEL: umulo.select.i64 -; CHECK: umulh [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp xzr, [[MREG]] -; CHECK-NEXT: csel x0, x0, x1, ne %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 @@ -542,11 +1319,28 @@ entry: } 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: -; CHECK-LABEL: umulo.not.i64 -; CHECK: umulh [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp xzr, [[MREG]] -; CHECK-NEXT: cset w0, eq %t = call {i64, i1} @llvm.umul.with.overflow.i64(i64 %v1, i64 %v2) %obit = extractvalue {i64, i1} %t, 1 %ret = xor i1 %obit, true @@ -554,14 +1348,821 @@ entry: } +define i8 @uaddo.selectboth.i8(i8 %a, i8 %b) { +; SDAG-LABEL: uaddo.selectboth.i8: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: and w8, w0, #0xff +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: add w8, w8, w1, uxtb +; SDAG-NEXT: tst w8, #0x100 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: uaddo.selectboth.i8: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w0, #0xff +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: add w8, w8, w1, uxtb +; FAST-NEXT: tst w8, #0x100 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.selectboth.i8: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w1, #0xff +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: add w8, w8, w0, uxtb +; GISEL-NEXT: cmp w8, w8, uxtb +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w0 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: add w8, w8, w1, sxtb +; SDAG-NEXT: cmp w8, w8, sxtb +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: saddo.selectboth.i8: +; FAST: // %bb.0: // %entry +; FAST-NEXT: sxtb w8, w0 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: add w8, w8, w1, sxtb +; FAST-NEXT: cmp w8, w8, sxtb +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo.selectboth.i8: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: sxtb w8, w1 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: add w8, w8, w0, sxtb +; GISEL-NEXT: cmp w8, w8, sxtb +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w0, #0xffff +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: add w8, w8, w1, uxth +; SDAG-NEXT: tst w8, #0x10000 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: uaddo.selectboth.i16: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w0, #0xffff +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: add w8, w8, w1, uxth +; FAST-NEXT: tst w8, #0x10000 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.selectboth.i16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w1, #0xffff +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: add w8, w8, w0, uxth +; GISEL-NEXT: cmp w8, w8, uxth +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w0 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: add w8, w8, w1, sxth +; SDAG-NEXT: cmp w8, w8, sxth +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: saddo.selectboth.i16: +; FAST: // %bb.0: // %entry +; FAST-NEXT: sxth w8, w0 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: add w8, w8, w1, sxth +; FAST-NEXT: cmp w8, w8, sxth +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo.selectboth.i16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: sxth w8, w1 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: add w8, w8, w0, sxth +; GISEL-NEXT: cmp w8, w8, sxth +; GISEL-NEXT: csel w0, w8, w9, 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: adds w8, w0, w1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, hs +; SDAG-NEXT: ret +; +; FAST-LABEL: uaddo.selectboth.i32: +; FAST: // %bb.0: // %entry +; FAST-NEXT: adds w8, w0, w1 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, hs +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.selectboth.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, w1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, hs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel w0, w8, w10, 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: adds w8, w0, w1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, vs +; SDAG-NEXT: ret +; +; FAST-LABEL: saddo.selectboth.i32: +; FAST: // %bb.0: // %entry +; FAST-NEXT: adds w8, w0, w1 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, vs +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo.selectboth.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w0, w1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel w0, w8, w10, 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: adds x8, x0, x1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel x0, x8, x9, hs +; SDAG-NEXT: ret +; +; FAST-LABEL: uaddo.selectboth.i64: +; FAST: // %bb.0: // %entry +; FAST-NEXT: adds x8, x0, x1 +; FAST-NEXT: mov x9, #10 +; FAST-NEXT: csel x0, x8, x9, hs +; FAST-NEXT: ret +; +; GISEL-LABEL: uaddo.selectboth.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, hs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel x0, x8, x10, 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: adds x8, x0, x1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel x0, x8, x9, vs +; SDAG-NEXT: ret +; +; FAST-LABEL: saddo.selectboth.i64: +; FAST: // %bb.0: // %entry +; FAST-NEXT: adds x8, x0, x1 +; FAST-NEXT: mov x9, #10 +; FAST-NEXT: csel x0, x8, x9, vs +; FAST-NEXT: ret +; +; GISEL-LABEL: saddo.selectboth.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds x8, x0, x1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel x0, x8, x10, 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 w8, w0, #0xff +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: sub w8, w8, w1, uxtb +; SDAG-NEXT: tst w8, #0xffffff00 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: usubo.selectboth.i8: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w0, #0xff +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: sub w8, w8, w1, uxtb +; FAST-NEXT: tst w8, #0xffffff00 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.selectboth.i8: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w0, #0xff +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: sub w8, w8, w1, uxtb +; GISEL-NEXT: cmp w8, w8, uxtb +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w0 +; CHECK-NEXT: mov w9, #10 +; CHECK-NEXT: sub w8, w8, w1, sxtb +; CHECK-NEXT: cmp w8, w8, sxtb +; CHECK-NEXT: csel w0, w8, w9, 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 w8, w0, #0xffff +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: sub w8, w8, w1, uxth +; SDAG-NEXT: tst w8, #0xffff0000 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: usubo.selectboth.i16: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w0, #0xffff +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: sub w8, w8, w1, uxth +; FAST-NEXT: tst w8, #0xffff0000 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.selectboth.i16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w0, #0xffff +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: sub w8, w8, w1, uxth +; GISEL-NEXT: cmp w8, w8, uxth +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w0 +; CHECK-NEXT: mov w9, #10 +; CHECK-NEXT: sub w8, w8, w1, sxth +; CHECK-NEXT: cmp w8, w8, sxth +; CHECK-NEXT: csel w0, w8, w9, 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: subs w8, w0, w1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, lo +; SDAG-NEXT: ret +; +; FAST-LABEL: usubo.selectboth.i32: +; FAST: // %bb.0: // %entry +; FAST-NEXT: subs w8, w0, w1 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, lo +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.selectboth.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs w8, w0, w1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, lo +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel w0, w8, w10, 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: subs w8, w0, w1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, vs +; SDAG-NEXT: ret +; +; FAST-LABEL: ssubo.selectboth.i32: +; FAST: // %bb.0: // %entry +; FAST-NEXT: subs w8, w0, w1 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, vs +; FAST-NEXT: ret +; +; GISEL-LABEL: ssubo.selectboth.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs w8, w0, w1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel w0, w8, w10, 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: subs x8, x0, x1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel x0, x8, x9, lo +; SDAG-NEXT: ret +; +; FAST-LABEL: usubo.selectboth.i64: +; FAST: // %bb.0: // %entry +; FAST-NEXT: subs x8, x0, x1 +; FAST-NEXT: mov x9, #10 +; FAST-NEXT: csel x0, x8, x9, lo +; FAST-NEXT: ret +; +; GISEL-LABEL: usubo.selectboth.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs x8, x0, x1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, lo +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel x0, x8, x10, 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: subs x8, x0, x1 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel x0, x8, x9, vs +; SDAG-NEXT: ret +; +; FAST-LABEL: ssubo.selectboth.i64: +; FAST: // %bb.0: // %entry +; FAST-NEXT: subs x8, x0, x1 +; FAST-NEXT: mov x9, #10 +; FAST-NEXT: csel x0, x8, x9, vs +; FAST-NEXT: ret +; +; GISEL-LABEL: ssubo.selectboth.i64: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: subs x8, x0, x1 +; GISEL-NEXT: mov w10, #10 +; GISEL-NEXT: cset w9, vs +; GISEL-NEXT: tst w9, #0x1 +; GISEL-NEXT: csel x0, x8, x10, 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 w8, w1, #0xff +; SDAG-NEXT: and w9, w0, #0xff +; SDAG-NEXT: mul w8, w9, w8 +; SDAG-NEXT: lsr w9, w8, #8 +; SDAG-NEXT: cmp w9, #0 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: umulo.selectboth.i8: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w1, #0xff +; FAST-NEXT: and w9, w0, #0xff +; FAST-NEXT: mul w8, w9, w8 +; FAST-NEXT: lsr w9, w8, #8 +; FAST-NEXT: cmp w9, #0 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: umulo.selectboth.i8: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w0, #0xff +; GISEL-NEXT: and w9, w1, #0xff +; GISEL-NEXT: mul w8, w8, w9 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: cmp w8, w8, uxtb +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w1 +; SDAG-NEXT: sxtb w9, w0 +; SDAG-NEXT: mul w8, w9, w8 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: cmp w8, w8, sxtb +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: smulo.selectboth.i8: +; FAST: // %bb.0: // %entry +; FAST-NEXT: sxtb w8, w1 +; FAST-NEXT: sxtb w9, w0 +; FAST-NEXT: mul w8, w9, w8 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: cmp w8, w8, sxtb +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: smulo.selectboth.i8: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: sxtb w8, w0 +; GISEL-NEXT: sxtb w9, w1 +; GISEL-NEXT: mul w8, w8, w9 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: cmp w8, w8, sxtb +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w1, #0xffff +; SDAG-NEXT: and w9, w0, #0xffff +; SDAG-NEXT: mul w8, w9, w8 +; SDAG-NEXT: lsr w9, w8, #16 +; SDAG-NEXT: cmp w9, #0 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: umulo.selectboth.i16: +; FAST: // %bb.0: // %entry +; FAST-NEXT: and w8, w1, #0xffff +; FAST-NEXT: and w9, w0, #0xffff +; FAST-NEXT: mul w8, w9, w8 +; FAST-NEXT: lsr w9, w8, #16 +; FAST-NEXT: cmp w9, #0 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: umulo.selectboth.i16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: and w8, w0, #0xffff +; GISEL-NEXT: and w9, w1, #0xffff +; GISEL-NEXT: mul w8, w8, w9 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: cmp w8, w8, uxth +; GISEL-NEXT: csel w0, w8, w9, 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 w8, w1 +; SDAG-NEXT: sxth w9, w0 +; SDAG-NEXT: mul w8, w9, w8 +; SDAG-NEXT: mov w9, #10 +; SDAG-NEXT: cmp w8, w8, sxth +; SDAG-NEXT: csel w0, w8, w9, ne +; SDAG-NEXT: ret +; +; FAST-LABEL: smulo.selectboth.i16: +; FAST: // %bb.0: // %entry +; FAST-NEXT: sxth w8, w1 +; FAST-NEXT: sxth w9, w0 +; FAST-NEXT: mul w8, w9, w8 +; FAST-NEXT: mov w9, #10 +; FAST-NEXT: cmp w8, w8, sxth +; FAST-NEXT: csel w0, w8, w9, ne +; FAST-NEXT: ret +; +; GISEL-LABEL: smulo.selectboth.i16: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: sxth w8, w0 +; GISEL-NEXT: sxth w9, w1 +; GISEL-NEXT: mul w8, w8, w9 +; GISEL-NEXT: mov w9, #10 +; GISEL-NEXT: cmp w8, w8, sxth +; GISEL-NEXT: csel w0, w8, w9, 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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 +; 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: mul x9, x0, x1 +; GISEL-NEXT: mov w8, #10 +; GISEL-NEXT: smulh x10, x0, x1 +; GISEL-NEXT: cmp x10, x9, asr #63 +; GISEL-NEXT: csel x0, x9, 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 w9, #1 +; FAST-NEXT: cset w8, vs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo.br.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: b.vc %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 @@ -575,10 +2176,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, vs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: saddo.br.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: b.vc %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 @@ -592,10 +2212,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, hs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.br.i32 -; CHECK: cmn w0, w1 -; CHECK-NEXT: b.lo %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 @@ -609,10 +2248,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, hs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: uaddo.br.i64 -; CHECK: cmn x0, x1 -; CHECK-NEXT: b.lo %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 @@ -626,10 +2284,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, vs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo.br.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: b.vc %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 @@ -643,10 +2320,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, vs +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: ssubo.br.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: b.vc %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 @@ -660,10 +2356,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, lo +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.br.i32 -; CHECK: cmp w0, w1 -; CHECK-NEXT: b.hs %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 @@ -677,10 +2392,29 @@ continue: } 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 w9, #1 +; FAST-NEXT: cset w8, lo +; FAST-NEXT: bic w8, w9, w8 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: usubo.br.i64 -; CHECK: cmp x0, x1 -; CHECK-NEXT: b.hs %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 @@ -694,11 +2428,32 @@ continue: } 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 +; 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 w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo.br.i32 -; CHECK: smull x[[MREG:[0-9]+]], w0, w1 -; CHECK-NEXT: cmp x[[MREG]], w[[MREG]], sxtw -; CHECK-NEXT: b.eq %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 @@ -712,12 +2467,33 @@ continue: } 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 +; 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: mul x8, x0, x1 +; GISEL-NEXT: smulh x9, x0, x1 +; GISEL-NEXT: cmp x9, x8, asr #63 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo.br.i64 -; CHECK: mul [[MREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: smulh [[HREG:x[0-9]+]], x0, x1 -; CHECK-NEXT: cmp [[HREG]], [[MREG]], asr #63 -; CHECK-NEXT: b.eq %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 @@ -731,10 +2507,29 @@ continue: } 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 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: smulo2.br.i64 -; CHECK: cmn x0, x0 -; CHECK-NEXT: b.vc %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 @@ -748,11 +2543,31 @@ continue: } 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 +; 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 w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo.br.i32 -; CHECK: umull [[MREG:x[0-9]+]], w0, w1 -; CHECK-NEXT: tst [[MREG]], #0xffffffff00000000 -; CHECK-NEXT: b.eq %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 @@ -766,10 +2581,30 @@ continue: } 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 +; 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 w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo.br.i64 -; CHECK: umulh [[REG:x[0-9]+]], x0, x1 -; CHECK-NEXT: {{cbz|cmp}} %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 @@ -783,10 +2618,29 @@ continue: } 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 +; 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: tst w8, #0x1 +; GISEL-NEXT: cset w0, eq +; GISEL-NEXT: ret entry: -; CHECK-LABEL: umulo2.br.i64 -; CHECK: cmn x0, x0 -; CHECK-NEXT: b.lo %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 @@ -799,16 +2653,28 @@ continue: ret i1 true } +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