summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-08 15:09:24 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-08 15:09:24 +0200
commit140efef10e83422f31b8773dd0ffbf72d2fb0741 (patch)
tree37b81694b561c6959b354f915245320fca6d080f
parent095fb75003c2ba67f9b1088dde507ab5bc0d41a9 (diff)
Adds ability to find casting between types
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/collect-types.c12
-rw-r--r--gcc/collect-types.h1
-rw-r--r--gcc/expr-escaper.hpp1
-rw-r--r--gcc/gimple-caster.c30
-rw-r--r--gcc/gimple-caster.hpp20
-rw-r--r--gcc/gimple-escaper.c45
-rw-r--r--gcc/gimple-escaper.hpp1
-rw-r--r--gcc/gimple-walker.c12
-rw-r--r--gcc/gimple-walker.hpp30
-rw-r--r--gcc/ipa-str-reorg-dead-field-eliminate.c9
-rw-r--r--gcc/ipa-str-reorg-utils.h10
-rw-r--r--gcc/ipa-structure-reorg.c81
-rw-r--r--gcc/ipa-structure-reorg.h22
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-ea-11-cast-to-void-ptr-0.c15
-rw-r--r--gcc/type-collector.c1
-rw-r--r--gcc/type-escaper.c23
-rw-r--r--gcc/type-escaper.hpp1
-rw-r--r--gcc/types-inlines.h31
19 files changed, 280 insertions, 66 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index aae84bf3b2b..74afacd6128 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1416,6 +1416,7 @@ OBJS = \
type-collector.o \
expr-collector.o \
gimple-collector.o \
+ gimple-caster.o \
type-escaper.o \
type-structural-equality.o \
type-structural-main-variant.o \
diff --git a/gcc/collect-types.c b/gcc/collect-types.c
index b3febdd57d7..f4ad113b56f 100644
--- a/gcc/collect-types.c
+++ b/gcc/collect-types.c
@@ -72,3 +72,15 @@ points_to_record_sets_s::in_complement(const_tree type) const
return seen_before;
}
+void
+points_to_record_sets_s::print_in_points_to_record() const
+{
+ TypeStringifier stringifier;
+ for (auto i = this->points_to_record.cbegin(), e = this->points_to_record.cend(); i != e; ++i)
+ {
+ const_tree t = *i;
+ gcc_assert(t);
+ std::string name = stringifier.stringify(t);
+ log("collected: %s\n", name.c_str());
+ }
+}
diff --git a/gcc/collect-types.h b/gcc/collect-types.h
index 1a6126f6a6d..a2439557332 100644
--- a/gcc/collect-types.h
+++ b/gcc/collect-types.h
@@ -15,6 +15,7 @@ struct points_to_record_sets_s {
bool in_points_to_record(const_tree) const;
bool in_complement(const_tree) const;
void insert(const_tree, bool);
+ void print_in_points_to_record() const;
};
typedef struct points_to_record_sets_s ptrset_t;
diff --git a/gcc/expr-escaper.hpp b/gcc/expr-escaper.hpp
index 6498f9e3dd4..bcadbe77782 100644
--- a/gcc/expr-escaper.hpp
+++ b/gcc/expr-escaper.hpp
@@ -12,6 +12,7 @@ public:
ExprEscaper(ptrset_t &types) : typeEscaper(types) {};
ptrset_t get_sets() { return typeEscaper.get_sets(); };
void update(const_tree t, Reason r);
+ void print_reasons() { typeEscaper.print_reasons(); };
private:
Reason _r;
virtual void _walk_pre(const_tree e);
diff --git a/gcc/gimple-caster.c b/gcc/gimple-caster.c
new file mode 100644
index 00000000000..ce96a78d7dc
--- /dev/null
+++ b/gcc/gimple-caster.c
@@ -0,0 +1,30 @@
+#include "gimple-caster.hpp"
+#include "gimple-pretty-print.h"
+
+#include "type-incomplete-equality.hpp"
+
+void
+GimpleCaster::_walk_pre(gassign *s)
+{
+ print_gimple_stmt(dump_file, s, TDF_NONE);
+ const enum gimple_rhs_class code = gimple_assign_rhs_class(s);
+ const bool valid_input = GIMPLE_SINGLE_RHS == code;
+ if (!valid_input) return;
+
+ // I originally was using gimple_assign_cast_p
+ // but that proved to be insufficient...
+ // So we have to use our equality comparison...
+ TypeIncompleteEquality equality;
+ const_tree lhs = gimple_assign_lhs(s);
+ const_tree rhs = gimple_assign_rhs1(s);
+ gcc_assert(lhs && rhs);
+ Reason reason {};
+ const_tree t_lhs = TREE_TYPE(lhs);
+ const_tree t_rhs = TREE_TYPE(rhs);
+ gcc_assert(t_lhs && t_rhs);
+ const bool is_cast = equality.equal(t_lhs, t_rhs);
+ reason.is_escaping = is_cast;
+ reason.type_is_casted = is_cast;
+ exprEscaper.update(lhs, reason);
+ exprEscaper.update(rhs, reason);
+}
diff --git a/gcc/gimple-caster.hpp b/gcc/gimple-caster.hpp
new file mode 100644
index 00000000000..2495d537649
--- /dev/null
+++ b/gcc/gimple-caster.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "gimple-escaper.hpp"
+
+/*
+ * GimpleCaster is intended to walk gimple
+ * and update a map that will hold information
+ * on whether a type was casted or not.
+ */
+class GimpleCaster : public GimpleEscaper
+{
+public:
+ GimpleCaster(ptrset_t &types) : GimpleEscaper(types) {};
+private:
+ // We don't need this from parent...
+ virtual void _walk_pre(gcall *s) final {};
+ // Find out which structs are casted.
+ // Technically we could find this out on parent
+ virtual void _walk_pre(gassign *s);
+};
diff --git a/gcc/gimple-escaper.c b/gcc/gimple-escaper.c
index 625235e0b8d..4c1cedd7412 100644
--- a/gcc/gimple-escaper.c
+++ b/gcc/gimple-escaper.c
@@ -92,31 +92,62 @@ GimpleEscaper::_walk_pre(__attribute__((unused)) const_tree t)
{
// Is any global variable escaping?
Reason reason;
- //exprEscaper.update(expr, reason);
+ exprEscaper.update(t, reason);
}
void
GimpleEscaper::_walk_pre(__attribute__((unused)) gassign *s)
{
Reason reason;
- // We really should also walk over the different assigns...
-
-// Is there a type cast?
-//exprEscaper.update(expr, reason);
+ const enum gimple_rhs_class code = gimple_assign_rhs_class(s);
+ switch (code)
+ {
+ case GIMPLE_TERNARY_RHS:
+ {
+ const_tree rhs3 = gimple_assign_rhs3(s);
+ exprEscaper.update(rhs3, reason);
+ }
+ /* fall-through */
+ case GIMPLE_BINARY_RHS:
+ {
+ const_tree rhs2 = gimple_assign_rhs2(s);
+ exprEscaper.update(rhs2, reason);
+ }
+ /* fall-through */
+ case GIMPLE_UNARY_RHS:
+ case GIMPLE_SINGLE_RHS:
+ {
+ const_tree rhs1 = gimple_assign_rhs1(s);
+ exprEscaper.update(rhs1, reason);
+ const_tree lhs = gimple_assign_lhs(s);
+ if (!lhs) break;
+ exprEscaper.update(lhs, reason);
+ }
+ break;
+ default:
+ gcc_unreachable();
+ break;
+ }
}
void
GimpleEscaper::_walk_pre(__attribute__((unused)) greturn *s)
{
Reason reason;
- //exprEscaper.update(expr, reason);
+ const_tree val = gimple_return_retval(s);
+ if (!val) return;
+ exprEscaper.update(val, reason);
}
void
GimpleEscaper::_walk_pre(__attribute__((unused)) gcond *s)
{
Reason reason;
- //exprEscaper.update(expr, reason);
+ const_tree lhs = gimple_cond_lhs(s);
+ const_tree rhs = gimple_cond_rhs(s);
+ gcc_assert(lhs && rhs);
+ exprEscaper.update(lhs, reason);
+ exprEscaper.update(rhs, reason);
}
void
diff --git a/gcc/gimple-escaper.hpp b/gcc/gimple-escaper.hpp
index 45cdd70ab4a..9c439fffe38 100644
--- a/gcc/gimple-escaper.hpp
+++ b/gcc/gimple-escaper.hpp
@@ -10,6 +10,7 @@ public:
GimpleEscaper(ptrset_t &types) : exprEscaper(types) { _init(); };
ExprEscaper exprEscaper;
ptrset_t get_sets() { return exprEscaper.get_sets(); };
+ void print_reasons() { exprEscaper.print_reasons(); };
private:
typedef std::set<const_tree> undefset;
undefset undefined;
diff --git a/gcc/gimple-walker.c b/gcc/gimple-walker.c
index 7a8d9ed2df6..eb15db85a01 100644
--- a/gcc/gimple-walker.c
+++ b/gcc/gimple-walker.c
@@ -40,6 +40,17 @@
#include "expr-walker.hpp"
#include "expr-collector.hpp"
#include "gimple-walker.hpp"
+#include "tree-cfg.h"
+
+inline static void
+print_function (cgraph_node *cnode)
+{
+ if (!dump_file)
+ return;
+ gcc_assert (cnode);
+ cnode->get_untransformed_body ();
+ dump_function_to_file (cnode->decl, dump_file, TDF_NONE);
+}
void
GimpleWalker::walk()
@@ -214,3 +225,4 @@ GimpleWalkerFuncDef(gcond *)
GimpleWalkerFuncDef(gcall *)
GimpleWalkerFuncDef(glabel *)
GimpleWalkerFuncDef(gswitch *)
+
diff --git a/gcc/gimple-walker.hpp b/gcc/gimple-walker.hpp
index 219eb7b00b2..cc1ece64f05 100644
--- a/gcc/gimple-walker.hpp
+++ b/gcc/gimple-walker.hpp
@@ -1,5 +1,35 @@
#pragma once
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
+#include "gimple-fold.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "tree-pretty-print.h"
+#include "tree-inline.h"
+#include "ipa-fnsummary.h"
+#include "ipa-utils.h"
+#include "tree-ssa-ccp.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-ssa-alias.h"
+#include "tree-ssanames.h"
+#include "gimple.h"
+#include "cfg.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+
class GimpleWalker
{
public:
diff --git a/gcc/ipa-str-reorg-dead-field-eliminate.c b/gcc/ipa-str-reorg-dead-field-eliminate.c
index 77f9d3141b2..2e192328ad8 100644
--- a/gcc/ipa-str-reorg-dead-field-eliminate.c
+++ b/gcc/ipa-str-reorg-dead-field-eliminate.c
@@ -52,6 +52,8 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-str-reorg-utils.h"
#include "ipa-hello-world.h"
+#include "gimple-caster.hpp"
+
#define test_write(M, ...) \
if (dump_file) \
{ \
@@ -2765,6 +2767,13 @@ str_reorg_dead_field_eliminate (__attribute__((unused)) Info *info)
int
str_reorg_dead_field_eliminate_qual (Info *info)
{
+ GimpleCaster caster(info->sets);
+ caster.walk();
+ // sets here now holds the types that
+ // are casted...
+ // So, maybe we want to print them?
+ caster.print_reasons();
+ ptrset_t sets = caster.get_sets();
return 0;
}
int
diff --git a/gcc/ipa-str-reorg-utils.h b/gcc/ipa-str-reorg-utils.h
index 1465db03d31..98b81acb565 100644
--- a/gcc/ipa-str-reorg-utils.h
+++ b/gcc/ipa-str-reorg-utils.h
@@ -33,15 +33,7 @@ const char* get_field_name (const_tree type);
#include <stdio.h>
-inline void
-log (const char * const format, ...)
-{
- if (!dump_file) return;
+#include "types-inlines.h"
- va_list args;
- va_start(args, format);
- vfprintf(dump_file, format, args);
- va_end(args);
-}
#endif
diff --git a/gcc/ipa-structure-reorg.c b/gcc/ipa-structure-reorg.c
index 5df74ba139e..58e7578a8c8 100644
--- a/gcc/ipa-structure-reorg.c
+++ b/gcc/ipa-structure-reorg.c
@@ -90,7 +90,6 @@ static void print_program ( FILE *, int);
static void print_function ( FILE *, int, function *);
static ReorgType_t *get_reorgtype( gimple *stmt, Info *, int);
static int num_reorgtypes( gimple *, Info *);
-static bool points_to_escape_analysis( Info *);
static bool uses_field_of_reorgtypes( gimple *, Info *);
//-- debugging only --
@@ -121,35 +120,25 @@ ipa_structure_reorg ( void)
// Why not make this a class and avoid having all these parameters
// to initialize?
// Also, all functions should be references and not pointers...
- Info info = { &Reorg_Type,
- &Saved_Reorg_Type,
- &Prog_Decl,
- &StructTypes,
- 0,
- 0.0,
- NULL,
- false,
- false,
- false,
- false,
- false,
- false,
- false};
+ Info info(&Reorg_Type, &Saved_Reorg_Type, &Prog_Decl, &StructTypes);
setup_debug_flags ( &info);
if ( !reorg_analysis ( &info) )
{
- gcc_unreachable();
return true;
}
- if ( reorg_qualification ( &info) )
+ bool qualified = reorg_qualification(&info);
+ if ( qualified )
{
- #if USE_NEW_INTERFACE
+#if USE_NEW_INTERFACE
if ( flag_ipa_structure_reorg || flag_ipa_dead_field_eliminate )
{
+ log("before str_reorg_dead_field_eliminate_qual \n");
str_reorg_dead_field_eliminate_qual ( &info);
+ // Because I just want to do this now...
+ return true;
}
if ( flag_ipa_structure_reorg || flag_ipa_field_reorder )
{
@@ -187,6 +176,7 @@ ipa_structure_reorg ( void)
// Also, if they change the shape of a type the must create my
// type and update the ReorgTypes to reflect this.
+ log("We are using the old interface...\n");
if ( flag_ipa_structure_reorg || flag_ipa_dead_field_eliminate ) {
str_reorg_dead_field_eliminate ( &info);
}
@@ -262,8 +252,8 @@ reorg_analysis ( Info *info)
ptrset_t types = collector.get_pointer_set();
GimpleEscaper gimpleEscaper(types);
gimpleEscaper.walk();
- types = gimpleEscaper.get_sets();
- gcc_unreachable();
+ info->sets = gimpleEscaper.get_sets();
+ info->sets.print_in_points_to_record();
return true;
}
struct cgraph_node *node;
@@ -866,24 +856,49 @@ reorg_qualification ( Info *info)
// TBD
// This only does a generic legality qualification and each
// subpass does its own performance qualification.
- return reorg_legality( info);
+ log("before reorg_leaglity...\n");
+ unsigned int retval = reorg_legality( info);
+ log("after reorg_leaglity...\n");
+ return retval;
}
// Return false if nothing qualified
bool
reorg_legality( Info *info) {
- // NOTE, the following line does nothing unless
- // we actually do our own points-to analysis
- if( !points_to_escape_analysis( info) ) return false;
-
- return transformation_legality( info);
+ log("before transformation leagality...\n");
+ bool retval = transformation_legality( info);
+ log("after transformation leagality...\n");
+ return retval;
+}
+
+bool
+Info::is_non_escaping_set_empty()
+{
+ log("before non escaping empty...\n");
+ bool retval = this->sets.non_escaping.empty();
+ log("after non escaping empty...%s \n", retval ? "t" : "f");
+ return retval;
}
// Return false if nothing qualified
+// TODO:
+// What exactly is the difference between legality and
+// non_escaping?
bool
transformation_legality ( Info *info)
{
+ //TODO: Gary, for my purposes, I need to start running the
+ // code related to dead field eliminate. So, I'll add this bit
+ const bool run_escape_analysis = flag_ipa_dead_field_eliminate && !flag_ipa_instance_interleave && !flag_ipa_field_reorder;
+ if (run_escape_analysis)
+ {
+ log("before empty...\n");
+ bool retval = !info->is_non_escaping_set_empty();
+ log("after empty...\n");
+ return retval;
+ }
+
cgraph_node* node;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY ( node)
@@ -1799,20 +1814,6 @@ print_type ( FILE *file, tree type)
fprintf ( file, "type: %s\n", text);
}
-// Does there really need to be here?
-// I suspect not. Perhaps if needed
-// to run our own points-to analysis
-// routine.... it would be invoked here.
-// So, just to maintain a point to do this
-// from, return true.
-// Return false if nothing qualified
-bool
-points_to_escape_analysis( Info *info)
-{
- // TBD
- return true;
-}
-
bool
uses_field_of_reorgtypes( gimple *stmt, Info * info)
{
diff --git a/gcc/ipa-structure-reorg.h b/gcc/ipa-structure-reorg.h
index 3861efa0be0..6864caf27a3 100644
--- a/gcc/ipa-structure-reorg.h
+++ b/gcc/ipa-structure-reorg.h
@@ -154,6 +154,7 @@ struct Info {
std::map <tree,BoolPair_t> *struct_types; // desing bug fix
// ptrset_t holds types which point to records
// and types which escape
+ ptrset_t sets;
int num_deleted;
double total_cache_accesses;
FILE *reorg_dump_file;
@@ -165,12 +166,33 @@ struct Info {
bool show_new_BBs;
bool show_transforms;
bool show_bounds;
+ bool is_non_escaping_set_empty();
+
+ Info (std::vector <ReorgType_t> *v1,
+ std::vector <ReorgType_t> *v2,
+ std::vector <ProgDecl_t> *v3,
+ std::map <tree, BoolPair_t> *v4)
+ : reorg_type(v1)
+ , saved_reorg_type(v2)
+ , prog_decl(v3)
+ , struct_types(v4)
+ , num_deleted(0)
+ , total_cache_accesses(0)
+ , reorg_dump_file(NULL)
+ , show_all_reorg_cands(false)
+ , show_all_reorg_cands_in_detail(false)
+ , show_prog_decls(false)
+ , show_new_BBs(false)
+ , show_transforms(false)
+ , show_bounds(false)
+ {};
};
// This will perform a function on the supplied
// reorg type. It's primarily to support debugging.
typedef void (*ReorgFn)( Info *, ReorgType_t *);
+#define USE_NEW_INTERFACE 1
#if USE_NEW_INTERFACE
extern int str_reorg_dead_field_eliminate_qual ( Info *);
extern int str_reorg_dead_field_eliminate_trans ( Info *);
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-ea-11-cast-to-void-ptr-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-ea-11-cast-to-void-ptr-0.c
index 5ef153eb5f9..596f220a72c 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-ea-11-cast-to-void-ptr-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-ea-11-cast-to-void-ptr-0.c
@@ -1,26 +1,23 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis" } */
+/* { dg-options "-flto -fipa-dead-field-eliminate -fdump-ipa-structure-reorg " } */
#include <stddef.h>
struct astruct_s { _Bool a; _Bool b; _Bool c;};
-struct astruct_s astruct; // This should not escape
struct bstruct_s { _Bool a; _Bool b; _Bool c;};
-struct bstruct_s bstruct; // This should not escape
-void casting_to_void (struct astruct_s *s)
+struct bstruct_s *casting_to_void (struct astruct_s *s)
{
- void *nullify_non_escape = s;
+ return (struct bstruct_s *)(s);
}
int main()
{
+ struct astruct_s astruct; // This should not escape
+ struct bstruct_s bstruct; // This should not escape
astruct.a = 0;
bstruct.b = 0;
}
-/* { dg-final { scan-wpa-ipa-dump "collected,astruct_s" "type-escape-analysis" } } */
-/* { dg-final { scan-wpa-ipa-dump "type astruct_s\\\* is escaping true" "type-escape-analysis" } } */
-/* { dg-final { scan-wpa-ipa-dump "collected,bstruct_s" "type-escape-analysis" } } */
-/* { dg-final { scan-wpa-ipa-dump "type bstruct_s is escaping false" "type-escape-analysis" } } */
+/* { dg-final { scan-wpa-ipa-dump "record" "structure-reorg" } } */
diff --git a/gcc/type-collector.c b/gcc/type-collector.c
index a199087ce56..e5bccb0a34a 100644
--- a/gcc/type-collector.c
+++ b/gcc/type-collector.c
@@ -44,7 +44,6 @@ TypeCollector::collect(const_tree t)
{
TypeStringifier stringifier;
std::string in_name = stringifier.stringify(t);
- log("in %s size = %d\n", in_name.c_str(), ptr.size());
gcc_unreachable();
}
walk(t);
diff --git a/gcc/type-escaper.c b/gcc/type-escaper.c
index 977a8af795c..466f13a77cc 100644
--- a/gcc/type-escaper.c
+++ b/gcc/type-escaper.c
@@ -31,6 +31,7 @@
#include "types-inlines.h"
#include "type-escaper.hpp"
+#include "type-stringifier.hpp"
bool
TypeEscaper::is_memoized(const_tree t)
@@ -65,6 +66,7 @@ TypeEscaper::get_sets()
void
TypeEscaper::place_escaping_types_in_set()
{
+ TypeStringifier stringifier;
for (auto i = calc.cbegin(), e = calc.cend(); i != e; ++i)
{
const_tree type = i->first;
@@ -78,6 +80,7 @@ TypeEscaper::place_escaping_types_in_set()
if (!_ptrset.in_points_to_record(type)) continue;
const Reason reason = i->second;
+ std::string name = stringifier.stringify(type);
reason.is_escaping ? _ptrset.escaping.insert(type) : _ptrset.non_escaping.insert(type);
}
}
@@ -154,3 +157,23 @@ TypeEscaper::_walk_METHOD_TYPE_pre(const_tree t)
{
_update(t);
}
+
+void
+TypeEscaper::print_reasons()
+{
+ TypeStringifier stringifier;
+ for (auto i = calc.cbegin(), e = calc.cend(); i != e; ++i)
+ {
+ const_tree t = i->first;
+ std::string name = stringifier.stringify(t);
+ const bool in_universe = _ptrset.in_universe(t);
+ if (!in_universe) continue;
+
+ Reason r = i->second;
+ const bool is_escaping = r.is_escaping;
+ if (!is_escaping) continue;
+
+ log("%s reason: ", name.c_str());
+ r.print();
+ }
+}
diff --git a/gcc/type-escaper.hpp b/gcc/type-escaper.hpp
index 3bda74aa297..e4025165237 100644
--- a/gcc/type-escaper.hpp
+++ b/gcc/type-escaper.hpp
@@ -13,6 +13,7 @@ public:
ptrset_t get_sets();
ptrset_t &_ptrset;
typemap calc;
+ void print_reasons();
private:
virtual void _walk_POINTER_TYPE_pre(const_tree t);
virtual void _walk_REFERENCE_TYPE_pre(const_tree t);
diff --git a/gcc/types-inlines.h b/gcc/types-inlines.h
index ef2629afeec..60666c3ce26 100644
--- a/gcc/types-inlines.h
+++ b/gcc/types-inlines.h
@@ -1,5 +1,36 @@
#pragma once
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
+#include "gimple-fold.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "tree-pretty-print.h"
+#include "tree-inline.h"
+#include "ipa-fnsummary.h"
+#include "ipa-utils.h"
+#include "tree-ssa-ccp.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-ssa-alias.h"
+#include "tree-ssanames.h"
+#include "gimple.h"
+#include "cfg.h" // needed for gimple-iterator.h
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include <stdbool.h>
+#include <stdio.h>
inline void