From 4f58fe36c141c2a328b6081be7d9cdf203cf2fcf Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Wed, 9 Sep 2015 08:39:13 +0000 Subject: [PATCH] [AArch64][1/3] Expand signed mod by power of 2 using CSNEG * config/aarch64/aarch64.md (mod3): New define_expand. (*neg2_compare0): Rename to... (neg2_compare0): ... This. * config/aarch64/aarch64.c (aarch64_rtx_costs, MOD case): Move check for speed inside the if-then-elses. Reflect CSNEG sequence in MOD by power of 2 case. From-SVN: r227585 --- gcc/ChangeLog | 9 ++++++ gcc/config/aarch64/aarch64.c | 19 ++++++++++++ gcc/config/aarch64/aarch64.md | 58 ++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 542abcfe0ec..25ecf5a89a5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-09-09 Kyrylo Tkachov + + * config/aarch64/aarch64.md (mod3): New define_expand. + (*neg2_compare0): Rename to... + (neg2_compare0): ... This. + * config/aarch64/aarch64.c (aarch64_rtx_costs, MOD case): + Move check for speed inside the if-then-elses. Reflect + CSNEG sequence in MOD by power of 2 case. + 2015-09-09 Alan Modra PR target/67378 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index feb7b28db1e..b2a481b4c29 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -6769,6 +6769,25 @@ cost_plus: return true; case MOD: + /* We can expand signed mod by power of 2 using a NEGS, two parallel + ANDs and a CSNEG. Assume here that CSNEG is the same as the cost of + an unconditional negate. This case should only ever be reached through + the set_smod_pow2_cheap check in expmed.c. */ + if (CONST_INT_P (XEXP (x, 1)) + && exact_log2 (INTVAL (XEXP (x, 1))) > 0 + && (mode == SImode || mode == DImode)) + { + /* We expand to 4 instructions. Reset the baseline. */ + *cost = COSTS_N_INSNS (4); + + if (speed) + *cost += 2 * extra_cost->alu.logical + + 2 * extra_cost->alu.arith; + + return true; + } + + /* Fall-through. */ case UMOD: if (speed) { diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 25229824fb5..594bef005c6 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -313,6 +313,62 @@ } ) +;; Expansion of signed mod by a power of 2 using CSNEG. +;; For x0 % n where n is a power of 2 produce: +;; negs x1, x0 +;; and x0, x0, #(n - 1) +;; and x1, x1, #(n - 1) +;; csneg x0, x0, x1, mi + +(define_expand "mod3" + [(match_operand:GPI 0 "register_operand" "") + (match_operand:GPI 1 "register_operand" "") + (match_operand:GPI 2 "const_int_operand" "")] + "" + { + HOST_WIDE_INT val = INTVAL (operands[2]); + + if (val <= 0 + || exact_log2 (val) <= 0 + || !aarch64_bitmask_imm (val - 1, mode)) + FAIL; + + rtx mask = GEN_INT (val - 1); + + /* In the special case of x0 % 2 we can do the even shorter: + cmp x0, xzr + and x0, x0, 1 + cneg x0, x0, lt. */ + if (val == 2) + { + rtx masked = gen_reg_rtx (mode); + rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx); + emit_insn (gen_and3 (masked, operands[1], mask)); + rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx); + emit_insn (gen_csneg3_insn (operands[0], x, masked, masked)); + DONE; + } + + rtx neg_op = gen_reg_rtx (mode); + rtx_insn *insn = emit_insn (gen_neg2_compare0 (neg_op, 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 (VOIDmode, cc_reg, const0_rtx); + + rtx masked_pos = gen_reg_rtx (mode); + emit_insn (gen_and3 (masked_pos, operands[1], mask)); + + rtx masked_neg = gen_reg_rtx (mode); + emit_insn (gen_and3 (masked_neg, neg_op, mask)); + + emit_insn (gen_csneg3_insn (operands[0], cond, + masked_neg, masked_pos)); + DONE; + } +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) @@ -2457,7 +2513,7 @@ [(set_attr "type" "adc_reg")] ) -(define_insn "*neg2_compare0" +(define_insn "neg2_compare0" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r")) (const_int 0))) -- 2.30.2