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]

[3.4-BIB] find_split_point tweek


Hi,
this patch teach combine how to split read-modify-write instruction into
read-modify that is needed for proper combining of some instructions dealing
with memory operands.
The testcase requires previous patch to work but it should help even
without it in some cases.

Honza

/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -msse2 -mfpmath=sse -march=athlon" } */
/* { dg-final { scan-assembler "sqrtss" } } */
float a;
t()
{
 double b=a;
 a=sqrt(b);
}
Sun Nov 10 22:41:29 CET 2002  Jan Hubicka  <jh@suse.cz>
	* combine.c (find_split_point):  Accept extra argument dest;
	split away the store from instruction when profitable; split away
	memory operands.
	(different_mem): New function.
	(try_combine): Handle reversal when find_split_point splits away set
	destination.
*** combine.c.old	Sun Nov 10 20:03:37 2002
--- combine.c	Sun Nov 10 22:36:33 2002
*************** static int contains_muldiv	PARAMS ((rtx)
*** 345,351 ****
  static rtx try_combine		PARAMS ((rtx, rtx, rtx, int *));
  static void undo_all		PARAMS ((void));
  static void undo_commit		PARAMS ((void));
! static rtx *find_split_point	PARAMS ((rtx *, rtx));
  static rtx subst		PARAMS ((rtx, rtx, rtx, int, int));
  static rtx combine_simplify_rtx	PARAMS ((rtx, enum machine_mode, int, int));
  static rtx simplify_if_then_else  PARAMS ((rtx));
--- 345,351 ----
  static rtx try_combine		PARAMS ((rtx, rtx, rtx, int *));
  static void undo_all		PARAMS ((void));
  static void undo_commit		PARAMS ((void));
! static rtx *find_split_point	PARAMS ((rtx *, rtx, int *));
  static rtx subst		PARAMS ((rtx, rtx, rtx, int, int));
  static rtx combine_simplify_rtx	PARAMS ((rtx, enum machine_mode, int, int));
  static rtx simplify_if_then_else  PARAMS ((rtx));
*************** static int insn_cuid		PARAMS ((rtx));
*** 400,405 ****
--- 400,406 ----
  static void record_promoted_value PARAMS ((rtx, rtx));
  static rtx reversed_comparison  PARAMS ((rtx, enum machine_mode, rtx, rtx));
  static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx));
+ static int different_mem 	PARAMS ((rtx *, void *));
  
  /* Substitute NEWVAL, an rtx expression, into INTO, a place in some
     insn.  The substitution can be undone by undo_all.  If INTO is already
*************** try_combine (i3, i2, i1, new_direct_jump
*** 1527,1532 ****
--- 1528,1534 ----
    rtx temp;
    rtx link;
    int i;
+   int dest;
  
    /* Exit early if one of the insns involved can't be used for
       combinations.  */
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2217,2227 ****
  		REG_N_SETS (REGNO (new_i2_dest))++;
  	    }
  	}
  
        /* If we can split it and use I2DEST, go ahead and see if that
  	 helps things be recognized.  Verify that none of the registers
  	 are set between I2 and I3.  */
!       if (insn_code_number < 0 && (split = find_split_point (&newpat, i3)) != 0
  #ifdef HAVE_cc0
  	  && GET_CODE (i2dest) == REG
  #endif
--- 2219,2230 ----
  		REG_N_SETS (REGNO (new_i2_dest))++;
  	    }
  	}
+       dest = 0;
  
        /* If we can split it and use I2DEST, go ahead and see if that
  	 helps things be recognized.  Verify that none of the registers
  	 are set between I2 and I3.  */
!       if (insn_code_number < 0 && (split = find_split_point (&newpat, i3, &dest)) != 0
  #ifdef HAVE_cc0
  	  && GET_CODE (i2dest) == REG
  #endif
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2286,2292 ****
  	    }
  #endif
  
! 	  newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
  	  SUBST (*split, newdest);
  	  i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
  
--- 2289,2298 ----
  	    }
  #endif
  
! 	  if (!dest)
! 	    newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
! 	  else
! 	    newi2pat = gen_rtx_SET (VOIDmode, *split, newdest);
  	  SUBST (*split, newdest);
  	  i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
  
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2294,2299 ****
--- 2300,2314 ----
  	     don't use one now.  */
  	  if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
  	    insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+ 	  if (dest && insn_code_number >=0)
+ 	    {
+ 	      rtx t = newpat;
+ 	      int t2 = insn_code_number;
+ 	      newpat = newi2pat;
+ 	      newi2pat = t;
+ 	      insn_code_number = i2_code_number;
+ 	      i2_code_number = t2;
+ 	    }
  	}
      }
  
*************** undo_commit ()
*** 2894,2912 ****
      }
    undobuf.undos = 0;
  }
- 
  
  /* Find the innermost point within the rtx at LOC, possibly LOC itself,
     where we have an arithmetic expression and return that point.  LOC will
!    be inside INSN.
  
     try_combine will call this function to see if an insn can be split into
     two insns.  */
  
  static rtx *
