11debfc3dSmrg /* Lower and optimize address expressions.
2*8feb0f0bSmrg Copyright (C) 2015-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Marek Polacek <polacek@redhat.com>
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
211debfc3dSmrg #include "config.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "alias.h"
251debfc3dSmrg #include "predict.h"
261debfc3dSmrg #include "tm.h"
271debfc3dSmrg #include "function.h"
281debfc3dSmrg #include "dominance.h"
291debfc3dSmrg #include "cfg.h"
301debfc3dSmrg #include "basic-block.h"
311debfc3dSmrg #include "tree-ssa-alias.h"
321debfc3dSmrg #include "symtab.h"
331debfc3dSmrg #include "tree.h"
341debfc3dSmrg #include "stringpool.h"
351debfc3dSmrg #include "tree-vrp.h"
361debfc3dSmrg #include "tree-ssanames.h"
371debfc3dSmrg #include "fold-const.h"
381debfc3dSmrg #include "gimple-expr.h"
391debfc3dSmrg #include "gimple.h"
401debfc3dSmrg #include "gimplify.h"
411debfc3dSmrg #include "gimple-iterator.h"
421debfc3dSmrg #include "gimplify-me.h"
431debfc3dSmrg #include "tree-pass.h"
441debfc3dSmrg
451debfc3dSmrg
461debfc3dSmrg namespace {
471debfc3dSmrg
481debfc3dSmrg const pass_data pass_data_laddress =
491debfc3dSmrg {
501debfc3dSmrg GIMPLE_PASS, /* type */
511debfc3dSmrg "laddress", /* name */
521debfc3dSmrg OPTGROUP_NONE, /* optinfo_flags */
531debfc3dSmrg TV_GIMPLE_LADDRESS, /* tv_id */
541debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
551debfc3dSmrg 0, /* properties_provided */
561debfc3dSmrg 0, /* properties_destroyed */
571debfc3dSmrg 0, /* todo_flags_start */
581debfc3dSmrg 0, /* todo_flags_finish */
591debfc3dSmrg };
601debfc3dSmrg
611debfc3dSmrg class pass_laddress : public gimple_opt_pass
621debfc3dSmrg {
631debfc3dSmrg public:
pass_laddress(gcc::context * ctxt)641debfc3dSmrg pass_laddress (gcc::context *ctxt)
651debfc3dSmrg : gimple_opt_pass (pass_data_laddress, ctxt)
661debfc3dSmrg {}
671debfc3dSmrg
681debfc3dSmrg /* opt_pass methods: */
clone()691debfc3dSmrg opt_pass * clone () { return new pass_laddress (m_ctxt); }
gate(function *)701debfc3dSmrg virtual bool gate (function *) { return optimize != 0; }
711debfc3dSmrg virtual unsigned int execute (function *);
721debfc3dSmrg
731debfc3dSmrg }; // class pass_laddress
741debfc3dSmrg
751debfc3dSmrg unsigned int
execute(function * fun)761debfc3dSmrg pass_laddress::execute (function *fun)
771debfc3dSmrg {
781debfc3dSmrg basic_block bb;
791debfc3dSmrg
801debfc3dSmrg FOR_EACH_BB_FN (bb, fun)
811debfc3dSmrg {
821debfc3dSmrg for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
831debfc3dSmrg {
841debfc3dSmrg gimple *stmt = gsi_stmt (gsi);
851debfc3dSmrg if (!is_gimple_assign (stmt)
861debfc3dSmrg || gimple_assign_rhs_code (stmt) != ADDR_EXPR
871debfc3dSmrg || is_gimple_invariant_address (gimple_assign_rhs1 (stmt)))
881debfc3dSmrg {
891debfc3dSmrg gsi_next (&gsi);
901debfc3dSmrg continue;
911debfc3dSmrg }
921debfc3dSmrg
931debfc3dSmrg /* Lower ADDR_EXPR assignments:
941debfc3dSmrg _4 = &b[i_9];
951debfc3dSmrg into
961debfc3dSmrg _1 = (sizetype) i_9;
971debfc3dSmrg _7 = _1 * 4;
981debfc3dSmrg _4 = &b + _7;
991debfc3dSmrg This ought to aid the vectorizer and expose CSE opportunities.
1001debfc3dSmrg */
1011debfc3dSmrg
1021debfc3dSmrg tree expr = gimple_assign_rhs1 (stmt);
103a2dc1f3fSmrg poly_int64 bitsize, bitpos;
1041debfc3dSmrg tree base, offset;
1051debfc3dSmrg machine_mode mode;
1061debfc3dSmrg int volatilep = 0, reversep, unsignedp = 0;
1071debfc3dSmrg base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
1081debfc3dSmrg &bitpos, &offset, &mode, &unsignedp,
1091debfc3dSmrg &reversep, &volatilep);
110a2dc1f3fSmrg gcc_assert (base != NULL_TREE);
111a2dc1f3fSmrg poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
1121debfc3dSmrg if (offset != NULL_TREE)
1131debfc3dSmrg {
114a2dc1f3fSmrg if (maybe_ne (bytepos, 0))
115a2dc1f3fSmrg offset = size_binop (PLUS_EXPR, offset, size_int (bytepos));
1161debfc3dSmrg offset = force_gimple_operand_gsi (&gsi, offset, true, NULL,
1171debfc3dSmrg true, GSI_SAME_STMT);
1181debfc3dSmrg base = build_fold_addr_expr (base);
1191debfc3dSmrg base = force_gimple_operand_gsi (&gsi, base, true, NULL,
1201debfc3dSmrg true, GSI_SAME_STMT);
1211debfc3dSmrg gimple *g = gimple_build_assign (gimple_assign_lhs (stmt),
1221debfc3dSmrg POINTER_PLUS_EXPR, base, offset);
1231debfc3dSmrg gsi_replace (&gsi, g, false);
1241debfc3dSmrg }
1251debfc3dSmrg gsi_next (&gsi);
1261debfc3dSmrg }
1271debfc3dSmrg }
1281debfc3dSmrg
1291debfc3dSmrg return 0;
1301debfc3dSmrg }
1311debfc3dSmrg
1321debfc3dSmrg } // anon namespace
1331debfc3dSmrg
1341debfc3dSmrg gimple_opt_pass *
make_pass_laddress(gcc::context * ctxt)1351debfc3dSmrg make_pass_laddress (gcc::context *ctxt)
1361debfc3dSmrg {
1371debfc3dSmrg return new pass_laddress (ctxt);
1381debfc3dSmrg }
139