2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief This file contains functions for matching firm graphs for
23 * nodes that can be used as addressmode for x86 commands
24 * @author Matthias Braun
31 #include "ia32_address_mode.h"
32 #include "ia32_transform.h"
38 #include "iredges_t.h"
41 #include "../benode_t.h"
45 /* gas/ld don't support negative symconsts :-( */
46 #undef SUPPORT_NEGATIVE_SYMCONSTS
48 static bitset_t *non_address_mode_nodes;
50 static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
55 switch(get_irn_opcode(node)) {
57 if(!tarval_is_long(get_Const_tarval(node))) {
59 ir_fprintf(stderr, "Optimisation warning tarval of %+F(%+F) is not "
60 "a long.\n", node, current_ir_graph);
66 #ifndef SUPPORT_NEGATIVE_SYMCONSTS
67 /* unfortunately the assembler/linker doesn't support -symconst */
72 if(get_SymConst_kind(node) != symconst_addr_ent)
81 if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
84 left = get_binop_left(node);
85 right = get_binop_right(node);
86 if(!do_is_immediate(left, symconsts, negate))
88 if(!do_is_immediate(right, symconsts, is_Sub(node) ? !negate : negate))
99 static int is_immediate_simple(const ir_node *node)
102 return do_is_immediate(node, &symconsts, 0);
105 static int is_immediate(ia32_address_t *addr, const ir_node *node, int negate)
108 if(addr->symconst_ent != NULL)
111 return do_is_immediate(node, &symconsts, negate);
114 static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
121 switch(get_irn_opcode(node)) {
123 tv = get_Const_tarval(node);
124 val = get_tarval_long(tv);
132 if(addr->symconst_ent != NULL) {
133 panic("Internal error: more than 1 symconst in address "
136 addr->symconst_ent = get_SymConst_entity(node);
137 #ifndef SUPPORT_NEGATIVE_SYMCONSTS
140 addr->symconst_sign = negate;
143 assert(!bitset_is_set(non_address_mode_nodes, get_irn_idx(node)));
144 left = get_Add_left(node);
145 right = get_Add_right(node);
146 eat_immediate(addr, left, negate);
147 eat_immediate(addr, right, negate);
150 assert(!bitset_is_set(non_address_mode_nodes, get_irn_idx(node)));
151 left = get_Sub_left(node);
152 right = get_Sub_right(node);
153 eat_immediate(addr, left, negate);
154 eat_immediate(addr, right, !negate);
157 panic("Internal error in immediate address calculation");
161 static ir_node *eat_immediates(ia32_address_t *addr, ir_node *node, int force)
163 if(!force && bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
167 ir_node *left = get_Add_left(node);
168 ir_node *right = get_Add_right(node);
170 if(is_immediate(addr, left, 0)) {
171 eat_immediate(addr, left, 0);
172 return eat_immediates(addr, right, 0);
174 if(is_immediate(addr, right, 0)) {
175 eat_immediate(addr, right, 0);
176 return eat_immediates(addr, left, 0);
178 } else if(is_Sub(node)) {
179 ir_node *left = get_Sub_left(node);
180 ir_node *right = get_Sub_right(node);
182 if(is_immediate(addr, right, 1)) {
183 eat_immediate(addr, right, 1);
184 return eat_immediates(addr, left, 0);
191 static int eat_shl(ia32_address_t *addr, ir_node *node)
193 ir_node *right = get_Shl_right(node);
197 /* we can only eat a shl if we don't have a scale or index set */
198 if(addr->scale != 0 || addr->index != NULL)
201 /* we can use shl with 1, 2 or 3 shift */
204 tv = get_Const_tarval(right);
205 if(!tarval_is_long(tv))
207 val = get_tarval_long(tv);
208 if(val < 0 || val > 3)
211 ir_fprintf(stderr, "Optimisation warning: unoptimized Shl(,0) found\n");
213 if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
216 #ifndef AGGRESSIVE_AM
217 if(get_irn_n_edges(node) > 1)
222 addr->index = eat_immediates(addr, get_Shl_left(node), 0);
227 * Returns non-zero if a value of a given mode can be stored in GP registers.
229 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
230 if(mode == mode_fpcw)
232 if(get_mode_size_bits(mode) > 32)
234 return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
238 * Check, if a given done is a Down-Conv, ie a integer Conv
239 * from a mode with mode to a mode with lesser bits.
240 * Moreover, we return only true if the node has not more than 1 user.
242 static int is_downconv(const ir_node *node)
250 /* we only want to skip the conv when we're the only user
251 * (not optimal but for now...)
253 if(get_irn_n_edges(node) > 1)
256 src_mode = get_irn_mode(get_Conv_op(node));
257 dest_mode = get_irn_mode(node);
258 return mode_needs_gp_reg(src_mode)
259 && mode_needs_gp_reg(dest_mode)
260 && get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode);
264 * Skip all Donw-Conv's on a given node.
266 static ir_node *skip_downconv(ir_node *node)
268 while(is_downconv(node))
269 node = get_Conv_op(node);
274 void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
279 if(is_immediate(addr, node, 0)) {
280 eat_immediate(addr, node, 0);
284 #ifndef AGGRESSIVE_AM
285 if(!force && get_irn_n_edges(node) > 1) {
291 if(!force && bitset_is_set(non_address_mode_nodes, get_irn_idx(node))) {
296 eat_imms = eat_immediates(addr, node, force);
297 if(eat_imms != node) {
299 eat_imms = skip_downconv(eat_imms);
304 #ifndef AGGRESSIVE_AM
305 if(get_irn_n_edges(node) > 1) {
310 if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node))) {
316 /* starting point Add, Sub or Shl, FrameAddr */
318 if(eat_shl(addr, node))
320 } else if(is_immediate(addr, node, 0)) {
321 eat_immediate(addr, node, 0);
323 } else if(be_is_FrameAddr(node)) {
324 assert(addr->base == NULL);
325 assert(addr->frame_entity == NULL);
326 addr->base = be_get_FrameAddr_frame(node);
328 addr->frame_entity = be_get_FrameAddr_entity(node);
330 } else if(is_Add(node)) {
331 ir_node *left = get_Add_left(node);
332 ir_node *right = get_Add_right(node);
335 left = skip_downconv(left);
336 right = skip_downconv(right);
339 assert(force || !is_immediate(addr, left, 0));
340 assert(force || !is_immediate(addr, right, 0));
342 if(is_Shl(left) && eat_shl(addr, left)) {
344 } else if(is_Shl(right) && eat_shl(addr, right)) {
347 if(left != NULL && be_is_FrameAddr(left)
348 && !bitset_is_set(non_address_mode_nodes, get_irn_idx(left))) {
349 assert(addr->base == NULL);
350 assert(addr->frame_entity == NULL);
351 addr->base = be_get_FrameAddr_frame(left);
353 addr->frame_entity = be_get_FrameAddr_entity(left);
355 } else if(right != NULL && be_is_FrameAddr(right)
356 && !bitset_is_set(non_address_mode_nodes, get_irn_idx(right))) {
357 assert(addr->base == NULL);
358 assert(addr->frame_entity == NULL);
359 addr->base = be_get_FrameAddr_frame(right);
361 addr->frame_entity = be_get_FrameAddr_entity(right);
366 if(addr->base != NULL) {
367 assert(addr->index == NULL && addr->scale == 0);
368 assert(right == NULL);
375 if(addr->base == NULL) {
378 assert(addr->index == NULL && addr->scale == 0);
390 static void mark_non_address_nodes(ir_node *node, void *env)
400 switch(get_irn_opcode(node)) {
402 ptr = get_Load_ptr(node);
403 mem = get_Load_mem(node);
405 bitset_set(non_address_mode_nodes, get_irn_idx(mem));
409 val = get_Store_value(node);
410 ptr = get_Store_ptr(node);
411 mem = get_Store_mem(node);
413 bitset_set(non_address_mode_nodes, get_irn_idx(val));
414 bitset_set(non_address_mode_nodes, get_irn_idx(mem));
418 left = get_Add_left(node);
419 right = get_Add_right(node);
420 /* if we can do source address mode then we will never fold the add
421 * into address mode */
422 if(!mode_is_float(get_irn_mode(node)) && (is_immediate_simple(right) ||
423 (!use_source_address_mode(get_nodes_block(node), left, right)
424 && !use_source_address_mode(get_nodes_block(node), right, left))))
428 bitset_set(non_address_mode_nodes, get_irn_idx(node));
432 arity = get_irn_arity(node);
434 for(i = 0; i < arity; ++i) {
435 ir_node *in = get_irn_n(node, i);
436 bitset_set(non_address_mode_nodes, get_irn_idx(in));
442 void calculate_non_address_mode_nodes(ir_graph *irg)
444 non_address_mode_nodes = bitset_malloc(get_irg_last_idx(irg));
446 irg_walk_graph(irg, NULL, mark_non_address_nodes, NULL);
449 void free_non_address_mode_nodes(void)
451 bitset_free(non_address_mode_nodes);