Commit 3e056efc by Jeff Law

pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode ADDR_VEC insns.

        * pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode
        ADDR_VEC insns.  Slightly rework code which explodes ADDR_VEC
        insns.
        * pa.h (TARGET_BIG_SWITCH): Define.
        (TARGET_SWITCHES): Add "big-switch" and "no-big-switch".
        (CASE_VECTOR_MODE): Use TI or DI depending on TARGET_BIG_SWITCH.
        (CASE_DROPS_THROUGH): Remove definition.
        (ASM_OUTPUT_ADDR_VEC_ELT): Rewrite to handle TARGET_BIG_SWITCH.
        (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
        * pa.md (casesi): Rework to avoid some potential long branch
        problems (also makes generated code faster!).  Handle
        TARGET_BIG_SWITCH.
        (casesi0): Corresponding changes.

From-SVN: r14528
parent b60334e8
......@@ -5807,7 +5807,7 @@ pa_reorg (insns)
pa_combine_instructions (get_insns ());
/* This is fairly cheap, so always run it if optimizing. */
if (optimize > 0)
if (optimize > 0 && !TARGET_BIG_SWITCH)
{
/* Find and explode all ADDR_VEC insns. */
insns = get_insns ();
......@@ -5831,28 +5831,33 @@ pa_reorg (insns)
for (i = 0; i < length; i++)
{
/* Emit a label before each jump to keep jump.c from
removing this code. */
tmp = gen_label_rtx ();
LABEL_NUSES (tmp) = 1;
emit_label_after (tmp, location);
location = NEXT_INSN (location);
/* Emit the jump itself. */
tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0));
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
LABEL_NUSES (JUMP_LABEL (tmp))++;
location = NEXT_INSN (location);
/* Emit a BARRIER after the jump. */
location = NEXT_INSN (location);
emit_barrier_after (location);
/* Put a CODE_LABEL before each so jump.c does not optimize
the jumps away. */
location = NEXT_INSN (location);
tmp = gen_label_rtx ();
LABEL_NUSES (tmp) = 1;
emit_label_after (tmp, location);
location = NEXT_INSN (location);
}
/* If needed, emit marker for the end of the branch table. */
if (TARGET_GAS)
emit_insn_before (gen_end_brtab (), location);
{
emit_insn_before (gen_end_brtab (), location);
location = NEXT_INSN (location);
emit_barrier_after (location);
}
/* Delete the ADDR_VEC. */
delete_insn (insn);
}
......
......@@ -112,6 +112,10 @@ extern int target_flags;
/* Use a faster sequence for indirect calls. */
#define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024)
/* Generate code with big switch statements to avoid out of range branches
occuring within the switch table. */
#define TARGET_BIG_SWITCH (target_flags & 2048)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
......@@ -143,6 +147,8 @@ extern int target_flags;
{"no-long-load-store", -512},\
{"fast-indirect-calls", 1024},\
{"no-fast-indirect-calls", -1024},\
{"big-switch", 2048}, \
{"no-big-switch", -2048}, \
{"linker-opt", 0}, \
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
......@@ -1677,14 +1683,8 @@ while (0)
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE DImode
/* Define this if the tablejump instruction expects the table
to contain offsets from the address of the table.
Do not define this if the table should contain absolute addresses. */
/* #define CASE_VECTOR_PC_RELATIVE */
#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode)
#define CASE_DROPS_THROUGH
/* Specify the tree operation to be used to convert reals to integers. */
#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
......@@ -2205,7 +2205,10 @@ DTORS_SECTION_FUNCTION
impossible. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldil LR'L$%04d,%%r1\n\tbe RR'L$%04d(%%sr4,%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE, VALUE); \
else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* Jump tables are executable code and live in the TEXT section on the PA. */
#define JUMP_TABLES_IN_TEXT_SECTION
......@@ -2218,7 +2221,10 @@ DTORS_SECTION_FUNCTION
rather than a table of absolute addresses. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv 0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE); \
else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* This is how to output an assembler line
that says to advance the location counter
......
......@@ -4006,37 +4006,29 @@
operands[0] = reg;
}
if (!INT_11_BITS (operands[2]))
if (!INT_5_BITS (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
emit_jump_insn (gen_casesi0 (operands[0], operands[2],
operands[3], operands[4]));
emit_insn (gen_cmpsi (operands[0], operands[2]));
emit_jump_insn (gen_bgtu (operands[4]));
if (TARGET_BIG_SWITCH)
{
rtx temp = gen_reg_rtx (SImode);
emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[0], operands[0]));
operands[0] = temp;
}
emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
DONE;
}")
(define_insn "casesi0"
[(set (pc)
(if_then_else (leu (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "arith11_operand" "rI"))
(plus:SI (mem:SI (plus:SI (pc) (match_dup 0)))
(label_ref (match_operand 2 "" "")))
(pc)))
(use (label_ref (match_operand 3 "" "")))]
[(set (pc) (plus:SI
(mem:SI (plus:SI (pc) (match_operand 0 "register_operand" "r")))
(label_ref (match_operand 1 "" ""))))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
operands[1] = GEN_INT (~INTVAL (operands[1]));
return \"addi,uv %1,%0,0\;blr,n %0,0\;b,n %l3\";
}
else
{
return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\";
}
}"
"blr %0,0\;nop"
[(set_attr "type" "multi")
(set_attr "length" "12")])
(set_attr "length" "8")])
;; Need nops for the calls because execution is supposed to continue
;; past; we don't want to nullify an instruction that we need.
......
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