On 29 July 2015 at 16:03, Kyrill Tkachov <kyrylo.tkac...@arm.com> wrote: > Hi Prathamesh, > > This is probably not appropriate for -Os optimisation. > And for speed optimisation I imagine it can vary a lot on the target the > code is run. > Do you have any benchmark results for this patch? Hi Kyrill, Thanks for the review. I have attempted to address your comments in the attached patch. Does it look OK from correctness perspective ? Unfortunately I haven't done benchmarking yet. I ran a test-case (attached) prepared by Charles for target arm-linux-gnueabihf (on APM Mustang), and it appeared to run faster with the patch: Options passed: -O3 -mfpu=neon -mfloat-abi=hard -funsafe-math-optimizations
Before: t8a, len = 32, took 2593977 ticks t8a, len = 128, took 2408907 ticks t8a, len = 1024, took 2354950 ticks t8a, len = 65536, took 2365041 ticks t8a, len = 1048576, took 2692928 ticks After: t8a, len = 32, took 2027323 ticks t8a, len = 128, took 1920595 ticks t8a, len = 1024, took 1827250 ticks t8a, len = 65536, took 1797924 ticks t8a, len = 1048576, took 2026274 ticks I will get back to you soon with benchmarking results. Thanks, Prathamesh > > Thanks, > Kyrill > > > On 29/07/15 11:09, Prathamesh Kulkarni wrote: >> >> Hi, >> This patch tries to implement division with multiplication by >> reciprocal using vrecpe/vrecps >> with -funsafe-math-optimizations and -freciprocal-math enabled. >> Tested on arm-none-linux-gnueabihf using qemu. >> OK for trunk ? >> >> Thank you, >> Prathamesh > > + /* Perform 2 iterations of Newton-Raphson method for better accuracy */ > + for (int i = 0; i < 2; i++) > + { > + emit_insn (gen_neon_vrecps<mode> (vrecps_temp, rec, operands[2])); > + emit_insn (gen_mul<mode>3 (rec, rec, vrecps_temp)); > + } > + > + /* We now have reciprocal in rec, perform operands[0] = operands[1] * > rec */ > + emit_insn (gen_mul<mode>3 (operands[0], operands[1], rec)); > + DONE; > + } > +) > + > > Full stop and two spaces at the end of the comments. >
2015-07-28 Prathamesh Kulkarni <prathamesh.kulka...@linaro.org> Charles Baylis <charles.bay...@linaro.org> * config/arm/neon.md (div<mode>3): New pattern. testsuite/ * gcc.target/arm/vect-div-1.c: New test-case. * gcc.target/arm/vect-div-2.c: Likewise.
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 654d9d5..f2dbcc4 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -548,6 +548,33 @@ (const_string "neon_mul_<V_elem_ch><q>")))] ) +(define_expand "div<mode>3" + [(set (match_operand:VCVTF 0 "s_register_operand" "=w") + (div:VCVTF (match_operand:VCVTF 1 "s_register_operand" "w") + (match_operand:VCVTF 2 "s_register_operand" "w")))] + "TARGET_NEON && !optimize_size + && flag_unsafe_math_optimizations && flag_reciprocal_math" + { + rtx rec = gen_reg_rtx (<MODE>mode); + rtx vrecps_temp = gen_reg_rtx (<MODE>mode); + + /* Reciprocal estimate. */ + emit_insn (gen_neon_vrecpe<mode> (rec, operands[2])); + + /* Perform 2 iterations of newton-raphson method. */ + for (int i = 0; i < 2; i++) + { + emit_insn (gen_neon_vrecps<mode> (vrecps_temp, rec, operands[2])); + emit_insn (gen_mul<mode>3 (rec, rec, vrecps_temp)); + } + + /* We now have reciprocal in rec, perform operands[0] = operands[1] * rec. */ + emit_insn (gen_mul<mode>3 (operands[0], operands[1], rec)); + DONE; + } +) + + (define_insn "mul<mode>3add<mode>_neon" [(set (match_operand:VDQW 0 "s_register_operand" "=w") (plus:VDQW (mult:VDQW (match_operand:VDQW 2 "s_register_operand" "w") diff --git a/gcc/testsuite/gcc.target/arm/vect-div-1.c b/gcc/testsuite/gcc.target/arm/vect-div-1.c new file mode 100644 index 0000000..e562ef3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/vect-div-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_neon_ok } */ +/* { dg-options "-O2 -funsafe-math-optimizations -ftree-vectorize -fdump-tree-vect-all" } */ +/* { dg-add-options arm_v8_neon } */ + +void +foo (int len, float * __restrict p, float *__restrict x) +{ + len = len & ~31; + for (int i = 0; i < len; i++) + p[i] = p[i] / x[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/arm/vect-div-2.c b/gcc/testsuite/gcc.target/arm/vect-div-2.c new file mode 100644 index 0000000..8e15d0a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/vect-div-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_neon_ok } */ +/* { dg-options "-O2 -funsafe-math-optimizations -fno-reciprocal-math -ftree-vectorize -fdump-tree-vect-all" } */ +/* { dg-add-options arm_v8_neon } */ + +void +foo (int len, float * __restrict p, float *__restrict x) +{ + len = len & ~31; + for (int i = 0; i < len; i++) + p[i] = p[i] / x[i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
test.tar.gz
Description: GNU Zip compressed data