Commit fc470718 by J"orn Rennecke Committed by Joern Rennecke

final.c (insn_last_address, [...]): New variables.

	* final.c (insn_last_address, insn_current_align, uid_align):
	New variables.
	(in_align_chain, align_fuzz, align_shrink_fuzz): New functions.
	(insn_current_reference_address): Likewise.
	(shorten_branches, final_scan_insn): Implement LABEL_ALIGN,
	LABEL_ALIGN_AFTER_BARRIER and LOOP_ALIGN target macros.
	(label_to_alignment): New function.
	* genattrtab.c (write_test_expr): If one of LABEL_ALIGN,
	LABEL_ALIGN_AFTER_BARRIER or LOOP_ALIGN is defined, call
	insn_current_reference_address instead of insn_current_address.
	(or_attr_value, write_length_unit_log): New functions.
	(main): Call write_length_unit_log.
	(write_const_num_delay_slots): Output extra '\n'.
	* alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE):
	replace with:
	(LOOP_ALIGN, ALIGN_LABEL_AFTER_BARRIER).
	* i386.h, i386/osfrose.h, i386/svr3dbx.h, m68k.h, sparc.h: Likewise.
	* arc.h, m32r.h (ASM_OUTPUT_LOOP_ALIGN): replace with:
	(LOOP_ALIGN).
	* i960.h, m88k.h: (ASM_OUTPUT_ALIGN_CODE): Replace with:
	(LABEL_ALIGN_AFTER_BARRIER).
	* ns32k/encore.h, ns32k/merlin.h, ns32k.h, ns32k/sequent.h: Likewise.
	* ns32k/tek6000.h: Likewise.
	* i386/gas.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Delete.
	* i386.md (casesi+1): Use ASM_OUTPUT_ALIGN instead of
	ASM_OUTPUT_ALIGN_CODE.

