Commit da734fa1 by Richard Sandiford Committed by Richard Sandiford

mips.h (BASE_INSN_LENGTH, [...]): New macros.

gcc/
	* config/mips/mips.h (BASE_INSN_LENGTH, NOP_INSN_LENGTH): New macros.
	* config/mips/mips.c (mips_symbol_insns, mips_address_insns)
	(mips_const_insns, mips_split_const_insns, mips_load_store_insns)
	(mips_idiv_insns): Update the comments to say that the returned
	instruction counts are in units of BASE_INSN_LENGTH.
	(mips_adjust_insn_length): Multiply the mips_load_label_num_insns
	by BASE_INSN_LENGTH rather than 4.  Add the jump separately,
	using 2 rather than 4 as the length of indirect MIPS16 and
	microMIPS jumps.  Use NOP_INSN_LENGTH rather than 4 as the
	length of a NOP.  Don't divide MIPS16 lengths by 2.
	(mips16_split_long_branches): Assume a branch is long if the
	length is greater than 4 rather than 8.
	* config/mips/mips.md (length): Give MIPS16 lengths directly,
	rather than multiplying them by 2.  Multiply instruction counts
	by BASE_INSN_LENGTH rather than 4.
	(*jump_mips16, tls_get_tp_mips16_<mode>)
	(*tls_get_tp_mips16_call_<mode>): Divide lengths by 2.

