static tree expand_return_expr (tree expr) { tree new_mod_list, new_var, new_mod, retval_expr; size_t rank = 0; location_t loc = EXPR_LOCATION (expr); if (TREE_CODE (expr) != RETURN_EXPR) return expr; if (!find_rank (loc, expr, expr, false, &rank)) return error_mark_node; /* If the return expression contains array notations, then flag it as error. */ if (rank >= 1) { error_at (loc, "array notation expression cannot be used as a return " "value"); return error_mark_node; } new_mod_list = push_stmt_list (); retval_expr = TREE_OPERAND (expr, 0); new_var = create_temporary_var (TREE_TYPE (retval_expr)); add_decl_expr (new_var); new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR, TREE_OPERAND (retval_expr, 1), tf_warning_or_error); TREE_OPERAND (retval_expr, 1) = new_var; TREE_OPERAND (expr, 0) = retval_expr; add_stmt (new_mod); add_stmt (expr); new_mod_list = pop_stmt_list (new_mod_list); return new_mod_list; }
tree c_finish_omp_master (location_t loc, tree stmt) { tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt)); SET_EXPR_LOCATION (t, loc); return t; }
tree c_finish_omp_ordered (location_t loc, tree stmt) { tree t = build1 (OMP_ORDERED, void_type_node, stmt); SET_EXPR_LOCATION (t, loc); return add_stmt (t); }
tree begin_eh_spec_block (void) { tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); return r; }
tree replace_invariant_exprs (tree *node) { size_t ix = 0; tree node_list = NULL_TREE; tree t = NULL_TREE, new_var = NULL_TREE, new_node; struct inv_list data; data.list_values = NULL; data.replacement = NULL; data.additional_tcodes = NULL; walk_tree (node, find_inv_trees, (void *)&data, NULL); if (vec_safe_length (data.list_values)) { node_list = push_stmt_list (); for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++) { new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE, TREE_TYPE (t)); gcc_assert (new_var != NULL_TREE && new_var != error_mark_node); new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t); add_stmt (new_node); vec_safe_push (data.replacement, new_var); } walk_tree (node, replace_inv_trees, (void *)&data, NULL); node_list = pop_stmt_list (node_list); } return node_list; }
tree add_stmt (tree t) { if (input_filename != last_expr_filename) { /* If the filename has changed, also add in a FILE_STMT. Do a string compare first, though, as it might be an equivalent string. */ int add = (strcmp (input_filename, last_expr_filename) != 0); last_expr_filename = input_filename; if (add) { tree pos = build_nt (FILE_STMT, get_identifier (input_filename)); add_stmt (pos); } } /* Add T to the statement-tree. */ TREE_CHAIN (last_tree) = t; last_tree = t; /* When we expand a statement-tree, we must know whether or not the statements are full-expressions. We record that fact here. */ STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p (); return t; }
tree add_scope_stmt (int begin_p, int partial_p) { tree *stack_ptr = current_scope_stmt_stack (); tree ss; tree top = *stack_ptr; /* Build the statement. */ ss = build_stmt (SCOPE_STMT, NULL_TREE); SCOPE_BEGIN_P (ss) = begin_p; SCOPE_PARTIAL_P (ss) = partial_p; /* Keep the scope stack up to date. */ if (begin_p) { top = tree_cons (ss, NULL_TREE, top); *stack_ptr = top; } else { if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top))) abort (); TREE_VALUE (top) = ss; *stack_ptr = TREE_CHAIN (top); } /* Add the new statement to the statement-tree. */ add_stmt (ss); return top; }
tree c_finish_oacc_wait (location_t loc, tree parms, tree clauses) { const int nparms = list_length (parms); tree stmt, t; vec<tree, va_gc> *args; vec_alloc (args, nparms + 2); stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT); if (find_omp_clause (clauses, OMP_CLAUSE_ASYNC)) t = OMP_CLAUSE_ASYNC_EXPR (clauses); else t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC); args->quick_push (t); args->quick_push (build_int_cst (integer_type_node, nparms)); for (t = parms; t; t = TREE_CHAIN (t)) { if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST) args->quick_push (build_int_cst (integer_type_node, TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t)))); else args->quick_push (OMP_CLAUSE_WAIT_EXPR (t)); } stmt = build_call_expr_loc_vec (loc, stmt, args); add_stmt (stmt); vec_free (args); return stmt; }
tree c_finish_omp_taskgroup (location_t loc, tree stmt) { tree t = add_stmt (build1 (OMP_TASKGROUP, void_type_node, stmt)); SET_EXPR_LOCATION (t, loc); return t; }
tree begin_eh_spec_block (void) { tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); EH_SPEC_STMTS (r) = push_stmt_list (); return r; }
void c_finish_omp_flush (void) { tree x; x = built_in_decls[BUILT_IN_SYNCHRONIZE]; x = build_function_call_expr (x, NULL); add_stmt (x); }
void c_finish_omp_taskyield (location_t loc) { tree x; x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD); x = build_call_expr_loc (loc, x, 0); add_stmt (x); }
void c_finish_omp_taskwait (location_t loc) { tree x; x = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; x = build_call_expr_loc (loc, x, 0); add_stmt (x); }
tree c_finish_omp_critical (tree body, tree name) { tree stmt = make_node (OMP_CRITICAL); TREE_TYPE (stmt) = void_type_node; OMP_CRITICAL_BODY (stmt) = body; OMP_CRITICAL_NAME (stmt) = name; return add_stmt (stmt); }
void c_finish_omp_taskwait (void) { tree x; x = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; x = build_call_expr (x, 0); add_stmt (x); }
void c_finish_omp_barrier (void) { tree x; x = built_in_decls[BUILT_IN_GOMP_BARRIER]; x = build_function_call_expr (x, NULL); add_stmt (x); }
void c_finish_omp_flush (location_t loc) { tree x; x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); x = build_call_expr_loc (loc, x, 0); add_stmt (x); }
void add_decl_stmt (tree decl) { tree decl_stmt; /* We need the type to last until instantiation time. */ decl_stmt = build_stmt (DECL_STMT, decl); add_stmt (decl_stmt); }
void c_finish_omp_barrier (location_t loc) { tree x; x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER); x = build_call_expr_loc (loc, x, 0); add_stmt (x); }
tree c_finish_omp_critical (location_t loc, tree body, tree name) { tree stmt = make_node (OMP_CRITICAL); TREE_TYPE (stmt) = void_type_node; OMP_CRITICAL_BODY (stmt) = body; OMP_CRITICAL_NAME (stmt) = name; SET_EXPR_LOCATION (stmt, loc); return add_stmt (stmt); }
tree c_finish_omp_ordered (location_t loc, tree clauses, tree stmt) { tree t = make_node (OMP_ORDERED); TREE_TYPE (t) = void_type_node; OMP_ORDERED_BODY (t) = stmt; OMP_ORDERED_CLAUSES (t) = clauses; SET_EXPR_LOCATION (t, loc); return add_stmt (t); }
void prog_load(Prog* prog, const char* cmdpipe, const char* filename) { int bufsize = BUF_EXT; char* buf = malloc((size_t)bufsize); MFP* fp; char* s; int lineno = 1; char newname [1024]; char* temp; char* myfilename; assert(prog != NULL); assert(filename != NULL); assert(buf != NULL); assert(filename != NULL); if (cmdpipe == NULL) myfilename = strdup(filename); else { myfilename = malloc(strlen(filename) + strlen(cmdpipe) + 1024); sprintf(&myfilename[1], cmdpipe, filename); myfilename[0] = '#'; } if (NULL == (fp = mio_open(myfilename, ".zpl"))) zpl_exit(EXIT_FAILURE); if (verbose) printf("Reading %s\n", myfilename); while((s = get_line(&buf, &bufsize, fp, &lineno)) != NULL) { assert(!isspace(*s)); /* This could happen if we have a ;; somewhere. */ if (*s == '\0') continue; if (1 == sscanf(s, "include \"%1023[^\"]\"", newname)) { temp = malloc(strlen(filename) + strlen(newname) + 2); prog_load(prog, cmdpipe, make_pathname(temp, filename, newname)); free(temp); } else { add_stmt(prog, filename, lineno, s); } } mio_close(fp); free(myfilename); free(buf); }
static inline void make_triplet_val_inv (location_t loc, tree *value) { tree var, new_exp; if (TREE_CODE (*value) != INTEGER_CST && TREE_CODE (*value) != PARM_DECL && TREE_CODE (*value) != VAR_DECL) { var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node); new_exp = build_modify_expr (loc, var, TREE_TYPE (var), NOP_EXPR, loc, *value, TREE_TYPE (*value)); add_stmt (new_exp); *value = var; } }
tree begin_eh_spec_block (void) { tree r; location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl); /* A noexcept specification (or throw() with -fnothrow-opt) is a MUST_NOT_THROW_EXPR. */ if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl))) { r = build_stmt (spec_location, MUST_NOT_THROW_EXPR, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (r) = 1; } else r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); TREE_OPERAND (r, 0) = push_stmt_list (); return r; }
static tree fix_conditional_array_notations_1 (tree stmt) { vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; size_t list_size = 0; tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE; size_t rank = 0, ii = 0; tree loop_init; location_t location = EXPR_LOCATION (stmt); tree body = NULL_TREE, loop_with_init = alloc_stmt_list (); vec<vec<an_parts> > an_info = vNULL; vec<an_loop_parts> an_loop_info = vNULL; if (TREE_CODE (stmt) == COND_EXPR) cond = COND_EXPR_COND (stmt); else if (TREE_CODE (stmt) == SWITCH_EXPR) cond = SWITCH_COND (stmt); else if (truth_value_p (TREE_CODE (stmt))) cond = TREE_OPERAND (stmt, 0); else /* Otherwise dont even touch the statement. */ return stmt; if (!find_rank (location, cond, cond, false, &rank)) return error_mark_node; extract_array_notation_exprs (stmt, false, &array_list); loop_init = push_stmt_list (); for (ii = 0; ii < vec_safe_length (array_list); ii++) { tree array_node = (*array_list)[ii]; if (TREE_CODE (array_node) == CALL_EXPR) { builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var); if (builtin_loop == error_mark_node) { add_stmt (error_mark_node); pop_stmt_list (loop_init); return loop_init; } else if (builtin_loop) { vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL; vec_safe_push (sub_list, array_node); vec_safe_push (new_var_list, new_var); add_stmt (builtin_loop); replace_array_notations (&stmt, false, sub_list, new_var_list); } } } if (!find_rank (location, stmt, stmt, true, &rank)) { pop_stmt_list (loop_init); return error_mark_node; } if (rank == 0) { add_stmt (stmt); pop_stmt_list (loop_init); return loop_init; } extract_array_notation_exprs (stmt, true, &array_list); if (vec_safe_length (array_list) == 0) return stmt; list_size = vec_safe_length (array_list); an_loop_info.safe_grow_cleared (rank); for (ii = 0; ii < list_size; ii++) if ((*array_list)[ii] && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF) { tree array_node = (*array_list)[ii]; make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node)); } cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info); for (ii = 0; ii < rank; ii++) { an_loop_info[ii].var = create_tmp_var (integer_type_node); an_loop_info[ii].ind_init = build_modify_expr (location, an_loop_info[ii].var, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location, build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0), TREE_TYPE (an_loop_info[ii].var)); } array_operand = create_array_refs (location, an_info, an_loop_info, list_size, rank); replace_array_notations (&stmt, true, array_list, array_operand); create_cmp_incr (location, &an_loop_info, rank, an_info); loop_init = pop_stmt_list (loop_init); body = stmt; append_to_statement_list_force (loop_init, &loop_with_init); for (ii = 0; ii < rank; ii++) { tree new_loop = push_stmt_list (); add_stmt (an_loop_info[ii].ind_init); c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr, body, NULL_TREE, NULL_TREE, true); body = pop_stmt_list (new_loop); } append_to_statement_list_force (body, &loop_with_init); an_loop_info.release (); an_info.release (); return loop_with_init; }
static tree fix_array_notation_call_expr (tree arg) { vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; tree new_var = NULL_TREE; size_t list_size = 0, rank = 0, ii = 0; tree loop_init; tree body, loop_with_init = alloc_stmt_list (); location_t location = UNKNOWN_LOCATION; vec<vec<an_parts> > an_info = vNULL; vec<an_loop_parts> an_loop_info = vNULL; if (TREE_CODE (arg) == CALL_EXPR && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg))) { loop_init = fix_builtin_array_notation_fn (arg, &new_var); /* We are ignoring the new var because either the user does not want to capture it OR he is using sec_reduce_mutating function. */ return loop_init; } if (!find_rank (location, arg, arg, false, &rank)) return error_mark_node; if (rank == 0) return arg; extract_array_notation_exprs (arg, true, &array_list); if (vec_safe_length (array_list) == 0) return arg; list_size = vec_safe_length (array_list); location = EXPR_LOCATION (arg); an_loop_info.safe_grow_cleared (rank); loop_init = push_stmt_list (); for (ii = 0; ii < list_size; ii++) if ((*array_list)[ii] && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF) { tree array_node = (*array_list)[ii]; make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node)); } cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info); if (length_mismatch_in_expr_p (location, an_info)) { pop_stmt_list (loop_init); return error_mark_node; } for (ii = 0; ii < rank; ii++) { an_loop_info[ii].var = create_tmp_var (integer_type_node); an_loop_info[ii].ind_init = build_modify_expr (location, an_loop_info[ii].var, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location, build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0), TREE_TYPE (an_loop_info[ii].var)); } array_operand = create_array_refs (location, an_info, an_loop_info, list_size, rank); replace_array_notations (&arg, true, array_list, array_operand); create_cmp_incr (location, &an_loop_info, rank, an_info); loop_init = pop_stmt_list (loop_init); append_to_statement_list_force (loop_init, &loop_with_init); body = arg; for (ii = 0; ii < rank; ii++) { tree new_loop = push_stmt_list (); add_stmt (an_loop_info[ii].ind_init); c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr, body, NULL_TREE, NULL_TREE, true); body = pop_stmt_list (new_loop); } append_to_statement_list_force (body, &loop_with_init); an_loop_info.release (); an_info.release (); return loop_with_init; }
tree c_finish_omp_ordered (tree stmt) { return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt)); }
tree build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, enum tree_code modifycode, location_t rhs_loc, tree rhs, tree rhs_origtype) { bool found_builtin_fn = false; tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE; tree array_expr = NULL_TREE; tree an_init = NULL_TREE; vec<tree> cond_expr = vNULL; tree body, loop_with_init = alloc_stmt_list(); tree scalar_mods = NULL_TREE; vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL; size_t lhs_rank = 0, rhs_rank = 0; size_t ii = 0; vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL; tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE; size_t rhs_list_size = 0, lhs_list_size = 0; vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL; vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL; /* If either of this is true, an error message must have been send out already. Not necessary to send out multiple error messages. */ if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; if (!find_rank (location, rhs, rhs, false, &rhs_rank)) return error_mark_node; extract_array_notation_exprs (rhs, false, &rhs_list); rhs_list_size = vec_safe_length (rhs_list); an_init = push_stmt_list (); if (rhs_rank) { scalar_mods = replace_invariant_exprs (&rhs); if (scalar_mods) add_stmt (scalar_mods); } for (ii = 0; ii < rhs_list_size; ii++) { tree rhs_node = (*rhs_list)[ii]; if (TREE_CODE (rhs_node) == CALL_EXPR) { builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var); if (builtin_loop == error_mark_node) { pop_stmt_list (an_init); return error_mark_node; } else if (builtin_loop) { add_stmt (builtin_loop); found_builtin_fn = true; if (new_var) { vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL; vec_safe_push (rhs_sub_list, rhs_node); vec_safe_push (new_var_list, new_var); replace_array_notations (&rhs, false, rhs_sub_list, new_var_list); } } } } lhs_rank = 0; rhs_rank = 0; if (!find_rank (location, lhs, lhs, true, &lhs_rank)) { pop_stmt_list (an_init); return error_mark_node; } if (!find_rank (location, rhs, rhs, true, &rhs_rank)) { pop_stmt_list (an_init); return error_mark_node; } if (lhs_rank == 0 && rhs_rank == 0) { if (found_builtin_fn) { new_modify_expr = build_modify_expr (location, lhs, lhs_origtype, modifycode, rhs_loc, rhs, rhs_origtype); add_stmt (new_modify_expr); pop_stmt_list (an_init); return an_init; } else { pop_stmt_list (an_init); return NULL_TREE; } } rhs_list_size = 0; rhs_list = NULL; extract_array_notation_exprs (rhs, true, &rhs_list); extract_array_notation_exprs (lhs, true, &lhs_list); rhs_list_size = vec_safe_length (rhs_list); lhs_list_size = vec_safe_length (lhs_list); if (lhs_rank == 0 && rhs_rank != 0) { tree rhs_base = rhs; if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF) { for (ii = 0; ii < (size_t) rhs_rank; ii++) rhs_base = ARRAY_NOTATION_ARRAY (rhs); error_at (location, "%qE cannot be scalar when %qE is not", lhs, rhs_base); return error_mark_node; } else { error_at (location, "%qE cannot be scalar when %qE is not", lhs, rhs_base); return error_mark_node; } } if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) { error_at (location, "rank mismatch between %qE and %qE", lhs, rhs); pop_stmt_list (an_init); return error_mark_node; } /* Here we assign the array notation components to variable so that we can satisfy the exec once rule. */ for (ii = 0; ii < lhs_list_size; ii++) { tree array_node = (*lhs_list)[ii]; make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node)); } for (ii = 0; ii < rhs_list_size; ii++) if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF) { tree array_node = (*rhs_list)[ii]; make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node)); make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node)); } cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank)); lhs_an_loop_info.safe_grow_cleared (lhs_rank); if (rhs_rank) rhs_an_loop_info.safe_grow_cleared (rhs_rank); cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank, &lhs_an_info); if (rhs_rank) { rhs_an_loop_info.safe_grow_cleared (rhs_rank); cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank, &rhs_an_info); } if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info) || (rhs_rank && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info))) { pop_stmt_list (an_init); return error_mark_node; } if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0 && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST && rhs_an_info[0][0].length && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST) { HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length); HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length); /* Length can be negative or positive. As long as the magnitude is OK, then the array notation is valid. */ if (absu_hwi (l_length) != absu_hwi (r_length)) { error_at (location, "length mismatch between LHS and RHS"); pop_stmt_list (an_init); return error_mark_node; } } for (ii = 0; ii < lhs_rank; ii++) if (lhs_an_info[0][ii].is_vector) { lhs_an_loop_info[ii].var = create_tmp_var (integer_type_node); lhs_an_loop_info[ii].ind_init = build_modify_expr (location, lhs_an_loop_info[ii].var, TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR, location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)), TREE_TYPE (lhs_an_loop_info[ii].var)); } for (ii = 0; ii < rhs_rank; ii++) { /* When we have a polynomial, we assume that the indices are of type integer. */ rhs_an_loop_info[ii].var = create_tmp_var (integer_type_node); rhs_an_loop_info[ii].ind_init = build_modify_expr (location, rhs_an_loop_info[ii].var, TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR, location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0), TREE_TYPE (rhs_an_loop_info[ii].var)); } if (lhs_rank) { lhs_array_operand = create_array_refs (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank); replace_array_notations (&lhs, true, lhs_list, lhs_array_operand); array_expr_lhs = lhs; } if (rhs_array_operand) vec_safe_truncate (rhs_array_operand, 0); if (rhs_rank) { rhs_array_operand = create_array_refs (location, rhs_an_info, rhs_an_loop_info, rhs_list_size, rhs_rank); replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); vec_safe_truncate (rhs_array_operand, 0); rhs_array_operand = fix_sec_implicit_args (location, rhs_list, rhs_an_loop_info, rhs_rank, rhs); if (!rhs_array_operand) return error_mark_node; replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); } else if (rhs_list_size > 0) { rhs_array_operand = fix_sec_implicit_args (location, rhs_list, lhs_an_loop_info, lhs_rank, lhs); if (!rhs_array_operand) return error_mark_node; replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); } array_expr_lhs = lhs; array_expr_rhs = rhs; array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype, modifycode, rhs_loc, array_expr_rhs, rhs_origtype); create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info); if (rhs_rank) create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info); for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++) if (ii < lhs_rank && ii < rhs_rank) cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node, lhs_an_loop_info[ii].cmp, rhs_an_loop_info[ii].cmp); else if (ii < lhs_rank && ii >= rhs_rank) cond_expr[ii] = lhs_an_loop_info[ii].cmp; else gcc_unreachable (); an_init = pop_stmt_list (an_init); append_to_statement_list_force (an_init, &loop_with_init); body = array_expr; for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++) { tree incr_list = alloc_stmt_list (); tree new_loop = push_stmt_list (); if (lhs_rank) add_stmt (lhs_an_loop_info[ii].ind_init); if (rhs_rank) add_stmt (rhs_an_loop_info[ii].ind_init); if (lhs_rank) append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list); if (rhs_rank && rhs_an_loop_info[ii].incr) append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list); c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE, NULL_TREE, true); body = pop_stmt_list (new_loop); } append_to_statement_list_force (body, &loop_with_init); lhs_an_info.release (); lhs_an_loop_info.release (); if (rhs_rank) { rhs_an_info.release (); rhs_an_loop_info.release (); } cond_expr.release (); return loop_with_init; }
tree c_finish_omp_master (tree stmt) { return add_stmt (build1 (OMP_MASTER, void_type_node, stmt)); }
tree c_finish_omp_for (location_t locus, tree decl, tree init, tree cond, tree incr, tree body, tree pre_body) { location_t elocus = locus; bool fail = false; if (EXPR_HAS_LOCATION (init)) elocus = EXPR_LOCATION (init); /* Validate the iteration variable. */ if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))) { error ("%Hinvalid type for iteration variable %qE", &elocus, decl); fail = true; } if (TYPE_UNSIGNED (TREE_TYPE (decl))) warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl); /* In the case of "for (int i = 0...)", init will be a decl. It should have a DECL_INITIAL that we can turn into an assignment. */ if (init == decl) { elocus = DECL_SOURCE_LOCATION (decl); init = DECL_INITIAL (decl); if (init == NULL) { error ("%H%qE is not initialized", &elocus, decl); init = integer_zero_node; fail = true; } init = build_modify_expr (decl, NOP_EXPR, init); SET_EXPR_LOCATION (init, elocus); } gcc_assert (TREE_CODE (init) == MODIFY_EXPR); gcc_assert (TREE_OPERAND (init, 0) == decl); if (cond == NULL_TREE) { error ("%Hmissing controlling predicate", &elocus); fail = true; } else { bool cond_ok = false; if (EXPR_HAS_LOCATION (cond)) elocus = EXPR_LOCATION (cond); if (TREE_CODE (cond) == LT_EXPR || TREE_CODE (cond) == LE_EXPR || TREE_CODE (cond) == GT_EXPR || TREE_CODE (cond) == GE_EXPR) { tree op0 = TREE_OPERAND (cond, 0); tree op1 = TREE_OPERAND (cond, 1); /* 2.5.1. The comparison in the condition is computed in the type of DECL, otherwise the behavior is undefined. For example: long n; int i; i < n; according to ISO will be evaluated as: (long)i < n; We want to force: i < (int)n; */ if (TREE_CODE (op0) == NOP_EXPR && decl == TREE_OPERAND (op0, 0)) { TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0); TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl), TREE_OPERAND (cond, 1)); } else if (TREE_CODE (op1) == NOP_EXPR && decl == TREE_OPERAND (op1, 0)) { TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0); TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl), TREE_OPERAND (cond, 0)); } if (decl == TREE_OPERAND (cond, 0)) cond_ok = true; else if (decl == TREE_OPERAND (cond, 1)) { TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond))); TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0); TREE_OPERAND (cond, 0) = decl; cond_ok = true; } } if (!cond_ok) { error ("%Hinvalid controlling predicate", &elocus); fail = true; } } if (incr == NULL_TREE) { error ("%Hmissing increment expression", &elocus); fail = true; } else { bool incr_ok = false; if (EXPR_HAS_LOCATION (incr)) elocus = EXPR_LOCATION (incr); /* Check all the valid increment expressions: v++, v--, ++v, --v, v = v + incr, v = incr + v and v = v - incr. */ switch (TREE_CODE (incr)) { case POSTINCREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case PREDECREMENT_EXPR: incr_ok = (TREE_OPERAND (incr, 0) == decl); break; case MODIFY_EXPR: if (TREE_OPERAND (incr, 0) != decl) break; if (TREE_OPERAND (incr, 1) == decl) break; if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl)) incr_ok = true; else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl) incr_ok = true; else { tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl); if (t != error_mark_node) { incr_ok = true; t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t); incr = build2 (MODIFY_EXPR, void_type_node, decl, t); } } break; default: break; } if (!incr_ok) { error ("%Hinvalid increment expression", &elocus); fail = true; } } if (fail) return NULL; else { tree t = make_node (OMP_FOR); TREE_TYPE (t) = void_type_node; OMP_FOR_INIT (t) = init; OMP_FOR_COND (t) = cond; OMP_FOR_INCR (t) = incr; OMP_FOR_BODY (t) = body; OMP_FOR_PRE_BODY (t) = pre_body; SET_EXPR_LOCATION (t, locus); return add_stmt (t); } }