From 0562b784fa989547001f390323209e873be92603 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Fri, 12 Jan 2007 18:02:02 +0000 Subject: [PATCH] - memory disambiguator option can be set for the irp and for every graph - more cases regarding TLS/locals implemented - type based analysis: check modes first - add option for bytes access is a may-alias for anything [r8517] --- ir/ana/irmemory.c | 110 +++++++++++++++++++++++++++++++++++----------- ir/ana/irmemory.h | 63 ++++++++++++++++++++++---- 2 files changed, 138 insertions(+), 35 deletions(-) diff --git a/ir/ana/irmemory.c b/ir/ana/irmemory.c index bec591623..94891fffb 100644 --- a/ir/ana/irmemory.c +++ b/ir/ana/irmemory.c @@ -29,16 +29,43 @@ /** The source language specific language disambiguator function. */ static DISAMBIGUATOR_FUNC language_disambuigator = NULL; +/** The global memory disambiguator options. */ +static unsigned global_mem_disamgig_opt = aa_opt_no_opt; + +/* Get the memory disambiguator options for a graph. */ +unsigned get_irg_memory_disambiguator_options(ir_graph *irg) { + unsigned opt = irg->mem_disamgig_opt; + if (opt & aa_opt_inherited) + return global_mem_disamgig_opt; + return opt; +} /* get_irg_memory_disambiguator_options */ + +/* Set the memory disambiguator options for a graph. */ +void set_irg_memory_disambiguator_options(ir_graph *irg, unsigned options) { + irg->mem_disamgig_opt = options & ~aa_opt_inherited; +} /* set_irg_memory_disambiguator_options */ + +/* Set the global disambiguator options for all graphs not having local options. */ +void set_irp_memory_disambiguator_options(unsigned options) { + global_mem_disamgig_opt = options; +} /* set_irp_memory_disambiguator_options */ + /** - * Find the base address of an Sel node. + * Find the base address and entity of an Sel node. + * + * @param sel the node + * @param pEnt after return points to the base entity. + * + * @return the base address. */ -static ir_node *find_base_adr(ir_node *sel) { +static ir_node *find_base_adr(ir_node *sel, ir_entity **pEnt) { ir_node *ptr = get_Sel_ptr(sel); while (is_Sel(ptr)) { sel = ptr; ptr = get_Sel_ptr(sel); } + *pEnt = get_Sel_entity(sel); return ptr; } /* find_base_adr */ @@ -56,6 +83,9 @@ static ir_alias_relation different_offsets(ir_node *adr1, ir_node *adr2) { /** * Determine the alias relation by checking if adr1 and adr2 are pointer * to different type. + * + * @param adr1 The first address. + * @param adr2 The second address. */ static ir_alias_relation different_types(ir_node *adr1, ir_node *adr2) { @@ -108,11 +138,11 @@ static ir_alias_relation different_types(ir_node *adr1, ir_node *adr2) static ir_alias_relation _get_alias_relation( ir_graph *irg, ir_node *adr1, ir_mode *mode1, - ir_node *adr2, ir_mode *mode2, - unsigned options) + ir_node *adr2, ir_mode *mode2) { opcode op1, op2; - ir_entity *ent1; + ir_entity *ent1, *ent2; + unsigned options; if (! get_opt_alias_analysis()) return may_alias; @@ -120,6 +150,12 @@ static ir_alias_relation _get_alias_relation( if (adr1 == adr2) return sure_alias; + options = get_irg_memory_disambiguator_options(irg); + + /* The Armageddon switch */ + if (options & aa_opt_no_alias) + return no_alias; + /* 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"); @@ -143,11 +179,13 @@ static ir_alias_relation _get_alias_relation( they are different (R1 a) */ if (get_SymConst_entity(adr1) != get_SymConst_entity(adr2)) return no_alias; - else + else { + /* equal addresses */ return sure_alias; + } } if (is_Sel(adr2)) { - ir_node *base = find_base_adr(adr2); + ir_node *base = find_base_adr(adr2, &ent2); if (is_SymConst(base) && get_SymConst_kind(base) == symconst_addr_ent) { /* base address is a global var (R1 a) */ @@ -175,16 +213,21 @@ static ir_alias_relation _get_alias_relation( } } else if (is_Sel(adr1)) { /* the first address is a Sel */ - ir_node *base1 = find_base_adr(adr1); + ir_node *base1 = find_base_adr(adr1, &ent1); if (base1 == get_irg_frame(irg)) { /* the first is a local variable */ if (is_Sel(adr2)) { /* the second address is a Sel */ - ir_node *base2 = find_base_adr(adr2); + ir_node *base2 = find_base_adr(adr2, &ent2); if (base2 == get_irg_frame(irg)) { - /* the second one is a local variable */ + /* both addresses are local variables and we know + they are different (R1 a) */ + if (ent1 != ent2) + return no_alias; + else + return different_offsets(adr1, adr2); } else if (base2 == get_irg_tls(irg)) { /* the second one is a TLS variable so they are always different (R1 d) */ @@ -195,22 +238,39 @@ static ir_alias_relation _get_alias_relation( /* the first is a TLS variable */ if (is_Sel(adr2)) { /* the second address is a Sel */ - ir_node *base2 = find_base_adr(adr2); + 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 d) */ return no_alias; } else if (base2 == get_irg_tls(irg)) { - /* the second one is a TLS variable */ + /* both addresses are TLS variables and we know + they are different (R1 a) */ + if (ent1 != ent2) + return no_alias; + else + return different_offsets(adr1, adr2); } } } } - if (options & opt_strong_typed) { + if (options & aa_opt_type_based) { + 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; + } + } + /* cheap check: If the mode sizes did not match, the types MUST be different */ + if (get_mode_size_bits(mode1) != get_mode_size_bits(mode2)) + return no_alias; + /* try rule R5 */ - ir_alias_relation rel = different_types(adr1, adr2); + rel = different_types(adr1, adr2); if (rel != may_alias) return rel; } @@ -232,10 +292,9 @@ static ir_alias_relation _get_alias_relation( ir_alias_relation get_alias_relation( ir_graph *irg, ir_node *adr1, ir_mode *mode1, - ir_node *adr2, ir_mode *mode2, - unsigned options) + ir_node *adr2, ir_mode *mode2) { - ir_alias_relation rel = _get_alias_relation(irg, adr1, mode1, adr2, mode2, options); + ir_alias_relation rel = _get_alias_relation(irg, adr1, mode1, adr2, mode2); return rel; } /* get_alias_relation */ @@ -279,8 +338,7 @@ void mem_disambig_init(void) { ir_alias_relation get_alias_relation_ex( ir_graph *irg, ir_node *adr1, ir_mode *mode1, - ir_node *adr2, ir_mode *mode2, - unsigned options) + ir_node *adr2, ir_mode *mode2) { mem_disambig_entry key, *entry; @@ -299,7 +357,7 @@ ir_alias_relation get_alias_relation_ex( if (entry) return entry->result; - key.result = get_alias_relation(irg, adr1, mode1, adr2, mode2, options); + key.result = get_alias_relation(irg, adr1, mode1, adr2, mode2); set_insert(result_cache, &key, sizeof(key), HASH_ENTRY(adr1, adr2)); return key.result; @@ -413,7 +471,7 @@ static void analyse_irg_address_taken(ir_graph *irg) { /* set initial state to not_taken, as this is the "smallest" state */ for (i = get_class_n_members(ft) - 1; i >= 0; --i) { - entity *ent = get_class_member(ft, i); + ir_entity *ent = get_class_member(ft, i); set_entity_address_taken(ent, ir_address_not_taken); } @@ -466,7 +524,7 @@ static void init_taken_flag(ir_type * tp) { /* All external visible entities are at least ir_address_taken_unknown. This is very conservative. */ for (i = get_compound_n_members(tp) - 1; i >= 0; --i) { - entity *ent = get_compound_member(tp, i); + ir_entity *ent = get_compound_member(tp, i); ir_address_taken_state state; state = get_entity_visibility(ent) == visibility_external_visible ? @@ -481,7 +539,7 @@ static void init_taken_flag(ir_type * tp) { static void print_address_taken_state(ir_type *tp) { int i; for (i = get_compound_n_members(tp) - 1; i >= 0; --i) { - entity *ent = get_compound_member(tp, i); + ir_entity *ent = get_compound_member(tp, i); ir_address_taken_state state = get_entity_address_taken(ent); if (state != ir_address_not_taken) { @@ -496,7 +554,7 @@ static void print_address_taken_state(ir_type *tp) { */ static void check_global_address(ir_node *irn, void *env) { ir_node *tls = env; - entity *ent; + ir_entity *ent; ir_address_taken_state state; if (is_SymConst(irn) && get_SymConst_kind(irn) == symconst_addr_ent) { @@ -532,8 +590,8 @@ static void analyse_irp_globals_address_taken(void) { assure_irg_outs(irg); irg_walk_graph(irg, NULL, check_global_address, get_irg_tls(irg)); } - print_address_taken_state(get_glob_type()); - print_address_taken_state(get_tls_type()); + //print_address_taken_state(get_glob_type()); + //print_address_taken_state(get_tls_type()); /* now computed */ irp->globals_adr_taken_state = ir_address_taken_computed; diff --git a/ir/ana/irmemory.h b/ir/ana/irmemory.h index 21e17f13d..794d7bace 100644 --- a/ir/ana/irmemory.h +++ b/ir/ana/irmemory.h @@ -7,7 +7,7 @@ * Created: 27.12.2006 * CVS-ID: $Id$ * Copyright: (c) 2006-2007 Universität Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * License: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. */ #ifndef _FIRM_MEMORY_H #define _FIRM_MEMORY_H @@ -29,8 +29,11 @@ typedef enum { /** Possible options for the memory disambiguator. */ typedef enum { - opt_non_opt = 0, /**< no options */ - opt_strong_typed = 1, /**< strong typed source language */ + aa_opt_no_opt = 0, /**< no options: most conservative */ + aa_opt_type_based = 1, /**< use type based alias analysis: strict typed source language */ + aa_opt_byte_type_may_alias = 2, /**< if type based analysis is enabled: bytes types may alias other types */ + aa_opt_no_alias = 4, /**< two addresses NEVER alias, use with CAUTION (gcc -fno-alias) */ + aa_opt_inherited = 128 /**< only for implementation: options from a graph are inherited from global */ } disambuigator_options; /** @@ -50,7 +53,6 @@ typedef ir_alias_relation (*DISAMBIGUATOR_FUNC)( * @param mode1 The mode of the first memory access. * @param adr2 The second address. * @param mode2 The mode of the second memory access. - * @param options Additional options. * * The memory disambiguator tries to determine the alias state between * two memory addresses. The following rules are used: @@ -73,8 +75,7 @@ typedef ir_alias_relation (*DISAMBIGUATOR_FUNC)( ir_alias_relation get_alias_relation( ir_graph *irg, ir_node *adr1, ir_mode *mode1, - ir_node *adr2, ir_mode *mode2, - unsigned options); + ir_node *adr2, ir_mode *mode2); /** * Set a source language specific memory disambiguator function. @@ -104,8 +105,7 @@ void mem_disambig_init(void); ir_alias_relation get_alias_relation_ex( ir_graph *irg, ir_node *adr1, ir_mode *mode1, - ir_node *adr2, ir_mode *mode2, - unsigned options); + ir_node *adr2, ir_mode *mode2); /** * Free the relation cache. @@ -119,11 +119,23 @@ ir_address_taken_computed_state get_irg_address_taken_state(const ir_graph *irg) /** * Sets the current address taken state of the graph. + * + * @param irg the graph + * @param state the new state */ void set_irg_address_taken_state(ir_graph *irg, ir_address_taken_computed_state state); /** * Assure that the address taken flag is computed for the given graph. + * + * This is an intraprocedural analysis that computes the address_taken state + * for all local variables. + * + * Note that this is a conservative estimation that by no Firm transformation + * can be invalidated, so it's only recomputed if manually triggered by calling + * set_irg_address_taken_state(irg, ir_address_taken_not_computed). + * Even then the information is not cleaned from the variables, call + * assure_irg_address_taken_computed() again for recomputation. */ void assure_irg_address_taken_computed(ir_graph *irg); @@ -134,12 +146,45 @@ ir_address_taken_computed_state get_irp_globals_address_taken_state(void); /** * Sets the current address taken state of the globals. + * + * @param state the new state */ void set_irp_globals_address_taken_state(ir_address_taken_computed_state state); /** - * Assure that the address taken flag is computed for the globals. + * Assure that the address taken flag is computed for the global and TLS entities (variables). + * + * This is an interprocedural analysis that computes the address_taken state + * for all global and TLS variables. + * + * Note that this is a conservative estimation that by no Firm transformation + * can be invalidated, so it's only recomputed if manually triggered by calling + * set_irp_globals_address_taken_state(ir_address_taken_not_computed). + * Even then the information is not cleaned from the variables, call + * assure_irp_globals_address_taken_computed() again for recomputation. */ void assure_irp_globals_address_taken_computed(void); +/** + * Get the memory disambiguator options for a graph. + * + * @param irg the graph + */ +unsigned get_irg_memory_disambiguator_options(ir_graph *irg); + +/** + * Set the memory disambiguator options for a graph. + * + * @param irg the graph + * @param option a set of options + */ +void set_irg_memory_disambiguator_options(ir_graph *irg, unsigned options); + +/** + * Set the global disambiguator options for all graphs not having local options. + * + * @param option a set of options + */ +void set_irp_memory_disambiguator_options(unsigned options); + #endif /* _FIRM_MEMORY_H */ -- 2.20.1