[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:
Kyrylo Tkachov 2015-09-09 08:41:41 +00:00 committed by Kyrylo Tkachov
parent 4f58fe36c1
commit 956db28eb5
10 changed files with 144 additions and 1 deletions

View File

@ -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.

View File

@ -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. */

View File

@ -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")))]

View File

@ -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

View 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 } } */

View File

@ -0,0 +1,5 @@
int
f (int x)
{
return x % 2;
}

View 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\]*" } } */

View File

@ -0,0 +1,5 @@
int
f (int x)
{
return x % 256;
}

View 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 } } */

View 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\]*" } } */