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]

Patch: fix crash with multiple commutative operands


Hi,

Below is an update to this patch:
http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01432.html
I renamed n_swapped into n_permutation and move it's calculation out of a
loop, I also added some comments.
Bootstrapped and regression tested on i686-linux and m68k-linux.

bye, Roman

2001-09-07  Roman Zippel  <zippel@linux-m68k.org>

	* reload.c (find_reloads): try all possible combinations for all
	commutable operands

Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.159
diff -u -c -p -r1.159 reload.c
*** reload.c	2001/08/31 14:49:31	1.159
--- reload.c	2001/09/06 21:13:26
*************** find_reloads (insn, replace, ind_levels,
*** 2437,2442 ****
--- 2437,2443 ----
    char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
    int this_alternative_matches[MAX_RECOG_OPERANDS];
    int swapped;
+   int n_permutation;
    int goal_alternative[MAX_RECOG_OPERANDS];
    int this_alternative_number;
    int goal_alternative_number = 0;
*************** find_reloads (insn, replace, ind_levels,
*** 2449,2455 ****
    char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
    int goal_alternative_swapped;
    int best;
!   int commutative;
    char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
    rtx substed_operand[MAX_RECOG_OPERANDS];
    rtx body = PATTERN (insn);
--- 2450,2457 ----
    char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
    int goal_alternative_swapped;
    int best;
!   int commutative[MAX_RECOG_OPERANDS];
!   int commutative_op[MAX_RECOG_OPERANDS/2];
    char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
    rtx substed_operand[MAX_RECOG_OPERANDS];
    rtx body = PATTERN (insn);
*************** find_reloads (insn, replace, ind_levels,
*** 2515,2528 ****
  	  noperands * sizeof (enum machine_mode));
    memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));

-   commutative = -1;
-
    /* If we will need to know, later, whether some pair of operands
       are the same, we must compare them now and save the result.
       Reloading the base and index registers will clobber them
       and afterward they will fail to match.  */
-
    for (i = 0; i < noperands; i++)
      {
        register char *p;
        register int c;
--- 2517,2530 ----
  	  noperands * sizeof (enum machine_mode));
    memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));

    /* If we will need to know, later, whether some pair of operands
       are the same, we must compare them now and save the result.
       Reloading the base and index registers will clobber them
       and afterward they will fail to match.  */
    for (i = 0; i < noperands; i++)
+     commutative[i] = i;
+
+   for (i = 0, j = 0; i < noperands; i++)
      {
        register char *p;
        register int c;
*************** find_reloads (insn, replace, ind_levels,
*** 2543,2553 ****
  	    modified[i] = RELOAD_READ_WRITE;
  	  else if (c == '%')
  	    {
! 	      /* The last operand should not be marked commutative.  */
! 	      if (i == noperands - 1)
  		abort ();

! 	      commutative = i;
  	    }
  	  else if (c >= '0' && c <= '9')
  	    {
--- 2545,2558 ----
  	    modified[i] = RELOAD_READ_WRITE;
  	  else if (c == '%')
  	    {
! 	      /* The last operand and two consecutive operands should not be
! 	          marked commutative.  */
! 	      if (i == noperands - 1 || commutative[i] != i)
  		abort ();

! 	      commutative_op[j++] = i;
! 	      commutative[i] = i + 1;
! 	      commutative[i + 1] = i;
  	    }
  	  else if (c >= '0' && c <= '9')
  	    {
*************** find_reloads (insn, replace, ind_levels,
*** 2560,2591 ****
  	      if (c == i)
  		abort ();

  	      /* If C can be commuted with C+1, and C might need to match I,
  		 then C+1 might also need to match I.  */
! 	      if (commutative >= 0)
! 		{
! 		  if (c == commutative || c == commutative + 1)
! 		    {
! 		      int other = c + (c == commutative ? 1 : -1);
! 		      operands_match[other][i]
! 			= operands_match_p (recog_data.operand[other],
! 					    recog_data.operand[i]);
! 		    }
! 		  if (i == commutative || i == commutative + 1)
! 		    {
! 		      int other = i + (i == commutative ? 1 : -1);
! 		      operands_match[c][other]
! 			= operands_match_p (recog_data.operand[c],
! 					    recog_data.operand[other]);
! 		    }
! 		  /* Note that C is supposed to be less than I.
! 		     No need to consider altering both C and I because in
! 		     that case we would alter one into the other.  */
! 		}
  	    }
  	}
      }

    /* Examine each operand that is a memory reference or memory address
       and reload parts of the addresses into index registers.
       Also here any references to pseudo regs that didn't get hard regs
--- 2565,2595 ----
  	      if (c == i)
  		abort ();

+ 	      if (commutative[i] != i)
+ 		operands_match[c][commutative[i]]
+ 		  = operands_match_p (recog_data.operand[c],
+ 				      recog_data.operand[commutative[i]]);
+
  	      /* If C can be commuted with C+1, and C might need to match I,
  		 then C+1 might also need to match I.  */
! 	      if (commutative[c] != c)
! 		operands_match[commutative[c]][i]
! 		  = operands_match_p (recog_data.operand[commutative[c]],
! 				      recog_data.operand[i]);
! 	      if (commutative[i] != i && commutative[c] != c)
! 		operands_match[commutative[c]][commutative[i]]
! 		  = operands_match_p (recog_data.operand[commutative[c]],
! 				      recog_data.operand[commutative[i]]);
  	    }
  	}
      }

