[ARM][3/3] Expand mod by power of 2
* config/arm/arm.md (*subsi3_compare0): Rename to... (subsi3_compare0): ... This. (modsi3): New define_expand. * config/arm/arm.c (arm_new_rtx_costs, MOD case): Handle case when operand is power of 2. * gcc.target/aarch64/mod_2.x: New file. * gcc.target/aarch64/mod_256.x: Likewise. * gcc.target/arm/mod_2.c: New test. * gcc.target/arm/mod_256.c: Likewise. * gcc.target/aarch64/mod_2.c: Likewise. * gcc.target/aarch64/mod_256.c: Likewise. From-SVN: r227586
This commit is contained in:
parent
4f58fe36c1
commit
956db28eb5
10 changed files with 144 additions and 1 deletions
|
@ -1,3 +1,11 @@
|
|||
2015-09-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
|
||||
|
||||
* config/arm/arm.md (*subsi3_compare0): Rename to...
|
||||
(subsi3_compare0): ... This.
|
||||
(modsi3): New define_expand.
|
||||
* config/arm/arm.c (arm_new_rtx_costs, MOD case): Handle case
|
||||
when operand is power of 2.
|
||||
|
||||
2015-09-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
|
||||
|
||||
* config/aarch64/aarch64.md (mod<mode>3): New define_expand.
|
||||
|
|
|
@ -9580,6 +9580,24 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
return false; /* All arguments must be in registers. */
|
||||
|
||||
case MOD:
|
||||
/* MOD by a power of 2 can be expanded as:
|
||||
rsbs r1, r0, #0
|
||||
and r0, r0, #(n - 1)
|
||||
and r1, r1, #(n - 1)
|
||||
rsbpl r0, r1, #0. */
|
||||
if (CONST_INT_P (XEXP (x, 1))
|
||||
&& exact_log2 (INTVAL (XEXP (x, 1))) > 0
|
||||
&& mode == SImode)
|
||||
{
|
||||
*cost += COSTS_N_INSNS (3);
|
||||
|
||||
if (speed_p)
|
||||
*cost += 2 * extra_cost->alu.logical
|
||||
+ extra_cost->alu.arith;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fall-through. */
|
||||
case UMOD:
|
||||
*cost = LIBCALL_COST (2);
|
||||
return false; /* All arguments must be in registers. */
|
||||
|
|
|
@ -1229,7 +1229,7 @@
|
|||
""
|
||||
)
|
||||
|
||||
(define_insn "*subsi3_compare0"
|
||||
(define_insn "subsi3_compare0"
|
||||
[(set (reg:CC_NOOV CC_REGNUM)
|
||||
(compare:CC_NOOV
|
||||
(minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
|
||||
|
@ -11142,6 +11142,75 @@
|
|||
""
|
||||
)
|
||||
|
||||
;; ARM-specific expansion of signed mod by power of 2
|
||||
;; using conditional negate.
|
||||
;; For r0 % n where n is a power of 2 produce:
|
||||
;; rsbs r1, r0, #0
|
||||
;; and r0, r0, #(n - 1)
|
||||
;; and r1, r1, #(n - 1)
|
||||
;; rsbpl r0, r1, #0
|
||||
|
||||
(define_expand "modsi3"
|
||||
[(match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "register_operand" "")
|
||||
(match_operand:SI 2 "const_int_operand" "")]
|
||||
"TARGET_32BIT"
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (operands[2]);
|
||||
|
||||
if (val <= 0
|
||||
|| exact_log2 (val) <= 0)
|
||||
FAIL;
|
||||
|
||||
rtx mask = GEN_INT (val - 1);
|
||||
|
||||
/* In the special case of x0 % 2 we can do the even shorter:
|
||||
cmp r0, #0
|
||||
and r0, r0, #1
|
||||
rsblt r0, r0, #0. */
|
||||
|
||||
if (val == 2)
|
||||
{
|
||||
rtx cc_reg = arm_gen_compare_reg (LT,
|
||||
operands[1], const0_rtx, NULL_RTX);
|
||||
rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
|
||||
rtx masked = gen_reg_rtx (SImode);
|
||||
|
||||
emit_insn (gen_andsi3 (masked, operands[1], mask));
|
||||
emit_move_insn (operands[0],
|
||||
gen_rtx_IF_THEN_ELSE (SImode, cond,
|
||||
gen_rtx_NEG (SImode,
|
||||
masked),
|
||||
masked));
|
||||
DONE;
|
||||
}
|
||||
|
||||
rtx neg_op = gen_reg_rtx (SImode);
|
||||
rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
|
||||
operands[1]));
|
||||
|
||||
/* Extract the condition register and mode. */
|
||||
rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
|
||||
rtx cc_reg = SET_DEST (cmp);
|
||||
rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
|
||||
|
||||
emit_insn (gen_andsi3 (operands[0], operands[1], mask));
|
||||
|
||||
rtx masked_neg = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
|
||||
|
||||
/* We want a conditional negate here, but emitting COND_EXEC rtxes
|
||||
during expand does not always work. Do an IF_THEN_ELSE instead. */
|
||||
emit_move_insn (operands[0],
|
||||
gen_rtx_IF_THEN_ELSE (SImode, cond,
|
||||
gen_rtx_NEG (SImode, masked_neg),
|
||||
operands[0]));
|
||||
|
||||
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
(define_expand "bswapsi2"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=r")
|
||||
(bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2015-09-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
|
||||
|
||||
* gcc.target/aarch64/mod_2.x: New file.
|
||||
* gcc.target/aarch64/mod_256.x: Likewise.
|
||||
* gcc.target/arm/mod_2.c: New test.
|
||||
* gcc.target/arm/mod_256.c: Likewise.
|
||||
* gcc.target/aarch64/mod_2.c: Likewise.
|
||||
* gcc.target/aarch64/mod_256.c: Likewise.
|
||||
|
||||
2015-09-09 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/67504
|
||||
|
|
7
gcc/testsuite/gcc.target/aarch64/mod_2.c
Normal file
7
gcc/testsuite/gcc.target/aarch64/mod_2.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -mcpu=cortex-a57 -save-temps" } */
|
||||
|
||||
#include "mod_2.x"
|
||||
|
||||
/* { dg-final { scan-assembler "csneg\t\[wx\]\[0-9\]*" } } */
|
||||
/* { dg-final { scan-assembler-times "and\t\[wx\]\[0-9\]*" 1 } } */
|
5
gcc/testsuite/gcc.target/aarch64/mod_2.x
Normal file
5
gcc/testsuite/gcc.target/aarch64/mod_2.x
Normal file
|
@ -0,0 +1,5 @@
|
|||
int
|
||||
f (int x)
|
||||
{
|
||||
return x % 2;
|
||||
}
|
6
gcc/testsuite/gcc.target/aarch64/mod_256.c
Normal file
6
gcc/testsuite/gcc.target/aarch64/mod_256.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -mcpu=cortex-a57 -save-temps" } */
|
||||
|
||||
#include "mod_256.x"
|
||||
|
||||
/* { dg-final { scan-assembler "csneg\t\[wx\]\[0-9\]*" } } */
|
5
gcc/testsuite/gcc.target/aarch64/mod_256.x
Normal file
5
gcc/testsuite/gcc.target/aarch64/mod_256.x
Normal file
|
@ -0,0 +1,5 @@
|
|||
int
|
||||
f (int x)
|
||||
{
|
||||
return x % 256;
|
||||
}
|
8
gcc/testsuite/gcc.target/arm/mod_2.c
Normal file
8
gcc/testsuite/gcc.target/arm/mod_2.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target arm32 } */
|
||||
/* { dg-options "-O2 -mcpu=cortex-a57 -save-temps" } */
|
||||
|
||||
#include "../aarch64/mod_2.x"
|
||||
|
||||
/* { dg-final { scan-assembler "rsblt\tr\[0-9\]*" } } */
|
||||
/* { dg-final { scan-assembler-times "and\tr\[0-9\].*1" 1 } } */
|
8
gcc/testsuite/gcc.target/arm/mod_256.c
Normal file
8
gcc/testsuite/gcc.target/arm/mod_256.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target arm32 } */
|
||||
/* { dg-options "-O2 -mcpu=cortex-a57 -save-temps" } */
|
||||
|
||||
#include "../aarch64/mod_256.x"
|
||||
|
||||
/* { dg-final { scan-assembler "rsbpl\tr\[0-9\]*" } } */
|
||||
|
Loading…
Add table
Reference in a new issue