public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@arm.com>
To: gcc-patches@gcc.gnu.org
Subject: [1/9] Simplify the implementation of HARD_REG_SET
Date: Mon, 09 Sep 2019 15:54:00 -0000	[thread overview]
Message-ID: <mptr24p8nzh.fsf@arm.com> (raw)
In-Reply-To: <mptv9u18o2j.fsf@arm.com> (Richard Sandiford's message of "Mon,	09 Sep 2019 16:52:04 +0100")

We have two styles of HARD_REG_SET: a single integer based on
HOST_WIDEST_FAST_INT (used when FIRST_PSEUDO_REGISTER is small enough)
or an array of integers.  One of the nice properties of this arrangement
is that:

  void foo (const HARD_REG_SET);

is passed by value as an integer when the set is small enough and
by reference otherwise.

(This is in constrast to "const HARD_REG_SET &", which would always
be passed by reference, and in contrast to passing a structure wrapper
like "struct s { T elts[1]; }" by value, where the structure might be
passed like a T or by reference, depending on the ABI.)

However, one of the disadvantages of using an array is that simple
assignment doesn't work.  We need to use COPY_HARD_REG_SET instead.

This patch uses a structure wrapper around the array, and preserves
the above "nice property" using a new const_hard_reg_set typedef.
The patch also removes the manual unrolling for small array sizes;
I think these days we can rely on the compiler to do that for us.

This meant fixing two port-specific quirks:

- epiphany passed NULL as a HARD_REG_SET whose value doesn't matter.
  The patch passes the NO_REGS set instead.

- ia64 reused TEST_HARD_REG_BIT and SET_HARD_REG_BIT for arrays that
  are bigger than HARD_REG_SET.  The patch just open-codes them.

The patch is probably being too conservative.  Very few places actually
take advantage of the "nice property" above, and we could have a
cleaner interface if we used a structure wrapper for all cases.


2019-09-09  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* hard-reg-set.h (HARD_REG_SET): Define using a typedef rather
	than a #define.  Use a structure rather than an array as the
	fallback definition.  Remove special cases for low array sizes.
	(const_hard_reg_set): New typedef.
	(hard_reg_set_subset_p): Use it instead of "const HARD_REG_SET".
	(hard_reg_set_equal_p, hard_reg_set_intersect_p): Likewise.
	(hard_reg_set_empty_p): Likewise.
	(SET_HARD_REG_BIT): Use a function rather than a macro to
	handle the case in which HARD_REG_SET is a structure.
	(CLEAR_HARD_REG_BIT, TEST_HARD_REG_BIT, CLEAR_HARD_REG_SET)
	(SET_HARD_REG_SET, COPY_HARD_REG_SET, COMPL_HARD_REG_SET)
	(AND_HARD_REG_SET, AND_COMPL_HARD_REG_SET, IOR_HARD_REG_SET)
	(IOR_COMPL_HARD_REG_SET): Likewise.
	(hard_reg_set_iterator::pset): Constify the pointer target.
	(hard_reg_set_iter_init): Take a const_hard_reg_set instead
	of a "const HARD_REG_SET".  Update the handling of non-integer
	HARD_REG_SETs.
	* recog.h: Test HARD_CONST instead of CLEAR_HARD_REG_SET.
	* reload.h: Likewise.
	* rtl.h (choose_hard_reg_mode): Remove unnecessary line break.
	* regs.h (in_hard_reg_set_p): Take a const_hard_reg_set instead
	of a "const HARD_REG_SET".
	(overlaps_hard_reg_set_p, range_overlaps_hard_reg_set_p): Likewise.
	(range_in_hard_reg_set_p): Likewise.
	* ira-costs.c (restrict_cost_classes): Likewise.
	* shrink-wrap.c (move_insn_for_shrink_wrap): Likewise.
	* config/epiphany/resolve-sw-modes.c (pass_resolve_sw_modes::execute):
	Pass a NO_REGS HARD_REG_SET rather than NULL to emit_set_fp_mode.
	* config/ia64/ia64.c (rws_insn): In the CHECKING_P version,
	use unsigned HOST_WIDEST_FAST_INT rather than HARD_REG_ELT_TYPE.
	(rws_insn_set, rws_insn_test): In the CHECKING_P version,
	take an unsigned int and open-code the HARD_REG_SET operations.

Index: gcc/hard-reg-set.h
===================================================================
*** gcc/hard-reg-set.h	2019-09-09 16:53:27.837266363 +0100
--- gcc/hard-reg-set.h	2019-09-09 16:53:27.829266420 +0100
*************** typedef unsigned HOST_WIDEST_FAST_INT HA
*** 42,55 ****
  
  #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT
  
! #define HARD_REG_SET HARD_REG_ELT_TYPE
  
  #else
  
  #define HARD_REG_SET_LONGS \
   ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1)	\
    / HOST_BITS_PER_WIDEST_FAST_INT)
! typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
  
  #endif
  
--- 42,61 ----
  
  #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT
  
! typedef HARD_REG_ELT_TYPE HARD_REG_SET;
! typedef const HARD_REG_SET const_hard_reg_set;
  
  #else
  
  #define HARD_REG_SET_LONGS \
   ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1)	\
    / HOST_BITS_PER_WIDEST_FAST_INT)
! 
! struct HARD_REG_SET
! {
!   HARD_REG_ELT_TYPE elts[HARD_REG_SET_LONGS];
! };
! typedef const HARD_REG_SET &const_hard_reg_set;
  
  #endif
  
*************** #define HARD_CONST(X) ((HARD_REG_ELT_TYP
*** 98,104 ****
  
  #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
  
! #ifdef HARD_REG_SET
  
  #define SET_HARD_REG_BIT(SET, BIT)  \
   ((SET) |= HARD_CONST (1) << (BIT))
--- 104,110 ----
  
  #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
  
! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT
  
  #define SET_HARD_REG_BIT(SET, BIT)  \
   ((SET) |= HARD_CONST (1) << (BIT))
*************** #define AND_HARD_REG_SET(TO, FROM) ((TO)
*** 119,513 ****
  #define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM))
  
  static inline bool
! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
    return (x & ~y) == HARD_CONST (0);
  }
  
  static inline bool
! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
    return x == y;
  }
  
  static inline bool
! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
    return (x & y) != HARD_CONST (0);
  }
  
  static inline bool
! hard_reg_set_empty_p (const HARD_REG_SET x)
  {
    return x == HARD_CONST (0);
  }
  
  #else
  
! #define SET_HARD_REG_BIT(SET, BIT)		\
!   ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT]	\
!    |= HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))
! 
! #define CLEAR_HARD_REG_BIT(SET, BIT)		\
!   ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT]	\
!    &= ~(HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))
! 
! #define TEST_HARD_REG_BIT(SET, BIT)		\
!   (!!((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT]	\
!       & (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))))
! 
! #if FIRST_PSEUDO_REGISTER <= 2*HOST_BITS_PER_WIDEST_FAST_INT
! #define CLEAR_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = 0;						\
!      scan_tp_[1] = 0; } while (0)
! 
! #define SET_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = -1;						\
!      scan_tp_[1] = -1; } while (0)
! 
! #define COPY_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = scan_fp_[0];					\
!      scan_tp_[1] = scan_fp_[1]; } while (0)
! 
! #define COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = ~ scan_fp_[0];				\
!      scan_tp_[1] = ~ scan_fp_[1]; } while (0)
! 
! #define AND_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= scan_fp_[0];				\
!      scan_tp_[1] &= scan_fp_[1]; } while (0)
! 
! #define AND_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= ~ scan_fp_[0];				\
!      scan_tp_[1] &= ~ scan_fp_[1]; } while (0)
! 
! #define IOR_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= scan_fp_[0];				\
!      scan_tp_[1] |= scan_fp_[1]; } while (0)
! 
! #define IOR_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= ~ scan_fp_[0];				\
!      scan_tp_[1] |= ~ scan_fp_[1]; } while (0)
! 
! static inline bool
! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return (x[0] & ~y[0]) == 0 && (x[1] & ~y[1]) == 0;
  }
  