+   /* # of loops needed to test all possible combinations of commutable operands.
+      for a single loop, keep n_permutation 0 to keep the test below easier.  */
+   n_permutation = 0;
+   if (j)
+     n_permutation = 1 << j;
+
    /* Examine each operand that is a memory reference or memory address
       and reload parts of the addresses into index registers.
       Also here any references to pseudo regs that didn't get hard regs
*************** find_reloads (insn, replace, ind_levels,
*** 2742,2747 ****
--- 2746,2753 ----

    swapped = 0;
    goal_alternative_swapped = 0;
+   for (i = 0; i < noperands; i++)
+     commutative[i] = i;
   try_swapped:

    /* The constraints are made of several alternatives.
*************** find_reloads (insn, replace, ind_levels,
*** 2913,2927 ****
  	  while (*p && (c = *p++) != ',')
  	    switch (c)
  	      {
! 	      case '=':  case '+':  case '*':
  		break;

- 	      case '%':
- 		/* The last operand should not be marked commutative.  */
- 		if (i != noperands - 1)
- 		  commutative = i;
- 		break;
-
  	      case '?':
  		reject += 6;
  		break;
--- 2919,2927 ----
  	  while (*p && (c = *p++) != ',')
  	    switch (c)
  	      {
! 	      case '=':  case '+':  case '*': case '%':
  		break;

  	      case '?':
  		reject += 6;
  		break;
*************** find_reloads (insn, replace, ind_levels,
*** 2949,2967 ****
  		   only a single reload insn will be needed to make
  		   the two operands win.  As a result, this alternative
  		   may be rejected when it is actually desirable.)  */
! 		if ((swapped && (c != commutative || i != commutative + 1))
! 		    /* If we are matching as if two operands were swapped,
! 		       also pretend that operands_match had been computed
! 		       with swapped.
! 		       But if I is the second of those and C is the first,
! 		       don't exchange them, because operands_match is valid
! 		       only on one side of its diagonal.  */
! 		    ? (operands_match
! 		       [(c == commutative || c == commutative + 1)
! 		       ? 2 * commutative + 1 - c : c]
! 		       [(i == commutative || i == commutative + 1)
! 		       ? 2 * commutative + 1 - i : i])
! 		    : operands_match[c][i])
  		  {
  		    /* If we are matching a non-offsettable address where an
  		       offsettable address was expected, then we must reject
--- 2949,2958 ----
  		   only a single reload insn will be needed to make
  		   the two operands win.  As a result, this alternative
  		   may be rejected when it is actually desirable.)  */
! 		/* If we are matching as if two operands were swapped,
! 		   also pretend that operands_match had been computed
! 		   with swapped. */
! 		if (operands_match[commutative[c]][commutative[i]])
  		  {
  		    /* If we are matching a non-offsettable address where an
  		       offsettable address was expected, then we must reject
*************** find_reloads (insn, replace, ind_levels,
*** 3430,3440 ****
        if (losers == 0)
  	{
  	  /* Unswap these so that they are never swapped at `finish'.  */
! 	  if (commutative >= 0)
  	    {
! 	      recog_data.operand[commutative] = substed_operand[commutative];
! 	      recog_data.operand[commutative + 1]
! 		= substed_operand[commutative + 1];
  	    }
  	  for (i = 0; i < noperands; i++)
  	    {
--- 3421,3442 ----
        if (losers == 0)
  	{
  	  /* Unswap these so that they are never swapped at `finish'.  */
! 	  if (swapped)
  	    {
! 	      int s = swapped;
! 	      s ^= s >> 1;
!
! 	      for (i = 0; s; i++, s >>= 1)
! 		{
! 		  register int c;
!
! 		  if (!(s & 1))
! 		    continue;
! 		  c = commutative_op[i];
!
! 		  recog_data.operand[c] = substed_operand[c];
! 		  recog_data.operand[c + 1] = substed_operand[c + 1];
! 		}
  	    }
  	  for (i = 0; i < noperands; i++)
  	    {
*************** find_reloads (insn, replace, ind_levels,
*** 3484,3523 ****
       then we need to try each alternative twice,
       the second time matching those two operands
       as if we had exchanged them.
!      To do this, really exchange them in operands.

!      If we have just tried the alternatives the second time,
!      return operands to normal and drop through.  */
!
!   if (commutative >= 0)
      {
!       swapped = !swapped;
!       if (swapped)
  	{
  	  register enum reg_class tclass;
- 	  register int t;
-
- 	  recog_data.operand[commutative] = substed_operand[commutative + 1];
- 	  recog_data.operand[commutative + 1] = substed_operand[commutative];

! 	  tclass = preferred_class[commutative];
! 	  preferred_class[commutative] = preferred_class[commutative + 1];
! 	  preferred_class[commutative + 1] = tclass;
!
! 	  t = pref_or_nothing[commutative];
! 	  pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
! 	  pref_or_nothing[commutative + 1] = t;

  	  memcpy (constraints, recog_data.constraints,
  		  noperands * sizeof (char *));
  	  goto try_swapped;
  	}
-       else
- 	{
- 	  recog_data.operand[commutative] = substed_operand[commutative];
- 	  recog_data.operand[commutative + 1]
- 	    = substed_operand[commutative + 1];
- 	}
      }

    /* The operands don't meet the constraints.
--- 3486,3535 ----
       then we need to try each alternative twice,
       the second time matching those two operands
       as if we had exchanged them.
!      To do this, really exchange them in operands. */

!   if (++swapped <= n_permutation)
      {
!       int s, t;
!       rtx x;
!
!       /* In every loop we just swap a single pair of operands, so that in the
! 	 last loop we only need to swap a single pair back to return operands
! 	 to normal and drop through.  */
!       s = swapped - 1;
!       if (swapped < n_permutation)
! 	s ^= swapped;
!       s ^= s >> 1;
!
!       for (i = 0; s; i++, s >>= 1)
! 	if (s & 1)
! 	  break;
!       i = commutative_op[i];
!
!       t = commutative[i];
!       commutative[i] = commutative[i + 1];
!       commutative[i + 1] = t;
!
!       x = recog_data.operand[i];
!       recog_data.operand[i] = recog_data.operand[i + 1];
!       recog_data.operand[i + 1] = x;
!
!       if (swapped < n_permutation)
  	{
  	  register enum reg_class tclass;

! 	  tclass = preferred_class[i];
! 	  preferred_class[i] = preferred_class[i + 1];
! 	  preferred_class[i + 1] = tclass;
!
! 	  t = pref_or_nothing[i];
! 	  pref_or_nothing[i] = pref_or_nothing[i + 1];
! 	  pref_or_nothing[i + 1] = t;

  	  memcpy (constraints, recog_data.constraints,
  		  noperands * sizeof (char *));
  	  goto try_swapped;
  	}
      }

    /* The operands don't meet the constraints.
*************** find_reloads (insn, replace, ind_levels,
*** 3564,3588 ****

    if (goal_alternative_swapped)
      {
!       register rtx tem;

!       tem = substed_operand[commutative];
!       substed_operand[commutative] = substed_operand[commutative + 1];
!       substed_operand[commutative + 1] = tem;
!       tem = recog_data.operand[commutative];
!       recog_data.operand[commutative] = recog_data.operand[commutative + 1];
!       recog_data.operand[commutative + 1] = tem;
!       tem = *recog_data.operand_loc[commutative];
!       *recog_data.operand_loc[commutative]
! 	= *recog_data.operand_loc[commutative + 1];
!       *recog_data.operand_loc[commutative + 1] = tem;
!
!       for (i = 0; i < n_reloads; i++)
  	{
! 	  if (rld[i].opnum == commutative)
! 	    rld[i].opnum = commutative + 1;
! 	  else if (rld[i].opnum == commutative + 1)
! 	    rld[i].opnum = commutative;
  	}
      }

--- 3576,3612 ----

    if (goal_alternative_swapped)
      {
!       int s = goal_alternative_swapped;
!       s ^= s >> 1;

!       for (i = 0; s; i++, s >>= 1)
  	{
! 	  register int c;
! 	  register rtx tem;
!
! 	  if (!(s & 1))
! 	    continue;
! 	  c = commutative_op[i];
!
! 	  tem = substed_operand[c];
! 	  substed_operand[c] = substed_operand[c + 1];
! 	  substed_operand[c + 1] = tem;
!
! 	  tem = recog_data.operand[c];
! 	  recog_data.operand[c] = recog_data.operand[c + 1];
! 	  recog_data.operand[c + 1] = tem;
!
! 	  tem = *recog_data.operand_loc[c];
! 	  *recog_data.operand_loc[c] = *recog_data.operand_loc[c + 1];
! 	  *recog_data.operand_loc[c + 1] = tem;
!
! 	  for (j = 0; j < n_reloads; j++)
! 	    {
! 	      if (rld[j].opnum == c)
! 		rld[j].opnum = c + 1;
! 	      else if (rld[j].opnum == c + 1)
! 		rld[j].opnum = c;
! 	    }
  	}
      }



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