From 43fa41c1aaa57d59cbb00ed5c8cfa185d075b105 Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Sun, 8 Apr 2018 06:00:34 +0000 Subject: [PATCH] [NDS32] New option -malways-align and -malign-functions. gcc/ * config/nds32/nds32-md-auxiliary.c (output_cond_branch): Output align information if necessary. (output_cond_branch_compare_zero): Likewise. * config/nds32/nds32.c (nds32_adjust_insn_length): Consider align case. (nds32_target_alignment): Refine for alignment. * config/nds32/nds32.h (NDS32_ALIGN_P): Define. (FUNCTION_BOUNDARY): Modify. * config/nds32/nds32.md (call_internal, call_value_internal): Consider align case. * config/nds32/nds32.opt (malways-align, malign-functions): New. From-SVN: r259217 --- gcc/ChangeLog | 13 ++++++++ gcc/config/nds32/nds32-md-auxiliary.c | 20 +++++++----- gcc/config/nds32/nds32.c | 47 ++++++++++++++++----------- gcc/config/nds32/nds32.h | 8 ++++- gcc/config/nds32/nds32.md | 38 ++++++++++++++++++---- gcc/config/nds32/nds32.opt | 8 +++++ 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1cd8f38d86d..6f98ac7af4b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2018-04-08 Chung-Ju Wu + + * config/nds32/nds32-md-auxiliary.c (output_cond_branch): Output align + information if necessary. + (output_cond_branch_compare_zero): Likewise. + * config/nds32/nds32.c (nds32_adjust_insn_length): Consider align case. + (nds32_target_alignment): Refine for alignment. + * config/nds32/nds32.h (NDS32_ALIGN_P): Define. + (FUNCTION_BOUNDARY): Modify. + * config/nds32/nds32.md (call_internal, call_value_internal): Consider + align case. + * config/nds32/nds32.opt (malways-align, malign-functions): New. + 2018-04-08 Monk Chiang * config/nds32/constants.md (unspec_volatile_element): Add values for diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c index 95bd82969ab..720e85a20eb 100644 --- a/gcc/config/nds32/nds32-md-auxiliary.c +++ b/gcc/config/nds32/nds32-md-auxiliary.c @@ -128,6 +128,8 @@ output_cond_branch (int code, const char *suffix, bool r5_p, { char pattern[256]; const char *cond_code; + bool align_p = NDS32_ALIGN_P (); + const char *align = align_p ? "\t.align\t2\n" : ""; if (r5_p && REGNO (operands[2]) == 5 && TARGET_16_BIT) { @@ -170,14 +172,14 @@ output_cond_branch (int code, const char *suffix, bool r5_p, if (r5_p && TARGET_16_BIT) { snprintf (pattern, sizeof (pattern), - "b%ss38\t %%2, .LCB%%=\n\tj\t%%3\n.LCB%%=:", - cond_code); + "b%ss38\t %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:", + cond_code, align); } else { snprintf (pattern, sizeof (pattern), - "b%s%s\t%%1, %%2, .LCB%%=\n\tj\t%%3\n.LCB%%=:", - cond_code, suffix); + "b%s%s\t%%1, %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:", + cond_code, suffix, align); } } else @@ -207,6 +209,8 @@ output_cond_branch_compare_zero (int code, const char *suffix, { char pattern[256]; const char *cond_code; + bool align_p = NDS32_ALIGN_P (); + const char *align = align_p ? "\t.align\t2\n" : ""; if (long_jump_p) { int inverse_code = nds32_inverse_cond_code (code); @@ -221,8 +225,8 @@ output_cond_branch_compare_zero (int code, const char *suffix, .LCB0: */ snprintf (pattern, sizeof (pattern), - "b%sz%s\t.LCB%%=\n\tj\t%%2\n.LCB%%=:", - cond_code, suffix); + "b%sz%s\t.LCB%%=\n\tj\t%%2\n%s.LCB%%=:", + cond_code, suffix, align); } else { @@ -233,8 +237,8 @@ output_cond_branch_compare_zero (int code, const char *suffix, .LCB0: */ snprintf (pattern, sizeof (pattern), - "b%sz%s\t%%1, .LCB%%=\n\tj\t%%2\n.LCB%%=:", - cond_code, suffix); + "b%sz%s\t%%1, .LCB%%=\n\tj\t%%2\n%s.LCB%%=:", + cond_code, suffix, align); } } else diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 9bd7f3fdb0c..76980d3ab1c 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -1566,6 +1566,12 @@ nds32_adjust_insn_length (rtx_insn *insn, int length) case CODE_FOR_call_internal: case CODE_FOR_call_value_internal: { + if (NDS32_ALIGN_P ()) + { + rtx_insn *next_insn = next_active_insn (insn); + if (next_insn && get_attr_length (next_insn) != 2) + adjust_value += 2; + } /* We need insert a nop after a noretun function call to prevent software breakpoint corrupt the next function. */ if (find_reg_note (insn, REG_NORETURN, NULL_RTX)) @@ -4749,6 +4755,28 @@ nds32_ls_333_p (rtx rt, rtx ra, rtx imm, machine_mode mode) return false; } +/* Return alignment for the label. */ +int +nds32_target_alignment (rtx_insn *label) +{ + rtx_insn *insn; + + if (!NDS32_ALIGN_P ()) + return 0; + + insn = next_active_insn (label); + + /* Always align to 4 byte when first instruction after label is jump + instruction since length for that might changed, so let's always align + it for make sure we don't lose any perfomance here. */ + if (insn == 0 + || (get_attr_length (insn) == 2 + && !JUMP_P (insn) && !CALL_P (insn))) + return 0; + else + return 2; +} + bool nds32_split_double_word_load_store_p(rtx *operands, bool load_p) { @@ -4780,25 +4808,6 @@ nds32_use_blocks_for_constant_p (machine_mode mode, return false; } -/* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */ -int -nds32_target_alignment (rtx_insn *label) -{ - rtx_insn *insn; - - if (optimize_size) - return 0; - - insn = next_active_insn (label); - - if (insn == 0) - return 0; - else if ((get_attr_length (insn) % 4) == 0) - return 2; - else - return 0; -} - /* ------------------------------------------------------------------------ */ /* PART 5: Initialize target hook structure and definitions. */ diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h index 13664f187e5..dc82c0a9494 100644 --- a/gcc/config/nds32/nds32.h +++ b/gcc/config/nds32/nds32.h @@ -135,6 +135,11 @@ enum nds32_16bit_address_type #define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0) #define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0) +/* Determine whether we would like to have code generation strictly aligned. + We set it strictly aligned when -malways-align is enabled. + Check gcc/common/config/nds32/nds32-common.c for the optimizations that + apply -malways-align. */ +#define NDS32_ALIGN_P() (TARGET_ALWAYS_ALIGN) /* Get alignment according to mode or type information. When 'type' is nonnull, there is no need to look at 'mode'. */ #define NDS32_MODE_TYPE_ALIGN(mode, type) \ @@ -643,7 +648,8 @@ enum nds32_builtins #define STACK_BOUNDARY 64 -#define FUNCTION_BOUNDARY 32 +#define FUNCTION_BOUNDARY \ + ((NDS32_ALIGN_P () || TARGET_ALIGN_FUNCTION) ? 32 : 16) #define BIGGEST_ALIGNMENT 64 diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md index 9e3e20a52fa..dd25e0690ef 100644 --- a/gcc/config/nds32/nds32.md +++ b/gcc/config/nds32/nds32.md @@ -1426,16 +1426,29 @@ (clobber (reg:SI TA_REGNUM))])] "" { + rtx_insn *next_insn = next_active_insn (insn); + bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) + && NDS32_ALIGN_P (); switch (which_alternative) { case 0: if (TARGET_16_BIT) - return "jral5\t%0"; + { + if (align_p) + return "jral5\t%0\;.align 2"; + else + return "jral5\t%0"; + } else - return "jral\t%0"; + { + if (align_p) + return "jral\t%0\;.align 2"; + else + return "jral\t%0"; + } case 1: return nds32_output_call (insn, operands, operands[0], - "bal\t%0", "jal\t%0", false); + "bal\t%0", "jal\t%0", align_p); default: gcc_unreachable (); } @@ -1477,16 +1490,29 @@ (clobber (reg:SI TA_REGNUM))])] "" { + rtx_insn *next_insn = next_active_insn (insn); + bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) + && NDS32_ALIGN_P (); switch (which_alternative) { case 0: if (TARGET_16_BIT) - return "jral5\t%1"; + { + if (align_p) + return "jral5\t%1\;.align 2"; + else + return "jral5\t%1"; + } else - return "jral\t%1"; + { + if (align_p) + return "jral\t%1\;.align 2"; + else + return "jral\t%1"; + } case 1: return nds32_output_call (insn, operands, operands[1], - "bal\t%1", "jal\t%1", false); + "bal\t%1", "jal\t%1", align_p); default: gcc_unreachable (); } diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt index bb2bbce18eb..ec6b9d47864 100644 --- a/gcc/config/nds32/nds32.opt +++ b/gcc/config/nds32/nds32.opt @@ -69,6 +69,14 @@ Use full-set registers for register allocation. ; --------------------------------------------------------------- +malways-align +Target Mask(ALWAYS_ALIGN) +Always align function entry, jump target and return address. + +malign-functions +Target Mask(ALIGN_FUNCTION) +Align function entry to 4 byte. + mbig-endian Target Undocumented RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN) Generate code in big-endian mode. -- 2.30.2