diff options
author | Jeff Law <law@gcc.gnu.org> | 1997-07-25 11:02:37 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1997-07-25 11:02:37 -0600 |
commit | 3e056efc31aab68f650a3fa5918ca2d7fb516852 (patch) | |
tree | 6efe17b5c1f3712932f0777e4cc93730a0356e51 /gcc/config | |
parent | b60334e840e077c460eb5e9a08f990c9844f2a48 (diff) | |
download | gcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.zip gcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.tar.gz gcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.tar.bz2 |
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
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/pa/pa.c | 25 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 24 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 38 |
3 files changed, 45 insertions, 42 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 5297cad..db6c495 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -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); } diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 7855904..daf63c7 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -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 diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 3551974..848567a 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -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. |