! static inline bool
! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return x[0] == y[0] && x[1] == y[1];
  }
  
! static inline bool
! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return (x[0] & y[0]) != 0 || (x[1] & y[1]) != 0;
  }
  
! static inline bool
! hard_reg_set_empty_p (const HARD_REG_SET x)
  {
!   return x[0] == 0 && x[1] == 0;
  }
  
! #else
! #if FIRST_PSEUDO_REGISTER <= 3*HOST_BITS_PER_WIDEST_FAST_INT
! #define CLEAR_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = 0;						\
!      scan_tp_[1] = 0;						\
!      scan_tp_[2] = 0; } while (0)
! 
! #define SET_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = -1;						\
!      scan_tp_[1] = -1;						\
!      scan_tp_[2] = -1; } while (0)
! 
! #define COPY_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = scan_fp_[0];					\
!      scan_tp_[1] = scan_fp_[1];					\
!      scan_tp_[2] = scan_fp_[2]; } while (0)
! 
! #define COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = ~ scan_fp_[0];				\
!      scan_tp_[1] = ~ scan_fp_[1];				\
!      scan_tp_[2] = ~ scan_fp_[2]; } while (0)
! 
! #define AND_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= scan_fp_[0];				\
!      scan_tp_[1] &= scan_fp_[1];				\
!      scan_tp_[2] &= scan_fp_[2]; } while (0)
! 
! #define AND_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= ~ scan_fp_[0];				\
!      scan_tp_[1] &= ~ scan_fp_[1];				\
!      scan_tp_[2] &= ~ scan_fp_[2]; } while (0)
! 
! #define IOR_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= scan_fp_[0];				\
!      scan_tp_[1] |= scan_fp_[1];				\
!      scan_tp_[2] |= scan_fp_[2]; } while (0)
! 
! #define IOR_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= ~ scan_fp_[0];				\
!      scan_tp_[1] |= ~ scan_fp_[1];				\
!      scan_tp_[2] |= ~ scan_fp_[2]; } while (0)
! 
! static inline bool
! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y)
! {
!   return ((x[0] & ~y[0]) == 0
! 	  && (x[1] & ~y[1]) == 0
! 	  && (x[2] & ~y[2]) == 0);
! }
! 
! static inline bool
! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
  }
  
! static inline bool
! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return ((x[0] & y[0]) != 0
! 	  || (x[1] & y[1]) != 0
! 	  || (x[2] & y[2]) != 0);
  }
  
! static inline bool
! hard_reg_set_empty_p (const HARD_REG_SET x)
  {
!   return x[0] == 0 && x[1] == 0 && x[2] == 0;
  }
  
! #else
! #if FIRST_PSEUDO_REGISTER <= 4*HOST_BITS_PER_WIDEST_FAST_INT
! #define CLEAR_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = 0;						\
!      scan_tp_[1] = 0;						\
!      scan_tp_[2] = 0;						\
!      scan_tp_[3] = 0; } while (0)
! 
! #define SET_HARD_REG_SET(TO)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      scan_tp_[0] = -1;						\
!      scan_tp_[1] = -1;						\
!      scan_tp_[2] = -1;						\
!      scan_tp_[3] = -1; } while (0)
! 
! #define COPY_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = scan_fp_[0];					\
!      scan_tp_[1] = scan_fp_[1];					\
!      scan_tp_[2] = scan_fp_[2];					\
!      scan_tp_[3] = scan_fp_[3]; } while (0)
! 
! #define COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] = ~ scan_fp_[0];				\
!      scan_tp_[1] = ~ scan_fp_[1];				\
!      scan_tp_[2] = ~ scan_fp_[2];				\
!      scan_tp_[3] = ~ scan_fp_[3]; } while (0)
! 
! #define AND_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= scan_fp_[0];				\
!      scan_tp_[1] &= scan_fp_[1];				\
!      scan_tp_[2] &= scan_fp_[2];				\
!      scan_tp_[3] &= scan_fp_[3]; } while (0)
! 
! #define AND_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] &= ~ scan_fp_[0];				\
!      scan_tp_[1] &= ~ scan_fp_[1];				\
!      scan_tp_[2] &= ~ scan_fp_[2];				\
!      scan_tp_[3] &= ~ scan_fp_[3]; } while (0)
! 
! #define IOR_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= scan_fp_[0];				\
!      scan_tp_[1] |= scan_fp_[1];				\
!      scan_tp_[2] |= scan_fp_[2];				\
!      scan_tp_[3] |= scan_fp_[3]; } while (0)
! 
! #define IOR_COMPL_HARD_REG_SET(TO, FROM)  \
! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
!      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
!      scan_tp_[0] |= ~ scan_fp_[0];				\
!      scan_tp_[1] |= ~ scan_fp_[1];				\
!      scan_tp_[2] |= ~ scan_fp_[2];				\
!      scan_tp_[3] |= ~ scan_fp_[3]; } while (0)
! 
! static inline bool
! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return ((x[0] & ~y[0]) == 0
! 	  && (x[1] & ~y[1]) == 0
! 	  && (x[2] & ~y[2]) == 0
! 	  && (x[3] & ~y[3]) == 0);
  }
  
