2012-08-23 Julian Brown <julian@codesourcery.com>

Sandra Loosemore  <sandra@codesourcery.com>

	gcc/
	* config/mips/mips.md
	(UNSPEC_CASESI_DISPATCH): New.
	(MIPS16_T_REGNUM): New constant.
	(tablejump): Don't use for MIPS16_SHORT_JUMP_TABLES.
	(casesi): New.
	(casesi_internal_mips16_<mode>): New.
	* config/mips/mips.c (mips16_split_long_branches): Adjust test
	to ignore casesi jump tables.
	* config/mips/mips.h (TARGET_MIPS16_SHORT_JUMP_TABLES): Update
	comment.
	(CASE_VECTOR_MODE): Use SImode unconditionally.
	(CASE_VECTOR_SHORTEN_MODE): Define.
	(ASM_OUTPUT_ADDR_DIFF_ELT): Output word-sized addr_diff_elts
	when necessary for MIPS16_SHORT_JUMP_TABLES.

	gcc/testsuite/
	* gcc.target/mips/code-readable-1.c: Add -O to options.

Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com>

From-SVN: r190625
This commit is contained in:
Julian Brown 2012-08-23 15:42:03 +00:00 committed by Sandra Loosemore
parent a147b6d28f
commit 545ca0f278
6 changed files with 136 additions and 14 deletions

View file

@ -1,3 +1,21 @@
2012-08-23 Julian Brown <julian@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
* config/mips/mips.md
(UNSPEC_CASESI_DISPATCH): New.
(MIPS16_T_REGNUM): New constant.
(tablejump): Don't use for MIPS16_SHORT_JUMP_TABLES.
(casesi): New.
(casesi_internal_mips16_<mode>): New.
* config/mips/mips.c (mips16_split_long_branches): Adjust test
to ignore casesi jump tables.
* config/mips/mips.h (TARGET_MIPS16_SHORT_JUMP_TABLES): Update
comment.
(CASE_VECTOR_MODE): Use SImode unconditionally.
(CASE_VECTOR_SHORTEN_MODE): Define.
(ASM_OUTPUT_ADDR_DIFF_ELT): Output word-sized addr_diff_elts
when necessary for MIPS16_SHORT_JUMP_TABLES.
2012-08-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_density_test): Free loop body.

View file

