diff options
author | Roger Sayle <roger@eyesopen.com> | 2006-02-18 17:26:35 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-02-18 17:26:35 +0000 |
commit | 3891cee2305bb50ede9598793afbedc761f6bcd7 (patch) | |
tree | 845df317e73a9d6012862b3e3c03232be1cd595e /gcc | |
parent | 4ea42ebadb93edf5f33b751cf53fbfee8a595ff8 (diff) | |
download | gcc-3891cee2305bb50ede9598793afbedc761f6bcd7.zip gcc-3891cee2305bb50ede9598793afbedc761f6bcd7.tar.gz gcc-3891cee2305bb50ede9598793afbedc761f6bcd7.tar.bz2 |
trans-stmt.c (struct temporary_list): Delete.
* trans-stmt.c (struct temporary_list): Delete.
(gfc_trans_where_2): Major reorganization. Remove no longer needed
TEMP argument. Allocate and deallocate the control mask and
pending control mask locally.
(gfc_trans_forall_1): Delete TEMP local variable, and update
call to gfc_trans_where_2. No need to deallocate arrays after.
(gfc_evaluate_where_mask): Major reorganization. Change return
type to void. Pass in parent execution mask, MASK, and two
already allocated mask arrays CMASK and PMASK. On return
CMASK := MASK & COND, PMASK := MASK & !COND. MASK, CMASK and
CMASK may all be NULL, or refer to the same temporary arrays.
(gfc_trans_where): Update call to gfc_trans_where_2. We no
longer need a TEMP variable or to deallocate temporary arrays
allocated by gfc_trans_where_2.
From-SVN: r111245
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/fortran/trans-stmt.c | 295 |
2 files changed, 136 insertions, 176 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index ab086b0..83a9059 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,20 @@ +2006-02-18 Roger Sayle <roger@eyesopen.com> + + * trans-stmt.c (struct temporary_list): Delete. + (gfc_trans_where_2): Major reorganization. Remove no longer needed + TEMP argument. Allocate and deallocate the control mask and + pending control mask locally. + (gfc_trans_forall_1): Delete TEMP local variable, and update + call to gfc_trans_where_2. No need to deallocate arrays after. + (gfc_evaluate_where_mask): Major reorganization. Change return + type to void. Pass in parent execution mask, MASK, and two + already allocated mask arrays CMASK and PMASK. On return + CMASK := MASK & COND, PMASK := MASK & !COND. MASK, CMASK and + CMASK may all be NULL, or refer to the same temporary arrays. + (gfc_trans_where): Update call to gfc_trans_where_2. We no + longer need a TEMP variable or to deallocate temporary arrays + allocated by gfc_trans_where_2. + 2006-02-18 Danny Smith <dannysmith@users.sourceforeg.net> * gfortran.h (gfc_add_attribute): Change uint to unsigned int. diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 2f8d09b..32c750a 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -49,13 +49,6 @@ typedef struct iter_info } iter_info; -typedef struct temporary_list -{ - tree temporary; - struct temporary_list *next; -} -temporary_list; - typedef struct forall_info { iter_info *this_loop; @@ -69,8 +62,7 @@ typedef struct forall_info } forall_info; -static void gfc_trans_where_2 (gfc_code *, tree, forall_info *, - stmtblock_t *, temporary_list **temp); +static void gfc_trans_where_2 (gfc_code *, tree, forall_info *, stmtblock_t *); /* Translate a F95 label number to a LABEL_EXPR. */ @@ -2317,7 +2309,6 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) gfc_saved_var *saved_vars; iter_info *this_forall, *iter_tmp; forall_info *info, *forall_tmp; - temporary_list *temp; gfc_start_block (&block); @@ -2523,27 +2514,9 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) break; case EXEC_WHERE: - /* Translate WHERE or WHERE construct nested in FORALL. */ - temp = NULL; - gfc_trans_where_2 (c, NULL, nested_forall_info, &block, &temp); - - while (temp) - { - tree args; - temporary_list *p; - - /* Free the temporary. */ - args = gfc_chainon_list (NULL_TREE, temp->temporary); - tmp = build_function_call_expr (gfor_fndecl_internal_free, args); - gfc_add_expr_to_block (&block, tmp); - - p = temp; - temp = temp->next; - gfc_free (p); - } - - break; + gfc_trans_where_2 (c, NULL, nested_forall_info, &block); + break; /* Pointer assignment inside FORALL. */ case EXEC_POINTER_ASSIGN: @@ -2622,71 +2595,27 @@ tree gfc_trans_forall (gfc_code * code) needed by the WHERE mask expression multiplied by the iterator number of the nested forall. ME is the WHERE mask expression. - MASK is the temporary whose value is mask's value. - NMASK is another temporary whose value is !mask, or NULL if not required. - TEMP records the temporary's address allocated in this function in order - to free them outside this function. - MASK, NMASK and TEMP are all OUT arguments. */ + MASK is the current execution mask upon input. + CMASK is the updated execution mask on output, or NULL if not required. + PMASK is the pending execution mask on output, or NULL if not required. + BLOCK is the block in which to place the condition evaluation loops. */ -static tree +static void gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info, - tree * mask, tree * nmask, temporary_list ** temp, - stmtblock_t * block) + tree mask, tree cmask, tree pmask, + tree mask_type, stmtblock_t * block) { tree tmp, tmp1; gfc_ss *lss, *rss; gfc_loopinfo loop; - tree ptemp1, ntmp, ptemp2; - tree inner_size, size; - stmtblock_t body, body1, inner_size_body; + stmtblock_t body, body1; + tree count, cond, mtmp; gfc_se lse, rse; - tree mask_type; - tree count; - tree tmpexpr; gfc_init_loopinfo (&loop); - /* Calculate the size of temporary needed by the mask-expr. */ - gfc_init_block (&inner_size_body); - inner_size = compute_inner_temp_size (me, me, &inner_size_body, &lss, &rss); - - /* Calculate the total size of temporary needed. */ - size = compute_overall_iter_number (nested_forall_info, inner_size, - &inner_size_body, block); - - /* As the mask array can be very big, prefer compact boolean types. */ - mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind); - - /* Allocate temporary for where mask. */ - tmp = allocate_temp_for_forall_nest_1 (mask_type, size, block, &ptemp1); - - /* Record the temporary address in order to free it later. */ - if (ptemp1) - { - temporary_list *tempo; - tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list)); - tempo->temporary = ptemp1; - tempo->next = *temp; - *temp = tempo; - } - - if (nmask) - { - /* Allocate temporary for !mask. */ - ntmp = allocate_temp_for_forall_nest_1 (mask_type, size, block, &ptemp2); - - /* Record the temporary in order to free it later. */ - if (ptemp2) - { - temporary_list *tempo; - tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list)); - tempo->temporary = ptemp2; - tempo->next = *temp; - *temp = tempo; - } - } - else - ntmp = NULL_TREE; + lss = gfc_walk_expr (me); + rss = gfc_walk_expr (me); /* Variable to index the temporary. */ count = gfc_create_var (gfc_array_index_type, "count"); @@ -2723,22 +2652,46 @@ gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info, rse.ss = rss; gfc_conv_expr (&rse, me); } - /* Form the expression of the temporary. */ - lse.expr = gfc_build_array_ref (tmp, count); - /* Use the scalar assignment to fill temporary TMP. */ - tmp1 = gfc_trans_scalar_assign (&lse, &rse, me->ts.type); - gfc_add_expr_to_block (&body1, tmp1); + /* Variable to evalate mask condition. */ + cond = gfc_create_var (mask_type, "cond"); + if (mask && (cmask || pmask)) + mtmp = gfc_create_var (mask_type, "mask"); + else mtmp = NULL_TREE; + + gfc_add_block_to_block (&body1, &lse.pre); + gfc_add_block_to_block (&body1, &rse.pre); - if (nmask) + gfc_add_modify_expr (&body1, cond, fold_convert (mask_type, rse.expr)); + + if (mask && (cmask || pmask)) { - /* Fill temporary NTMP. */ - tmp1 = build1 (TRUTH_NOT_EXPR, TREE_TYPE (lse.expr), lse.expr); - tmpexpr = gfc_build_array_ref (ntmp, count); - gfc_add_modify_expr (&body1, tmpexpr, tmp1); + tmp = gfc_build_array_ref (mask, count); + gfc_add_modify_expr (&body1, mtmp, tmp); } - if (lss == gfc_ss_terminator) + if (cmask) + { + tmp1 = gfc_build_array_ref (cmask, count); + tmp = cond; + if (mask) + tmp = build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp); + gfc_add_modify_expr (&body1, tmp1, tmp); + } + + if (pmask) + { + tmp1 = gfc_build_array_ref (pmask, count); + tmp = build1 (TRUTH_NOT_EXPR, mask_type, cond); + if (mask) + tmp = build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp); + gfc_add_modify_expr (&body1, tmp1, tmp); + } + + gfc_add_block_to_block (&body1, &lse.post); + gfc_add_block_to_block (&body1, &rse.post); + + if (lss == gfc_ss_terminator) { gfc_add_block_to_block (&body, &body1); } @@ -2766,12 +2719,6 @@ gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info, tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1); gfc_add_expr_to_block (block, tmp1); - - *mask = tmp; - if (nmask) - *nmask = ntmp; - - return tmp1; } @@ -2999,80 +2946,76 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2, tree mask, /* Translate the WHERE construct or statement. This function can be called iteratively to translate the nested WHERE construct or statement. - MASK is the control mask. - TEMP records the temporary address which must be freed later. */ + MASK is the control mask. */ static void gfc_trans_where_2 (gfc_code * code, tree mask, - forall_info * nested_forall_info, stmtblock_t * block, - temporary_list ** temp) + forall_info * nested_forall_info, stmtblock_t * block) { + stmtblock_t inner_size_body; + tree inner_size, size; + gfc_ss *lss, *rss; + tree mask_type; gfc_expr *expr1; gfc_expr *expr2; gfc_code *cblock; gfc_code *cnext; - tree tmp, tmp1, tmp2; + tree tmp; tree count1, count2; - tree mask_copy; int need_temp; - tree *tmp1_ptr; - tree pmask; - - pmask = NULL_TREE; + tree pcmask = NULL_TREE; + tree ppmask = NULL_TREE; + tree cmask = NULL_TREE; + tree pmask = NULL_TREE; /* the WHERE statement or the WHERE construct statement. */ cblock = code->block; + + /* Calculate the size of temporary needed by the mask-expr. */ + gfc_init_block (&inner_size_body); + inner_size = compute_inner_temp_size (cblock->expr, cblock->expr, + &inner_size_body, &lss, &rss); + + /* Calculate the total size of temporary needed. */ + size = compute_overall_iter_number (nested_forall_info, inner_size, + &inner_size_body, block); + + /* As the mask array can be very big, prefer compact boolean types. */ + mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind); + + /* Allocate temporary for where mask. */ + cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block, &pcmask); + + if (cblock->block) + { + /* Allocate temporary for !mask. */ + pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block, + &ppmask); + } + else + { + ppmask = NULL_TREE; + pmask = NULL_TREE; + } + while (cblock) { /* Has mask-expr. */ if (cblock->expr) { /* If this is the last clause of the WHERE construct, then - we don't need to allocate/populate/deallocate a complementary - pending control mask (pmask). */ + we don't need to update the pending control mask (pmask). */ if (! cblock->block) - { - tmp1 = NULL_TREE; - tmp1_ptr = NULL; - } - else - tmp1_ptr = &tmp1; + pmask = NULL_TREE; /* Ensure that the WHERE mask be evaluated only once. */ - tmp2 = gfc_evaluate_where_mask (cblock->expr, nested_forall_info, - &tmp, tmp1_ptr, temp, block); - - /* Set the control mask and the pending control mask. */ - /* It's a where-stmt. */ - if (mask == NULL) - { - mask = tmp; - pmask = tmp1; - } - /* It's a nested where-stmt. */ - else if (mask && pmask == NULL) - { - tree tmp2; - /* Use the TREE_CHAIN to list the masks. */ - tmp2 = copy_list (mask); - pmask = chainon (mask, tmp1); - mask = chainon (tmp2, tmp); - } - /* It's a masked-elsewhere-stmt. */ - else if (mask && cblock->expr) - { - tree tmp2; - tmp2 = copy_list (pmask); + gfc_evaluate_where_mask (cblock->expr, nested_forall_info, + mask, cmask, pmask, mask_type, block); - mask = pmask; - tmp2 = chainon (tmp2, tmp); - pmask = chainon (mask, tmp1); - mask = tmp2; - } } /* It's a elsewhere-stmt. No mask-expr is present. */ else - mask = pmask; + cmask = mask; /* Get the assignment statement of a WHERE statement, or the first statement in where-body-construct of a WHERE construct. */ @@ -3089,7 +3032,7 @@ gfc_trans_where_2 (gfc_code * code, tree mask, { need_temp = gfc_check_dependency (expr1, expr2, 0); if (need_temp) - gfc_trans_assign_need_temp (expr1, expr2, mask, + gfc_trans_assign_need_temp (expr1, expr2, cmask, nested_forall_info, block); else { @@ -3099,8 +3042,8 @@ gfc_trans_where_2 (gfc_code * code, tree mask, gfc_add_modify_expr (block, count1, gfc_index_zero_node); gfc_add_modify_expr (block, count2, gfc_index_zero_node); - tmp = gfc_trans_where_assign (expr1, expr2, mask, count1, - count2); + tmp = gfc_trans_where_assign (expr1, expr2, cmask, + count1, count2); tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1); @@ -3115,8 +3058,8 @@ gfc_trans_where_2 (gfc_code * code, tree mask, gfc_add_modify_expr (block, count1, gfc_index_zero_node); gfc_add_modify_expr (block, count2, gfc_index_zero_node); - tmp = gfc_trans_where_assign (expr1, expr2, mask, count1, - count2); + tmp = gfc_trans_where_assign (expr1, expr2, cmask, + count1, count2); gfc_add_expr_to_block (block, tmp); } @@ -3124,11 +3067,9 @@ gfc_trans_where_2 (gfc_code * code, tree mask, /* WHERE or WHERE construct is part of a where-body-construct. */ case EXEC_WHERE: - /* Ensure that MASK is not modified by next gfc_trans_where_2. */ - mask_copy = copy_list (mask); - gfc_trans_where_2 (cnext, mask_copy, nested_forall_info, - block, temp); - break; + /* Ensure that MASK is not modified by next gfc_trans_where_2. */ + gfc_trans_where_2 (cnext, cmask, nested_forall_info, block); + break; default: gcc_unreachable (); @@ -3139,7 +3080,24 @@ gfc_trans_where_2 (gfc_code * code, tree mask, } /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */ cblock = cblock->block; + mask = pmask; } + + /* If we allocated a pending mask array, deallocate it now. */ + if (ppmask) + { + tree args = gfc_chainon_list (NULL_TREE, ppmask); + tmp = build_function_call_expr (gfor_fndecl_internal_free, args); + gfc_add_expr_to_block (block, tmp); + } + + /* If we allocated a current mask array, deallocate it now. */ + if (pcmask) + { + tree args = gfc_chainon_list (NULL_TREE, pcmask); + tmp = build_function_call_expr (gfor_fndecl_internal_free, args); + gfc_add_expr_to_block (block, tmp); + } } /* Translate a simple WHERE construct or statement without dependencies. @@ -3282,11 +3240,8 @@ tree gfc_trans_where (gfc_code * code) { stmtblock_t block; - temporary_list *temp, *p; gfc_code *cblock; gfc_code *eblock; - tree args; - tree tmp; cblock = code->block; if (cblock->next @@ -3333,21 +3288,9 @@ gfc_trans_where (gfc_code * code) } gfc_start_block (&block); - temp = NULL; - - gfc_trans_where_2 (code, NULL, NULL, &block, &temp); - /* Add calls to free temporaries which were dynamically allocated. */ - while (temp) - { - args = gfc_chainon_list (NULL_TREE, temp->temporary); - tmp = build_function_call_expr (gfor_fndecl_internal_free, args); - gfc_add_expr_to_block (&block, tmp); + gfc_trans_where_2 (code, NULL, NULL, &block); - p = temp; - temp = temp->next; - gfc_free (p); - } return gfc_finish_block (&block); } |