RFA: RL78: Add muladdhi3 pattern
Hi DJ, Compiling this test case with the RL78 toolchain results in an ICE: unsigned char g_X; unsigned char g_Y; const __far unsigned char TabA[2][2] = { { 3, 0 }, { 4, 5 } }; void main (void) { g_X = 1; g_Y = TabA[g_X][g_X]; } The problem appears to be that GCC will create a multiply-plus-add instruction to access the table regardless of whether the backend supports such an instruction. I could not work out where in the middle end this was occurring, so instead I created the patch below which contains a splitter to separate out the multiply and addition operations. Tested with no regressions on an rl78-elf toolchain. OK to apply ? Cheers Nick gcc/ChangeLog 2015-03-03 Nick Clifton ni...@redhat.com * config/rl78/rl78.md (muladdhi4): New splitter. Index: gcc/config/rl78/rl78.md === --- gcc/config/rl78/rl78.md (revision 221150) +++ gcc/config/rl78/rl78.md (working copy) @@ -441,3 +441,15 @@ ) + +(define_insn_and_split muladdhi4 + [(set (match_operand:HI 0 register_operand =v) + (plus:HI (mult:HI (match_operand:HI 1 general_operand vi) + (match_operand:HI 2 general_operand vi)) +(match_operand:HI 3 register_operand v)))] + ! RL78_MUL_NONE + # + + [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 3)))] +)
Re: RFA: RL78: Add muladdhi3 pattern
The problem appears to be that GCC will create a multiply-plus-add instruction to access the table regardless of whether the backend supports such an instruction. I could not work out where in the middle end this was occurring, so instead I created the patch below which contains a splitter to separate out the multiply and addition operations. I've seen this before. The root of the problem is in expand_expr_real_1() where convert_to_mode() is called (around line 10262 in my tree) to change the address's mode from HImode to SImode, but this happens *before* the address itself is legitimized (I think). So we have an invalid address causing the problem, at a point were we don't care if the address is valid or not. Either the address must be legitimized before that point, or some other conversion needs to be used. Either way, I think adding a pattern for this particular address is only hiding the problem, not fixing it. if (offset) { machine_mode address_mode; rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM); gcc_assert (MEM_P (op0)); address_mode = get_address_mode (op0); if (GET_MODE (offset_rtx) != address_mode) -- offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);