This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, IRA] Fix ALLOCNO_MODE in the case of paradoxical subreg.
- From: Wei Mi <wmi at google dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Vladimir Makarov <vmakarov at redhat dot com>, David Li <davidxl at google dot com>
- Date: Tue, 24 Sep 2013 16:57:21 -0700
- Subject: [PATCH, IRA] Fix ALLOCNO_MODE in the case of paradoxical subreg.
- Authentication-results: sourceware.org; auth=none
Hi,
This patch is to address the problem described here:
http://gcc.gnu.org/ml/gcc/2013-09/msg00187.html
The patch changes ALLOCNO_MODE of a pseudo reg to be outermode if the
pseudo reg is used in a paradoxical subreg, so IRA will not mistakenly
assign an operand with a bigger mode to a smaller hardreg which
couldn't find a pair register.
No test is added because I cannot create a small testcase to reproduce
the problem on trunk, the difficulty of which was described in the
above post.
bootstrap and regression pass. ok for trunk?
Thanks,
Wei Mi.
2013-09-24 Wei Mi <wmi@google.com>
* ira-build.c (create_insn_allocnos): Fix ALLOCNO_MODE
in the case of paradoxical subreg.
Index: ira-build.c
===================================================================
--- ira-build.c (revision 201963)
+++ ira-build.c (working copy)
@@ -1688,6 +1688,30 @@ create_insn_allocnos (rtx x, bool output
}
return;
}
+ else if (code == SUBREG)
+ {
+ int regno;
+ rtx subreg_reg = SUBREG_REG (x);
+ enum machine_mode outermode, innermode;
+
+ create_insn_allocnos (subreg_reg, output_p);
+ /* For paradoxical subreg, set allocno's mode to be
+ the outermode. */
+ outermode = GET_MODE (x);
+ innermode = GET_MODE (subreg_reg);
+ if (REG_P (subreg_reg)
+ && (GET_MODE_SIZE (outermode) > GET_MODE_SIZE (innermode)))
+ {
+ regno = REGNO (subreg_reg);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+ ira_assert (a != NULL);
+ ALLOCNO_MODE (a) = outermode;
+ }
+ }
+ return;
+ }
else if (code == SET)
{
create_insn_allocnos (SET_DEST (x), true);