xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/gimple-laddress.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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