mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			re PR target/51931 (No support for MIPS16 long branches)
gcc/ PR target/51931 * config/mips/mips-protos.h (mips_strip_unspec_address): Declare. * config/mips/mips.c (mips_strip_unspec_address): Make extern. (mips16_rewrite_pool_constant): Make a copy of the pool constant before adding to a PC-relative table. (mips16_lay_out_constants): Add a SPLIT_P parameter. (mips16_load_branch_target, mips16_split_long_branches): New functions. (mips_reorg): Update call to mips16_lay_out_constants. Call mips16_split_long_branches. * config/mips/predicates.md (pc_or_label_operand): Delete. * config/mips/mips.md (length): Add a calculation for MIPS16 branches. Move the extended_mips16 handling further down. (*branch_equality<mode>_mips16): Replace use pc_or_label_operand with explicit label_ref and pc. Follow the usual operand numbering. (*branch_equality<mode>_mips16_inverted): New pattern. (*jump_mips16): Add length attribute. (indirect_jump_and_restore_<mode>): New pattern. (consttable_int): Call mips_strip_unspec_address on the operand. gcc/testsuite/ PR target/51931 * gcc.c-torture/compile/20001226-1.c: Remove nomips16 attribute. * g++.dg/opt/longbranch1.C: Likewise. From-SVN: r190104
This commit is contained in:
		
							parent
							
								
									b5b071a568
								
							
						
					
					
						commit
						36be1dee1d
					
				|  | @ -1,3 +1,24 @@ | ||||||
|  | 2012-08-02  Richard Sandiford  <rdsandiford@googlemail.com> | ||||||
|  | 
 | ||||||
|  | 	PR target/51931 | ||||||
|  | 	* config/mips/mips-protos.h (mips_strip_unspec_address): Declare. | ||||||
|  | 	* config/mips/mips.c (mips_strip_unspec_address): Make extern. | ||||||
|  | 	(mips16_rewrite_pool_constant): Make a copy of the pool constant | ||||||
|  | 	before adding to a PC-relative table. | ||||||
|  | 	(mips16_lay_out_constants): Add a SPLIT_P parameter. | ||||||
|  | 	(mips16_load_branch_target, mips16_split_long_branches): New functions. | ||||||
|  | 	(mips_reorg): Update call to mips16_lay_out_constants. | ||||||
|  | 	Call mips16_split_long_branches. | ||||||
|  | 	* config/mips/predicates.md (pc_or_label_operand): Delete. | ||||||
|  | 	* config/mips/mips.md (length): Add a calculation for MIPS16 branches. | ||||||
|  | 	Move the extended_mips16 handling further down. | ||||||
|  | 	(*branch_equality<mode>_mips16): Replace use pc_or_label_operand | ||||||
|  | 	with explicit label_ref and pc.  Follow the usual operand numbering. | ||||||
|  | 	(*branch_equality<mode>_mips16_inverted): New pattern. | ||||||
|  | 	(*jump_mips16): Add length attribute. | ||||||
|  | 	(indirect_jump_and_restore_<mode>): New pattern. | ||||||
|  | 	(consttable_int): Call mips_strip_unspec_address on the operand. | ||||||
|  | 
 | ||||||
| 2012-08-02  Richard Sandiford  <rdsandiford@googlemail.com> | 2012-08-02  Richard Sandiford  <rdsandiford@googlemail.com> | ||||||
| 
 | 
 | ||||||
| 	* recog.c (split_insn): Copy the original SET_SRC before using | 	* recog.c (split_insn): Copy the original SET_SRC before using | ||||||
|  |  | ||||||
|  | @ -190,6 +190,7 @@ extern rtx mips_pic_base_register (rtx); | ||||||
| extern rtx mips_got_load (rtx, rtx, enum mips_symbol_type); | extern rtx mips_got_load (rtx, rtx, enum mips_symbol_type); | ||||||
| extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *); | extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *); | ||||||
| extern rtx mips_unspec_address (rtx, enum mips_symbol_type); | extern rtx mips_unspec_address (rtx, enum mips_symbol_type); | ||||||
|  | extern rtx mips_strip_unspec_address (rtx); | ||||||
| extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT); | extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT); | ||||||
| extern bool mips_legitimize_move (enum machine_mode, rtx, rtx); | extern bool mips_legitimize_move (enum machine_mode, rtx, rtx); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2563,7 +2563,7 @@ mips_unspec_address (rtx address, enum mips_symbol_type symbol_type) | ||||||
| /* If OP is an UNSPEC address, return the address to which it refers,
 | /* If OP is an UNSPEC address, return the address to which it refers,
 | ||||||
|    otherwise return OP itself.  */ |    otherwise return OP itself.  */ | ||||||
| 
 | 
 | ||||||
