summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-17 18:31:52 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-17 18:31:52 +0200
commit5e12dd9d138a0afec5290df234523204e6fef21d (patch)
treeaacd2786c9632c81edb0380a8fc286930bd5547e
parent1ea9a204ef32fc5c3e1636c003ac68bd32cc2723 (diff)
wip
-rw-r--r--gcc/expr-rewriter.c153
-rw-r--r--gcc/expr-rewriter.hpp5
-rw-r--r--gcc/gimple-rewriter.c5
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-26-array-cast-0.c2
4 files changed, 142 insertions, 23 deletions
diff --git a/gcc/expr-rewriter.c b/gcc/expr-rewriter.c
index f0e517662ba..0b92827cf0f 100644
--- a/gcc/expr-rewriter.c
+++ b/gcc/expr-rewriter.c
@@ -1,3 +1,28 @@
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "options.h"
+#include "cgraph.h"
+#include "tree-pass.h"
+#include "tree-cfg.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
+#include "stringpool.h" //get_identifier
+#include "basic-block.h" //needed for gimple.h
+#include "function.h" //needed for gimple.h
+#include "gimple.h"
+#include "cfg.h" // needed for gimple-iterator.h
+#include "gimple-iterator.h"
+#include "stor-layout.h" // layout_type
+#include "fold-const.h" //build_fold_addr_expr
+#include "gimple-ssa.h" // update_stmt
+#include "attribs.h" // decl_attributes
+#include "gimplify.h" //unshare_expr
+#include "value-range.h" // make_ssa_name dependency
+#include "tree-ssanames.h" // make_ssa_name
+#include "ssa.h"
+#include "tree-into-ssa.h"
#include "expr-rewriter.hpp"
#include "type-stringifier.hpp"
#include <string>
@@ -23,8 +48,74 @@ ExprTypeRewriter::is_interesting_type(tree t)
}
void
-ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tree op_1)
+ExprTypeRewriter::handle_pointer_arithmetic_diff(gimple *s, tree op_0, tree op_1)
{
+
+ // lhs = op0 - op1 // <-- we are here
+ // ... SNIP ...
+ // var = lhs / [ex] old_struct_size // <-- we want to be here
+ //
+ // Let's explore the uses of lhs
+ tree lhs = gimple_assign_lhs(s);
+
+ tree reorg_type = TREE_TYPE(op_0);
+ const enum tree_code code = TREE_CODE(reorg_type);
+ const bool is_pointer = POINTER_TYPE == code;
+ const bool is_array = ARRAY_TYPE == code;
+ const bool is_valid_input = is_pointer != is_array;
+ gcc_assert(is_valid_input);
+
+ tree inner_reorg_type = TREE_TYPE(reorg_type);
+ gcc_assert(inner_reorg_type);
+ tree reorg_type_size_tree = TYPE_SIZE_UNIT(inner_reorg_type);
+ int reorg_type_size_int = tree_to_shwi(reorg_type_size_tree);
+
+ tree old_type = (tree)_imap[reorg_type];
+ tree inner_old_type = TREE_TYPE(old_type);
+ gcc_assert(old_type);
+ tree old_type_size_tree = TYPE_SIZE_UNIT(inner_old_type);
+ int old_type_size_int = tree_to_shwi(old_type_size_tree);
+
+
+ gimple *stmt;
+ imm_use_iterator iterator;
+ FOR_EACH_IMM_USE_STMT(stmt, iterator, lhs)
+ {
+ // stmt is a use of lhs
+ // gimple_expr_code is only valid for non-debug statements
+ bool is_debug = is_gimple_debug (stmt);
+ if (is_debug)
+ continue;
+
+ enum tree_code code = gimple_expr_code (stmt);
+ bool is_exact_div = code == EXACT_DIV_EXPR;
+ if (!is_exact_div)
+ continue;
+
+ tree divisor = gimple_op (stmt, 2);
+ enum tree_code divisor_code = TREE_CODE (divisor);
+ bool is_constant = divisor_code == INTEGER_CST;
+ if (!is_constant)
+ continue;
+
+ int divisor_int = tree_to_shwi (divisor);
+ bool is_same_size = divisor_int == old_type_size_int;
+ if (!is_same_size)
+ continue;
+
+ tree new_integer_cst_tree = build_int_cst(TREE_TYPE(divisor), reorg_type_size_int);
+ gimple_set_op (stmt, 2, new_integer_cst_tree);
+ }
+}
+
+void
+ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tree op_1, bool is_pointer_plus)
+{
+ if (!is_pointer_plus)
+ {
+ handle_pointer_arithmetic_diff(s, op_0, op_1);
+ return;
+ }
// _1 = _0 * 72
// ... SNIP ...
// _2 = _1 + CONSTANT;
@@ -47,7 +138,7 @@ ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tr
// operand 0 is the lhs
// operand 1 is the rhs
// I.e. lhs = (unary_operator) rhs;
- const bool get_another_definition = num_operands == 2;
+ bool get_another_definition = num_operands == 2;
tree possibly_not_needed = get_another_definition ? gimple_op (def_for_variable, 1) : NULL;
def_for_variable = get_another_definition ? SSA_NAME_DEF_STMT(possibly_not_needed) : def_for_variable;
@@ -59,20 +150,7 @@ ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tr
// _4 = &array + _3;
enum tree_code code = gimple_expr_code (def_for_variable);
- const bool is_mult_expr = MULT_EXPR == code;
- bool is_valid_input = is_mult_expr;
- gcc_assert(is_valid_input);
-
- tree op_0_earlier = gimple_assign_rhs1(def_for_variable);
- tree op_1_earlier = gimple_assign_rhs2(def_for_variable);
-
- // We should be able to just call the constant implementation
- //handle_pointer_arithmetic_constants(def_for_variable, op_0, op_1);
- //However...
- //these variables no longer hold the type needed for them to change correctly
- //so, let's do it from here...
-
- assert_is_type(op_1_earlier, INTEGER_CST);
+ const bool is_plus_expr = PLUS_EXPR == code;
// op_0 is the variable
// That means that the reorg_type is
@@ -86,6 +164,46 @@ ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tr
tree old_type_size_tree = TYPE_SIZE_UNIT(old_inner_type);
int old_type_size_int = tree_to_shwi(old_type_size_tree);
+ if (is_plus_expr)
+ {
+ // If we are here it is because we are adding an offset.
+ // It is usually whenever we do somehting like
+ // _2 = _1 + CONSTANT; <-- to change
+ // _3 = &array + _2;
+ tree constant_plus = gimple_op (def_for_variable, 2);
+ assert_is_type(constant_plus, INTEGER_CST);
+
+ int old_integer_cst_int = tree_to_uhwi(constant_plus);
+ int modulo = old_integer_cst_int % old_type_size_int;
+ int new_integer_cst_int = old_integer_cst_int / old_type_size_int * reorg_type_size_int + modulo;
+
+ tree new_integer_cst_tree = build_int_cst(TREE_TYPE(constant_plus), new_integer_cst_int);
+ gimple_set_op(def_for_variable, 2, new_integer_cst_tree);
+
+ tree variable = gimple_op (def_for_variable, 1);
+ def_for_variable = SSA_NAME_DEF_STMT(variable);
+ num_operands = gimple_num_ops (def_for_variable);
+ get_another_definition = num_operands == 2;
+ def_for_variable = get_another_definition ? SSA_NAME_DEF_STMT(gimple_op(def_for_variable, 1)) : def_for_variable;
+ code = gimple_expr_code(def_for_variable);
+
+
+ }
+
+ if (code == MULT_EXPR) {
+
+ tree op_0_earlier = gimple_assign_rhs1(def_for_variable);
+ tree op_1_earlier = gimple_assign_rhs2(def_for_variable);
+
+ // We should be able to just call the constant implementation
+ //handle_pointer_arithmetic_constants(def_for_variable, op_0, op_1);
+ //However...
+ //these variables no longer hold the type needed for them to change correctly
+ //so, let's do it from here...
+
+ assert_is_type(op_1_earlier, INTEGER_CST);
+
+
tree old_integer_cst_tree = op_1_earlier;
int old_integer_cst_int = tree_to_uhwi(old_integer_cst_tree);
@@ -95,10 +213,11 @@ ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tr
tree new_integer_cst_tree = build_int_cst(TREE_TYPE(old_integer_cst_tree), new_integer_cst_int);
gimple_set_op(def_for_variable, 2, new_integer_cst_tree);
+ }
}
void
-ExprTypeRewriter::handle_pointer_arithmetic_constants(gimple *s, tree p, tree i)
+ExprTypeRewriter::handle_pointer_arithmetic_constants(gimple *s, tree p, tree i, bool is_pointer_plus)
{
// So, because we have already changed the type
// tree p will either be the original type
diff --git a/gcc/expr-rewriter.hpp b/gcc/expr-rewriter.hpp
index 5893f4970ae..dfa9ac4035d 100644
--- a/gcc/expr-rewriter.hpp
+++ b/gcc/expr-rewriter.hpp
@@ -14,8 +14,9 @@ public:
_imap[modified] = original;
}
};
- void handle_pointer_arithmetic_constants(gimple *s, tree p, tree i);
- void handle_pointer_arithmetic_nonconstant(gimple *s, tree p, tree i);
+ void handle_pointer_arithmetic_constants(gimple *s, tree p, tree i, bool);
+ void handle_pointer_arithmetic_diff(gimple *s, tree p, tree i);
+ void handle_pointer_arithmetic_nonconstant(gimple *s, tree p, tree i, bool);
bool is_interesting_type(tree);
private:
TypeReconstructor::reorg_record_map_t _map;
diff --git a/gcc/gimple-rewriter.c b/gcc/gimple-rewriter.c
index ce482fb90a9..076083a1805 100644
--- a/gcc/gimple-rewriter.c
+++ b/gcc/gimple-rewriter.c
@@ -34,7 +34,6 @@ GimpleTypeRewriter::handle_pointer_arithmetic(gimple *s)
bool is_valid_input = is_pointer_plus != is_pointer_diff;
gcc_assert(is_valid_input);
// TODO: Implement pointer diff
- if (!is_pointer_plus) return;
const enum gimple_rhs_class rhs_class = gimple_assign_rhs_class(s);
is_valid_input = GIMPLE_BINARY_RHS == rhs_class;
@@ -56,7 +55,7 @@ GimpleTypeRewriter::handle_pointer_arithmetic(gimple *s)
const bool is_constant_case = is_op_0_icst != is_op_1_icst;
if (!is_constant_case)
{
- exprTypeRewriter.handle_pointer_arithmetic_nonconstant(s, op_0, op_1);
+ exprTypeRewriter.handle_pointer_arithmetic_nonconstant(s, op_0, op_1, is_pointer_plus);
return;
}
@@ -66,7 +65,7 @@ GimpleTypeRewriter::handle_pointer_arithmetic(gimple *s)
assert_is_type(maybe_pointer_t, POINTER_TYPE);
tree pointer_variable = maybe_pointer;
- exprTypeRewriter.handle_pointer_arithmetic_constants(s, pointer_variable, integer_constant);
+ exprTypeRewriter.handle_pointer_arithmetic_constants(s, pointer_variable, integer_constant, is_pointer_plus);
}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-26-array-cast-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-26-array-cast-0.c
index 5d1cb281c76..37ac48a701c 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-26-array-cast-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-26-array-cast-0.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=b -fipa-typelist-struct=astruct_s" } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
#include <assert.h>
#include <stdio.h>