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] Bugfix: Additional parameter for canonicalize comparison


Hi Richard,

is the attached patch ok for ARM?

Bye,

-Andreas-

2012-12-12  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* target.def: Define canonicalize_comparison hook.
	* targhooks.h (default_canonicalize_comparison): New prototype.
	* targhooks.c (default_canonicalize_comparison): New function.
	* doc/tm.texi: Add documentation for the new target hook.
	* doc/tm.texi.in: Likewise.
	* combine.c (try_combine): Adjust to use the target hook.
	* config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
	definition.
	* config/alpha/alpha.c (alpha_canonicalize_comparison): New
	function.
	(TARGET_CANONICALIZE_COMPARISON): New macro definition.
	* config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
	prototype.
	* config/arm/arm.c (arm_canonicalize_comparison): Add new
	parameter.
	(TARGET_CANONICALIZE_COMPARISON): New macro definition.
	* config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
	definition.
	* config/s390/s390-protos.h (s390_canonicalize_comparison): Remove
	prototype.
	* config/s390/s390.c (s390_canonicalize_comparison): Add new
	parameter.
	(TARGET_CANONICALIZE_COMPARISON): New macro definition.
	* config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
	definition.
	* config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
	prototype.
	* config/sh/sh.c (sh_canonicalize_comparison): Add new prototype.  New
	function overloading the old one.
	(TARGET_CANONICALIZE_COMPARISON): New macro definition.
	* config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
	definition.
	* config/spu/spu.c (spu_canonicalize_comparison): New function.
	(TARGET_CANONICALIZE_COMPARISON): New macro definition.
	* config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
	definition.

---
 gcc/combine.c                 |   19 ++++++-!!!
 gcc/config/alpha/alpha.c      |   27 ++++++++++++++++
 gcc/config/alpha/alpha.h      |   20 ------------
 gcc/config/arm/arm-protos.h   |    1 
 gcc/config/arm/arm.c          |   68 ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 gcc/config/arm/arm.h          |    3 -
 gcc/config/s390/s390-protos.h |    1 
 gcc/config/s390/s390.c        |   13 +++!!!!!
 gcc/config/s390/s390.h        |    4 --
 gcc/config/sh/sh-protos.h     |    2 -
 gcc/config/sh/sh.c            |   34 +++++++++++!!!!!!!!!!
 gcc/config/sh/sh.h            |    4 --
 gcc/config/spu/spu.c          |   17 ++++++++++
 gcc/config/spu/spu.h          |   12 -------
 gcc/doc/tm.texi               |   20 !!!!!!!!!!!!
 gcc/doc/tm.texi.in            |   20 !!!!!!!!!!!!
 gcc/target.def                |    8 ++++
 gcc/targhooks.h               |    2 +
 18 files changed, 94 insertions(+), 50 deletions(-), 131 modifications(!)

Index: gcc/combine.c
===================================================================
*** gcc/combine.c.orig
--- gcc/combine.c
*************** static rtx gen_lowpart_or_truncate (enum
*** 494,499 ****
--- 494,510 ----
  static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
  
  
+ /* Convenience wrapper for the canonicalize_comparison target hook.
+    Target hooks cannot use enum rtx_code.  */
+ static inline void
+ target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
+ 				bool op0_preserve_value)
+ {
+   int code_int = (int)*code;
+   targetm.canonicalize_comparison (&code_int, op0, op1, op0_preserve_value);
+   *code = (enum rtx_code)code_int;
+ }
+ 
  /* Try to split PATTERN found in INSN.  This returns NULL_RTX if
     PATTERN can not be split.  Otherwise, it returns an insn sequence.
     This is a wrapper around split_insns which ensures that the
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2944,2952 ****
  	  compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
  	  compare_code = simplify_compare_const (compare_code,
  						 op0, &op1);
! #ifdef CANONICALIZE_COMPARISON
! 	  CANONICALIZE_COMPARISON (compare_code, op0, op1);
! #endif
  	}
  
        /* Do the rest only if op1 is const0_rtx, which may be the
--- 2955,2961 ----
  	  compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
  	  compare_code = simplify_compare_const (compare_code,
  						 op0, &op1);
! 	  target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
  	}
  
        /* Do the rest only if op1 is const0_rtx, which may be the
*************** simplify_comparison (enum rtx_code code,
*** 11959,11969 ****
  	    }
  	}
  
- #ifdef CANONICALIZE_COMPARISON
    /* If this machine only supports a subset of valid comparisons, see if we
       can convert an unsupported one into a supported one.  */
