diff --git a/0310-CFGO-Add-cfgo-pgo-optimization.patch b/0310-CFGO-Add-cfgo-pgo-optimization.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4a930aba6773ef382ee5c83821b5f3a1894aa8df
--- /dev/null
+++ b/0310-CFGO-Add-cfgo-pgo-optimization.patch
@@ -0,0 +1,168 @@
+From 84635dc65ebe285457d0c16bbb5caf995f803436 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 27 Nov 2024 18:36:27 +0800
+Subject: [PATCH] [CFGO] Add cfgo-pgo optimization
+
+Add a cfgo-pgo to better optimize with AI4C
+---
+ gcc/common.opt | 16 +++++++++++++
+ gcc/gcc.cc | 4 ++--
+ gcc/lto-cgraph.cc | 3 ++-
+ gcc/opts.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 77 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index c9baa12be..a45fbfe1b 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2485,6 +2485,14 @@ fprofile-generate=
+ Common Joined RejectNegative
+ Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
+
++fcfgo-profile-generate
++Common Var(flag_cfgo_profile_generate)
++Enable common options for generating cfgo profile info for profile feedback directed optimizations.
++
++fcfgo-profile-generate=
++Common Joined RejectNegative
++Enable common options for generating cfgo profile info for profile feedback directed optimizations, and set -fprofile-dir=.
++
+ fcfgo-csprofile-generate
+ Common Var(flag_csprofile_generate)
+ Enable common options for generating context sensitive profile info for profile feedback directed optimizations.
+@@ -2517,6 +2525,14 @@ fprofile-use=
+ Common Joined RejectNegative
+ Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
+
++fcfgo-profile-use
++Common Var(flag_cfgo_profile_use)
++Enable common options for performing profile feedback directed optimizations.
++
++fcfgo-profile-use=
++Common Joined RejectNegative
++Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
++
+ fcfgo-csprofile-use
+ Common Var(flag_csprofile_use)
+ Enable common options for performing context sensitive profile feedback directed optimizations.
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index b37b50be2..e5c43dd90 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -1147,7 +1147,7 @@ proper position among the other output files. */
+ %:include(libgomp.spec)%(link_gomp)}\
+ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
+ %(mflib) " STACK_SPLIT_SPEC "\
+- %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:-lgcov} \
++ %{fprofile-arcs|fprofile-generate*|fcfgo-profile-generate*|fcfgo-csprofile-generate*|coverage:-lgcov} \
+ " SANITIZER_SPEC " \
+ %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\
+ %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} \n%(post_link) }}}}}}"
+@@ -1266,7 +1266,7 @@ static const char *cc1_options =
+ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
+ %{fsyntax-only:-o %j} %{-param*}\
+ %{coverage:-fprofile-arcs -ftest-coverage}\
+- %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:\
++ %{fprofile-arcs|fprofile-generate*|fcfgo-profile-generate*|fcfgo-csprofile-generate*|coverage:\
+ %{!fprofile-update=single:\
+ %{pthread:-fprofile-update=prefer-atomic}}}";
+
+diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
+index fd41941d1..9a30f1190 100644
+--- a/gcc/lto-cgraph.cc
++++ b/gcc/lto-cgraph.cc
+@@ -1681,7 +1681,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
+ stages with unknown bug resulted in different scaling results, which led
+ different optimization decisions and finally led to coverage mismatch.
+ Therefore, skip the following processing steps when doing cspgo. */
+- if (flag_csprofile_generate || flag_csprofile_use)
++ if (flag_csprofile_generate || flag_csprofile_use
++ || flag_cfgo_profile_generate || flag_cfgo_profile_use)
+ return;
+
+ /* Now compute count_materialization_scale of each node.
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 89d03e834..84dd8925a 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2087,6 +2087,38 @@ enable_fdo_optimizations (struct gcc_options *opts,
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value);
+ }
+
++/* Enable cfgo-related flags. */
++
++static void
++enable_cfgo_optimizations (struct gcc_options *opts,
++ struct gcc_options *opts_set,
++ int value)
++{
++ SET_OPTION_IF_UNSET (opts, opts_set, flag_modulo_sched, value);
++ SET_OPTION_IF_UNSET (opts, opts_set, flag_selective_scheduling, value);
++ SET_OPTION_IF_UNSET (opts, opts_set, flag_rename_registers, value);
++
++ SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto, 185);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_inline_unit_growth, 66);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_recursive_depth_auto,
++ 31);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_large_function_insns, 7286);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_large_function_growth, 89);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_large_unit_insns, 11783);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_eval_threshold, 864);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_loop_hint_bonus, 440);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_max_recursive_depth, 29);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_min_recursive_probability,
++ 4);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_recursive_freq_factor, 18);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_recursion_penalty, 64);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_single_call_penalty, 43);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_unit_growth, 96);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_large_unit_insns, 47631);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_value_list_size, 12);
++ SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_profile_count_base, 54);
++}
++
+ /* -f{,no-}sanitize{,-recover}= suboptions. */
+ const struct sanitizer_opts_s sanitizer_opts[] =
+ {
+@@ -3033,6 +3065,18 @@ common_handle_option (struct gcc_options *opts,
+ /* Deferred. */
+ break;
+
++ case OPT_fcfgo_profile_use_:
++ /* No break here - do -fcfgo-profile-use processing. */
++ /* FALLTHRU */
++ case OPT_fcfgo_profile_use:
++ value = true;
++ if (value)
++ {
++ enable_cfgo_optimizations (opts, opts_set, value);
++ SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_use, value);
++ }
++ /* No break here - do -fprofile-use processing. */
++ /* FALLTHRU */
+ case OPT_fprofile_use_:
+ opts->x_profile_data_prefix = xstrdup (arg);
+ opts->x_flag_profile_use = true;
+@@ -3090,6 +3134,19 @@ common_handle_option (struct gcc_options *opts,
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_reorg, value);
+ break;
+
++ case OPT_fcfgo_profile_generate_:
++ /* No break here - do -fcfgo-profile-generate processing. */
++ /* FALLTHRU */
++ case OPT_fcfgo_profile_generate:
++ value = true;
++ if (value)
++ {
++ enable_cfgo_optimizations (opts, opts_set, value);
++ SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_generate,
++ value);
++ }
++ /* No break here - do -fcfgo-profile-generate processing. */
++ /* FALLTHRU */
+ case OPT_fprofile_generate_:
+ opts->x_profile_data_prefix = xstrdup (arg);
+ value = true;
+--
+2.25.1
+
diff --git a/0311-PATCH-Add-if-split-optimization-pass.patch b/0311-PATCH-Add-if-split-optimization-pass.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5e3b75e2435c857d786ded4f10a7eba6a5774987
--- /dev/null
+++ b/0311-PATCH-Add-if-split-optimization-pass.patch
@@ -0,0 +1,1203 @@
+From 899db9bca3c2ef3cd346814be761eed8b85f5e1e Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 27 Nov 2024 19:26:13 +0800
+Subject: [PATCH] [PATCH] Add if-split optimization pass
+
+This pass splits conditions like
+if (cond1 or cond2)
+to the sequense of separate conditions.
+
+This happens only if there is a function call under condition
+Which depends on the condition variable.
+---
+ gcc/Makefile.in | 1 +
+ gcc/common.opt | 4 +
+ gcc/gimple-if-split.cc | 567 ++++++++++++++++++++
+ gcc/opts.cc | 2 +-
+ gcc/passes.def | 1 +
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c | 24 +
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c | 45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c | 36 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c | 36 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c | 42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c | 42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c | 45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c | 45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c | 42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c | 44 ++
+ gcc/timevar.def | 1 +
+ gcc/tree-cfg.h | 2 +
+ gcc/tree-pass.h | 1 +
+ gcc/tree-ssa-ifcombine.cc | 6 +-
+ 19 files changed, 981 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/gimple-if-split.cc
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index bb6197a8e..683b28896 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1393,6 +1393,7 @@ OBJS = \
+ gimple-builder.o \
+ gimple-expr.o \
+ gimple-if-to-switch.o \
++ gimple-if-split.o \
+ gimple-iterator.o \
+ gimple-fold.o \
+ gimple-harden-conditionals.o \
+diff --git a/gcc/common.opt b/gcc/common.opt
+index a45fbfe1b..a52fa9814 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1981,6 +1981,10 @@ finstrument-functions-exclude-file-list=
+ Common RejectNegative Joined
+ -finstrument-functions-exclude-file-list=filename,... Do not instrument functions listed in files.
+
++fif-split
++Common Var(flag_if_split) Init(0) Optimization
++Perform splitting if complex conditions on separate ones with clonning their bodies (gimple version).
++
+ fipa-cp
+ Common Var(flag_ipa_cp) Optimization
+ Perform interprocedural constant propagation.
+diff --git a/gcc/gimple-if-split.cc b/gcc/gimple-if-split.cc
+new file mode 100644
+index 000000000..3446204ea
+--- /dev/null
++++ b/gcc/gimple-if-split.cc
+@@ -0,0 +1,567 @@
++/* If-split.
++ Copyright (C) 2024 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++. */
++
++#include "config.h"
++#define INCLUDE_FUNCTIONAL
++#include "system.h"
++#include "coretypes.h"
++#include "tree.h"
++#include "tree-ssa.h"
++#include "tree-pass.h"
++#include "diagnostic-core.h"
++#include "function.h"
++#include "basic-block.h"
++#include "gimple.h"
++#include "gimple-pretty-print.h"
++#include "gimple-iterator.h"
++#include "cfg.h"
++#include "cfghooks.h"
++#include "ssa.h"
++#include "fold-const.h"
++#include "tree-into-ssa.h"
++#include "tree-cfg.h"
++#include "bitmap.h"
++#include "cfganal.h"
++
++/* Perform splitting if-then-else patterns, whose complex OR condition in
++cond-bb contains comparison of some variable with constant and then-bb got
++function call, whose arg list contains this var (or this variable is a
++scalar of an aggregate which is an arg of this call). We split condition on
++two separate ones and duplicate then-bb for each one, thus help ipa const
++prop to propagate corresponding constant in function calls.
++Example:
++ Before:
++ if (n == const || some_cond)
++ func (n);
++ After:
++ if (n == const)
++ func (n);
++ else if (some_cond)
++ func (n); */
++
++//-------------------------------------------------------------------------
++// Auxiliary functions
++//-------------------------------------------------------------------------
++/* Check if arg list of call got n. */
++bool
++got_in_args_p (gimple* call, tree n)
++{
++ unsigned num_args = gimple_call_num_args (call);
++
++ for (int i = 0; i < num_args; i++)
++ {
++ if (n == gimple_call_arg (call, i))
++ return true;
++ }
++
++ return false;
++}
++
++#define SCALAR_NESTING 2
++/* Check if call is "necessary" for n. Call is called "necessary"
++ * for n, if n is one of call args, or n is scalar of some aggregate,
++ * which is one of this call args. Nesting param determines how many
++ * levels of aggregate-scalar nesting we want to check. For example,
++ * if nesting == 2, we allow only 2 levels of nesting, like
++ * outer_aggr->inner_aggr->scalar. */
++static bool
++necessary_call_p (gimple *call, tree n, unsigned nesting)
++{
++ if (!call)
++ return false;
++
++ if (got_in_args_p (call, n))
++ return true;
++
++ /* Else we need to check if n could be a scalar of some aggregate which
++ * is one of call args. */
++ tree scalar = n;
++ tree aggregate = NULL_TREE;
++
++ for (int i = 0; i < nesting; i++)
++ {
++ if (!scalar || TREE_CODE (scalar) != SSA_NAME)
++ return false;
++
++ gimple *scalar_def = SSA_NAME_DEF_STMT (scalar);
++
++ if (!is_gimple_assign (scalar_def)
++ || gimple_assign_rhs_code (scalar_def) != COMPONENT_REF)
++ return false;
++
++ tree scalar_def_rhs = gimple_assign_rhs1 (scalar_def);
++ tree aggregate = TREE_OPERAND (scalar_def_rhs, 0);
++
++ if (TREE_CODE (aggregate) == MEM_REF)
++ aggregate = TREE_OPERAND (aggregate, 0);
++
++ if (aggregate && got_in_args_p (call, aggregate))
++ return true;
++
++ scalar = aggregate;
++ }
++
++ return false;
++}
++
++/* Check if bb got a "necessary" call statement. */
++static bool
++bb_got_necessary_call_p (basic_block bb, tree n, unsigned nesting)
++{
++ gimple *stmt = NULL;
++
++ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
++ gsi_next (&gsi))
++ {
++ gimple *stmt = gsi_stmt (gsi);
++
++ if (is_gimple_call (stmt) && necessary_call_p (stmt, n, nesting))
++ return true;
++ }
++
++ return false;
++}
++
++//-------------------------------------------------------------------------
++// Complex conditions
++//-------------------------------------------------------------------------
++/* Auxiliary struct which contains var and its constant of comaprison
++ * of expr: n == cst. */
++struct var_const
++{
++ tree n = NULL_TREE;
++ tree cst = NULL_TREE;
++};
++
++/* Check if var_def stmt got this pattern:
++ * var = (n == const);
++ * If it does, we need to set var_cst struct. */
++static bool
++comp_with_const_p (gimple *var_def, var_const *var_cst)
++{
++ if (gimple_expr_code (var_def) != EQ_EXPR)
++ return false;
++
++ tree var_def_rhs2 = gimple_assign_rhs2 (var_def);
++
++ if (TREE_CODE (var_def_rhs2) != INTEGER_CST)
++ return false;
++
++ var_cst->n = gimple_assign_rhs1 (var_def);
++ var_cst->cst = var_def_rhs2;
++
++ return true;
++}
++
++/* Auxiliary struct which contains defenition of each part of
++ * complex condition, like:
++ * a = ... <- a_def
++ * b = ... <- b_def
++ * c = a | b <- complex_cond. */
++struct cond_parts_defs
++{
++ gimple *a_def = NULL;
++ gimple *b_def = NULL;
++};
++
++/* Check if cond got this pattern:
++ * a = ...; <- a_def
++ * b = ...; <- b_def
++ * c = a | b;
++ * if (c != 0)
++ * and a_def or b_def is comparison with constant. If it does,
++ * we need to set a with a_def and b with b_def. */
++static bool
++necessary_complex_cond_p (const gimple *cond, basic_block then_bb,
++ cond_parts_defs *defs)
++{
++ tree lhs = gimple_cond_lhs (cond);
++ tree rhs = gimple_cond_rhs (cond);
++
++ /* As we look for: if (c != 0). */
++ if (gimple_cond_code (cond) != NE_EXPR || TREE_CODE (lhs) != SSA_NAME
++ || !integer_zerop (rhs))
++ return false;
++
++ gimple *c_def = SSA_NAME_DEF_STMT (lhs);
++
++ /* As we look for: c = a | b. */
++ if (!c_def || !is_gimple_assign (c_def) || gimple_num_ops (c_def) != 3
++ || gimple_expr_code (c_def) != BIT_IOR_EXPR)
++ return false;
++
++ tree a_var = gimple_assign_rhs1 (c_def);
++ tree b_var = gimple_assign_rhs2 (c_def);
++ gimple *a_def = SSA_NAME_DEF_STMT (a_var);
++ gimple *b_def = SSA_NAME_DEF_STMT (b_var);
++
++ if (!a_def || !is_gimple_assign (a_def) || !b_def
++ || !is_gimple_assign (b_def))
++ return false;
++
++ var_const var_cst;
++
++ if (!(comp_with_const_p (a_def, &var_cst)
++ && bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING))
++ && !(comp_with_const_p (b_def, &var_cst)
++ && bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING)))
++ return false;
++
++ defs->a_def = a_def;
++ defs->b_def = b_def;
++
++ return true;
++}
++
++/* Check if our complex condition seems to be "necessary"
++ * and if it does split it on two separate ones. Like:
++ * a = (n == const); <- a_def
++ * b = smth; <- b_def
++ * c = a | b
++ * if (c != 0)
++ * call func (n, ...)
++ * Transform this to:
++ * if (n == const)
++ * goto then
++ * else if (b != 0)
++ * goto then
++ * then:
++ * call func (n, ...).
++ * A complex condition is called "necessary", if it is OR of two
++ * conditions, one of them is comparison with constant and then_bb
++ * of this cond got "necessary" function_call. To know, what
++ * "necessary" function call means look at necessary_call_p (). */
++static void
++process_complex_cond (basic_block cond_bb, basic_block then_bb,
++ basic_block else_bb)
++{
++ gimple *cond = last_stmt (cond_bb);
++ cond_parts_defs defs;
++
++ if (!can_duplicate_block_p (then_bb)
++ || !necessary_complex_cond_p (cond, then_bb, &defs))
++ return;
++
++ if (dump_file && (dump_flags & TDF_DETAILS))
++ {
++ fprintf (dump_file,
++ "Recognized necessary complex condition: ", cond_bb->index);
++ print_gimple_stmt (dump_file, cond, 0, TDF_NONE);
++ }
++
++ var_const var_cst;
++
++ /* Setting cond. */
++ if (comp_with_const_p (defs.a_def, &var_cst))
++ /* Setting cond as: if (n == const). */
++ gimple_cond_set_condition (as_a (cond), EQ_EXPR, var_cst.n,
++ var_cst.cst);
++ else
++ {
++ /* Setting cond as: if (a != 0). */
++ tree cond_lhs = gimple_assign_lhs (defs.a_def);
++ gimple_cond_set_condition (as_a (cond), NE_EXPR, cond_lhs,
++ build_zero_cst (TREE_TYPE (cond_lhs)));
++ }
++ update_stmt (cond);
++
++ /* Creating inner_cond_bb. */
++ edge then_e = find_edge (cond_bb, then_bb);
++ edge else_e = find_edge (cond_bb, else_bb);
++ basic_block inner_cond_bb = split_edge (else_e);
++
++ /* Setting inner_cond. */
++ gcond *inner_cond = NULL;
++ if (comp_with_const_p (defs.b_def, &var_cst))
++ {
++ /* Setting inner cond as: if (b == const). */
++ inner_cond = gimple_build_cond (EQ_EXPR, var_cst.n, var_cst.cst,
++ NULL_TREE, NULL_TREE);
++ }
++ else
++ {
++ /* Setting inner cond as: if (b != 0). */
++ tree inner_cond_lhs = gimple_assign_lhs (defs.b_def);
++ inner_cond = gimple_build_cond (
++ NE_EXPR, inner_cond_lhs, build_zero_cst (TREE_TYPE (inner_cond_lhs)),
++ NULL_TREE, NULL_TREE);
++ }
++ gimple_stmt_iterator gsi = gsi_last_bb (inner_cond_bb);
++ gsi_insert_after (&gsi, inner_cond, GSI_NEW_STMT);
++
++ /* Configuring edges. */
++ edge inner_cond_then_e = make_edge (inner_cond_bb, then_bb, EDGE_TRUE_VALUE);
++ edge inner_cond_else_e = find_edge (inner_cond_bb, else_bb);
++ inner_cond_else_e->flags = EDGE_FALSE_VALUE;
++
++ /* Setting phinode args in then_bb coming from inner_cond_bb the same as
++ * ones coming from cond_bb. */
++ for (gphi_iterator psi = gsi_start_phis (then_bb); !gsi_end_p (psi);
++ gsi_next (&psi))
++ {
++ gphi *phi = psi.phi ();
++ add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (phi, then_e), inner_cond_then_e,
++ UNKNOWN_LOCATION);
++ }
++
++ /* Updating dominators. */
++ set_immediate_dominator (CDI_DOMINATORS, inner_cond_bb, cond_bb);
++ basic_block cond_bb_postdominator
++ = get_immediate_dominator (CDI_POST_DOMINATORS, cond_bb);
++ set_immediate_dominator (CDI_POST_DOMINATORS, inner_cond_bb,
++ cond_bb_postdominator);
++
++ if (dump_file && (dump_flags & TDF_DETAILS))
++ {
++ fprintf (dump_file, "Successfully transformed:\n (o_cond) ",
++ cond_bb->index);
++ print_gimple_stmt (dump_file, cond, 0, TDF_NONE);
++ fprintf (dump_file, " (i_cond) ", inner_cond_bb->index);
++ print_gimple_stmt (dump_file, inner_cond, 0, TDF_NONE);
++ }
++}
++
++//-------------------------------------------------------------------------
++// Condition pairs
++//-------------------------------------------------------------------------
++/* Transforming cfg if we recognized patern in process_condition_pair (). */
++static basic_block
++make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
++ basic_block then_bb)
++{
++ if (!can_duplicate_block_p (then_bb) || EDGE_COUNT (then_bb->succs) != 1)
++ return NULL;
++
++ edge outer_then_e = find_edge (outer_cond_bb, then_bb);
++
++ /* Making duplication of then_bb. */
++ basic_block then_bb_dom = get_immediate_dominator (CDI_DOMINATORS, then_bb);
++ basic_block merge_bb = split_edge (single_succ_edge (then_bb));
++ basic_block then_bb1 = duplicate_block (then_bb, outer_then_e, outer_cond_bb);
++ edge outer_then1_e = find_edge (outer_cond_bb, then_bb1);
++
++ /* Setting phinode args in then_bb1 coming from outer_cond_bb by previously
++ * collected args_from_outer_cond_bb. */
++ flush_pending_stmts (outer_then1_e);
++
++ /* Updating dominators. */
++ if (then_bb_dom == outer_cond_bb)
++ set_immediate_dominator (CDI_DOMINATORS, then_bb, inner_cond_bb);
++
++ set_immediate_dominator (CDI_DOMINATORS, merge_bb, then_bb_dom);
++ set_immediate_dominator (CDI_DOMINATORS, then_bb1, outer_cond_bb);
++
++ set_immediate_dominator (CDI_POST_DOMINATORS, then_bb, merge_bb);
++ set_immediate_dominator (CDI_POST_DOMINATORS, then_bb1, merge_bb);
++ set_immediate_dominator (CDI_POST_DOMINATORS, merge_bb,
++ single_succ (merge_bb));
++
++ return then_bb1;
++}
++
++/* Here we check if cond of bb got this pattern:
++ * if (n == const)
++ * And if it does we need to set n. */
++static bool
++got_necessary_cond_p (basic_block bb, tree *n)
++{
++ gimple *stmt = last_stmt (bb);
++ if (!stmt || gimple_code (stmt) != GIMPLE_COND)
++ return false;
++
++ gcond *cond = as_a (stmt);
++
++ if (gimple_cond_code (cond) != EQ_EXPR
++ || TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
++ || TREE_CODE (gimple_cond_rhs (cond)) != INTEGER_CST)
++ return false;
++
++ *n = gimple_cond_lhs (cond);
++
++ return true;
++}
++
++/* Recognize pattern:
++ * if (n == const)
++ * goto then
++ * else if (some_cond)
++ * goto then
++ * then:
++ * call func (n, ...)
++ * Transform this to:
++ * if (n == const)
++ * call func (n, ...)
++ * else if (some_cond)
++ * call func (n, ...). */
++static void
++process_cond_pair (basic_block outer_cond_bb, basic_block inner_cond_bb,
++ basic_block then_bb)
++{
++ tree n = NULL_TREE;
++
++ if (inner_cond_bb == then_bb
++ || !recognize_if_then_else (outer_cond_bb, &then_bb, &inner_cond_bb)
++ || !same_phi_args_p (outer_cond_bb, inner_cond_bb, then_bb)
++ || (!got_necessary_cond_p (outer_cond_bb, &n)
++ && !got_necessary_cond_p (inner_cond_bb, &n))
++ || !bb_got_necessary_call_p (then_bb, n, SCALAR_NESTING))
++ return;
++
++ if (dump_file && (dump_flags & TDF_DETAILS))
++ {
++ fprintf (dump_file, "Recognized necessary condition pair: (o_cond) ");
++ print_gimple_stmt (dump_file, last_stmt (outer_cond_bb), 0, TDF_NONE);
++ fprintf (dump_file, " (i_cond) ");
++ print_gimple_stmt (dump_file, last_stmt (inner_cond_bb), 0, TDF_NONE);
++ }
++
++ basic_block then_bb1
++ = make_two_separate_calls (outer_cond_bb, inner_cond_bb, then_bb);
++
++ if (dump_file && (dump_flags & TDF_DETAILS))
++ {
++ if (then_bb1)
++ fprintf (dump_file,
++ "Successfully transformed: bb<%d> is a copy of bb<%d> \n",
++ then_bb1->index, then_bb->index);
++ else
++ fprintf (dump_file, "No transformation: bb<%d> cannot be duplicated \n",
++ then_bb->index);
++ }
++}
++
++//-------------------------------------------------------------------------
++// Main logic
++//-------------------------------------------------------------------------
++/* If cond_bb suits if-then-else pattern and got single pred, execute func
++ * over it and its then, else basic blocks. */
++template
++static void
++process_bb (basic_block cond_bb, F func)
++{
++ basic_block then_bb = NULL, else_bb = NULL;
++
++ if (!recognize_if_then_else (cond_bb, &then_bb, &else_bb))
++ return;
++
++ func (cond_bb, then_bb, else_bb);
++}
++
++/* For each block, if it has condition, execute function over it. We walk
++ * the blocks in order that guarantees that a block with a single predecessor
++ * is processed after the predecessor. */
++template
++static void
++execute_function_over_conditional_bbs (F func)
++{
++ basic_block *bbs = single_pred_before_succ_order ();
++ for (int i = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
++ {
++ gimple *stmt = last_stmt (bbs[i]);
++
++ if (stmt && gimple_code (stmt) == GIMPLE_COND)
++ {
++ process_bb (bbs[i], func);
++ }
++ }
++ update_ssa (TODO_update_ssa);
++ free (bbs);
++}
++
++static void
++process_if_split_cfun ()
++{
++ /* First pass. Split complex conditions, so process_condition_pair_bb ()
++ * will be able to recognize more necessary patterns. */
++ execute_function_over_conditional_bbs (process_complex_cond);
++
++ /* Second pass. Search each basic block for condition pair we may be
++ * able to optimize. */
++ execute_function_over_conditional_bbs (
++ [] (basic_block cond_bb, basic_block then_bb, basic_block else_bb)
++ {
++ if (!single_pred_p (cond_bb))
++ return;
++ process_cond_pair (single_pred (cond_bb), cond_bb, then_bb);
++ });
++}
++
++namespace
++{
++
++const pass_data pass_data_if_split = {
++ GIMPLE_PASS, /* type. */
++ "if-split", /* name. */
++ OPTGROUP_NONE, /* optinfo_flags. */
++ TV_TREE_IF_SPLIT, /* tv_id. */
++ 0, /* properties_required. */
++ 0, /* properties_provided. */
++ 0, /* properties_destroyed. */
++ 0, /* todo_flags_start. */
++ 0 /* todo_flags_finish. */
++};
++
++class pass_if_split : public gimple_opt_pass
++{
++public:
++ pass_if_split (gcc::context *ctxt)
++ : gimple_opt_pass (pass_data_if_split, ctxt)
++ {
++ }
++
++ /* opt_pass methods: */
++ virtual bool
++ gate (function *)
++ {
++ /* Don't bother doing anything if the program has errors. */
++ return (optimize >= 3 && flag_if_split && !seen_error ());
++ }
++
++ virtual unsigned int execute (function *);
++
++}; // class pass_if_split
++
++unsigned int
++pass_if_split::execute (function *fun)
++{
++ calculate_dominance_info (CDI_DOMINATORS);
++ calculate_dominance_info (CDI_POST_DOMINATORS);
++ initialize_original_copy_tables ();
++
++ process_if_split_cfun ();
++
++ checking_verify_ssa (true, true);
++ checking_verify_flow_info ();
++ checking_verify_dominators (CDI_DOMINATORS);
++ checking_verify_dominators (CDI_POST_DOMINATORS);
++
++ free_original_copy_tables ();
++ free_dominance_info (CDI_POST_DOMINATORS);
++ free_dominance_info (CDI_DOMINATORS);
++
++ return 0;
++}
++
++} // anon namespace
++
++gimple_opt_pass *
++make_pass_if_split (gcc::context *ctxt)
++{
++ return new pass_if_split (ctxt);
++}
+\ No newline at end of file
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 84dd8925a..4f3eb4bd4 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -3145,7 +3145,7 @@ common_handle_option (struct gcc_options *opts,
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_generate,
+ value);
+ }
+- /* No break here - do -fcfgo-profile-generate processing. */
++ /* No break here - do -fprofile-generate processing. */
+ /* FALLTHRU */
+ case OPT_fprofile_generate_:
+ opts->x_profile_data_prefix = xstrdup (arg);
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 862ef0d8f..fbe828439 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -100,6 +100,7 @@ along with GCC; see the file COPYING3. If not see
+ NEXT_PASS (pass_if_to_switch);
+ NEXT_PASS (pass_convert_switch);
+ NEXT_PASS (pass_cleanup_eh);
++ NEXT_PASS (pass_if_split);
+ NEXT_PASS (pass_profile);
+ NEXT_PASS (pass_local_pure_const);
+ NEXT_PASS (pass_modref);
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+new file mode 100644
+index 000000000..5909dac41
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ int b = argc;
++ int res = 0;
++
++ if (b == 5 || b == 52)
++ res = foo (b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+new file mode 100644
+index 000000000..20a45116b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++ int foo2_res = foo2();
++
++ if (data.y.b == 5 || data.y.b == 52 || foo2_res == 25)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+new file mode 100644
+index 000000000..1370f9474
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+@@ -0,0 +1,36 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct X
++{
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_a (X* x, int val)
++{
++ x->a = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ X data;
++ set_a (&data, argc);
++ int res = 0;
++
++ if (data.a == 5 || data.a == 52)
++ res = foo (data.a);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+new file mode 100644
+index 000000000..93a6eb6dd
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+@@ -0,0 +1,36 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct X
++{
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_a (X* x, int val)
++{
++ x->a = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ X data;
++ set_a (&data, argc);
++ int res = 0;
++
++ if (data.a == 5 || data.a == 52 || data.a == 25)
++ res = foo (data.a);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+new file mode 100644
+index 000000000..36f2a15b3
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++
++ if (data.y.b == 5 || data.y.b == 52)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+new file mode 100644
+index 000000000..fbc3b0c19
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++
++ if (data.y.b == 5 || data.y.b == 52 || data.y.b == 25)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+new file mode 100644
+index 000000000..185127c79
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++ int foo2_res = foo2();
++
++ if (data.y.b == 5 || foo2_res == 52)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+new file mode 100644
+index 000000000..23f1a8f04
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++
++ if (data.y.b == 5 || foo2() == 52)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary complex condition:" 0 "if-split" } } */
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 0 "if-split" } } */
++/* { dg-final { scan-tree-dump-times "Successfully transformed:" 0 "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+new file mode 100644
+index 000000000..028b6dc40
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++
++ if (data.y.b == 5 || data.a == 52)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+new file mode 100644
+index 000000000..3ff7e2efc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++ int b;
++} Y;
++
++typedef struct X
++{
++ Y y;
++ int a;
++} X;
++
++
++void __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++ y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++ int res = 1;
++ for (int i = 0; i < b; i++) {
++ res*=3;
++ }
++ return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++ X data;
++ set_b (&data.y, argc);
++ int res = 0;
++
++ if (data.y.b == 5 || data.y.b == 52 || foo2() == 25)
++ res = foo (data.y.b);
++
++ return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 6fdb2c767..b0d3d1188 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -306,6 +306,7 @@ DEFTIMEVAR (TV_VAR_TRACKING_DATAFLOW , "var-tracking dataflow")
+ DEFTIMEVAR (TV_VAR_TRACKING_EMIT , "var-tracking emit")
+ DEFTIMEVAR (TV_TREE_IFCOMBINE , "tree if-combine")
+ DEFTIMEVAR (TV_TREE_IF_TO_SWITCH , "if to switch conversion")
++DEFTIMEVAR (TV_TREE_IF_SPLIT , "gimple if splitting")
+ DEFTIMEVAR (TV_TREE_UNINIT , "uninit var analysis")
+ DEFTIMEVAR (TV_PLUGIN_INIT , "plugin initialization")
+ DEFTIMEVAR (TV_PLUGIN_RUN , "plugin execution")
+diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
+index cb67cdf87..bfe44c073 100644
+--- a/gcc/tree-cfg.h
++++ b/gcc/tree-cfg.h
+@@ -112,6 +112,8 @@ extern basic_block gimple_switch_default_bb (function *, gswitch *);
+ extern edge gimple_switch_edge (function *, gswitch *, unsigned);
+ extern edge gimple_switch_default_edge (function *, gswitch *);
+ extern bool cond_only_block_p (basic_block);
++extern bool recognize_if_then_else (basic_block, basic_block *, basic_block *);
++extern bool same_phi_args_p (basic_block, basic_block, basic_block);
+
+ /* Return true if the LHS of a call should be removed. */
+
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index f9c2eed8b..fb17b189c 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -383,6 +383,7 @@ extern gimple_opt_pass *make_pass_graphite (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_graphite_transforms (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_if_conversion (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_if_to_switch (gcc::context *ctxt);
++extern gimple_opt_pass *make_pass_if_split (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_loop_distribution (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_vectorize (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_simduid_cleanup (gcc::context *ctxt);
+diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
+index 264a8bcae..3b50fc114 100644
+--- a/gcc/tree-ssa-ifcombine.cc
++++ b/gcc/tree-ssa-ifcombine.cc
+@@ -76,8 +76,7 @@ along with GCC; see the file COPYING3. If not see
+ match the then and else basic-blocks to make the pattern match.
+ Returns true if the pattern matched, false otherwise. */
+
+-static bool
+-recognize_if_then_else (basic_block cond_bb,
++bool recognize_if_then_else (basic_block cond_bb,
+ basic_block *then_bb, basic_block *else_bb)
+ {
+ edge t, e;
+@@ -168,8 +167,7 @@ forwarder_block_to (basic_block bb, basic_block to_bb)
+ BB2 to DEST are the same. This makes the CFG merge point
+ free from side-effects. Return true in this case, else false. */
+
+-static bool
+-same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
++bool same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
+ {
+ edge e1 = find_edge (bb1, dest);
+ edge e2 = find_edge (bb2, dest);
+--
+2.25.1
+
diff --git a/LoongArch-Allow-attributes-in-non-gnu-namespaces.diff b/LoongArch-Allow-attributes-in-non-gnu-namespaces.diff
new file mode 100644
index 0000000000000000000000000000000000000000..ae7ac9be1055138d4c4d70b97e0283df2f5f715d
--- /dev/null
+++ b/LoongArch-Allow-attributes-in-non-gnu-namespaces.diff
@@ -0,0 +1,23 @@
+diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
+index 6be0d80b3..12af95f70 100644
+--- a/gcc/config/loongarch/loongarch.cc
++++ b/gcc/config/loongarch/loongarch.cc
+@@ -7917,15 +7917,13 @@ loongarch_handle_model_attribute (tree *node, tree name, tree arg, int,
+ return NULL_TREE;
+ }
+
+-static const struct attribute_spec loongarch_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (loongarch_attribute_table,
+ {
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+ affects_type_identity, handler, exclude } */
+ { "model", 1, 1, true, false, false, false,
+- loongarch_handle_model_attribute, NULL },
+- /* The last attribute spec is set to be NULL. */
+- {}
+-};
++ loongarch_handle_model_attribute, NULL }
++});
+
+ bool
+ loongarch_use_anchors_for_symbol_p (const_rtx symbol)
diff --git a/gcc.spec b/gcc.spec
index f793dd72053bf691b8d4c23f80a500e3edcf18c9..488ed520580e4d743b67a5a43688a578601ac446 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -2,7 +2,7 @@
%global gcc_major 12
# Note, gcc_release must be integer, if you want to add suffixes to
# %%{release}, append them after %%{gcc_release} on Release: line.
-%global gcc_release 46
+%global gcc_release 49
%global _unpackaged_files_terminate_build 0
%global _performance_build 1
@@ -415,6 +415,8 @@ Patch306: 0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch
Patch307: 0307-Set-fallback-value-for-print-multi-os-directory.patch
Patch308: 0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch
Patch309: 0309-CSPGO-Add-context-sensitive-PGO.patch
+Patch310: 0310-CFGO-Add-cfgo-pgo-optimization.patch
+Patch311: 0311-PATCH-Add-if-split-optimization-pass.patch
# Part 3000 ~ 4999
%ifarch loongarch64
@@ -740,6 +742,7 @@ Patch3319: 0189-LoongArch-fix-building-errors.patch
Patch3320: 0190-tree-optimization-110702-avoid-zero-based-memory-ref.patch
Patch3321: 0191-LoongArch-Change-OSDIR-for-distribution.patch
Patch3322: Fix-indentation-and-numbering-errors.diff
+Patch3323: LoongArch-Allow-attributes-in-non-gnu-namespaces.diff
%endif
# On ARM EABI systems, we do want -gnueabi to be part of the
@@ -1488,6 +1491,8 @@ not stable, so plugins must be rebuilt any time GCC is updated.
%patch -P307 -p1
%patch -P308 -p1
%patch -P309 -p1
+%patch -P310 -p1
+%patch -P311 -p1
%ifarch loongarch64
%patch -P3001 -p1
@@ -1812,6 +1817,7 @@ not stable, so plugins must be rebuilt any time GCC is updated.
%patch -P3320 -p1
%patch -P3321 -p1
%patch -P3322 -p1
+%patch -P3323 -p1
%endif
echo '%{_vendor} %{version}-%{release}' > gcc/DEV-PHASE
@@ -4080,6 +4086,19 @@ end
%doc rpm.doc/changelogs/libcc1/ChangeLog*
%changelog
+* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-49
+- Type: Sync
+- DESC: Add if split optimization
+
+* Wed Nov 27 2024 Peng Fan - 12.3.1-48
+- Type: BUGFIX
+- DESC:
+- LoongArch: Allow attributes in non-gnu namespaces.
+
+* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-47
+- Type: Sync
+- DESC: Add cfgo-pgo optimization
+
* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-46
- Type: Sync
- DESC: Add context sensitive PGO