[tree-ssa] Enhance statement checking & fix minor buglets

law@redhat.com law@redhat.com
Sat Feb 28 03:20:00 GMT 2004


This patch enhances our statement checking to verify that the operands
of unary and binary operators are gimple values.

Not surprisingly this exposed a few bugs in our optimizers.  This patch
addresses those issues (though the builtin folding as a whole worries
me -- there may be more lurking problems in it).

We might seriously consider a parallel set of is_gimple_blah predicates
which check their operands.  That would make building a statement
checker a lot easier.  It would also mean that passes could check for
gimple expressions after combining and simplifying complex expressions.

While sorting through these issues I saw cases where it would be useful
to also handle MINUS_EXPR in is_gimple_min_invariant in the same way
it handles PLUS_EXPR.  It's not terribly important, so if someone objects
to adding it at this point I'd pull that code out without arguing.

Bootstrapped and regression tested.  i686-pc-linux-gnu.

	* tree-cfg.c (verify_expr): Do not walk down into types.
	Expand checking to verify that unary/binary operators have
	gimple operands.
	* tree-ssa-ccp.c (ccp_fold_builtin, case BUILT_IN_STRLEN): Do not
	create non-gimple code.  Similarly for BUILTIN_IN_STRCPY and
	BUILT_IN_STRNCPY.
	* tree-ssa-phiopt.c (conditional_replacement): Do not create
	non-gimple code.
	* tree-ssa-dom.c (simplify_rhs_and_lookup_avail_expr): Likewise.

	* tree-simple.c (is_gimple_min_invariant): Subtraction of a 
	constant from a constant pointer is a gimple invariant as well.
	* tree-ssa-operands.c (get_expr_operands): Handle subtraction
	of a constant from a constant pointer too.
	

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.276
diff -c -p -r1.1.4.276 tree-cfg.c
*** tree-cfg.c	27 Feb 2004 20:18:44 -0000	1.1.4.276
--- tree-cfg.c	28 Feb 2004 00:41:03 -0000
*************** verify_expr (tree *tp, int *walk_subtree
*** 2925,2930 ****
--- 2925,2933 ----
  {
    tree t = *tp, x;
  
+   if (TYPE_P (t))
+     *walk_subtrees = 0;
+ 
    switch (TREE_CODE (t))
      {
      case SSA_NAME:
*************** verify_expr (tree *tp, int *walk_subtree
*** 2956,2961 ****
--- 2959,3046 ----
        if (TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE)
  	{
  	  error ("non-boolean used in condition");
+ 	  return x;
+ 	}
+       break;
+ 
+     case NOP_EXPR:
+     case CONVERT_EXPR:
+     case FIX_TRUNC_EXPR:
+     case FIX_CEIL_EXPR:
+     case FIX_FLOOR_EXPR:
+     case FIX_ROUND_EXPR:
+     case FLOAT_EXPR:
+     case NEGATE_EXPR:
+     case ABS_EXPR:
+     case BIT_NOT_EXPR:
+     case NON_LVALUE_EXPR:
+     case TRUTH_NOT_EXPR:
+       x = TREE_OPERAND (t, 0);
+       /* We check for constants explicitly since they are not considered
+ 	 gimple invariants if they overflowed.  */
+       if (TREE_CODE_CLASS (TREE_CODE (x)) != 'c'
+ 	  && !is_gimple_val (x))
+ 	{
+ 	  error ("Invalid operand to unary operator");
+ 	  return x;
+ 	}
+       break;
+ 
+     case REALPART_EXPR:
+     case IMAGPART_EXPR:
+       break;
+ 
+     case LT_EXPR:
+     case LE_EXPR:
+     case GT_EXPR:
+     case GE_EXPR:
+     case EQ_EXPR:
+     case NE_EXPR:
+     case UNORDERED_EXPR:
+     case ORDERED_EXPR:
+     case UNLT_EXPR:
+     case UNLE_EXPR:
+     case UNGT_EXPR:
+     case UNGE_EXPR:
+     case UNEQ_EXPR:
+     case PLUS_EXPR:
+     case MINUS_EXPR:
+     case MULT_EXPR:
+     case TRUNC_DIV_EXPR:
+     case CEIL_DIV_EXPR:
+     case FLOOR_DIV_EXPR:
+     case ROUND_DIV_EXPR:
+     case TRUNC_MOD_EXPR:
+     case CEIL_MOD_EXPR:
+     case FLOOR_MOD_EXPR:
+     case ROUND_MOD_EXPR:
+     case RDIV_EXPR:
+     case EXACT_DIV_EXPR:
+     case MIN_EXPR:
+     case MAX_EXPR:
+     case LSHIFT_EXPR:
+     case RSHIFT_EXPR:
+     case LROTATE_EXPR:
+     case RROTATE_EXPR:
+     case BIT_IOR_EXPR:
+     case BIT_XOR_EXPR:
+     case BIT_AND_EXPR:
+       x = TREE_OPERAND (t, 0);
+       /* We check for constants explicitly since they are not considered
+ 	 gimple invariants if they overflowed.  */
+       if (TREE_CODE_CLASS (TREE_CODE (x)) != 'c'
+ 	  && !is_gimple_val (x))
+ 	{
+ 	  error ("Invalid operand to binary operator");
+ 	  return x;
+ 	}
+       x = TREE_OPERAND (t, 1);
+       /* We check for constants explicitly since they are not considered
+ 	 gimple invariants if they overflowed.  */
+       if (TREE_CODE_CLASS (TREE_CODE (x)) != 'c'
+ 	  && !is_gimple_val (x))
+ 	{
+ 	  error ("Invalid operand to binary operator");
  	  return x;
  	}
        break;
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.71
diff -c -p -r1.1.4.71 tree-simple.c
*** tree-simple.c	20 Feb 2004 15:58:31 -0000	1.1.4.71
--- tree-simple.c	28 Feb 2004 00:41:04 -0000
*************** is_gimple_min_invariant (tree t)
*** 296,301 ****
--- 296,302 ----
        return TREE_INVARIANT (t);
  
      case PLUS_EXPR:
+     case MINUS_EXPR:
        {
  	tree op0, op1;
  
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.144
diff -c -p -r1.1.2.144 tree-ssa-ccp.c
*** tree-ssa-ccp.c	27 Feb 2004 22:21:58 -0000	1.1.2.144
--- tree-ssa-ccp.c	28 Feb 2004 00:41:07 -0000
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2088,2103 ****
  
    BITMAP_XFREE (visited);
  
    switch (DECL_FUNCTION_CODE (callee))
      {
      case BUILT_IN_STRLEN:
        /* Convert from the internal "sizetype" type to "size_t".  */
!       if (strlen_val[0] && size_type_node)
! 	return convert (size_type_node, strlen_val[0]);
        return strlen_val[0];
      case BUILT_IN_STRCPY:
        return simplify_builtin_strcpy (arglist, strlen_val[1]);
      case BUILT_IN_STRNCPY:
        return simplify_builtin_strncpy (arglist, strlen_val[1]);
      case BUILT_IN_FPUTS:
        return simplify_builtin_fputs (arglist,
--- 2088,2121 ----
  
    BITMAP_XFREE (visited);
  
+   /* FIXME.  All this code looks dangerous in the sense that it might
+      create non-gimple expressions.  */
    switch (DECL_FUNCTION_CODE (callee))
      {
      case BUILT_IN_STRLEN:
        /* Convert from the internal "sizetype" type to "size_t".  */
!       if (strlen_val[0]
! 	  && size_type_node)
! 	{
! 	  tree new = convert (size_type_node, strlen_val[0]);
! 
! 	  /* If the result is not a valid gimple value, or not a cast
! 	     of a valid gimple value, then we can not use the result.  */
! 	  if (is_gimple_val (new)
! 	      || (is_gimple_cast (new)
! 		  && is_gimple_val (TREE_OPERAND (new, 0))))
! 	    return new;
! 	  else
! 	    return NULL_TREE;
! 	}
        return strlen_val[0];
      case BUILT_IN_STRCPY:
+       if (strlen_val[1]
+ 	  && is_gimple_val (strlen_val[1]))
        return simplify_builtin_strcpy (arglist, strlen_val[1]);
      case BUILT_IN_STRNCPY:
+       if (strlen_val[1]
+ 	  && is_gimple_val (strlen_val[1]))
        return simplify_builtin_strncpy (arglist, strlen_val[1]);
      case BUILT_IN_FPUTS:
        return simplify_builtin_fputs (arglist,
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.142
diff -c -p -r1.1.2.142 tree-ssa-dom.c
*** tree-ssa-dom.c	26 Feb 2004 19:22:16 -0000	1.1.2.142
--- tree-ssa-dom.c	28 Feb 2004 00:41:13 -0000
*************** simplify_rhs_and_lookup_avail_expr (stru
*** 1694,1700 ****
  		      || ((TREE_CODE_CLASS (TREE_CODE (t)) == '2'
  			   || TREE_CODE_CLASS (TREE_CODE (t)) == '<')
  			  && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
! 			  && TREE_CONSTANT (TREE_OPERAND (t, 1))))
  		    result = update_rhs_and_lookup_avail_expr
  		      (stmt, t, &bd->avail_exprs, ann, insert);
  		}
--- 1694,1701 ----
  		      || ((TREE_CODE_CLASS (TREE_CODE (t)) == '2'
  			   || TREE_CODE_CLASS (TREE_CODE (t)) == '<')
  			  && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
! 			  && (TREE_CODE (TREE_OPERAND (t, 1)) == SSA_NAME
! 			      || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 1))) == 'c')))
  		    result = update_rhs_and_lookup_avail_expr
  		      (stmt, t, &bd->avail_exprs, ann, insert);
  		}
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-operands.c,v
retrieving revision 1.1.2.12
diff -c -p -r1.1.2.12 tree-ssa-operands.c
*** tree-ssa-operands.c	25 Feb 2004 00:13:10 -0000	1.1.2.12
--- tree-ssa-operands.c	28 Feb 2004 00:41:14 -0000
*************** get_expr_operands (tree stmt, tree *expr
*** 960,966 ****
  	 cannot just abort here.  If we were absolutely certain that we
  	 do handle all valid cases, then we could just do nothing here.
  	 That seems optimistic, so attempt to do something logical... */
!       else if (TREE_CODE (ptr) == PLUS_EXPR
  	       && TREE_CODE (TREE_OPERAND (ptr, 0)) == ADDR_EXPR
  	       && TREE_CODE (TREE_OPERAND (ptr, 1)) == INTEGER_CST)
  	{
--- 960,966 ----
  	 cannot just abort here.  If we were absolutely certain that we
  	 do handle all valid cases, then we could just do nothing here.
  	 That seems optimistic, so attempt to do something logical... */
!       else if ((TREE_CODE (ptr) == PLUS_EXPR || TREE_CODE (ptr) == MINUS_EXPR)
  	       && TREE_CODE (TREE_OPERAND (ptr, 0)) == ADDR_EXPR
  	       && TREE_CODE (TREE_OPERAND (ptr, 1)) == INTEGER_CST)
  	{
Index: tree-ssa-phiopt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-phiopt.c,v
retrieving revision 1.1.2.6
diff -c -p -r1.1.2.6 tree-ssa-phiopt.c
*** tree-ssa-phiopt.c	26 Feb 2004 18:51:51 -0000	1.1.2.6
--- tree-ssa-phiopt.c	28 Feb 2004 00:41:15 -0000
*************** conditional_replacement (basic_block bb,
*** 221,226 ****
--- 221,230 ----
      {
        cond = invert_truthvalue (cond);
    
+       if (is_gimple_cast (cond)
+ 	  && !is_gimple_val (TREE_OPERAND (cond, 0)))
+ 	return false;
+ 
        new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
                      PHI_RESULT (phi), cond);
      }





More information about the Gcc-patches mailing list