! static inline bool
! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3];
  }
  
! static inline bool
! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   return ((x[0] & y[0]) != 0
! 	  || (x[1] & y[1]) != 0
! 	  || (x[2] & y[2]) != 0
! 	  || (x[3] & y[3]) != 0);
  }
  
! static inline bool
! hard_reg_set_empty_p (const HARD_REG_SET x)
  {
!   return x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == 0;
  }
  
- #else /* FIRST_PSEUDO_REGISTER > 4*HOST_BITS_PER_WIDEST_FAST_INT */
- 
- #define CLEAR_HARD_REG_SET(TO)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ = 0; } while (0)
- 
- #define SET_HARD_REG_SET(TO)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ = -1; } while (0)
- 
- #define COPY_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ = *scan_fp_++; } while (0)
- 
- #define COMPL_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ = ~ *scan_fp_++; } while (0)
- 
- #define AND_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ &= *scan_fp_++; } while (0)
- 
- #define AND_COMPL_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ &= ~ *scan_fp_++; } while (0)
- 
- #define IOR_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ |= *scan_fp_++; } while (0)
- 
- #define IOR_COMPL_HARD_REG_SET(TO, FROM)  \
- do { HARD_REG_ELT_TYPE *scan_tp_ = (TO);			\
-      const HARD_REG_ELT_TYPE *scan_fp_ = (FROM);		\
-      int i;							\
-      for (i = 0; i < HARD_REG_SET_LONGS; i++)			\
-        *scan_tp_++ |= ~ *scan_fp_++; } while (0)
- 
  static inline bool
! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   int i;
! 
!   for (i = 0; i < HARD_REG_SET_LONGS; i++)
!     if ((x[i] & ~y[i]) != 0)
!       return false;
!   return true;
  }
  
  static inline bool
! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   int i;
! 
!   for (i = 0; i < HARD_REG_SET_LONGS; i++)
!     if (x[i] != y[i])
!       return false;
!   return true;
  }
  
  static inline bool
! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y)
  {
!   int i;
! 
!   for (i = 0; i < HARD_REG_SET_LONGS; i++)
!     if ((x[i] & y[i]) != 0)
!       return true;
!   return false;
  }
  
  static inline bool
! hard_reg_set_empty_p (const HARD_REG_SET x)
  {
!   int i;
! 
!   for (i = 0; i < HARD_REG_SET_LONGS; i++)
!     if (x[i] != 0)
!       return false;
!   return true;
  }
- 
- #endif
- #endif
- #endif
  #endif
  
  /* Iterator for hard register sets.  */
--- 125,266 ----
  #define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM))
  
  static inline bool
! hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y)
  {
    return (x & ~y) == HARD_CONST (0);
  }
  
  static inline bool
! hard_reg_set_equal_p (const_hard_reg_set x, const_hard_reg_set y)
  {
    return x == y;
  }
  
  static inline bool
! hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y)
  {
    return (x & y) != HARD_CONST (0);
  }
  
  static inline bool
! hard_reg_set_empty_p (const_hard_reg_set x)
  {
    return x == HARD_CONST (0);
  }
  
  #else
  
! inline void
! SET_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit)
  {
!   set.elts[bit / UHOST_BITS_PER_WIDE_INT]
!     |= HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT);
  }
  
! inline void
! CLEAR_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit)
  {
!   set.elts[bit / UHOST_BITS_PER_WIDE_INT]
!     &= ~(HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT));
  }
  
! inline bool
! TEST_HARD_REG_BIT (const_hard_reg_set set, unsigned int bit)
  {
!   return (set.elts[bit / UHOST_BITS_PER_WIDE_INT]
! 	  & (HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT)));
  }
  
! inline void
! CLEAR_HARD_REG_SET (HARD_REG_SET &set)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i)
!     set.elts[i] = 0;
  }
  
! inline void
! SET_HARD_REG_SET (HARD_REG_SET &set)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i)
!     set.elts[i] = -1;
  }
  
! inline void
! COPY_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   to = from;
  }
  
! inline void
! COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i)
!     to.elts[i] = ~from.elts[i];
  }
  
! inline void
! AND_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i)
!     to.elts[i] &= from.elts[i];
  }
  
! inline void
! AND_COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i)
!     to.elts[i] &= ~from.elts[i];
  }
  
! inline void
! IOR_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i)
!     to.elts[i] |= from.elts[i];
  }
  
! inline void
! IOR_COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from)
  {
!   for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i)
!     to.elts[i] |= ~from.elts[i];
  }
  
  static inline bool
! hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y)
  {
!   HARD_REG_ELT_TYPE bad = 0;
!   for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
!     bad |= (x.elts[i] & ~y.elts[i]);
!   return bad == 0;
  }
  
  static inline bool
! hard_reg_set_equal_p (const_hard_reg_set x, const_hard_reg_set y)
  {
!   HARD_REG_ELT_TYPE bad = 0;
!   for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
!     bad |= (x.elts[i] ^ y.elts[i]);
!   return bad == 0;
  }
  
  static inline bool
! hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y)
  {
!   HARD_REG_ELT_TYPE good = 0;
!   for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
!     good |= (x.elts[i] & y.elts[i]);
!   return good != 0;
  }
  
  static inline bool
! hard_reg_set_empty_p (const_hard_reg_set x)
  {
!   HARD_REG_ELT_TYPE bad = 0;
!   for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
!     bad |= x.elts[i];
!   return bad == 0;
  }
  #endif
  
  /* Iterator for hard register sets.  */
