From: Amaury Sechet Date: Mon, 27 Feb 2017 18:32:54 +0000 (+0000) Subject: Refactor xaluo.ll and xmulo.ll tests. NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6cc2c9efb9bf4b9071f814c9d282db91397d5d70;p=llvm Refactor xaluo.ll and xmulo.ll tests. NFC git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296367 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/CodeGen/X86/xaluo.ll b/test/CodeGen/X86/xaluo.ll index 57e6b4a5042..c78e7d8d04b 100644 --- a/test/CodeGen/X86/xaluo.ll +++ b/test/CodeGen/X86/xaluo.ll @@ -1,16 +1,35 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=x86_64-darwin-unknown < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG -; RUN: llc -mtriple=x86_64-darwin-unknown -fast-isel -fast-isel-abort=1 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST +; RUN: llc -mtriple=x86_64-darwin-unknown < %s | FileCheck %s --check-prefix=SDAG +; RUN: llc -mtriple=x86_64-darwin-unknown -fast-isel -fast-isel-abort=1 < %s | FileCheck %s --check-prefix=FAST ; RUN: llc -mtriple=x86_64-darwin-unknown -mcpu=knl < %s | FileCheck %s --check-prefix=KNL + ; ; Get the actual value of the overflow bit. ; ; SADDO reg, reg -define zeroext i1 @saddo.i8(i8 signext %v1, i8 signext %v2, i8* %res) { -entry: -; CHECK-LABEL: saddo.i8 -; CHECK: addb %sil, %dil -; CHECK-NEXT: seto %al +define zeroext i1 @saddoi8(i8 signext %v1, i8 signext %v2, i8* %res) { +; SDAG-LABEL: saddoi8: +; SDAG: ## BB#0: +; SDAG-NEXT: addb %sil, %dil +; SDAG-NEXT: seto %al +; SDAG-NEXT: movb %dil, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi8: +; FAST: ## BB#0: +; FAST-NEXT: addb %sil, %dil +; FAST-NEXT: seto %al +; FAST-NEXT: movb %dil, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi8: +; KNL: ## BB#0: +; KNL-NEXT: addb %sil, %dil +; KNL-NEXT: seto %al +; KNL-NEXT: movb %dil, (%rdx) +; KNL-NEXT: retq %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v1, i8 %v2) %val = extractvalue {i8, i1} %t, 0 %obit = extractvalue {i8, i1} %t, 1 @@ -18,11 +37,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i16(i16 %v1, i16 %v2, i16* %res) { -entry: -; CHECK-LABEL: saddo.i16 -; CHECK: addw %si, %di -; CHECK-NEXT: seto %al +define zeroext i1 @saddoi16(i16 %v1, i16 %v2, i16* %res) { +; SDAG-LABEL: saddoi16: +; SDAG: ## BB#0: +; SDAG-NEXT: addw %si, %di +; SDAG-NEXT: seto %al +; SDAG-NEXT: movw %di, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi16: +; FAST: ## BB#0: +; FAST-NEXT: addw %si, %di +; FAST-NEXT: seto %al +; FAST-NEXT: movw %di, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi16: +; KNL: ## BB#0: +; KNL-NEXT: addw %si, %di +; KNL-NEXT: seto %al +; KNL-NEXT: movw %di, (%rdx) +; KNL-NEXT: retq %t = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %v1, i16 %v2) %val = extractvalue {i16, i1} %t, 0 %obit = extractvalue {i16, i1} %t, 1 @@ -30,11 +67,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: saddo.i32 -; CHECK: addl %esi, %edi -; CHECK-NEXT: seto %al +define zeroext i1 @saddoi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: saddoi32: +; SDAG: ## BB#0: +; SDAG-NEXT: addl %esi, %edi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movl %edi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi32: +; FAST: ## BB#0: +; FAST-NEXT: addl %esi, %edi +; FAST-NEXT: seto %al +; FAST-NEXT: movl %edi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi32: +; KNL: ## BB#0: +; KNL-NEXT: addl %esi, %edi +; KNL-NEXT: seto %al +; KNL-NEXT: movl %edi, (%rdx) +; KNL-NEXT: retq %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 @@ -42,11 +97,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: saddo.i64 -; CHECK: addq %rsi, %rdi -; CHECK-NEXT: seto %al +define zeroext i1 @saddoi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: saddoi64: +; SDAG: ## BB#0: +; SDAG-NEXT: addq %rsi, %rdi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64: +; FAST: ## BB#0: +; FAST-NEXT: addq %rsi, %rdi +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64: +; KNL: ## BB#0: +; KNL-NEXT: addq %rsi, %rdi +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rdx) +; KNL-NEXT: retq %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 @@ -55,11 +128,29 @@ entry: } ; SADDO reg, 1 | INC -define zeroext i1 @saddo.inc.i8(i8 %v1, i8* %res) { -entry: -; CHECK-LABEL: saddo.inc.i8 -; CHECK: incb %dil -; CHECK-NEXT: seto %al +define zeroext i1 @saddoinci8(i8 %v1, i8* %res) { +; SDAG-LABEL: saddoinci8: +; SDAG: ## BB#0: +; SDAG-NEXT: incb %dil +; SDAG-NEXT: seto %al +; SDAG-NEXT: movb %dil, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoinci8: +; FAST: ## BB#0: +; FAST-NEXT: incb %dil +; FAST-NEXT: seto %al +; FAST-NEXT: movb %dil, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoinci8: +; KNL: ## BB#0: +; KNL-NEXT: incb %dil +; KNL-NEXT: seto %al +; KNL-NEXT: movb %dil, (%rsi) +; KNL-NEXT: retq %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v1, i8 1) %val = extractvalue {i8, i1} %t, 0 %obit = extractvalue {i8, i1} %t, 1 @@ -67,11 +158,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.inc.i16(i16 %v1, i16* %res) { -entry: -; CHECK-LABEL: saddo.inc.i16 -; CHECK: incw %di -; CHECK-NEXT: seto %al +define zeroext i1 @saddoinci16(i16 %v1, i16* %res) { +; SDAG-LABEL: saddoinci16: +; SDAG: ## BB#0: +; SDAG-NEXT: incw %di +; SDAG-NEXT: seto %al +; SDAG-NEXT: movw %di, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoinci16: +; FAST: ## BB#0: +; FAST-NEXT: incw %di +; FAST-NEXT: seto %al +; FAST-NEXT: movw %di, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoinci16: +; KNL: ## BB#0: +; KNL-NEXT: incw %di +; KNL-NEXT: seto %al +; KNL-NEXT: movw %di, (%rsi) +; KNL-NEXT: retq %t = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %v1, i16 1) %val = extractvalue {i16, i1} %t, 0 %obit = extractvalue {i16, i1} %t, 1 @@ -79,11 +188,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.inc.i32(i32 %v1, i32* %res) { -entry: -; CHECK-LABEL: saddo.inc.i32 -; CHECK: incl %edi -; CHECK-NEXT: seto %al +define zeroext i1 @saddoinci32(i32 %v1, i32* %res) { +; SDAG-LABEL: saddoinci32: +; SDAG: ## BB#0: +; SDAG-NEXT: incl %edi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movl %edi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoinci32: +; FAST: ## BB#0: +; FAST-NEXT: incl %edi +; FAST-NEXT: seto %al +; FAST-NEXT: movl %edi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoinci32: +; KNL: ## BB#0: +; KNL-NEXT: incl %edi +; KNL-NEXT: seto %al +; KNL-NEXT: movl %edi, (%rsi) +; KNL-NEXT: retq %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %v1, i32 1) %val = extractvalue {i32, i1} %t, 0 %obit = extractvalue {i32, i1} %t, 1 @@ -91,11 +218,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.inc.i64(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: saddo.inc.i64 -; CHECK: incq %rdi -; CHECK-NEXT: seto %al +define zeroext i1 @saddoinci64(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoinci64: +; SDAG: ## BB#0: +; SDAG-NEXT: incq %rdi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoinci64: +; FAST: ## BB#0: +; FAST-NEXT: incq %rdi +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoinci64: +; KNL: ## BB#0: +; KNL-NEXT: incq %rdi +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 1) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -105,15 +250,31 @@ entry: ; SADDO reg, imm | imm, reg ; FIXME: DAG doesn't optimize immediates on the LHS. -define zeroext i1 @saddo.i64imm1(i64 %v1, i64* %res) { -entry: -; SDAG-LABEL: saddo.i64imm1 -; SDAG: mov -; SDAG-NEXT: addq -; SDAG-NEXT: seto -; FAST-LABEL: saddo.i64imm1 -; FAST: addq $2, %rdi -; FAST-NEXT: seto %al +define zeroext i1 @saddoi64imm1(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoi64imm1: +; SDAG: ## BB#0: +; SDAG-NEXT: movl $2, %ecx +; SDAG-NEXT: addq %rdi, %rcx +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rcx, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64imm1: +; FAST: ## BB#0: +; FAST-NEXT: addq $2, %rdi +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64imm1: +; KNL: ## BB#0: +; KNL-NEXT: movl $2, %ecx +; KNL-NEXT: addq %rdi, %rcx +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rcx, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 2, i64 %v1) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -122,11 +283,29 @@ entry: } ; Check boundary conditions for large immediates. -define zeroext i1 @saddo.i64imm2(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: saddo.i64imm2 -; CHECK: addq $-2147483648, %rdi -; CHECK-NEXT: seto %al +define zeroext i1 @saddoi64imm2(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoi64imm2: +; SDAG: ## BB#0: +; SDAG-NEXT: addq $-2147483648, %rdi ## imm = 0x80000000 +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64imm2: +; FAST: ## BB#0: +; FAST-NEXT: addq $-2147483648, %rdi ## imm = 0x80000000 +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64imm2: +; KNL: ## BB#0: +; KNL-NEXT: addq $-2147483648, %rdi ## imm = 0x80000000 +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -2147483648) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -134,12 +313,32 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i64imm3(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: saddo.i64imm3 -; CHECK: movabsq $-21474836489, %[[REG:[a-z]+]] -; CHECK-NEXT: addq %rdi, %[[REG]] -; CHECK-NEXT: seto +define zeroext i1 @saddoi64imm3(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoi64imm3: +; SDAG: ## BB#0: +; SDAG-NEXT: movabsq $-21474836489, %rcx ## imm = 0xFFFFFFFAFFFFFFF7 +; SDAG-NEXT: addq %rdi, %rcx +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rcx, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64imm3: +; FAST: ## BB#0: +; FAST-NEXT: movabsq $-21474836489, %rax ## imm = 0xFFFFFFFAFFFFFFF7 +; FAST-NEXT: addq %rdi, %rax +; FAST-NEXT: seto %cl +; FAST-NEXT: movq %rax, (%rsi) +; FAST-NEXT: andb $1, %cl +; FAST-NEXT: movzbl %cl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64imm3: +; KNL: ## BB#0: +; KNL-NEXT: movabsq $-21474836489, %rcx ## imm = 0xFFFFFFFAFFFFFFF7 +; KNL-NEXT: addq %rdi, %rcx +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rcx, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -21474836489) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -147,11 +346,29 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i64imm4(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: saddo.i64imm4 -; CHECK: addq $2147483647, %rdi -; CHECK-NEXT: seto +define zeroext i1 @saddoi64imm4(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoi64imm4: +; SDAG: ## BB#0: +; SDAG-NEXT: addq $2147483647, %rdi ## imm = 0x7FFFFFFF +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64imm4: +; FAST: ## BB#0: +; FAST-NEXT: addq $2147483647, %rdi ## imm = 0x7FFFFFFF +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64imm4: +; KNL: ## BB#0: +; KNL-NEXT: addq $2147483647, %rdi ## imm = 0x7FFFFFFF +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 2147483647) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -159,12 +376,32 @@ entry: ret i1 %obit } -define zeroext i1 @saddo.i64imm5(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: saddo.i64imm5 -; CHECK: movl $2147483648 -; CHECK: addq %rdi -; CHECK-NEXT: seto +define zeroext i1 @saddoi64imm5(i64 %v1, i64* %res) { +; SDAG-LABEL: saddoi64imm5: +; SDAG: ## BB#0: +; SDAG-NEXT: movl $2147483648, %ecx ## imm = 0x80000000 +; SDAG-NEXT: addq %rdi, %rcx +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rcx, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoi64imm5: +; FAST: ## BB#0: +; FAST-NEXT: movl $2147483648, %eax ## imm = 0x80000000 +; FAST-NEXT: addq %rdi, %rax +; FAST-NEXT: seto %cl +; FAST-NEXT: movq %rax, (%rsi) +; FAST-NEXT: andb $1, %cl +; FAST-NEXT: movzbl %cl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoi64imm5: +; KNL: ## BB#0: +; KNL-NEXT: movl $2147483648, %ecx ## imm = 0x80000000 +; KNL-NEXT: addq %rdi, %rcx +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rcx, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 2147483648) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -173,11 +410,29 @@ entry: } ; UADDO -define zeroext i1 @uaddo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: uaddo.i32 -; CHECK: addl %esi, %edi -; CHECK-NEXT: setb %al +define zeroext i1 @uaddoi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: uaddoi32: +; SDAG: ## BB#0: +; SDAG-NEXT: addl %esi, %edi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movl %edi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoi32: +; FAST: ## BB#0: +; FAST-NEXT: addl %esi, %edi +; FAST-NEXT: setb %al +; FAST-NEXT: movl %edi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoi32: +; KNL: ## BB#0: +; KNL-NEXT: addl %esi, %edi +; KNL-NEXT: setb %al +; KNL-NEXT: movl %edi, (%rdx) +; KNL-NEXT: retq %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 @@ -185,11 +440,29 @@ entry: ret i1 %obit } -define zeroext i1 @uaddo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: uaddo.i64 -; CHECK: addq %rsi, %rdi -; CHECK-NEXT: setb %al +define zeroext i1 @uaddoi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: uaddoi64: +; SDAG: ## BB#0: +; SDAG-NEXT: addq %rsi, %rdi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movq %rdi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoi64: +; FAST: ## BB#0: +; FAST-NEXT: addq %rsi, %rdi +; FAST-NEXT: setb %al +; FAST-NEXT: movq %rdi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoi64: +; KNL: ## BB#0: +; KNL-NEXT: addq %rsi, %rdi +; KNL-NEXT: setb %al +; KNL-NEXT: movq %rdi, (%rdx) +; KNL-NEXT: retq %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 @@ -198,10 +471,29 @@ entry: } ; UADDO reg, 1 | NOT INC -define zeroext i1 @uaddo.inc.i8(i8 %v1, i8* %res) { -entry: -; CHECK-LABEL: uaddo.inc.i8 -; CHECK-NOT: incb %dil +define zeroext i1 @uaddoinci8(i8 %v1, i8* %res) { +; SDAG-LABEL: uaddoinci8: +; SDAG: ## BB#0: +; SDAG-NEXT: addb $1, %dil +; SDAG-NEXT: setb %al +; SDAG-NEXT: movb %dil, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoinci8: +; FAST: ## BB#0: +; FAST-NEXT: addb $1, %dil +; FAST-NEXT: setb %al +; FAST-NEXT: movb %dil, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoinci8: +; KNL: ## BB#0: +; KNL-NEXT: addb $1, %dil +; KNL-NEXT: setb %al +; KNL-NEXT: movb %dil, (%rsi) +; KNL-NEXT: retq %t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %v1, i8 1) %val = extractvalue {i8, i1} %t, 0 %obit = extractvalue {i8, i1} %t, 1 @@ -209,10 +501,29 @@ entry: ret i1 %obit } -define zeroext i1 @uaddo.inc.i16(i16 %v1, i16* %res) { -entry: -; CHECK-LABEL: uaddo.inc.i16 -; CHECK-NOT: incw %di +define zeroext i1 @uaddoinci16(i16 %v1, i16* %res) { +; SDAG-LABEL: uaddoinci16: +; SDAG: ## BB#0: +; SDAG-NEXT: addw $1, %di +; SDAG-NEXT: setb %al +; SDAG-NEXT: movw %di, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoinci16: +; FAST: ## BB#0: +; FAST-NEXT: addw $1, %di +; FAST-NEXT: setb %al +; FAST-NEXT: movw %di, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoinci16: +; KNL: ## BB#0: +; KNL-NEXT: addw $1, %di +; KNL-NEXT: setb %al +; KNL-NEXT: movw %di, (%rsi) +; KNL-NEXT: retq %t = call {i16, i1} @llvm.uadd.with.overflow.i16(i16 %v1, i16 1) %val = extractvalue {i16, i1} %t, 0 %obit = extractvalue {i16, i1} %t, 1 @@ -220,10 +531,29 @@ entry: ret i1 %obit } -define zeroext i1 @uaddo.inc.i32(i32 %v1, i32* %res) { -entry: -; CHECK-LABEL: uaddo.inc.i32 -; CHECK-NOT: incl %edi +define zeroext i1 @uaddoinci32(i32 %v1, i32* %res) { +; SDAG-LABEL: uaddoinci32: +; SDAG: ## BB#0: +; SDAG-NEXT: addl $1, %edi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movl %edi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoinci32: +; FAST: ## BB#0: +; FAST-NEXT: addl $1, %edi +; FAST-NEXT: setb %al +; FAST-NEXT: movl %edi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoinci32: +; KNL: ## BB#0: +; KNL-NEXT: addl $1, %edi +; KNL-NEXT: setb %al +; KNL-NEXT: movl %edi, (%rsi) +; KNL-NEXT: retq %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 1) %val = extractvalue {i32, i1} %t, 0 %obit = extractvalue {i32, i1} %t, 1 @@ -231,10 +561,29 @@ entry: ret i1 %obit } -define zeroext i1 @uaddo.inc.i64(i64 %v1, i64* %res) { -entry: -; CHECK-LABEL: uaddo.inc.i64 -; CHECK-NOT: incq %rdi +define zeroext i1 @uaddoinci64(i64 %v1, i64* %res) { +; SDAG-LABEL: uaddoinci64: +; SDAG: ## BB#0: +; SDAG-NEXT: addq $1, %rdi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movq %rdi, (%rsi) +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoinci64: +; FAST: ## BB#0: +; FAST-NEXT: addq $1, %rdi +; FAST-NEXT: setb %al +; FAST-NEXT: movq %rdi, (%rsi) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoinci64: +; KNL: ## BB#0: +; KNL-NEXT: addq $1, %rdi +; KNL-NEXT: setb %al +; KNL-NEXT: movq %rdi, (%rsi) +; KNL-NEXT: retq %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %v1, i64 1) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -243,11 +592,29 @@ entry: } ; SSUBO -define zeroext i1 @ssubo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: ssubo.i32 -; CHECK: subl %esi, %edi -; CHECK-NEXT: seto %al +define zeroext i1 @ssuboi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: ssuboi32: +; SDAG: ## BB#0: +; SDAG-NEXT: subl %esi, %edi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movl %edi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: ssuboi32: +; FAST: ## BB#0: +; FAST-NEXT: subl %esi, %edi +; FAST-NEXT: seto %al +; FAST-NEXT: movl %edi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: ssuboi32: +; KNL: ## BB#0: +; KNL-NEXT: subl %esi, %edi +; KNL-NEXT: seto %al +; KNL-NEXT: movl %edi, (%rdx) +; KNL-NEXT: retq %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 @@ -255,11 +622,29 @@ entry: ret i1 %obit } -define zeroext i1 @ssubo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: ssubo.i64 -; CHECK: subq %rsi, %rdi -; CHECK-NEXT: seto %al +define zeroext i1 @ssuboi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: ssuboi64: +; SDAG: ## BB#0: +; SDAG-NEXT: subq %rsi, %rdi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: ssuboi64: +; FAST: ## BB#0: +; FAST-NEXT: subq %rsi, %rdi +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: ssuboi64: +; KNL: ## BB#0: +; KNL-NEXT: subq %rsi, %rdi +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rdx) +; KNL-NEXT: retq %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 @@ -268,11 +653,29 @@ entry: } ; USUBO -define zeroext i1 @usubo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: usubo.i32 -; CHECK: subl %esi, %edi -; CHECK-NEXT: setb %al +define zeroext i1 @usuboi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: usuboi32: +; SDAG: ## BB#0: +; SDAG-NEXT: subl %esi, %edi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movl %edi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: usuboi32: +; FAST: ## BB#0: +; FAST-NEXT: subl %esi, %edi +; FAST-NEXT: setb %al +; FAST-NEXT: movl %edi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: usuboi32: +; KNL: ## BB#0: +; KNL-NEXT: subl %esi, %edi +; KNL-NEXT: setb %al +; KNL-NEXT: movl %edi, (%rdx) +; KNL-NEXT: retq %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 @@ -280,11 +683,29 @@ entry: ret i1 %obit } -define zeroext i1 @usubo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: usubo.i64 -; CHECK: subq %rsi, %rdi -; CHECK-NEXT: setb %al +define zeroext i1 @usuboi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: usuboi64: +; SDAG: ## BB#0: +; SDAG-NEXT: subq %rsi, %rdi +; SDAG-NEXT: setb %al +; SDAG-NEXT: movq %rdi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: usuboi64: +; FAST: ## BB#0: +; FAST-NEXT: subq %rsi, %rdi +; FAST-NEXT: setb %al +; FAST-NEXT: movq %rdi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: usuboi64: +; KNL: ## BB#0: +; KNL-NEXT: subq %rsi, %rdi +; KNL-NEXT: setb %al +; KNL-NEXT: movq %rdi, (%rdx) +; KNL-NEXT: retq %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 @@ -292,250 +713,277 @@ entry: ret i1 %obit } -; SMULO -define zeroext i1 @smulo.i8(i8 %v1, i8 %v2, i8* %res) { -entry: -; CHECK-LABEL: smulo.i8 -; CHECK: movl %edi, %eax -; CHECK-NEXT: imulb %sil -; CHECK-NEXT: seto %cl - %t = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %v1, i8 %v2) - %val = extractvalue {i8, i1} %t, 0 - %obit = extractvalue {i8, i1} %t, 1 - store i8 %val, i8* %res - ret i1 %obit -} - -define zeroext i1 @smulo.i16(i16 %v1, i16 %v2, i16* %res) { -entry: -; CHECK-LABEL: smulo.i16 -; CHECK: imulw %si, %di -; CHECK-NEXT: seto %al - %t = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %v1, i16 %v2) - %val = extractvalue {i16, i1} %t, 0 - %obit = extractvalue {i16, i1} %t, 1 - store i16 %val, i16* %res - ret i1 %obit -} - -define zeroext i1 @smulo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: smulo.i32 -; CHECK: imull %esi, %edi -; CHECK-NEXT: seto %al - %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, i32* %res - ret i1 %obit -} - -define zeroext i1 @smulo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: smulo.i64 -; CHECK: imulq %rsi, %rdi -; CHECK-NEXT: seto %al - %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, i64* %res - ret i1 %obit -} - -; UMULO -define zeroext i1 @umulo.i8(i8 %v1, i8 %v2, i8* %res) { -entry: -; CHECK-LABEL: umulo.i8 -; CHECK: movl %edi, %eax -; CHECK-NEXT: mulb %sil -; CHECK-NEXT: seto %cl - %t = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %v1, i8 %v2) - %val = extractvalue {i8, i1} %t, 0 - %obit = extractvalue {i8, i1} %t, 1 - store i8 %val, i8* %res - ret i1 %obit -} - -define zeroext i1 @umulo.i16(i16 %v1, i16 %v2, i16* %res) { -entry: -; CHECK-LABEL: umulo.i16 -; CHECK: mulw %si -; CHECK-NEXT: seto - %t = call {i16, i1} @llvm.umul.with.overflow.i16(i16 %v1, i16 %v2) - %val = extractvalue {i16, i1} %t, 0 - %obit = extractvalue {i16, i1} %t, 1 - store i16 %val, i16* %res - ret i1 %obit -} - -define zeroext i1 @umulo.i32(i32 %v1, i32 %v2, i32* %res) { -entry: -; CHECK-LABEL: umulo.i32 -; CHECK: mull %esi -; CHECK-NEXT: seto - %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, i32* %res - ret i1 %obit -} - -define zeroext i1 @umulo.i64(i64 %v1, i64 %v2, i64* %res) { -entry: -; CHECK-LABEL: umulo.i64 -; CHECK: mulq %rsi -; CHECK-NEXT: seto - %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, i64* %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) { -entry: -; CHECK-LABEL: saddo.select.i32 -; CHECK: addl %esi, %eax -; CHECK-NEXT: cmovol %edi, %esi +define i32 @saddoselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: saddoselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: addl %esi, %eax +; SDAG-NEXT: cmovol %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoselecti32: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: addl %esi, %eax +; FAST-NEXT: cmovol %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoselecti32: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: addl %esi, %eax +; KNL-NEXT: cmovol %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq %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 i64 @saddo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: saddo.select.i64 -; CHECK: addq %rsi, %rax -; CHECK-NEXT: cmovoq %rdi, %rsi +define i64 @saddoselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: saddoselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: addq %rsi, %rax +; SDAG-NEXT: cmovoq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: saddoselecti64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: addq %rsi, %rax +; FAST-NEXT: cmovoq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: saddoselecti64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: addq %rsi, %rax +; KNL-NEXT: cmovoq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq %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 i32 @uaddo.select.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: uaddo.select.i32 -; CHECK: addl %esi, %eax -; CHECK-NEXT: cmovbl %edi, %esi +define i32 @uaddoselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: uaddoselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: addl %esi, %eax +; SDAG-NEXT: cmovbl %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoselecti32: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: addl %esi, %eax +; FAST-NEXT: cmovbl %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoselecti32: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: addl %esi, %eax +; KNL-NEXT: cmovbl %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq %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 i64 @uaddo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: uaddo.select.i64 -; CHECK: addq %rsi, %rax -; CHECK-NEXT: cmovbq %rdi, %rsi +define i64 @uaddoselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: uaddoselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: addq %rsi, %rax +; SDAG-NEXT: cmovbq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoselecti64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: addq %rsi, %rax +; FAST-NEXT: cmovbq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddoselecti64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: addq %rsi, %rax +; KNL-NEXT: cmovbq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq %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 i32 @ssubo.select.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: ssubo.select.i32 -; CHECK: cmpl %esi, %edi -; CHECK-NEXT: cmovol %edi, %esi +define i32 @ssuboselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: ssuboselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpl %esi, %edi +; SDAG-NEXT: cmovol %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: ssuboselecti32: +; FAST: ## BB#0: +; FAST-NEXT: cmpl %esi, %edi +; FAST-NEXT: cmovol %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: ssuboselecti32: +; KNL: ## BB#0: +; KNL-NEXT: cmpl %esi, %edi +; KNL-NEXT: cmovol %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq %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 i64 @ssubo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: ssubo.select.i64 -; CHECK: cmpq %rsi, %rdi -; CHECK-NEXT: cmovoq %rdi, %rsi +define i64 @ssuboselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: ssuboselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpq %rsi, %rdi +; SDAG-NEXT: cmovoq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: ssuboselecti64: +; FAST: ## BB#0: +; FAST-NEXT: cmpq %rsi, %rdi +; FAST-NEXT: cmovoq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: ssuboselecti64: +; KNL: ## BB#0: +; KNL-NEXT: cmpq %rsi, %rdi +; KNL-NEXT: cmovoq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq %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 i32 @usubo.select.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: usubo.select.i32 -; CHECK: cmpl %esi, %edi -; CHECK-NEXT: cmovbl %edi, %esi +define i32 @usuboselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: usuboselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpl %esi, %edi +; SDAG-NEXT: cmovbl %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: usuboselecti32: +; FAST: ## BB#0: +; FAST-NEXT: cmpl %esi, %edi +; FAST-NEXT: cmovbl %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: usuboselecti32: +; KNL: ## BB#0: +; KNL-NEXT: cmpl %esi, %edi +; KNL-NEXT: cmovbl %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq %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 i64 @usubo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: usubo.select.i64 -; CHECK: cmpq %rsi, %rdi -; CHECK-NEXT: cmovbq %rdi, %rsi +define i64 @usuboselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: usuboselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpq %rsi, %rdi +; SDAG-NEXT: cmovbq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: usuboselecti64: +; FAST: ## BB#0: +; FAST-NEXT: cmpq %rsi, %rdi +; FAST-NEXT: cmovbq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: usuboselecti64: +; KNL: ## BB#0: +; KNL-NEXT: cmpq %rsi, %rdi +; KNL-NEXT: cmovbq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq %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 i32 @smulo.select.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: smulo.select.i32 -; CHECK: imull %esi, %eax -; CHECK-NEXT: cmovol %edi, %esi - %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 i64 @smulo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: smulo.select.i64 -; CHECK: imulq %rsi, %rax -; CHECK-NEXT: cmovoq %rdi, %rsi - %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 i32 @umulo.select.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: umulo.select.i32 -; CHECK: mull %esi -; CHECK-NEXT: cmovol %edi, %esi - %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 i64 @umulo.select.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: umulo.select.i64 -; CHECK: mulq %rsi -; CHECK-NEXT: cmovoq %rdi, %rsi - %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 -} - - ; ; Check the use of the overflow bit in combination with a branch instruction. ; -define zeroext i1 @saddo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: saddo.br.i32 -; CHECK: addl %esi, %edi -; CHECK-NEXT: jo +define zeroext i1 @saddobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: saddobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: addl %esi, %edi +; SDAG-NEXT: jo LBB31_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB31_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: saddobri32: +; FAST: ## BB#0: +; FAST-NEXT: addl %esi, %edi +; FAST-NEXT: jo LBB31_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB31_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddobri32: +; KNL: ## BB#0: +; KNL-NEXT: addl %esi, %edi +; KNL-NEXT: jo LBB31_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB31_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -548,11 +996,43 @@ continue: ret i1 true } -define zeroext i1 @saddo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: saddo.br.i64 -; CHECK: addq %rsi, %rdi -; CHECK-NEXT: jo +define zeroext i1 @saddobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: saddobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: addq %rsi, %rdi +; SDAG-NEXT: jo LBB32_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB32_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: saddobri64: +; FAST: ## BB#0: +; FAST-NEXT: addq %rsi, %rdi +; FAST-NEXT: jo LBB32_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB32_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: saddobri64: +; KNL: ## BB#0: +; KNL-NEXT: addq %rsi, %rdi +; KNL-NEXT: jo LBB32_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB32_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -565,11 +1045,43 @@ continue: ret i1 true } -define zeroext i1 @uaddo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: uaddo.br.i32 -; CHECK: addl %esi, %edi -; CHECK-NEXT: jb +define zeroext i1 @uaddobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: uaddobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: addl %esi, %edi +; SDAG-NEXT: jb LBB33_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB33_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddobri32: +; FAST: ## BB#0: +; FAST-NEXT: addl %esi, %edi +; FAST-NEXT: jb LBB33_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB33_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddobri32: +; KNL: ## BB#0: +; KNL-NEXT: addl %esi, %edi +; KNL-NEXT: jb LBB33_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB33_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -582,11 +1094,43 @@ continue: ret i1 true } -define zeroext i1 @uaddo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: uaddo.br.i64 -; CHECK: addq %rsi, %rdi -; CHECK-NEXT: jb +define zeroext i1 @uaddobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: uaddobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: addq %rsi, %rdi +; SDAG-NEXT: jb LBB34_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB34_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddobri64: +; FAST: ## BB#0: +; FAST-NEXT: addq %rsi, %rdi +; FAST-NEXT: jb LBB34_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB34_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: uaddobri64: +; KNL: ## BB#0: +; KNL-NEXT: addq %rsi, %rdi +; KNL-NEXT: jb LBB34_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB34_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -599,11 +1143,43 @@ continue: ret i1 true } -define zeroext i1 @ssubo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: ssubo.br.i32 -; CHECK: cmpl %esi, %edi -; CHECK-NEXT: jo +define zeroext i1 @ssubobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: ssubobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpl %esi, %edi +; SDAG-NEXT: jo LBB35_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB35_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: ssubobri32: +; FAST: ## BB#0: +; FAST-NEXT: cmpl %esi, %edi +; FAST-NEXT: jo LBB35_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB35_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: ssubobri32: +; KNL: ## BB#0: +; KNL-NEXT: cmpl %esi, %edi +; KNL-NEXT: jo LBB35_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB35_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -616,11 +1192,43 @@ continue: ret i1 true } -define zeroext i1 @ssubo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: ssubo.br.i64 -; CHECK: cmpq %rsi, %rdi -; CHECK-NEXT: jo +define zeroext i1 @ssubobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: ssubobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpq %rsi, %rdi +; SDAG-NEXT: jo LBB36_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB36_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: ssubobri64: +; FAST: ## BB#0: +; FAST-NEXT: cmpq %rsi, %rdi +; FAST-NEXT: jo LBB36_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB36_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: ssubobri64: +; KNL: ## BB#0: +; KNL-NEXT: cmpq %rsi, %rdi +; KNL-NEXT: jo LBB36_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB36_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -633,11 +1241,43 @@ continue: ret i1 true } -define zeroext i1 @usubo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: usubo.br.i32 -; CHECK: cmpl %esi, %edi -; CHECK-NEXT: jb +define zeroext i1 @usubobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: usubobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpl %esi, %edi +; SDAG-NEXT: jb LBB37_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB37_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: usubobri32: +; FAST: ## BB#0: +; FAST-NEXT: cmpl %esi, %edi +; FAST-NEXT: jb LBB37_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB37_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: usubobri32: +; KNL: ## BB#0: +; KNL-NEXT: cmpl %esi, %edi +; KNL-NEXT: jb LBB37_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB37_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -650,11 +1290,43 @@ continue: ret i1 true } -define zeroext i1 @usubo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: usubo.br.i64 -; CHECK: cmpq %rsi, %rdi -; CHECK-NEXT: jb +define zeroext i1 @usubobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: usubobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: cmpq %rsi, %rdi +; SDAG-NEXT: jb LBB38_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB38_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: usubobri64: +; FAST: ## BB#0: +; FAST-NEXT: cmpq %rsi, %rdi +; FAST-NEXT: jb LBB38_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB38_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: usubobri64: +; KNL: ## BB#0: +; KNL-NEXT: cmpq %rsi, %rdi +; KNL-NEXT: jb LBB38_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB38_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq %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 @@ -667,102 +1339,34 @@ continue: ret i1 true } -define zeroext i1 @smulo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: smulo.br.i32 -; CHECK: imull %esi, %edi -; CHECK-NEXT: jo - %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, !prof !0 - -overflow: - ret i1 false - -continue: - ret i1 true -} - -define zeroext i1 @smulo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: smulo.br.i64 -; CHECK: imulq %rsi, %rdi -; CHECK-NEXT: jo - %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, !prof !0 - -overflow: - ret i1 false - -continue: - ret i1 true -} - -define zeroext i1 @umulo.br.i32(i32 %v1, i32 %v2) { -entry: -; CHECK-LABEL: umulo.br.i32 -; CHECK: mull %esi -; CHECK-NEXT: jo - %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, !prof !0 - -overflow: - ret i1 false - -continue: - ret i1 true -} - -define zeroext i1 @umulo.br.i64(i64 %v1, i64 %v2) { -entry: -; CHECK-LABEL: umulo.br.i64 -; CHECK: mulq %rsi -; CHECK-NEXT: jo - %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, !prof !0 - -overflow: - ret i1 false - -continue: - ret i1 true -} - -define i1 @bug27873(i64 %c1, i1 %c2) { -; CHECK-LABEL: bug27873: -; CHECK: ## BB#0: -; CHECK-NEXT: movl $160, %ecx -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: mulq %rcx -; CHECK-NEXT: seto %al -; CHECK-NEXT: orb %sil, %al -; CHECK-NEXT: retq +define {i64, i1} @uaddoovf(i64 %a, i64 %b) { +; SDAG-LABEL: uaddoovf: +; SDAG: ## BB#0: +; SDAG-NEXT: movzbl %dil, %ecx +; SDAG-NEXT: movzbl %sil, %eax +; SDAG-NEXT: addq %rcx, %rax +; SDAG-NEXT: setb %dl +; SDAG-NEXT: retq +; +; FAST-LABEL: uaddoovf: +; FAST: ## BB#0: +; FAST-NEXT: movzbl %dil, %ecx +; FAST-NEXT: movzbl %sil, %eax +; FAST-NEXT: addq %rcx, %rax +; FAST-NEXT: setb %dl +; FAST-NEXT: retq ; -; KNL-LABEL: bug27873: +; KNL-LABEL: uaddoovf: ; KNL: ## BB#0: -; KNL-NEXT: andl $1, %esi -; KNL-NEXT: kmovw %esi, %k0 -; KNL-NEXT: movl $160, %ecx -; KNL-NEXT: movq %rdi, %rax -; KNL-NEXT: mulq %rcx -; KNL-NEXT: seto %al -; KNL-NEXT: andl $1, %eax -; KNL-NEXT: kmovw %eax, %k1 -; KNL-NEXT: korw %k1, %k0, %k0 -; KNL-NEXT: kmovw %k0, %eax -; KNL-NEXT: ## kill: %AL %AL %EAX +; KNL-NEXT: movzbl %dil, %ecx +; KNL-NEXT: movzbl %sil, %eax +; KNL-NEXT: addq %rcx, %rax +; KNL-NEXT: setb %dl ; KNL-NEXT: retq - %mul = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %c1, i64 160) - %mul.overflow = extractvalue { i64, i1 } %mul, 1 - %x1 = or i1 %c2, %mul.overflow - ret i1 %x1 + %1 = and i64 %a, 255 + %2 = and i64 %b, 255 + %t = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %1, i64 %2) + ret {i64, i1} %t } declare {i8, i1} @llvm.sadd.with.overflow.i8 (i8, i8 ) nounwind readnone @@ -777,13 +1381,5 @@ 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 {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 !0 = !{!"branch_weights", i32 0, i32 2147483647} diff --git a/test/CodeGen/X86/xmulo.ll b/test/CodeGen/X86/xmulo.ll index 76a7e72ca96..e0f2fc16d09 100644 --- a/test/CodeGen/X86/xmulo.ll +++ b/test/CodeGen/X86/xmulo.ll @@ -1,50 +1,742 @@ -; RUN: llc %s -o - | FileCheck %s -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128" -target triple = "i386-apple-macosx10.8.0" +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-darwin-unknown < %s | FileCheck %s --check-prefix=SDAG +; RUN: llc -mtriple=x86_64-darwin-unknown -fast-isel -fast-isel-abort=1 < %s | FileCheck %s --check-prefix=FAST +; RUN: llc -mtriple=x86_64-darwin-unknown -mcpu=knl < %s | FileCheck %s --check-prefix=KNL -declare {i64, i1} @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone -declare i32 @printf(i8*, ...) - -@.str = private unnamed_addr constant [10 x i8] c"%llx, %d\0A\00", align 1 - -define i32 @t1() nounwind { -; CHECK-LABEL: t1: -; CHECK: pushl $0 -; CHECK: pushl $0 -; CHECK: pushl $72 - - %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 8) - %2 = extractvalue {i64, i1} %1, 0 - %3 = extractvalue {i64, i1} %1, 1 - %4 = zext i1 %3 to i32 - %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0), i64 %2, i32 %4) - ret i32 0 -} - -define i32 @t2() nounwind { -; CHECK-LABEL: t2: -; CHECK: pushl $0 -; CHECK: pushl $0 -; CHECK: pushl $0 - - %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 0) - %2 = extractvalue {i64, i1} %1, 0 - %3 = extractvalue {i64, i1} %1, 1 - %4 = zext i1 %3 to i32 - %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0), i64 %2, i32 %4) - ret i32 0 -} - -define i32 @t3() nounwind { -; CHECK-LABEL: t3: -; CHECK: pushl $1 -; CHECK: pushl $-1 -; CHECK: pushl $-9 - - %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 -1) - %2 = extractvalue {i64, i1} %1, 0 - %3 = extractvalue {i64, i1} %1, 1 - %4 = zext i1 %3 to i32 - %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0), i64 %2, i32 %4) - ret i32 0 +define {i64, i1} @t1() nounwind { +; SDAG-LABEL: t1: +; SDAG: ## BB#0: +; SDAG-NEXT: movl $8, %ecx +; SDAG-NEXT: movl $9, %eax +; SDAG-NEXT: mulq %rcx +; SDAG-NEXT: seto %dl +; SDAG-NEXT: retq +; +; FAST-LABEL: t1: +; FAST: ## BB#0: +; FAST-NEXT: movl $8, %ecx +; FAST-NEXT: movl $9, %eax +; FAST-NEXT: mulq %rcx +; FAST-NEXT: seto %dl +; FAST-NEXT: retq +; +; KNL-LABEL: t1: +; KNL: ## BB#0: +; KNL-NEXT: movl $8, %ecx +; KNL-NEXT: movl $9, %eax +; KNL-NEXT: mulq %rcx +; KNL-NEXT: seto %dl +; KNL-NEXT: retq + %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 8) + ret {i64, i1} %1 +} + +define {i64, i1} @t2() nounwind { +; SDAG-LABEL: t2: +; SDAG: ## BB#0: +; SDAG-NEXT: xorl %ecx, %ecx +; SDAG-NEXT: movl $9, %eax +; SDAG-NEXT: mulq %rcx +; SDAG-NEXT: seto %dl +; SDAG-NEXT: retq +; +; FAST-LABEL: t2: +; FAST: ## BB#0: +; FAST-NEXT: xorl %ecx, %ecx +; FAST-NEXT: movl $9, %eax +; FAST-NEXT: mulq %rcx +; FAST-NEXT: seto %dl +; FAST-NEXT: retq +; +; KNL-LABEL: t2: +; KNL: ## BB#0: +; KNL-NEXT: xorl %ecx, %ecx +; KNL-NEXT: movl $9, %eax +; KNL-NEXT: mulq %rcx +; KNL-NEXT: seto %dl +; KNL-NEXT: retq + %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 0) + ret {i64, i1} %1 +} + +define {i64, i1} @t3() nounwind { +; SDAG-LABEL: t3: +; SDAG: ## BB#0: +; SDAG-NEXT: movq $-1, %rcx +; SDAG-NEXT: movl $9, %eax +; SDAG-NEXT: mulq %rcx +; SDAG-NEXT: seto %dl +; SDAG-NEXT: retq +; +; FAST-LABEL: t3: +; FAST: ## BB#0: +; FAST-NEXT: movq $-1, %rcx +; FAST-NEXT: movl $9, %eax +; FAST-NEXT: mulq %rcx +; FAST-NEXT: seto %dl +; FAST-NEXT: retq +; +; KNL-LABEL: t3: +; KNL: ## BB#0: +; KNL-NEXT: movq $-1, %rcx +; KNL-NEXT: movl $9, %eax +; KNL-NEXT: mulq %rcx +; KNL-NEXT: seto %dl +; KNL-NEXT: retq + %1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 -1) + ret {i64, i1} %1 +} + +; SMULO +define zeroext i1 @smuloi8(i8 %v1, i8 %v2, i8* %res) { +; SDAG-LABEL: smuloi8: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: imulb %sil +; SDAG-NEXT: seto %cl +; SDAG-NEXT: movb %al, (%rdx) +; SDAG-NEXT: movl %ecx, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloi8: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: imulb %sil +; FAST-NEXT: seto %cl +; FAST-NEXT: movb %al, (%rdx) +; FAST-NEXT: andb $1, %cl +; FAST-NEXT: movzbl %cl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloi8: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: imulb %sil +; KNL-NEXT: seto %cl +; KNL-NEXT: movb %al, (%rdx) +; KNL-NEXT: movl %ecx, %eax +; KNL-NEXT: retq + %t = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %v1, i8 %v2) + %val = extractvalue {i8, i1} %t, 0 + %obit = extractvalue {i8, i1} %t, 1 + store i8 %val, i8* %res + ret i1 %obit +} + +define zeroext i1 @smuloi16(i16 %v1, i16 %v2, i16* %res) { +; SDAG-LABEL: smuloi16: +; SDAG: ## BB#0: +; SDAG-NEXT: imulw %si, %di +; SDAG-NEXT: seto %al +; SDAG-NEXT: movw %di, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloi16: +; FAST: ## BB#0: +; FAST-NEXT: imulw %si, %di +; FAST-NEXT: seto %al +; FAST-NEXT: movw %di, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloi16: +; KNL: ## BB#0: +; KNL-NEXT: imulw %si, %di +; KNL-NEXT: seto %al +; KNL-NEXT: movw %di, (%rdx) +; KNL-NEXT: retq + %t = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %v1, i16 %v2) + %val = extractvalue {i16, i1} %t, 0 + %obit = extractvalue {i16, i1} %t, 1 + store i16 %val, i16* %res + ret i1 %obit +} + +define zeroext i1 @smuloi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: smuloi32: +; SDAG: ## BB#0: +; SDAG-NEXT: imull %esi, %edi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movl %edi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloi32: +; FAST: ## BB#0: +; FAST-NEXT: imull %esi, %edi +; FAST-NEXT: seto %al +; FAST-NEXT: movl %edi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloi32: +; KNL: ## BB#0: +; KNL-NEXT: imull %esi, %edi +; KNL-NEXT: seto %al +; KNL-NEXT: movl %edi, (%rdx) +; KNL-NEXT: retq + %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, i32* %res + ret i1 %obit +} + +define zeroext i1 @smuloi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: smuloi64: +; SDAG: ## BB#0: +; SDAG-NEXT: imulq %rsi, %rdi +; SDAG-NEXT: seto %al +; SDAG-NEXT: movq %rdi, (%rdx) +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloi64: +; FAST: ## BB#0: +; FAST-NEXT: imulq %rsi, %rdi +; FAST-NEXT: seto %al +; FAST-NEXT: movq %rdi, (%rdx) +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloi64: +; KNL: ## BB#0: +; KNL-NEXT: imulq %rsi, %rdi +; KNL-NEXT: seto %al +; KNL-NEXT: movq %rdi, (%rdx) +; KNL-NEXT: retq + %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, i64* %res + ret i1 %obit +} + +; UMULO +define zeroext i1 @umuloi8(i8 %v1, i8 %v2, i8* %res) { +; SDAG-LABEL: umuloi8: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: mulb %sil +; SDAG-NEXT: seto %cl +; SDAG-NEXT: movb %al, (%rdx) +; SDAG-NEXT: movl %ecx, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloi8: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: mulb %sil +; FAST-NEXT: seto %cl +; FAST-NEXT: movb %al, (%rdx) +; FAST-NEXT: andb $1, %cl +; FAST-NEXT: movzbl %cl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloi8: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: mulb %sil +; KNL-NEXT: seto %cl +; KNL-NEXT: movb %al, (%rdx) +; KNL-NEXT: movl %ecx, %eax +; KNL-NEXT: retq + %t = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %v1, i8 %v2) + %val = extractvalue {i8, i1} %t, 0 + %obit = extractvalue {i8, i1} %t, 1 + store i8 %val, i8* %res + ret i1 %obit +} + +define zeroext i1 @umuloi16(i16 %v1, i16 %v2, i16* %res) { +; SDAG-LABEL: umuloi16: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdx, %rcx +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: mulw %si +; SDAG-NEXT: seto %dl +; SDAG-NEXT: movw %ax, (%rcx) +; SDAG-NEXT: movl %edx, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloi16: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdx, %rcx +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: mulw %si +; FAST-NEXT: seto %dl +; FAST-NEXT: movw %ax, (%rcx) +; FAST-NEXT: andb $1, %dl +; FAST-NEXT: movzbl %dl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloi16: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdx, %rcx +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: mulw %si +; KNL-NEXT: seto %dl +; KNL-NEXT: movw %ax, (%rcx) +; KNL-NEXT: movl %edx, %eax +; KNL-NEXT: retq + %t = call {i16, i1} @llvm.umul.with.overflow.i16(i16 %v1, i16 %v2) + %val = extractvalue {i16, i1} %t, 0 + %obit = extractvalue {i16, i1} %t, 1 + store i16 %val, i16* %res + ret i1 %obit +} + +define zeroext i1 @umuloi32(i32 %v1, i32 %v2, i32* %res) { +; SDAG-LABEL: umuloi32: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdx, %rcx +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: mull %esi +; SDAG-NEXT: seto %dl +; SDAG-NEXT: movl %eax, (%rcx) +; SDAG-NEXT: movl %edx, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloi32: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdx, %rcx +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: mull %esi +; FAST-NEXT: seto %dl +; FAST-NEXT: movl %eax, (%rcx) +; FAST-NEXT: andb $1, %dl +; FAST-NEXT: movzbl %dl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloi32: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdx, %rcx +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: mull %esi +; KNL-NEXT: seto %dl +; KNL-NEXT: movl %eax, (%rcx) +; KNL-NEXT: movl %edx, %eax +; KNL-NEXT: retq + %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, i32* %res + ret i1 %obit +} + +define zeroext i1 @umuloi64(i64 %v1, i64 %v2, i64* %res) { +; SDAG-LABEL: umuloi64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdx, %rcx +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: mulq %rsi +; SDAG-NEXT: seto %dl +; SDAG-NEXT: movq %rax, (%rcx) +; SDAG-NEXT: movl %edx, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloi64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdx, %rcx +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: mulq %rsi +; FAST-NEXT: seto %dl +; FAST-NEXT: movq %rax, (%rcx) +; FAST-NEXT: andb $1, %dl +; FAST-NEXT: movzbl %dl, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloi64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdx, %rcx +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: mulq %rsi +; KNL-NEXT: seto %dl +; KNL-NEXT: movq %rax, (%rcx) +; KNL-NEXT: movl %edx, %eax +; KNL-NEXT: retq + %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, i64* %res + ret i1 %obit +} + +; +; Check the use of the overflow bit in combination with a select instruction. +; +define i32 @smuloselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: smuloselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: imull %esi, %eax +; SDAG-NEXT: cmovol %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloselecti32: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: imull %esi, %eax +; FAST-NEXT: cmovol %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloselecti32: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: imull %esi, %eax +; KNL-NEXT: cmovol %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq + %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 i64 @smuloselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: smuloselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: imulq %rsi, %rax +; SDAG-NEXT: cmovoq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: smuloselecti64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: imulq %rsi, %rax +; FAST-NEXT: cmovoq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: smuloselecti64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: imulq %rsi, %rax +; KNL-NEXT: cmovoq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq + %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 i32 @umuloselecti32(i32 %v1, i32 %v2) { +; SDAG-LABEL: umuloselecti32: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: mull %esi +; SDAG-NEXT: cmovol %edi, %esi +; SDAG-NEXT: movl %esi, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloselecti32: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: mull %esi +; FAST-NEXT: cmovol %edi, %esi +; FAST-NEXT: movl %esi, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloselecti32: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: mull %esi +; KNL-NEXT: cmovol %edi, %esi +; KNL-NEXT: movl %esi, %eax +; KNL-NEXT: retq + %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 i64 @umuloselecti64(i64 %v1, i64 %v2) { +; SDAG-LABEL: umuloselecti64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: mulq %rsi +; SDAG-NEXT: cmovoq %rdi, %rsi +; SDAG-NEXT: movq %rsi, %rax +; SDAG-NEXT: retq +; +; FAST-LABEL: umuloselecti64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: mulq %rsi +; FAST-NEXT: cmovoq %rdi, %rsi +; FAST-NEXT: movq %rsi, %rax +; FAST-NEXT: retq +; +; KNL-LABEL: umuloselecti64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: mulq %rsi +; KNL-NEXT: cmovoq %rdi, %rsi +; KNL-NEXT: movq %rsi, %rax +; KNL-NEXT: retq + %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 +} + +; +; Check the use of the overflow bit in combination with a branch instruction. +; +define zeroext i1 @smulobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: smulobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: imull %esi, %edi +; SDAG-NEXT: jo LBB15_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB15_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: smulobri32: +; FAST: ## BB#0: +; FAST-NEXT: imull %esi, %edi +; FAST-NEXT: jo LBB15_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB15_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smulobri32: +; KNL: ## BB#0: +; KNL-NEXT: imull %esi, %edi +; KNL-NEXT: jo LBB15_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB15_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq + %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, !prof !0 + +overflow: + ret i1 false + +continue: + ret i1 true +} + +define zeroext i1 @smulobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: smulobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: imulq %rsi, %rdi +; SDAG-NEXT: jo LBB16_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB16_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: smulobri64: +; FAST: ## BB#0: +; FAST-NEXT: imulq %rsi, %rdi +; FAST-NEXT: jo LBB16_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB16_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: smulobri64: +; KNL: ## BB#0: +; KNL-NEXT: imulq %rsi, %rdi +; KNL-NEXT: jo LBB16_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB16_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq + %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, !prof !0 + +overflow: + ret i1 false + +continue: + ret i1 true +} + +define zeroext i1 @umulobri32(i32 %v1, i32 %v2) { +; SDAG-LABEL: umulobri32: +; SDAG: ## BB#0: +; SDAG-NEXT: movl %edi, %eax +; SDAG-NEXT: mull %esi +; SDAG-NEXT: jo LBB17_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB17_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umulobri32: +; FAST: ## BB#0: +; FAST-NEXT: movl %edi, %eax +; FAST-NEXT: mull %esi +; FAST-NEXT: jo LBB17_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB17_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umulobri32: +; KNL: ## BB#0: +; KNL-NEXT: movl %edi, %eax +; KNL-NEXT: mull %esi +; KNL-NEXT: jo LBB17_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB17_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq + %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, !prof !0 + +overflow: + ret i1 false + +continue: + ret i1 true +} + +define zeroext i1 @umulobri64(i64 %v1, i64 %v2) { +; SDAG-LABEL: umulobri64: +; SDAG: ## BB#0: +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: mulq %rsi +; SDAG-NEXT: jo LBB18_1 +; SDAG-NEXT: ## BB#2: ## %continue +; SDAG-NEXT: movb $1, %al +; SDAG-NEXT: retq +; SDAG-NEXT: LBB18_1: ## %overflow +; SDAG-NEXT: xorl %eax, %eax +; SDAG-NEXT: retq +; +; FAST-LABEL: umulobri64: +; FAST: ## BB#0: +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: mulq %rsi +; FAST-NEXT: jo LBB18_1 +; FAST-NEXT: ## BB#2: ## %continue +; FAST-NEXT: movb $1, %al +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; FAST-NEXT: LBB18_1: ## %overflow +; FAST-NEXT: xorl %eax, %eax +; FAST-NEXT: andb $1, %al +; FAST-NEXT: movzbl %al, %eax +; FAST-NEXT: retq +; +; KNL-LABEL: umulobri64: +; KNL: ## BB#0: +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: mulq %rsi +; KNL-NEXT: jo LBB18_1 +; KNL-NEXT: ## BB#2: ## %continue +; KNL-NEXT: movb $1, %al +; KNL-NEXT: retq +; KNL-NEXT: LBB18_1: ## %overflow +; KNL-NEXT: xorl %eax, %eax +; KNL-NEXT: retq + %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, !prof !0 + +overflow: + ret i1 false + +continue: + ret i1 true +} + +define i1 @bug27873(i64 %c1, i1 %c2) { +; SDAG-LABEL: bug27873: +; SDAG: ## BB#0: +; SDAG-NEXT: movl $160, %ecx +; SDAG-NEXT: movq %rdi, %rax +; SDAG-NEXT: mulq %rcx +; SDAG-NEXT: seto %al +; SDAG-NEXT: orb %sil, %al +; SDAG-NEXT: retq +; +; FAST-LABEL: bug27873: +; FAST: ## BB#0: +; FAST-NEXT: movl $160, %ecx +; FAST-NEXT: movq %rdi, %rax +; FAST-NEXT: mulq %rcx +; FAST-NEXT: seto %al +; FAST-NEXT: orb %sil, %al +; FAST-NEXT: retq +; +; KNL-LABEL: bug27873: +; KNL: ## BB#0: +; KNL-NEXT: andl $1, %esi +; KNL-NEXT: kmovw %esi, %k0 +; KNL-NEXT: movl $160, %ecx +; KNL-NEXT: movq %rdi, %rax +; KNL-NEXT: mulq %rcx +; KNL-NEXT: seto %al +; KNL-NEXT: andl $1, %eax +; KNL-NEXT: kmovw %eax, %k1 +; KNL-NEXT: korw %k1, %k0, %k0 +; KNL-NEXT: kmovw %k0, %eax +; KNL-NEXT: ## kill: %AL %AL %EAX +; KNL-NEXT: retq + %mul = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %c1, i64 160) + %mul.overflow = extractvalue { i64, i1 } %mul, 1 + %x1 = or i1 %c2, %mul.overflow + ret i1 %x1 +} + +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 + +!0 = !{!"branch_weights", i32 0, i32 2147483647}