From-SVN: r199080
parent e2420687
2013-05-19 Richard Sandiford <rdsandiford@googlemail.com> 2013-05-19 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips.h (BASE_INSN_LENGTH, NOP_INSN_LENGTH): New macros.
* config/mips/mips.c (mips_symbol_insns, mips_address_insns)
(mips_const_insns, mips_split_const_insns, mips_load_store_insns)
(mips_idiv_insns): Update the comments to say that the returned
instruction counts are in units of BASE_INSN_LENGTH.
(mips_adjust_insn_length): Multiply the mips_load_label_num_insns
by BASE_INSN_LENGTH rather than 4. Add the jump separately,
using 2 rather than 4 as the length of indirect MIPS16 and
microMIPS jumps. Use NOP_INSN_LENGTH rather than 4 as the
length of a NOP. Don't divide MIPS16 lengths by 2.
(mips16_split_long_branches): Assume a branch is long if the
length is greater than 4 rather than 8.
* config/mips/mips.md (length): Give MIPS16 lengths directly,
rather than multiplying them by 2. Multiply instruction counts
by BASE_INSN_LENGTH rather than 4.
(*jump_mips16, tls_get_tp_mips16_<mode>)
(*tls_get_tp_mips16_call_<mode>): Divide lengths by 2.
2013-05-19 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips.md (extended_mips16): Remove branch case. * config/mips/mips.md (extended_mips16): Remove branch case.
(length): Remove duplicated extended_mips16 test. (length): Remove duplicated extended_mips16 test.
......
...@@ -2007,7 +2007,7 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode) ...@@ -2007,7 +2007,7 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
values of mode MODE to or from addresses of type TYPE. Return 0 if values of mode MODE to or from addresses of type TYPE. Return 0 if
the given type of symbol is not valid in addresses. the given type of symbol is not valid in addresses.
In both cases, treat extended MIPS16 instructions as two instructions. */ In both cases, instruction counts are based off BASE_INSN_LENGTH. */
static int static int
mips_symbol_insns (enum mips_symbol_type type, enum machine_mode mode) mips_symbol_insns (enum mips_symbol_type type, enum machine_mode mode)
...@@ -2334,12 +2334,11 @@ mips16_unextended_reference_p (enum machine_mode mode, rtx base, ...@@ -2334,12 +2334,11 @@ mips16_unextended_reference_p (enum machine_mode mode, rtx base,
} }
/* Return the number of instructions needed to load or store a value /* Return the number of instructions needed to load or store a value
of mode MODE at address X. Return 0 if X isn't valid for MODE. of mode MODE at address X, assuming that BASE_INSN_LENGTH is the
length of one instruction. Return 0 if X isn't valid for MODE.
Assume that multiword moves may need to be split into word moves Assume that multiword moves may need to be split into word moves
if MIGHT_SPLIT_P, otherwise assume that a single load or store is if MIGHT_SPLIT_P, otherwise assume that a single load or store is
enough. enough. */
For MIPS16 code, count extended instructions as two instructions. */
int int
mips_address_insns (rtx x, enum machine_mode mode, bool might_split_p) mips_address_insns (rtx x, enum machine_mode mode, bool might_split_p)
...@@ -2441,7 +2440,8 @@ umips_12bit_offset_address_p (rtx x, enum machine_mode mode) ...@@ -2441,7 +2440,8 @@ umips_12bit_offset_address_p (rtx x, enum machine_mode mode)
&& UMIPS_12BIT_OFFSET_P (INTVAL (addr.offset))); && UMIPS_12BIT_OFFSET_P (INTVAL (addr.offset)));
} }
/* Return the number of instructions needed to load constant X. /* Return the number of instructions needed to load constant X,
assuming that BASE_INSN_LENGTH is the length of one instruction.
Return 0 if X isn't a valid constant. */ Return 0 if X isn't a valid constant. */
int int
...@@ -2524,7 +2524,8 @@ mips_const_insns (rtx x) ...@@ -2524,7 +2524,8 @@ mips_const_insns (rtx x)
/* X is a doubleword constant that can be handled by splitting it into /* X is a doubleword constant that can be handled by splitting it into
two words and loading each word separately. Return the number of two words and loading each word separately. Return the number of
instructions required to do this. */ instructions required to do this, assuming that BASE_INSN_LENGTH
is the length of one instruction. */
int int
mips_split_const_insns (rtx x) mips_split_const_insns (rtx x)
...@@ -2538,8 +2539,8 @@ mips_split_const_insns (rtx x) ...@@ -2538,8 +2539,8 @@ mips_split_const_insns (rtx x)
} }
/* Return the number of instructions needed to implement INSN, /* Return the number of instructions needed to implement INSN,
given that it loads from or stores to MEM. Count extended given that it loads from or stores to MEM. Assume that
MIPS16 instructions as two instructions. */ BASE_INSN_LENGTH is the length of one instruction. */
int int
mips_load_store_insns (rtx mem, rtx insn) mips_load_store_insns (rtx mem, rtx insn)
...@@ -2563,7 +2564,8 @@ mips_load_store_insns (rtx mem, rtx insn) ...@@ -2563,7 +2564,8 @@ mips_load_store_insns (rtx mem, rtx insn)
return mips_address_insns (XEXP (mem, 0), mode, might_split_p); return mips_address_insns (XEXP (mem, 0), mode, might_split_p);
} }
/* Return the number of instructions needed for an integer division. */ /* Return the number of instructions needed for an integer division,
assuming that BASE_INSN_LENGTH is the length of one instruction. */
int int
mips_idiv_insns (void) mips_idiv_insns (void)
...@@ -12273,16 +12275,18 @@ mips_adjust_insn_length (rtx insn, int length) ...@@ -12273,16 +12275,18 @@ mips_adjust_insn_length (rtx insn, int length)
is a conditional branch. */ is a conditional branch. */
length = simplejump_p (insn) ? 0 : 8; length = simplejump_p (insn) ? 0 : 8;
/* Load the label into $AT and jump to it. Ignore the delay /* Add the size of a load into $AT. */
slot of the jump. */ length += BASE_INSN_LENGTH * mips_load_label_num_insns ();
length += 4 * mips_load_label_num_insns() + 4;
/* Add the length of an indirect jump, ignoring the delay slot. */
length += TARGET_COMPRESSION ? 2 : 4;
} }
/* A unconditional jump has an unfilled delay slot if it is not part /* A unconditional jump has an unfilled delay slot if it is not part
of a sequence. A conditional jump normally has a delay slot, but of a sequence. A conditional jump normally has a delay slot, but
does not on MIPS16. */ does not on MIPS16. */
if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn))) if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn)))
length += 4; length += TARGET_MIPS16 ? 2 : 4;
/* See how many nops might be needed to avoid hardware hazards. */ /* See how many nops might be needed to avoid hardware hazards. */
if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0) if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0)
...@@ -12292,20 +12296,14 @@ mips_adjust_insn_length (rtx insn, int length) ...@@ -12292,20 +12296,14 @@ mips_adjust_insn_length (rtx insn, int length)
break; break;
case HAZARD_DELAY: case HAZARD_DELAY:
length += 4; length += NOP_INSN_LENGTH;
break; break;
case HAZARD_HILO: case HAZARD_HILO:
length += 8; length += NOP_INSN_LENGTH * 2;
break; break;
} }
/* In order to make it easier to share MIPS16 and non-MIPS16 patterns,
the .md file length attributes are 4-based for both modes.
Adjust the MIPS16 ones here. */
if (TARGET_MIPS16)
length /= 2;
return length; return length;
} }
...@@ -16201,7 +16199,7 @@ mips16_split_long_branches (void) ...@@ -16201,7 +16199,7 @@ mips16_split_long_branches (void)
something_changed = false; something_changed = false;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (JUMP_P (insn) if (JUMP_P (insn)
&& get_attr_length (insn) > 8 && get_attr_length (insn) > 4
&& (any_condjump_p (insn) || any_uncondjump_p (insn))) && (any_condjump_p (insn) || any_uncondjump_p (insn)))
{ {
rtx old_label, new_label, temp, saved_temp; rtx old_label, new_label, temp, saved_temp;
......
...@@ -2439,6 +2439,14 @@ typedef struct mips_args { ...@@ -2439,6 +2439,14 @@ typedef struct mips_args {
#define BRANCH_COST(speed_p, predictable_p) mips_branch_cost #define BRANCH_COST(speed_p, predictable_p) mips_branch_cost
#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 #define LOGICAL_OP_NON_SHORT_CIRCUIT 0
/* The MIPS port has several functions that return an instruction count.
Multiplying the count by this value gives the number of bytes that
the instructions occupy. */
#define BASE_INSN_LENGTH (TARGET_MIPS16 ? 2 : 4)
/* The length of a NOP in bytes. */
#define NOP_INSN_LENGTH (TARGET_COMPRESSION ? 2 : 4)
/* If defined, modifies the length assigned to instruction INSN as a /* If defined, modifies the length assigned to instruction INSN as a
function of the context in which it is used. LENGTH is an lvalue function of the context in which it is used. LENGTH is an lvalue
that contains the initially computed length of the insn and should that contains the initially computed length of the insn and should
......
...@@ -425,7 +425,7 @@ ...@@ -425,7 +425,7 @@
(define_attr "length" "" (define_attr "length" ""
(cond [(and (eq_attr "extended_mips16" "yes") (cond [(and (eq_attr "extended_mips16" "yes")
(match_test "TARGET_MIPS16")) (match_test "TARGET_MIPS16"))
(const_int 8) (const_int 4)
(and (eq_attr "compression" "micromips,all") (and (eq_attr "compression" "micromips,all")
(eq_attr "dword_mode" "no") (eq_attr "dword_mode" "no")
...@@ -567,68 +567,69 @@ ...@@ -567,68 +567,69 @@
;; move $2,$1 2 bytes ;; move $2,$1 2 bytes
;; foo: ;; foo:
;; (20 bytes in the worst case) ;; (20 bytes in the worst case)
;;
;; Note that the conditions test adjusted lengths, whereas the
;; result is an unadjusted length, and is thus twice the true value.
(and (eq_attr "type" "branch") (and (eq_attr "type" "branch")
(match_test "TARGET_MIPS16")) (match_test "TARGET_MIPS16"))
(cond [(and (le (minus (match_dup 0) (pc)) (const_int 254)) (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
(le (minus (pc) (match_dup 0)) (const_int 254))) (le (minus (pc) (match_dup 0)) (const_int 254)))
(const_int 4) (const_int 2)
(and (le (minus (match_dup 0) (pc)) (const_int 65534)) (and (le (minus (match_dup 0) (pc)) (const_int 65534))
(le (minus (pc) (match_dup 0)) (const_int 65532))) (le (minus (pc) (match_dup 0)) (const_int 65532)))
(const_int 8) (const_int 4)
(and (match_test "TARGET_ABICALLS") (and (match_test "TARGET_ABICALLS")
(not (match_test "TARGET_ABSOLUTE_ABICALLS"))) (not (match_test "TARGET_ABSOLUTE_ABICALLS")))
(const_int 40) (const_int 20)
(match_test "Pmode == SImode") (match_test "Pmode == SImode")
(const_int 32) (const_int 16)
] (const_int 48)) ] (const_int 24))
;; "Ghost" instructions occupy no space. ;; "Ghost" instructions occupy no space.
(eq_attr "type" "ghost") (eq_attr "type" "ghost")
(const_int 0) (const_int 0)
;; GOT loads are extended MIPS16 instructions and 4-byte
;; microMIPS instructions.
(eq_attr "got" "load") (eq_attr "got" "load")
(if_then_else (match_test "TARGET_MIPS16") (const_int 4)
(const_int 8)
(const_int 4)) ;; A GOT load followed by an add of $gp.
(eq_attr "got" "xgot_high") (eq_attr "got" "xgot_high")
(const_int 8) (const_int 8)
;; In general, constant-pool loads are extended instructions. ;; In general, constant-pool loads are extended instructions.
(eq_attr "move_type" "loadpool") (eq_attr "move_type" "loadpool")
(const_int 8) (const_int 4)
;; SHIFT_SHIFTs are decomposed into two separate instructions. ;; SHIFT_SHIFTs are decomposed into two separate instructions.
;; They are extended instructions on MIPS16 targets. ;; They are extended instructions on MIPS16 targets.
(eq_attr "move_type" "shift_shift") (eq_attr "move_type" "shift_shift")
(if_then_else (match_test "TARGET_MIPS16") (const_int 8)
(const_int 16)
(const_int 8))
;; Check for doubleword moves that are decomposed into two ;; Check for doubleword moves that are decomposed into two
;; instructions. ;; instructions. The individual instructions are unextended
;; MIPS16 ones or 2-byte microMIPS ones.
(and (eq_attr "move_type" "mtc,mfc,mtlo,mflo,move") (and (eq_attr "move_type" "mtc,mfc,mtlo,mflo,move")
(eq_attr "dword_mode" "yes")) (eq_attr "dword_mode" "yes"))
(const_int 8) (if_then_else (match_test "TARGET_COMPRESSION")
(const_int 4)
(const_int 8))
;; Doubleword CONST{,N} moves are split into two word ;; Doubleword CONST{,N} moves are split into two word
;; CONST{,N} moves. ;; CONST{,N} moves.
(and (eq_attr "move_type" "const,constN") (and (eq_attr "move_type" "const,constN")
(eq_attr "dword_mode" "yes")) (eq_attr "dword_mode" "yes"))
(symbol_ref "mips_split_const_insns (operands[1]) * 4") (symbol_ref "mips_split_const_insns (operands[1]) * BASE_INSN_LENGTH")
;; Otherwise, constants, loads and stores are handled by external ;; Otherwise, constants, loads and stores are handled by external
;; routines. ;; routines.
(eq_attr "move_type" "const,constN") (eq_attr "move_type" "const,constN")
(symbol_ref "mips_const_insns (operands[1]) * 4") (symbol_ref "mips_const_insns (operands[1]) * BASE_INSN_LENGTH")
(eq_attr "move_type" "load,fpload") (eq_attr "move_type" "load,fpload")
(symbol_ref "mips_load_store_insns (operands[1], insn) * 4") (symbol_ref "mips_load_store_insns (operands[1], insn)
* BASE_INSN_LENGTH")
(eq_attr "move_type" "store,fpstore") (eq_attr "move_type" "store,fpstore")
(cond [(not (match_test "TARGET_FIX_24K")) (symbol_ref "mips_load_store_insns (operands[0], insn)
(symbol_ref "mips_load_store_insns (operands[0], insn) * 4")] * BASE_INSN_LENGTH
(symbol_ref "mips_load_store_insns (operands[0], insn) * 4 + 4")) + (TARGET_FIX_24K ? NOP_INSN_LENGTH : 0)")
;; In the worst case, a call macro will take 8 instructions: ;; In the worst case, a call macro will take 8 instructions:
;; ;;
...@@ -659,10 +660,14 @@ ...@@ -659,10 +660,14 @@
(const_int 8) (const_int 8)
(eq_attr "type" "idiv,idiv3") (eq_attr "type" "idiv,idiv3")
(symbol_ref "mips_idiv_insns () * 4") (symbol_ref "mips_idiv_insns () * BASE_INSN_LENGTH")
(not (eq_attr "sync_mem" "none")) (not (eq_attr "sync_mem" "none"))
(symbol_ref "mips_sync_loop_insns (insn, operands) * 4") (symbol_ref "mips_sync_loop_insns (insn, operands)
* BASE_INSN_LENGTH")
(match_test "TARGET_MIPS16")
(const_int 2)
] (const_int 4))) ] (const_int 4)))
;; Attribute describing the processor. ;; Attribute describing the processor.
...@@ -5373,7 +5378,7 @@ ...@@ -5373,7 +5378,7 @@
"" ""
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "16")]) (set_attr "length" "8")])
(define_insn "rotr<mode>3" (define_insn "rotr<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=d") [(set (match_operand:GPR 0 "register_operand" "=d")
...@@ -5845,16 +5850,16 @@ ...@@ -5845,16 +5850,16 @@
;; is one instruction shorter than for conditional branches. ;; is one instruction shorter than for conditional branches.
(cond [(and (le (minus (match_dup 0) (pc)) (const_int 2046)) (cond [(and (le (minus (match_dup 0) (pc)) (const_int 2046))
(le (minus (pc) (match_dup 0)) (const_int 2046))) (le (minus (pc) (match_dup 0)) (const_int 2046)))
(const_int 4) (const_int 2)
(and (le (minus (match_dup 0) (pc)) (const_int 65534)) (and (le (minus (match_dup 0) (pc)) (const_int 65534))
(le (minus (pc) (match_dup 0)) (const_int 65532))) (le (minus (pc) (match_dup 0)) (const_int 65532)))
(const_int 8) (const_int 4)
(and (match_test "TARGET_ABICALLS") (and (match_test "TARGET_ABICALLS")
(not (match_test "TARGET_ABSOLUTE_ABICALLS"))) (not (match_test "TARGET_ABSOLUTE_ABICALLS")))
(const_int 36) (const_int 18)
(match_test "Pmode == SImode") (match_test "Pmode == SImode")
(const_int 28) (const_int 14)
] (const_int 44)))]) ] (const_int 22)))])
(define_expand "indirect_jump" (define_expand "indirect_jump"
[(set (pc) (match_operand 0 "register_operand"))] [(set (pc) (match_operand 0 "register_operand"))]
...@@ -6947,7 +6952,7 @@ ...@@ -6947,7 +6952,7 @@
(set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))] (set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))]
"" ""
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "16") (set_attr "length" "8")
(set_attr "mode" "<MODE>")]) (set_attr "mode" "<MODE>")])
(define_insn "*tls_get_tp_mips16_call_<mode>" (define_insn "*tls_get_tp_mips16_call_<mode>"
...@@ -6959,7 +6964,7 @@ ...@@ -6959,7 +6964,7 @@
"HAVE_AS_TLS && TARGET_MIPS16" "HAVE_AS_TLS && TARGET_MIPS16"
{ return MIPS_CALL ("jal", operands, 0, -1); } { return MIPS_CALL ("jal", operands, 0, -1); }
[(set_attr "type" "call") [(set_attr "type" "call")
(set_attr "length" "12") (set_attr "length" "6")
(set_attr "mode" "<MODE>")]) (set_attr "mode" "<MODE>")])
;; Named pattern for expanding thread pointer reference. ;; Named pattern for expanding thread pointer reference.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment