Commit 545ca0f2 by Julian Brown Committed by Sandra Loosemore

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
parent a147b6d2
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> 2012-08-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_density_test): Free loop body. * config/rs6000/rs6000.c (rs6000_density_test): Free loop body.
......
...@@ -15575,7 +15575,8 @@ mips16_split_long_branches (void) ...@@ -15575,7 +15575,8 @@ mips16_split_long_branches (void)
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)
&& USEFUL_INSN_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 old_label, new_label, temp, saved_temp;
rtx target, jump, jump_sequence; rtx target, jump, jump_sequence;
......
...@@ -2330,13 +2330,18 @@ typedef struct mips_args { ...@@ -2330,13 +2330,18 @@ typedef struct mips_args {
/* True if we're generating a form of MIPS16 code in which jump tables /* 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 are stored in the text section and encoded as 16-bit PC-relative
offsets. This is only possible when general text loads are allowed, offsets. This is only possible when general text loads are allowed,
since the table access itself will be an "lh" instruction. */ since the table access itself will be an "lh" instruction. If the
/* ??? 16-bit offsets can overflow in large functions. */ PC-relative offsets grow too large, 32-bit offsets are used instead. */
#define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS #define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS
#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16_SHORT_JUMP_TABLES #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 #define CASE_VECTOR_PC_RELATIVE TARGET_MIPS16_SHORT_JUMP_TABLES
...@@ -2636,8 +2641,14 @@ while (0) ...@@ -2636,8 +2641,14 @@ while (0)
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
do { \ do { \
if (TARGET_MIPS16_SHORT_JUMP_TABLES) \ 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) \ else if (TARGET_GPWORD) \
fprintf (STREAM, "\t%s\t%sL%d\n", \ fprintf (STREAM, "\t%s\t%sL%d\n", \
ptr_mode == DImode ? ".gpdword" : ".gpword", \ ptr_mode == DImode ? ".gpdword" : ".gpword", \
......
...@@ -134,10 +134,14 @@ ...@@ -134,10 +134,14 @@
;; Used in a call expression in place of args_size. It's present for PIC ;; 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. ;; indirect calls where it contains args_size and the function symbol.
UNSPEC_CALL_ATTR UNSPEC_CALL_ATTR
;; MIPS16 casesi jump table dispatch.
UNSPEC_CASESI_DISPATCH
]) ])
(define_constants (define_constants
[(TLS_GET_TP_REGNUM 3) [(TLS_GET_TP_REGNUM 3)
(MIPS16_T_REGNUM 24)
(PIC_FUNCTION_ADDR_REGNUM 25) (PIC_FUNCTION_ADDR_REGNUM 25)
(RETURN_ADDR_REGNUM 31) (RETURN_ADDR_REGNUM 31)
(CPRESTORE_SLOT_REGNUM 76) (CPRESTORE_SLOT_REGNUM 76)
...@@ -5904,14 +5908,9 @@ ...@@ -5904,14 +5908,9 @@
[(set (pc) [(set (pc)
(match_operand 0 "register_operand")) (match_operand 0 "register_operand"))
(use (label_ref (match_operand 1 "")))] (use (label_ref (match_operand 1 "")))]
"" "!TARGET_MIPS16_SHORT_JUMP_TABLES"
{ {
if (TARGET_MIPS16_SHORT_JUMP_TABLES) if (TARGET_GPWORD)
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)
operands[0] = expand_binop (Pmode, add_optab, operands[0], operands[0] = expand_binop (Pmode, add_optab, operands[0],
pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
else if (TARGET_RTP_PIC) else if (TARGET_RTP_PIC)
...@@ -5937,6 +5936,94 @@ ...@@ -5937,6 +5936,94 @@
[(set_attr "type" "jump") [(set_attr "type" "jump")
(set_attr "mode" "none")]) (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. ;; 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 ;; While it is possible to either pull it off the stack (in the
;; o32 case) or recalculate it given t9 and our target label, ;; o32 case) or recalculate it given t9 and our target label,
......
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> 2012-08-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/20420 PR c++/20420
......
/* { dg-options "(-mips16) -mcode-readable=yes -mgp32 addressing=absolute" } */ /* { dg-options "(-mips16) -mcode-readable=yes -mgp32 addressing=absolute -O" } */
MIPS16 int MIPS16 int
foo (int i) foo (int i)
......
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