re PR target/61737 (ICE when building libgcc for cris cross-compiler)
authorHans-Peter Nilsson <hp@axis.com>
Thu, 17 Jul 2014 02:03:52 +0000 (02:03 +0000)
committerHans-Peter Nilsson <hp@gcc.gnu.org>
Thu, 17 Jul 2014 02:03:52 +0000 (02:03 +0000)
PR target/61737.
* config/cris/cris.c (TARGET_LEGITIMATE_CONSTANT_P)
(TARGET_CANNOT_FORCE_CONST_MEM): Define.
(cris_cannot_force_const_mem, cris_legitimate_constant_p): New
functions.
(cris_print_index, cris_print_operand, cris_constant_index_p)
(cris_side_effect_mode_ok): Replace CONSTANT_P with CRIS_CONSTANT_P.
(cris_address_cost): Ditto last CONSTANT_P.
(cris_symbol_type_of): Rename from cris_pic_symbol_type_of.  All
        callers changed.  Yield cris_offsettable_symbol for non-PIC
        constant symbolic expressions including labels.  Yield cris_unspec
for all unspecs.
(cris_expand_pic_call_address): New parameter MARKERP.  Set its
        target to pic_offset_table_rtx for calls that will likely go
        through PLT, const0_rtx when they can't.  All callers changed.
Assert flag_pic.  Use CONSTANT_P, not CONSTANT_ADDRESS_P, for
symbolic expressions to be PICified.  Remove second, redundant,
assert on can_create_pseudo_p returning non-zero.  Use
replace_equiv_address_nv, not replace_equiv_address, for final
operand update.
* config/cris/cris.md ("movsi"): Move variable t to pattern
toplevel. Adjust assert for new cris_symbol_type member.  Use
CONSTANT_P instead of CONSTANT_ADDRESS_P.
("*movsi_internal") <case 9>: Make check for valid unspec operands
for lapc stricter.
<case CRIS_UNSPEC_PCREL, CRIS_UNSPEC_PLT_PCREL>: Clear condition
codes.
("call", "call_value"): Use second incoming operand as a marker
for pic-offset-table-register being used.
("*expanded_call_non_v32", "*expanded_call_v32")
        ("*expanded_call_value_non_v32", "*expanded_call_value_v32"): For
second incoming operand to CALL, match cris_call_type_marker.
("*expanded_call_value_side"): Ditto.  Disable before
reload_completed.
("*expanded_call_side"): Ditto.  Fix typo in comment.
(moverside, movemside peepholes): Check for CRIS_CONSTANT_P, not
CONSTANT_P.
* config/cris/predicates.md ("cris_call_type_marker"): New predicate.
* config/cris/cris.h (CRIS_CONSTANT_P): New macro.
(enum cris_symbol_type): Rename from cris_pic_symbol_type.  All
        users changed.  Add members cris_offsettable_symbol and
cris_unspec.
(cris_symbol_type): Rename from cris_pic_symbol_type.
* config/cris/constraints.md ("T"): Use CRIS_CONSTANT_P, not
        just CONSTANT_P.
* config/cris/cris-protos.h (cris_symbol_type_of,
cris_expand_pic_call_address): Adjust prototypes.
(cris_legitimate_constant_p): New prototype.

From-SVN: r212708

gcc/ChangeLog
gcc/config/cris/constraints.md
gcc/config/cris/cris-protos.h
gcc/config/cris/cris.c
gcc/config/cris/cris.h
gcc/config/cris/cris.md
gcc/config/cris/predicates.md

index 8e10479648996750d0f512c39e30026faa128cf4..563d3d55c40fe515c06de35b3bdcb8072f2454ba 100644 (file)
@@ -1,5 +1,54 @@
 2014-07-16  Hans-Peter Nilsson  <hp@axis.com>
 
