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]

[PPC PATCH] Extend easy_altivec_constant for FP vector constants


The following patch extends the rs6000's easy_vector_const machinery
to recognize that some floating point vector constants may be synthesized
using the altivec's vspltisb, vspltish and vspltisw instructions.  After
further investigation and discussion this is the correct fix to
PR target/27158, which I'd previsouly tackled with a patch to reload.c.
Unfortunately, the reload change was incorrect, causing PR target/27858,
but simply reverting it would cause powerpc to regress without this
change (and perhaps require testcases to be XFAILed temporarily).

Recognizing floating point vectors is actually quite easy, as the only
place in the easy_*_constant machinery that relied on integers was the
function vspltis_constant.  Replacing each use of CONST_VECTOR_ELT in
this subroutine with a new const_vector_elt_as_int, allows us to handle
VECTOR_FLOAT_MODEs, by reinterpreting the CONST_DOUBLEs as CONST_INTs
upon demand.  This routine handles both V4SF and V2SF modes.  Although
it only needed to handle V4SF at the moment [the only floating point
ALTIVEC_VECTOR_MODE], its trivial to also do the same for V2SF to allow
a similar optimization to be done for SPE at some point in the future.



The following patch has been tested on powerpc-apple-darwin7.9.0,
together with a second reversion patch appended below it, and a fix to
allow darwin to bootstrap (posted previously), with a full "make
bootstrap", all default languages and regression tested with a top-level
"make -k check" with no new failures.  I've also confirmed that applying
just the second reversion patch, causes gcc.target/powerpc/pr27158.c to
FAIL, which shows this patch is a valid alternate solution to the
original problem.


Are the rs6000 bits OK for mainline, and the 4.1 branch after a while?
If approved, I'll commit them concurrently with the second patch below
which will resolve the regression PR target/27858 on the alpha.

Many thanks in advance, and my apologies to the alpha folks for any
inconvenience.



2006-06-11  Roger Sayle  <roger@eyesopen.com>

	PR target/27158
	* config/rs6000/rs6000.c (const_vector_elt_as_int): New function to
	extract a CONST_VECTOR element and interpret it as an integer.
	(vspltis_constant): Use const_vector_elt_as_int instead of the
	macro CONST_VECTOR_ELT in order to handle FP vector modes.
	* config/rs6000/predicates.md (easy_vector_const): Consider
	floating point ALTIVEC_VECTOR_MODEs via easy_altivec_constant.


Index: config/rs6000/rs6000.c
===================================================================
*** config/rs6000/rs6000.c	(revision 114540)
--- config/rs6000/rs6000.c	(working copy)
*************** num_insns_constant (rtx op, enum machine
*** 2122,2127 ****
--- 2122,2141 ----
      }
  }

+ /* Interpret element ELT of the CONST_VECTOR OP as an integer value.
+    If the mode of OP is MODE_VECTOR_INT, this simply returns the
+    corresponding element of the vector, but for V4SFmode and V2SFmode,
+    the corresponding "float" is interpreted as an SImode integer.  */
+
+ static HOST_WIDE_INT
+ const_vector_elt_as_int (rtx op, unsigned int elt)
+ {
+   rtx tmp = CONST_VECTOR_ELT (op, elt);
+   if (GET_MODE (op) == V4SFmode
+       || GET_MODE (op) == V2SFmode)
+     tmp = gen_lowpart (SImode, tmp);
+   return INTVAL (tmp);
+ }

  /* Return true if OP can be synthesized with a particular vspltisb, vspltish
     or vspltisw instruction.  OP is a CONST_VECTOR.  Which instruction is used
*************** vspltis_constant (rtx op, unsigned step,
*** 2141,2148 ****
    unsigned bitsize = GET_MODE_BITSIZE (inner);
    unsigned mask = GET_MODE_MASK (inner);

!   rtx last = CONST_VECTOR_ELT (op, nunits - 1);
!   HOST_WIDE_INT val = INTVAL (last);
    HOST_WIDE_INT splat_val = val;
    HOST_WIDE_INT msb_val = val > 0 ? 0 : -1;

--- 2155,2161 ----
    unsigned bitsize = GET_MODE_BITSIZE (inner);
    unsigned mask = GET_MODE_MASK (inner);

!   HOST_WIDE_INT val = const_vector_elt_as_int (op, nunits - 1);
    HOST_WIDE_INT splat_val = val;
    HOST_WIDE_INT msb_val = val > 0 ? 0 : -1;

*************** vspltis_constant (rtx op, unsigned step,
*** 2182,2188 ****
        else
  	desired_val = msb_val;

!       if (desired_val != INTVAL (CONST_VECTOR_ELT (op, i)))
  	return false;
      }

--- 2195,2201 ----
        else
  	desired_val = msb_val;

!       if (desired_val != const_vector_elt_as_int (op, i))
  	return false;
      }

Index: config/rs6000/predicates.md
===================================================================
*** config/rs6000/predicates.md	(revision 114540)
--- config/rs6000/predicates.md	(working copy)
***************
*** 278,286 ****
      {
        if (zero_constant (op, mode))
          return true;
-       if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
-         return false;
-
        return easy_altivec_constant (op, mode);
      }

--- 278,283 ----


2006-06-11  Roger Sayle  <roger@eyesopen.com>

	PR target/27858
	Revert incorrect fix for PR target/27158
	2006-05-08  Roger Sayle  <roger@eyesopen.com>
        * reload.c (find_reloads_toplev): Only return the simplified SUBREG
        of a reg_equiv_constant if the result is a legitimate constant.


Index: reload.c
===================================================================
*** reload.c	(revision 114540)
--- reload.c	(working copy)
*************** find_reloads_toplev (rtx x, int opnum, e
*** 4572,4579 ****
  	  && reg_renumber[regno] < 0
  	  && reg_equiv_constant[regno] != 0
  	  && (tem = gen_lowpart_common (GET_MODE (x),
! 					reg_equiv_constant[regno])) != 0
! 	  && LEGITIMATE_CONSTANT_P (tem))
  	return tem;

        if (regno >= FIRST_PSEUDO_REGISTER
--- 4572,4578 ----
  	  && reg_renumber[regno] < 0
  	  && reg_equiv_constant[regno] != 0
  	  && (tem = gen_lowpart_common (GET_MODE (x),
! 					reg_equiv_constant[regno])) != 0)
  	return tem;

        if (regno >= FIRST_PSEUDO_REGISTER
*************** find_reloads_toplev (rtx x, int opnum, e
*** 4584,4591 ****
  	    simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
  				 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
  	  gcc_assert (tem);
! 	  if (LEGITIMATE_CONSTANT_P (tem))
! 	    return tem;
  	}

        /* If the subreg contains a reg that will be converted to a mem,
--- 4583,4589 ----
  	    simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
  				 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
  	  gcc_assert (tem);
! 	  return tem;
  	}

        /* If the subreg contains a reg that will be converted to a mem,


Roger
--


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