summaryrefslogtreecommitdiff
path: root/gcc/expr-rewriter.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr-rewriter.c')
-rw-r--r--gcc/expr-rewriter.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/gcc/expr-rewriter.c b/gcc/expr-rewriter.c
index 6ea2b42c580..f0e517662ba 100644
--- a/gcc/expr-rewriter.c
+++ b/gcc/expr-rewriter.c
@@ -3,9 +3,154 @@
#include <string>
#include <map>
+bool
+ExprTypeRewriter::is_interesting_type(tree t)
+{
+ const bool in_imap = _imap.find(t) != _imap.end();
+ bool interesting = in_imap;
+ if (!interesting) return false;
+
+ tree possibly_copy = (tree)_imap[t];
+ const bool is_copy = possibly_copy == t;
+ interesting = !is_copy;
+ if (!interesting) return false;
+
+ // Let's just do a quick sanity check
+ tree interesting_type = t;
+ const bool has_valid_suffix = strstr(TypeStringifier::get_type_identifier(interesting_type).c_str(), ".reorg");
+ gcc_assert(has_valid_suffix);
+ return true;
+}
+
+void
+ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tree op_1)
+{
+ // _1 = _0 * 72
+ // ... SNIP ...
+ // _2 = _1 + CONSTANT;
+ // ... SNIP ...
+ // _3 = &array + _2; < -- this is where we are
+ //enum tree_code code = TREE_CODE(op_1);
+ //assert_is_type(op_1, SSA_NAME);
+
+ gimple *def_for_variable = SSA_NAME_DEF_STMT(op_1);
+ // It is possible that we are in a negation statement...
+ // Example:
+ // _2 = _1 * 72;
+ // ... SNIP ...
+ // _3 = -_2; < -- def_for_variable **might** be this stmt.
+ // ... SNIP ...
+ // _4 = &array + _3;
+ // Let's find out how many operands we have
+ unsigned num_operands = gimple_num_ops(def_for_variable);
+ // Here operands is kind of a minomer.
+ // operand 0 is the lhs
+ // operand 1 is the rhs
+ // I.e. lhs = (unary_operator) rhs;
+ const 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;
+
+ // Example:
+ // _2 = _1 * 72; <-- Now we are here...
+ // ... SNIP ...
+ // _3 = -_2;
+ // ... SNIP ...
+ // _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);
+
+ // op_0 is the variable
+ // That means that the reorg_type is
+ tree reorg_type_tree = TREE_TYPE(op_0);
+ tree reorg_inner_type = TREE_TYPE(reorg_type_tree);
+ tree reorg_type_size_tree = TYPE_SIZE_UNIT(reorg_inner_type);
+ int reorg_type_size_int = tree_to_shwi(reorg_type_size_tree);
+ // That means that the old type is
+ tree old_type_tree = (tree)_imap[reorg_type_tree];
+ tree old_inner_type = TREE_TYPE(old_type_tree);
+ tree old_type_size_tree = TYPE_SIZE_UNIT(old_inner_type);
+ int old_type_size_int = tree_to_shwi(old_type_size_tree);
+
+ tree old_integer_cst_tree = op_1_earlier;
+ int old_integer_cst_int = tree_to_uhwi(old_integer_cst_tree);
+
+ int offset = 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 + offset;
+ log("%d = %d / %d * %d + %d\n", new_integer_cst_int, old_integer_cst_int, old_type_size_int, reorg_type_size_int, offset);
+
+ 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)
+{
+ // So, because we have already changed the type
+ // tree p will either be the original type
+ // if we do not need to modify this expression
+ // How do we know if we have an original type?
+ // It is when we don't have a type in our map
+ tree possibly_reorged_type = TREE_TYPE(p);
+ bool is_interesting_case = is_interesting_type(possibly_reorged_type);
+ if (!is_interesting_case) return;
+
+ tree reorg_type = possibly_reorged_type; // this is the type of the variable
+ const_tree original_type = _imap[reorg_type];
+ // If we are here, that means that our type has the ".reorg" suffix
+ const bool has_suffix = strstr(TypeStringifier::get_type_identifier(reorg_type).c_str(), ".reorg");
+ bool is_valid_input = has_suffix;
+ gcc_assert(is_valid_input);
+
+ // We need to know what size is the previous original type
+ tree inner_reorg_type = TREE_TYPE(reorg_type);
+ tree inner_orig_type = TREE_TYPE(original_type);
+ tree old_size_tree = TYPE_SIZE_UNIT(inner_orig_type);
+ int old_size_int = tree_to_shwi(old_size_tree);
+ tree new_size_tree = TYPE_SIZE_UNIT(inner_reorg_type);
+ int new_size_int = tree_to_shwi(new_size_tree);
+ tree old_integer_cst_tree = i;
+ int old_integer_cst_int = tree_to_uhwi(old_integer_cst_tree);
+
+ int offset = old_integer_cst_int % old_size_int;
+ const bool is_modulo = offset == 0;
+ is_valid_input = is_modulo;
+ gcc_assert(is_valid_input);
+
+ int new_integer_cst_int = old_integer_cst_int / old_size_int * new_size_int + offset;
+ log("%d = %d / %d * %d\n", new_integer_cst_int, old_integer_cst_int, old_size_int, new_size_int);
+
+ tree new_integer_cst_tree = build_int_cst(TREE_TYPE(old_integer_cst_tree), new_integer_cst_int);
+ gimple_set_op(s, 2, new_integer_cst_tree);
+
+
+}
+
void
ExprTypeRewriter::_walk_post(const_tree e)
{
+ const enum tree_code code = TREE_CODE(e);
+ log("tree_code_name = %s\n", get_tree_code_name(code));
+
+ if(dump_file) {
+ print_generic_expr(dump_file, (tree)e);
+ log("\n");
+ }
+
gcc_assert(e);
tree t = TREE_TYPE(e);
const bool in_map = _map.find(t) != _map.end();