| static rtx | rtx | ||||||
| mips_strip_unspec_address (rtx op) | mips_strip_unspec_address (rtx op) | ||||||
| { | { | ||||||
|   rtx base, offset; |   rtx base, offset; | ||||||
|  | @ -14070,7 +14070,7 @@ mips16_rewrite_pool_constant (struct mips16_constant_pool *pool, rtx *x) | ||||||
|   split_const (*x, &base, &offset); |   split_const (*x, &base, &offset); | ||||||
|   if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base)) |   if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base)) | ||||||
|     { |     { | ||||||
|       label = mips16_add_constant (pool, get_pool_constant (base), |       label = mips16_add_constant (pool, copy_rtx (get_pool_constant (base)), | ||||||
| 				   get_pool_mode (base)); | 				   get_pool_mode (base)); | ||||||
|       base = gen_rtx_LABEL_REF (Pmode, label); |       base = gen_rtx_LABEL_REF (Pmode, label); | ||||||
|       *x = mips_unspec_address_offset (base, offset, SYMBOL_PC_RELATIVE); |       *x = mips_unspec_address_offset (base, offset, SYMBOL_PC_RELATIVE); | ||||||
|  | @ -14126,10 +14126,11 @@ mips_cfg_in_reorg (void) | ||||||
| 	  || TARGET_RELAX_PIC_CALLS); | 	  || TARGET_RELAX_PIC_CALLS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Build MIPS16 constant pools.  */ | /* Build MIPS16 constant pools.  Split the instructions if SPLIT_P,
 | ||||||
|  |    otherwise assume that they are already split.  */ | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mips16_lay_out_constants (void) | mips16_lay_out_constants (bool split_p) | ||||||
| { | { | ||||||
|   struct mips16_constant_pool pool; |   struct mips16_constant_pool pool; | ||||||
|   struct mips16_rewrite_pool_refs_info info; |   struct mips16_rewrite_pool_refs_info info; | ||||||
|  | @ -14138,10 +14139,13 @@ mips16_lay_out_constants (void) | ||||||
|   if (!TARGET_MIPS16_PCREL_LOADS) |   if (!TARGET_MIPS16_PCREL_LOADS) | ||||||
|     return; |     return; | ||||||
| 
 | 
 | ||||||
|   if (mips_cfg_in_reorg ()) |   if (split_p) | ||||||
|     split_all_insns (); |     { | ||||||
|   else |       if (mips_cfg_in_reorg ()) | ||||||
|     split_all_insns_noflow (); | 	split_all_insns (); | ||||||
|  |       else | ||||||
|  | 	split_all_insns_noflow (); | ||||||
|  |     } | ||||||
|   barrier = 0; |   barrier = 0; | ||||||
|   memset (&pool, 0, sizeof (pool)); |   memset (&pool, 0, sizeof (pool)); | ||||||
|   for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) |   for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | ||||||
|  | @ -15490,6 +15494,110 @@ mips_df_reorg (void) | ||||||
|   df_finish_pass (false); |   df_finish_pass (false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Emit code to load LABEL_REF SRC into MIPS16 register DEST.  This is
 | ||||||
|  |    called very late in mips_reorg, but the caller is required to run | ||||||
|  |    mips16_lay_out_constants on the result.  */ | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | mips16_load_branch_target (rtx dest, rtx src) | ||||||
|  | { | ||||||
|  |   if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) | ||||||
|  |     { | ||||||
|  |       rtx page, low; | ||||||
|  | 
 | ||||||
|  |       if (mips_cfun_has_cprestore_slot_p ()) | ||||||
|  | 	mips_emit_move (dest, mips_cprestore_slot (dest, true)); | ||||||
|  |       else | ||||||
|  | 	mips_emit_move (dest, pic_offset_table_rtx); | ||||||
|  |       page = mips_unspec_address (src, SYMBOL_GOTOFF_PAGE); | ||||||
|  |       low = mips_unspec_address (src, SYMBOL_GOT_PAGE_OFST); | ||||||
|  |       emit_insn (gen_rtx_SET (VOIDmode, dest, | ||||||
|  | 			      PMODE_INSN (gen_unspec_got, (dest, page)))); | ||||||
|  |       emit_insn (gen_rtx_SET (VOIDmode, dest, | ||||||
|  | 			      gen_rtx_LO_SUM (Pmode, dest, low))); | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       src = mips_unspec_address (src, SYMBOL_ABSOLUTE); | ||||||
|  |       mips_emit_move (dest, src); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* If we're compiling a MIPS16 function, look for and split any long branches.
 | ||||||
|  |    This must be called after all other instruction modifications in | ||||||
|  |    mips_reorg.  */ | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | mips16_split_long_branches (void) | ||||||
|  | { | ||||||
|  |   bool something_changed; | ||||||
|  | 
 | ||||||
|  |   if (!TARGET_MIPS16) | ||||||
|  |     return; | ||||||
|  | 
 | ||||||
|  |   /* Loop until the alignments for all targets are sufficient.  */ | ||||||
|  |   do | ||||||
|  |     { | ||||||
|  |       rtx insn; | ||||||
|  | 
 | ||||||
|  |       shorten_branches (get_insns ()); | ||||||
|  |       something_changed = false; | ||||||
|  |       for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | ||||||
|  | 	if (JUMP_P (insn) | ||||||
|  | 	    && USEFUL_INSN_P (insn) | ||||||
|  | 	    && get_attr_length (insn) > 8) | ||||||
|  | 	  { | ||||||
|  | 	    rtx old_label, new_label, temp, saved_temp; | ||||||
|  | 	    rtx target, jump, jump_sequence; | ||||||
|  | 
 | ||||||
|  | 	    start_sequence (); | ||||||
|  | 
 | ||||||
|  | 	    /* Free up a MIPS16 register by saving it in $1.  */ | ||||||
|  | 	    saved_temp = gen_rtx_REG (Pmode, AT_REGNUM); | ||||||
|  | 	    temp = gen_rtx_REG (Pmode, GP_REG_FIRST + 2); | ||||||
|  | 	    emit_move_insn (saved_temp, temp); | ||||||
|  | 
 | ||||||
|  | 	    /* Load the branch target into TEMP.  */ | ||||||
|  | 	    old_label = JUMP_LABEL (insn); | ||||||
|  | 	    target = gen_rtx_LABEL_REF (Pmode, old_label); | ||||||
|  | 	    mips16_load_branch_target (temp, target); | ||||||
|  | 
 | ||||||
|  | 	    /* Jump to the target and restore the register's
 | ||||||
|  | 	       original value.  */ | ||||||
|  | 	    jump = emit_jump_insn (PMODE_INSN (gen_indirect_jump_and_restore, | ||||||
|  | 					       (temp, temp, saved_temp))); | ||||||
|  | 	    JUMP_LABEL (jump) = old_label; | ||||||
|  | 	    LABEL_NUSES (old_label)++; | ||||||
|  | 
 | ||||||
|  | 	    /* Rewrite any symbolic references that are supposed to use
 | ||||||
|  | 	       a PC-relative constant pool.  */ | ||||||
|  | 	    mips16_lay_out_constants (false); | ||||||
|  | 
 | ||||||
|  | 	    if (simplejump_p (insn)) | ||||||
|  | 	      /* We're going to replace INSN with a longer form.  */ | ||||||
|  | 	      new_label = NULL_RTX; | ||||||
|  | 	    else | ||||||
|  | 	      { | ||||||
|  | 		/* Create a branch-around label for the original
 | ||||||
|  | 		   instruction.  */ | ||||||
|  | 		new_label = gen_label_rtx (); | ||||||
|  | 		emit_label (new_label); | ||||||
|  | 	      } | ||||||
|  | 
 | ||||||
|  | 	    jump_sequence = get_insns (); | ||||||
|  | 	    end_sequence (); | ||||||
|  | 
 | ||||||
|  | 	    emit_insn_after (jump_sequence, insn); | ||||||
|  | 	    if (new_label) | ||||||
|  | 	      invert_jump (insn, new_label, false); | ||||||
|  | 	    else | ||||||
|  | 	      delete_insn (insn); | ||||||
|  | 	    something_changed = true; | ||||||
|  | 	  } | ||||||
|  |     } | ||||||
|  |   while (something_changed); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Implement TARGET_MACHINE_DEPENDENT_REORG.  */ | /* Implement TARGET_MACHINE_DEPENDENT_REORG.  */ | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -15500,7 +15608,7 @@ mips_reorg (void) | ||||||
|      to date if the CFG is available.  */ |      to date if the CFG is available.  */ | ||||||
|   if (mips_cfg_in_reorg ()) |   if (mips_cfg_in_reorg ()) | ||||||
|     compute_bb_for_insn (); |     compute_bb_for_insn (); | ||||||
|   mips16_lay_out_constants (); |   mips16_lay_out_constants (true); | ||||||
|   if (mips_cfg_in_reorg ()) |   if (mips_cfg_in_reorg ()) | ||||||
|     { |     { | ||||||
|       mips_df_reorg (); |       mips_df_reorg (); | ||||||
|  | @ -15519,6 +15627,7 @@ mips_reorg (void) | ||||||
|     /* The expansion could invalidate some of the VR4130 alignment
 |     /* The expansion could invalidate some of the VR4130 alignment
 | ||||||
|        optimizations, but this should be an extremely rare case anyhow.  */ |        optimizations, but this should be an extremely rare case anyhow.  */ | ||||||
|     mips_reorg_process_insns (); |     mips_reorg_process_insns (); | ||||||
|  |   mips16_split_long_branches (); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
 | /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
 | ||||||
|  | @ -15639,7 +15748,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, | ||||||
|   insn = get_insns (); |   insn = get_insns (); | ||||||
|   insn_locators_alloc (); |   insn_locators_alloc (); | ||||||
|   split_all_insns_noflow (); |   split_all_insns_noflow (); | ||||||
|   mips16_lay_out_constants (); |   mips16_lay_out_constants (true); | ||||||
|   shorten_branches (insn); |   shorten_branches (insn); | ||||||
|   final_start_function (insn, file, 1); |   final_start_function (insn, file, 1); | ||||||
|   final (insn, file, 1); |   final (insn, file, 1); | ||||||
|  |  | ||||||
|  | @ -402,11 +402,7 @@ | ||||||
| 
 | 
 | ||||||
| ;; Length of instruction in bytes. | ;; Length of instruction in bytes. | ||||||
| (define_attr "length" "" | (define_attr "length" "" | ||||||
|    (cond [(and (eq_attr "extended_mips16" "yes") |    (cond [;; Direct branch instructions have a range of [-0x20000,0x1fffc], | ||||||
| 	       (match_test "TARGET_MIPS16")) |  | ||||||
| 	  (const_int 8) |  | ||||||
| 
 |  | ||||||
| 	  ;; Direct branch instructions have a range of [-0x20000,0x1fffc], |  | ||||||
| 	  ;; relative to the address of the delay slot.  If a branch is | 	  ;; relative to the address of the delay slot.  If a branch is | ||||||
| 	  ;; outside this range, we have a choice of two sequences. | 	  ;; outside this range, we have a choice of two sequences. | ||||||
| 	  ;; For PIC, an out-of-range branch like: | 	  ;; For PIC, an out-of-range branch like: | ||||||
|  | @ -431,14 +427,21 @@ | ||||||
| 	  ;; using la/jr in this case too, but we do not do so at | 	  ;; using la/jr in this case too, but we do not do so at | ||||||
| 	  ;; present. | 	  ;; present. | ||||||
| 	  ;; | 	  ;; | ||||||
| 	  ;; Note that this value does not account for the delay slot | 	  ;; The value we specify here does not account for the delay slot | ||||||
| 	  ;; instruction, whose length is added separately.  If the RTL | 	  ;; instruction, whose length is added separately.  If the RTL | ||||||
| 	  ;; pattern has no explicit delay slot, mips_adjust_insn_length | 	  ;; pattern has no explicit delay slot, mips_adjust_insn_length | ||||||
| 	  ;; will add the length of the implicit nop.  The values for | 	  ;; will add the length of the implicit nop.  The range of | ||||||
| 	  ;; forward and backward branches will be different as well. | 	  ;; [-0x20000, 0x1fffc] from the address of the delay slot | ||||||
| 	  (eq_attr "type" "branch") | 	  ;; therefore translates to a range of: | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;    [-(0x20000 - sizeof (branch)), 0x1fffc - sizeof (slot)] | ||||||
|  | 	  ;; == [-0x1fffc, 0x1fff8] | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; from the shorten_branches reference address. | ||||||
|  | 	  (and (eq_attr "type" "branch") | ||||||
|  | 	       (not (match_test "TARGET_MIPS16"))) | ||||||
| 	  (cond [(and (le (minus (match_dup 0) (pc)) (const_int 131064)) | 	  (cond [(and (le (minus (match_dup 0) (pc)) (const_int 131064)) | ||||||
| 			  (le (minus (pc) (match_dup 0)) (const_int 131068))) | 		      (le (minus (pc) (match_dup 0)) (const_int 131068))) | ||||||
| 		   (const_int 4) | 		   (const_int 4) | ||||||
| 
 | 
 | ||||||
| 		 ;; The non-PIC case: branch, first delay slot, and J. | 		 ;; The non-PIC case: branch, first delay slot, and J. | ||||||
|  | @ -453,6 +456,100 @@ | ||||||
| 		 ;; of an insn. | 		 ;; of an insn. | ||||||
| 		 (const_int MAX_PIC_BRANCH_LENGTH)) | 		 (const_int MAX_PIC_BRANCH_LENGTH)) | ||||||
| 
 | 
 | ||||||
|  | 	  ;; An unextended MIPS16 branch has a range of [-0x100, 0xfe] | ||||||
|  | 	  ;; from the address of the following instruction, which leads | ||||||
|  | 	  ;; to a range of: | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;    [-(0x100 - sizeof (branch)), 0xfe] | ||||||
|  | 	  ;; == [-0xfe, 0xfe] | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; from the shorten_branches reference address.  Extended branches | ||||||
|  | 	  ;; likewise have a range of [-0x10000, 0xfffe] from the address | ||||||
|  | 	  ;; of the following instruction, which leads to a range of: | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;    [-(0x10000 - sizeof (branch)), 0xfffe] | ||||||
|  | 	  ;; == [-0xfffc, 0xfffe] | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; from the reference address. | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; When a branch is out of range, mips_reorg splits it into a form | ||||||
|  | 	  ;; that uses in-range branches.  There are four basic sequences: | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; (1) Absolute addressing with a readable text segment | ||||||
|  | 	  ;;     (32-bit addresses): | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;	 b... foo		2 bytes | ||||||
|  | 	  ;;	 move $1,$2		2 bytes | ||||||
|  | 	  ;;     lw $2,label		2 bytes | ||||||
|  | 	  ;;	 jr $2			2 bytes | ||||||
|  | 	  ;;	 move $2,$1		2 bytes | ||||||
|  | 	  ;;	 .align 2		0 or 2 bytes | ||||||
|  | 	  ;; label: | ||||||
|  | 	  ;;	 .word target		4 bytes | ||||||
|  | 	  ;; foo: | ||||||
|  | 	  ;;				(16 bytes in the worst case) | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; (2) Absolute addressing with a readable text segment | ||||||
|  | 	  ;;     (64-bit addresses): | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;	 b... foo		2 bytes | ||||||
|  | 	  ;;	 move $1,$2		2 bytes | ||||||
|  | 	  ;;     ld $2,label		2 bytes | ||||||
|  | 	  ;;	 jr $2			2 bytes | ||||||
|  | 	  ;;	 move $2,$1		2 bytes | ||||||
|  | 	  ;;	 .align 3		0 to 6 bytes | ||||||
|  | 	  ;; label: | ||||||
|  | 	  ;;	 .dword target		8 bytes | ||||||
|  | 	  ;; foo: | ||||||
|  | 	  ;;				(24 bytes in the worst case) | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; (3) Absolute addressing without a readable text segment | ||||||
|  | 	  ;;     (which requires 32-bit addresses at present): | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;	 b... foo		2 bytes | ||||||
|  | 	  ;;	 move $1,$2		2 bytes | ||||||
|  | 	  ;;     lui $2,%hi(target)	4 bytes | ||||||
|  | 	  ;;	 sll $2,8		2 bytes | ||||||
|  | 	  ;;	 sll $2,8		2 bytes | ||||||
|  | 	  ;;     addiu $2,%lo(target)	4 bytes | ||||||
|  | 	  ;;	 jr $2			2 bytes | ||||||
|  | 	  ;;	 move $2,$1		2 bytes | ||||||
|  | 	  ;; foo: | ||||||
|  | 	  ;;				(20 bytes) | ||||||
|  | 	  ;; | ||||||
|  | 	  ;; (4) PIC addressing (which requires 32-bit addresses at present): | ||||||
|  | 	  ;; | ||||||
|  | 	  ;;	 b... foo		2 bytes | ||||||
|  | 	  ;;	 move $1,$2		2 bytes | ||||||
|  | 	  ;;     lw $2,cprestore	0, 2 or 4 bytes | ||||||
|  | 	  ;;	 lw $2,%got(target)($2)	4 bytes | ||||||
|  | 	  ;;     addiu $2,%lo(target)	4 bytes | ||||||
|  | 	  ;;	 jr $2			2 bytes | ||||||
|  | 	  ;;	 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) | ||||||
|  | 		 (and (le (minus (match_dup 0) (pc)) (const_int 65534)) | ||||||
|  | 		      (le (minus (pc) (match_dup 0)) (const_int 65532))) | ||||||
|  | 		 (const_int 8) | ||||||
|  | 		 (and (match_test "TARGET_ABICALLS") | ||||||
|  | 		      (not (match_test "TARGET_ABSOLUTE_ABICALLS"))) | ||||||
|  | 		 (const_int 40) | ||||||
|  | 		 (match_test "Pmode == SImode") | ||||||
|  | 		 (const_int 32) | ||||||
|  | 		 ] (const_int 48)) | ||||||
|  | 
 | ||||||
|  | 	  (and (eq_attr "extended_mips16" "yes") | ||||||
|  | 	       (match_test "TARGET_MIPS16")) | ||||||
|  | 	  (const_int 8) | ||||||
|  | 
 | ||||||
| 	  ;; "Ghost" instructions occupy no space. | 	  ;; "Ghost" instructions occupy no space. | ||||||
| 	  (eq_attr "type" "ghost") | 	  (eq_attr "type" "ghost") | ||||||
| 	  (const_int 0) | 	  (const_int 0) | ||||||
|  | @ -5400,28 +5497,29 @@ | ||||||
| (define_insn "*branch_equality<mode>_mips16" | (define_insn "*branch_equality<mode>_mips16" | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
| 	(if_then_else | 	(if_then_else | ||||||
| 	 (match_operator 0 "equality_operator" | 	 (match_operator 1 "equality_operator" | ||||||
| 			 [(match_operand:GPR 1 "register_operand" "d,t") | 			 [(match_operand:GPR 2 "register_operand" "d,t") | ||||||
| 			  (const_int 0)]) | 			  (const_int 0)]) | ||||||
| 	 (match_operand 2 "pc_or_label_operand" "") | 	 (label_ref (match_operand 0 "" "")) | ||||||
| 	 (match_operand 3 "pc_or_label_operand" "")))] | 	 (pc)))] | ||||||
|   "TARGET_MIPS16" |   "TARGET_MIPS16" | ||||||
| { |   "@ | ||||||
|   if (operands[2] != pc_rtx) |    b%C1z\t%2,%0 | ||||||
|     { |    bt%C1z\t%0" | ||||||
|       if (which_alternative == 0) |   [(set_attr "type" "branch")]) | ||||||
| 	return "b%C0z\t%1,%2"; | 
 | ||||||
|       else | (define_insn "*branch_equality<mode>_mips16_inverted" | ||||||
| 	return "bt%C0z\t%2"; |   [(set (pc) | ||||||
|     } | 	(if_then_else | ||||||
|   else | 	 (match_operator 1 "equality_operator" | ||||||
|     { | 			 [(match_operand:GPR 2 "register_operand" "d,t") | ||||||
|       if (which_alternative == 0) | 			  (const_int 0)]) | ||||||
| 	return "b%N0z\t%1,%3"; | 	 (pc) | ||||||
|       else | 	 (label_ref (match_operand 0 "" ""))))] | ||||||
| 	return "bt%N0z\t%3"; |   "TARGET_MIPS16" | ||||||
|     } |   "@ | ||||||
| } |    b%N1z\t%2,%0 | ||||||
|  |    bt%N1z\t%0" | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch")]) | ||||||
| 
 | 
 | ||||||
| (define_expand "cbranch<mode>4" | (define_expand "cbranch<mode>4" | ||||||
|  | @ -5717,7 +5815,30 @@ | ||||||
| 	(label_ref (match_operand 0 "" "")))] | 	(label_ref (match_operand 0 "" "")))] | ||||||
|   "TARGET_MIPS16" |   "TARGET_MIPS16" | ||||||
|   "b\t%l0" |   "b\t%l0" | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch") | ||||||
|  |    (set (attr "length") | ||||||
|  | 	;; This calculation is like the normal branch one, but the | ||||||
|  | 	;; range of the unextended instruction is [-0x800, 0x7fe] rather | ||||||
|  | 	;; than [-0x100, 0xfe].  This translates to a range of: | ||||||
|  | 	;; | ||||||
|  | 	;;    [-(0x800 - sizeof (branch)), 0x7fe] | ||||||
|  | 	;; == [-0x7fe, 0x7fe] | ||||||
|  | 	;; | ||||||
|  | 	;; from the shorten_branches reference address.  Long-branch | ||||||
|  | 	;; sequences will replace this one, so the minimum length | ||||||
|  | 	;; 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) | ||||||
|  | 	       (and (le (minus (match_dup 0) (pc)) (const_int 65534)) | ||||||
|  | 		    (le (minus (pc) (match_dup 0)) (const_int 65532))) | ||||||
|  | 	       (const_int 8) | ||||||
|  | 	       (and (match_test "TARGET_ABICALLS") | ||||||
|  | 		    (not (match_test "TARGET_ABSOLUTE_ABICALLS"))) | ||||||
|  | 	       (const_int 36) | ||||||
|  | 	       (match_test "Pmode == SImode") | ||||||
|  | 	       (const_int 28) | ||||||
|  | 	       ] (const_int 44)))]) | ||||||
| 
 | 
 | ||||||