+       PR target/61737.
+       * config/cris/cris.c (TARGET_LEGITIMATE_CONSTANT_P)
+       (TARGET_CANNOT_FORCE_CONST_MEM): Define.
+       (cris_cannot_force_const_mem, cris_legitimate_constant_p): New
+       functions.
+       (cris_print_index, cris_print_operand, cris_constant_index_p)
+       (cris_side_effect_mode_ok): Replace CONSTANT_P with CRIS_CONSTANT_P.
+       (cris_address_cost): Ditto last CONSTANT_P.
+       (cris_symbol_type_of): Rename from cris_pic_symbol_type_of.  All
+        callers changed.  Yield cris_offsettable_symbol for non-PIC
+        constant symbolic expressions including labels.  Yield cris_unspec
+       for all unspecs.
+       (cris_expand_pic_call_address): New parameter MARKERP.  Set its
+        target to pic_offset_table_rtx for calls that will likely go
+        through PLT, const0_rtx when they can't.  All callers changed.
+       Assert flag_pic.  Use CONSTANT_P, not CONSTANT_ADDRESS_P, for
+       symbolic expressions to be PICified.  Remove second, redundant,
+       assert on can_create_pseudo_p returning non-zero.  Use
+       replace_equiv_address_nv, not replace_equiv_address, for final
+       operand update.
+       * config/cris/cris.md ("movsi"): Move variable t to pattern
+       toplevel. Adjust assert for new cris_symbol_type member.  Use
+       CONSTANT_P instead of CONSTANT_ADDRESS_P.
+       ("*movsi_internal") <case 9>: Make check for valid unspec operands
+       for lapc stricter.
+       <case CRIS_UNSPEC_PCREL, CRIS_UNSPEC_PLT_PCREL>: Clear condition
+       codes.
+       ("call", "call_value"): Use second incoming operand as a marker
+       for pic-offset-table-register being used.
+       ("*expanded_call_non_v32", "*expanded_call_v32")
+        ("*expanded_call_value_non_v32", "*expanded_call_value_v32"): For
+       second incoming operand to CALL, match cris_call_type_marker.
+       ("*expanded_call_value_side"): Ditto.  Disable before
+       reload_completed.
+       ("*expanded_call_side"): Ditto.  Fix typo in comment.
+       (moverside, movemside peepholes): Check for CRIS_CONSTANT_P, not
+       CONSTANT_P.
+       * config/cris/predicates.md ("cris_call_type_marker"): New predicate.
+       * config/cris/cris.h (CRIS_CONSTANT_P): New macro.
+       (enum cris_symbol_type): Rename from cris_pic_symbol_type.  All
+        users changed.  Add members cris_offsettable_symbol and
+       cris_unspec.
+       (cris_symbol_type): Rename from cris_pic_symbol_type.
+       * config/cris/constraints.md ("T"): Use CRIS_CONSTANT_P, not
+        just CONSTANT_P.
+       * config/cris/cris-protos.h (cris_symbol_type_of,
+       cris_expand_pic_call_address): Adjust prototypes.
+       (cris_legitimate_constant_p): New prototype.
+
        * config.gcc (crisv32-*-linux* | cris-*-linux*): Do not override
        an existing tmake_file.  Don't add t-slibgcc and t-linux.
 
index 651fbedb0a01cd22aa0b6fa1278477300661d94d..f927ccaaa0feb676104b6f96ce5159973ac8dd69 100644 (file)
                                                       reload_in_progress
                                                       || reload_completed)"))
            ;; Just an explicit indirect reference: [const]?
