[tree-ssa] Avoiding useless jumps

law@redhat.com law@redhat.com
Wed May 21 05:18:00 GMT 2003


The gimplification process used by the tree-ssa branch converts IF_STMTs
into COND_EXPRs.  An interesting side effect is that the code in 
c-semantics.c and stmt.c to generate efficient code for IF statements
is bypassed -- and the code to expand COND_EXPR didn't have similar
capabilities.

The net result was generation of a *ton* of useless jump to the next
statement insns when the THEN or ELSE clause of a COND_EXPR was
empty.  In fact, this accounts for nearly half of the increase in
insns generated by the gimplification process when compiling combine.c!


	* expr.c (expand_expr, case COND_EXPR): Avoid useless RTL generation
	when the THEN or ELSE arm is empty.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.31
diff -c -3 -p -r1.467.2.31 expr.c
*** expr.c	13 May 2003 02:16:31 -0000	1.467.2.31
--- expr.c	21 May 2003 04:05:59 -0000
*************** expand_expr (exp, target, tmode, modifie
*** 9051,9087 ****
  	  }
  	else
  	  {
! 	    op1 = gen_label_rtx ();
! 	    jumpifnot (TREE_OPERAND (exp, 0), op0);
  
! 	    start_cleanup_deferral ();
  
! 	    /* One branch of the cond can be void, if it never returns. For
! 	       example A ? throw : E  */
! 	    if (temp != 0
! 		&& TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
! 	      store_expr (TREE_OPERAND (exp, 1), temp,
! 			  modifier == EXPAND_STACK_PARM ? 2 : 0);
! 	    else
! 	      expand_expr (TREE_OPERAND (exp, 1),
! 			   ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
! 	    end_cleanup_deferral ();
! 	    emit_queue ();
! 	    emit_jump_insn (gen_jump (op1));
! 	    emit_barrier ();
! 	    emit_label (op0);
! 	    start_cleanup_deferral ();
! 	    if (temp != 0
! 		&& TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
! 	      store_expr (TREE_OPERAND (exp, 2), temp,
! 			  modifier == EXPAND_STACK_PARM ? 2 : 0);
  	    else
! 	      expand_expr (TREE_OPERAND (exp, 2),
  			   ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
  	  }
  
  	end_cleanup_deferral ();
! 
  	emit_queue ();
  	emit_label (op1);
  	OK_DEFER_POP;
--- 9051,9134 ----
  	  }
  	else
  	  {
! 	    /* This used heavily by gimplified code, so it's worth
! 	       trying to be semi-intelligent about the code we generate.   */
  
! 	    /* Expand the condition and jump around THEN clause if the
! 	       condition does not hold.
  
! 	       However, if the THEN clause is empty, then jump around
! 	       the ELSE clause if the condition does hold.
! 
! 	       If both the THEN and the ELSE are empty, then just emit
! 	       the condition (in case it had embedded side effects).  */
! 	    if (! IS_EMPTY_STMT (TREE_OPERAND (exp, 1)))
! 	      jumpifnot (TREE_OPERAND (exp, 0), op0);
! 	    else if (! IS_EMPTY_STMT (TREE_OPERAND (exp, 2)))
! 	      {
! 	        op1 = gen_label_rtx ();
! 	        jumpif (TREE_OPERAND (exp, 0), op1);
! 	      }
  	    else
! 	      expand_expr (TREE_OPERAND (exp, 0), 
  			   ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
+ 	      
+ 	    /* Generate RTL for the THEN clause if it is not empty.  */
+ 	    if (! IS_EMPTY_STMT (TREE_OPERAND (exp, 1)))
+ 	      {
+ 		start_cleanup_deferral ();
+ 
+ 		/* One branch of the cond can be void, if it never returns. For
+ 		   example A ? throw : E  */
+ 		if (temp != 0
+ 		    && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
+ 		  store_expr (TREE_OPERAND (exp, 1), temp,
+ 			      modifier == EXPAND_STACK_PARM ? 2 : 0);
+ 		else
+ 		  expand_expr (TREE_OPERAND (exp, 1),
+ 			       ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
+ 		end_cleanup_deferral ();
+ 		emit_queue ();
+ 
+ 		/* If the ELSE clause was not empty, then we need to
+ 		   jump around it.  */
+ 		if (! IS_EMPTY_STMT (TREE_OPERAND (exp, 2)))
+ 		  {
+ 		    op1 = gen_label_rtx ();
+ 		    emit_jump_insn (gen_jump (op1));
+ 		    emit_barrier ();
+ 		  }
+ 
+ 		/* This is the target of the jump around the THEN block.  */
+ 		emit_label (op0);
+ 	      }
+ 
+ 	    /* Generate RTL for the ELSE clause if it is not empty.  */
+ 	    if (! IS_EMPTY_STMT (TREE_OPERAND (exp, 2)))
+ 	      {
+ 		start_cleanup_deferral ();
+ 
+ 		if (temp != 0
+ 		    && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
+ 		  store_expr (TREE_OPERAND (exp, 2), temp,
+ 			      modifier == EXPAND_STACK_PARM ? 2 : 0);
+ 		else
+ 		  expand_expr (TREE_OPERAND (exp, 2),
+ 			       ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
+ 
+ 		end_cleanup_deferral ();
+  
+ 	        emit_queue ();
+ 		emit_label (op1);
+ 	      }
+ 	    OK_DEFER_POP;
+ 	    return temp;
  	  }
  
+ 	/* We fall into this path from earlier in the COND_EXPR case, so this
+ 	   can not be pulled up into the trailing else clause.  */
  	end_cleanup_deferral ();
!  
  	emit_queue ();
  	emit_label (op1);
  	OK_DEFER_POP;





More information about the Gcc-patches mailing list