PATCH: C++ front end & register vars
Andrew Haley
aph@pasanda.cygnus.co.uk
Sun Jan 16 04:06:00 GMT 2000
I think we're not properly emitting USE notes for register variables
when compiling C++ in whole-function mode. The stupid register
allocator depends on these notes in order to allocate registers
correctly, so any C++ code using register vars will probably be
incorrect.
The symptom is that registers are incorrectly re-used. Consider this
fragment of C++ code:
for (register short int i = number_of_operations; --i >= 0; )
{
unsigned int tmp;
if ((tmp = (***p)()) > max)
{
max = tmp;
}
}
the current x86 egcs C++ compiler generates:
movw number_of_operations, %ax # 22 *movhi_1/2 [length = 7]
.p2align 4
.L3:
decw %ax # 28 *addhi_1/1 [length = 2]
testw %ax, %ax # 29 cmphi_0/1 [length = 4]
jns .L6 # 30 *jcc_1 [length = 2]
jmp .L4 # 31 jump [length = 2]
.p2align 4,,7
.L6:
movl p, %eax # 43 *movsi_1/1 [length = 6]
movl (%eax), %edx # 45 *movsi_1/1 [length = 2]
[ ... ]
Note here that the loop index variable (ax) is nuked by insn # 43.
I've written a patch which ensures that expand_end_bindings is passed
a list of the the register variables use at the end of a scope. With
this patch, the compiler generates:
movw number_of_operations, %bx # 22 *movhi_1/2 [length = 7]
.p2align 4
.L3:
decw %bx # 28 *addhi_1/1 [length = 2]
testw %bx, %bx # 29 cmphi_0/1 [length = 4]
jns .L6 # 30 *jcc_1 [length = 2]
jmp .L4 # 31 jump [length = 2]
.p2align 4,,7
.L6:
movl p, %eax # 43 *movsi_1/1 [length = 6]
movl (%eax), %edx # 45 *movsi_1/1 [length = 2]
Which is correct; it's using bx for the loop index instead of ax.
I don't know the C++ front end at all well; persuading it to generate
the USE notes was tricky, and I'm pretty sure that there must be a
better way of doing it than the solution I found. IMO the stupid
allocator is more trouble than it's worth, but we had that argument
last year.
Nonetheless, I offer you this patch.
Andrew.
2000-01-14 Andrew Haley <aph@cygnus.com>
* semantics.c (regdecls): New variable.
(expand_stmt): Keep a copy of all register variables used in a
scope and pass them to expand_end_bindings at the end of the
scope.
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.121
diff -c -2 -p -r1.121 semantics.c
*** semantics.c 2000/01/11 02:43:00 1.121
--- semantics.c 2000/01/14 17:25:50
*************** static tree maybe_convert_cond PROTO((tr
*** 50,53 ****
--- 50,57 ----
static tree simplify_aggr_init_exprs_r PROTO((tree *, int *, void *));
+ /* regdecls is used when we have to keep track of declared register
+ variables because of the stupid allocator. */
+ static tree regdecls;
+
/* Record the fact that STMT was the last statement added to the
statement tree. */
*************** expand_stmt (t)
*** 2352,2355 ****
--- 2356,2368 ----
expand_anon_union_decl (decl, NULL_TREE,
DECL_ANON_UNION_ELEMS (decl));
+ /* If we're using the stupid allocator and this is a
+ register variable we'll need to emit a reference at
+ the end of its scope. */
+ if (obey_regdecls && DECL_REGISTER (decl))
+ {
+ tree node = TREE_VALUE(regdecls);
+ TREE_VALUE (regdecls) = copy_node (decl);
+ TREE_CHAIN (TREE_VALUE (regdecls)) = node;
+ }
}
else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
*************** expand_stmt (t)
*** 2516,2524 ****
{
if (SCOPE_BEGIN_P (t))
! expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
! SCOPE_STMT_BLOCK (t));
else if (SCOPE_END_P (t))
! expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t),
! SCOPE_PARTIAL_P (t));
}
else if (!SCOPE_NULLIFIED_P (t))
--- 2529,2552 ----
{
if (SCOPE_BEGIN_P (t))
! {
! if (obey_regdecls)
! regdecls = tree_cons (NULL_TREE, NULL_TREE, regdecls);
! expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
! SCOPE_STMT_BLOCK (t));
! }
else if (SCOPE_END_P (t))
! {
! if (obey_regdecls)
! {
! expand_end_bindings (TREE_VALUE (regdecls),
! !SCOPE_NULLIFIED_P (t),
! SCOPE_PARTIAL_P (t));
!
! regdecls = TREE_CHAIN (regdecls);
! }
! else
! expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t),
! SCOPE_PARTIAL_P (t));
! }
}
else if (!SCOPE_NULLIFIED_P (t))
*************** expand_body (fn)
*** 2639,2642 ****
--- 2667,2672 ----
int saved_lineno;
char *saved_input_filename;
+
+ regdecls = NULL_TREE;
/* When the parser calls us after finishing the body of a template
More information about the Gcc-patches
mailing list