-           (match_test "CONSTANT_P (XEXP (op, 0))")
+           (match_test "CRIS_CONSTANT_P (XEXP (op, 0))")
            ;; Something that is indexed; [...+...]?
            (and (match_code "plus" "0")
                      ;; A BDAP constant: [reg+(8|16|32)bit offset]?
 (define_constraint "U"
   "@internal"
   (and (match_test "flag_pic")
+       ;; We're just interested in the ..._or_callable_symbol part.
+       ;; (Using CRIS_CONSTANT_P would exclude that too.)
        (match_test "CONSTANT_P (op)")
        (match_operand 0 "cris_nonmemory_operand_or_callable_symbol")))
 
index 0fdcafe52ca9741e3afc45bec87f9ccb7825dcc5..b09babd6991bc332d49615a92ee368029de8e491 100644 (file)
@@ -31,8 +31,9 @@ extern bool cris_cc0_user_requires_cmp (rtx);
 extern rtx cris_return_addr_rtx (int, rtx);
 extern rtx cris_split_movdx (rtx *);
 extern int cris_legitimate_pic_operand (rtx);
-extern enum cris_pic_symbol_type cris_pic_symbol_type_of (const_rtx);
+extern enum cris_symbol_type cris_symbol_type_of (const_rtx);
 extern bool cris_valid_pic_const (const_rtx, bool);
+extern bool cris_legitimate_constant_p (enum machine_mode, rtx);
 extern bool cris_constant_index_p (const_rtx);
 extern bool cris_base_p (const_rtx, bool);
 extern bool cris_base_or_autoincr_p (const_rtx, bool);
@@ -46,7 +47,7 @@ extern int cris_cfun_uses_pic_table (void);
 extern void cris_asm_output_case_end (FILE *, int, rtx);
 extern rtx cris_gen_movem_load (rtx, rtx, int);
 extern rtx cris_emit_movem_store (rtx, rtx, int, bool);
-extern void cris_expand_pic_call_address (rtx *);
+extern void cris_expand_pic_call_address (rtx *, rtx *);
 extern void cris_order_for_addsi3 (rtx *, int);
 extern void cris_emit_trap_for_misalignment (rtx);
 #endif /* RTX_CODE */
index cbed2df8ead8175fea958cd4dc98cf8a04ab042f..4a2e387a3dd454ba7790f74b11a56e703380f0e2 100644 (file)
@@ -148,6 +148,7 @@ static rtx cris_function_incoming_arg (cumulative_args_t,
 static void cris_function_arg_advance (cumulative_args_t, enum machine_mode,
                                       const_tree, bool);
 static tree cris_md_asm_clobbers (tree, tree, tree);
+static bool cris_cannot_force_const_mem (enum machine_mode, rtx);
 
 static void cris_option_override (void);
 
@@ -215,6 +216,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p
 
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P cris_legitimate_constant_p
+
 #undef TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class
 
@@ -249,6 +253,10 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
 #define TARGET_FUNCTION_ARG_ADVANCE cris_function_arg_advance
 #undef TARGET_MD_ASM_CLOBBERS
 #define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM cris_cannot_force_const_mem
+
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required
 
@@ -507,6 +515,21 @@ cris_cfun_uses_pic_table (void)
   return crtl->uses_pic_offset_table;
 }
 
+/* Worker function for TARGET_CANNOT_FORCE_CONST_MEM.
+   We can't put PIC addresses in the constant pool, not even the ones that
+   can be reached as pc-relative as we can't tell when or how to do that.  */
+
+static bool
+cris_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  enum cris_symbol_type t = cris_symbol_type_of (x);
+
+  return
+    t == cris_unspec
+    || t == cris_got_symbol
+    || t == cris_rel_symbol;
+}
+
 /* Given an rtx, return the text string corresponding to the CODE of X.
    Intended for use in the assembly language output section of a
    define_insn.  */
@@ -602,7 +625,7 @@ cris_print_index (rtx index, FILE *file)
 
   if (REG_P (index))
     fprintf (file, "$%s.b", reg_names[REGNO (index)]);
