restriction is in number of input characters (see \xnn &
\whatever). So we have to do this very carefully. */
- fprintf (file, "\t.STRING \"");
+ fputs ("\t.STRING \"", file);
chars_output = 0;
for (i = 0; i < size; i += 4)
}
if (chars_output + co > 243)
{
- fprintf (file, "\"\n\t.STRING \"");
+ fputs ("\"\n\t.STRING \"", file);
chars_output = 0;
}
fwrite (partial_output, 1, co, file);
chars_output += co;
co = 0;
}
- fprintf (file, "\"\n");
+ fputs ("\"\n", file);
}
\f
/* You may have trouble believing this, but this is the HP-PA stack
of a function. */
fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
if (regs_ever_live[2] || profile_flag)
- fprintf (file, ",CALLS,SAVE_RP");
+ fputs (",CALLS,SAVE_RP", file);
else
- fprintf (file, ",NO_CALLS");
+ fputs (",NO_CALLS", file);
if (frame_pointer_needed)
- fprintf (file, ",SAVE_SP");
+ fputs (",SAVE_SP", file);
/* Pass on information about the number of callee register saves
performed in the prologue.
if (fr_saved)
fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
- fprintf (file, "\n\t.ENTRY\n");
+ fputs ("\n\t.ENTRY\n", file);
/* Horrid hack. emit_function_prologue will modify this RTL in
place to get the expected results. */
/* If insn is a CALL_INSN, then it must be a call to a volatile
function (otherwise there would be epilogue insns). */
if (insn && GET_CODE (insn) == CALL_INSN)
- fprintf (file, "\tnop\n");
+ fputs ("\tnop\n", file);
- fprintf (file, "\t.EXIT\n\t.PROCEND\n");
+ fputs ("\t.EXIT\n\t.PROCEND\n", file);
/* If we have deferred plabels, then we need to switch into the data
section and align it to a 4 byte boundary before we output the
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case NE:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case GT:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case GE:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case GEU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case GTU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case LT:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case LE:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case LEU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case LTU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
default:
abort ();
}
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case GE:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case GEU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case GTU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case LT:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case LE:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case LEU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case LTU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
default:
abort ();
}
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "!="); break;
+ fputs ("!=", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, "!>"); break;
+ fputs ("!>", file); break;
case GE:
- fprintf (file, "!>="); break;
+ fputs ("!>=", file); break;
case LT:
- fprintf (file, "!<"); break;
+ fputs ("!<", file); break;
case LE:
- fprintf (file, "!<="); break;
+ fputs ("!<=", file); break;
default:
abort ();
}
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "?="); break;
+ fputs ("?=", file); break;
case NE:
- fprintf (file, "!?="); break;
+ fputs ("!?=", file); break;
case GT:
- fprintf (file, "!<="); break;
+ fputs ("!<=", file); break;
case GE:
- fprintf (file, "!<"); break;
+ fputs ("!<", file); break;
case LT:
- fprintf (file, "!>="); break;
+ fputs ("!>=", file); break;
case LE:
- fprintf (file, "!>"); break;
+ fputs ("!>", file); break;
default:
abort ();
}
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case NE:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case GT:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case GE:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case GEU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case GTU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case LT:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case LE:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case LEU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case LTU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
default:
abort ();
}
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case GE:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case GEU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case GTU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case LT:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case LE:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case LEU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case LTU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
default:
abort ();
}
{
case PRE_DEC:
case PRE_INC:
- fprintf (file, "s,mb");
+ fputs ("s,mb", file);
break;
case POST_DEC:
case POST_INC:
- fprintf (file, "s,ma");
+ fputs ("s,ma", file);
break;
default:
break;
{
case PRE_DEC:
case PRE_INC:
- fprintf (file, ",mb");
+ fputs (",mb", file);
break;
case POST_DEC:
case POST_INC:
- fprintf (file, ",ma");
+ fputs (",ma", file);
break;
default:
break;
else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
{
assemble_name (file, XSTR (x, 0));
- fprintf (file, "-$global$");
+ fputs ("-$global$", file);
}
else if (GET_CODE (x) == CONST)
{
else abort ();
if (!read_only_operand (base) && !flag_pic)
- fprintf (file, "-$global$");
+ fputs ("-$global$", file);
if (offset)
fprintf (file,"%s%d", sep, offset);
}
if using the portable runtime calling conventions. */
if (TARGET_PORTABLE_RUNTIME)
{
- fprintf (asm_out_file,
- "\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n");
+ fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n",
+ asm_out_file);
return;
}
fputc ('\n', asm_out_file);
}
\f
-/* Memory loads/stores to/from the shift need to go through
- the general registers. */
+/* Return the class of any secondary reload register that is needed to
+ move IN into a register in class CLASS using mode MODE.
+
+ Profiling has showed this routine and its descendants account for
+ a significant amount of compile time (~7%). So it has been
+ optimized to reduce redundant computations and eliminate useless
+ function calls.
+
+ It might be worthwhile to try and make this a leaf function too. */
enum reg_class
secondary_reload_class (class, mode, in)
enum machine_mode mode;
rtx in;
{
- int regno = true_regnum (in);
+ int regno, is_symbolic;
/* Trying to load a constant into a FP register during PIC code
generation will require %r1 as a scratch register. */
&& (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
return R1_REGS;
+ /* Profiling showed the PA port spends about 1.3% of its compilation
+ time in true_regnum from calls inside secondary_reload_class. */
+
+ if (GET_CODE (in) == REG)
+ {
+ regno = REGNO (in);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = true_regnum (in);
+ }
+ else if (GET_CODE (in) == SUBREG)
+ regno = true_regnum (in);
+ else
+ regno = -1;
+
+ /* Profiling showed the PA port spends about 1.3% of its compilation
+ time in true_regnum from calls inside secondary_reload_class. */
+
+ if (GET_CODE (in) == REG)
+ {
+ regno = REGNO (in);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = true_regnum (in);
+ }
+ else if (GET_CODE (in) == SUBREG)
+ regno = true_regnum (in);
+ else
+ regno = -1;
+
if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
&& GET_MODE_CLASS (mode) == MODE_INT
&& FP_REG_CLASS_P (class))
if (GET_CODE (in) == HIGH)
in = XEXP (in, 0);
+ /* Profiling has showed GCC spends about 2.6% of its compilation
+ time in symbolic_operand from calls inside secondary_reload_class.
+
+ We use an inline copy and only compute its return value once to avoid
+ useless work. */
+ switch (GET_CODE (in))
+ {
+ rtx tmp;
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ is_symbolic = 1;
+ break;
+ case CONST:
+ tmp = XEXP (in, 0);
+ is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
+ break;
+ default:
+ is_symbolic = 0;
+ break;
+ }
+
if (!flag_pic
- && symbolic_operand (in, VOIDmode)
+ && is_symbolic
&& read_only_operand (in))
return NO_REGS;
- if (class != R1_REGS && symbolic_operand (in, VOIDmode))
+ if (class != R1_REGS && is_symbolic)
return R1_REGS;
- if (GET_CODE (in) == SUBREG)
- in = SUBREG_REG (in);
-
return NO_REGS;
}
/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (hppa)");
+#define TARGET_VERSION fputs (" (hppa)", stderr);
/* Run-time compilation parameters selecting different hardware subsets. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
/* Return the register class of a scratch register needed to copy IN into
- or out of a register in CLASS in MODE. If it can be done directly,
- NO_REGS is returned. */
+ or out of a register in CLASS in MODE. If it can be done directly
+ NO_REGS is returned.
+
+ Avoid doing any work for the common case calls. */
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
- secondary_reload_class (CLASS, MODE, IN)
+ ((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \
+ && REGNO (IN) < FIRST_PSEUDO_REGISTER) \
+ ? NO_REGS : secondary_reload_class (CLASS, MODE, IN))
/* On the PA it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
fprintf (FILE, ",ARGW%d=GR", i); \
} \
if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT) \
- fprintf (FILE, ",RTNVAL=FR"); \
+ fputs (",RTNVAL=FR", FILE); \
else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \
- fprintf (FILE, ",RTNVAL=FU"); \
+ fputs (",RTNVAL=FU", FILE); \
else if (fntype != void_type_node) \
- fprintf (FILE, ",RTNVAL=GR"); \
+ fputs (",RTNVAL=GR", FILE); \
fputs ("\n", FILE); \
}} while (0)
#define TRAMPOLINE_TEMPLATE(FILE) \
{ \
- fprintf (FILE, "\tldw 36(0,%%r22),%%r21\n"); \
- fprintf (FILE, "\tbb,>=,n %%r21,30,.+16\n"); \
- fprintf (FILE, "\tdepi 0,31,2,%%r21\n"); \
- fprintf (FILE, "\tldw 4(0,%%r21),%%r19\n"); \
- fprintf (FILE, "\tldw 0(0,%%r21),%%r21\n"); \
- fprintf (FILE, "\tldsid (0,%%r21),%%r1\n"); \
- fprintf (FILE, "\tmtsp %%r1,%%sr0\n"); \
- fprintf (FILE, "\tbe 0(%%sr0,%%r21)\n"); \
- fprintf (FILE, "\tldw 40(0,%%r22),%%r29\n"); \
- fprintf (FILE, "\t.word 0\n"); \
- fprintf (FILE, "\t.word 0\n"); \
+ fputs ("\tldw 36(0,%%r22),%%r21\n", FILE); \
+ fputs ("\tbb,>=,n %%r21,30,.+16\n", FILE); \
+ fputs ("\tdepi 0,31,2,%%r21\n", FILE); \
+ fputs ("\tldw 4(0,%%r21),%%r19\n", FILE); \
+ fputs ("\tldw 0(0,%%r21),%%r21\n", FILE); \
+ fputs ("\tldsid (0,%%r21),%%r1\n", FILE); \
+ fputs ("\tmtsp %%r1,%%sr0\n", FILE); \
+ fputs ("\tbe 0(%%sr0,%%r21)\n", FILE); \
+ fputs ("\tldw 40(0,%%r22),%%r29\n", FILE); \
+ fputs ("\t.word 0\n", FILE); \
+ fputs ("\t.word 0\n", FILE); \
}
/* Length in units of the trampoline for entering a nested function.
/* Output at beginning of assembler file. */
#define ASM_FILE_START(FILE) \
-do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
+do { fputs ("\t.SPACE $PRIVATE$\n\
\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\
\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\
\t.SPACE $TEXT$\n\
\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\
\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\
\t.IMPORT $global$,DATA\n\
-\t.IMPORT $$dyncall,MILLICODE\n");\
+\t.IMPORT $$dyncall,MILLICODE\n", FILE);\
if (profile_flag)\
fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\
if (write_symbols != NO_DEBUG) \
#define ASM_APP_OFF ""
/* We don't yet know how to identify GCC to HP-PA machines. */
-#define ASM_IDENTIFY_GCC(FILE) fprintf (FILE, "; gcc_compiled.:\n")
+#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc_compiled.:\n", FILE)
/* Output before code. */
/* This is how to output an assembler line defining an `int' constant. */
#define ASM_OUTPUT_INT(FILE,VALUE) \
-{ fprintf (FILE, "\t.word "); \
+{ fputs ("\t.word ", FILE); \
if (function_label_operand (VALUE, VOIDmode) \
&& !TARGET_PORTABLE_RUNTIME) \
- fprintf (FILE, "P%%"); \
+ fputs ("P%%", FILE); \
output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n");}
+ fputs ("\n", FILE);}
/* Likewise for `short' and `char' constants. */
#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t.half "), \
+( fputs ("\t.half ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ fputs ("\n", FILE))
#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t.byte "), \
+( fputs ("\t.byte ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ fputs ("\n", FILE))
/* This is how to output an assembler line for a numeric constant byte. */