This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: Add IRA support to FRV
- From: Nick Clifton <nickc at redhat dot com>
- To: aldyh at redhat dot com, aoliva at redhat dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Sep 2008 15:31:56 +0100
- Subject: RFA: Add IRA support to FRV
Hi Aldy, Hi Alex,
OK, here is my official submission of a patch to add IRA support to
the FRV target. Actually there are three patches, although I have
combined them into one submission.
The first patch fixes an ICE when trying to compile any program.
(It shows up as a configure failure when trying to build libgcc).
This patch is independent of the IRA addition, but it was necessary
to fix it in order to build the frv-elf toolchain so that I could
test the IRA patch.
The problem is that during register class initialisation the code in
regclass.c:init_reg_autoinc() calls secondary_reload_class() which
goes through to default_secondary_reload() in targhooks.c which then
tries to use the reload_[in|out]_optab[] arrays, even though they
have not yet been initialised. This results in the 'icode' variable
being given a value of 0, which triggers an assertion failure
because pattern 0 does not take 3 operands.
My original fix for this problem was a patch to
default_secondary_reload() to treat an icode of 0 as if it were
CODE_FOR_nothing, but I have reconsidered this since I cannot be
sure that on another target icode 0 might very well be a valid insn
code. Instead I have gone for an FRV specific fix which defines a
new function frv_secondary_reload() just to handle this problem.
The second part of the patch is the addition of the
IRA_COVER_CLASSES macro. This is quite straightforward.
The final part of the patch is a fix for the FR550 insn reservations
because the new register allocator triggers a latent bug in the
restrictions on floating point and media instructions. Specifically
the problem is that the exclusions do not prevent a single media
instruction from being added to a packet that already contains two
or more floating point instructions. I have discussed this patch
with Alex via email, and although it is not ideal, it will do for
now. (Well at least that is my opinion. :-)
So - please may I apply this patch ?
I am running the gcc and g++ testsuites locally with the patches
applied and I will send the results to gcc-testresults one they are
done (and assuming that the patch is approved).
Cheers
Nick
gcc/ChangeLog
2008-09-16 Nick Clifton <nickc@redhat.com>
* config/frv/frv.h (IRA_COVER_CLASSES): Define.
(SECONDARY_INPUT_RELOAD_CLASS): Omit unused argument in call
to frv_secondary_reload_class.
(SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
* config/frv/frv.c (TARGET_SECONDARY_RELOAD): Define.
(frv_secondary_reload_class): Omit unused parameter.
(frv_secondary_reload): New function. Handle the case when
secondary_reload_class() is called before the reload_(in|out)
_optabs have been initialised.
* config/frv/frv-protos.h (frv_secondary_reload_class): Omit
unused parameter.
* config/frv/frv.md: Define an exclusion set between fr550_m0
and fr550_f0.
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h (revision 140386)
+++ gcc/config/frv/frv.h (working copy)
@@ -1153,6 +1153,21 @@
{ 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x1fff}, /* ALL_REGS */\
}
+/* The following macro defines cover classes for Integrated Register
+ Allocator. Cover classes is a set of non-intersected register
+ classes covering all hard registers used for register allocation
+ purpose. Any move between two registers of a cover class should be
+ cheaper than load or store of the registers. The macro value is
+ array of register classes with LIM_REG_CLASSES used as the end
+ marker. */
+
+#define IRA_COVER_CLASSES \
+{ \
+ GPR_REGS, FPR_REGS, ACC_REGS, ICR_REGS, FCR_REGS, ICC_REGS, FCC_REGS, \
+ ACCG_REGS, SPR_REGS, \
+ LIM_REG_CLASSES \
+}
+
/* A C expression whose value is a register class containing hard register
REGNO. In general there is more than one such class; choose a class which
is "minimal", meaning that no smaller class also contains the register. */
@@ -1235,10 +1250,10 @@
#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
- frv_secondary_reload_class (CLASS, MODE, X, TRUE)
+ frv_secondary_reload_class (CLASS, MODE, X)
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
- frv_secondary_reload_class (CLASS, MODE, X, FALSE)
+ frv_secondary_reload_class (CLASS, MODE, X)
/* A C expression whose value is nonzero if pseudos that have been assigned to
registers of class CLASS would likely be spilled because registers of CLASS
Index: gcc/config/frv/frv.md
===================================================================
--- gcc/config/frv/frv.md (revision 140386)
+++ gcc/config/frv/frv.md (working copy)
@@ -1179,6 +1179,18 @@
(define_cpu_unit "fr550_f0,fr550_f1,fr550_f2,fr550_f3" "fr550_float_media")
(define_cpu_unit "fr550_m0,fr550_m1,fr550_m2,fr550_m3" "fr550_float_media")
(exclusion_set "fr550_f1,fr550_f2,fr550_f3" "fr550_m1,fr550_m2,fr550_m3")
+(exclusion_set "fr550_m0" "fr550_f1,fr550_f2,fr550_f3")
+;; FIXME: This next exclusion set should be defined as well, so that we do
+;; not get a packet containing multiple media instructions plus a single
+;; floating point instruction. At the moment we can get away with not
+;; defining it because gcc does not seem to generate such packets.
+;;
+;; If we do enable the exclusion however the insertion of fnop insns into
+;; a packet containing media instructions will stop working, because the
+;; fnop insn counts as a floating point instruction. The correct solution
+;; is to fix the reservation for the fnop insn so that it does not have the
+;; same restrictions as ordinary floating point insns.
+;;(exclusion_set "fr550_f0" "fr550_m1,fr550_m2,fr550_m3")
(define_reservation "fr550_float" "fr550_f0|fr550_f1|fr550_f2|fr550_f3")
(define_reservation "fr550_media" "fr550_m0|fr550_m1|fr550_m2|fr550_m3")
Index: gcc/config/frv/frv-protos.h
===================================================================
--- gcc/config/frv/frv-protos.h (revision 140386)
+++ gcc/config/frv/frv-protos.h (working copy)
@@ -104,9 +104,8 @@
extern int frv_trampoline_size (void);
extern void frv_initialize_trampoline (rtx, rtx, rtx);
extern enum reg_class frv_secondary_reload_class
- (enum reg_class rclass,
- enum machine_mode mode,
- rtx x, int);
+ (enum reg_class,
+ enum machine_mode, rtx);
extern int frv_class_likely_spilled_p (enum reg_class rclass);
extern int frv_hard_regno_mode_ok (int, enum machine_mode);
extern int frv_hard_regno_nregs (int, enum machine_mode);
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c (revision 140386)
+++ gcc/config/frv/frv.c (working copy)
@@ -381,6 +381,9 @@
tree, bool);
static void frv_output_dwarf_dtprel (FILE *, int, rtx)
ATTRIBUTE_UNUSED;
+static bool frv_secondary_reload (bool, rtx, enum reg_class,
+ enum machine_mode,
+ secondary_reload_info *);
/* Allow us to easily change the default for -malloc-cc. */
#ifndef DEFAULT_NO_ALLOC_CC
@@ -462,6 +465,9 @@
#define TARGET_ASM_OUTPUT_DWARF_DTPREL frv_output_dwarf_dtprel
#endif
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD frv_secondary_reload
+
struct gcc_target targetm = TARGET_INITIALIZER;
#define FRV_SYMBOL_REF_TLS_P(RTX) \
@@ -6343,8 +6349,7 @@
enum reg_class
frv_secondary_reload_class (enum reg_class rclass,
enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx x,
- int in_p ATTRIBUTE_UNUSED)
+ rtx x)
{
enum reg_class ret;
@@ -6403,6 +6408,42 @@
return ret;
}
+/* This hook exists to catch the case where secondary_reload_class() is
+ called from init_reg_autoinc() in regclass.c - before the reload optabs
+ have been initialised. */
+
+static bool
+frv_secondary_reload (bool in_p, rtx x, enum reg_class reload_class,
+ enum machine_mode reload_mode,
+ secondary_reload_info * sri)
+{
+ enum reg_class rclass = NO_REGS;
+
+ if (sri->prev_sri && sri->prev_sri->t_icode != CODE_FOR_nothing)
+ {
+ sri->icode = sri->prev_sri->t_icode;
+ return NO_REGS;
+ }
+
+ rclass = frv_secondary_reload_class (reload_class, reload_mode, x);
+
+ if (rclass != NO_REGS)
+ {
+ enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
+ : reload_out_optab[(int) reload_mode]);
+ if (icode == 0)
+ {
+ /* This happens when then the reload_[in|out]_optabs have
+ not been initialised. */
+ sri->t_icode = CODE_FOR_nothing;
+ return rclass;
+ }
+ }
+
+ /* Fall back to the default secondary reload handler. */
+ return default_secondary_reload (in_p, x, reload_class, reload_mode, sri);
+
+}
/* A C expression whose value is nonzero if pseudos that have been assigned to
registers of class RCLASS would likely be spilled because registers of RCLASS