[MIPS][LS2][4/5] Scheduling and tuning
Richard Sandiford
rdsandiford@googlemail.com
Thu Jun 12 18:06:00 GMT 2008
Maxim Kuvyrkov <maxim@codesourcery.com> writes:
> Maxim Kuvyrkov wrote:
>> Richard Sandiford wrote:
>
> ...
>
>>> Anyway, this patch looks good, thanks. A neat use of CPU querying ;)
>
> I believe this patch exposes a latent bug in MIPS backend.
>
> Though the bug is visible only when scheduling for Loongson, my
> investigation suggests that it can occur on other MIPS architectures too.
>
> Here is the error:
>
> <snip>
> ./cc1 -quiet -march=loongson2e -O2 -o testcase.s testcase.c
> testcase.c: In function '_nl_normalize_codeset':
> testcase.c:211: error: unable to find a register to spill in class 'V1_REG'
> testcase.c:211: error: this is the insn:
> (insn 51 45 47 3 testcase.c:150 (set (reg:SI 11 $11 [279])
> (unspec:SI [
> (const_int 0 [0x0])
> ] 30)) 570 {tls_get_tp_si} (expr_list:REG_EQUIV (unspec:SI [
> (const_int 0 [0x0])
> ] 30)
> (nil)))
> testcase.c:211: internal compiler error: in spill_failure, at reload1.c:1999
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
> </snip>
FWIW, this is PR 35802. 'Fraid I still haven't had chance to look at it,
what with IRA, recog-related stuff and reviews.
> The error is triggered by two consecutive tls_get_tp_si instructions.
> These instructions use "v" constraint, which specifies V1_REG, aka $3.
>
> If no scheduling is performed, then the two tls_get_tp_si instructions
> are separated by one instruction; when the scheduler is on, they end up
> together and reload crashes.
>
> In the case when two get_tp instructions are separated by a third
> instruction, reload manages to remove the second get_tp instruction
> (instructions are the same, so only one of them is needed) and
> everything works out well. If the two instructions are side-by-side
> reload can't find a spill register for the second get_tp and crashes.
>
> My speculation is that mov<mode>_internal should be taught how to move
> "v" into "d". RichardS should know for sure.
It already knows how to do that. "v" is a subclass of "d", so it's
just a normal GPR<->GPR move.
The problem is that "v" represents a single register: $3. We initially
generate these instructions with $3 as the result, but the insn predicates
allow it to be replaced by any register_operand later. Thus we can end
up with a pseudo register that is:
(a) the output operand of a tls_get_tp_<mode> insn, and must thus
be reloaded into $3;
(b) live at the same time as an explicit $3.
We have two choices:
- always use pseudo registers, rather than introducing uses of $3
from the outset
- force the destination of tls_get_tp_<mode> to be $3 only.
The second is probably the most conservative approach, since explicit
uses of $3 can occur through normal calls. The patch below does this.
I admit I haven't verified any of this yet, so sorry if I'm off-ball.
But does the patch fix things?
Richard
gcc/
* config/mips/predicates.md (v1_operand): New predicate.
* config/mips/mips.md (tls_get_tp_<mode>): Use it instead of
register_operand.
Index: gcc/config/mips/predicates.md
===================================================================
--- gcc/config/mips/predicates.md 2008-06-12 18:54:01.000000000 +0100
+++ gcc/config/mips/predicates.md 2008-06-12 19:03:27.000000000 +0100
@@ -76,6 +76,10 @@ (define_predicate "const_0_or_1_operand"
(ior (match_test "op == CONST0_RTX (GET_MODE (op))")
(match_test "op == CONST1_RTX (GET_MODE (op))"))))
+(define_predicate "v1_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == GP_RETURN + 1")))
+
(define_predicate "d_operand"
(and (match_code "reg")
(match_test "TARGET_MIPS16
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md 2008-06-12 18:53:41.000000000 +0100
+++ gcc/config/mips/mips.md 2008-06-12 18:53:49.000000000 +0100
@@ -6410,7 +6410,7 @@ (define_insn "*mips16e_save_restore"
; accept it.
(define_insn "tls_get_tp_<mode>"
- [(set (match_operand:P 0 "register_operand" "=v")
+ [(set (match_operand:P 0 "v1_operand" "=v")
(unspec:P [(const_int 0)]
UNSPEC_TLS_GET_TP))]
"HAVE_AS_TLS && !TARGET_MIPS16"
More information about the Gcc-patches
mailing list