Skip to content
This repository has been archived by the owner on Sep 28, 2019. It is now read-only.

Commit

Permalink
Merge branch 'riscv-gcc-7.2.0' into riscv-gcc-7.2.0-gme
Browse files Browse the repository at this point in the history
  • Loading branch information
ilg-ul committed May 6, 2018
2 parents 1cd09ef + 36e932c commit ea82cca
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 21 deletions.
11 changes: 11 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
2017-11-07 Eric Botcazou <ebotcazou@adacore.com>

Backport from mainline
2017-10-31 Matthew Fortune <matthew.fortune@imgtec.com>
Eric Botcazou <ebotcazou@adacore.com>

PR rtl-optimization/81803
* lra-constraints.c (curr_insn_transform): Also reload the whole
register for a strict subreg no wider than a word if this is for
a WORD_REGISTER_OPERATIONS target.

2018-01-08 Jim Wilson <jimw@sifive.com>

Backport from mainline
Expand Down
1 change: 1 addition & 0 deletions gcc/config/riscv/riscv-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ extern bool riscv_split_64bit_move_p (rtx, rtx);
extern void riscv_split_doubleword_move (rtx, rtx);
extern const char *riscv_output_move (rtx, rtx);
extern const char *riscv_output_gpr_save (unsigned);
extern const char *riscv_output_return ();
#ifdef RTX_CODE
extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
Expand Down
136 changes: 119 additions & 17 deletions gcc/config/riscv/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ struct GTY(()) machine_function {
This area is allocated by the callee at the very top of the frame. */
int varargs_size;

/* True if current function is a naked function. */
bool naked_p;

/* The current frame information, calculated by riscv_compute_frame_info. */
struct riscv_frame_info frame;
};
Expand Down Expand Up @@ -319,6 +322,19 @@ static const struct riscv_tune_info optimize_size_tune_info = {
false, /* slow_unaligned_access */
};

/* Defining target-specific uses of __attribute__. */
static const struct attribute_spec riscv_attribute_table[] =
{
/* Syntax: { name, min_len, max_len, decl_required, type_required,
function_type_required, handler, affects_type_identity } */

/* The attribute telling no prologue/epilogue. */
{ "naked", 0, 0, true, false, false, NULL, false },

/* The last attribute spec is set to be NULL. */
{ NULL, 0, 0, false, false, false, NULL, false }
};

/* A table describing all the processors GCC knows about. */
static const struct riscv_cpu_info riscv_cpu_info_table[] = {
{ "rocket", &rocket_tune_info },
Expand Down Expand Up @@ -1849,6 +1865,16 @@ riscv_output_move (rtx dest, rtx src)
}
gcc_unreachable ();
}

const char *
riscv_output_return ()
{
if (cfun->machine->naked_p)
return "";

return "ret";
}


/* Return true if CMP1 is a suitable second operand for integer ordering
test CODE. See also the *sCC patterns in riscv.md. */
Expand Down Expand Up @@ -2669,6 +2695,33 @@ riscv_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD;
}

/* Return true if func is a naked function. */
static bool
riscv_naked_function_p (tree func)
{
tree func_decl = func;
if (func == NULL_TREE)
func_decl = current_function_decl;
return NULL_TREE != lookup_attribute ("naked", DECL_ATTRIBUTES (func_decl));
}

/* Implement TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS. */
static bool
riscv_allocate_stack_slots_for_args ()
{
/* Naked functions should not allocate stack slots for arguments. */
return !riscv_naked_function_p (current_function_decl);
}

/* Implement TARGET_WARN_FUNC_RETURN. */
static bool
riscv_warn_func_return (tree decl)
{
/* Naked functions are implemented entirely in assembly, including the
return sequence, so suppress warnings about this. */
return !riscv_naked_function_p (decl);
}

/* Implement TARGET_EXPAND_BUILTIN_VA_START. */

static void
Expand Down Expand Up @@ -3208,23 +3261,26 @@ riscv_compute_frame_info (void)
frame = &cfun->machine->frame;
memset (frame, 0, sizeof (*frame));

/* Find out which GPRs we need to save. */
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;

/* If this function calls eh_return, we must also save and restore the
EH data registers. */
if (crtl->calls_eh_return)
for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;

/* Find out which FPRs we need to save. This loop must iterate over
the same space as its companion in riscv_for_each_saved_reg. */
if (TARGET_HARD_FLOAT)
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
if (!cfun->machine->naked_p)
{
/* Find out which GPRs we need to save. */
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;

/* If this function calls eh_return, we must also save and restore the
EH data registers. */
if (crtl->calls_eh_return)
for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;

/* Find out which FPRs we need to save. This loop must iterate over
the same space as its companion in riscv_for_each_saved_reg. */
if (TARGET_HARD_FLOAT)
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
}

/* At the bottom of the frame are any outgoing stack arguments. */
offset = crtl->outgoing_args_size;
Expand Down Expand Up @@ -3494,6 +3550,14 @@ riscv_expand_prologue (void)
unsigned mask = frame->mask;
rtx insn;

if (cfun->machine->naked_p)
{
if (flag_stack_usage_info)
current_function_static_stack_size = 0;

return;
}

if (flag_stack_usage_info)
current_function_static_stack_size = size;