| (define_expand "indirect_jump" | (define_expand "indirect_jump" | ||||||
|   [(set (pc) (match_operand 0 "register_operand"))] |   [(set (pc) (match_operand 0 "register_operand"))] | ||||||
|  | @ -5735,6 +5856,18 @@ | ||||||
|   [(set_attr "type" "jump") |   [(set_attr "type" "jump") | ||||||
|    (set_attr "mode" "none")]) |    (set_attr "mode" "none")]) | ||||||
| 
 | 
 | ||||||
|  | ;; A combined jump-and-move instruction, used for MIPS16 long-branch | ||||||
|  | ;; sequences.  Having a dedicated pattern is more convenient than | ||||||
|  | ;; creating a SEQUENCE for this special case. | ||||||
|  | (define_insn "indirect_jump_and_restore_<mode>" | ||||||
|  |   [(set (pc) (match_operand:P 1 "register_operand" "d")) | ||||||
|  |    (set (match_operand:P 0 "register_operand" "=d") | ||||||
|  |    	(match_operand:P 2 "register_operand" "y"))] | ||||||
|  |   "" | ||||||
|  |   "%(%<jr\t%1\;move\t%0,%2%>%)" | ||||||
|  |   [(set_attr "type" "multi") | ||||||
|  |    (set_attr "extended_mips16" "yes")]) | ||||||
|  | 
 | ||||||
| (define_expand "tablejump" | (define_expand "tablejump" | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
| 	(match_operand 0 "register_operand")) | 	(match_operand 0 "register_operand")) | ||||||
|  | @ -6549,7 +6682,8 @@ | ||||||
| 		    UNSPEC_CONSTTABLE_INT)] | 		    UNSPEC_CONSTTABLE_INT)] | ||||||
|   "TARGET_MIPS16" |   "TARGET_MIPS16" | ||||||
| { | { | ||||||
|   assemble_integer (operands[0], INTVAL (operands[1]), |   assemble_integer (mips_strip_unspec_address (operands[0]), | ||||||
|  | 		    INTVAL (operands[1]), | ||||||
| 		    BITS_PER_UNIT * INTVAL (operands[1]), 1); | 		    BITS_PER_UNIT * INTVAL (operands[1]), 1); | ||||||
|   return ""; |   return ""; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -139,9 +139,6 @@ | ||||||
| 		(match_operand 0 "hilo_operand") | 		(match_operand 0 "hilo_operand") | ||||||
| 		(match_operand 0 "register_operand"))) | 		(match_operand 0 "register_operand"))) | ||||||
| 
 | 
 | ||||||
| (define_special_predicate "pc_or_label_operand" |  | ||||||
|   (match_code "pc,label_ref")) |  | ||||||
| 
 |  | ||||||
