[csl-sol210] Patch to disable ldd and std for 32-bit SPARC

Eric Botcazou ebotcazou@libertysurf.fr
Thu May 19 23:54:00 GMT 2005


> This patch, for csl-sol210-3_4-branch (which is now being used more
> generally for the Solaris 10 compiler on SPARC as well as AMD64), adds
> a command-line option to disable use of the SPARC ldd and std
> instructions with integer operands.  This is for use with large bodies
> of legacy code which has inadequately aligned 64-bit values.  As the
> specification given was for such an option for 32-bit mode only, not
> much consideration has been given to how it interacts with -m64; some
> ldd and std uses may be disabled in 64-bit mode, but not all since
> 64-bit-only instruction patterns have not been touched.

GCC doesn't emit ldd/std for integer registers in 64-bit mode (their semantics 
would be that of unpack/pack insns).  Both insns are deprecated in V9.

> Any comments on whether this would be a useful feature for mainline
> (and if so what should happen with -m64)?

Yes, I suppose this would be useful on mainline too.

> Bootstrapped with no regressions on sparc-sun-solaris2.10.1, and ran
> the testsuite with -mno-integer-ldd-std with no regressions.  Applied
> to csl-sol210-3_4-branch.

Some comments:

        * gcc/config/sparc/sparc.h (MASK_NO_INTEGER_LDD_STD,
        TARGET_INTEGER_LDD_STD): New.
        (TARGET_SWITCHES): Define -mno-integer-ldd-std option.
        * gcc/doc/invoke.texi (-mno-integer-std-ldd): Document.

std/ldd are swapped.

diff -rupN GCC.orig/gcc/config/sparc/sparc.c GCC/gcc/config/sparc/sparc.c
--- GCC.orig/gcc/config/sparc/sparc.c   2004-10-13 14:16:25.000000000 +0000
+++ GCC/gcc/config/sparc/sparc.c        2005-05-18 23:07:24.000000000 +0000
@@ -4117,7 +4117,8 @@ save_regs (FILE *file, int low, int high
        {
          if (regs_ever_live[i] && ! call_used_regs[i])
            {
-             if (regs_ever_live[i+1] && ! call_used_regs[i+1])
+             if (TARGET_INTEGER_LDD_STD
+                 && regs_ever_live[i+1] && ! call_used_regs[i+1])
                {
                  fprintf (file, "\tstd\t%s, [%s+%d]\n",
                           reg_names[i], base, offset + 4 * n_regs);
@@ -4180,7 +4181,8 @@ restore_regs (FILE *file, int low, int h
       for (i = low; i < high; i += 2)
        {
          if (regs_ever_live[i] && ! call_used_regs[i])
-           if (regs_ever_live[i+1] && ! call_used_regs[i+1])
+           if (TARGET_INTEGER_LDD_STD
+               && regs_ever_live[i+1] && ! call_used_regs[i+1])
              fprintf (file, "\tldd\t[%s+%d], %s\n",
                       base, offset + 4 * n_regs, reg_names[i]),
              n_regs += 2;

Theoretically that's not quite correct, as registers that need to be saved 
have to be saved.  You should split every insn into 2 insns.  Moreover 
save_regs/restore_regs are only used in prologue/epilogue code and everything 
is 64-bit aligned there, so that's unnecessary.

In practice save_regs/restore_regs are never used on Solaris so that doesn't 
really matter.

@@ -7740,7 +7743,8 @@ sparc_flat_save_restore (FILE *file, con
        {
          if ((gmask & (1L << regno)) != 0)
            {
-             if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0))
+             if (TARGET_INTEGER_LDD_STD
+                 && (regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0))
                {
                  /* We can save two registers in a row.  If we're not at a
                     double word boundary, move to one.

Same problem as with save_regs/restore_regs, unnecessary too and in practice 
dead too (unless you compile with -mflat, but do not do that :-).

@@ -2126,12 +2126,39 @@
    (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
    (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
 
+(define_insn "*movdi_insn_sp32_v9_nolddstd"
+  [(set (match_operand:DI 0 "nonimmediate_operand"
+                                       "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
+        (match_operand:DI 1 "input_operand"
+                                       " J,J,U,T,r,o,i,r, f, T, o, f, e, W, 
e"))]
+  "! TARGET_ARCH64 && TARGET_V9 && ! TARGET_INTEGER_LDD_STD
+   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+  "@
+   stx\t%%g0, %0
+   #
+   #
+   #
+   #
+   #
+   #
+   #
+   std\t%1, %0
+   ldd\t%1, %0
+   #
+   #
+   fmovd\\t%1, %0
+   ldd\\t%1, %0
+   std\\t%1, %0"
+  [(set_attr "type" 
"store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
+   (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")

Every # alternative should have length 2.

@@ -2150,6 +2177,30 @@
   [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
    (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
 
+(define_insn "*movdi_insn_sp32_nolddstd"
+  [(set (match_operand:DI 0 "nonimmediate_operand"
+                               "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+        (match_operand:DI 1 "input_operand"
+                               " J,U,T,r,o,i,r, f, T, o, f, f"))]
+  "! TARGET_ARCH64 && ! TARGET_INTEGER_LDD_STD
+   && (register_operand (operands[0], DImode)
+       || register_operand (operands[1], DImode))"
+  "@
+   #
+   #
+   #
+   #
+   #
+   #
+   #
+   std\t%1, %0
+   ldd\t%1, %0
+   #
+   #
+   #"
+  [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+   (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])

Likewise.

diff -rupN GCC.orig/gcc/doc/invoke.texi GCC/gcc/doc/invoke.texi
--- GCC.orig/gcc/doc/invoke.texi        2004-10-06 20:15:08.000000000 +0000
+++ GCC/gcc/doc/invoke.texi     2005-05-18 22:36:20.000000000 +0000
@@ -365,6 +365,7 @@ in the following sections.
 -mstack-bias  -mno-stack-bias @gol
 -munaligned-doubles  -mno-unaligned-doubles @gol
 -mv8plus  -mno-v8plus  -mvis  -mno-vis @gol
+-minteger-std-ldd  -mno-integer-std-ldd @gol

ldd/std are swapped.

@@ -6375,6 +6376,15 @@ mode for all SPARC-V9 processors.
 @opindex mno-vis
 With @option{-mvis}, GCC generates code that takes advantage of the 
UltraSPARC
 Visual Instruction Set extensions.  The default is @option{-mno-vis}.
+
+@item -minteger-std-ldd
+@itemx -mno-integer-std-ldd
+@opindex minteger-std-ldd
+@opindex mno-integer-std-ldd
+With @option{-mno-integer-std-ldd}, GCC does not use the @code{ldd}
+and @code{std} instructions for integer operands in 32-bit mode.  This
+is for use with legacy code using 64-bit quantities which are not
+64-bit aligned.  The default is @option{-minteger-std-ldd}.
 @end table

Likewise.

-- 
Eric Botcazou



More information about the Gcc-patches mailing list