Expand Down Expand Up @@ -3606,6 +3670,15 @@ riscv_expand_epilogue (bool sibcall_p)
bool need_barrier_p = (get_frame_size ()
+ cfun->machine->frame.arg_pointer_offset) != 0;

if (cfun->machine->naked_p)
{
gcc_assert (!sibcall_p);

emit_jump_insn (gen_return ());

return;
}

if (!sibcall_p && riscv_can_use_return_insn ())
{
emit_jump_insn (gen_return ());
Expand Down Expand Up @@ -4163,9 +4236,27 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
if (TARGET_SAVE_RESTORE)
return false;

/* Don't use sibcall for naked function. */
if (cfun->machine->naked_p)
return false;

return true;
}

/* Implement `TARGET_SET_CURRENT_FUNCTION'. */
/* Sanity cheching for above function attributes. */
static void
riscv_set_current_function (tree decl)
{
if (decl == NULL_TREE
|| current_function_decl == NULL_TREE
|| current_function_decl == error_mark_node
|| !cfun->machine)
return;

cfun->machine->naked_p = riscv_naked_function_p (decl);
}

/* Implement TARGET_CANNOT_COPY_INSN_P. */

static bool
Expand Down Expand Up @@ -4194,6 +4285,9 @@ riscv_cannot_copy_insn_p (rtx_insn *insn)
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall

#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION riscv_set_current_function

#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST riscv_register_move_cost
#undef TARGET_MEMORY_MOVE_COST
Expand Down Expand Up @@ -4229,6 +4323,8 @@ riscv_cannot_copy_insn_p (rtx_insn *insn)

#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs
#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS riscv_allocate_stack_slots_for_args
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
#undef TARGET_MUST_PASS_IN_STACK
Expand Down Expand Up @@ -4304,6 +4400,12 @@ riscv_cannot_copy_insn_p (rtx_insn *insn)
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN riscv_expand_builtin

#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE riscv_attribute_table

#undef TARGET_WARN_FUNC_RETURN
#define TARGET_WARN_FUNC_RETURN riscv_warn_func_return

struct gcc_target targetm = TARGET_INITIALIZER;

#include "gt-riscv.h"
4 changes: 3 additions & 1 deletion gcc/config/riscv/riscv.md
Original file line number Diff line number Diff line change
Expand Up @@ -1877,7 +1877,9 @@
(define_insn "simple_return"
[(simple_return)]
""
"ret"
{
return riscv_output_return ();
}
[(set_attr "type" "jump")
(set_attr "mode" "none")])

Expand Down
19 changes: 19 additions & 0 deletions gcc/doc/extend.texi
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,7 @@ GCC plugins may provide their own attributes.
* Nios II Function Attributes::
* Nvidia PTX Function Attributes::
* PowerPC Function Attributes::
* RISC-V Function Attributes::
* RL78 Function Attributes::
* RX Function Attributes::
* S/390 Function Attributes::
Expand Down Expand Up @@ -4910,6 +4911,24 @@ function that has different target options than the caller, unless the
callee has a subset of the target options of the caller.
@end table

@node RISC-V Function Attributes
@subsection RISC-V Function Attributes

These function attributes are supported by the RISC-V back end:

@table @code
@item naked
@cindex @code{naked} function attribute, RISC-V
This attribute allows the compiler to construct the
requisite function declaration, while allowing the body of the
function to be assembly code. The specified function will not have
prologue/epilogue sequences generated by the compiler. Only basic
@code{asm} statements can safely be included in naked functions
(@pxref{Basic Asm}). While using extended @code{asm} or a mixture of
basic @code{asm} and C code may appear to work, they cannot be
depended upon to work reliably and are not supported.
@end table

@node RL78 Function Attributes
@subsection RL78 Function Attributes

Expand Down
11 changes: 8 additions & 3 deletions gcc/lra-constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -4222,8 +4222,9 @@ curr_insn_transform (bool check_only_p)
reg = SUBREG_REG (*loc);
byte = SUBREG_BYTE (*loc);
if (REG_P (reg)
/* Strict_low_part requires reload the register not
the sub-register. */
/* Strict_low_part requires reloading the register and not
just the subreg. Likewise for a strict subreg no wider
than a word for WORD_REGISTER_OPERATIONS targets. */
&& (curr_static_id->operand[i].strict_low
|| (GET_MODE_SIZE (mode)
<= GET_MODE_SIZE (GET_MODE (reg))
Expand All @@ -4235,7 +4236,11 @@ curr_insn_transform (bool check_only_p)
&& (goal_alt[i] == NO_REGS
|| (simplify_subreg_regno
(ira_class_hard_regs[goal_alt[i]][0],
GET_MODE (reg), byte, mode) >= 0)))))
GET_MODE (reg), byte, mode) >= 0)))
|| (GET_MODE_PRECISION (mode)
< GET_MODE_PRECISION (GET_MODE (reg))
&& GET_MODE_SIZE (GET_MODE (reg)) <= UNITS_PER_WORD
&& WORD_REGISTER_OPERATIONS)))
{
/* An OP_INOUT is required when reloading a subreg of a
mode wider than a word to ensure that data beyond the
Expand Down

0 comments on commit ea82cca

Please sign in to comment.