This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

two ssa-ccp fixes



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;
  	    }
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]