From 43c058162f9ee10a3149b502aa4c76f668b64e34 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Mon, 28 Nov 2016 08:40:11 +0000 Subject: [PATCH] re PR target/41076 ([avr] pessimal code for logical OR of 8-bit fields) PR 41076 * config/avr/avr.md (SPLIT34): New mode iterator. (bitop): New code iterator. (*iorhi3.ashift8-*). New insn-and-split patterns. (*movhi): Post-reload split reg = 0. [!MOVW]: Post-reload split reg = reg. (*mov) [SI,SF,PSI,SQ,USQ,SA,USA]: Post-reload split reg = reg. (andhi3, andpsi3, andsi3): Post-reload split reg-reg operations. (iorhi3, iorpsi3, iorsi3): Same. (xorhi3, xorpsi3, xorsi3): Same. * config/avr/avr.c (avr_rtx_costs_1) [IOR && HImode]: Adjust rtx costs to *iorhi3.ashift8-* patterns. From-SVN: r242907 --- gcc/ChangeLog | 15 ++++++ gcc/config/avr/avr.c | 13 +++++ gcc/config/avr/avr.md | 144 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 171 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4cd9332..44ba41e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2016-11-28 Georg-Johann Lay + + PR 41076 + * config/avr/avr.md (SPLIT34): New mode iterator. + (bitop): New code iterator. + (*iorhi3.ashift8-*). New insn-and-split patterns. + (*movhi): Post-reload split reg = 0. + [!MOVW]: Post-reload split reg = reg. + (*mov) [SI,SF,PSI,SQ,USQ,SA,USA]: Post-reload split reg = reg. + (andhi3, andpsi3, andsi3): Post-reload split reg-reg operations. + (iorhi3, iorpsi3, iorsi3): Same. + (xorhi3, xorpsi3, xorsi3): Same. + * config/avr/avr.c (avr_rtx_costs_1) [IOR && HImode]: Adjust rtx + costs to *iorhi3.ashift8-* patterns. + 2016-11-27 Iain Sandoe Rainer Orth diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index b6b1756..ba00147 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -10645,6 +10645,19 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, /* FALLTHRU */ case AND: case IOR: + if (IOR == code + && HImode == mode + && ASHIFT == GET_CODE (XEXP (x, 0))) + { + *total = COSTS_N_INSNS (2); + // Just a rough estimate. If we see no sign- or zero-extend, + // then increase the cost a little bit. + if (REG_P (XEXP (XEXP (x, 0), 0))) + *total += COSTS_N_INSNS (1); + if (REG_P (XEXP (x, 1))) + *total += COSTS_N_INSNS (1); + return true; + } *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)); *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed); if (!CONST_INT_P (XEXP (x, 1))) diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index cfc6b8d..df111ef 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -260,6 +260,10 @@ HQ UHQ HA UHA SQ USQ SA USA]) +;; Post-reload split of 3, 4 bytes wide moves. +(define_mode_iterator SPLIT34 [SI SF PSI + SQ USQ SA USA]) + ;; Define code iterators ;; Define two incarnations so that we can build the cross product. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -267,6 +271,7 @@ (define_code_iterator any_extract [sign_extract zero_extract]) (define_code_iterator any_shiftrt [lshiftrt ashiftrt]) +(define_code_iterator bitop [xor ior and]) (define_code_iterator xior [xor ior]) (define_code_iterator eqne [eq ne]) @@ -3328,6 +3333,66 @@ (set_attr "adjust_len" "*,out_bitop,out_bitop") (set_attr "cc" "set_n,clobber,clobber")]) + +(define_split + [(set (match_operand:SPLIT34 0 "register_operand") + (match_operand:SPLIT34 1 "register_operand"))] + "optimize + && reload_completed" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 4) (match_dup 5))] + { + machine_mode mode_hi = 4 == GET_MODE_SIZE (mode) ? HImode : QImode; + bool lo_first = REGNO (operands[0]) < REGNO (operands[1]); + rtx dst_lo = simplify_gen_subreg (HImode, operands[0], mode, 0); + rtx src_lo = simplify_gen_subreg (HImode, operands[1], mode, 0); + rtx dst_hi = simplify_gen_subreg (mode_hi, operands[0], mode, 2); + rtx src_hi = simplify_gen_subreg (mode_hi, operands[1], mode, 2); + + operands[2] = lo_first ? dst_lo : dst_hi; + operands[3] = lo_first ? src_lo : src_hi; + operands[4] = lo_first ? dst_hi : dst_lo; + operands[5] = lo_first ? src_hi : src_lo; + }) + +(define_split + [(set (match_operand:HI 0 "register_operand") + (match_operand:HI 1 "reg_or_0_operand"))] + "optimize + && reload_completed + && (!AVR_HAVE_MOVW + || const0_rtx == operands[1])" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 4) (match_dup 5))] + { + operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 1); + operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 1); + operands[4] = simplify_gen_subreg (QImode, operands[0], HImode, 0); + operands[5] = simplify_gen_subreg (QImode, operands[1], HImode, 0); + }) + +;; Split andhi3, andpsi3, andsi3. +;; Split iorhi3, iorpsi3, iorsi3. +;; Split xorhi3, xorpsi3, xorsi3. +(define_split + [(parallel [(set (match_operand:HISI 0 "register_operand") + (bitop:HISI (match_dup 0) + (match_operand:HISI 1 "register_operand"))) + (clobber (scratch:QI))])] + "optimize + && reload_completed" + [(const_int 1)] + { + for (int i = 0; i < GET_MODE_SIZE (mode); i++) + { + rtx dst = simplify_gen_subreg (QImode, operands[0], mode, i); + rtx src = simplify_gen_subreg (QImode, operands[1], mode, i); + emit_insn (gen_qi3 (dst, dst, src)); + } + DONE; + }) + + ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap ;; swap @@ -6696,6 +6761,84 @@ operands[4] = simplify_gen_subreg (QImode, operands[0], mode, byteno); }) + +(define_insn_and_split "*iorhi3.ashift8-ext.zerox" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (ashift:HI (any_extend:HI + (match_operand:QI 1 "register_operand" "r")) + (const_int 8)) + (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] + "optimize" + { gcc_unreachable(); } + "&& reload_completed" + [(set (match_dup 1) (xor:QI (match_dup 1) (match_dup 2))) + (set (match_dup 2) (xor:QI (match_dup 2) (match_dup 1))) + (set (match_dup 1) (xor:QI (match_dup 1) (match_dup 2)))] + { + rtx hi = simplify_gen_subreg (QImode, operands[0], HImode, 1); + rtx lo = simplify_gen_subreg (QImode, operands[0], HImode, 0); + + if (!reg_overlap_mentioned_p (hi, operands[2])) + { + emit_move_insn (hi, operands[1]); + emit_move_insn (lo, operands[2]); + DONE; + } + else if (!reg_overlap_mentioned_p (lo, operands[1])) + { + emit_move_insn (lo, operands[2]); + emit_move_insn (hi, operands[1]); + DONE; + } + + gcc_assert (REGNO (operands[1]) == REGNO (operands[0])); + gcc_assert (REGNO (operands[2]) == 1 + REGNO (operands[0])); + }) + +(define_insn_and_split "*iorhi3.ashift8-ext.reg" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (ashift:HI (any_extend:HI + (match_operand:QI 1 "register_operand" "r")) + (const_int 8)) + (match_operand:HI 2 "register_operand" "0")))] + "optimize" + { gcc_unreachable(); } + "&& reload_completed" + [(set (match_dup 3) + (ior:QI (match_dup 4) + (match_dup 1)))] + { + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1); + operands[4] = simplify_gen_subreg (QImode, operands[2], HImode, 1); + }) + +(define_insn_and_split "*iorhi3.ashift8-reg.zerox" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r") + (const_int 8)) + (zero_extend:HI (match_operand:QI 2 "register_operand" "0"))))] + "optimize" + { gcc_unreachable(); } + "&& reload_completed" + [(set (match_dup 3) + (match_dup 4))] + { + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1); + operands[4] = simplify_gen_subreg (QImode, operands[1], HImode, 0); + }) + + +(define_peephole2 + [(set (match_operand:QI 0 "register_operand") + (const_int 0)) + (set (match_dup 0) + (ior:QI (match_dup 0) + (match_operand:QI 1 "register_operand")))] + "" + [(set (match_dup 0) + (match_dup 1))]) + + (define_expand "extzv" [(set (match_operand:QI 0 "register_operand" "") (zero_extract:QI (match_operand:QI 1 "register_operand" "") @@ -6778,7 +6921,6 @@ operands[4] = GEN_INT (bitno % 8); }) - ;; Fixed-point instructions (include "avr-fixed.md") -- 2.7.4