! find_split_point (loc, insn)
       rtx *loc;
       rtx insn;
  {
    rtx x = *loc;
    enum rtx_code code = GET_CODE (x);
--- 2909,2948 ----
      }
    undobuf.undos = 0;
  }
  
+ /* Subroutine of find_split_point; called through for_each_rtx.
+    Look for MEM expression different from one pointed to by data.
+    On sucess rewrite data and return 1  */
+ static int
+ different_mem (xp, data)
+      rtx *xp;
+      void *data;
+ {
+   if (GET_CODE (*xp) == MEM)
+     {
+       rtx **store = (rtx **)data;
+       if (!rtx_equal_p (**store, *xp))
+ 	{
+ 	  *store = xp;
+ 	  return 1;
+ 	}
+     }
+   return 0;
+ }
+ 
  /* Find the innermost point within the rtx at LOC, possibly LOC itself,
     where we have an arithmetic expression and return that point.  LOC will
!    be inside INSN.  Set DEST to 1 when LOC is the destination of SET so
!    we need to emit instructions in reversed order.
  
     try_combine will call this function to see if an insn can be split into
     two insns.  */
  
  static rtx *
! find_split_point (loc, insn, dest)
       rtx *loc;
       rtx insn;
+      int *dest;
  {
    rtx x = *loc;
    enum rtx_code code = GET_CODE (x);
*************** find_split_point (loc, insn)
*** 2926,2932 ****
        if (GET_CODE (SUBREG_REG (x)) == MEM)
  	return loc;
  #endif
!       return find_split_point (&SUBREG_REG (x), insn);
  
      case MEM:
  #ifdef HAVE_lo_sum
--- 2962,2968 ----
        if (GET_CODE (SUBREG_REG (x)) == MEM)
  	return loc;
  #endif
!       return find_split_point (&SUBREG_REG (x), insn, dest);
  
      case MEM:
  #ifdef HAVE_lo_sum
*************** find_split_point (loc, insn)
*** 3008,3014 ****
  			 && (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (XEXP (x, 0), 0))))
  			     == 'o')))
  	    return &XEXP (XEXP (x, 0), 0);
! 	}
        break;
  
      case SET:
--- 3044,3052 ----
  			 && (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (XEXP (x, 0), 0))))
  			     == 'o')))
  	    return &XEXP (XEXP (x, 0), 0);
! 	} /* Otherwise try to split away the MEM operand itself.  */
!       else
! 	return loc;
        break;
  
      case SET:
*************** find_split_point (loc, insn)
*** 3028,3039 ****
  #endif
  
        /* See if we can split SET_SRC as it stands.  */
!       split = find_split_point (&SET_SRC (x), insn);
        if (split && split != &SET_SRC (x))
! 	return split;
  
        /* See if we can split SET_DEST as it stands.  */
!       split = find_split_point (&SET_DEST (x), insn);
        if (split && split != &SET_DEST (x))
  	return split;
  
--- 3066,3095 ----
  #endif
  
        /* See if we can split SET_SRC as it stands.  */
!       split = find_split_point (&SET_SRC (x), insn, dest);
        if (split && split != &SET_SRC (x))
! 	{
! 	  /* Some architectures (i386) do have load-execute instructions, but
! 	     it is probably uncommong to have execute-store instructions, so
! 	     it is better to split load-execute-store instruction into
! 	     load followed by execute-write.
! 	     Exception may be the case where two different MEM input operands
! 	     are present.  Then we should split load-load-execute-store into
! 	     load followed by load-execute-store.  */
! 	  if (GET_CODE (*split) == MEM
! 	      && GET_CODE (SET_DEST (x)) == MEM)
! 	    {
! 	      rtx *sp = &SET_DEST (x);
! 
! 	      if (!for_each_rtx (&SET_SRC (x), different_mem, &sp))
! 		*dest = 1;
! 	      return sp;
! 	    }
! 	  return split;
! 	}
  
        /* See if we can split SET_DEST as it stands.  */
!       split = find_split_point (&SET_DEST (x), insn, dest);
        if (split && split != &SET_DEST (x))
  	return split;
  
*************** find_split_point (loc, insn)
*** 3053,3060 ****
  	  HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
  	  unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
  	  unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
! 	  rtx dest = XEXP (SET_DEST (x), 0);
! 	  enum machine_mode mode = GET_MODE (dest);
  	  unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
  
  	  if (BITS_BIG_ENDIAN)
--- 3109,3116 ----
  	  HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
  	  unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
  	  unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
! 	  rtx destexp = XEXP (SET_DEST (x), 0);
! 	  enum machine_mode mode = GET_MODE (destexp);
  	  unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
  
  	  if (BITS_BIG_ENDIAN)