-  else if (CONSTANT_P (index))
+  else if (CRIS_CONSTANT_P (index))
     cris_output_addr_const (file, index);
   else if (GET_CODE (index) == MULT)
     {
@@ -1042,7 +1065,7 @@ cris_print_operand (FILE *file, rtx x, int code)
       /* If this is a GOT symbol, force it to be emitted as :GOT and
         :GOTPLT regardless of -fpic (i.e. not as :GOT16, :GOTPLT16).
         Avoid making this too much of a special case.  */
-      if (flag_pic == 1 && CONSTANT_P (operand))
+      if (flag_pic == 1 && CRIS_CONSTANT_P (operand))
        {
          int flag_pic_save = flag_pic;
 
@@ -1162,7 +1185,7 @@ cris_print_operand (FILE *file, rtx x, int code)
     default:
       /* No need to handle all strange variants, let output_addr_const
         do it for us.  */
-      if (CONSTANT_P (operand))
+      if (CRIS_CONSTANT_P (operand))
        {
          cris_output_addr_const (file, operand);
          return;
@@ -1359,7 +1382,7 @@ reg_ok_for_index_p (const_rtx x, bool strict)
 bool
 cris_constant_index_p (const_rtx x)
 {
-  return (CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
+  return (CRIS_CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
 }
 
 /* True if X is a valid base register.  */
@@ -1468,6 +1491,29 @@ cris_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
   return false;
 }
 
+/* Worker function for TARGET_LEGITIMATE_CONSTANT_P.  We have to handle
+   PIC constants that aren't legitimized.  FIXME: there used to be a
+   guarantee that the target LEGITIMATE_CONSTANT_P didn't have to handle
+   PIC constants, but no more (4.7 era); testcase: glibc init-first.c.
+   While that may be seen as a bug, that guarantee seems a wart by design,
+   so don't bother; fix the documentation instead.  */
+
+bool
+cris_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  enum cris_symbol_type t;
+
+  if (flag_pic)
+    return LEGITIMATE_PIC_OPERAND_P (x);
+
+  t = cris_symbol_type_of (x);
+
+  return
+    t == cris_no_symbol
+    || t == cris_offsettable_symbol
+    || t == cris_unspec;
+}
+
 /* Worker function for LEGITIMIZE_RELOAD_ADDRESS.  */
 
 bool
@@ -2215,7 +2261,7 @@ cris_address_cost (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED,
        return (2 + 2) / 2;
 
       /* A BDAP with some other constant is 2 bytes extra.  */
-      if (CONSTANT_P (tem2))
+      if (CRIS_CONSTANT_P (tem2))
        return (2 + 2 + 2) / 2;
 
       /* BDAP with something indirect should have a higher cost than
@@ -2313,7 +2359,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
        return 0;
 
       /* Check allowed cases, like [r(+)?].[bwd] and const.  */
-      if (CONSTANT_P (val_rtx))
+      if (CRIS_CONSTANT_P (val_rtx))
        return 1;
 
       if (MEM_P (val_rtx)
@@ -2465,32 +2511,34 @@ cris_valid_pic_const (const_rtx x, bool any_operand)
        gcc_unreachable ();
       }
 
-  return cris_pic_symbol_type_of (x) == cris_no_symbol;
+  return cris_symbol_type_of (x) == cris_no_symbol;
 }
 
-/* Helper function to find the right PIC-type symbol to generate,
+/* Helper function to find the right symbol-type to generate,
    given the original (non-PIC) representation.  */
 
-enum cris_pic_symbol_type
-cris_pic_symbol_type_of (const_rtx x)
+enum cris_symbol_type
+cris_symbol_type_of (const_rtx x)
 {
   switch (GET_CODE (x))
     {
     case SYMBOL_REF:
-      return SYMBOL_REF_LOCAL_P (x)
-       ? cris_rel_symbol : cris_got_symbol;
+      return flag_pic
+       ? (SYMBOL_REF_LOCAL_P (x)
+          ? cris_rel_symbol : cris_got_symbol)
+       : cris_offsettable_symbol;
 
     case LABEL_REF:
-      return cris_rel_symbol;
+      return flag_pic ? cris_rel_symbol : cris_offsettable_symbol;
 
     case CONST:
-      return cris_pic_symbol_type_of (XEXP (x, 0));
+      return cris_symbol_type_of (XEXP (x, 0));
 
     case PLUS:
     case MINUS:
       {
-       enum cris_pic_symbol_type t1 = cris_pic_symbol_type_of (XEXP (x, 0));
-       enum cris_pic_symbol_type t2 = cris_pic_symbol_type_of (XEXP (x, 1));
+       enum cris_symbol_type t1 = cris_symbol_type_of (XEXP (x, 0));
+       enum cris_symbol_type t2 = cris_symbol_type_of (XEXP (x, 1));
 
        gcc_assert (t1 == cris_no_symbol || t2 == cris_no_symbol);
 
@@ -2505,9 +2553,7 @@ cris_pic_symbol_type_of (const_rtx x)
       return cris_no_symbol;
 
     case UNSPEC:
-      /* Likely an offsettability-test attempting to add a constant to
-        a GOTREAD symbol, which can't be handled.  */
-      return cris_invalid_pic_symbol;
+      return cris_unspec;
 
     default:
       fatal_insn ("unrecognized supposed constant", x);
@@ -3715,19 +3761,19 @@ cris_emit_movem_store (rtx dest, rtx nregs_rtx, int increment,
 /* Worker function for expanding the address for PIC function calls.  */
 
 void
-cris_expand_pic_call_address (rtx *opp)
+cris_expand_pic_call_address (rtx *opp, rtx *markerp)
 {
   rtx op = *opp;
 
-  gcc_assert (MEM_P (op));
+  gcc_assert (flag_pic && MEM_P (op));
   op = XEXP (op, 0);
 
   /* It might be that code can be generated that jumps to 0 (or to a
      specific address).  Don't die on that.  (There is a
      testcase.)  */
-  if (CONSTANT_ADDRESS_P (op) && !CONST_INT_P (op))
+  if (CONSTANT_P (op) && !CONST_INT_P (op))
     {
-      enum cris_pic_symbol_type t = cris_pic_symbol_type_of (op);
+      enum cris_symbol_type t = cris_symbol_type_of (op);
 
       CRIS_ASSERT (can_create_pseudo_p ());
 
@@ -3753,18 +3799,21 @@ cris_expand_pic_call_address (rtx *opp)
            }
          else
            op = force_reg (Pmode, op);
+
+         /* A local call.  */
+         *markerp = const0_rtx;
        }
       else if (t == cris_got_symbol)
        {
          if (TARGET_AVOID_GOTPLT)
            {
              /* Change a "jsr sym" into (allocate register rM, rO)
-                "move.d (const (unspec [sym rPIC] CRIS_UNSPEC_PLT_GOTREL)),rM"
+                "move.d (const (unspec [sym] CRIS_UNSPEC_PLT_GOTREL)),rM"
                 "add.d rPIC,rM,rO", "jsr rO" for pre-v32 and
-                "jsr (const (unspec [sym rPIC] CRIS_UNSPEC_PLT_PCREL))"
+                "jsr (const (unspec [sym] CRIS_UNSPEC_PLT_PCREL))"
                 for v32.  */
              rtx tem, rm, ro;
-             gcc_assert (can_create_pseudo_p ());
+
              crtl->uses_pic_offset_table = 1;
              tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op),
                                    TARGET_V32
@@ -3818,14 +3867,27 @@ cris_expand_pic_call_address (rtx *opp)
              MEM_NOTRAP_P (mem) = 1;
              op = mem;
            }
+
+         /* We need to prepare this call to go through the PLT; we
+            need to make GOT available.  */
+         *markerp = pic_offset_table_rtx;
        }
       else
-       /* Can't possibly get a GOT-needing-fixup for a function-call,
-          right?  */
+       /* Can't possibly get anything else for a function-call, right?  */
        fatal_insn ("unidentifiable call op", op);
 
-      *opp = replace_equiv_address (*opp, op);
+      /* If the validizing variant is called, it will try to validize
+        the address as a valid any-operand constant, but as it's only
+        valid for calls and moves, it will fail and always be forced
+        into a register.  */
+      *opp = replace_equiv_address_nv (*opp, op);
     }
+  else
+    /* Can't tell what locality a call to a non-constant address has;
+       better make the GOT register alive at it.
+       FIXME: Can we see whether the register has known constant
+       contents?  */
+    *markerp = pic_offset_table_rtx;
 }
 
 /* Make sure operands are in the right order for an addsi3 insn as
index 37b562e5d00de6d77baf6a021bd9be00ee88469c..c5aa83edba37f2e90ccd151ce2fea54e7cabb86b 100644 (file)
@@ -794,6 +794,12 @@ struct cum_args {int regs;};
     }                                                                  \
   while (0)
 
+/* The mode argument to cris_legitimate_constant_p isn't used, so just
+   pass a cheap dummy.  N.B. we have to cast away const from the
+   parameter rather than adjust the parameter, as it's type is mandated
+   by the TARGET_LEGITIMATE_CONSTANT_P target hook interface.  */
+#define CRIS_CONSTANT_P(X) \
+  (CONSTANT_P (X) && cris_legitimate_constant_p (VOIDmode, CONST_CAST_RTX (X)))
 
 /* Node: Condition Code */
 
@@ -833,13 +839,14 @@ struct cum_args {int regs;};
 
 /* Helper type.  */
 
-enum cris_pic_symbol_type
+enum cris_symbol_type
   {
     cris_no_symbol = 0,
     cris_got_symbol = 1,
     cris_rel_symbol = 2,
     cris_got_symbol_needing_fixup = 3,
-    cris_invalid_pic_symbol = 4
+    cris_unspec = 7,
+    cris_offsettable_symbol = 8
   };
 
 #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? CRIS_GOT_REGNUM : INVALID_REGNUM)
index 47f64512a6f4f8670b5111a649d41e91dad659e9..18b9787866343a702cb256a40c4c1031ce8f4be9 100644 (file)
     (match_operand:SI 1 "cris_general_operand_or_symbol" ""))]
   ""
 {
+  enum cris_symbol_type t;
+
   /* If the output goes to a MEM, make sure we have zero or a register as
      input.  */
   if (MEM_P (operands[0])
      valid symbol?  Can we exclude global PIC addresses with an added
      offset?  */
     if (flag_pic
-       && CONSTANT_ADDRESS_P (operands[1])
+       && CONSTANT_P (operands[1])
        && !cris_valid_pic_const (operands[1], false))
       {
-       enum cris_pic_symbol_type t = cris_pic_symbol_type_of (operands[1]);
+       t = cris_symbol_type_of (operands[1]);
 
-       gcc_assert (t != cris_no_symbol);
+       gcc_assert (t != cris_no_symbol && t != cris_offsettable_symbol);
 
        if (! REG_S_P (operands[0]))
          {
         if (!flag_pic
             && (GET_CODE (operands[1]) == SYMBOL_REF
                 || GET_CODE (operands[1]) == LABEL_REF
-                || GET_CODE (operands[1]) == CONST))
+                || (GET_CODE (operands[1]) == CONST
+                    && (GET_CODE (XEXP (operands[1], 0)) != UNSPEC
+                        || (XINT (XEXP (operands[1], 0), 1)
+                            == CRIS_UNSPEC_PLT_PCREL)
+                        || (XINT (XEXP (operands[1], 0), 1)
+                            == CRIS_UNSPEC_PCREL)))))
           {
             /* FIXME: Express this through (set_attr cc none) instead,
                since we can't express the ``none'' at this point.  FIXME:
          case CRIS_UNSPEC_PCREL:
          case CRIS_UNSPEC_PLT_PCREL:
            gcc_assert (TARGET_V32);
+           /* LAPC doesn't set condition codes; clear them to make the
+              (equivalence-marked) result of this insn not presumed
+              present.  This instruction can be a PIC symbol load (for
+              a hidden symbol) which for weak symbols will be followed
+              by a test for NULL.  */
+           CC_STATUS_INIT;
            return "lapc %1,%0";
 
          default:
 {
   gcc_assert (MEM_P (operands[0]));
   if (flag_pic)
-    cris_expand_pic_call_address (&operands[0]);
+    cris_expand_pic_call_address (&operands[0], &operands[1]);
+  else
+    operands[1] = const0_rtx;
 })
 
-;; Accept *anything* as operand 1.  Accept operands for operand 0 in
-;; order of preference.
+;; Accept operands for operand 0 in order of preference.
 
 (define_insn "*expanded_call_non_v32"
   [(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g"))
-        (match_operand 1 "" ""))
+        (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "!TARGET_V32"
   "jsr %0")
   [(call
     (mem:QI
      (match_operand:SI 0 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
-    (match_operand 1 "" ""))
+    (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "TARGET_V32"
   "@
 ;; Parallel when calculating and reusing address of indirect pointer
 ;; with simple offset.  (Makes most sense with PIC.)  It looks a bit
 ;; wrong not to have the clobber last, but that's the way combine
-;; generates it (except it doesn' look into the *inner* mem, so this
+;; generates it (except it doesn't look into the *inner* mem, so this
 ;; just matches a peephole2).  FIXME: investigate that.
 (define_insn "*expanded_call_side"
   [(call (mem:QI
          (mem:SI
           (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,  r,r")
                    (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))))
-        (match_operand 2 "" ""))
+        (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))
    (set (match_operand:SI 3 "register_operand" "=*0,r,r")
        (plus:SI (match_dup 0)
                 (match_dup 1)))]
-  "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+  ;; Disabled until after reload until we can avoid an output reload for
+  ;; operand 3 (being forbidden for call insns).
+  "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
   "jsr [%3=%0%S1]")
 
 (define_expand "call_value"
 {
   gcc_assert (MEM_P (operands[1]));
   if (flag_pic)
-    cris_expand_pic_call_address (&operands[1]);
+    cris_expand_pic_call_address (&operands[1], &operands[2]);
+  else
+    operands[2] = const0_rtx;
 })
 
-;; Accept *anything* as operand 2.  The validity other than "general" of
+;; The validity other than "general" of
 ;; operand 0 will be checked elsewhere.  Accept operands for operand 1 in
 ;; order of preference (Q includes r, but r is shorter, faster).
 ;;  We also accept a PLT symbol.  We output it as [rPIC+sym:GOTPLT] rather
 (define_insn "*expanded_call_value_non_v32"
   [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
        (call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g"))
-             (match_operand 2 "" "")))
+             (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM")))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "!TARGET_V32"
   "Jsr %1"
          (mem:SI
           (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,  r,r")
                    (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
-             (match_operand 3 "" "")))
+        (match_operand:SI 3 "cris_call_type_marker" "rM,rM,rM")))
    (clobber (reg:SI CRIS_SRP_REGNUM))
    (set (match_operand:SI 4 "register_operand" "=*1,r,r")
        (plus:SI (match_dup 1)
                 (match_dup 2)))]
-  "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+  ;; Disabled until after reload until we can avoid an output reload for
+  ;; operand 4 (being forbidden for call insns).
+  "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
   "Jsr [%4=%1%S2]"
   [(set_attr "cc" "clobber")])
 
     (call
      (mem:QI
       (match_operand:SI 1 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
-     (match_operand 2 "" "")))
+     (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM,rM")))
    (clobber (reg:SI 16))]
   "TARGET_V32"
   "@
   /* Make sure we have canonical RTX so we match the insn pattern -
      not a constant in the first operand.  We also require the order
      (plus reg mem) to match the final pattern.  */
-  if (CONSTANT_P (otherop) || MEM_P (otherop))
+  if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
     {
       operands[7] = operands[1];
       operands[8] = otherop;
   /* Make sure we have canonical RTX so we match the insn pattern -
      not a constant in the first operand.  We also require the order
      (plus reg mem) to match the final pattern.  */
-  if (CONSTANT_P (otherop) || MEM_P (otherop))
+  if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
     {
       operands[7] = operands[1];
       operands[8] = otherop;
index 0169b0b715d48a44995a6d9607914a1e6f34e08e..ddb090eab71b5b3160a4a962c71119f8d97267e1 100644 (file)
   (ior (match_operand 0 "general_operand")
        (and (match_code "const, symbol_ref, label_ref")
                    ; The following test is actually just an assertion.
-           (match_test "cris_pic_symbol_type_of (op) != cris_no_symbol"))))
+           (match_test "cris_symbol_type_of (op) != cris_no_symbol"))))
 
 ;; A predicate for the anon movsi expansion, one that fits a PCREL
 ;; operand as well as general_operand.
        (ior (match_operand 0 "memory_operand")
            (match_test "cris_general_operand_or_symbol (XEXP (op, 0),
                                                         Pmode)"))))
+
+;; A marker for the call-insn: (const_int 0) for a call to a
+;; hidden or static function and non-pic and
+;; pic_offset_table_rtx for a call that *might* go through the
+;; PLT.
+
+(define_predicate "cris_call_type_marker"
+  (ior (and (match_operand 0 "const_int_operand")
+           (match_test "op == const0_rtx"))
+       (and (and (match_operand 0 "register_operand")
+                (match_test "op == pic_offset_table_rtx"))
+           (match_test "flag_pic != 0"))))