!   CANONICALIZE_COMPARISON (code, op0, op1);
! #endif
  
    *pop0 = op0;
    *pop1 = op1;
--- 11968,11976 ----
  	    }
  	}
  
    /* If this machine only supports a subset of valid comparisons, see if we
       can convert an unsupported one into a supported one.  */
!   target_canonicalize_comparison (&code, &op0, &op1, 0);
  
    *pop0 = op0;
    *pop1 = op1;
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c.orig
--- gcc/config/alpha/alpha.c
*************** alpha_conditional_register_usage (void)
*** 9683,9688 ****
--- 9683,9712 ----
      for (i = 32; i < 63; i++)
        fixed_regs[i] = call_used_regs[i] = 1;
  }
+ 
+ /* Canonicalize a comparison from one we don't have to one we do have.  */
+ 
+ static void
+ alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ 			       bool op0_preserve_value)
+ {
+   if (!op0_preserve_value
+       && (*code == GE || *code == GT || *code == GEU || *code == GTU)
+       && (REG_P (*op1) || *op1 == const0_rtx))
+     {
+       rtx tem = *op0;
+       *op0 = *op1;
+       *op1 = tem;
+       *code = (int)swap_condition ((enum rtx_code)*code);
+     }
+ 
+   if ((*code == LT || *code == LTU)
+       && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
+     {
+       *code = *code == LT ? LE : LEU;
+       *op1 = GEN_INT (255);
+     }
+ }
  
  /* Initialize the GCC target structure.  */
  #if TARGET_ABI_OPEN_VMS
*************** alpha_conditional_register_usage (void)
*** 9850,9855 ****
--- 9874,9882 ----
  #undef TARGET_CONDITIONAL_REGISTER_USAGE
  #define TARGET_CONDITIONAL_REGISTER_USAGE alpha_conditional_register_usage
  
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  
Index: gcc/config/alpha/alpha.h
===================================================================
*** gcc/config/alpha/alpha.h.orig
--- gcc/config/alpha/alpha.h
*************** do {									     \
*** 922,947 ****
  #define FLOAT_STORE_FLAG_VALUE(MODE) \
    REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
  
- /* Canonicalize a comparison from one we don't have to one we do have.  */
- 
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
-   do {									\
-     if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \
- 	&& (REG_P (OP1) || (OP1) == const0_rtx))		\
-       {									\
- 	rtx tem = (OP0);						\
- 	(OP0) = (OP1);							\
- 	(OP1) = tem;							\
- 	(CODE) = swap_condition (CODE);					\
-       }									\
-     if (((CODE) == LT || (CODE) == LTU)					\
- 	&& CONST_INT_P (OP1) && INTVAL (OP1) == 256)			\
-       {									\
- 	(CODE) = (CODE) == LT ? LE : LEU;				\
- 	(OP1) = GEN_INT (255);						\
-       }									\
-   } while (0)
- 
  /* Specify the machine mode that pointers have.
     After generation of rtl, the compiler makes no further distinction
     between pointers and any other objects of this machine mode.  */
--- 922,927 ----
Index: gcc/config/arm/arm-protos.h
===================================================================
*** gcc/config/arm/arm-protos.h.orig
--- gcc/config/arm/arm-protos.h
*************** extern int const_ok_for_op (HOST_WIDE_IN
*** 53,59 ****
  extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
  extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
  			       HOST_WIDE_INT, rtx, rtx, int);
- extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
  extern int legitimate_pic_operand_p (rtx);
  extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
  extern rtx legitimize_tls_address (rtx, rtx);
--- 53,58 ----
Index: gcc/config/arm/arm.c
===================================================================
*** gcc/config/arm/arm.c.orig
--- gcc/config/arm/arm.c
*************** static int arm_cortex_a5_branch_cost (bo
*** 269,275 ****
  
  static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
  					     const unsigned char *sel);
! 
  
  /* Table of machine attributes.  */
  static const struct attribute_spec arm_attribute_table[] =
--- 269,276 ----
  
  static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
  					     const unsigned char *sel);
! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! 					 bool op0_preserve_value);
  
  /* Table of machine attributes.  */
  static const struct attribute_spec arm_attribute_table[] =
*************** static const struct attribute_spec arm_a
*** 626,631 ****
--- 627,636 ----
  #define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
    arm_vectorize_vec_perm_const_ok
  
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON \
+   arm_canonicalize_comparison
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  /* Obstack for minipool constant handling.  */
*************** arm_gen_constant (enum rtx_code code, en
*** 3543,3550 ****
     This can be done for a few constant compares, where we can make the
     immediate value easier to load.  */
  
! enum rtx_code
! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
  {
    enum machine_mode mode;
    unsigned HOST_WIDE_INT i, maxval;
--- 3548,3556 ----
     This can be done for a few constant compares, where we can make the
     immediate value easier to load.  */
  
! static void
! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! 			     bool op0_preserve_value)
  {
    enum machine_mode mode;
    unsigned HOST_WIDE_INT i, maxval;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3563,3577 ****
      {
        rtx tem;
  
!       if (code == GT || code == LE
! 	  || (!TARGET_ARM && (code == GTU || code == LEU)))
  	{
  	  /* Missing comparison.  First try to use an available
  	     comparison.  */
  	  if (CONST_INT_P (*op1))
  	    {
  	      i = INTVAL (*op1);
! 	      switch (code)
  		{
  		case GT:
  		case LE:
--- 3569,3583 ----
      {
        rtx tem;
  
!       if (*code == GT || *code == LE
! 	  || (!TARGET_ARM && (*code == GTU || *code == LEU)))
  	{
  	  /* Missing comparison.  First try to use an available
  	     comparison.  */
  	  if (CONST_INT_P (*op1))
  	    {
  	      i = INTVAL (*op1);
! 	      switch (*code)
  		{
  		case GT:
  		case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3579,3585 ****
  		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
  		    {
  		      *op1 = GEN_INT (i + 1);
! 		      return code == GT ? GE : LT;
  		    }
  		  break;
  		case GTU:
--- 3585,3592 ----
  		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
  		    {
  		      *op1 = GEN_INT (i + 1);
! 		      *code = *code == GT ? GE : LT;
! 		      return;
  		    }
  		  break;
  		case GTU:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3588,3594 ****
  		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
  		    {
  		      *op1 = GEN_INT (i + 1);
! 		      return code == GTU ? GEU : LTU;
  		    }
  		  break;
  		default:
--- 3595,3602 ----
  		      && arm_const_double_by_immediates (GEN_INT (i + 1)))
  		    {
  		      *op1 = GEN_INT (i + 1);
! 		      *code = *code == GTU ? GEU : LTU;
! 		      return;
  		    }
  		  break;
  		default:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3597,3615 ****
  	    }
  
  	  /* If that did not work, reverse the condition.  */
! 	  tem = *op0;
! 	  *op0 = *op1;
! 	  *op1 = tem;
! 	  return swap_condition (code);
  	}
! 
!       return code;
      }
  
    /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
       with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
       to facilitate possible combining with a cmp into 'ands'.  */
!   if (mode == SImode
        && GET_CODE (*op0) == ZERO_EXTEND
        && GET_CODE (XEXP (*op0, 0)) == SUBREG
        && GET_MODE (XEXP (*op0, 0)) == QImode
--- 3605,3626 ----
  	    }
  
  	  /* If that did not work, reverse the condition.  */
! 	  if (!op0_preserve_value)
! 	    {
! 	      tem = *op0;
! 	      *op0 = *op1;
! 	      *op1 = tem;
! 	      *code = (int)swap_condition ((enum rtx_code)*code);
! 	    }
  	}
!       return;
      }
  
    /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
       with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
       to facilitate possible combining with a cmp into 'ands'.  */
!   if (!op0_preserve_value
!       && mode == SImode
        && GET_CODE (*op0) == ZERO_EXTEND
        && GET_CODE (XEXP (*op0, 0)) == SUBREG
        && GET_MODE (XEXP (*op0, 0)) == QImode
*************** arm_canonicalize_comparison (enum rtx_co
*** 3624,3638 ****
    if (!CONST_INT_P (*op1)
        || const_ok_for_arm (INTVAL (*op1))
        || const_ok_for_arm (- INTVAL (*op1)))
!     return code;
  
    i = INTVAL (*op1);
  
!   switch (code)
      {
      case EQ:
      case NE:
!       return code;
  
      case GT:
      case LE:
--- 3635,3649 ----
    if (!CONST_INT_P (*op1)
        || const_ok_for_arm (INTVAL (*op1))
        || const_ok_for_arm (- INTVAL (*op1)))
!     return;
  
    i = INTVAL (*op1);
  
!   switch (*code)
      {
      case EQ:
      case NE:
!       return;
  
      case GT:
      case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3640,3646 ****
  	  && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
  	{
  	  *op1 = GEN_INT (i + 1);
! 	  return code == GT ? GE : LT;
  	}
        break;
  
--- 3651,3658 ----
  	  && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
  	{
  	  *op1 = GEN_INT (i + 1);
! 	  *code = *code == GT ? GE : LT;
! 	  return;
  	}
        break;
  
*************** arm_canonicalize_comparison (enum rtx_co
*** 3650,3656 ****
  	  && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
  	{
  	  *op1 = GEN_INT (i - 1);
! 	  return code == GE ? GT : LE;
  	}
        break;
  
--- 3662,3669 ----
  	  && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
  	{
  	  *op1 = GEN_INT (i - 1);
! 	  *code = *code == GE ? GT : LE;
! 	  return;
  	}
        break;
  
*************** arm_canonicalize_comparison (enum rtx_co
*** 3660,3666 ****
  	  && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
  	{
  	  *op1 = GEN_INT (i + 1);
! 	  return code == GTU ? GEU : LTU;
  	}
        break;
  
--- 3673,3680 ----
  	  && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
  	{
  	  *op1 = GEN_INT (i + 1);
! 	  *code = *code == GTU ? GEU : LTU;
! 	  return;
  	}
        break;
  
*************** arm_canonicalize_comparison (enum rtx_co
*** 3670,3684 ****
  	  && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
  	{
  	  *op1 = GEN_INT (i - 1);
! 	  return code == GEU ? GTU : LEU;
  	}
        break;
  
      default:
        gcc_unreachable ();
      }
- 
-   return code;
  }
  
  
--- 3684,3697 ----
  	  && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
  	{
  	  *op1 = GEN_INT (i - 1);
! 	  *code = *code == GEU ? GTU : LEU;
! 	  return;
  	}
        break;
  
      default:
        gcc_unreachable ();
      }
  }
  
  
*************** bool
*** 26979,26985 ****
  arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
  {
    enum rtx_code code = GET_CODE (*comparison);
!   enum rtx_code canonical_code;
    enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) 
      ? GET_MODE (*op2) : GET_MODE (*op1);
  
--- 26992,26998 ----
  arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
  {
    enum rtx_code code = GET_CODE (*comparison);
!   int code_int;
    enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) 
      ? GET_MODE (*op2) : GET_MODE (*op1);
  
*************** arm_validize_comparison (rtx *comparison
*** 26988,26995 ****
    if (code == UNEQ || code == LTGT)
      return false;
  
!   canonical_code = arm_canonicalize_comparison (code, op1, op2);
!   PUT_CODE (*comparison, canonical_code);
  
    switch (mode)
      {
--- 27001,27009 ----
    if (code == UNEQ || code == LTGT)
      return false;
  
!   code_int = (int)code;
!   arm_canonicalize_comparison (&code_int, op1, op2, 0);
!   PUT_CODE (*comparison, (enum rtx_code)code_int);
  
    switch (mode)
      {
Index: gcc/config/arm/arm.h
===================================================================
*** gcc/config/arm/arm.h.orig
--- gcc/config/arm/arm.h
*************** extern int making_const_table;
*** 2078,2086 ****
     ? reverse_condition_maybe_unordered (code) \
     : reverse_condition (code))
  
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1)				\
-   (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
- 
  /* The arm5 clz instruction returns 32.  */
  #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
  #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
--- 2078,2083 ----
Index: gcc/config/s390/s390-protos.h
===================================================================
*** gcc/config/s390/s390-protos.h.orig
--- gcc/config/s390/s390-protos.h
*************** extern int tls_symbolic_operand (rtx);
*** 58,64 ****
  extern bool s390_match_ccmode (rtx, enum machine_mode);
  extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
  extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
- extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
  extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
  extern void s390_emit_jump (rtx, rtx);
  extern bool symbolic_reference_mentioned_p (rtx);
--- 58,63 ----
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_select_ccmode (enum rtx_code code, 
*** 745,753 ****
  /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
     that we can implement more efficiently.  */
  
! void
! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
  {
    /* Convert ZERO_EXTRACT back to AND to enable TM patterns.  */
    if ((*code == EQ || *code == NE)
        && *op1 == const0_rtx
--- 745,757 ----
  /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
     that we can implement more efficiently.  */
  
! static void
! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! 			      bool op0_preserve_value)
  {
+   if (op0_preserve_value)
+     return;
+ 
    /* Convert ZERO_EXTRACT back to AND to enable TM patterns.  */
    if ((*code == EQ || *code == NE)
        && *op1 == const0_rtx
*************** s390_canonicalize_comparison (enum rtx_c
*** 894,900 ****
    if (MEM_P (*op0) && REG_P (*op1))
      {
        rtx tem = *op0; *op0 = *op1; *op1 = tem;
!       *code = swap_condition (*code);
      }
  }
  
--- 898,904 ----
    if (MEM_P (*op0) && REG_P (*op1))
      {
        rtx tem = *op0; *op0 = *op1; *op1 = tem;
!       *code = (int)swap_condition ((enum rtx_code)*code);
      }
  }
  
*************** s390_loop_unroll_adjust (unsigned nunrol
*** 11071,11076 ****
--- 11075,11083 ----
  #undef TARGET_UNWIND_WORD_MODE
  #define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
  
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  #include "gt-s390.h"
Index: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig
--- gcc/config/s390/s390.h
*************** do {									\
*** 720,729 ****
     return the mode to be used for the comparison.  */
  #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
  
- /* Canonicalize a comparison from one we don't have to one we do have.  */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
-   s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
- 
  /* Relative costs of operations.  */
  
  /* A C expression for the cost of a branch instruction.  A value of 1
--- 720,725 ----
Index: gcc/config/sh/sh-protos.h
===================================================================
*** gcc/config/sh/sh-protos.h.orig
--- gcc/config/sh/sh-protos.h
*************** extern bool sh_expand_t_scc (rtx *);
*** 159,166 ****
  extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
  extern bool sh_vector_mode_supported_p (enum machine_mode);
  extern bool sh_cfun_trap_exit_p (void);
- extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
- 					enum machine_mode mode = VOIDmode);
  extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
  extern int sh_eval_treg_value (rtx op);
  
--- 159,164 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c.orig
--- gcc/config/sh/sh.c
*************** static int max_mov_insn_displacement (en
*** 314,319 ****
--- 314,322 ----
  static int mov_insn_alignment_mask (enum machine_mode, bool);
  static HOST_WIDE_INT disp_addr_displacement (rtx);
  static bool sequence_insn_p (rtx);
+ static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
+ static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
+ 					enum machine_mode, bool);
  
  static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
  
*************** static const struct attribute_spec sh_at
*** 586,591 ****
--- 589,597 ----
  #undef TARGET_LEGITIMATE_CONSTANT_P
  #define TARGET_LEGITIMATE_CONSTANT_P	sh_legitimate_constant_p
  
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON	sh_canonicalize_comparison
+ 
  /* Machine-specific symbol_ref flags.  */
  #define SYMBOL_FLAG_FUNCVEC_FUNCTION    (SYMBOL_FLAG_MACH_DEP << 0)
  
*************** prepare_move_operands (rtx operands[], e
*** 1909,1920 ****
      }
  }
  
! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
!    This function is also re-used to canonicalize comparisons in cbranch
!    pattern expanders.  */
! void
  sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! 			    enum machine_mode mode)
  {
    /* When invoked from within the combine pass the mode is not specified,
       so try to get it from one of the operands.  */
--- 1915,1928 ----
      }
  }
  
! /* Implement the canonicalize_comparison target hook for the combine
!    pass.  For the target hook this function is invoked via
!    sh_canonicalize_comparison.  This function is also re-used to
!    canonicalize comparisons in cbranch pattern expanders.  */
! static void
  sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! 			    enum machine_mode mode,
! 			    bool op0_preserve_value ATTRIBUTE_UNUSED)
  {
    /* When invoked from within the combine pass the mode is not specified,
       so try to get it from one of the operands.  */
*************** sh_canonicalize_comparison (enum rtx_cod
*** 2008,2013 ****
--- 2016,2034 ----
      }
  }
  
+ /* This function implements the canonicalize_comparison target hook.
+    This wrapper around the internally used sh_canonicalize_comparison
+    function is needed to do the enum rtx_code <-> int conversion.
+    Target hooks cannot use enum rtx_code in its definition.  */
+ static void
+ sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ 			    bool op0_preserve_value)
+ {
+   enum rtx_code tmp_code = (enum rtx_code)*code;
+   sh_canonicalize_comparison (tmp_code, *op0, *op1,
+ 			      VOIDmode, op0_preserve_value);
+   *code = (int)tmp_code;
+ }
  enum rtx_code
  prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
  			  enum rtx_code comparison)
*************** prepare_cbranch_operands (rtx *operands,
*** 2021,2027 ****
    else
      scratch = operands[4];
  
!   sh_canonicalize_comparison (comparison, operands[1], operands[2], mode);
  
    /* Notice that this function is also invoked after reload by
       the cbranchdi4_i pattern, through expand_cbranchdi4.  */
--- 2042,2049 ----
    else
      scratch = operands[4];
  
!   sh_canonicalize_comparison (comparison, operands[1], operands[2],
! 			      mode, false);
  
    /* Notice that this function is also invoked after reload by
       the cbranchdi4_i pattern, through expand_cbranchdi4.  */
Index: gcc/config/sh/sh.h
===================================================================
*** gcc/config/sh/sh.h.orig
--- gcc/config/sh/sh.h
*************** struct sh_args {
*** 1873,1882 ****
     more compact code.  */
  #define SHIFT_COUNT_TRUNCATED (0)
  
- /* CANONICALIZE_COMPARISON macro for the combine pass.  */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
-   sh_canonicalize_comparison ((CODE), (OP0), (OP1))
- 
  /* All integers have the same format so truncation is easy.  */
  /* But SHmedia must sign-extend DImode when truncating to SImode.  */
  #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
--- 1873,1878 ----
Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c.orig
--- gcc/config/spu/spu.c
*************** spu_output_mi_thunk (FILE *file, tree th
*** 7095,7100 ****
--- 7095,7114 ----
    final_end_function ();
  }
  
+ /* Canonicalize a comparison from one we don't have to one we do have.  */
+ static void
+ spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ 			     bool op0_preserve_value)
+ {
+   if (!op0_preserve_value
+       && (*code == LE || *code == LT || *code == LEU || *code == LTU))
+     {
+       rtx tem = *op0;
+       *op0 = *op1;
+       *op1 = tem;
+       *code = (int)swap_condition ((enum rtx_code)*code);
+     }
+ }
  
  /*  Table of machine attributes.  */
  static const struct attribute_spec spu_attribute_table[] =
*************** static const struct attribute_spec spu_a
*** 7308,7313 ****
--- 7322,7330 ----
  #undef TARGET_DELAY_VARTRACK
  #define TARGET_DELAY_VARTRACK true
  
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  #include "gt-spu.h"
Index: gcc/config/spu/spu.h
===================================================================
*** gcc/config/spu/spu.h.orig
--- gcc/config/spu/spu.h
*************** do {									\
*** 520,537 ****
  
  #define NO_IMPLICIT_EXTERN_C 1
  
- /* Canonicalize a comparison from one we don't have to one we do have.  */
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
-   do {                                                                    \
-     if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) == LTU)) \
-       {                                                                   \
-         rtx tem = (OP0);                                                  \
-         (OP0) = (OP1);                                                    \
-         (OP1) = tem;                                                      \
-         (CODE) = swap_condition (CODE);                                   \
-       }                                                                   \
-   } while (0)
- 
  
  /* Address spaces.  */
  #define ADDR_SPACE_EA	1
--- 520,525 ----
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in.orig
--- gcc/doc/tm.texi.in
*************** You should define this macro if and only
*** 5928,5952 ****
  in @file{@var{machine}-modes.def}.
  @end defmac
  
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
  On some machines not all possible comparisons are defined, but you can
  convert an invalid comparison into a valid one.  For example, the Alpha
  does not have a @code{GT} comparison, but you can use an @code{LT}
  comparison instead and swap the order of the operands.
  
! On such machines, define this macro to be a C statement to do any
! required conversions.  @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively.  You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
  
  GCC will not assume that the comparison resulting from this macro is
  valid but will see if the resulting insn matches a pattern in the
  @file{md} file.
  
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
  
  @defmac REVERSIBLE_CC_MODE (@var{mode})
  A C expression whose value is one if it is always safe to reverse a
--- 5928,5954 ----
  in @file{@var{machine}-modes.def}.
  @end defmac
  
! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
  On some machines not all possible comparisons are defined, but you can
  convert an invalid comparison into a valid one.  For example, the Alpha
  does not have a @code{GT} comparison, but you can use an @code{LT}
  comparison instead and swap the order of the operands.
  
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively.  If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons.  E.g. the implementation is not
! allowed to swap operands in that case.
  
  GCC will not assume that the comparison resulting from this macro is
  valid but will see if the resulting insn matches a pattern in the
  @file{md} file.
  
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
  
  @defmac REVERSIBLE_CC_MODE (@var{mode})
  A C expression whose value is one if it is always safe to reverse a
Index: gcc/target.def
===================================================================
*** gcc/target.def.orig
--- gcc/target.def
*************** DEFHOOK
*** 2877,2882 ****
--- 2877,2890 ----
   enum unwind_info_type, (void),
   default_debug_unwind_info)
  
+ /* The code parameter should be of type enum rtx_code but this is not
+    defined at this time.  */
+ DEFHOOK
+ (canonicalize_comparison,
+  "",
+  void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
+  default_canonicalize_comparison)
+ 
  DEFHOOKPOD
  (atomic_test_and_set_trueval,
   "This value should be set if the result written by\
Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h.orig
--- gcc/targhooks.h
*************** extern unsigned char default_class_max_n
*** 179,184 ****
--- 179,186 ----
  
  extern enum unwind_info_type default_debug_unwind_info (void);
  
+ extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
+ 
  extern int default_label_align_after_barrier_max_skip (rtx);
  extern int default_loop_align_max_skip (rtx);
  extern int default_label_align_max_skip (rtx);
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi.orig
--- gcc/doc/tm.texi
*************** You should define this macro if and only
*** 6024,6048 ****
  in @file{@var{machine}-modes.def}.
  @end defmac
  
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
  On some machines not all possible comparisons are defined, but you can
  convert an invalid comparison into a valid one.  For example, the Alpha
  does not have a @code{GT} comparison, but you can use an @code{LT}
  comparison instead and swap the order of the operands.
  
! On such machines, define this macro to be a C statement to do any
! required conversions.  @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively.  You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
  
  GCC will not assume that the comparison resulting from this macro is
  valid but will see if the resulting insn matches a pattern in the
  @file{md} file.
  
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
  
  @defmac REVERSIBLE_CC_MODE (@var{mode})
  A C expression whose value is one if it is always safe to reverse a
--- 6024,6050 ----
  in @file{@var{machine}-modes.def}.
  @end defmac
  
! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int *@var{code}, rtx *@var{op0}, rtx *@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
  On some machines not all possible comparisons are defined, but you can
  convert an invalid comparison into a valid one.  For example, the Alpha
  does not have a @code{GT} comparison, but you can use an @code{LT}
  comparison instead and swap the order of the operands.
  
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively.  If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons.  E.g. the implementation is not
! allowed to swap operands in that case.
  
  GCC will not assume that the comparison resulting from this macro is
  valid but will see if the resulting insn matches a pattern in the
  @file{md} file.
  
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
  
  @defmac REVERSIBLE_CC_MODE (@var{mode})
  A C expression whose value is one if it is always safe to reverse a


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