*************** find_split_point (loc, insn)
*** 3062,3079 ****
  
  	  if (src == mask)
  	    SUBST (SET_SRC (x),
! 		   gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
  	  else
  	    SUBST (SET_SRC (x),
  		   gen_binary (IOR, mode,
! 			       gen_binary (AND, mode, dest,
  					   gen_int_mode (~(mask << pos),
  							 mode)),
  			       GEN_INT (src << pos)));
  
! 	  SUBST (SET_DEST (x), dest);
  
! 	  split = find_split_point (&SET_SRC (x), insn);
  	  if (split && split != &SET_SRC (x))
  	    return split;
  	}
--- 3118,3135 ----
  
  	  if (src == mask)
  	    SUBST (SET_SRC (x),
! 		   gen_binary (IOR, mode, destexp, GEN_INT (src << pos)));
  	  else
  	    SUBST (SET_SRC (x),
  		   gen_binary (IOR, mode,
! 			       gen_binary (AND, mode, destexp,
  					   gen_int_mode (~(mask << pos),
  							 mode)),
  			       GEN_INT (src << pos)));
  
! 	  SUBST (SET_DEST (x), destexp);
  
! 	  split = find_split_point (&SET_SRC (x), insn, dest);
  	  if (split && split != &SET_SRC (x))
  	    return split;
  	}
*************** find_split_point (loc, insn)
*** 3109,3115 ****
  	      if (extraction != 0)
  		{
  		  SUBST (SET_SRC (x), extraction);
! 		  return find_split_point (loc, insn);
  		}
  	    }
  	  break;
--- 3165,3171 ----
  	      if (extraction != 0)
  		{
  		  SUBST (SET_SRC (x), extraction);
! 		  return find_split_point (loc, insn, dest);
  		}
  	    }
  	  break;
*************** find_split_point (loc, insn)
*** 3131,3137 ****
  						    XEXP (SET_SRC (x), 0),
  						    GEN_INT (pos))));
  
! 	      split = find_split_point (&SET_SRC (x), insn);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
--- 3187,3193 ----
  						    XEXP (SET_SRC (x), 0),
  						    GEN_INT (pos))));
  
! 	      split = find_split_point (&SET_SRC (x), insn, dest);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
*************** find_split_point (loc, insn)
*** 3190,3196 ****
  				   GEN_INT (pos)),
  				  GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
  
! 	      split = find_split_point (&SET_SRC (x), insn);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
--- 3246,3252 ----
  				   GEN_INT (pos)),
  				  GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
  
! 	      split = find_split_point (&SET_SRC (x), insn, dest);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
*************** find_split_point (loc, insn)
*** 3205,3211 ****
  					       - len - pos)),
  		      GEN_INT (GET_MODE_BITSIZE (mode) - len)));
  
! 	      split = find_split_point (&SET_SRC (x), insn);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
--- 3261,3267 ----
  					       - len - pos)),
  		      GEN_INT (GET_MODE_BITSIZE (mode) - len)));
  
! 	      split = find_split_point (&SET_SRC (x), insn, dest);
  	      if (split && split != &SET_SRC (x))
  		return split;
  	    }
*************** find_split_point (loc, insn)
*** 3251,3257 ****
  					      GET_MODE (x),
  					      XEXP (XEXP (x, 0), 0),
  					      XEXP (XEXP (x, 1), 0))));
! 	  return find_split_point (loc, insn);
  	}
  
        /* Many RISC machines have a large set of logical insns.  If the
--- 3307,3313 ----
  					      GET_MODE (x),
  					      XEXP (XEXP (x, 0), 0),
  					      XEXP (XEXP (x, 1), 0))));
! 	  return find_split_point (loc, insn, dest);
  	}
  
        /* Many RISC machines have a large set of logical insns.  If the
*************** find_split_point (loc, insn)
*** 3274,3287 ****
      {
      case 'b':			/* This is ZERO_EXTRACT and SIGN_EXTRACT.  */
      case '3':
!       split = find_split_point (&XEXP (x, 2), insn);
        if (split)
  	return split;
        /* ... fall through ...  */
      case '2':
      case 'c':
      case '<':
!       split = find_split_point (&XEXP (x, 1), insn);
        if (split)
  	return split;
        /* ... fall through ...  */
--- 3330,3343 ----
      {
      case 'b':			/* This is ZERO_EXTRACT and SIGN_EXTRACT.  */
      case '3':
!       split = find_split_point (&XEXP (x, 2), insn, dest);
        if (split)
  	return split;
        /* ... fall through ...  */
      case '2':
      case 'c':
      case '<':
!       split = find_split_point (&XEXP (x, 1), insn, dest);
        if (split)
  	return split;
        /* ... fall through ...  */
*************** find_split_point (loc, insn)
*** 3291,3297 ****
        if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND)
  	return &XEXP (x, 0);
  
!       split = find_split_point (&XEXP (x, 0), insn);
        if (split)
  	return split;
        return loc;
--- 3347,3353 ----
        if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND)
  	return &XEXP (x, 0);
  
!       split = find_split_point (&XEXP (x, 0), insn, dest);
        if (split)
  	return split;
        return loc;


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