X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Firmemory.c;h=9b3343aee9349c2d0ba2fc60be12ca325f8084ca;hb=af874fa6439abc37a74564bf32a623dee73e9e34;hp=082dc6685e05abe59c9c4d5a2a4d4e3e16f5c2ed;hpb=263f27959bcf3612c59dd6d1214e30ac1d0472e3;p=libfirm diff --git a/ir/ana/irmemory.c b/ir/ana/irmemory.c index 082dc6685..9b3343aee 100644 --- a/ir/ana/irmemory.c +++ b/ir/ana/irmemory.c @@ -1,13 +1,28 @@ /* - * Project: libFIRM - * File name: ir/ana/irmemory.c - * Purpose: Memory disambiguator - * Author: Michael Beck - * Modified by: - * Created: 27.12.2006 - * CVS-ID: $Id$ - * Copyright: (c) 2006-2007 Universität Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Memory disambiguator + * @author Michael Beck + * @date 27.12.2006 + * @version $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -69,6 +84,25 @@ static ir_node *find_base_adr(ir_node *sel, ir_entity **pEnt) { return ptr; } /* find_base_adr */ +/** + * Check if the address can be decomposed into base PLUS offset. + */ +static int has_offset(ir_node *adr, int *offset) { + if (is_SymConst(adr)) { + *offset = 0; + return 1; + } + if (is_Sel(adr)) { + ir_entity *ent = get_Sel_entity(adr); + ir_type *owner = get_entity_owner(ent); + + if (get_type_state(owner) != layout_fixed) { + /* The layout is NOT fixed yet, symbolic evaluation needed */ + } + } + return 0; +} /* has_offset */ + /** * Two address expressions have the same base address, * check if there offsets are different. @@ -77,6 +111,10 @@ static ir_node *find_base_adr(ir_node *sel, ir_entity **pEnt) { * @param adr2 The second address. */ static ir_alias_relation different_offsets(ir_node *adr1, ir_node *adr2) { + int offset1, offset2; + if (has_offset(adr1, &offset1) && has_offset(adr2, &offset2)) { + /* */ + } return may_alias; } /* different_offsets */ @@ -132,6 +170,20 @@ static ir_alias_relation different_types(ir_node *adr1, ir_node *adr2) return may_alias; } /* different_types */ +/** + * Returns non-zero if a node is a routine parameter. + * + * @param node the node to test + */ +static int is_arg_Proj(ir_node *node) { + if (! is_Proj(node)) + return 0; + node = get_Proj_pred(node); + if (! is_Proj(node)) + return 0; + return pn_Start_T_args == get_Proj_proj(node) && is_Start(get_Proj_pred(node)); +} /* is_arg_Proj */ + /** * Determine the alias relation between two addresses. */ @@ -140,7 +192,7 @@ static ir_alias_relation _get_alias_relation( ir_node *adr1, ir_mode *mode1, ir_node *adr2, ir_mode *mode2) { - opcode op1, op2; + ir_opcode op1, op2; ir_entity *ent1, *ent2; unsigned options; @@ -158,7 +210,7 @@ static ir_alias_relation _get_alias_relation( /* Two save some code, sort the addresses by its id's. Beware, this might break some things, so better check here. */ - assert(iro_SymConst < iro_Sel && "Code dependence breaked"); + assert(iro_SymConst < iro_Sel && iro_Sel < iro_Proj && "Code dependence breaked"); op1 = get_irn_opcode(adr1); op2 = get_irn_opcode(adr2); @@ -232,7 +284,14 @@ static ir_alias_relation _get_alias_relation( /* the second one is a TLS variable so they are always different (R1 d) */ return no_alias; + } else if (is_arg_Proj(base2)) { + /* the second one is an offset from a parameter so they are + always different (R1 e) */ + return no_alias; } + } else if (is_arg_Proj(adr2)) { + /* a local variable and a parameter are always different (R1 e) */ + return no_alias; } } else if (base1 == get_irg_tls(irg)) { /* the first is a TLS variable */ @@ -253,16 +312,29 @@ static ir_alias_relation _get_alias_relation( return different_offsets(adr1, adr2); } } + } else if (is_arg_Proj(base1)) { + /* the first one is an offset from a parameter */ + if (is_Sel(adr2)) { + /* the second address is a Sel */ + ir_node *base2 = find_base_adr(adr2, &ent2); + + if (base2 == get_irg_frame(irg)) { + /* the second one is a local variable so they are always + different (R1 e) */ + return no_alias; + } + } } } - if (options & aa_opt_type_based) { + if (options & aa_opt_type_based) { /* Type based alias analysis */ ir_alias_relation rel; if (options & aa_opt_byte_type_may_alias) { if (get_mode_size_bits(mode1) == 8 || get_mode_size_bits(mode2) == 8) { - /* One of the modes address a byte. Assume a may_alias. */ - return may_alias; + /* One of the modes address a byte. Assume a may_alias and leave + the type based check. */ + goto leave_type_based_alias; } } /* cheap check: If the mode sizes did not match, the types MUST be different */ @@ -273,6 +345,7 @@ static ir_alias_relation _get_alias_relation( rel = different_types(adr1, adr2); if (rel != may_alias) return rel; +leave_type_based_alias:; } /* do we have a language specific memory disambiguator? */ @@ -533,6 +606,7 @@ static void init_taken_flag(ir_type * tp) { } } /* init_taken_flag */ +#if 0 /** * Print the address taken state of all entities of a given type for debugging. */ @@ -548,6 +622,7 @@ static void print_address_taken_state(ir_type *tp) { } } } /* print_address_taken_state */ +#endif /** * Post-walker: check for global entity address @@ -562,11 +637,11 @@ static void check_global_address(ir_node *irn, void *env) { ent = get_SymConst_entity(irn); } else if (is_Sel(irn) && get_Sel_ptr(irn) == tls) { /* A TLS variable. */ - ent = get_SymConst_entity(irn); + ent = get_Sel_entity(irn); } else return; - if (get_entity_address_taken(ent) == ir_address_not_taken) { + if (get_entity_address_taken(ent) >= ir_address_taken) { /* Already at the maximum. */ return; }