PATCH [11/n]: Prepare x32: PR rtl-optimization/48155: Reload doesn't handle subreg properly
H.J. Lu
hongjiu.lu@intel.com
Sat Jun 25 19:21:00 GMT 2011
Hi,
This is the last target independent patch for x32. I will start
submitting x86 specific patches in a week.
Given input:
(plus:SI (subreg:SI (plus:DI (reg/f:DI 7 sp)
(const_int 16 [0x10])) 0)
(const_int -1 [0xffffffffffffffff]))
reloads tries to add
(subreg:SI (plus:DI (reg/f:DI 7 sp)
(const_int 16 [0x10])) 0)
to
(reg:SI 1 dx)
This code:
/* How to do this reload can get quite tricky. Normally, we are being
asked to reload a simple operand, such as a MEM, a constant, or a
pseudo
register that didn't get a hard register. In that case we can just
call emit_move_insn.
We can also be asked to reload a PLUS that adds a register or a MEM
to
another register, constant or MEM. This can occur during frame
pointer
elimination and while reloading addresses. This case is handled by
trying to emit a single insn to perform the add. If it is not
valid,
we use a two insn sequence.
Or we can be asked to reload an unary operand that was a fragment
of
an addressing mode, into a register. If it isn't recognized as-is,
we try making the unop operand and the reload-register the same:
(set reg:X (unop:X expr:Y))
-> (set reg:Y expr:Y) (set reg:X (unop:X reg:Y)).
Finally, we could be called to handle an 'o' constraint by putting
an address into a register. In that case, we first try to do this
with a named pattern of "reload_load_address". If no such pattern
exists, we just emit a SET insn and hope for the best (it will
normally
be valid on machines that use 'o').
This entire process is made complex because reload will never
process the insns we generate here and so we must ensure that
they will fit their constraints and also by the fact that parts of
IN might be being reloaded separately and replaced with spill
registers.
Because of this, we are, in some sense, just guessing the right
approach
here. The one listed above seems to work.
??? At some point, this whole thing needs to be rethought. */
if (GET_CODE (in) == PLUS
&& (REG_P (XEXP (in, 0))
|| GET_CODE (XEXP (in, 0)) == SUBREG
|| MEM_P (XEXP (in, 0)))
&& (REG_P (XEXP (in, 1))
|| GET_CODE (XEXP (in, 1)) == SUBREG
|| CONSTANT_P (XEXP (in, 1))
|| MEM_P (XEXP (in, 1))))
doesn't check if XEXP (in, 0/1) is a SUBREG of REG.
This patch adds a new function, reload_plus_ok, to check this condition.
OK for trunk?
Thanks.
H.J.
---
2011-06-25 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/48155
* reload1.c (reload_plus_ok): New.
(gen_reload_chain_without_interm_reg_p): Use it.
(gen_reload): Likewise.
diff --git a/gcc/reload1.c b/gcc/reload1.c
index e65503b..1864ae6 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -5544,6 +5544,54 @@ substitute (rtx *where, const_rtx what, rtx repl)
}
}
+/* Return TRUE if IN is a valid plus operation. */
+
+static bool
+reload_plus_ok (rtx in)
+{
+ if (GET_CODE (in) == PLUS)
+ {
+ rtx op0 = XEXP (in, 0);
+ rtx op1 = XEXP (in, 1);
+ if ((REG_P (op0)
+ || GET_CODE (op0) == SUBREG
+ || MEM_P (op0))
+ && (REG_P (op1)
+ || GET_CODE (op1) == SUBREG
+ || CONSTANT_P (op1)
+ || MEM_P (op1)))
+ {
+ rtx subreg, other;
+ if (GET_CODE (op0) == SUBREG)
+ {
+ subreg = SUBREG_REG (op0);
+ other = op1;
+ }
+ else if (GET_CODE (op1) == SUBREG)
+ {
+ subreg = SUBREG_REG (op1);
+ other = op0;
+ }
+ else
+ return true;
+
+ /* Avoid
+ (plus (subreg (plus (reg)
+ (const_int NNN)))
+ (const_int NNN))
+ */
+ if (GET_CODE (subreg) == PLUS
+ && (CONSTANT_P (XEXP (subreg, 0))
+ || CONSTANT_P (XEXP (subreg, 1)))
+ && CONSTANT_P (other))
+ return false;
+
+ return true;
+ }
+ }
+ return false;
+}
+
/* The function returns TRUE if chain of reload R1 and R2 (in any
order) can be evaluated without usage of intermediate register for
the reload containing another reload. It is important to see
@@ -5596,14 +5644,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
strip_paradoxical_subreg (&in, &out);
- if (GET_CODE (in) == PLUS
- && (REG_P (XEXP (in, 0))
- || GET_CODE (XEXP (in, 0)) == SUBREG
- || MEM_P (XEXP (in, 0)))
- && (REG_P (XEXP (in, 1))
- || GET_CODE (XEXP (in, 1)) == SUBREG
- || CONSTANT_P (XEXP (in, 1))
- || MEM_P (XEXP (in, 1))))
+ if (reload_plus_ok (in))
{
insn = emit_insn (gen_rtx_SET (VOIDmode, out, in));
code = recog_memoized (insn);
@@ -8449,14 +8490,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
??? At some point, this whole thing needs to be rethought. */
- if (GET_CODE (in) == PLUS
- && (REG_P (XEXP (in, 0))
- || GET_CODE (XEXP (in, 0)) == SUBREG
- || MEM_P (XEXP (in, 0)))
- && (REG_P (XEXP (in, 1))
- || GET_CODE (XEXP (in, 1)) == SUBREG
- || CONSTANT_P (XEXP (in, 1))
- || MEM_P (XEXP (in, 1))))
+ if (reload_plus_ok (in))
{
/* We need to compute the sum of a register or a MEM and another
register, constant, or MEM, and put it into the reload
More information about the Gcc-patches
mailing list