From: Hans-Peter Nilsson Date: Thu, 17 Jul 2014 02:03:52 +0000 (+0000) Subject: re PR target/61737 (ICE when building libgcc for cris cross-compiler) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ab4e53feba14df1de389b194b095f7932a8ca9ee;p=gcc.git re PR target/61737 (ICE when building libgcc for cris cross-compiler) 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") : Make check for valid unspec operands for lapc stricter. : 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8e104796489..563d3d55c40 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,54 @@ 2014-07-16 Hans-Peter Nilsson + 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") : Make check for valid unspec operands + for lapc stricter. + : 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. diff --git a/gcc/config/cris/constraints.md b/gcc/config/cris/constraints.md index 651fbedb0a0..f927ccaaa0f 100644 --- a/gcc/config/cris/constraints.md +++ b/gcc/config/cris/constraints.md @@ -118,7 +118,7 @@ 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]? @@ -159,6 +159,8 @@ (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"))) diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h index 0fdcafe52ca..b09babd6991 100644 --- a/gcc/config/cris/cris-protos.h +++ b/gcc/config/cris/cris-protos.h @@ -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 */ diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index cbed2df8ead..4a2e387a3dd 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -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 diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 37b562e5d00..c5aa83edba3 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -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) diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 47f64512a6f..18b97878663 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -919,6 +919,8 @@ (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]) @@ -934,12 +936,12 @@ 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])) { @@ -1086,7 +1088,12 @@ 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: @@ -1169,6 +1176,12 @@ 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: @@ -3710,15 +3723,16 @@ { 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") @@ -3727,7 +3741,7 @@ [(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" "@ @@ -3740,19 +3754,21 @@ ;; 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" @@ -3764,10 +3780,12 @@ { 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 @@ -3776,7 +3794,7 @@ (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" @@ -3790,12 +3808,14 @@ (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")]) @@ -3805,7 +3825,7 @@ (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" "@ @@ -4827,7 +4847,7 @@ /* 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; @@ -4878,7 +4898,7 @@ /* 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; diff --git a/gcc/config/cris/predicates.md b/gcc/config/cris/predicates.md index 0169b0b715d..ddb090eab71 100644 --- a/gcc/config/cris/predicates.md +++ b/gcc/config/cris/predicates.md @@ -142,7 +142,7 @@ (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. @@ -176,3 +176,15 @@ (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"))))