diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-17 18:31:52 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-17 18:31:52 +0200 |
commit | 5e12dd9d138a0afec5290df234523204e6fef21d (patch) | |
tree | aacd2786c9632c81edb0380a8fc286930bd5547e /gcc/expr-rewriter.c | |
parent | 1ea9a204ef32fc5c3e1636c003ac68bd32cc2723 (diff) |
wip
Diffstat (limited to 'gcc/expr-rewriter.c')
-rw-r--r-- | gcc/expr-rewriter.c | 153 |
1 files changed, 136 insertions, 17 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 |