RFA: RL78: Add muladdhi3 pattern

2015-03-03 Thread Nick Clifton
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

2015-03-03 Thread DJ Delorie

   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);