diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2025-08-05 17:48:43 +0200 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2025-08-05 17:53:58 +0200 |
commit | 59236d56eec6854e261dbf16963d5ee9e03bf7d5 (patch) | |
tree | 0e16969e00ba09219e4b3eb9a6ae287ddd4e4241 | |
parent | c9da74d5ad383b309195afb37b9044c1087da026 (diff) | |
download | gcc-master.zip gcc-master.tar.gz gcc-master.tar.bz2 |
gcc/
* config/avr/avr.cc (avr_rtx_costs_1) [SIGN_EXTEND]: Adjust cost.
* config/avr/avr.md (*sext.ashift<QIPSI:mode><HISI:mode>2): New
insn and a cc split.
-rw-r--r-- | gcc/config/avr/avr.cc | 10 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 37 |
2 files changed, 46 insertions, 1 deletions
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 1bfa3f5..ae49d4d 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -12758,6 +12758,16 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, return true; case SIGN_EXTEND: + if (GET_CODE (XEXP (x, 0)) == ASHIFT + && CONST_INT_P (XEXP (XEXP (x, 0), 1))) + { + // "*sext.ashift<QIPSI:mode><HISI:mode>2_split" + int m0 = GET_MODE_SIZE (GET_MODE (XEXP (x, 0))); + int m1 = GET_MODE_SIZE (mode); + *total = COSTS_N_INSNS (m0 * INTVAL (XEXP (XEXP (x, 0), 1)) + + m1 - m0); + return true; + } *total = COSTS_N_INSNS (n_bytes + 2 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))); *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)), diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index d4bf4da..60b1f60 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2943,7 +2943,7 @@ [(set (match_operand:HI 0 "register_operand" "=r,*r") (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r")) (const_int 1))) - (clobber (reg:CC REG_CC)) ] + (clobber (reg:CC REG_CC))] "reload_completed" "@ lsl %A0\;sbc %B0,%B0 @@ -3004,6 +3004,41 @@ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode); }) +(define_insn_and_split "*sext.ashift<QIPSI:mode><HISI:mode>2_split" + [(set (match_operand:HISI 0 "register_operand" "=r") + (sign_extend:HISI (ashift:QIPSI (match_operand:QIPSI 1 "register_operand" "0") + (match_operand:QI 2 "const_int_operand" "PKC03"))))] + "<HISI:SIZE> > <QIPSI:SIZE> + && IN_RANGE (INTVAL (operands[2]), 1, 2 + (<QIPSI:SIZE> <= 2))" + "#" + "&& reload_completed" + [(scratch)] + { DONE_ADD_CCC }) + +(define_insn "*sext.ashift<QIPSI:mode><HISI:mode>2" + [(set (match_operand:HISI 0 "register_operand" "=r") + (sign_extend:HISI (ashift:QIPSI (match_operand:QIPSI 1 "register_operand" "0") + (match_operand:QI 2 "const_int_operand" "PKC03")))) + (clobber (reg:CC REG_CC))] + "reload_completed + && <HISI:SIZE> > <QIPSI:SIZE> + && IN_RANGE (INTVAL (operands[2]), 1, 2 + (<QIPSI:SIZE> <= 2))" + { + const int regno = REGNO (operands[0]); + // The shift. + for (int s = 0; s < (int) INTVAL (operands[2]); ++s) + for (int b = 0; b < <QIPSI:SIZE>; ++b) + output_asm_insn (b == 0 ? "lsl %0" : "rol %0", + &all_regs_rtx[regno + b]); + // Sign-extend can use carry. + for (int b = <QIPSI:SIZE>; b < <HISI:SIZE>; ++b) + output_asm_insn ("sbc %0,%0", &all_regs_rtx[regno + b]); + return ""; + } + [(set (attr "length") + (plus (symbol_ref "<QIPSI:SIZE> * INTVAL (operands[2])") + (symbol_ref "<HISI:SIZE> - <QIPSI:SIZE>")))]) + ;****************************************************************************** ; mul HI: $1 = sign-/zero-/one-extend, $2 = reg ;****************************************************************************** |