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]

[PATCH] ifcvt: Handle INSV patterns properly when a temp reg is needed


Hi,

when the if conversion step optimizes something like:

if (x)
  y = c1;
else
  y = c2;

it introduces a temporary register for calculating the value for y without jumps. 
Even if y = c1 is an INSV pattern ifcvt replaces c1 with the temporary register without asking
recog whether the insn stays valid. On S/390 we allow only MEMs or immediates as
source in INSV patterns. Hence we get an "unrecognizable insn" in such cases.

ifcvt uses the noce_emit_move function for moving the temporary to the target
location. This function performs several checks for the structure of the source rtx
if the resulting insn couldn't be recognized but doesn't care about 'unusual'
destinations. The attached patch adds a check for ZERO_EXTRACT as destination and
calls store_bit_field to emit the move instruction. This fixes the failure on s390x.

As it seems due to this patch store_bit_field encounters rtxs which it didn't had to
deal with before. This revealed a store_bit_field bug when handling paradoxical subregs.
I've fixed this with another patch which is a prerequisite for this one:
http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01793.html

Bootstrapped on s390 and s390x with gcc 4.1 and gcc 4.2.
No testsuite regressions.

I will bootstrap and test this patch on i686 as well.

OK for mainline and 4.1?

Bye,

-Andreas-


2006-03-31  Andreas Krebbel  <krebbel1@de.ibm.com>

	* ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting
	move would be an INSV insn.


2006-03-31  Andreas Krebbel  <krebbel1@de.ibm.com>

	* gcc.c-torture/compile/20060331-1.c: Added.


Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c.orig	2006-03-31 13:10:17.000000000 +0200
--- gcc/ifcvt.c	2006-03-31 13:10:31.000000000 +0200
*************** noce_emit_move_insn (rtx x, rtx y)
*** 702,748 ****
        end_sequence();
  
        if (recog_memoized (insn) <= 0)
! 	switch (GET_RTX_CLASS (GET_CODE (y)))
! 	  {
! 	  case RTX_UNARY:
! 	    ot = code_to_optab[GET_CODE (y)];
! 	    if (ot)
! 	      {
! 		start_sequence ();
! 		target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
! 		if (target != NULL_RTX)
! 		  {
! 		    if (target != x)
! 		      emit_move_insn (x, target);
! 		    seq = get_insns ();
! 		  }
! 		end_sequence ();
! 	      }
! 	    break;
! 
! 	  case RTX_BIN_ARITH:
! 	  case RTX_COMM_ARITH:
! 	    ot = code_to_optab[GET_CODE (y)];
! 	    if (ot)
! 	      {
! 		start_sequence ();
! 		target = expand_binop (GET_MODE (y), ot,
! 				       XEXP (y, 0), XEXP (y, 1),
! 				       x, 0, OPTAB_DIRECT);
! 		if (target != NULL_RTX)
! 		  {
! 		    if (target != x)
! 		      emit_move_insn (x, target);
! 		    seq = get_insns ();
! 		  }
! 		end_sequence ();
! 	      }
! 	    break;
  
! 	  default:
! 	    break;
! 	  }
  
        emit_insn (seq);
        return;
      }
--- 702,760 ----
        end_sequence();
  
        if (recog_memoized (insn) <= 0)
! 	{
! 	  if (GET_CODE (x) == ZERO_EXTRACT)
! 	    {
! 	      rtx op = XEXP (x, 0);
! 	      unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
! 	      unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
  
! 	      store_bit_field (op, size, start, GET_MODE (x), y);
! 	      return;
! 	    }
  
+ 	  switch (GET_RTX_CLASS (GET_CODE (y)))
+ 	    {
+ 	    case RTX_UNARY:
+ 	      ot = code_to_optab[GET_CODE (y)];
+ 	      if (ot)
+ 		{
+ 		  start_sequence ();
+ 		  target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
+ 		  if (target != NULL_RTX)
+ 		    {
+ 		      if (target != x)
+ 			emit_move_insn (x, target);
+ 		      seq = get_insns ();
+ 		    }
+ 		  end_sequence ();
+ 		}
+ 	      break;
+ 	      
+ 	    case RTX_BIN_ARITH:
+ 	    case RTX_COMM_ARITH:
+ 	      ot = code_to_optab[GET_CODE (y)];
+ 	      if (ot)
+ 		{
+ 		  start_sequence ();
+ 		  target = expand_binop (GET_MODE (y), ot,
+ 					 XEXP (y, 0), XEXP (y, 1),
+ 					 x, 0, OPTAB_DIRECT);
+ 		  if (target != NULL_RTX)
+ 		    {
+ 		      if (target != x)
+ 			  emit_move_insn (x, target);
+ 		      seq = get_insns ();
+ 		    }
+ 		  end_sequence ();
+ 		}
+ 	      break;
+ 	      
+ 	    default:
+ 	      break;
+ 	    }
+ 	}
+       
        emit_insn (seq);
        return;
      }
Index: gcc/testsuite/gcc.c-torture/compile/20060331-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/20060331-1.c	2006-03-31 13:10:31.000000000 +0200
***************
*** 0 ****
--- 1,21 ----
+ /* This failed because if conversion didn't handle insv patterns properly.  */
+ 
+ union y
+ {
+   int a;
+   unsigned short b;
+ };
+ 
+ extern void bar (unsigned short u, union y v);
+ 
+ void
+ foo (int check)
+ {
+   union y x;
+ 
+   if (check != 0)
+     x.b = 1;
+   else
+     x.b = 2;
+   bar (x.b, x);
+ }


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