From: Richard Sandiford Date: Sun, 19 May 2013 10:16:29 +0000 (+0000) Subject: mips.h (BASE_INSN_LENGTH, [...]): New macros. X-Git-Tag: releases/gcc-4.9.0~5810 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da734fa108e7f5c41e0689c72f19bb01f974e7ae;p=thirdparty%2Fgcc.git 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_) (*tls_get_tp_mips16_call_): Divide lengths by 2. From-SVN: r199080 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index adfb5b29c4cb..310c14d97fd9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2013-05-19 Richard Sandiford + + * 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_) + (*tls_get_tp_mips16_call_): Divide lengths by 2. + 2013-05-19 Richard Sandiford * config/mips/mips.md (extended_mips16): Remove branch case. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 066e7a1b1386..1f2774638fc2 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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 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 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, } /* 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 if MIGHT_SPLIT_P, otherwise assume that a single load or store is - enough. - - For MIPS16 code, count extended instructions as two instructions. */ + enough. */ int 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) && 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. */ int @@ -2524,7 +2524,8 @@ mips_const_insns (rtx x) /* X is a doubleword constant that can be handled by splitting it into 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 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, - given that it loads from or stores to MEM. Count extended - MIPS16 instructions as two instructions. */ + given that it loads from or stores to MEM. Assume that + BASE_INSN_LENGTH is the length of one instruction. */ int 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 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 mips_idiv_insns (void) @@ -12273,16 +12275,18 @@ mips_adjust_insn_length (rtx insn, int length) is a conditional branch. */ length = simplejump_p (insn) ? 0 : 8; - /* Load the label into $AT and jump to it. Ignore the delay - slot of the jump. */ - length += 4 * mips_load_label_num_insns() + 4; + /* Add the size of a load into $AT. */ + length += BASE_INSN_LENGTH * mips_load_label_num_insns (); + + /* 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 of a sequence. A conditional jump normally has a delay slot, but does not on MIPS16. */ 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. */ if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0) @@ -12292,20 +12296,14 @@ mips_adjust_insn_length (rtx insn, int length) break; case HAZARD_DELAY: - length += 4; + length += NOP_INSN_LENGTH; break; case HAZARD_HILO: - length += 8; + length += NOP_INSN_LENGTH * 2; 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; } @@ -16201,7 +16199,7 @@ mips16_split_long_branches (void) something_changed = false; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (JUMP_P (insn) - && get_attr_length (insn) > 8 + && get_attr_length (insn) > 4 && (any_condjump_p (insn) || any_uncondjump_p (insn))) { rtx old_label, new_label, temp, saved_temp; diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index dd694f30e5c6..50a030f7f2c9 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2439,6 +2439,14 @@ typedef struct mips_args { #define BRANCH_COST(speed_p, predictable_p) mips_branch_cost #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 function of the context in which it is used. LENGTH is an lvalue that contains the initially computed length of the insn and should diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 8d38a7749206..7284e5f33848 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -425,7 +425,7 @@ (define_attr "length" "" (cond [(and (eq_attr "extended_mips16" "yes") (match_test "TARGET_MIPS16")) - (const_int 8) + (const_int 4) (and (eq_attr "compression" "micromips,all") (eq_attr "dword_mode" "no") @@ -567,68 +567,69 @@ ;; move $2,$1 2 bytes ;; foo: ;; (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") (match_test "TARGET_MIPS16")) (cond [(and (le (minus (match_dup 0) (pc)) (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)) (le (minus (pc) (match_dup 0)) (const_int 65532))) - (const_int 8) + (const_int 4) (and (match_test "TARGET_ABICALLS") (not (match_test "TARGET_ABSOLUTE_ABICALLS"))) - (const_int 40) + (const_int 20) (match_test "Pmode == SImode") - (const_int 32) - ] (const_int 48)) + (const_int 16) + ] (const_int 24)) ;; "Ghost" instructions occupy no space. (eq_attr "type" "ghost") (const_int 0) + ;; GOT loads are extended MIPS16 instructions and 4-byte + ;; microMIPS instructions. (eq_attr "got" "load") - (if_then_else (match_test "TARGET_MIPS16") - (const_int 8) - (const_int 4)) + (const_int 4) + + ;; A GOT load followed by an add of $gp. (eq_attr "got" "xgot_high") (const_int 8) ;; In general, constant-pool loads are extended instructions. (eq_attr "move_type" "loadpool") - (const_int 8) + (const_int 4) ;; SHIFT_SHIFTs are decomposed into two separate instructions. ;; They are extended instructions on MIPS16 targets. (eq_attr "move_type" "shift_shift") - (if_then_else (match_test "TARGET_MIPS16") - (const_int 16) - (const_int 8)) + (const_int 8) ;; 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") (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 ;; CONST{,N} moves. (and (eq_attr "move_type" "const,constN") (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 ;; routines. (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") - (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") - (cond [(not (match_test "TARGET_FIX_24K")) - (symbol_ref "mips_load_store_insns (operands[0], insn) * 4")] - (symbol_ref "mips_load_store_insns (operands[0], insn) * 4 + 4")) + (symbol_ref "mips_load_store_insns (operands[0], insn) + * BASE_INSN_LENGTH + + (TARGET_FIX_24K ? NOP_INSN_LENGTH : 0)") ;; In the worst case, a call macro will take 8 instructions: ;; @@ -659,10 +660,14 @@ (const_int 8) (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")) - (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))) ;; Attribute describing the processor. @@ -5373,7 +5378,7 @@ "" [(set_attr "type" "load") (set_attr "mode" "SI") - (set_attr "length" "16")]) + (set_attr "length" "8")]) (define_insn "rotr3" [(set (match_operand:GPR 0 "register_operand" "=d") @@ -5845,16 +5850,16 @@ ;; is one instruction shorter than for conditional branches. (cond [(and (le (minus (match_dup 0) (pc)) (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)) (le (minus (pc) (match_dup 0)) (const_int 65532))) - (const_int 8) + (const_int 4) (and (match_test "TARGET_ABICALLS") (not (match_test "TARGET_ABSOLUTE_ABICALLS"))) - (const_int 36) + (const_int 18) (match_test "Pmode == SImode") - (const_int 28) - ] (const_int 44)))]) + (const_int 14) + ] (const_int 22)))]) (define_expand "indirect_jump" [(set (pc) (match_operand 0 "register_operand"))] @@ -6947,7 +6952,7 @@ (set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))] "" [(set_attr "type" "multi") - (set_attr "length" "16") + (set_attr "length" "8") (set_attr "mode" "")]) (define_insn "*tls_get_tp_mips16_call_" @@ -6959,7 +6964,7 @@ "HAVE_AS_TLS && TARGET_MIPS16" { return MIPS_CALL ("jal", operands, 0, -1); } [(set_attr "type" "call") - (set_attr "length" "12") + (set_attr "length" "6") (set_attr "mode" "")]) ;; Named pattern for expanding thread pointer reference.