📄 trans-array.c
字号:
gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag, stmtblock_t * pblock){ tree index; tree stride; gfc_ss_info *info; gfc_ss *ss; gfc_se se; int i; /* This code will be executed before entering the scalarization loop for this dimension. */ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) { if ((ss->useflags & flag) == 0) continue; if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR && ss->type != GFC_SS_COMPONENT) continue; info = &ss->data.info; if (dim >= info->dimen) continue; if (dim == info->dimen - 1) { /* For the outermost loop calculate the offset due to any elemental dimensions. It will have been initialized with the base offset of the array. */ if (info->ref) { for (i = 0; i < info->ref->u.ar.dimen; i++) { if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT) continue; gfc_init_se (&se, NULL); se.loop = loop; se.expr = info->descriptor; stride = gfc_conv_array_stride (info->descriptor, i); index = gfc_conv_array_index_offset (&se, info, i, -1, &info->ref->u.ar, stride); gfc_add_block_to_block (pblock, &se.pre); info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type, info->offset, index); info->offset = gfc_evaluate_now (info->offset, pblock); } i = loop->order[0]; stride = gfc_conv_array_stride (info->descriptor, info->dim[i]); } else stride = gfc_conv_array_stride (info->descriptor, 0); /* Calculate the stride of the innermost loop. Hopefully this will allow the backend optimizers to do their stuff more effectively. */ info->stride0 = gfc_evaluate_now (stride, pblock); } else { /* Add the offset for the previous loop dimension. */ gfc_array_ref *ar; if (info->ref) { ar = &info->ref->u.ar; i = loop->order[dim + 1]; } else { ar = NULL; i = dim + 1; } gfc_init_se (&se, NULL); se.loop = loop; se.expr = info->descriptor; stride = gfc_conv_array_stride (info->descriptor, info->dim[i]); index = gfc_conv_array_index_offset (&se, info, info->dim[i], i, ar, stride); gfc_add_block_to_block (pblock, &se.pre); info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type, info->offset, index); info->offset = gfc_evaluate_now (info->offset, pblock); } /* Remember this offset for the second loop. */ if (dim == loop->temp_dim - 1) info->saved_offset = info->offset; }}/* Start a scalarized expression. Creates a scope and declares loop variables. */voidgfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody){ int dim; int n; int flags; gcc_assert (!loop->array_parameter); for (dim = loop->dimen - 1; dim >= 0; dim--) { n = loop->order[dim]; gfc_start_block (&loop->code[n]); /* Create the loop variable. */ loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S"); if (dim < loop->temp_dim) flags = 3; else flags = 1; /* Calculate values that will be constant within this loop. */ gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]); } gfc_start_block (pbody);}/* Generates the actual loop code for a scalarization loop. */static voidgfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n, stmtblock_t * pbody){ stmtblock_t block; tree cond; tree tmp; tree loopbody; tree exit_label; loopbody = gfc_finish_block (pbody); /* Initialize the loopvar. */ gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]); exit_label = gfc_build_label_decl (NULL_TREE); /* Generate the loop body. */ gfc_init_block (&block); /* The exit condition. */ cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]); tmp = build1_v (GOTO_EXPR, exit_label); TREE_USED (exit_label) = 1; tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (&block, tmp); /* The main body. */ gfc_add_expr_to_block (&block, loopbody); /* Increment the loopvar. */ tmp = build2 (PLUS_EXPR, gfc_array_index_type, loop->loopvar[n], gfc_index_one_node); gfc_add_modify_expr (&block, loop->loopvar[n], tmp); /* Build the loop. */ tmp = gfc_finish_block (&block); tmp = build1_v (LOOP_EXPR, tmp); gfc_add_expr_to_block (&loop->code[n], tmp); /* Add the exit label. */ tmp = build1_v (LABEL_EXPR, exit_label); gfc_add_expr_to_block (&loop->code[n], tmp);}/* Finishes and generates the loops for a scalarized expression. */voidgfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body){ int dim; int n; gfc_ss *ss; stmtblock_t *pblock; tree tmp; pblock = body; /* Generate the loops. */ for (dim = 0; dim < loop->dimen; dim++) { n = loop->order[dim]; gfc_trans_scalarized_loop_end (loop, n, pblock); loop->loopvar[n] = NULL_TREE; pblock = &loop->code[n]; } tmp = gfc_finish_block (pblock); gfc_add_expr_to_block (&loop->pre, tmp); /* Clear all the used flags. */ for (ss = loop->ss; ss; ss = ss->loop_chain) ss->useflags = 0;}/* Finish the main body of a scalarized expression, and start the secondary copying body. */voidgfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body){ int dim; int n; stmtblock_t *pblock; gfc_ss *ss; pblock = body; /* We finish as many loops as are used by the temporary. */ for (dim = 0; dim < loop->temp_dim - 1; dim++) { n = loop->order[dim]; gfc_trans_scalarized_loop_end (loop, n, pblock); loop->loopvar[n] = NULL_TREE; pblock = &loop->code[n]; } /* We don't want to finish the outermost loop entirely. */ n = loop->order[loop->temp_dim - 1]; gfc_trans_scalarized_loop_end (loop, n, pblock); /* Restore the initial offsets. */ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) { if ((ss->useflags & 2) == 0) continue; if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR && ss->type != GFC_SS_COMPONENT) continue; ss->data.info.offset = ss->data.info.saved_offset; } /* Restart all the inner loops we just finished. */ for (dim = loop->temp_dim - 2; dim >= 0; dim--) { n = loop->order[dim]; gfc_start_block (&loop->code[n]); loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q"); gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]); } /* Start a block for the secondary copying code. */ gfc_start_block (body);}/* Calculate the upper bound of an array section. */static treegfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock){ int dim; gfc_expr *end; tree desc; tree bound; gfc_se se; gfc_ss_info *info; gcc_assert (ss->type == GFC_SS_SECTION); info = &ss->data.info; dim = info->dim[n]; if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR) /* We'll calculate the upper bound once we have access to the vector's descriptor. */ return NULL; gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE); desc = info->descriptor; end = info->ref->u.ar.end[dim]; if (end) { /* The upper bound was specified. */ gfc_init_se (&se, NULL); gfc_conv_expr_type (&se, end, gfc_array_index_type); gfc_add_block_to_block (pblock, &se.pre); bound = se.expr; } else { /* No upper bound was specified, so use the bound of the array. */ bound = gfc_conv_array_ubound (desc, dim); } return bound;}/* Calculate the lower bound of an array section. */static voidgfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n){ gfc_expr *start; gfc_expr *stride; tree desc; gfc_se se; gfc_ss_info *info; int dim; gcc_assert (ss->type == GFC_SS_SECTION); info = &ss->data.info; dim = info->dim[n]; if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR) { /* We use a zero-based index to access the vector. */ info->start[n] = gfc_index_zero_node; info->stride[n] = gfc_index_one_node; return; } gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE); desc = info->descriptor; start = info->ref->u.ar.start[dim]; stride = info->ref->u.ar.stride[dim]; /* Calculate the start of the range. For vector subscripts this will be the range of the vector. */ if (start) { /* Specified section start. */ gfc_init_se (&se, NULL); gfc_conv_expr_type (&se, start, gfc_array_index_type); gfc_add_block_to_block (&loop->pre, &se.pre); info->start[n] = se.expr; } else { /* No lower bound specified so use the bound of the array. */ info->start[n] = gfc_conv_array_lbound (desc, dim); } info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre); /* Calculate the stride. */ if (stride == NULL) info->stride[n] = gfc_index_one_node; else { gfc_init_se (&se, NULL); gfc_conv_expr_type (&se, stride, gfc_array_index_type); gfc_add_block_to_block (&loop->pre, &se.pre); info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre); }}/* Calculates the range start and stride for a SS chain. Also gets the descriptor and data pointer. The range of vector subscripts is the size of the vector. Array bounds are also checked. */voidgfc_conv_ss_startstride (gfc_loopinfo * loop){ int n; tree tmp; gfc_ss *ss; tree desc; loop->dimen = 0; /* Determine the rank of the loop. */ for (ss = loop->ss; ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain) { switch (ss->type) { case GFC_SS_SECTION: case GFC_SS_CONSTRUCTOR: case GFC_SS_FUNCTION: case GFC_SS_COMPONENT: loop->dimen = ss->data.info.dimen; break; default: break; } } if (loop->dimen == 0) gfc_todo_error ("Unable to determine rank of expression"); /* Loop over all the SS in the chain. */ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) { if (ss->expr && ss->expr->shape && !ss->shape) ss->shape = ss->expr->shape; switch (ss->type) { case GFC_SS_SECTION: /* Get the descriptor for the array. */ gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter); for (n = 0; n < ss->data.info.dimen; n++) gfc_conv_section_startstride (loop, ss, n); break; case GFC_SS_CONSTRUCTOR: case GFC_SS_FUNCTION: for (n = 0; n < ss->data.info.dimen; n++) { ss->data.info.start[n] = gfc_index_zero_node; ss->data.info.stride[n] = gfc_index_one_node; } break; default: break; } } /* The rest is just runtime bound checking. */ if (flag_bounds_check) { stmtblock_t block; tree fault; tree bound; tree end; tree size[GFC_MAX_DIMENSIONS]; gfc_ss_info *info; int dim; gfc_start_block (&block); fault = integer_zero_node; for (n = 0; n < loop->dimen; n++) size[n] = NULL_TREE; for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain) { if (ss->type != GFC_SS_SECTION) continue; /* TODO: range checking for mapped dimensions. */ info = &ss->data.info; /* This code only checks ranges. Elemental and vector dimensions are checked later. */ for (n = 0; n < loop->dimen; n++) { dim = info->dim[n]; if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE) continue; desc = ss->data.info.descriptor; /* Check lower bound. */ bound = gfc_conv_array_lbound (desc, dim); tmp = info->start[n]; tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp, bound);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -