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:
parent
a147b6d28f
commit
545ca0f278
6 changed files with 136 additions and 14 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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", \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue