This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: don't generate dead bytecode
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Subject: Patch: don't generate dead bytecode
- From: Tom Tromey <tromey at redhat dot com>
- Date: 09 Oct 2001 09:30:31 -0600
- Cc: Java Patch List <java-patches at gcc dot gnu dot org>, Alexandre Petit-Bianco <apbianco at cygnus dot com>, Per Bothner <per at bothner dot com>
- Reply-To: tromey at redhat dot com
Today I ran `make class-check' on libgcj. One of the problems is a
bug in the front end (previously reported). All the other problems
turned out to be dead byte code which was generated. It turns out we
generate code for a statement like this:
if (false) { do something }
This patch removes all that dead bytecode. It does so by simply not
generating code along a dead branch.
This rebuilds libgcj and passes the test suite (including class-check)
fine.
Ok?
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
* jcf-write.c (generate_bytecode_conditional): Return result
reflects whether condition was generated.
(generate_bytecode_return): Use return result.
(generate_bytecode_insns): Likewise.
Index: jcf-write.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-write.c,v
retrieving revision 1.90
diff -u -r1.90 jcf-write.c
--- jcf-write.c 2001/10/08 20:35:03 1.90
+++ jcf-write.c 2001/10/09 03:59:15
@@ -297,7 +297,7 @@
static int get_access_flags PARAMS ((tree));
static void write_chunks PARAMS ((FILE *, struct chunk *));
static int adjust_typed_op PARAMS ((tree, int));
-static void generate_bytecode_conditional PARAMS ((tree, struct jcf_block *,
+static int generate_bytecode_conditional PARAMS ((tree, struct jcf_block *,
struct jcf_block *, int,
struct jcf_partial *));
static void generate_bytecode_return PARAMS ((tree, struct jcf_partial *));
@@ -1141,9 +1141,11 @@
branch to TRUE_LABEL; otherwise, branch to FALSE_LABEL.
TRUE_BRANCH_FIRST is a code geneation hint that the
TRUE_LABEL may follow right after this. (The idea is that we
- may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:) */
+ may be able to optimize away GOTO TRUE_LABEL; TRUE_LABEL:)
+ Return 0 if we generated a conditional, -1 if the test is always
+ false, and 1 if the test is always true. */
-static void
+static int
generate_bytecode_conditional (exp, true_label, false_label,
true_branch_first, state)
tree exp;
@@ -1155,54 +1157,86 @@
tree exp0, exp1, type;
int save_SP = state->code_SP;
enum java_opcode op, negop;
+ int result = 0;
+
switch (TREE_CODE (exp))
{
case INTEGER_CST:
emit_goto (integer_zerop (exp) ? false_label : true_label, state);
+ result = integer_zerop (exp) ? -1 : 1;
break;
case COND_EXPR:
{
struct jcf_block *then_label = gen_jcf_label (state);
struct jcf_block *else_label = gen_jcf_label (state);
- int save_SP_before, save_SP_after;
- generate_bytecode_conditional (TREE_OPERAND (exp, 0),
- then_label, else_label, 1, state);
- define_jcf_label (then_label, state);
+ int save_SP_before, save_SP_after, r2;
+ int r = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ then_label, else_label,
+ 1, state);
save_SP_before = state->code_SP;
- generate_bytecode_conditional (TREE_OPERAND (exp, 1),
- true_label, false_label, 1, state);
+ if (r >= 0)
+ {
+ define_jcf_label (then_label, state);
+ r2 = generate_bytecode_conditional (TREE_OPERAND (exp, 1),
+ true_label, false_label,
+ 1, state);
+ if (r > 0)
+ result = r2;
+ }
save_SP_after = state->code_SP;
state->code_SP = save_SP_before;
- define_jcf_label (else_label, state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 2),
- true_label, false_label,
- true_branch_first, state);
+ if (r <= 0)
+ {
+ define_jcf_label (else_label, state);
+ r2 = generate_bytecode_conditional (TREE_OPERAND (exp, 2),
+ true_label, false_label,
+ true_branch_first, state);
+ if (r < 0)
+ result = r2;
+ }
if (state->code_SP != save_SP_after)
abort ();
}
break;
case TRUTH_NOT_EXPR:
- generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label,
- true_label, ! true_branch_first, state);
+ result = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ false_label, true_label,
+ ! true_branch_first, state);
break;
case TRUTH_ANDIF_EXPR:
{
struct jcf_block *next_label = gen_jcf_label (state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 0),
- next_label, false_label, 1, state);
- define_jcf_label (next_label, state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 1),
- true_label, false_label, 1, state);
+ int r, r2;
+ r = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ next_label, false_label, 1, state);
+ if (r >= 0)
+ {
+ define_jcf_label (next_label, state);
+ r2 = generate_bytecode_conditional (TREE_OPERAND (exp, 1),
+ true_label, false_label,
+ 1, state);
+ if (r > 0)
+ r = r2;
+ }
+ result = r;
}
break;
case TRUTH_ORIF_EXPR:
{
+ int r, r2;
struct jcf_block *next_label = gen_jcf_label (state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 0),
- true_label, next_label, 1, state);
- define_jcf_label (next_label, state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 1),
- true_label, false_label, 1, state);
+ r = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ true_label, next_label, 1, state);
+ if (r <= 0)
+ {
+ define_jcf_label (next_label, state);
+ r2 = generate_bytecode_conditional (TREE_OPERAND (exp, 1),
+ true_label, false_label,
+ 1, state);
+ if (r < 0)
+ r = r2;
+ }
+ result = r;
}
break;
compare_1:
@@ -1348,6 +1382,8 @@
}
if (save_SP != state->code_SP)
abort ();
+
+ return result;
}
/* Call pending cleanups i.e. those for surrounding CLEANUP_POINT_EXPRs
@@ -1389,12 +1425,19 @@
{
struct jcf_block *then_label = gen_jcf_label (state);
struct jcf_block *else_label = gen_jcf_label (state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 0),
- then_label, else_label, 1, state);
- define_jcf_label (then_label, state);
- generate_bytecode_return (TREE_OPERAND (exp, 1), state);
- define_jcf_label (else_label, state);
- generate_bytecode_return (TREE_OPERAND (exp, 2), state);
+ int r = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ then_label, else_label,
+ 1, state);
+ if (r >= 0)
+ {
+ define_jcf_label (then_label, state);
+ generate_bytecode_return (TREE_OPERAND (exp, 1), state);
+ }
+ if (r <= 0)
+ {
+ define_jcf_label (else_label, state);
+ generate_bytecode_return (TREE_OPERAND (exp, 2), state);
+ }
}
return;
default:
@@ -1617,13 +1660,19 @@
struct jcf_block *then_label = gen_jcf_label (state);
struct jcf_block *else_label = gen_jcf_label (state);
struct jcf_block *end_label = gen_jcf_label (state);
- generate_bytecode_conditional (exp,
- then_label, else_label, 1, state);
- define_jcf_label (then_label, state);
- push_int_const (1, state);
- emit_goto (end_label, state);
- define_jcf_label (else_label, state);
- push_int_const (0, state);
+ int r = generate_bytecode_conditional (exp, then_label, else_label,
+ 1, state);
+ if (r >= 0)
+ {
+ define_jcf_label (then_label, state);
+ push_int_const (1, state);
+ emit_goto (end_label, state);
+ }
+ if (r <= 0)
+ {
+ define_jcf_label (else_label, state);
+ push_int_const (0, state);
+ }
define_jcf_label (end_label, state);
NOTE_PUSH (1);
}
@@ -1633,16 +1682,24 @@
struct jcf_block *then_label = gen_jcf_label (state);
struct jcf_block *else_label = gen_jcf_label (state);
struct jcf_block *end_label = gen_jcf_label (state);
- generate_bytecode_conditional (TREE_OPERAND (exp, 0),
- then_label, else_label, 1, state);
- define_jcf_label (then_label, state);
- generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
- if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
- /* Not all expressions have CAN_COMPLETE_NORMALLY set properly. */
- || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
- emit_goto (end_label, state);
- define_jcf_label (else_label, state);
- generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
+ int r = generate_bytecode_conditional (TREE_OPERAND (exp, 0),
+ then_label, else_label,
+ 1, state);
+ if (r >= 0)
+ {
+ define_jcf_label (then_label, state);
+ generate_bytecode_insns (TREE_OPERAND (exp, 1), target, state);
+ if (CAN_COMPLETE_NORMALLY (TREE_OPERAND (exp, 1))
+ /* Not all expressions have CAN_COMPLETE_NORMALLY set
+ properly. */
+ || TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE)
+ emit_goto (end_label, state);
+ }
+ if (r <= 0)
+ {
+ define_jcf_label (else_label, state);
+ generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
+ }
define_jcf_label (end_label, state);
/* COND_EXPR can be used in a binop. The stack must be adjusted. */
if (TREE_TYPE (exp) != void_type_node)