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]
Other format: [Raw text]

[tree-ssa] Improving dominator opts


This patch fixes a couple of the newly added tree-ssa tests.  It addresses
two deficiencies.

First <anything> IOR <nonzero constant> always produces a nonzero value.
Even if we don't know the exact resulting value, knowing the result is
nonzero is worth recording.

Second, signed DIV/MOD by a power of two can be turned into a SHIFT/AND
if we know the dividend has a positive value.  



	* tree-ssa-dom.c (optimize_stmt): Record that the destination of
	a MODIFY_EXPR nonzero if the RHS contains an IOR with a nonzero
	constant.  Turn DIV/MOD by a power of 2 into SHIFT/AND if we know
	dividend is positive.

Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.17
diff -c -3 -p -r1.1.2.17 tree-ssa-dom.c
*** tree-ssa-dom.c	6 Aug 2003 03:16:40 -0000	1.1.2.17
--- tree-ssa-dom.c	12 Aug 2003 14:22:57 -0000
*************** optimize_stmt (block_stmt_iterator si, v
*** 722,737 ****
  	}
      }
  
!   /* If this is an assignment statement, look at both sides for pointer
!      dereferences.
! 
!      If a pointer is dereferenced, then we know that the pointer must be
!      nonnull.  In which case we can enter some equivalences into the
!      hash tables.  */
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      {
        int i;
  
        for (i = 0; i < 2; i++)
  	{
  	  tree t = TREE_OPERAND (stmt, i);
--- 722,737 ----
  	}
      }
  
!   /* Now a few special cases.  Odds are this code will be factored out
!      into several subroutines in the near future.  I'm waiting to see
!      what other cases arise before factoring the code out.  */
    if (TREE_CODE (stmt) == MODIFY_EXPR)
      {
        int i;
  
+       /* Look at both sides for pointer dereferences.  If we find one, then
+          the pointer must be nonnull and we can enter that equivalence into
+ 	 the hash tables.  */
        for (i = 0; i < 2; i++)
  	{
  	  tree t = TREE_OPERAND (stmt, i);
*************** optimize_stmt (block_stmt_iterator si, v
*** 764,769 ****
--- 764,837 ----
  		}
  	    }
  	}
+ 
+       /* IOR of any value with a nonzero value will result in a nonzero
+          value.  Even if we do not know the exact result recording that
+ 	 the result is nonzero is worth the effort.  */
+       if (TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME
+ 	  && TREE_CODE (TREE_OPERAND (stmt, 1)) == BIT_IOR_EXPR
+ 	  && integer_zerop (TREE_OPERAND (TREE_OPERAND (stmt, 1), 1)))
+ 	{
+ 	  tree cond;
+ 	  tree op = TREE_OPERAND (stmt, 0);
+ 
+ 	  cond = build (EQ_EXPR, boolean_type_node, op, null_pointer_node);
+ 	  record_cond_is_false (cond, block_avail_exprs_p, const_and_copies);
+ 
+ 	  cond = build (NE_EXPR, boolean_type_node, op, null_pointer_node);
+ 	  record_cond_is_true (cond, block_avail_exprs_p, const_and_copies);
+ 			  	
+ 	}
+ 
+       /* Transform TRUNC_DIV_EXPR and TRUNC_MOD_EXPR into RSHIFT_EXPR and
+          BIT_AND_EXPR respectively if the first operand is greater than
+ 	 zero and the second operand is an exact power of two.  */
+       if (TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME
+ 	  && (TREE_CODE (TREE_OPERAND (stmt, 1)) == TRUNC_DIV_EXPR
+ 	      || TREE_CODE (TREE_OPERAND (stmt, 1)) == TRUNC_MOD_EXPR)
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (stmt, 1), 0)))
+ 	  && integer_pow2p (TREE_OPERAND (TREE_OPERAND (stmt, 1), 1)))
+         {
+ 	  tree cond, val;
+ 	  tree op = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
+ 
+ 	  cond = build (GT_EXPR, boolean_type_node, op, integer_zero_node);
+ 	  cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
+ 	  val = lookup_avail_expr (cond, block_avail_exprs_p, const_and_copies);
+ 
+ 	  if (val && integer_onep (val))
+ 	    {
+ 	      tree t;
+ 	      tree op0 = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
+ 	      tree op1 = TREE_OPERAND (TREE_OPERAND (stmt, 1), 1);
+ 
+ 	      if (TREE_CODE (TREE_OPERAND (stmt, 1)) == TRUNC_DIV_EXPR)
+ 		t = build (RSHIFT_EXPR, TREE_TYPE (op0), op0,
+ 			   build_int_2 (tree_log2 (op1), 0));
+ 	      else
+ 		t = build (BIT_AND_EXPR, TREE_TYPE (op0), op0,
+ 			   fold (build (MINUS_EXPR, TREE_TYPE (op1),
+ 					op1, integer_one_node)));
+ 
+ 	      /* Remove the old entry from the hash table.  */
+ 	      htab_remove_elt (avail_exprs, stmt);
+ 
+ 	      /* Now update the RHS of the assignment to use the new node.  */
+ 	      TREE_OPERAND (stmt, 1) = t;
+ 
+ 	      /* Now force the updated statement into the hash table.  */
+ 	      lookup_avail_expr (stmt, block_avail_exprs_p, const_and_copies);
+ 
+ 	      /* Annoyingly we now have two entries for this statement in
+ 	         BLOCK_AVAIL_EXPRs.  Luckily we can just pop off the newest
+ 		 entry.  */
+ 	      VARRAY_POP (*block_avail_exprs_p);
+ 
+ 	      /* And make sure we record the fact that we modified this
+ 	         statement.  */
+ 	      ann->modified = 1;
+ 	    }
+         }
      }
  
    /* If STMT is a COND_EXPR and it was modified, then we may know




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