*************** hard_reg_set_empty_p (const HARD_REG_SET
*** 515,521 ****
  struct hard_reg_set_iterator
  {
    /* Pointer to the current element.  */
!   HARD_REG_ELT_TYPE *pelt;
  
    /* The length of the set.  */
    unsigned short length;
--- 268,274 ----
  struct hard_reg_set_iterator
  {
    /* Pointer to the current element.  */
!   const HARD_REG_ELT_TYPE *pelt;
  
    /* The length of the set.  */
    unsigned short length;
*************** #define HARD_REG_ELT_BITS UHOST_BITS_PER
*** 534,544 ****
  /* The implementation of the iterator functions is fully analogous to
     the bitmap iterators.  */
  static inline void
! hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET set,
                          unsigned min, unsigned *regno)
  {
  #ifdef HARD_REG_SET_LONGS
!   iter->pelt = set;
    iter->length = HARD_REG_SET_LONGS;
  #else
    iter->pelt = &set;
--- 287,297 ----
  /* The implementation of the iterator functions is fully analogous to
     the bitmap iterators.  */
  static inline void
! hard_reg_set_iter_init (hard_reg_set_iterator *iter, const_hard_reg_set set,
                          unsigned min, unsigned *regno)
  {
  #ifdef HARD_REG_SET_LONGS
!   iter->pelt = set.elts;
    iter->length = HARD_REG_SET_LONGS;
  #else
    iter->pelt = &set;
Index: gcc/recog.h
===================================================================
*** gcc/recog.h	2019-09-09 16:53:27.837266363 +0100
--- gcc/recog.h	2019-09-09 16:53:27.829266420 +0100
*************** extern void preprocess_constraints (rtx_
*** 142,148 ****
  extern rtx_insn *peep2_next_insn (int);
  extern int peep2_regno_dead_p (int, int);
  extern int peep2_reg_dead_p (int, rtx);
! #ifdef CLEAR_HARD_REG_SET
  extern rtx peep2_find_free_register (int, int, const char *,
  				     machine_mode, HARD_REG_SET *);
  #endif
--- 142,148 ----
  extern rtx_insn *peep2_next_insn (int);
  extern int peep2_regno_dead_p (int, int);
  extern int peep2_reg_dead_p (int, rtx);
! #ifdef HARD_CONST
  extern rtx peep2_find_free_register (int, int, const char *,
  				     machine_mode, HARD_REG_SET *);
  #endif
Index: gcc/reload.h
===================================================================
*** gcc/reload.h	2019-09-09 16:53:27.837266363 +0100
--- gcc/reload.h	2019-09-09 16:53:27.829266420 +0100
*************** #define reg_equiv_init(ELT) \
*** 274,280 ****
  
  extern int num_not_at_initial_offset;
  
! #if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET
  /* This structure describes instructions which are relevant for reload.
     Apart from all regular insns, this also includes CODE_LABELs, since they
     must be examined for register elimination.  */
--- 274,280 ----
  
  extern int num_not_at_initial_offset;
  
! #if defined HARD_CONST && defined CLEAR_REG_SET
  /* This structure describes instructions which are relevant for reload.
     Apart from all regular insns, this also includes CODE_LABELs, since they
     must be examined for register elimination.  */
*************** #define reg_equiv_init(ELT) \
*** 326,332 ****
  extern class insn_chain *new_insn_chain (void);
  #endif
  
! #if defined SET_HARD_REG_BIT
  extern void compute_use_by_pseudos (HARD_REG_SET *, bitmap);
  #endif
  
--- 326,332 ----
  extern class insn_chain *new_insn_chain (void);
  #endif
  
! #if defined HARD_CONST
  extern void compute_use_by_pseudos (HARD_REG_SET *, bitmap);
  #endif
  
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	2019-09-09 16:53:27.837266363 +0100
--- gcc/rtl.h	2019-09-09 16:53:27.833266392 +0100
*************** extern bool val_signbit_known_clear_p (m
*** 3383,3390 ****
  				       unsigned HOST_WIDE_INT);
  
  /* In reginfo.c  */
! extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
! 					       bool);
  extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &);
  
  /* In emit-rtl.c  */
--- 3383,3389 ----
  				       unsigned HOST_WIDE_INT);
  
  /* In reginfo.c  */
! extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int, bool);
  extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &);
  
  /* In emit-rtl.c  */
