1 /* Lower and optimize address expressions.
2 Copyright (C) 2015-2022 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"
36 #include "tree-ssanames.h"
37 #include "fold-const.h"
38 #include "gimple-expr.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "tree-pass.h"
48 const pass_data pass_data_laddress
=
50 GIMPLE_PASS
, /* type */
51 "laddress", /* name */
52 OPTGROUP_NONE
, /* optinfo_flags */
53 TV_GIMPLE_LADDRESS
, /* tv_id */
54 ( PROP_cfg
| PROP_ssa
), /* properties_required */
55 0, /* properties_provided */
56 0, /* properties_destroyed */
57 0, /* todo_flags_start */
58 0, /* todo_flags_finish */
61 class pass_laddress
: public gimple_opt_pass
64 pass_laddress (gcc::context
*ctxt
)
65 : gimple_opt_pass (pass_data_laddress
, ctxt
)
68 /* opt_pass methods: */
69 opt_pass
* clone () final override
{ return new pass_laddress (m_ctxt
); }
70 bool gate (function
*) final override
{ return optimize
!= 0; }
71 unsigned int execute (function
*) final override
;
73 }; // class pass_laddress
76 pass_laddress::execute (function
*fun
)
80 FOR_EACH_BB_FN (bb
, fun
)
82 for (gimple_stmt_iterator gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
84 gimple
*stmt
= gsi_stmt (gsi
);
85 if (!is_gimple_assign (stmt
)
86 || gimple_assign_rhs_code (stmt
) != ADDR_EXPR
87 || is_gimple_invariant_address (gimple_assign_rhs1 (stmt
)))
93 /* Lower ADDR_EXPR assignments:
99 This ought to aid the vectorizer and expose CSE opportunities.
102 tree expr
= gimple_assign_rhs1 (stmt
);
103 poly_int64 bitsize
, bitpos
;
106 int volatilep
= 0, reversep
, unsignedp
= 0;
107 base
= get_inner_reference (TREE_OPERAND (expr
, 0), &bitsize
,
108 &bitpos
, &offset
, &mode
, &unsignedp
,
109 &reversep
, &volatilep
);
110 gcc_assert (base
!= NULL_TREE
);
111 poly_int64 bytepos
= exact_div (bitpos
, BITS_PER_UNIT
);
112 if (offset
!= NULL_TREE
)
114 if (maybe_ne (bytepos
, 0))
115 offset
= size_binop (PLUS_EXPR
, offset
, size_int (bytepos
));
116 offset
= force_gimple_operand_gsi (&gsi
, offset
, true, NULL
,
117 true, GSI_SAME_STMT
);
118 base
= build_fold_addr_expr (base
);
119 base
= force_gimple_operand_gsi (&gsi
, base
, true, NULL
,
120 true, GSI_SAME_STMT
);
121 gimple
*g
= gimple_build_assign (gimple_assign_lhs (stmt
),
122 POINTER_PLUS_EXPR
, base
, offset
);
123 gsi_replace (&gsi
, g
, false);
135 make_pass_laddress (gcc::context
*ctxt
)
137 return new pass_laddress (ctxt
);