1 /* Lower and optimize address expressions.
2 Copyright (C) 2015 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "dominance.h"
30 #include "basic-block.h"
31 #include "tree-ssa-alias.h"
34 #include "stringpool.h"
35 #include "tree-ssanames.h"
36 #include "fold-const.h"
37 #include "gimple-expr.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "tree-pass.h"
47 const pass_data pass_data_laddress
=
49 GIMPLE_PASS
, /* type */
50 "laddress", /* name */
51 OPTGROUP_NONE
, /* optinfo_flags */
52 TV_GIMPLE_LADDRESS
, /* tv_id */
53 ( PROP_cfg
| PROP_ssa
), /* properties_required */
54 0, /* properties_provided */
55 0, /* properties_destroyed */
56 0, /* todo_flags_start */
57 0, /* todo_flags_finish */
60 class pass_laddress
: public gimple_opt_pass
63 pass_laddress (gcc::context
*ctxt
)
64 : gimple_opt_pass (pass_data_laddress
, ctxt
)
67 /* opt_pass methods: */
68 opt_pass
* clone () { return new pass_laddress (m_ctxt
); }
69 virtual bool gate (function
*) { return optimize
!= 0; }
70 virtual unsigned int execute (function
*);
72 }; // class pass_laddress
75 pass_laddress::execute (function
*fun
)
79 FOR_EACH_BB_FN (bb
, fun
)
81 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
83 gimple
*stmt
= gsi_stmt (gsi
);
84 if (!is_gimple_assign (stmt
)
85 || gimple_assign_rhs_code (stmt
) != ADDR_EXPR
86 || is_gimple_invariant_address (gimple_assign_rhs1 (stmt
)))
92 /* Lower ADDR_EXPR assignments:
98 This ought to aid the vectorizer and expose CSE opportunities.
101 tree expr
= gimple_assign_rhs1 (stmt
);
102 HOST_WIDE_INT bitsize
, bitpos
;
105 int volatilep
= 0, reversep
, unsignedp
= 0;
106 base
= get_inner_reference (TREE_OPERAND (expr
, 0), &bitsize
,
107 &bitpos
, &offset
, &mode
, &unsignedp
,
108 &reversep
, &volatilep
, false);
109 gcc_assert (base
!= NULL_TREE
&& (bitpos
% BITS_PER_UNIT
) == 0);
110 if (offset
!= NULL_TREE
)
113 offset
= size_binop (PLUS_EXPR
, offset
,
114 size_int (bitpos
/ BITS_PER_UNIT
));
115 offset
= force_gimple_operand_gsi (&gsi
, offset
, true, NULL
,
116 true, GSI_SAME_STMT
);
117 base
= build_fold_addr_expr (base
);
118 base
= force_gimple_operand_gsi (&gsi
, base
, true, NULL
,
119 true, GSI_SAME_STMT
);
120 gimple
*g
= gimple_build_assign (gimple_assign_lhs (stmt
),
121 POINTER_PLUS_EXPR
, base
, offset
);
122 gsi_replace (&gsi
, g
, false);
134 make_pass_laddress (gcc::context
*ctxt
)
136 return new pass_laddress (ctxt
);