@@ -88,6 +88,7 @@ static int thumb1_base_register_rtx_p (rtx, enum machine_mode, int);
static rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
static reg_class_t arm_preferred_reload_class (rtx, reg_class_t);
static rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
+static void arm_reassoc_shifts_in_address (rtx);
inline static int thumb1_index_register_rtx_p (rtx, int);
static bool arm_legitimate_address_p (enum machine_mode, rtx, bool);
static int thumb_far_jump_used_p (void);
@@ -7501,7 +7502,8 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{
/* TODO: legitimize_address for Thumb2. */
if (TARGET_THUMB2)
- return x;
+ return x;
+
return thumb_legitimize_address (x, orig_x, mode);
}
@@ -7551,6 +7553,9 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
}
else if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1))
x = gen_rtx_PLUS (SImode, xop0, xop1);
+
+ if (GET_CODE (xop0) == PLUS)
+ arm_reassoc_shifts_in_address (xop0);
}
/* XXX We don't allow MINUS any more -- see comment in
@@ -7614,7 +7619,8 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
/* Try machine-dependent ways of modifying an illegitimate Thumb address
to be legitimate. If we find one, return the new, valid address. */
-rtx
+
+static rtx
thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{
if (GET_CODE (x) == PLUS
@@ -7679,6 +7685,47 @@ thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
return x;
}
+/* Transform
+ PLUS (PLUS (MULT1, MULT2), REG)
+ to
+ PLUS (PLUS (MULT1, REG), MULT2)
+ so that we can use two add (shifted register) instructions
+ to compute the expression. Note that SHIFTs has already
+ been replaced with MULTs as a result of canonicalization.
+
+ This routine is to help undo the undesired canonicalization
+ that is done by simplify_gen_binary on addresses with
+ multiple shifts. For example, it will help transform
+ (x << 6) + (y << 4) + p + 8
+ back to:
+ (x << 6) + p + (y << 4) + 8
+ where p is the start address of a two-dimensional array and
+ x and y are the indexes. */
+
+static void
+arm_reassoc_shifts_in_address (rtx x)
+{
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (GET_CODE (op0) == PLUS && REG_P (op1))
+ {
+ rtx xop0 = XEXP (op0, 0);
+ rtx xop1 = XEXP (op0, 1);
+
+ if (GET_CODE (xop0) == MULT && GET_CODE (xop1) == MULT
+ && power_of_two_operand (XEXP (xop0, 1), GET_MODE (xop0))
+ && power_of_two_operand (XEXP (xop1, 1), GET_MODE (xop1)))
+ {
+ XEXP (op0, 1) = op1;
+ XEXP (x, 1) = xop1;
+ }
+ }
+ }
+}
+
bool
arm_legitimize_reload_address (rtx *p,
enum machine_mode mode,
new file mode 100644
@@ -0,0 +1,47 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2" } */
+
+typedef struct { int x,y,a,b; } x;
+
+int
+f7a(x p[][4], int x, int y)
+{
+ return p[x][y].a;
+}
+
+/* { dg-final { object-size text <= 16 { target { { ! arm_thumb1 } && { ! arm_thumb2 } } } } } */
+/* { dg-final { object-size text <= 12 { target arm_thumb2 } } } */
+
+
+/* For arm code-gen, expect four instructions like:
+
+ 0: e0801301 add r1, r0, r1, lsl #6
+ 4: e0812202 add r2, r1, r2, lsl #4
+ 8: e5920008 ldr r0, [r2, #8]
+ c: e12fff1e bx lr
+
+ instead of
+
+ 0: e1a02202 lsl r2, r2, #4
+ 4: e0821301 add r1, r2, r1, lsl #6
+ 8: e0800001 add r0, r0, r1
+ c: e5900008 ldr r0, [r0, #8]
+ 10: e12fff1e bx lr
+
+
+ for thumb2 code-gen, expect four instructions like:
+
+ 0: eb00 1181 add.w r1, r0, r1, lsl #6
+ 4: eb01 1202 add.w r2, r1, r2, lsl #4
+ 8: 6890 ldr r0, [r2, #8]
+ a: 4770 bx lr
+
+ instead of
+
+ 0: ea4f 1202 mov.w r2, r2, lsl #4
+ 4: eb02 1181 add.w r1, r2, r1, lsl #6
+ 8: 4408 add r0, r1
+ a: 6880 ldr r0, [r0, #8]
+ c: 4770 bx lr
+ e: bf00 nop
+*/
new file mode 100644
@@ -0,0 +1,50 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2" } */
+
+typedef struct { int x,y,a,b; } x;
+
+int
+f8a(x p[][4][4], int x, int y, int z)
+{
+ return p[x][y][z].a;
+}
+
+/* { dg-final { object-size text <= 20 { target { { ! arm_thumb1 } && { ! arm_thumb2 } } } } } */
+/* { dg-final { object-size text <= 16 { target arm_thumb2 } } } */
+
+
+/* For arm code-gen, expect five instructions like:
+
+ 0: e0833102 add r3, r3, r2, lsl #2
+ 4: e0800401 add r0, r0, r1, lsl #8
+ 8: e0803203 add r3, r0, r3, lsl #4
+ c: e5930008 ldr r0, [r3, #8]
+ 10: e12fff1e bx lr
+
+ instead of
+
+ 0: e0833102 add r3, r3, r2, lsl #2
+ 4: e1a03203 lsl r3, r3, #4
+ 8: e0831401 add r1, r3, r1, lsl #8
+ c: e0800001 add r0, r0, r1
+ 10: e5900008 ldr r0, [r0, #8]
+ 14: e12fff1e bx lr
+
+ for thumb2 code-gen, expect five instructions like:
+
+ 0: eb03 0382 add.w r3, r3, r2, lsl #2
+ 4: eb00 2001 add.w r0, r0, r1, lsl #8
+ 8: eb00 1303 add.w r3, r0, r3, lsl #4
+ c: 6898 ldr r0, [r3, #8]
+ e: 4770 bx lr
+
+ instead of
+
+ 0: eb03 0382 add.w r3, r3, r2, lsl #2
+ 4: ea4f 1303 mov.w r3, r3, lsl #4
+ 8: eb03 2101 add.w r1, r3, r1, lsl #8
+ c: 4408 add r0, r1
+ e: 6880 ldr r0, [r0, #8]
+ 10: 4770 bx lr
+ 12: bf00 nop
+*/