If the Floating-Point Coprocessor option is configured and there are no
floating-point coprocessor instructions in the function, the unused
floating-point registers (f0 thru f15) can be good targets for spilling
address (integer) registers.
For reference, the ISA manual says that [RW]FR machine instructions have
non-arithmetic behavior and do not raise floating-point exceptions.
/* example */
int test(int a, int b) {
asm volatile ("#
clobbers":::"a2","a3","a4","a5","a6","a7","a8","a9","a10","a11","a12","a13","a14","a15");
return a + b * 8;
}
;; before (-O2 -mabi=windowed)
test:
entry sp, 48
s32i.n a2, sp, 0
s32i.n a3, sp, 4
# clobbers
l32i.n a8, sp, 4
l32i.n a9, sp, 0
addx8 a2, a8, a9
retw.n
;; after (-O2 -mabi=windowed)
test:
entry sp, 48
wfr f1, a2
wfr f0, a3
# clobbers
rfr a8, f0
rfr a9, f1
addx8 a2, a8, a9
retw.n
gcc/ChangeLog:
* config/xtensa/xtensa.cc (machine_function):
Add a new int field "hard_float_insn_usage".
(xtensa_spill_class): New prototype and function.
(TARGET_SPILL_CLASS): Define macro.
(xtensa_option_override): Modify the organization of the
"xtensa_hard_regno_mode_ok_p" matrix to allow floating-point
registers to hold SImode values in addition to SFmode.
* config/xtensa/xtensa.md (movsi_internal):
Add two machine instructions for moving from/to floating-point
registers to the instruction template list.
---
gcc/config/xtensa/xtensa.cc | 74 ++++++++++++++++++++++++++++++++++++-
gcc/config/xtensa/xtensa.md | 34 +++++++++--------
2 files changed, 91 insertions(+), 17 deletions(-)
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 2e7a9df32d2..7573b55b36b 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -110,6 +110,7 @@ struct GTY(()) machine_function
rtx last_logues_a9_content;
HARD_REG_SET eliminated_callee_saved;
hash_map<rtx, int> *litpool_usage;
+ int hard_float_insn_usage;
};
static void xtensa_option_override (void);
@@ -203,6 +204,7 @@ static rtx xtensa_delegitimize_address (rtx);
static reg_class_t xtensa_ira_change_pseudo_allocno_class (int, reg_class_t,
reg_class_t);
static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET);
+static reg_class_t xtensa_spill_class (reg_class_t, machine_mode);
@@ -376,6 +378,9 @@ static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET);
#undef TARGET_ZERO_CALL_USED_REGS
#define TARGET_ZERO_CALL_USED_REGS xtensa_zero_call_used_regs
+#undef TARGET_SPILL_CLASS
+#define TARGET_SPILL_CLASS xtensa_spill_class
+
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -3040,7 +3045,7 @@ xtensa_option_override (void)
else if (GP_REG_P (regno))
temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
else if (FP_REG_P (regno))
- temp = (TARGET_HARD_FLOAT && (mode == SFmode));
+ temp = (TARGET_HARD_FLOAT && (mode == SFmode || mode == SImode));
else if (BR_REG_P (regno))
temp = (TARGET_BOOLEANS && (mode == CCmode));
else
@@ -5671,4 +5676,71 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs)
return selected_regs;
}
+/* Implement TARGET_SPILL_CLASS.
+
+ This hook is called several times during the LRA pass, for each function
+ being compiled. */
+
+static reg_class_t
+xtensa_spill_class (reg_class_t rclass, machine_mode mode)
+{
+ rtx_insn *insn;
+
+ /* This does not apply unless all of the following conditions are met:
+ - The Floating-Point Coprocessor Option is enabled (prerequisite)
+ - The optimization level is greater than 1
+ - Optimizing for speed or the Code Density Option is not enabled */
+ if (! (TARGET_HARD_FLOAT
+ && optimize > 1
+ && (!optimize_size || !TARGET_DENSITY)))
+ return NO_REGS;
+
+ /* Allow integer registers to be spilled into FP_REGS rclass (to which
+ floating-point registers belong) only if the function currently being
+ compiled does not contain any floating-point coprocessor instructions. */
+retry:
+ switch (cfun->machine->hard_float_insn_usage)
+ {
+ case 0: /* Not yet investigated (the initial state). */
+ /* Scan the insns in the function for floating-point coprocessor
+ instructions. */
+ for (insn = get_insns ();
+ (insn = next_nonnote_nondebug_insn (insn)); )
+ if (recog_memoized (insn) >= 0)
+ switch (get_attr_type (insn))
+ {
+ /* An insn that is a floating-point coprocessor instruction is
+ found, so record this. */
+ case TYPE_FARITH:
+ case TYPE_FMADD:
+ case TYPE_FCONV:
+ case TYPE_FLOAD:
+ case TYPE_FSTORE:
+ cfun->machine->hard_float_insn_usage = 1;
+ goto retry;
+ default:
+ break;
+ }
+ /* No insn that is a floating-point coprocessor instruction was found,
+ so record this. */
+ cfun->machine->hard_float_insn_usage = 2;
+ goto retry;
+ case 1: /* Contains floating-point coprocessor instructions. */
+ /* Deny spilling to any rclass. */
+ return NO_REGS;
+ default: /* Does not contain floating-point coprocessor
+ instructions. */
+ break;
+ }
+
+ /* If rclass belongs to GENERAL_REGS and SImode is specified, spilling
+ to FP_REGS is allowed. */
+ if (reg_class_subset_p (rclass, GENERAL_REGS)
+ && mode == SImode)
+ return FP_REGS;
+
+ /* Deny spilling to any rclass. */
+ return NO_REGS;
+}
+
#include "gt-xtensa.h"
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 52ffb161c0f..6371e3976f1 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1293,22 +1293,24 @@
(match_operand:SI 1 "move_operand"))]
"xtensa_valid_move (SImode, operands)"
{@ [cons: =0, 1; attrs: type, length]
- [ D, M; move , 2] movi.n\t%0, %x1
- [ D, D; move , 2] mov.n\t%0, %1
- [ D, d; move , 2] ^
- [ D, R; load , 2] %v1l32i.n\t%0, %1
- [ R, D; store, 2] %v0s32i.n\t%1, %0
- [ R, d; store, 2] ^
- [ a, r; move , 3] mov\t%0, %1
- [ q, r; move , 3] movsp\t%0, %1
- [ a, I; move , 3] movi\t%0, %x1
- [ a, Y; load , 3] movi\t%0, %1
- [ W, i; move , 6] const16\t%0, %t1\;const16\t%0, %b1
- [ a, T; load , 3] %v1l32r\t%0, %1
- [ a, U; load , 3] %v1l32i\t%0, %1
- [ U, r; store, 3] %v0s32i\t%1, %0
- [*a, *A; rsr , 3] rsr\t%0, ACCLO
- [*A, *r; wsr , 3] wsr\t%1, ACCLO
+ [ D, M; move , 2] movi.n\t%0, %x1
+ [ D, D; move , 2] mov.n\t%0, %1
+ [ D, d; move , 2] ^
+ [ D, R; load , 2] %v1l32i.n\t%0, %1
+ [ R, D; store , 2] %v0s32i.n\t%1, %0
+ [ R, d; store , 2] ^
+ [ a, r; move , 3] mov\t%0, %1
+ [ q, r; move , 3] movsp\t%0, %1
+ [ a, I; move , 3] movi\t%0, %x1
+ [ a, Y; load , 3] movi\t%0, %1
+ [ W, i; move , 6] const16\t%0, %t1\;const16\t%0, %b1
+ [ a, T; load , 3] %v1l32r\t%0, %1
+ [ a, U; load , 3] %v1l32i\t%0, %1
+ [ U, r; store , 3] %v0s32i\t%1, %0
+ [*a, *f; farith, 3] rfr\t%0, %1
+ [*f, *r; farith, 3] wfr\t%0, %1
+ [*a, *A; rsr , 3] rsr\t%0, ACCLO
+ [*A, *r; wsr , 3] wsr\t%1, ACCLO
}
[(set_attr "mode" "SI")])
--
2.39.5