From a67a9ad833bba4d3f89eb1b3c8dec312511a1d58 Mon Sep 17 00:00:00 2001 From: liuhongt Date: Wed, 29 May 2024 11:14:26 +0800 Subject: [PATCH 1/5] [Backport] Align tight and hot loops without a max-skip limit Reference: https://gcc.gnu.org/cgit/gcc/commit/?id=b644126237a1aa8599f767a5e0bbada1d7286f44 Backport the initial x86 tight-loop alignment implementation to the EulerGCC GCC 12 base. Signed-off-by: Zhongjie Guo (cherry picked from commit 2b2e1efd85ad070698033a3b3d0d784e37ea9d1f) --- gcc/config/i386/i386.cc | 148 +++++++++++++++++++++++++++++++++++++++- gcc/config/i386/i386.md | 10 +-- 2 files changed, 153 insertions(+), 5 deletions(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 169b2dd24b6..a4d41cffb80 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -21742,7 +21742,7 @@ ix86_avoid_jump_mispredicts (void) if (dump_file) fprintf (dump_file, "Padding insn %i by %i bytes!\n", INSN_UID (insn), padsize); - emit_insn_before (gen_pad (GEN_INT (padsize)), insn); + emit_insn_before (gen_max_skip_align (GEN_INT (4), GEN_INT (padsize)), insn); } } } @@ -22015,6 +22015,150 @@ ix86_split_stlf_stall_load () } } +/* When a hot loop can be fit into one cacheline, + force align the loop without considering the max skip. */ +static void +ix86_align_loops () +{ + basic_block bb; + + /* Don't do this when we don't know cache line size. */ + if (ix86_cost->prefetch_block == 0) + return; + + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + profile_count count_threshold = cfun->cfg->count_max / param_align_threshold; + FOR_EACH_BB_FN (bb, cfun) + { + rtx_insn *label = BB_HEAD (bb); + bool has_fallthru = 0; + edge e; + edge_iterator ei; + + if (!LABEL_P (label)) + continue; + + profile_count fallthru_count = profile_count::zero (); + profile_count branch_count = profile_count::zero (); + + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (e->flags & EDGE_FALLTHRU) + has_fallthru = 1, fallthru_count += e->count (); + else + branch_count += e->count (); + } + + if (!fallthru_count.initialized_p () || !branch_count.initialized_p ()) + continue; + + if (bb->loop_father + && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun) + && (has_fallthru + ? (!(single_succ_p (bb) + && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)) + && optimize_bb_for_speed_p (bb) + && branch_count + fallthru_count > count_threshold + && (branch_count > fallthru_count * param_align_loop_iterations)) + /* In case there'no fallthru for the loop. + Nops inserted won't be executed. */ + : (branch_count > count_threshold + || (bb->count > bb->prev_bb->count * 10 + && (bb->prev_bb->count + <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2))))) + { + rtx_insn* insn, *end_insn; + HOST_WIDE_INT size = 0; + bool padding_p = true; + basic_block tbb = bb; + unsigned cond_branch_num = 0; + bool detect_tight_loop_p = false; + + for (unsigned int i = 0; i != bb->loop_father->num_nodes; + i++, tbb = tbb->next_bb) + { + /* Only handle continuous cfg layout. */ + if (bb->loop_father != tbb->loop_father) + { + padding_p = false; + break; + } + + FOR_BB_INSNS (tbb, insn) + { + if (!NONDEBUG_INSN_P (insn)) + continue; + size += ix86_min_insn_size (insn); + + /* We don't know size of inline asm. + Don't align loop for call. */ + if (asm_noperands (PATTERN (insn)) >= 0 + || CALL_P (insn)) + { + size = -1; + break; + } + } + + if (size == -1 || size > ix86_cost->prefetch_block) + { + padding_p = false; + break; + } + + FOR_EACH_EDGE (e, ei, tbb->succs) + { + /* It could be part of the loop. */ + if (e->dest == bb) + { + detect_tight_loop_p = true; + break; + } + } + + if (detect_tight_loop_p) + break; + + end_insn = BB_END (tbb); + if (JUMP_P (end_insn)) + { + /* For decoded icache: + 1. Up to two branches are allowed per Way. + 2. A non-conditional branch is the last micro-op in a Way. + */ + if (onlyjump_p (end_insn) + && (any_uncondjump_p (end_insn) + || single_succ_p (tbb))) + { + padding_p = false; + break; + } + else if (++cond_branch_num >= 2) + { + padding_p = false; + break; + } + } + + } + + if (padding_p && detect_tight_loop_p) + { + emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)), + GEN_INT (0)), label); + /* End of function. */ + if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun)) + break; + /* Skip bb which already fits into one cacheline. */ + bb = tbb; + } + } + } + + loop_optimizer_finalize (); + free_dominance_info (CDI_DOMINATORS); +} + /* Implement machine specific optimizations. We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */ static void @@ -22038,6 +22182,8 @@ ix86_reorg (void) #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN if (TARGET_FOUR_JUMP_LIMIT) ix86_avoid_jump_mispredicts (); + + ix86_align_loops (); #endif } } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index d23f3dac6a0..e2fe2d0802e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -15536,16 +15536,18 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) -;; Pad to 16-byte boundary, max skip in op0. Used to avoid +;; Pad to 1 << op0 byte boundary, max skip in op1. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. +;; Also it's used to align tight loops which can be fix into 1 cacheline. +;; It can help code prefetch and reduce DSB miss. -(define_insn "pad" - [(unspec_volatile [(match_operand 0)] UNSPECV_ALIGN)] +(define_insn "max_skip_align" + [(unspec_volatile [(match_operand 0) (match_operand 1)] UNSPECV_ALIGN)] "" { #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN - ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0])); + ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, (int)INTVAL (operands[0]), (int)INTVAL (operands[1])); #else /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. The align insn is used to avoid 3 jump instructions in the row to improve -- Gitee From 5460f4f76e17984e6c9d1ad30533f7a81c00531f Mon Sep 17 00:00:00 2001 From: liuhongt Date: Mon, 12 Aug 2024 14:35:31 +0800 Subject: [PATCH 2/5] [Backport] Move tight-loop alignment into a separate RTL pass Reference: https://gcc.gnu.org/cgit/gcc/commit/?id=c3c83d22d212a35cb1bfb8727477819463f0dcd8 Move the alignment logic after ENDBR insertion and adapt the implementation to the GCC 12 profile_count API. Signed-off-by: Zhongjie Guo (cherry picked from commit 6245f19a2e2406b14534bcb7a29e627fc791818c) --- gcc/config/i386/i386-features.cc | 197 ++++++++++++++++++++++++++++++- gcc/config/i386/i386-passes.def | 3 + gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.cc | 149 +---------------------- 4 files changed, 201 insertions(+), 149 deletions(-) diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 6a2444eb6b6..3f43d11a313 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -2163,6 +2163,201 @@ make_pass_insert_endbr_and_patchable_area (gcc::context *ctxt) return new pass_insert_endbr_and_patchable_area (ctxt); } +/* When a hot loop can be fit into one cacheline, + force align the loop without considering the max skip. */ +static void +ix86_align_loops () +{ + basic_block bb; + + /* Don't do this when we don't know cache line size. */ + if (ix86_cost->prefetch_block == 0) + return; + + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + profile_count count_threshold = cfun->cfg->count_max.apply_scale + (1, param_align_threshold); + FOR_EACH_BB_FN (bb, cfun) + { + rtx_insn *label = BB_HEAD (bb); + bool has_fallthru = 0; + edge e; + edge_iterator ei; + + if (!LABEL_P (label)) + continue; + + profile_count fallthru_count = profile_count::zero (); + profile_count branch_count = profile_count::zero (); + + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (e->flags & EDGE_FALLTHRU) + has_fallthru = 1, fallthru_count += e->count (); + else + branch_count += e->count (); + } + + if (!fallthru_count.initialized_p () || !branch_count.initialized_p ()) + continue; + + if (bb->loop_father + && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun) + && (has_fallthru + ? (!(single_succ_p (bb) + && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)) + && optimize_bb_for_speed_p (bb) + && branch_count + fallthru_count > count_threshold + && (branch_count + > fallthru_count.apply_scale + (param_align_loop_iterations, 1))) + /* In case there'no fallthru for the loop. + Nops inserted won't be executed. */ + : (branch_count > count_threshold + || (bb->count > bb->prev_bb->count.apply_scale (10, 1) + && (bb->prev_bb->count + <= ENTRY_BLOCK_PTR_FOR_FN (cfun) + ->count.apply_scale (1, 2)))))) + { + rtx_insn* insn, *end_insn; + HOST_WIDE_INT size = 0; + bool padding_p = true; + basic_block tbb = bb; + unsigned cond_branch_num = 0; + bool detect_tight_loop_p = false; + + for (unsigned int i = 0; i != bb->loop_father->num_nodes; + i++, tbb = tbb->next_bb) + { + /* Only handle continuous cfg layout. */ + if (bb->loop_father != tbb->loop_father) + { + padding_p = false; + break; + } + + FOR_BB_INSNS (tbb, insn) + { + if (!NONDEBUG_INSN_P (insn)) + continue; + size += ix86_min_insn_size (insn); + + /* We don't know size of inline asm. + Don't align loop for call. */ + if (asm_noperands (PATTERN (insn)) >= 0 + || CALL_P (insn)) + { + size = -1; + break; + } + } + + if (size == -1 || size > ix86_cost->prefetch_block) + { + padding_p = false; + break; + } + + FOR_EACH_EDGE (e, ei, tbb->succs) + { + /* It could be part of the loop. */ + if (e->dest == bb) + { + detect_tight_loop_p = true; + break; + } + } + + if (detect_tight_loop_p) + break; + + end_insn = BB_END (tbb); + if (JUMP_P (end_insn)) + { + /* For decoded icache: + 1. Up to two branches are allowed per Way. + 2. A non-conditional branch is the last micro-op in a Way. + */ + if (onlyjump_p (end_insn) + && (any_uncondjump_p (end_insn) + || single_succ_p (tbb))) + { + padding_p = false; + break; + } + else if (++cond_branch_num >= 2) + { + padding_p = false; + break; + } + } + + } + + if (padding_p && detect_tight_loop_p) + { + emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)), + GEN_INT (0)), label); + /* End of function. */ + if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun)) + break; + /* Skip bb which already fits into one cacheline. */ + bb = tbb; + } + } + } + + loop_optimizer_finalize (); + free_dominance_info (CDI_DOMINATORS); +} + +namespace { + +const pass_data pass_data_align_tight_loops = +{ + RTL_PASS, /* type */ + "align_tight_loops", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +class pass_align_tight_loops : public rtl_opt_pass +{ +public: + pass_align_tight_loops (gcc::context *ctxt) + : rtl_opt_pass (pass_data_align_tight_loops, ctxt) + {} + + /* opt_pass methods: */ + bool gate (function *) final override + { + return optimize && optimize_function_for_speed_p (cfun); + } + + unsigned int execute (function *) final override + { + timevar_push (TV_MACH_DEP); +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN + ix86_align_loops (); +#endif + timevar_pop (TV_MACH_DEP); + return 0; + } +}; // class pass_align_tight_loops + +} // anon namespace + +rtl_opt_pass * +make_pass_align_tight_loops (gcc::context *ctxt) +{ + return new pass_align_tight_loops (ctxt); +} + /* At entry of the nearest common dominator for basic blocks with conversions/rcp/sqrt/rsqrt/round, generate a single vxorps %xmmN, %xmmN, %xmmN @@ -2964,5 +3159,3 @@ ix86_generate_version_dispatcher_body (void *node_p) pop_cfun (); return resolver_decl; } - - diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def index ab49882457d..bd6ea387865 100644 --- a/gcc/config/i386/i386-passes.def +++ b/gcc/config/i386/i386-passes.def @@ -31,5 +31,8 @@ along with GCC; see the file COPYING3. If not see INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */); INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbr_and_patchable_area); + /* pass_align_tight_loops must be after pass_insert_endbr_and_patchable_area. + PR116174. */ + INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_align_tight_loops); INSERT_PASS_AFTER (pass_combine, 1, pass_remove_partial_avx_dependency); diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 5b09924c929..07f0d40407a 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -397,6 +397,7 @@ extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *); extern rtl_opt_pass *make_pass_stv (gcc::context *); extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area (gcc::context *); +extern rtl_opt_pass *make_pass_align_tight_loops (gcc::context *); extern rtl_opt_pass *make_pass_remove_partial_avx_dependency (gcc::context *); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index a4d41cffb80..291a191d8cb 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -21742,7 +21742,8 @@ ix86_avoid_jump_mispredicts (void) if (dump_file) fprintf (dump_file, "Padding insn %i by %i bytes!\n", INSN_UID (insn), padsize); - emit_insn_before (gen_max_skip_align (GEN_INT (4), GEN_INT (padsize)), insn); + emit_insn_before (gen_max_skip_align (GEN_INT (4), + GEN_INT (padsize)), insn); } } } @@ -22015,150 +22016,6 @@ ix86_split_stlf_stall_load () } } -/* When a hot loop can be fit into one cacheline, - force align the loop without considering the max skip. */ -static void -ix86_align_loops () -{ - basic_block bb; - - /* Don't do this when we don't know cache line size. */ - if (ix86_cost->prefetch_block == 0) - return; - - loop_optimizer_init (AVOID_CFG_MODIFICATIONS); - profile_count count_threshold = cfun->cfg->count_max / param_align_threshold; - FOR_EACH_BB_FN (bb, cfun) - { - rtx_insn *label = BB_HEAD (bb); - bool has_fallthru = 0; - edge e; - edge_iterator ei; - - if (!LABEL_P (label)) - continue; - - profile_count fallthru_count = profile_count::zero (); - profile_count branch_count = profile_count::zero (); - - FOR_EACH_EDGE (e, ei, bb->preds) - { - if (e->flags & EDGE_FALLTHRU) - has_fallthru = 1, fallthru_count += e->count (); - else - branch_count += e->count (); - } - - if (!fallthru_count.initialized_p () || !branch_count.initialized_p ()) - continue; - - if (bb->loop_father - && bb->loop_father->latch != EXIT_BLOCK_PTR_FOR_FN (cfun) - && (has_fallthru - ? (!(single_succ_p (bb) - && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)) - && optimize_bb_for_speed_p (bb) - && branch_count + fallthru_count > count_threshold - && (branch_count > fallthru_count * param_align_loop_iterations)) - /* In case there'no fallthru for the loop. - Nops inserted won't be executed. */ - : (branch_count > count_threshold - || (bb->count > bb->prev_bb->count * 10 - && (bb->prev_bb->count - <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2))))) - { - rtx_insn* insn, *end_insn; - HOST_WIDE_INT size = 0; - bool padding_p = true; - basic_block tbb = bb; - unsigned cond_branch_num = 0; - bool detect_tight_loop_p = false; - - for (unsigned int i = 0; i != bb->loop_father->num_nodes; - i++, tbb = tbb->next_bb) - { - /* Only handle continuous cfg layout. */ - if (bb->loop_father != tbb->loop_father) - { - padding_p = false; - break; - } - - FOR_BB_INSNS (tbb, insn) - { - if (!NONDEBUG_INSN_P (insn)) - continue; - size += ix86_min_insn_size (insn); - - /* We don't know size of inline asm. - Don't align loop for call. */ - if (asm_noperands (PATTERN (insn)) >= 0 - || CALL_P (insn)) - { - size = -1; - break; - } - } - - if (size == -1 || size > ix86_cost->prefetch_block) - { - padding_p = false; - break; - } - - FOR_EACH_EDGE (e, ei, tbb->succs) - { - /* It could be part of the loop. */ - if (e->dest == bb) - { - detect_tight_loop_p = true; - break; - } - } - - if (detect_tight_loop_p) - break; - - end_insn = BB_END (tbb); - if (JUMP_P (end_insn)) - { - /* For decoded icache: - 1. Up to two branches are allowed per Way. - 2. A non-conditional branch is the last micro-op in a Way. - */ - if (onlyjump_p (end_insn) - && (any_uncondjump_p (end_insn) - || single_succ_p (tbb))) - { - padding_p = false; - break; - } - else if (++cond_branch_num >= 2) - { - padding_p = false; - break; - } - } - - } - - if (padding_p && detect_tight_loop_p) - { - emit_insn_before (gen_max_skip_align (GEN_INT (ceil_log2 (size)), - GEN_INT (0)), label); - /* End of function. */ - if (!tbb || tbb == EXIT_BLOCK_PTR_FOR_FN (cfun)) - break; - /* Skip bb which already fits into one cacheline. */ - bb = tbb; - } - } - } - - loop_optimizer_finalize (); - free_dominance_info (CDI_DOMINATORS); -} - /* Implement machine specific optimizations. We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */ static void @@ -22182,8 +22039,6 @@ ix86_reorg (void) #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN if (TARGET_FOUR_JUMP_LIMIT) ix86_avoid_jump_mispredicts (); - - ix86_align_loops (); #endif } } -- Gitee From 66e490ba8fee92987a84929f13a6b11c5166f7c8 Mon Sep 17 00:00:00 2001 From: MayShao-oc Date: Thu, 7 Nov 2024 10:57:02 +0800 Subject: [PATCH 3/5] [Backport] Add a tune control for tight-loop alignment Reference: https://gcc.gnu.org/cgit/gcc/commit/?id=6350e956d1a74963a62bedabef3d4a1a3f2d4852 Backport the target tune gate used to control the late tight-loop alignment pass. Signed-off-by: Zhongjie Guo (cherry picked from commit 0343fa1f3941e5db719be5f3dd78f8368400494d) --- gcc/config/i386/i386-features.cc | 4 +++- gcc/config/i386/i386.h | 2 ++ gcc/config/i386/x86-tune.def | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 3f43d11a313..27bbf94b237 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -2336,7 +2336,9 @@ public: /* opt_pass methods: */ bool gate (function *) final override { - return optimize && optimize_function_for_speed_p (cfun); + return TARGET_ALIGN_TIGHT_LOOPS + && optimize + && optimize_function_for_speed_p (cfun); } unsigned int execute (function *) final override diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 34c9f2b0182..0f187c50a5d 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -364,6 +364,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; #define TARGET_INTER_UNIT_CONVERSIONS \ ix86_tune_features[X86_TUNE_INTER_UNIT_CONVERSIONS] #define TARGET_FOUR_JUMP_LIMIT ix86_tune_features[X86_TUNE_FOUR_JUMP_LIMIT] +#define TARGET_ALIGN_TIGHT_LOOPS \ + ix86_tune_features[X86_TUNE_ALIGN_TIGHT_LOOPS] #define TARGET_SCHEDULE ix86_tune_features[X86_TUNE_SCHEDULE] #define TARGET_USE_BT ix86_tune_features[X86_TUNE_USE_BT] #define TARGET_USE_INCDEC ix86_tune_features[X86_TUNE_USE_INCDEC] diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index a7c3b252185..6e5008ac8b6 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -224,6 +224,10 @@ DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", m_PPRO | m_P4_NOCONA | m_BONNELL | m_SILVERMONT | m_KNL | m_KNM | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL | m_ATHLON_K8 | m_AMDFAM10) +/* X86_TUNE_ALIGN_TIGHT_LOOPS: if false, tight loops are not aligned. */ +DEF_TUNE (X86_TUNE_ALIGN_TIGHT_LOOPS, "align_tight_loops", + ~(m_ZHAOXIN | m_CASCADELAKE | m_SKYLAKE_AVX512)) + /*****************************************************************************/ /* Integer instruction selection tuning */ /*****************************************************************************/ -- Gitee From a50608d6a9de73533cdaf260c2929a1f04e148ce Mon Sep 17 00:00:00 2001 From: Lili Cui Date: Wed, 14 Jan 2026 09:53:04 +0800 Subject: [PATCH 4/5] [Backport] x86: Disable tight-loop alignment for CORE_ATOM Reference: https://gcc.gnu.org/cgit/gcc/commit/?id=dfd063aeccb52a51c7d98052920328facec401a9 Preserve the upstream exclusion for CORE_ATOM before applying the EulerGCC-specific tune selection. Signed-off-by: Zhongjie Guo (cherry picked from commit c577beed7c4ed505bd248848dd76e267c5a764ef) --- gcc/config/i386/x86-tune.def | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index 6e5008ac8b6..5f21b288a75 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -226,7 +226,8 @@ DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", /* X86_TUNE_ALIGN_TIGHT_LOOPS: if false, tight loops are not aligned. */ DEF_TUNE (X86_TUNE_ALIGN_TIGHT_LOOPS, "align_tight_loops", - ~(m_ZHAOXIN | m_CASCADELAKE | m_SKYLAKE_AVX512)) + ~(m_ZHAOXIN | m_CASCADELAKE | m_SKYLAKE_AVX512 + | m_CORE_ATOM)) /*****************************************************************************/ /* Integer instruction selection tuning */ -- Gitee From 7e250fd5e7610b43abe5fa24fce8619d30403916 Mon Sep 17 00:00:00 2001 From: Zhongjie Guo Date: Fri, 14 Aug 2026 20:31:36 +0800 Subject: [PATCH 5/5] [EulerGCC] Adapt tight-loop alignment for GCC 12 and c86-4g-m7 Use the GCC 12 profile_count scaling API, enable the tune only for c86-4g-m7, and adapt the focused tests to this branch. The resulting source tree is intentionally identical to the previously validated squashed backport. Signed-off-by: Zhongjie Guo (cherry picked from commit a9e50713c2fee9c50d9f4e13755d213166dabfa8) --- gcc/config/i386/i386-features.cc | 1 + gcc/config/i386/i386.md | 3 ++- gcc/config/i386/x86-tune.def | 4 +--- .../gcc.target/i386/align-tight-loop-generic.c | 11 +++++++++++ gcc/testsuite/gcc.target/i386/pr116174.c | 10 ++++++++++ 5 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/align-tight-loop-generic.c create mode 100644 gcc/testsuite/gcc.target/i386/pr116174.c diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 27bbf94b237..114aa7df8bb 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -3161,3 +3161,4 @@ ix86_generate_version_dispatcher_body (void *node_p) pop_cfun (); return resolver_decl; } + diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e2fe2d0802e..788ea1f93cb 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -15547,7 +15547,8 @@ "" { #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN - ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, (int)INTVAL (operands[0]), (int)INTVAL (operands[1])); + ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, (int)INTVAL (operands[0]), + (int)INTVAL (operands[1])); #else /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. The align insn is used to avoid 3 jump instructions in the row to improve diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index 5f21b288a75..8522a9c5dc1 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -225,9 +225,7 @@ DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", | m_GOLDMONT | m_GOLDMONT_PLUS | m_INTEL | m_ATHLON_K8 | m_AMDFAM10) /* X86_TUNE_ALIGN_TIGHT_LOOPS: if false, tight loops are not aligned. */ -DEF_TUNE (X86_TUNE_ALIGN_TIGHT_LOOPS, "align_tight_loops", - ~(m_ZHAOXIN | m_CASCADELAKE | m_SKYLAKE_AVX512 - | m_CORE_ATOM)) +DEF_TUNE (X86_TUNE_ALIGN_TIGHT_LOOPS, "align_tight_loops", m_C86_4G_M7) /*****************************************************************************/ /* Integer instruction selection tuning */ diff --git a/gcc/testsuite/gcc.target/i386/align-tight-loop-generic.c b/gcc/testsuite/gcc.target/i386/align-tight-loop-generic.c new file mode 100644 index 00000000000..f8000ce9aa2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/align-tight-loop-generic.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -g0 -fcf-protection=branch -mtune=generic" } */ +/* { dg-final { scan-assembler-not "\\.p2align 5" } } */ + +char * +foo (char *dest, const char *src) +{ + while ((*dest++ = *src++) != '\0') + /* nothing */; + return --dest; +} diff --git a/gcc/testsuite/gcc.target/i386/pr116174.c b/gcc/testsuite/gcc.target/i386/pr116174.c new file mode 100644 index 00000000000..a8aaee87f8f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr116174.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -g0 -fcf-protection=branch -mtune=c86-4g-m7" } */ +/* { dg-final { scan-assembler "endbr64\\n\\t\\.p2align 5" } } */ +char * +foo (char *dest, const char *src) +{ + while ((*dest++ = *src++) != '\0') + /* nothing */; + return --dest; +} -- Gitee