| (define_predicate "const_call_insn_operand" | (define_predicate "const_call_insn_operand" | ||||||
|   (match_code "const,symbol_ref,label_ref") |   (match_code "const,symbol_ref,label_ref") | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -1,3 +1,9 @@ | ||||||
|  | 2012-08-02  Richard Sandiford  <rdsandiford@googlemail.com> | ||||||
|  | 
 | ||||||
|  | 	PR target/51931 | ||||||
|  | 	* gcc.c-torture/compile/20001226-1.c: Remove nomips16 attribute. | ||||||
|  | 	* g++.dg/opt/longbranch1.C: Likewise. | ||||||
|  | 
 | ||||||
| 2012-08-02  Marc Glisse  <marc.glisse@inria.fr> | 2012-08-02  Marc Glisse  <marc.glisse@inria.fr> | ||||||
| 
 | 
 | ||||||
| 	PR tree-optimization/53805 | 	PR tree-optimization/53805 | ||||||
|  |  | ||||||
|  | @ -26,10 +26,6 @@ | ||||||
|         muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \ |         muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \ | ||||||
|         muchcode; muchcode; muchcode; muchcode; muchcode; muchcode |         muchcode; muchcode; muchcode; muchcode; muchcode; muchcode | ||||||
| 
 | 
 | ||||||
| #ifdef __mips |  | ||||||
| /* See PR 51931.  */ |  | ||||||
| __attribute__((nomips16)) |  | ||||||
| #endif |  | ||||||
| int | int | ||||||
| main (int argc, char **argv) | main (int argc, char **argv) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -21,10 +21,6 @@ | ||||||
| #define C1024(x,y) C256(x,y) C256(x+16,y) C256(x+32,y) C256(x+48,y) | #define C1024(x,y) C256(x,y) C256(x+16,y) C256(x+32,y) C256(x+48,y) | ||||||
| #define C4096(x,y) C1024(x,y) C1024(x,y+16) C1024(x,y+32) C1024(x,y+48) | #define C4096(x,y) C1024(x,y) C1024(x,y+16) C1024(x,y+32) C1024(x,y+48) | ||||||
| 
 | 
 | ||||||
| #ifdef __mips |  | ||||||
| /* See PR 51931.  */ |  | ||||||
| __attribute__((nomips16)) |  | ||||||
| #endif |  | ||||||
| unsigned foo(int x[64], int y[64]) | unsigned foo(int x[64], int y[64]) | ||||||
| { | { | ||||||
|   C4096(x,y); |   C4096(x,y); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Richard Sandiford
						Richard Sandiford