This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
two ssa-ccp fixes
- To: gcc-patches at gcc dot gnu dot org
- Subject: two ssa-ccp fixes
- From: law at redhat dot com
- Date: Wed, 25 Jul 2001 08:23:33 -0600
- Reply-to: law at redhat dot com
As you may know, I have code in my local tree which scans the RTL for each
function and conditionally sends us down the SSA path when the RTL has no
constructs which are problematical for SSA.
I recently updated that code to allow us to use the SSA path in some
additional cases. This has exposed a few latent bugs.
The first two bugs are in the ssa-ccp optimization pass.
First, a CALL_INSN may end a basic block and the block may have multiple
outgoing edges (consider a call that throws). Clearly if we visit a
block which ends in a CALL_INSN, then we must consider all outgoing edges
from that block as executable. This bug showed up as an abort when
building libstdc++-v3 on ia64-linux.
Second, the simplifier mis-compiled expmed.c::mask_rtx. We had something
like
(set (reg:SI X) (const_int -1))
(set (reg:DI Y) (zero_extend:DI (reg:SI X))
We determined that (reg:SI X) had a known constant value. So we
tried to simplify
(zero_extend:DI (const_int -1))
The lack of a mode on the constant caused this to be effectively be
treated like
(zero_extend:DI (const_int:DI -1))
When it should have been treated like
(zero_extend:DI (const_int:SI -1))
The fix is pretty simple -- compute the mode to pass to
simplify_unary_operation before we replace registers with constants :-)
Bootstrapped on ia64-linux.
* ssa-ccp.c (visit_expression): Handle CALL_INSNs that can
throw an exception.
(visit_expression): When attempting to simplify an expression,
retrieve any modes for arguments before they are simplified
to constants.
Index: ssa-ccp.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/ssa-ccp.c,v
retrieving revision 1.2.2.3
diff -c -3 -p -r1.2.2.3 ssa-ccp.c
*** ssa-ccp.c 2001/07/11 22:23:07 1.2.2.3
--- ssa-ccp.c 2001/07/25 14:06:39
*************** visit_expression (insn, block)
*** 246,251 ****
--- 246,275 ----
{
rtx src, dest, set;
+
+ /* Ugh. CALL_INSNs may end a basic block and have multiple edges
+ leading out from them.
+
+ Mark all the outgoing edges as executable, then fall into the
+ normal processing below. */
+ if (GET_CODE (insn) == CALL_INSN && block->end == insn)
+ {
+ edge curredge;
+
+ for (curredge = block->succ; curredge;
+ curredge = curredge->succ_next)
+ {
+ int index = EIE (curredge->src, curredge->dest);
+
+ if (TEST_BIT (executable_edges, index))
+ continue;
+
+ SET_BIT (executable_edges, index);
+ edge_info[index] = flow_edges;
+ flow_edges = curredge;
+ }
+ }
+
set = single_set (insn);
if (! set)
{
*************** visit_expression (insn, block)
*** 450,456 ****
defs_to_undefined (insn);
break;
}
!
/* Simplify source operands to whatever known values they
may have. */
if (GET_CODE (src0) == REG
--- 474,486 ----
defs_to_undefined (insn);
break;
}
!
! /* Determine the mode for the operation before we simplify
! our arguments to constants. */
! mode = GET_MODE (src0);
! if (mode == VOIDmode)
! mode = GET_MODE (src1);
!
/* Simplify source operands to whatever known values they
may have. */
if (GET_CODE (src0) == REG
*************** visit_expression (insn, block)
*** 463,472 ****
/* See if the simplifier can determine if this operation
computes a constant value. */
- mode = GET_MODE (src0);
- if (mode == VOIDmode)
- mode = GET_MODE (src1);
-
simplified = simplify_relational_operation (GET_CODE (src),
mode, src0, src1);
break;
--- 493,498 ----
*************** visit_expression (insn, block)
*** 476,481 ****
--- 502,508 ----
case '1':
{
rtx src0 = XEXP (src, 0);
+ enum machine_mode mode0 = GET_MODE (src0);
/* If the operand is undefined, then the result is undefined. */
if (GET_CODE (src0) == REG
*************** visit_expression (insn, block)
*** 496,502 ****
simplified = simplify_unary_operation (GET_CODE (src),
GET_MODE (src),
src0,
! GET_MODE (src0));
break;
}
--- 523,529 ----
simplified = simplify_unary_operation (GET_CODE (src),
GET_MODE (src),
src0,
! mode0);
break;
}