Message ID | CY1PR1201MB10980D2DAAC082241FDE10788F1F0@CY1PR1201MB1098.namprd12.prod.outlook.com |
---|---|
State | New |
Headers | show |
On Sun, Nov 15, 2015 at 12:14 PM, Kumar, Venkataramanan <Venkataramanan.Kumar@amd.com> wrote: > Hi Richard and Bernhard. > >> -----Original Message----- >> From: Richard Biener [mailto:richard.guenther@gmail.com] >> Sent: Tuesday, November 10, 2015 5:33 PM >> To: Kumar, Venkataramanan >> Cc: Andrew Pinski; gcc-patches@gcc.gnu.org >> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c trap >> assumptions. >> >> On Sat, Nov 7, 2015 at 12:41 PM, Kumar, Venkataramanan >> <Venkataramanan.Kumar@amd.com> wrote: >> > Hi Richard, >> > >> > I have now implemented storing of DR and references using hash maps. >> > Please find attached patch. >> > >> > As discussed, I am now storing the ref, DR and baseref, DR pairs along with >> unconditional read/write information in hash tables while iterating over DR >> during its initialization. >> > Then during checking for possible traps for if-converting, just check if the >> memory reference for a gimple statement is read/written unconditionally by >> querying the hash table instead of quadratic walk. >> > >> > Boot strapped and regression tested on x86_64. >> >> @@ -592,137 +598,153 @@ struct ifc_dr { >> >> /* -1 when not initialized, 0 when false, 1 when true. */ >> int rw_unconditionally; >> + >> + tree ored_result; >> + >> >> excess vertical space at the end. A better name would be simply "predicate". >> >> + if (!exsist1) >> + { >> + if (is_true_predicate (ca)) >> + { >> + DR_RW_UNCONDITIONALLY (a) = 1; >> + } >> >> - while (TREE_CODE (ref_base_a) == COMPONENT_REF >> - || TREE_CODE (ref_base_a) == IMAGPART_EXPR >> - || TREE_CODE (ref_base_a) == REALPART_EXPR) >> - ref_base_a = TREE_OPERAND (ref_base_a, 0); >> + IFC_DR (a)->ored_result = ca; >> + *master_dr = a; >> + } >> + else >> + { >> + IFC_DR (*master_dr)->ored_result >> + = fold_or_predicates >> + (EXPR_LOCATION (IFC_DR (*master_dr)->ored_result), >> + ca, IFC_DR (*master_dr)->ored_result); >> >> - while (TREE_CODE (ref_base_b) == COMPONENT_REF >> - || TREE_CODE (ref_base_b) == IMAGPART_EXPR >> - || TREE_CODE (ref_base_b) == REALPART_EXPR) >> - ref_base_b = TREE_OPERAND (ref_base_b, 0); >> + if (is_true_predicate (ca) >> + || is_true_predicate (IFC_DR (*master_dr)->ored_result)) >> + { >> + DR_RW_UNCONDITIONALLY (*master_dr) = 1; >> + } >> + } >> >> please common the predicate handling from both cases, that is, do >> >> if (is_true_predicate (IFC_DR (*master_dr)->ored_result)) >> DR_RW_... >> >> after the if. Note no {}s around single stmts. >> >> Likewise for the base_master_dr code. >> >> + if (!found) >> + { >> + DR_WRITTEN_AT_LEAST_ONCE (a) =0; >> + DR_RW_UNCONDITIONALLY (a) = 0; >> + return false; >> >> no need to update the flags on non-"master" DRs. >> >> Please remove the 'found' variable and simply return 'true' >> whenever found. >> >> static bool >> ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs) { >> - return write_memrefs_written_at_least_once (stmt, refs) >> - && memrefs_read_or_written_unconditionally (stmt, refs); >> + return memrefs_read_or_written_unconditionally (stmt, refs); >> >> please simply inline memrefs_read_or_written_unconditionally here. >> >> + if (ref_DR_map) >> + delete ref_DR_map; >> + ref_DR_map = NULL; >> + >> + if (baseref_DR_map) >> + delete baseref_DR_map; >> + baseref_DR_map = NULL; >> >> at this point the pointers will never be NULL. >> >> Ok with those changes. > > The attached patch addresses all the review comments and is rebased to current trunk. > GCC regression test and bootstrap passed. > > Wanted to check with you once before committing it to trunk. > Ok for trunk? > > gcc/ChangeLog > > 2015-11-15 Venkataramanan <Venkataramanan.Kumar@amd.com> > * tree-if-conv.c (ref_DR_map): Define. > (baseref_DR_map): Like wise > (struct ifc_dr): Add new tree predicate field. > (hash_memrefs_baserefs_and_store_DRs_read_written_info): New function. > (memrefs_read_or_written_unconditionally): Use hash maps to query > unconditional read/written information. > (write_memrefs_written_at_least_once): Remove. > (ifcvt_memrefs_wont_trap): Remove call to > write_memrefs_written_at_least_once. > (if_convertible_loop_p_1): Initialize hash maps and predicates > before hashing data references. > * tree-data-ref.h (decl_binds_to_current_def_p): Declare . It's already declared in varasm.h which you need to include. You are correct in that we don't handle multiple data references in a single stmt in ifcvt_memrefs_wont_trap but that's a situation that cannot not happen. So it would be nice to make this clearer by changing the function to not loop over all DRs but instead just do data_reference_p a = drs[gimple_uid (stmt) - 1]; gcc_assert (DR_STMT (a) == stmt); instead of the for() loop. Ok with that change. Thanks, Richard. > > gcc/testsuite/ChangeLog > 2015-11-15 Venkataramanan <Venkataramanan.Kumar@amd.com> > * gcc.dg/tree-ssa/ifc-8.c: Add new. > > > Regards, > Venkat. > >> >> Note the tree-hash-traits.h part is already committed. >> >> >> > gcc/ChangeLog >> > 2015-11-07 Venkataramanan <Venkataramanan.Kumar@amd.com> >> > >> > *tree-hash-traits.h (struct tree_operand_hash). Use compare_type >> and value_type. >> > (equal_keys): Rename to equal and use compare_type and >> value_type. >> > * tree-if-conv.c (ref_DR_map): Define. >> > (baseref_DR_map): Like wise >> > (struct ifc_dr): New tree predicate field. >> > (hash_memrefs_baserefs_and_store_DRs_read_written_info): New >> function. >> > (memrefs_read_or_written_unconditionally): Use hashmap to query >> unconditional read/written information. >> > (write_memrefs_written_at_least_once) : Remove. >> > (ifcvt_memrefs_wont_trap): Remove call to >> write_memrefs_written_at_least_once. >> > (if_convertible_loop_p_1): Initialize/delete hash maps an initialize >> predicates >> > before the call to >> hash_memrefs_baserefs_and_store_DRs_read_written_info. >> >> Watch changelog formatting. >> >> Thanks, >> Richard. >> >> > gcc/testsuite/ChangeLog >> > 2015-11-07 Venkataramanan <Venkataramanan.Kumar@amd.com> >> > *gcc.dg/tree-ssa/ifc-8.c: Add new. >> > >> > Ok for trunk? >> > >> > Regards, >> > Venkat. >> >> >> >> >> > + } >> >> >> > + } >> >> >> > + } >> >> >> > + return found; >> >> >> > +} >> >> >> > + >> >> >> > /* Return true when the memory references of STMT won't trap in >> the >> >> >> > if-converted code. There are two things that we have to check for: >> >> >> > >> >> >> > @@ -748,8 +776,20 @@ write_memrefs_written_at_least_once >> >> (gimple >> >> >> > *stmt, static bool ifcvt_memrefs_wont_trap (gimple *stmt, >> >> >> > vec<data_reference_p> refs) { >> >> >> > - return write_memrefs_written_at_least_once (stmt, refs) >> >> >> > - && memrefs_read_or_written_unconditionally (stmt, refs); >> >> >> > + bool memrefs_written_once, >> >> memrefs_read_written_unconditionally; >> >> >> > + bool memrefs_safe_to_access; >> >> >> > + >> >> >> > + memrefs_written_once >> >> >> > + = write_memrefs_written_at_least_once (stmt, >> >> >> > + refs); >> >> >> > + >> >> >> > + memrefs_read_written_unconditionally >> >> >> > + = memrefs_read_or_written_unconditionally (stmt, >> >> >> > + refs); >> >> >> > + >> >> >> > + memrefs_safe_to_access >> >> >> > + = write_memrefs_safe_to_access_unconditionally >> >> >> > + (stmt, refs); >> >> >> > + >> >> >> > + return ((memrefs_written_once || memrefs_safe_to_access) >> >> >> > + && memrefs_read_written_unconditionally); >> >> >> > } >> >> >> > >> >> >> > /* Wrapper around gimple_could_trap_p refined for the needs of >> >> >> > the >> >> >> > >> >> >> > >> >> >> > do I need this function write_memrefs_written_at_least_once >> >> anymore? >> >> >> > Please suggest if there a better way to do this. >> >> >> > >> >> >> > Bootstrapped and regression tested on x86_64. >> >> >> > I am not adding change log and comments now, as I wanted to >> >> >> > check >> >> >> approach first. >> >> >> > >> >> >> > Regards, >> >> >> > Venkat. >> >> >> > >> >> >> > >> >
Hi Richard, > -----Original Message----- > From: Richard Biener [mailto:richard.guenther@gmail.com] > Sent: Monday, November 16, 2015 3:28 PM > To: Kumar, Venkataramanan > Cc: Bernhard Reutner-Fischer; Andrew Pinski; gcc-patches@gcc.gnu.org > Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c trap > assumptions. > > On Sun, Nov 15, 2015 at 12:14 PM, Kumar, Venkataramanan > <Venkataramanan.Kumar@amd.com> wrote: > > Hi Richard and Bernhard. > > > >> -----Original Message----- > >> From: Richard Biener [mailto:richard.guenther@gmail.com] > >> Sent: Tuesday, November 10, 2015 5:33 PM > >> To: Kumar, Venkataramanan > >> Cc: Andrew Pinski; gcc-patches@gcc.gnu.org > >> Subject: Re: [RFC] [PATCH V2]: RE: [RFC] [Patch] Relax tree-if-conv.c > >> trap assumptions. > >> > >> On Sat, Nov 7, 2015 at 12:41 PM, Kumar, Venkataramanan > >> <Venkataramanan.Kumar@amd.com> wrote: > >> > Hi Richard, > >> > > >> > I have now implemented storing of DR and references using hash maps. > >> > Please find attached patch. > >> > > >> > As discussed, I am now storing the ref, DR and baseref, DR pairs > >> > along with > >> unconditional read/write information in hash tables while iterating > >> over DR during its initialization. > >> > Then during checking for possible traps for if-converting, just > >> > check if the > >> memory reference for a gimple statement is read/written > >> unconditionally by querying the hash table instead of quadratic walk. > >> > > >> > Boot strapped and regression tested on x86_64. > >> > >> @@ -592,137 +598,153 @@ struct ifc_dr { > >> > >> /* -1 when not initialized, 0 when false, 1 when true. */ > >> int rw_unconditionally; > >> + > >> + tree ored_result; > >> + > >> > >> excess vertical space at the end. A better name would be simply > "predicate". > >> > >> + if (!exsist1) > >> + { > >> + if (is_true_predicate (ca)) > >> + { > >> + DR_RW_UNCONDITIONALLY (a) = 1; > >> + } > >> > >> - while (TREE_CODE (ref_base_a) == COMPONENT_REF > >> - || TREE_CODE (ref_base_a) == IMAGPART_EXPR > >> - || TREE_CODE (ref_base_a) == REALPART_EXPR) > >> - ref_base_a = TREE_OPERAND (ref_base_a, 0); > >> + IFC_DR (a)->ored_result = ca; > >> + *master_dr = a; > >> + } > >> + else > >> + { > >> + IFC_DR (*master_dr)->ored_result > >> + = fold_or_predicates > >> + (EXPR_LOCATION (IFC_DR (*master_dr)->ored_result), > >> + ca, IFC_DR (*master_dr)->ored_result); > >> > >> - while (TREE_CODE (ref_base_b) == COMPONENT_REF > >> - || TREE_CODE (ref_base_b) == IMAGPART_EXPR > >> - || TREE_CODE (ref_base_b) == REALPART_EXPR) > >> - ref_base_b = TREE_OPERAND (ref_base_b, 0); > >> + if (is_true_predicate (ca) > >> + || is_true_predicate (IFC_DR (*master_dr)->ored_result)) > >> + { > >> + DR_RW_UNCONDITIONALLY (*master_dr) = 1; > >> + } > >> + } > >> > >> please common the predicate handling from both cases, that is, do > >> > >> if (is_true_predicate (IFC_DR (*master_dr)->ored_result)) > >> DR_RW_... > >> > >> after the if. Note no {}s around single stmts. > >> > >> Likewise for the base_master_dr code. > >> > >> + if (!found) > >> + { > >> + DR_WRITTEN_AT_LEAST_ONCE (a) =0; > >> + DR_RW_UNCONDITIONALLY (a) = 0; > >> + return false; > >> > >> no need to update the flags on non-"master" DRs. > >> > >> Please remove the 'found' variable and simply return 'true' > >> whenever found. > >> > >> static bool > >> ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs) > >> { > >> - return write_memrefs_written_at_least_once (stmt, refs) > >> - && memrefs_read_or_written_unconditionally (stmt, refs); > >> + return memrefs_read_or_written_unconditionally (stmt, refs); > >> > >> please simply inline memrefs_read_or_written_unconditionally here. > >> > >> + if (ref_DR_map) > >> + delete ref_DR_map; > >> + ref_DR_map = NULL; > >> + > >> + if (baseref_DR_map) > >> + delete baseref_DR_map; > >> + baseref_DR_map = NULL; > >> > >> at this point the pointers will never be NULL. > >> > >> Ok with those changes. > > > > The attached patch addresses all the review comments and is rebased to > current trunk. > > GCC regression test and bootstrap passed. > > > > Wanted to check with you once before committing it to trunk. > > Ok for trunk? > > > > gcc/ChangeLog > > > > 2015-11-15 Venkataramanan <Venkataramanan.Kumar@amd.com> > > * tree-if-conv.c (ref_DR_map): Define. > > (baseref_DR_map): Like wise > > (struct ifc_dr): Add new tree predicate field. > > (hash_memrefs_baserefs_and_store_DRs_read_written_info): New > function. > > (memrefs_read_or_written_unconditionally): Use hash maps to query > > unconditional read/written information. > > (write_memrefs_written_at_least_once): Remove. > > (ifcvt_memrefs_wont_trap): Remove call to > > write_memrefs_written_at_least_once. > > (if_convertible_loop_p_1): Initialize hash maps and predicates > > before hashing data references. > > * tree-data-ref.h (decl_binds_to_current_def_p): Declare . > > It's already declared in varasm.h which you need to include. > > You are correct in that we don't handle multiple data references in a single > stmt in ifcvt_memrefs_wont_trap but that's a situation that cannot not > happen. > > So it would be nice to make this clearer by changing the function to not loop > over all DRs but instead just do > > data_reference_p a = drs[gimple_uid (stmt) - 1]; > gcc_assert (DR_STMT (a) == stmt); > > instead of the for() loop. > > Ok with that change. Up streamed the changes after Boot strap and regression testing on X86_64 target. Ref: https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=230454 Regards, Venkat. > > Thanks, > Richard. > > > > > gcc/testsuite/ChangeLog > > 2015-11-15 Venkataramanan <Venkataramanan.Kumar@amd.com> > > * gcc.dg/tree-ssa/ifc-8.c: Add new. > > > > > > Regards, > > Venkat. > > > >> > >> Note the tree-hash-traits.h part is already committed. > >> > >> > >> > gcc/ChangeLog > >> > 2015-11-07 Venkataramanan <Venkataramanan.Kumar@amd.com> > >> > > >> > *tree-hash-traits.h (struct tree_operand_hash). Use > >> > compare_type > >> and value_type. > >> > (equal_keys): Rename to equal and use compare_type and > >> value_type. > >> > * tree-if-conv.c (ref_DR_map): Define. > >> > (baseref_DR_map): Like wise > >> > (struct ifc_dr): New tree predicate field. > >> > (hash_memrefs_baserefs_and_store_DRs_read_written_info): > >> > New > >> function. > >> > (memrefs_read_or_written_unconditionally): Use hashmap > >> > to query > >> unconditional read/written information. > >> > (write_memrefs_written_at_least_once) : Remove. > >> > (ifcvt_memrefs_wont_trap): Remove call to > >> write_memrefs_written_at_least_once. > >> > (if_convertible_loop_p_1): Initialize/delete hash maps > >> > an initialize > >> predicates > >> > before the call to > >> hash_memrefs_baserefs_and_store_DRs_read_written_info. > >> > >> Watch changelog formatting. > >> > >> Thanks, > >> Richard. > >> > >> > gcc/testsuite/ChangeLog > >> > 2015-11-07 Venkataramanan <Venkataramanan.Kumar@amd.com> > >> > *gcc.dg/tree-ssa/ifc-8.c: Add new. > >> > > >> > Ok for trunk? > >> > > >> > Regards, > >> > Venkat. > >> >> > >> >> >> > + } > >> >> >> > + } > >> >> >> > + } > >> >> >> > + return found; > >> >> >> > +} > >> >> >> > + > >> >> >> > /* Return true when the memory references of STMT won't trap > >> >> >> > in > >> the > >> >> >> > if-converted code. There are two things that we have to check > for: > >> >> >> > > >> >> >> > @@ -748,8 +776,20 @@ write_memrefs_written_at_least_once > >> >> (gimple > >> >> >> > *stmt, static bool ifcvt_memrefs_wont_trap (gimple *stmt, > >> >> >> > vec<data_reference_p> refs) { > >> >> >> > - return write_memrefs_written_at_least_once (stmt, refs) > >> >> >> > - && memrefs_read_or_written_unconditionally (stmt, refs); > >> >> >> > + bool memrefs_written_once, > >> >> memrefs_read_written_unconditionally; > >> >> >> > + bool memrefs_safe_to_access; > >> >> >> > + > >> >> >> > + memrefs_written_once > >> >> >> > + = write_memrefs_written_at_least_once (stmt, > >> >> >> > + refs); > >> >> >> > + > >> >> >> > + memrefs_read_written_unconditionally > >> >> >> > + = memrefs_read_or_written_unconditionally > >> >> >> > + (stmt, refs); > >> >> >> > + > >> >> >> > + memrefs_safe_to_access > >> >> >> > + = write_memrefs_safe_to_access_unconditionally > >> >> >> > + (stmt, refs); > >> >> >> > + > >> >> >> > + return ((memrefs_written_once || memrefs_safe_to_access) > >> >> >> > + && memrefs_read_written_unconditionally); > >> >> >> > } > >> >> >> > > >> >> >> > /* Wrapper around gimple_could_trap_p refined for the needs > >> >> >> > of the > >> >> >> > > >> >> >> > > >> >> >> > do I need this function write_memrefs_written_at_least_once > >> >> anymore? > >> >> >> > Please suggest if there a better way to do this. > >> >> >> > > >> >> >> > Bootstrapped and regression tested on x86_64. > >> >> >> > I am not adding change log and comments now, as I wanted to > >> >> >> > check > >> >> >> approach first. > >> >> >> > > >> >> >> > Regards, > >> >> >> > Venkat. > >> >> >> > > >> >> >> > > >> >
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c new file mode 100644 index 0000000..89a3410 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-8.c @@ -0,0 +1,17 @@ + +/* { dg-do compile } */ +/* { dg-options "-Ofast -fdump-tree-ifcvt-details -fno-common -ftree-loop-if-convert-stores" } */ + +#define LEN 4096 + __attribute__((aligned (32))) float array[LEN]; + +void test () +{ + for (int i = 0; i < LEN; i++) + { + if (array[i] > (float)0.) + array[i] = 3; + } +} + +/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */ diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index 4c9e357..d32dce8 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -340,6 +340,7 @@ extern bool dr_may_alias_p (const struct data_reference *, const struct data_reference *, bool); extern bool dr_equal_offsets_p (struct data_reference *, struct data_reference *); +extern bool decl_binds_to_current_def_p (const_tree); /* Return true when the base objects of data references A and B are the same memory object. */ diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 88b6405..8f4be60 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -117,6 +117,12 @@ static basic_block *ifc_bbs; /* Apply more aggressive (extended) if-conversion if true. */ static bool aggressive_if_conv; +/* Hash table to store references, DR pairs. */ +static hash_map<tree_operand_hash, data_reference_p> *ref_DR_map; + +/* Hash table to store base reference, DR pairs. */ +static hash_map<tree_operand_hash, data_reference_p> *baseref_DR_map; + /* Structure used to predicate basic blocks. This is attached to the ->aux field of the BBs in the loop to be if-converted. */ struct bb_predicate { @@ -580,139 +586,71 @@ struct ifc_dr { /* -1 when not initialized, 0 when false, 1 when true. */ int rw_unconditionally; + + tree predicate; }; #define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux) #define DR_WRITTEN_AT_LEAST_ONCE(DR) (IFC_DR (DR)->written_at_least_once) #define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally) -/* Returns true when the memory references of STMT are read or written - unconditionally. In other words, this function returns true when - for every data reference A in STMT there exist other accesses to - a data reference with the same base with predicates that add up (OR-up) to - the true predicate: this ensures that the data reference A is touched - (read or written) on every iteration of the if-converted loop. */ - -static bool -memrefs_read_or_written_unconditionally (gimple *stmt, - vec<data_reference_p> drs) -{ - int i, j; - data_reference_p a, b; - tree ca = bb_predicate (gimple_bb (stmt)); - - for (i = 0; drs.iterate (i, &a); i++) - if (DR_STMT (a) == stmt) - { - bool found = false; - int x = DR_RW_UNCONDITIONALLY (a); - - if (x == 0) - return false; - - if (x == 1) - continue; - - for (j = 0; drs.iterate (j, &b); j++) - { - tree ref_base_a = DR_REF (a); - tree ref_base_b = DR_REF (b); - - if (DR_STMT (b) == stmt) - continue; - - while (TREE_CODE (ref_base_a) == COMPONENT_REF - || TREE_CODE (ref_base_a) == IMAGPART_EXPR - || TREE_CODE (ref_base_a) == REALPART_EXPR) - ref_base_a = TREE_OPERAND (ref_base_a, 0); - - while (TREE_CODE (ref_base_b) == COMPONENT_REF - || TREE_CODE (ref_base_b) == IMAGPART_EXPR - || TREE_CODE (ref_base_b) == REALPART_EXPR) - ref_base_b = TREE_OPERAND (ref_base_b, 0); - - if (operand_equal_p (ref_base_a, ref_base_b, 0)) - { - tree cb = bb_predicate (gimple_bb (DR_STMT (b))); - - if (DR_RW_UNCONDITIONALLY (b) == 1 - || is_true_predicate (cb) - || is_true_predicate (ca - = fold_or_predicates (EXPR_LOCATION (cb), ca, cb))) - { - DR_RW_UNCONDITIONALLY (a) = 1; - DR_RW_UNCONDITIONALLY (b) = 1; - found = true; - break; - } - } - } - - if (!found) - { - DR_RW_UNCONDITIONALLY (a) = 0; - return false; - } - } - - return true; -} - -/* Returns true when the memory references of STMT are unconditionally - written. In other words, this function returns true when for every - data reference A written in STMT, there exist other writes to the - same data reference with predicates that add up (OR-up) to the true - predicate: this ensures that the data reference A is written on - every iteration of the if-converted loop. */ - -static bool -write_memrefs_written_at_least_once (gimple *stmt, - vec<data_reference_p> drs) +/* Iterates over DR's and stores refs, DR and base refs, DR pairs in + HASH tables. While storing them in HASH table, it checks if the + reference is unconditionally read or written and stores that as a flag + information. For base reference it checks if it is written atlest once + unconditionally and stores it as flag information along with DR. + In other words for every data reference A in STMT there exist other + accesses to a data reference with the same base with predicates that + add up (OR-up) to the true predicate: this ensures that the data + reference A is touched (read or written) on every iteration of the + if-converted loop. */ +static void +hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a) { - int i, j; - data_reference_p a, b; - tree ca = bb_predicate (gimple_bb (stmt)); - for (i = 0; drs.iterate (i, &a); i++) - if (DR_STMT (a) == stmt - && DR_IS_WRITE (a)) - { - bool found = false; - int x = DR_WRITTEN_AT_LEAST_ONCE (a); + data_reference_p *master_dr, *base_master_dr; + tree ref = DR_REF (a); + tree base_ref = DR_BASE_OBJECT (a); + tree ca = bb_predicate (gimple_bb (DR_STMT (a))); + bool exist1, exist2; - if (x == 0) - return false; + while (TREE_CODE (ref) == COMPONENT_REF + || TREE_CODE (ref) == IMAGPART_EXPR + || TREE_CODE (ref) == REALPART_EXPR) + ref = TREE_OPERAND (ref, 0); - if (x == 1) - continue; + master_dr = &ref_DR_map->get_or_insert (ref, &exist1); - for (j = 0; drs.iterate (j, &b); j++) - if (DR_STMT (b) != stmt - && DR_IS_WRITE (b) - && same_data_refs_base_objects (a, b)) - { - tree cb = bb_predicate (gimple_bb (DR_STMT (b))); + if (!exist1) + { + IFC_DR (a)->predicate = ca; + *master_dr = a; + } + else + IFC_DR (*master_dr)->predicate + = fold_or_predicates + (EXPR_LOCATION (IFC_DR (*master_dr)->predicate), + ca, IFC_DR (*master_dr)->predicate); - if (DR_WRITTEN_AT_LEAST_ONCE (b) == 1 - || is_true_predicate (cb) - || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb), - ca, cb))) - { - DR_WRITTEN_AT_LEAST_ONCE (a) = 1; - DR_WRITTEN_AT_LEAST_ONCE (b) = 1; - found = true; - break; - } - } + if (is_true_predicate (IFC_DR (*master_dr)->predicate)) + DR_RW_UNCONDITIONALLY (*master_dr) = 1; - if (!found) - { - DR_WRITTEN_AT_LEAST_ONCE (a) = 0; - return false; - } - } + base_master_dr = &baseref_DR_map->get_or_insert (base_ref,&exist2); - return true; + if (!exist2) + { + IFC_DR (a)->predicate = ca; + *base_master_dr = a; + } + else + IFC_DR (*base_master_dr)->predicate + = fold_or_predicates + (EXPR_LOCATION (IFC_DR (*base_master_dr)->predicate), + ca, IFC_DR (*base_master_dr)->predicate); + + if (DR_IS_WRITE (a) + && (is_true_predicate (IFC_DR (*base_master_dr)->predicate))) + DR_WRITTEN_AT_LEAST_ONCE (*base_master_dr) = 1; } /* Return true when the memory references of STMT won't trap in the @@ -731,13 +669,54 @@ write_memrefs_written_at_least_once (gimple *stmt, iteration. To check that the memory accesses are correctly formed and that we are allowed to read and write in these locations, we check that the memory accesses to be if-converted occur at every - iteration unconditionally. */ - + iteration unconditionally. + + Returns true for the memory reference in STMT, same memory reference + is read or written unconditionally atleast once and the base memory + reference is written unconditionally once. This is to check reference + will not write fault. Also retuns true if the memory reference is + unconditionally read once then we are conditionally writing to memory + which is defined as read and write and is bound to the definition + we are seeing. */ static bool -ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> refs) +ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs) { - return write_memrefs_written_at_least_once (stmt, refs) - && memrefs_read_or_written_unconditionally (stmt, refs); + int i; + data_reference_p a, *master_dr, *base_master_dr; + + for (i = gimple_uid (stmt) - 1; drs.iterate (i, &a); i++) + { + if (DR_STMT (a) != stmt) + break; + + tree ref_base_a = DR_REF (a); + tree base = DR_BASE_OBJECT (a); + + while (TREE_CODE (ref_base_a) == COMPONENT_REF + || TREE_CODE (ref_base_a) == IMAGPART_EXPR + || TREE_CODE (ref_base_a) == REALPART_EXPR) + ref_base_a = TREE_OPERAND (ref_base_a, 0); + + master_dr = ref_DR_map->get (ref_base_a); + base_master_dr = baseref_DR_map->get (base); + + gcc_assert (master_dr != NULL && base_master_dr != NULL); + + if (DR_RW_UNCONDITIONALLY (*master_dr) == 1) + { + if (DR_WRITTEN_AT_LEAST_ONCE (*base_master_dr) == 1) + return true; + else + { + tree base_tree = get_base_address (DR_REF (a)); + if (DECL_P (base_tree) + && decl_binds_to_current_def_p (base_tree) + && !TREE_READONLY (base_tree)) + return true; + } + } + } + return false; } /* Wrapper around gimple_could_trap_p refined for the needs of the @@ -1280,6 +1259,7 @@ if_convertible_loop_p_1 (struct loop *loop, case GIMPLE_CALL: case GIMPLE_DEBUG: case GIMPLE_COND: + gimple_set_uid (gsi_stmt (gsi), 0); break; default: return false; @@ -1288,13 +1268,20 @@ if_convertible_loop_p_1 (struct loop *loop, data_reference_p dr; + ref_DR_map = new hash_map<tree_operand_hash, data_reference_p>; + baseref_DR_map = new hash_map<tree_operand_hash, data_reference_p>; + + predicate_bbs (loop); + for (i = 0; refs->iterate (i, &dr); i++) { dr->aux = XNEW (struct ifc_dr); DR_WRITTEN_AT_LEAST_ONCE (dr) = -1; DR_RW_UNCONDITIONALLY (dr) = -1; + if (gimple_uid (DR_STMT (dr)) == 0) + gimple_set_uid (DR_STMT (dr), i + 1); + hash_memrefs_baserefs_and_store_DRs_read_written_info (dr); } - predicate_bbs (loop); for (i = 0; i < loop->num_nodes; i++) { @@ -1391,6 +1378,13 @@ if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store) free_data_refs (refs); free_dependence_relations (ddrs); + + delete ref_DR_map; + ref_DR_map = NULL; + + delete baseref_DR_map; + baseref_DR_map = NULL; + return res; }