@ -15575,7 +15575,8 @@ mips16_split_long_branches (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (JUMP_P (insn)
&& USEFUL_INSN_P (insn)
&& get_attr_length (insn) > 8)
&& get_attr_length (insn) > 8
&& (any_condjump_p (insn) || any_uncondjump_p (insn)))
{
rtx old_label, new_label, temp, saved_temp;
rtx target, jump, jump_sequence;

View file

@ -2330,13 +2330,18 @@ typedef struct mips_args {
/* True if we're generating a form of MIPS16 code in which jump tables
are stored in the text section and encoded as 16-bit PC-relative
offsets. This is only possible when general text loads are allowed,
since the table access itself will be an "lh" instruction. */
/* ??? 16-bit offsets can overflow in large functions. */
since the table access itself will be an "lh" instruction. If the
PC-relative offsets grow too large, 32-bit offsets are used instead. */
#define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS
#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16_SHORT_JUMP_TABLES
#define CASE_VECTOR_MODE (TARGET_MIPS16_SHORT_JUMP_TABLES ? HImode : ptr_mode)
#define CASE_VECTOR_MODE SImode
/* Only use short offsets if their range will not overflow. */
#define CASE_VECTOR_SHORTEN_MODE(MIN, MAX, BODY) \
(TARGET_MIPS16_SHORT_JUMP_TABLES && ((MIN) >= -32768 && (MAX) < 32768) \
? HImode : SImode)
#define CASE_VECTOR_PC_RELATIVE TARGET_MIPS16_SHORT_JUMP_TABLES
@ -2636,8 +2641,14 @@ while (0)
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
do { \
if (TARGET_MIPS16_SHORT_JUMP_TABLES) \
fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n", \
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
{ \
if (GET_MODE (BODY) == HImode) \
fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n", \
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
else \
fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
} \
else if (TARGET_GPWORD) \
fprintf (STREAM, "\t%s\t%sL%d\n", \
ptr_mode == DImode ? ".gpdword" : ".gpword", \

View file

@ -134,10 +134,14 @@
;; Used in a call expression in place of args_size. It's present for PIC
;; indirect calls where it contains args_size and the function symbol.
UNSPEC_CALL_ATTR
;; MIPS16 casesi jump table dispatch.
UNSPEC_CASESI_DISPATCH
])
(define_constants
[(TLS_GET_TP_REGNUM 3)
(MIPS16_T_REGNUM 24)
(PIC_FUNCTION_ADDR_REGNUM 25)
(RETURN_ADDR_REGNUM 31)
(CPRESTORE_SLOT_REGNUM 76)
@ -5904,14 +5908,9 @@
[(set (pc)
(match_operand 0 "register_operand"))
(use (label_ref (match_operand 1 "")))]
""
"!TARGET_MIPS16_SHORT_JUMP_TABLES"
{
if (TARGET_MIPS16_SHORT_JUMP_TABLES)
operands[0] = expand_binop (Pmode, add_optab,
convert_to_mode (Pmode, operands[0], false),
gen_rtx_LABEL_REF (Pmode, operands[1]),
0, 0, OPTAB_WIDEN);
else if (TARGET_GPWORD)
if (TARGET_GPWORD)
operands[0] = expand_binop (Pmode, add_optab, operands[0],
pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
else if (TARGET_RTP_PIC)
@ -5937,6 +5936,94 @@
[(set_attr "type" "jump")
(set_attr "mode" "none")])
;; For MIPS16, we don't know whether a given jump table will use short or
;; word-sized offsets until late in compilation, when we are able to determine
;; the sizes of the insns which comprise the containing function. This
;; necessitates the use of the casesi rather than the tablejump pattern, since
;; the latter tries to calculate the index of the offset to jump through early
;; in compilation, i.e. at expand time, when nothing is known about the
;; eventual function layout.
(define_expand "casesi"
[(match_operand:SI 0 "register_operand" "") ; index to jump on
(match_operand:SI 1 "const_int_operand" "") ; lower bound
(match_operand:SI 2 "const_int_operand" "") ; total range
(match_operand 3 "" "") ; table label
(match_operand 4 "" "")] ; out of range label
"TARGET_MIPS16_SHORT_JUMP_TABLES"
{
if (operands[1] != const0_rtx)
{
rtx reg = gen_reg_rtx (SImode);
rtx offset = gen_int_mode (-INTVAL (operands[1]), SImode);
if (!arith_operand (offset, SImode))
offset = force_reg (SImode, offset);
emit_insn (gen_addsi3 (reg, operands[0], offset));
operands[0] = reg;
}
if (!arith_operand (operands[0], SImode))
operands[0] = force_reg (SImode, operands[0]);
operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
emit_jump_insn (PMODE_INSN (gen_casesi_internal_mips16,
(operands[0], operands[2],
operands[3], operands[4])));
DONE;
})
(define_insn "casesi_internal_mips16_<mode>"
[(set (pc)
(if_then_else
(leu (match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "arith_operand" "dI"))
(unspec:P
[(match_dup 0)
(label_ref (match_operand 2 "" ""))]
UNSPEC_CASESI_DISPATCH)
(label_ref (match_operand 3 "" ""))))
(clobber (match_scratch:P 4 "=d"))
(clobber (match_scratch:P 5 "=d"))
(clobber (reg:SI MIPS16_T_REGNUM))]
"TARGET_MIPS16_SHORT_JUMP_TABLES"
{
rtx diff_vec = PATTERN (next_real_insn (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
output_asm_insn ("sltu\t%0, %1", operands);
output_asm_insn ("bteqz\t%3", operands);
switch (GET_MODE (diff_vec))
{
case HImode:
output_asm_insn ("sll\t%5, %0, 1", operands);
output_asm_insn ("la\t%4, %2", operands);
output_asm_insn ("<d>addu\t%5, %4, %5", operands);
output_asm_insn ("lh\t%5, 0(%5)", operands);
break;
case SImode:
output_asm_insn ("sll\t%5, %0, 2", operands);
output_asm_insn ("la\t%4, %2", operands);
output_asm_insn ("<d>addu\t%5, %4, %5", operands);
output_asm_insn ("lw\t%5, 0(%5)", operands);
break;
default:
gcc_unreachable ();
}
output_asm_insn ("addu\t%4, %4, %5", operands);
return "j\t%4";
}
[(set_attr "length" "32")])
;; For TARGET_USE_GOT, we save the gp in the jmp_buf as well.
;; While it is possible to either pull it off the stack (in the
;; o32 case) or recalculate it given t9 and our target label,

View file

@ -1,3 +1,8 @@
2012-08-23 Julian Brown <julian@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
* gcc.target/mips/code-readable-1.c: Add -O to options.
2012-08-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/20420

View file

@ -1,4 +1,4 @@
/* { dg-options "(-mips16) -mcode-readable=yes -mgp32 addressing=absolute" } */
/* { dg-options "(-mips16) -mcode-readable=yes -mgp32 addressing=absolute -O" } */
MIPS16 int
foo (int i)