Index: test/CodeGen/X86/atom-bypass-slow-division-64.ll =================================================================== --- test/CodeGen/X86/atom-bypass-slow-division-64.ll +++ /dev/null @@ -1,58 +0,0 @@ -; RUN: llc < %s -mcpu=atom -march=x86-64 -asm-verbose=false | FileCheck %s -; RUN: llc < %s -mcpu=silvermont -march=x86-64 -asm-verbose=false | FileCheck %s -; RUN: llc < %s -mcpu=skylake -march=x86-64 -asm-verbose=false | FileCheck %s - -target triple = "x86_64-unknown-linux-gnu" - -; Additional tests for 64-bit divide bypass - -define i64 @Test_get_quotient(i64 %a, i64 %b) nounwind { -; CHECK-LABEL: Test_get_quotient: -; CHECK: movq %rdi, %rax -; CHECK-DAG: movabsq $-4294967296, %rcx -; CHECK-DAG: orq %rsi, %rax -; CHECK: testq %rcx, %rax -; CHECK: je -; CHECK: idivq -; CHECK: ret -; CHECK: divl -; CHECK: ret - %result = sdiv i64 %a, %b - ret i64 %result -} - -define i64 @Test_get_remainder(i64 %a, i64 %b) nounwind { -; CHECK-LABEL: Test_get_remainder: -; CHECK: movq %rdi, %rax -; CHECK-DAG: movabsq $-4294967296, %rcx -; CHECK-DAG: orq %rsi, %rax -; CHECK: testq %rcx, %rax -; CHECK: je -; CHECK: idivq -; CHECK: ret -; CHECK: divl -; CHECK: ret - %result = srem i64 %a, %b - ret i64 %result -} - -define i64 @Test_get_quotient_and_remainder(i64 %a, i64 %b) nounwind { -; CHECK-LABEL: Test_get_quotient_and_remainder: -; CHECK: movq %rdi, %rax -; CHECK-DAG: movabsq $-4294967296, %rcx -; CHECK-DAG: orq %rsi, %rax -; CHECK: testq %rcx, %rax -; CHECK: je -; CHECK: idivq -; CHECK-NEXT: addq -; CHECK-NEXT: retq -; CHECK: divl -; CHECK-NEXT: addq -; CHECK-NEXT: retq -; CHECK-NOT: idivq -; CHECK-NOT: divw - %resultdiv = sdiv i64 %a, %b - %resultrem = srem i64 %a, %b - %result = add i64 %resultdiv, %resultrem - ret i64 %result -} Index: test/CodeGen/X86/atom-bypass-slow-division.ll =================================================================== --- test/CodeGen/X86/atom-bypass-slow-division.ll +++ /dev/null @@ -1,112 +0,0 @@ -; RUN: llc < %s -mcpu=atom -mtriple=i686-linux | FileCheck %s - -define i32 @Test_get_quotient(i32 %a, i32 %b) nounwind { -; CHECK-LABEL: Test_get_quotient: -; CHECK: orl %ecx, %edx -; CHECK-NEXT: testl $-256, %edx -; CHECK-NEXT: je -; CHECK: idivl -; CHECK: ret -; CHECK: divb -; CHECK: ret - %result = sdiv i32 %a, %b - ret i32 %result -} - -define i32 @Test_get_remainder(i32 %a, i32 %b) nounwind { -; CHECK-LABEL: Test_get_remainder: -; CHECK: orl %ecx, %edx -; CHECK-NEXT: testl $-256, %edx -; CHECK-NEXT: je -; CHECK: idivl -; CHECK: ret -; CHECK: divb -; CHECK: ret - %result = srem i32 %a, %b - ret i32 %result -} - -define i32 @Test_get_quotient_and_remainder(i32 %a, i32 %b) nounwind { -; CHECK-LABEL: Test_get_quotient_and_remainder: -; CHECK: orl %ecx, %edx -; CHECK-NEXT: testl $-256, %edx -; CHECK-NEXT: je -; CHECK: idivl -; CHECK: divb -; CHECK: addl -; CHECK: ret -; CHECK-NOT: idivl -; CHECK-NOT: divb - %resultdiv = sdiv i32 %a, %b - %resultrem = srem i32 %a, %b - %result = add i32 %resultdiv, %resultrem - ret i32 %result -} - -define i32 @Test_use_div_and_idiv(i32 %a, i32 %b) nounwind { -; CHECK-LABEL: Test_use_div_and_idiv: -; CHECK: idivl -; CHECK: divb -; CHECK: divl -; CHECK: divb -; CHECK: addl -; CHECK: ret - %resultidiv = sdiv i32 %a, %b - %resultdiv = udiv i32 %a, %b - %result = add i32 %resultidiv, %resultdiv - ret i32 %result -} - -define i32 @Test_use_div_imm_imm() nounwind { -; CHECK-LABEL: Test_use_div_imm_imm: -; CHECK: movl $64 - %resultdiv = sdiv i32 256, 4 - ret i32 %resultdiv -} - -define i32 @Test_use_div_reg_imm(i32 %a) nounwind { -; CHECK-LABEL: Test_use_div_reg_imm: -; CHECK-NOT: test -; CHECK-NOT: idiv -; CHECK-NOT: divb - %resultdiv = sdiv i32 %a, 33 - ret i32 %resultdiv -} - -define i32 @Test_use_rem_reg_imm(i32 %a) nounwind { -; CHECK-LABEL: Test_use_rem_reg_imm: -; CHECK-NOT: test -; CHECK-NOT: idiv -; CHECK-NOT: divb - %resultrem = srem i32 %a, 33 - ret i32 %resultrem -} - -define i32 @Test_use_divrem_reg_imm(i32 %a) nounwind { -; CHECK-LABEL: Test_use_divrem_reg_imm: -; CHECK-NOT: test -; CHECK-NOT: idiv -; CHECK-NOT: divb - %resultdiv = sdiv i32 %a, 33 - %resultrem = srem i32 %a, 33 - %result = add i32 %resultdiv, %resultrem - ret i32 %result -} - -define i32 @Test_use_div_imm_reg(i32 %a) nounwind { -; CHECK-LABEL: Test_use_div_imm_reg: -; CHECK: test -; CHECK: idiv -; CHECK: divb - %resultdiv = sdiv i32 4, %a - ret i32 %resultdiv -} - -define i32 @Test_use_rem_imm_reg(i32 %a) nounwind { -; CHECK-LABEL: Test_use_rem_imm_reg: -; CHECK: test -; CHECK: idiv -; CHECK: divb - %resultdiv = sdiv i32 4, %a - ret i32 %resultdiv -} Index: test/CodeGen/X86/bypass-slow-division-32.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/bypass-slow-division-32.ll @@ -0,0 +1,113 @@ +; Check that 32-bit division is bypassed correctly. +; RUN: llc < %s -mattr=+idivl-to-divb -mtriple=i686-linux | FileCheck %s + +define i32 @Test_get_quotient(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: Test_get_quotient: +; CHECK: orl %ecx, %edx +; CHECK-NEXT: testl $-256, %edx +; CHECK-NEXT: je +; CHECK: idivl +; CHECK: ret +; CHECK: divb +; CHECK: ret + %result = sdiv i32 %a, %b + ret i32 %result +} + +define i32 @Test_get_remainder(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: Test_get_remainder: +; CHECK: orl %ecx, %edx +; CHECK-NEXT: testl $-256, %edx +; CHECK-NEXT: je +; CHECK: idivl +; CHECK: ret +; CHECK: divb +; CHECK: ret + %result = srem i32 %a, %b + ret i32 %result +} + +define i32 @Test_get_quotient_and_remainder(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: Test_get_quotient_and_remainder: +; CHECK: orl %ecx, %edx +; CHECK-NEXT: testl $-256, %edx +; CHECK-NEXT: je +; CHECK: idivl +; CHECK: divb +; CHECK: addl +; CHECK: ret +; CHECK-NOT: idivl +; CHECK-NOT: divb + %resultdiv = sdiv i32 %a, %b + %resultrem = srem i32 %a, %b + %result = add i32 %resultdiv, %resultrem + ret i32 %result +} + +define i32 @Test_use_div_and_idiv(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: Test_use_div_and_idiv: +; CHECK: idivl +; CHECK: divb +; CHECK: divl +; CHECK: divb +; CHECK: addl +; CHECK: ret + %resultidiv = sdiv i32 %a, %b + %resultdiv = udiv i32 %a, %b + %result = add i32 %resultidiv, %resultdiv + ret i32 %result +} + +define i32 @Test_use_div_imm_imm() nounwind { +; CHECK-LABEL: Test_use_div_imm_imm: +; CHECK: movl $64 + %resultdiv = sdiv i32 256, 4 + ret i32 %resultdiv +} + +define i32 @Test_use_div_reg_imm(i32 %a) nounwind { +; CHECK-LABEL: Test_use_div_reg_imm: +; CHECK-NOT: test +; CHECK-NOT: idiv +; CHECK-NOT: divb + %resultdiv = sdiv i32 %a, 33 + ret i32 %resultdiv +} + +define i32 @Test_use_rem_reg_imm(i32 %a) nounwind { +; CHECK-LABEL: Test_use_rem_reg_imm: +; CHECK-NOT: test +; CHECK-NOT: idiv +; CHECK-NOT: divb + %resultrem = srem i32 %a, 33 + ret i32 %resultrem +} + +define i32 @Test_use_divrem_reg_imm(i32 %a) nounwind { +; CHECK-LABEL: Test_use_divrem_reg_imm: +; CHECK-NOT: test +; CHECK-NOT: idiv +; CHECK-NOT: divb + %resultdiv = sdiv i32 %a, 33 + %resultrem = srem i32 %a, 33 + %result = add i32 %resultdiv, %resultrem + ret i32 %result +} + +define i32 @Test_use_div_imm_reg(i32 %a) nounwind { +; CHECK-LABEL: Test_use_div_imm_reg: +; CHECK: test +; CHECK: idiv +; CHECK: divb + %resultdiv = sdiv i32 4, %a + ret i32 %resultdiv +} + +define i32 @Test_use_rem_imm_reg(i32 %a) nounwind { +; CHECK-LABEL: Test_use_rem_imm_reg: +; CHECK: test +; CHECK: idiv +; CHECK: divb + %resultdiv = sdiv i32 4, %a + ret i32 %resultdiv +} Index: test/CodeGen/X86/bypass-slow-division-64.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/bypass-slow-division-64.ll @@ -0,0 +1,57 @@ +; Check that 64-bit division is bypassed correctly. +; RUN: llc < %s -mattr=+idivq-to-divl -march=x86-64 -asm-verbose=false | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +; Additional tests for 64-bit divide bypass + +define i64 @Test_get_quotient(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: Test_get_quotient: +; CHECK: movq %rdi, %rax +; CHECK-DAG: movabsq $-4294967296, %rcx +; CHECK-DAG: orq %rsi, %rax +; CHECK: testq %rcx, %rax +; CHECK: je +; CHECK: idivq +; CHECK: ret +; CHECK: divl +; CHECK: ret + %result = sdiv i64 %a, %b + ret i64 %result +} + +define i64 @Test_get_remainder(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: Test_get_remainder: +; CHECK: movq %rdi, %rax +; CHECK-DAG: movabsq $-4294967296, %rcx +; CHECK-DAG: orq %rsi, %rax +; CHECK: testq %rcx, %rax +; CHECK: je +; CHECK: idivq +; CHECK: ret +; CHECK: divl +; CHECK: ret + %result = srem i64 %a, %b + ret i64 %result +} + +define i64 @Test_get_quotient_and_remainder(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: Test_get_quotient_and_remainder: +; CHECK: movq %rdi, %rax +; CHECK-DAG: movabsq $-4294967296, %rcx +; CHECK-DAG: orq %rsi, %rax +; CHECK: testq %rcx, %rax +; CHECK: je +; CHECK: idivq +; CHECK-NEXT: addq +; CHECK-NEXT: retq +; CHECK: divl +; CHECK-NEXT: addq +; CHECK-NEXT: retq +; CHECK-NOT: idivq +; CHECK-NOT: divw + %resultdiv = sdiv i64 %a, %b + %resultrem = srem i64 %a, %b + %result = add i64 %resultdiv, %resultrem + ret i64 %result +} Index: test/CodeGen/X86/bypass-slow-division-tune.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/bypass-slow-division-tune.ll @@ -0,0 +1,56 @@ +; Check that a division is bypassed when appropriate only. +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=atom < %s | FileCheck -check-prefixes=ATOM,CHECK %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=silvermont < %s | FileCheck -check-prefixes=REST,CHECK %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s | FileCheck -check-prefixes=REST,CHECK %s + +; Verify that div32 is bypassed only for Atoms. +define i32 @div32(i32 %a, i32 %b) { +entry: +; ATOM-LABEL: div32: +; ATOM: orl %{{.*}}, [[REG:%[a-z]+]] +; ATOM: testl $-256, [[REG]] +; ATOM: divb +; +; REST-LABEL: div32: +; REST-NOT: divb +; + %div = sdiv i32 %a, %b + ret i32 %div +} + +; Verify that div64 is always bypassed. +define i64 @div64(i64 %a, i64 %b) { +entry: +; CHECK-LABEL: div64: +; CHECK-DAG: movabsq $-4294967296, [[REGMSK:%[a-z]+]] +; CHECK-DAG: orq %{{.*}}, [[REG:%[a-z]+]] +; CHECK: testq [[REGMSK]], [[REG]] +; CHECK: divl +; + %div = sdiv i64 %a, %b + ret i64 %div +} + + +; Verify that no extra code is generated when optimizing for size. + +define i64 @div64_optsize(i64 %a, i64 %b) optsize { +; CHECK-LABEL: div64_optsize: +; CHECK-NOT: divl + %div = sdiv i64 %a, %b + ret i64 %div +} + +define i32 @div32_optsize(i32 %a, i32 %b) optsize { +; CHECK-LABEL: div32_optsize: +; CHECK-NOT: divb + %div = sdiv i32 %a, %b + ret i32 %div +} + +define i32 @div32_minsize(i32 %a, i32 %b) minsize { +; CHECK-LABEL: div32_minsize: +; CHECK-NOT: divb + %div = sdiv i32 %a, %b + ret i32 %div +} Index: test/CodeGen/X86/slow-div.ll =================================================================== --- test/CodeGen/X86/slow-div.ll +++ /dev/null @@ -1,44 +0,0 @@ -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+idivl-to-divb < %s | FileCheck -check-prefix=DIV32 %s -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+idivq-to-divl < %s | FileCheck -check-prefix=DIV64 %s - -define i32 @div32(i32 %a, i32 %b) { -entry: -; DIV32-LABEL: div32: -; DIV32: orl %{{.*}}, [[REG:%[a-z]+]] -; DIV32: testl $-256, [[REG]] -; DIV32: divb -; DIV64-LABEL: div32: -; DIV64-NOT: divb - %div = sdiv i32 %a, %b - ret i32 %div -} - -define i64 @div64(i64 %a, i64 %b) { -entry: -; DIV32-LABEL: div64: -; DIV32-NOT: divl -; DIV64-LABEL: div64: -; DIV64-DAG: movabsq $-4294967296, [[REGMSK:%[a-z]+]] -; DIV64-DAG: orq %{{.*}}, [[REG:%[a-z]+]] -; DIV64: testq [[REGMSK]], [[REG]] -; DIV64: divl - %div = sdiv i64 %a, %b - ret i64 %div -} - -; Verify that no extra code is generated when optimizing for size. - -define i32 @div32_optsize(i32 %a, i32 %b) optsize { -; DIV32-LABEL: div32_optsize: -; DIV32-NOT: divb - %div = sdiv i32 %a, %b - ret i32 %div -} - -define i32 @div32_minsize(i32 %a, i32 %b) minsize { -; DIV32-LABEL: div32_minsize: -; DIV32-NOT: divb - %div = sdiv i32 %a, %b - ret i32 %div -} -