------- Comment #31 from jakub at gcc dot gnu dot org  2008-05-09 14:18 -------
Alternate patch to #c12 that doesn't touch at all rs6000_legitimate_address,
just changes print_operand_address:

--- gcc/config/rs6000/rs6000.c.jj       2008-04-24 18:30:39.000000000 +0200
+++ gcc/config/rs6000/rs6000.c  2008-05-09 16:10:24.000000000 +0200
@@ -723,6 +723,7 @@ static unsigned rs6000_hash_constant (rt
 static unsigned toc_hash_function (const void *);
 static int toc_hash_eq (const void *, const void *);
 static int constant_pool_expr_1 (rtx, int *, int *);
+static int find_constant_pool_expr (rtx *, rtx **, rtx **);
 static bool constant_pool_expr_p (rtx);
 static bool legitimate_small_data_p (enum machine_mode, rtx);
 static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
@@ -3335,6 +3336,44 @@ constant_pool_expr_1 (rtx op, int *have_
     }
 }

+static int
+find_constant_pool_expr (rtx *op, rtx **sym, rtx **toc)
+{
+  switch (GET_CODE (*op))
+    {
+    case SYMBOL_REF:
+      if (RS6000_SYMBOL_REF_TLS_P (*op))
+       return 0;
+      else if (CONSTANT_POOL_ADDRESS_P (*op))
+       {
+         if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (*op), Pmode))
+           {
+             *sym = op;
+             return 1;
+           }
+         else
+           return 0;
+       }
+      else if (! strcmp (XSTR (*op, 0), toc_label_name))
+       {
+         *toc = op;
+         return 1;
+       }
+      else
+       return 0;
+    case PLUS:
+    case MINUS:
+      return (find_constant_pool_expr (&XEXP (*op, 0), sym, toc)
+             && find_constant_pool_expr (&XEXP (*op, 1), sym, toc));
+    case CONST:
+      return find_constant_pool_expr (&XEXP (*op, 0), sym, toc);
+    case CONST_INT:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
 static bool
 constant_pool_expr_p (rtx op)
 {
@@ -12268,32 +12307,36 @@ print_operand_address (FILE *file, rtx x
     {
       if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
        {
-         rtx contains_minus = XEXP (x, 1);
-         rtx minus, symref;
+         rtx *symref = NULL, *tocref = NULL, toc = NULL, addr;
          const char *name;

-         /* Find the (minus (sym) (toc)) buried in X, and temporarily
-            turn it into (sym) for output_addr_const.  */
-         while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
-           contains_minus = XEXP (contains_minus, 0);
-
-         minus = XEXP (contains_minus, 0);
-         symref = XEXP (minus, 0);
-         XEXP (contains_minus, 0) = symref;
+         find_constant_pool_expr (&XEXP (x, 1), &symref, &tocref);
+         if (tocref)
+           {
+             toc = *tocref;
+             *tocref = const0_rtx;
+           }
          if (TARGET_ELF)
            {
              char *newname;

-             name = XSTR (symref, 0);
+             name = XSTR (*symref, 0);
              newname = alloca (strlen (name) + sizeof ("@toc"));
              strcpy (newname, name);
              strcat (newname, "@toc");
-             XSTR (symref, 0) = newname;
+             XSTR (*symref, 0) = newname;
            }
-         output_addr_const (file, XEXP (x, 1));
+         addr = XEXP (x, 1);
+         if (GET_CODE (addr) == CONST)
+           addr = XEXP (addr, 0);
+         addr = simplify_rtx (addr);
+         if (!addr)
+           addr = XEXP (x, 1);
+         output_addr_const (file, addr);
          if (TARGET_ELF)
-           XSTR (symref, 0) = name;
-         XEXP (contains_minus, 0) = minus;
+           XSTR (*symref, 0) = name;
+         if (tocref)
+           *tocref = toc;
        }
       else
        output_addr_const (file, XEXP (x, 1));


The differences from #c12: 1) it doesn't reuse the same routine for finding
the addresses.  The disadvantage of this is that whenever making changes to
constant_pool_expr_1 the other should be adjusted too.
2) it will silently miscompile things if more than one sym or more than one toc
is in the address (unlikely to be ever generated, true) 3) similarly, it
doesn't
check that toc is subtracted from sym, so in some pathological case we could
have
.LC1 + .LCTOC1 or -.LC1 - .LCTOC1.  No testing done on the patch except for
testing that it fixes the testcase.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36090

Reply via email to