This is the mail archive of the gcc@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]

dangerous cleverness? ppc int<->float conversions, subreg


I am attempting to add a switch to GCC which has the effect of preventing
it from allocating floating-point registers for integer values.  It is
still allowed in this mode to use floating point, but if the programmer
writes no floating point they should get code which uses only the integer
unit.

At first look this is a straightforward change to HARD_REGNO_MODE_OK for
each target that currently allows use of float registers for integer modes.
However, I tripped over a detail of the rs6000 machine description: the
architecture's float<->int conversion instructions pick up or deposit
integers in the float registers, and the machine description therefore
has patterns such as

  (set (match_operand:DI 0 "gpc_reg_operand" "=f")
       (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))

HARD_REGNO_MODE_OK doesn't distinguish between this pattern's requirements
and a plain old integer quantity that register allocation wants to put in
a float register.  Therefore my switch makes the compiler announce its
inability to allocate a spill register and give up.

I came up with a clever trick to avoid the problem.  If the above pattern
is written instead

  (set (subreg:DI (match_operand:DF 0 "gpc_reg_operand" "=f") 0)
       (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))

then register allocation happily assigns operand 0 a floating point
register and we carry on, generating what appears to be correct assembly.

I am worried that this trick is _too_ clever and something horrible will
happen on code which is marginally more complicated than __fixunsdfsi.
Can any experts on SUBREGs, the PPC, etc. offer clues?  The rs6000 bits
of the patch I'm working on are below, to give you an idea.  I may be
trying to get it to work on sparc as well.

Note the tree this is being developed in is vintage 2.96-era and does not
include the SUBREG_BYTE patch, although I may want to roll it forward into
3.1.

zw

================================================================
--- rs6000.h	Fri Oct 19 16:23:59 2001
+++ rs6000.h	Fri Oct 19 17:33:14 2001
@@ -824,7 +824,7 @@ extern int rs6000_debug_arg;		/* debug a
 #define HARD_REGNO_MODE_OK(REGNO, MODE)					\
   (FP_REGNO_P (REGNO) ?							\
    (GET_MODE_CLASS (MODE) == MODE_FLOAT					\
-    || (GET_MODE_CLASS (MODE) == MODE_INT				\
+    || (flag_implicit_fp && GET_MODE_CLASS (MODE) == MODE_INT		\
 	&& GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD))			\
    : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC		\
    : FPMEM_REGNO_P (REGNO) ? ((MODE) == DImode || (MODE) == DFmode)	\
================================================================
--- rs6000.md	Wed Oct 17 17:09:58 2001
+++ rs6000.md	Mon Oct 22 15:52:43 2001
@@ -4301,7 +4301,7 @@
       DONE;
     }
 
-  operands[2] = gen_reg_rtx (DImode);
+  operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (Pmode);
   operands[4] = gen_rtx_REG (DImode, FPMEM_REGNUM);
 }")
@@ -4309,7 +4309,7 @@
 (define_insn "*fix_truncdfsi2_internal"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 	(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
-   (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
+   (clobber (match_operand:DF 2 "gpc_reg_operand" "=f"))
    (clobber (match_operand 3 "gpc_reg_operand" "=b"))
    (clobber (reg:DI 76))]
   "TARGET_HARD_FLOAT"
@@ -4319,16 +4319,16 @@
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
 	(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
-   (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+   (clobber (match_operand:DF 2 "gpc_reg_operand" ""))
    (clobber (match_operand 3 "gpc_reg_operand" ""))
    (clobber (reg:DI 76))]
   "TARGET_HARD_FLOAT"
-  [(set (match_dup 2)
+  [(set (subreg:DI (match_dup 2) 0)
 	(sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))))
    (set (match_dup 3)
 	(unspec [(const_int 0)] 11))
    (set (match_dup 4)
-	(unspec [(match_dup 2)
+	(unspec [(subreg:DI (match_dup 2) 0)
 		 (match_dup 3)] 15))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
 	(unspec [(match_dup 4)
@@ -4337,7 +4337,7 @@
 
 (define_insn "*fix_truncdfsi2_store"
   [(set (reg:DI 76)
-	(unspec [(match_operand:DI 0 "gpc_reg_operand" "f")
+	(unspec [(subreg:DI (match_operand:DF 0 "gpc_reg_operand" "f") 0)
 		 (match_operand 1 "gpc_reg_operand" "b")] 15))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
   "*
@@ -4433,7 +4433,7 @@
 }")
 
 (define_insn "*fctiwz"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+  [(set (subreg:DI (match_operand:DF 0 "gpc_reg_operand" "=f") 0)
 	(sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
   "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
   "{fcirz|fctiwz} %0,%1"
@@ -4441,13 +4441,13 @@
 
 (define_insn "floatdidf2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
-	(float:DF (match_operand:DI 1 "gpc_reg_operand" "f")))]
+	(float:DF (subreg:DI (match_operand:DF 1 "gpc_reg_operand" "f") 0)))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
   "fcfid %0,%1"
   [(set_attr "type" "fp")])
 
 (define_insn "fix_truncdfdi2"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+  [(set (subreg:DI (match_operand:DF 0 "gpc_reg_operand" "=f") 0)
 	(fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
   "fctidz %0,%1"


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