From-SVN: r18357
parent 948edfa7
Mon Mar 2 19:51:27 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
* final.c (insn_last_address, insn_current_align, uid_align):
New variables.
(in_align_chain, align_fuzz, align_shrink_fuzz): New functions.
(insn_current_reference_address): Likewise.
(shorten_branches, final_scan_insn): Implement LABEL_ALIGN,
LABEL_ALIGN_AFTER_BARRIER and LOOP_ALIGN target macros.
(label_to_alignment): New function.
* genattrtab.c (write_test_expr): If one of LABEL_ALIGN,
LABEL_ALIGN_AFTER_BARRIER or LOOP_ALIGN is defined, call
insn_current_reference_address instead of insn_current_address.
(or_attr_value, write_length_unit_log): New functions.
(main): Call write_length_unit_log.
(write_const_num_delay_slots): Output extra '\n'.
* alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE):
replace with:
(LOOP_ALIGN, ALIGN_LABEL_AFTER_BARRIER).
* i386.h, i386/osfrose.h, i386/svr3dbx.h, m68k.h, sparc.h: Likewise.
* arc.h, m32r.h (ASM_OUTPUT_LOOP_ALIGN): replace with:
(LOOP_ALIGN).
* i960.h, m88k.h: (ASM_OUTPUT_ALIGN_CODE): Replace with:
(LABEL_ALIGN_AFTER_BARRIER).
* ns32k/encore.h, ns32k/merlin.h, ns32k.h, ns32k/sequent.h: Likewise.
* ns32k/tek6000.h: Likewise.
* i386/gas.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Delete.
* i386.md (casesi+1): Use ASM_OUTPUT_ALIGN instead of
ASM_OUTPUT_ALIGN_CODE.
Mon Mar 2 01:05:50 PST 1998 Jeff Law (law@cygnus.com) Mon Mar 2 01:05:50 PST 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot. * version.c: Bump for snapshot.
......
...@@ -387,9 +387,8 @@ extern void override_options (); ...@@ -387,9 +387,8 @@ extern void override_options ();
/* Aligning past 2**3 wastes insn cache lines, and doesn't buy much /* Aligning past 2**3 wastes insn cache lines, and doesn't buy much
issue-wise on average anyway. */ issue-wise on average anyway. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ #define LOOP_ALIGN(LABEL) \
if (optimize > 0 && write_symbols != SDB_DEBUG) \ (optimize > 0 && write_symbols != SDB_DEBUG ? 3 : 0)
ASM_OUTPUT_ALIGN (FILE, 3)
/* This is how to align an instruction for optimal branching. /* This is how to align an instruction for optimal branching.
On Alpha we'll get better performance by aligning on a quadword On Alpha we'll get better performance by aligning on a quadword
...@@ -397,9 +396,8 @@ extern void override_options (); ...@@ -397,9 +396,8 @@ extern void override_options ();
/* Aligning past 2**3 wastes insn cache lines, and doesn't buy much /* Aligning past 2**3 wastes insn cache lines, and doesn't buy much
issue-wise on average anyway. */ issue-wise on average anyway. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define ALIGN_LABEL_AFTER_BARRIER(FILE) \
if (optimize > 0 && write_symbols != SDB_DEBUG) \ (optimize > 0 && write_symbols != SDB_DEBUG ? 3 : 0)
ASM_OUTPUT_ALIGN ((FILE), 3)
/* No data type wants to be aligned rounder than this. */ /* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 64 #define BIGGEST_ALIGNMENT 64
......
...@@ -1504,12 +1504,11 @@ do { \ ...@@ -1504,12 +1504,11 @@ do { \
fprintf (FILE, ")\n"); \ fprintf (FILE, ")\n"); \
} while (0) } while (0)
/* A C expression to output text to align the location counter in the way /* The desired alignment for the location counter at the beginning
that is desirable at the beginning of a loop. */ of a loop. */
/* On the ARC, align loops to 32 byte boundaries (cache line size) /* On the ARC, align loops to 32 byte boundaries (cache line size)
if -malign-loops. */ if -malign-loops. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ #define LOOP_ALIGN(LABEL) (TARGET_ALIGN_LOOPS ? 5 : 0)
do { if (TARGET_ALIGN_LOOPS) ASM_OUTPUT_SKIP (FILE, 5); } while (0)
/* This is how to output an assembler line /* This is how to output an assembler line
that says to advance the location counter that says to advance the location counter
......
...@@ -85,20 +85,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -85,20 +85,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_ALIGN(FILE,LOG) \ #define ASM_OUTPUT_ALIGN(FILE,LOG) \
if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG)) if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
#endif #endif
/* Align labels, etc. at 4-byte boundaries.
For the 486, align to 16-byte boundary for sake of cache. */
#undef ASM_OUTPUT_ALIGN_CODE
#define ASM_OUTPUT_ALIGN_CODE(FILE) \
fprintf ((FILE), "\t.align %d,0x90\n", i386_align_jumps)
/* Align start of loop at 4-byte boundary. */
#undef ASM_OUTPUT_LOOP_ALIGN
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \
fprintf ((FILE), "\t.align %d,0x90\n", i386_align_loops)
/* A C statement or statements which output an assembler instruction /* A C statement or statements which output an assembler instruction
opcode to the stdio stream STREAM. The macro-operand PTR is a opcode to the stdio stream STREAM. The macro-operand PTR is a
......
...@@ -446,12 +446,12 @@ extern int ix86_arch; ...@@ -446,12 +446,12 @@ extern int ix86_arch;
#define MAX_CODE_ALIGN 6 /* 64 byte alignment */ #define MAX_CODE_ALIGN 6 /* 64 byte alignment */
/* Align loop starts for optimal branching. */ /* Align loop starts for optimal branching. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) ASM_OUTPUT_ALIGN (FILE, i386_align_loops) #define LOOP_ALIGN(LABEL) (i386_align_loops)
/* This is how to align an instruction for optimal branching. /* This is how to align an instruction for optimal branching.
On i486 we'll get better performance by aligning on a On i486 we'll get better performance by aligning on a
cache line (i.e. 16 byte) boundary. */ cache line (i.e. 16 byte) boundary. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) ASM_OUTPUT_ALIGN ((FILE), i386_align_jumps) #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps)
/* Standard register usage. */ /* Standard register usage. */
......
...@@ -6193,7 +6193,7 @@ byte_xor_operation: ...@@ -6193,7 +6193,7 @@ byte_xor_operation:
output_asm_insn (AS2 (mov%L2,%3,%2), xops); output_asm_insn (AS2 (mov%L2,%3,%2), xops);
output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
output_asm_insn (AS1 (jmp,%*%2), xops); output_asm_insn (AS1 (jmp,%*%2), xops);
ASM_OUTPUT_ALIGN_CODE (asm_out_file); ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps);
RET; RET;
}") }")
......
...@@ -404,10 +404,9 @@ while (0) ...@@ -404,10 +404,9 @@ while (0)
alignment to be done at such a time. Most machine descriptions do alignment to be done at such a time. Most machine descriptions do
not currently define the macro. */ not currently define the macro. */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
#define ASM_OUTPUT_ALIGN_CODE(STREAM) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) \
fprintf (STREAM, "\t.align\t%d\n", \ ((!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps)
(!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps)
/* A C expression to output text to align the location counter in the /* A C expression to output text to align the location counter in the
way that is desirable at the beginning of a loop. way that is desirable at the beginning of a loop.
...@@ -416,9 +415,8 @@ while (0) ...@@ -416,9 +415,8 @@ while (0)
alignment to be done at such a time. Most machine descriptions do alignment to be done at such a time. Most machine descriptions do
not currently define the macro. */ not currently define the macro. */
#undef ASM_OUTPUT_LOOP_ALIGN #undef LOOP_ALIGN
#define ASM_OUTPUT_LOOP_ALIGN(STREAM) \ #define LOOP_ALIGN(LABEL) (i386_align_loops)
fprintf (STREAM, "\t.align\t%d\n", i386_align_loops)
/* A C statement to output to the stdio stream STREAM an assembler /* A C statement to output to the stdio stream STREAM an assembler
command to advance the location counter to a multiple of 2 to the command to advance the location counter to a multiple of 2 to the
......
...@@ -46,16 +46,13 @@ Boston, MA 02111-1307, USA. */ ...@@ -46,16 +46,13 @@ Boston, MA 02111-1307, USA. */
/* Align labels, etc. at 4-byte boundaries. /* Align labels, etc. at 4-byte boundaries.
For the 486, align to 16-byte boundary for sake of cache. */ For the 486, align to 16-byte boundary for sake of cache. */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps)
fprintf ((FILE), "\t.align %d,0x90\n", \
1 << i386_align_jumps)
/* Align start of loop at 4-byte boundary. */ /* Align start of loop at 4-byte boundary. */
#undef ASM_OUTPUT_LOOP_ALIGN #undef LOOP_ALIGN
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ #define LOOP_ALIGN(LABEL) (i386_align_loops)
fprintf ((FILE), "\t.align %d,0x90\n", 1 << i386_align_loops);
/* Additional overrides needed for dbx-in-coff gas, mostly taken from pbb.h */ /* Additional overrides needed for dbx-in-coff gas, mostly taken from pbb.h */
......
...@@ -1407,8 +1407,7 @@ extern struct rtx_def *gen_compare_reg (); ...@@ -1407,8 +1407,7 @@ extern struct rtx_def *gen_compare_reg ();
/* Align code to 8 byte boundary if TARGET_CODE_ALIGN is true. */ /* Align code to 8 byte boundary if TARGET_CODE_ALIGN is true. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (TARGET_CODE_ALIGN ? 3 : 0)
{ if (TARGET_CODE_ALIGN) fputs("\t.align 3\n",FILE); }
/* Store in OUTPUT a string (made with alloca) containing /* Store in OUTPUT a string (made with alloca) containing
an assembler-name for a local static variable named NAME. an assembler-name for a local static variable named NAME.
......
...@@ -1673,12 +1673,11 @@ do { \ ...@@ -1673,12 +1673,11 @@ do { \
fprintf (FILE, ")\n"); \ fprintf (FILE, ")\n"); \
} while (0) } while (0)
/* A C expression to output text to align the location counter in the way /* The desired alignment for the location counter at the beginning
that is desirable at the beginning of a loop. */ of a loop. */
/* On the M32R, align loops to 32 byte boundaries (cache line size) /* On the M32R, align loops to 32 byte boundaries (cache line size)
if -malign-loops. */ if -malign-loops. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ #define LOOP_ALIGN(LABEL) (TARGET_ALIGN_LOOPS ? 5 : 0)
do { if (TARGET_ALIGN_LOOPS) ASM_OUTPUT_ALIGN (FILE, 5); } while (0)
/* This is how to output an assembler line /* This is how to output an assembler line
that says to advance the location counter that says to advance the location counter
......
...@@ -294,10 +294,10 @@ extern int target_flags; ...@@ -294,10 +294,10 @@ extern int target_flags;
#define MAX_CODE_ALIGN 2 /* 4 byte alignment */ #define MAX_CODE_ALIGN 2 /* 4 byte alignment */
/* Align loop starts for optimal branching. */ /* Align loop starts for optimal branching. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) ASM_OUTPUT_ALIGN ((FILE), m68k_align_loops) #define LOOP_ALIGN(LABEL) (m68k_align_loops)
/* This is how to align an instruction for optimal branching. */ /* This is how to align an instruction for optimal branching. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) ASM_OUTPUT_ALIGN ((FILE), m68k_align_jumps) #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (m68k_align_jumps)
#define SELECT_RTX_SECTION(MODE, X) \ #define SELECT_RTX_SECTION(MODE, X) \
{ \ { \
......
...@@ -198,13 +198,13 @@ extern char * reg_names[]; ...@@ -198,13 +198,13 @@ extern char * reg_names[];
Redefined in sysv4.h, and luna.h. */ Redefined in sysv4.h, and luna.h. */
#define VERSION_INFO1 "m88k, " #define VERSION_INFO1 "m88k, "
#ifndef VERSION_INFO2 #ifndef VERSION_INFO2
#define VERSION_INFO2 "$Revision: 1.3 $" #define VERSION_INFO2 "$Revision: 1.4 $"
#endif #endif
#ifndef VERSION_STRING #ifndef VERSION_STRING
#define VERSION_STRING version_string #define VERSION_STRING version_string
#ifdef __STDC__ #ifdef __STDC__
#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.3 $ " __DATE__ #define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.4 $ " __DATE__
#else #else
#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $" #define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $"
#endif /* __STDC__ */ #endif /* __STDC__ */
...@@ -2212,9 +2212,8 @@ do { \ ...@@ -2212,9 +2212,8 @@ do { \
/* On the m88100, align the text address to half a cache boundary when it /* On the m88100, align the text address to half a cache boundary when it
can only be reached by jumping. Pack code tightly when compiling can only be reached by jumping. Pack code tightly when compiling
crtstuff.c. */ crtstuff.c. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) \
ASM_OUTPUT_ALIGN (FILE, \ (TARGET_88100 && !flag_inhibit_size_directive ? 3 : 2)
(TARGET_88100 && !flag_inhibit_size_directive ? 3 : 2))
/* Override svr[34].h. */ /* Override svr[34].h. */
#undef ASM_OUTPUT_SKIP #undef ASM_OUTPUT_SKIP
......
...@@ -79,8 +79,8 @@ output_file_directive ((FILE), main_input_filename) ...@@ -79,8 +79,8 @@ output_file_directive ((FILE), main_input_filename)
/* The Encore assembler doesn't seem to accept the usual second argument /* The Encore assembler doesn't seem to accept the usual second argument
and warns that .align may not work in the text section if optimization and warns that .align may not work in the text section if optimization
is on. */ is on. */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
#define ASM_OUTPUT_ALIGN_CODE(FILE) #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
/* /*
* Internal labels are prefixed with a period. * Internal labels are prefixed with a period.
......
...@@ -53,7 +53,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -53,7 +53,7 @@ Boston, MA 02111-1307, USA. */
/* This is how to align the code that follows an unconditional branch. /* This is how to align the code that follows an unconditional branch.
Don't define it, since it confuses the assembler (we hear). */ Don't define it, since it confuses the assembler (we hear). */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
/* Assembler pseudo-op for shared data segment. */ /* Assembler pseudo-op for shared data segment. */
#define SHARED_SECTION_ASM_OP ".shdata" #define SHARED_SECTION_ASM_OP ".shdata"
......
...@@ -1383,11 +1383,9 @@ do { \ ...@@ -1383,11 +1383,9 @@ do { \
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf (LABEL, "*%s%d", PREFIX, NUM) sprintf (LABEL, "*%s%d", PREFIX, NUM)
/* This is how to align the code that follows an unconditional branch. /* This is how to align the code that follows an unconditional branch. */
Note that 0xa2 is a no-op. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (2)
fprintf (FILE, "\t.align 2,0xa2\n")
/* This is how to output an element of a case-vector that is absolute. /* This is how to output an element of a case-vector that is absolute.
(The ns32k does not use such vectors, (The ns32k does not use such vectors,
......
...@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
/* This is how to align the code that follows an unconditional branch. /* This is how to align the code that follows an unconditional branch.
Don't define it, since it confuses the assembler (we hear). */ Don't define it, since it confuses the assembler (we hear). */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
/* Assembler pseudo-op for shared data segment. */ /* Assembler pseudo-op for shared data segment. */
#define SHARED_SECTION_ASM_OP ".shdata" #define SHARED_SECTION_ASM_OP ".shdata"
......
...@@ -106,7 +106,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -106,7 +106,7 @@ Boston, MA 02111-1307, USA. */
/* This is how to align the code that follows an unconditional branch. /* This is how to align the code that follows an unconditional branch.
Don't define it, since it confuses the assembler (we hear). */ Don't define it, since it confuses the assembler (we hear). */
#undef ASM_OUTPUT_ALIGN_CODE #undef LABEL_ALIGN_AFTER_BARRIER
/* Assembler pseudo-op for shared data segment. */ /* Assembler pseudo-op for shared data segment. */
#define SHARED_SECTION_ASM_OP ".shdata" #define SHARED_SECTION_ASM_OP ".shdata"
......
...@@ -2991,11 +2991,9 @@ do { \ ...@@ -2991,11 +2991,9 @@ do { \
if ((LOG) != 0) \ if ((LOG) != 0) \
fprintf (FILE, "\t.align %d\n", (1<<(LOG))) fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
#define ASM_OUTPUT_ALIGN_CODE(FILE) \ #define LABEL_ALIGN_AFTER_BARRIER(LABEL) (sparc_align_jumps)
ASM_OUTPUT_ALIGN (FILE, sparc_align_jumps)
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ #define LOOP_ALIGN(LABEL) (sparc_align_loops)
ASM_OUTPUT_ALIGN (FILE, sparc_align_loops)
#define ASM_OUTPUT_SKIP(FILE,SIZE) \ #define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\t.skip %u\n", (SIZE)) fprintf (FILE, "\t.skip %u\n", (SIZE))
......
...@@ -153,6 +153,8 @@ static int count_basic_blocks; ...@@ -153,6 +153,8 @@ static int count_basic_blocks;
/* Number of instrumented arcs when profile_arc_flag is set. */ /* Number of instrumented arcs when profile_arc_flag is set. */
extern int count_instrumented_arcs; extern int count_instrumented_arcs;
extern int length_unit_log; /* This is defined in insn-attrtab.c. */
/* Nonzero while outputting an `asm' with operands. /* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't abort. This means that inconsistencies are the user's fault, so don't abort.
The precise value is the insn being output, to pass to error_for_asm. */ The precise value is the insn being output, to pass to error_for_asm. */
...@@ -628,6 +630,12 @@ int *insn_addresses; ...@@ -628,6 +630,12 @@ int *insn_addresses;
/* Address of insn being processed. Used by `insn_current_length'. */ /* Address of insn being processed. Used by `insn_current_length'. */
int insn_current_address; int insn_current_address;
/* Address of insn being processed in previous iteration. */
int insn_last_address;
/* konwn invariant alignment of insn being processed. */
int insn_current_align;
/* Indicate that branch shortening hasn't yet been done. */ /* Indicate that branch shortening hasn't yet been done. */
void void
...@@ -666,16 +674,8 @@ get_attr_length (insn) ...@@ -666,16 +674,8 @@ get_attr_length (insn)
body = PATTERN (insn); body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{ {
/* This only takes room if jump tables go into the text section. */ /* Alignment is machine-dependent and should be handled by
#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION) ADDR_VEC_ALIGN. */
length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
/* Be pessimistic and assume worst-case alignment. */
length += (GET_MODE_SIZE (GET_MODE (body)) - 1);
#else
return 0;
#endif
} }
else else
length = insn_default_length (insn); length = insn_default_length (insn);
...@@ -708,6 +708,205 @@ get_attr_length (insn) ...@@ -708,6 +708,205 @@ get_attr_length (insn)
#endif /* not HAVE_ATTR_length */ #endif /* not HAVE_ATTR_length */
} }
/* Code to handle alignment inside shorten_branches. */
/* Here is an explanation how the algorithm in align_fuzz can give
proper results:
Call a sequence of instructions beginning with alignment point X
and continuing until the next alignment point `block X'. When `X'
is used in an expression, it means the alignment value of the
alignment point.
Call the distance between the start of the first insn of block X, and
the end of the last insn of block X `IX', for the `inner size of X'.
This is clearly the sum of the instruction lengths.
Likewise with the next alignment-delimited block following X, which we
shall call block Y.
Call the distance between the start of the first insn of block X, and
the start of the first insn of block Y `OX', for the `outer size of X'.
The estimated padding is then OX - IX.
OX can be safely estimated as
if (X >= Y)
OX = round_up(IX, Y)
else
OX = round_up(IX, X) + Y - X
Clearly est(IX) >= real(IX), because that only depends on the
instruction lengths, and those being overestimated is a given.
Clearly round_up(foo, Z) >= round_up(bar, Z) if foo >= bar, so
we needn't worry about that when thinking about OX.
When X >= Y, the alignment provided by Y adds no uncertainty factor
for branch ranges starting before X, so we can just round what we have.
But when X < Y, we don't know anything about the, so to speak,
`middle bits', so we have to assume the worst when aligning up from an
address mod X to one mod Y, which is Y - X. */
#ifndef LABEL_ALIGN
#define LABEL_ALIGN(LABEL) 0
#endif
#ifndef LOOP_ALIGN
#define LOOP_ALIGN(LABEL) 0
#endif
#ifndef LABEL_ALIGN_AFTER_BARRIER
#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
#endif
#ifndef ADDR_VEC_ALIGN
int
final_addr_vec_align (addr_vec)
rtx addr_vec;
{
int align = exact_log2 (GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec))));
if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
return align;
}
#define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC)
#endif
#ifndef INSN_LENGTH_ALIGNMENT
#define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log
#endif
/* For any insn, uid_align[INSN_UID (insn)] gives the next following
alignment insn that increases the known alignment, or NULL_RTX if
there is no such insn.
For any alignment obtained this way, we can again index uid_align with
its uid to obtain the next following align that in turn increases the
alignment, till we reach NULL_RTX; the sequence obtained this way
for each insn we'll call the alignment chain of this insn in the following
comments. */
rtx *uid_align;
int *uid_shuid;
short *label_align; /* sh.c needs this to calculate constant tables. */
#define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
static int min_labelno;
#define LABEL_TO_ALIGNMENT(LABEL) \
(label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno])
/* For the benefit of port specific code do this also as a function. */
int
label_to_alignment (label)
rtx label;
{
return LABEL_TO_ALIGNMENT (label);
}
#ifdef HAVE_ATTR_length
/* The differences in addresses
between a branch and its target might grow or shrink depending on
the alignment the start insn of the range (the branch for a forward
branch or the label for a backward branch) starts out on; if these
differences are used naively, they can even oscillate infinitely.
We therefore want to compute a 'worst case' address difference that
is independent of the alignment the start insn of the range end
up on, and that is at least as large as the actual difference.
The function align_fuzz calculates the amount we have to add to the
naively computed difference, by traversing the part of the alignment
chain of the start insn of the range that is in front of the end insn
of the range, and considering for each alignment the maximum amount
that it might contribute to a size increase.
For casesi tables, we also want to know worst case minimum amounts of
address difference, in case a machine description wants to introduce
some common offset that is added to all offsets in a table.
For this purpose, align_fuzz with a growth argument of 0 comuptes the
appropriate adjustment. */
/* Compute the maximum delta by which the difference of the addresses of
START and END might grow / shrink due to a different address for start
which changes the size of alignment insns between START and END.
KNOWN_ALIGN_LOG is the alignment known for START.
GROWTH should be ~0 if the objective is to compute potential code size
increase, and 0 if the objective is to compute potential shrink.
The return value is undefined for any other value of GROWTH. */
int align_fuzz (start, end, known_align_log, growth)
rtx start, end;
int known_align_log;
unsigned growth;
{
int uid = INSN_UID (start);
rtx align_label;
int known_align = 1 << known_align_log;
int end_shuid = INSN_SHUID (end);
int fuzz = 0;
for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
{
int align_addr, new_align;
uid = INSN_UID (align_label);
align_addr = insn_addresses[uid] - insn_lengths[uid];
if (uid_shuid[uid] > end_shuid)
break;
known_align_log = LABEL_TO_ALIGNMENT (align_label);
new_align = 1 << known_align_log;
if (new_align < known_align)
continue;
fuzz += (-align_addr ^ growth) & (new_align - known_align);
known_align = new_align;
}
return fuzz;
}
/* Compute a worst-case reference address of a branch so that it
can be safely used in the presence of aligned labels. Since the
size of the branch itself is unknown, the size of the branch is
not included in the range. I.e. for a forward branch, the reference
address is the end address of the branch as known from the previous
branch shortening pass, minus a value to account for possible size
increase due to alignment. For a backward branch, it is the start
address of the branch as known from the current pass, plus a value
to account for possible size increase due to alignment.
NB.: Therefore, the maximum offset allowed for backward branches needs
to exclude the branch size. */
int
insn_current_reference_address (branch)
rtx branch;
{
rtx dest;
rtx seq = NEXT_INSN (PREV_INSN (branch));
int seq_uid = INSN_UID (seq);
if (GET_CODE (branch) != JUMP_INSN)
/* This can happen for example on the PA; the objective is to know the
offset to address something in front of the start of the function.
Thus, we can treat it like a backward branch.
We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than
any alignment we'd encounter, so we skip the call to align_fuzz. */
return insn_current_address;
dest = JUMP_LABEL (branch);
if (INSN_SHUID (branch) < INSN_SHUID (dest))
{
/* Forward branch. */
return (insn_last_address + insn_lengths[seq_uid]
- align_fuzz (branch, dest, length_unit_log, ~0));
}
else
{
/* Backward branch. */
return (insn_current_address
+ align_fuzz (dest, branch, length_unit_log, ~0));
}
}
#endif /* HAVE_ATTR_length */
/* Make a pass over all insns and compute their actual lengths by shortening /* Make a pass over all insns and compute their actual lengths by shortening
any branches of variable length if possible. */ any branches of variable length if possible. */
...@@ -717,34 +916,188 @@ get_attr_length (insn) ...@@ -717,34 +916,188 @@ get_attr_length (insn)
#define FIRST_INSN_ADDRESS 0 #define FIRST_INSN_ADDRESS 0
#endif #endif
/* shorten_branches might be called multiple times: for example, the SH
port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG.
In order to do this, it needs proper length information, which it obtains
by calling shorten_branches. This cannot be collapsed with
shorten_branches itself into a single pass unless we also want to intergate
reorg.c, since the branch splitting exposes new instructions with delay
slots. */
void void
shorten_branches (first) shorten_branches (first)
rtx first; rtx first;
{ {
#ifdef HAVE_ATTR_length
rtx insn; rtx insn;
int max_uid;
int i;
int max_labelno;
int max_log;
#ifdef HAVE_ATTR_length
#define MAX_CODE_ALIGN 16
rtx seq;
int something_changed = 1; int something_changed = 1;
int max_uid = 0;
char *varying_length; char *varying_length;
rtx body; rtx body;
int uid; int uid;
rtx align_tab[MAX_CODE_ALIGN];
/* In order to make sure that all instructions have valid length info, /* In order to make sure that all instructions have valid length info,
we must split them before we compute the address/length info. */ we must split them before we compute the address/length info. */
for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn)) for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
insn = try_split (PATTERN (insn), insn, 1); {
rtx old = insn;
insn = try_split (PATTERN (old), old, 1);
/* When not optimizing, the old insn will be still left around
with only the 'deleted' bit set. Transform it into a note
to avoid confusion of subsequent processing. */
if (INSN_DELETED_P (old))
{
PUT_CODE (old , NOTE);
NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (old) = 0;
}
}
#endif
/* Compute maximum UID and allocate arrays. */ /* We must do some computations even when not actually shortening, in
for (insn = first; insn; insn = NEXT_INSN (insn)) order to get the alignment information for the labels. */
if (INSN_UID (insn) > max_uid)
max_uid = INSN_UID (insn); /* Compute maximum UID and allocate label_align / uid_shuid. */
max_uid = get_max_uid ();
max_labelno = max_label_num ();
min_labelno = get_first_label_num ();
if (label_align)
free (label_align);
label_align
= (short*) xmalloc ((max_labelno - min_labelno + 1) * sizeof (short));
bzero (label_align, (max_labelno - min_labelno + 1) * sizeof (short));
if (uid_shuid)
free (uid_shuid);
uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
/* Initialize label_align and set up uid_shuid to be strictly
monotonically rising with insn order. */
for (max_log = 0, insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
{
int log;
INSN_SHUID (insn) = i++;
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
max_log = 0;
else if (GET_CODE (insn) == CODE_LABEL)
{
rtx next;
log = LABEL_ALIGN (insn);
if (max_log < log)
max_log = log;
next = NEXT_INSN (insn);
/* ADDR_VECs only take room if read-only data goes into the text section. */
#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
if (next && GET_CODE (next) == JUMP_INSN)
{
rtx nextbody = PATTERN (next);
if (GET_CODE (nextbody) == ADDR_VEC
|| GET_CODE (nextbody) == ADDR_DIFF_VEC)
{
log = ADDR_VEC_ALIGN (next);
if (max_log < log)
max_log = log;
}
}
#endif
LABEL_TO_ALIGNMENT (insn) = max_log;
max_log = 0;
}
else if (GET_CODE (insn) == BARRIER)
{
rtx label;
for (label = insn; label && GET_RTX_CLASS (GET_CODE (label)) != 'i';
label = NEXT_INSN (label))
if (GET_CODE (label) == CODE_LABEL)
{
log = LABEL_ALIGN_AFTER_BARRIER (insn);
if (max_log < log)
max_log = log;
break;
}
}
else if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
{
rtx label;
for (label = insn; label && GET_RTX_CLASS (GET_CODE (label)) != 'i';
label = NEXT_INSN (label))
if (GET_CODE (label) == CODE_LABEL)
{
log = LOOP_ALIGN (insn);
if (max_log < log)
max_log = log;
break;
}
}
else
continue;
}
#ifdef HAVE_ATTR_length
/* Allocate the rest of the arrays. */
if (insn_lengths)
free (insn_lengths);
insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
if (insn_addresses)
free (insn_addresses);
insn_addresses = (int *) xmalloc (max_uid * sizeof (int));
if (uid_align)
free (uid_align);
uid_align = (rtx *) xmalloc (max_uid * sizeof *uid_align);
varying_length = (char *) xmalloc (max_uid * sizeof (char));
bzero (varying_length, max_uid);
/* Initialize uid_align. We scan instructions
from end to start, and keep in align_tab[n] the last seen insn
that does an alignment of at least n+1, i.e. the successor
in the alignment chain for an insn that does / has a known
alignment of n. */
bzero ((char *) uid_align, max_uid * sizeof *uid_align);
for (i = MAX_CODE_ALIGN; --i >= 0; )
align_tab[i] = NULL_RTX;
seq = get_last_insn ();
for (insn_current_address = 0; seq; seq = PREV_INSN (seq))
{
int uid = INSN_UID (seq);
int log;
int length_align;
log = (GET_CODE (seq) == CODE_LABEL ? LABEL_TO_ALIGNMENT (seq) : 0);
uid_align[uid] = align_tab[0];
insn_addresses[uid] = --insn_current_address;
if (log)
{
/* Found an alignment label. */
uid_align[uid] = align_tab[log];
for (i = log - 1; i >= 0; i--)
align_tab[i] = seq;
}
if (GET_CODE (seq) != INSN || GET_CODE (PATTERN (seq)) != SEQUENCE)
insn = seq;
else
{
insn = XVECEXP (PATTERN (seq), 0, 0);
uid = INSN_UID (insn);
}
}
max_uid++;
insn_lengths = (short *) oballoc (max_uid * sizeof (short));
insn_addresses = (int *) oballoc (max_uid * sizeof (int));
varying_length = (char *) oballoc (max_uid * sizeof (char));
/* Compute initial lengths, addresses, and varying flags for each insn. */ /* Compute initial lengths, addresses, and varying flags for each insn. */
for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
...@@ -752,9 +1105,22 @@ shorten_branches (first) ...@@ -752,9 +1105,22 @@ shorten_branches (first)
insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
{ {
uid = INSN_UID (insn); uid = INSN_UID (insn);
insn_addresses[uid] = insn_current_address;
insn_lengths[uid] = 0; insn_lengths[uid] = 0;
varying_length[uid] = 0;
if (GET_CODE (insn) == CODE_LABEL)
{
int log = LABEL_TO_ALIGNMENT (insn);
if (log)
{
int align = 1 << log;
int new_address = insn_current_address + align - 1 & -align;
insn_lengths[uid] = new_address - insn_current_address;
insn_current_address = new_address;
}
}
insn_addresses[uid] = insn_current_address;
if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
|| GET_CODE (insn) == CODE_LABEL) || GET_CODE (insn) == CODE_LABEL)
...@@ -764,25 +1130,7 @@ shorten_branches (first) ...@@ -764,25 +1130,7 @@ shorten_branches (first)
body = PATTERN (insn); body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{ ; /* This should be handled by LABEL_ALIGN. */
/* This only takes room if read-only data goes into the text
section. */
#if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
int unitsize = GET_MODE_SIZE (GET_MODE (body));
insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
/* We don't know what address the ADDR_VEC/ADDR_DIFF_VEC will end
up at after branch shortening. As a result, it is impossible
to determine how much padding we need at this point. Therefore,
assume worst possible alignment. */
insn_lengths[uid] += unitsize - 1;
#else
;
#endif
}
else if (asm_noperands (body) >= 0) else if (asm_noperands (body) >= 0)
insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn); insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
else if (GET_CODE (body) == SEQUENCE) else if (GET_CODE (body) == SEQUENCE)
...@@ -842,6 +1190,7 @@ shorten_branches (first) ...@@ -842,6 +1190,7 @@ shorten_branches (first)
while (something_changed) while (something_changed)
{ {
something_changed = 0; something_changed = 0;
insn_current_align = MAX_CODE_ALIGN - 1;
for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
insn != 0; insn != 0;
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
...@@ -852,9 +1201,34 @@ shorten_branches (first) ...@@ -852,9 +1201,34 @@ shorten_branches (first)
int tmp_length; int tmp_length;
#endif #endif
#endif #endif
int length_align;
uid = INSN_UID (insn); uid = INSN_UID (insn);
if (GET_CODE (insn) == CODE_LABEL)
{
int log = LABEL_TO_ALIGNMENT (insn);
if (log > insn_current_align)
{
int align = 1 << log;
int new_address= insn_current_address + align - 1 & -align;
insn_lengths[uid] = new_address - insn_current_address;
insn_current_align = log;
insn_current_address = new_address;
}
else
insn_lengths[uid] = 0;
insn_addresses[uid] = insn_current_address;
continue;
}
length_align = INSN_LENGTH_ALIGNMENT (insn);
if (length_align < insn_current_align)
insn_current_align = length_align;
insn_last_address = insn_addresses[uid];
insn_addresses[uid] = insn_current_address; insn_addresses[uid] = insn_current_address;
if (! varying_length[uid]) if (! varying_length[uid])
{ {
insn_current_address += insn_lengths[uid]; insn_current_address += insn_lengths[uid];
...@@ -915,6 +1289,9 @@ shorten_branches (first) ...@@ -915,6 +1289,9 @@ shorten_branches (first)
if (!optimize) if (!optimize)
break; break;
} }
free (varying_length);
#endif /* HAVE_ATTR_length */ #endif /* HAVE_ATTR_length */
} }
...@@ -1413,17 +1790,8 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -1413,17 +1790,8 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
/* Align the beginning of a loop, for higher speed /* Align the beginning of a loop, for higher speed
on certain machines. */ on certain machines. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
{ break; /* This used to depend on optimize, but that was bogus. */
#ifdef ASM_OUTPUT_LOOP_ALIGN
rtx next = next_nonnote_insn (insn);
if (next && GET_CODE (next) == CODE_LABEL)
{
ASM_OUTPUT_LOOP_ALIGN (asm_out_file);
}
#endif
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
break; break;
...@@ -1633,13 +2001,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -1633,13 +2001,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
break; break;
case BARRIER: case BARRIER:
#ifdef ASM_OUTPUT_ALIGN_CODE
/* Don't litter the assembler output with needless alignments. A
BARRIER will be placed at the end of every function if HAVE_epilogue
is true. */
if (NEXT_INSN (insn))
ASM_OUTPUT_ALIGN_CODE (file);
#endif
#if defined (DWARF2_UNWIND_INFO) && !defined (ACCUMULATE_OUTGOING_ARGS) #if defined (DWARF2_UNWIND_INFO) && !defined (ACCUMULATE_OUTGOING_ARGS)
/* If we push arguments, we need to check all insns for stack /* If we push arguments, we need to check all insns for stack
adjustments. */ adjustments. */
...@@ -1649,6 +2010,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ...@@ -1649,6 +2010,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
break; break;
case CODE_LABEL: case CODE_LABEL:
{
int align = LABEL_TO_ALIGNMENT (insn);
if (align && NEXT_INSN (insn))
ASM_OUTPUT_ALIGN (file, align);
}
CC_STATUS_INIT; CC_STATUS_INIT;
if (prescan > 0) if (prescan > 0)
break; break;
......
...@@ -448,6 +448,7 @@ static void gen_delay PROTO((rtx)); ...@@ -448,6 +448,7 @@ static void gen_delay PROTO((rtx));
static void gen_unit PROTO((rtx)); static void gen_unit PROTO((rtx));
static void write_test_expr PROTO((rtx, int)); static void write_test_expr PROTO((rtx, int));
static int max_attr_value PROTO((rtx)); static int max_attr_value PROTO((rtx));
static int or_attr_value PROTO((rtx));
static void walk_attr_value PROTO((rtx)); static void walk_attr_value PROTO((rtx));
static void write_attr_get PROTO((struct attr_desc *)); static void write_attr_get PROTO((struct attr_desc *));
static rtx eliminate_known_true PROTO((rtx, rtx, int, int)); static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
...@@ -2500,6 +2501,26 @@ max_fn (exp) ...@@ -2500,6 +2501,26 @@ max_fn (exp)
{ {
return make_numeric_value (max_attr_value (exp)); return make_numeric_value (max_attr_value (exp));
} }
static void
write_length_unit_log ()
{
struct attr_desc *length_attr = find_attr ("length", 0);
struct attr_value *av;
struct insn_ent *ie;
unsigned int length_unit_log, length_or;
if (length_attr == 0)
return;
length_or = or_attr_value (length_attr->default_val->value);
for (av = length_attr->first_value; av; av = av->next)
for (ie = av->first_insn; ie; ie = ie->next)
length_or |= or_attr_value (av->value);
length_or = ~length_or;
for (length_unit_log = 0; length_or & 1; length_or >>= 1)
length_unit_log++;
printf ("int length_unit_log = %u;\n", length_unit_log);
}
/* Take a COND expression and see if any of the conditions in it can be /* Take a COND expression and see if any of the conditions in it can be
simplified. If any are known true or known false for the particular insn simplified. If any are known true or known false for the particular insn
...@@ -4639,12 +4660,13 @@ write_test_expr (exp, flags) ...@@ -4639,12 +4660,13 @@ write_test_expr (exp, flags)
XINT (exp, 0), XINT (exp, 0), XINT (exp, 0)); XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
break; break;
/* The address of the current insn. It would be more consistent with
other usage to make this the address of the NEXT insn, but this gets
too confusing because of the ambiguity regarding the length of the
current insn. */
case PC: case PC:
printf ("insn_current_address"); /* The address of the current insn. We implement this actually as the
address of the current insn for backward branches, but the last
address of the next insn for forward branches, and both with
adjustments that account for the worst-case possible stretching of
intervening alignments between this insn and its destination. */
printf("insn_current_reference_address (insn)");
break; break;
case CONST_STRING: case CONST_STRING:
...@@ -4708,6 +4730,42 @@ max_attr_value (exp) ...@@ -4708,6 +4730,42 @@ max_attr_value (exp)
return current_max; return current_max;
} }
/* Given an attribute value, return the result of ORing together all
CONST_STRING arguments encountered. It is assumed that they are
all numeric. */
static int
or_attr_value (exp)
rtx exp;
{
int current_or = 0;
int i;
if (GET_CODE (exp) == CONST_STRING)
return atoi (XSTR (exp, 0));
else if (GET_CODE (exp) == COND)
{
for (i = 0; i < XVECLEN (exp, 0); i += 2)
{
current_or |= or_attr_value (XVECEXP (exp, 0, i + 1));
}
current_or |= or_attr_value (XEXP (exp, 1));
}
else if (GET_CODE (exp) == IF_THEN_ELSE)
{
current_or = or_attr_value (XEXP (exp, 1));
current_or |= or_attr_value (XEXP (exp, 2));
}
else
abort ();
return current_or;
}
/* Scan an attribute value, possibly a conditional, and record what actions /* Scan an attribute value, possibly a conditional, and record what actions
will be required to do any conditional tests in it. will be required to do any conditional tests in it.
...@@ -5795,7 +5853,7 @@ write_const_num_delay_slots () ...@@ -5795,7 +5853,7 @@ write_const_num_delay_slots ()
printf (" default:\n"); printf (" default:\n");
printf (" return 1;\n"); printf (" return 1;\n");
printf (" }\n}\n"); printf (" }\n}\n\n");
} }
} }
...@@ -5982,6 +6040,8 @@ from the machine description file `md'. */\n\n"); ...@@ -5982,6 +6040,8 @@ from the machine description file `md'. */\n\n");
/* Write out constant delay slot info */ /* Write out constant delay slot info */
write_const_num_delay_slots (); write_const_num_delay_slots ();
write_length_unit_log ();
fflush (stdout); fflush (stdout);
exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
/* NOTREACHED */ /* NOTREACHED */
......
...@@ -6154,25 +6154,30 @@ instead of inline unwinders and __unwind_function in the non-setjmp case. ...@@ -6154,25 +6154,30 @@ instead of inline unwinders and __unwind_function in the non-setjmp case.
This describes commands for alignment. This describes commands for alignment.
@table @code @table @code
@findex ASM_OUTPUT_ALIGN_CODE @findex LABEL_ALIGN_AFTER_BARRIER
@item ASM_OUTPUT_ALIGN_CODE (@var{file}) @item LABEL_ALIGN_AFTER_BARRIER (@var{label})
A C expression to output text to align the location counter in the way The alignment (log base 2) to put in front of @var{label}, which follows
that is desirable at a point in the code that is reached only by a BARRIER.
jumping.
This macro need not be defined if you don't want any special alignment This macro need not be defined if you don't want any special alignment
to be done at such a time. Most machine descriptions do not currently to be done at such a time. Most machine descriptions do not currently
define the macro. define the macro.
@findex ASM_OUTPUT_LOOP_ALIGN @findex LOOP_ALIGN
@item ASM_OUTPUT_LOOP_ALIGN (@var{file}) @item LOOP_ALIGN (@var{label})
A C expression to output text to align the location counter in the way The alignment (log base 2) to put in front of @var{label}, which follows
that is desirable at the beginning of a loop. a NOTE_INSN_LOOP_BEG note.
This macro need not be defined if you don't want any special alignment This macro need not be defined if you don't want any special alignment
to be done at such a time. Most machine descriptions do not currently to be done at such a time. Most machine descriptions do not currently
define the macro. define the macro.
@findex LABEL_ALIGN
@item LABEL_ALIGN (@var{label})
The alignment (log base 2) to put in front of @var{label}.
If LABEL_ALIGN_AFTER_BARRIER / LOOP_ALIGN specify a different alignment,
the maximum of the specified values is used.
@findex ASM_OUTPUT_SKIP @findex ASM_OUTPUT_SKIP
@item ASM_OUTPUT_SKIP (@var{stream}, @var{nbytes}) @item ASM_OUTPUT_SKIP (@var{stream}, @var{nbytes})
A C statement to output to the stdio stream @var{stream} an assembler A C statement to output to the stdio stream @var{stream} an assembler
......
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