Index: gcc/regs.h
===================================================================
*** gcc/regs.h	2019-09-09 16:53:27.837266363 +0100
--- gcc/regs.h	2019-09-09 16:53:27.829266420 +0100
*************** remove_from_hard_reg_set (HARD_REG_SET *
*** 298,304 ****
  /* Return true if REGS contains the whole of (reg:MODE REGNO).  */
  
  static inline bool
! in_hard_reg_set_p (const HARD_REG_SET regs, machine_mode mode,
  		   unsigned int regno)
  {
    unsigned int end_regno;
--- 298,304 ----
  /* Return true if REGS contains the whole of (reg:MODE REGNO).  */
  
  static inline bool
! in_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode,
  		   unsigned int regno)
  {
    unsigned int end_regno;
*************** in_hard_reg_set_p (const HARD_REG_SET re
*** 323,329 ****
  /* Return true if (reg:MODE REGNO) includes an element of REGS.  */
  
  static inline bool
! overlaps_hard_reg_set_p (const HARD_REG_SET regs, machine_mode mode,
  			 unsigned int regno)
  {
    unsigned int end_regno;
--- 323,329 ----
  /* Return true if (reg:MODE REGNO) includes an element of REGS.  */
  
  static inline bool
! overlaps_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode,
  			 unsigned int regno)
  {
    unsigned int end_regno;
*************** remove_range_from_hard_reg_set (HARD_REG
*** 363,369 ****
  /* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of
     REGNO and MODE.  */
  static inline bool
! range_overlaps_hard_reg_set_p (const HARD_REG_SET set, unsigned regno,
  			       int nregs)
  {
    while (nregs-- > 0)
--- 363,369 ----
  /* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of
     REGNO and MODE.  */
  static inline bool
! range_overlaps_hard_reg_set_p (const_hard_reg_set set, unsigned regno,
  			       int nregs)
  {
    while (nregs-- > 0)
*************** range_overlaps_hard_reg_set_p (const HAR
*** 375,381 ****
  /* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of
     REGNO and MODE.  */
  static inline bool
! range_in_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs)
  {
    while (nregs-- > 0)
      if (!TEST_HARD_REG_BIT (set, regno + nregs))
--- 375,381 ----
  /* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of
     REGNO and MODE.  */
  static inline bool
! range_in_hard_reg_set_p (const_hard_reg_set set, unsigned regno, int nregs)
  {
    while (nregs-- > 0)
      if (!TEST_HARD_REG_BIT (set, regno + nregs))
Index: gcc/ira-costs.c
===================================================================
*** gcc/ira-costs.c	2019-09-09 16:53:27.837266363 +0100
--- gcc/ira-costs.c	2019-09-09 16:53:27.829266420 +0100
*************** setup_cost_classes (cost_classes_t from)
*** 237,243 ****
     allocated.  */
  static cost_classes_t
  restrict_cost_classes (cost_classes_t full, machine_mode mode,
! 		       const HARD_REG_SET &regs)
  {
    static struct cost_classes narrow;
    int map[N_REG_CLASSES];
--- 237,243 ----
     allocated.  */
  static cost_classes_t
  restrict_cost_classes (cost_classes_t full, machine_mode mode,
! 		       const_hard_reg_set regs)
  {
    static struct cost_classes narrow;
    int map[N_REG_CLASSES];
Index: gcc/shrink-wrap.c
===================================================================
*** gcc/shrink-wrap.c	2019-09-09 16:53:27.837266363 +0100
--- gcc/shrink-wrap.c	2019-09-09 16:53:27.833266392 +0100
*************** live_edge_for_reg (basic_block bb, int r
*** 151,158 ****
  
  static bool
  move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn,
! 			   const HARD_REG_SET uses,
! 			   const HARD_REG_SET defs,
  			   bool *split_p,
  			   struct dead_debug_local *debug)
  {
--- 151,158 ----
  
  static bool
  move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn,
! 			   const_hard_reg_set uses,
! 			   const_hard_reg_set defs,
  			   bool *split_p,
  			   struct dead_debug_local *debug)
  {
Index: gcc/config/epiphany/resolve-sw-modes.c
===================================================================
*** gcc/config/epiphany/resolve-sw-modes.c	2019-09-09 16:53:27.837266363 +0100
--- gcc/config/epiphany/resolve-sw-modes.c	2019-09-09 16:53:27.825266448 +0100
*************** pass_resolve_sw_modes::execute (function
*** 167,173 ****
  	    }
  	  start_sequence ();
  	  emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
! 			    jilted_mode, FP_MODE_NONE, NULL);
  	  seq = get_insns ();
  	  end_sequence ();
  	  need_commit = true;
--- 167,174 ----
  	    }
  	  start_sequence ();
  	  emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN,
! 			    jilted_mode, FP_MODE_NONE,
! 			    reg_class_contents[NO_REGS]);
  	  seq = get_insns ();
  	  end_sequence ();
  	  need_commit = true;
Index: gcc/config/ia64/ia64.c
===================================================================
*** gcc/config/ia64/ia64.c	2019-09-09 16:53:27.837266363 +0100
--- gcc/config/ia64/ia64.c	2019-09-09 16:53:27.829266420 +0100
*************** struct reg_write_state
*** 6230,6249 ****
  struct reg_write_state rws_sum[NUM_REGS];
  #if CHECKING_P
  /* Bitmap whether a register has been written in the current insn.  */
! HARD_REG_ELT_TYPE rws_insn[(NUM_REGS + HOST_BITS_PER_WIDEST_FAST_INT - 1)
! 			   / HOST_BITS_PER_WIDEST_FAST_INT];
  
  static inline void
! rws_insn_set (int regno)
  {
!   gcc_assert (!TEST_HARD_REG_BIT (rws_insn, regno));
!   SET_HARD_REG_BIT (rws_insn, regno);
  }
  
  static inline int
! rws_insn_test (int regno)
  {
!   return TEST_HARD_REG_BIT (rws_insn, regno);
  }
  #else
  /* When not checking, track just REG_AR_CFM and REG_VOLATILE.  */
--- 6230,6254 ----
  struct reg_write_state rws_sum[NUM_REGS];
  #if CHECKING_P
  /* Bitmap whether a register has been written in the current insn.  */
! unsigned HOST_WIDEST_FAST_INT rws_insn
!   [(NUM_REGS + HOST_BITS_PER_WIDEST_FAST_INT - 1)
!    / HOST_BITS_PER_WIDEST_FAST_INT];
  
  static inline void
! rws_insn_set (unsigned int regno)
  {
!   unsigned int elt = regno / HOST_BITS_PER_WIDEST_FAST_INT;
!   unsigned int bit = regno % HOST_BITS_PER_WIDEST_FAST_INT;
!   gcc_assert (!((rws_insn[elt] >> bit) & 1));
!   rws_insn[elt] |= (unsigned HOST_WIDEST_FAST_INT) 1 << bit;
  }
  
  static inline int
! rws_insn_test (unsigned int regno)
  {
!   unsigned int elt = regno / HOST_BITS_PER_WIDEST_FAST_INT;
!   unsigned int bit = regno % HOST_BITS_PER_WIDEST_FAST_INT;
!   return (rws_insn[elt] >> bit) & 1;
  }
  #else
  /* When not checking, track just REG_AR_CFM and REG_VOLATILE.  */

  reply	other threads:[~2019-09-09 15:54 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-09 15:52 [0/9] Make HARD_REG_SETs easier to use Richard Sandiford
2019-09-09 15:54 ` Richard Sandiford [this message]
2019-09-09 17:35   ` [1/9] Simplify the implementation of HARD_REG_SET Jeff Law
2019-09-09 18:05     ` Richard Sandiford
2019-09-10  9:16       ` Oleg Endo
2019-09-09 15:58 ` [2/9] Remove COPY_HARD_REG_SET Richard Sandiford
2019-09-09 17:36   ` Jeff Law
2019-09-09 15:59 ` [3/9] Remove COMPL_HARD_REG_SET Richard Sandiford
2019-09-09 17:37   ` Jeff Law
2019-09-09 16:00 ` [5/9] Remove IOR_HARD_REG_SET Richard Sandiford
2019-09-09 17:39   ` Jeff Law
2019-09-09 16:00 ` [4/9] Remove AND_HARD_REG_SET Richard Sandiford
2019-09-09 17:38   ` Jeff Law
2019-09-09 16:01 ` [6/9] Remove AND_COMPL_HARD_REG_SET Richard Sandiford
2019-09-09 17:40   ` Jeff Law
2019-09-09 16:01 ` [7/9] Remove IOR_COMPL_HARD_REG_SET Richard Sandiford
2019-09-09 17:41   ` Jeff Law
2019-09-09 16:02 ` [8/9] Remove hard_reg_set_equal_p Richard Sandiford
2019-09-09 17:41   ` Jeff Law
2019-09-09 16:03 ` [9/9] Tweak interface to ira-build.c:ior_hard_reg_conflicts Richard Sandiford
2019-09-09 17:42   ` Jeff Law

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=mptr24p8nzh.fsf@arm.com \
    --to=richard.sandiford@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).