int main(int argc, char * argv[]) { osl_scop_p scop = NULL; osl_generic_p x, last; osl_clay_p clay_tag; clay_options_p options; int parsing_result = 0; // Read command line parameters options = clay_options_read(argc, argv); if (options->print_infos) { clay_options_free(options); exit(0); } // Open the scop file #ifdef CLAN_LINKED if (options->readc) { clan_options_p clan_opt = clan_options_malloc(); clan_opt->precision = OSL_PRECISION_MP; clan_opt->name = options->input_name; clan_opt->extbody = 1; scop = clan_scop_extract(options->input, clan_opt); //clan_options_free(clan_opt); // bug, the name is also freed free(clan_opt); fclose(options->input); } else #endif { scop = osl_scop_read(options->input); if (options->input != stdin) fclose(options->input); } if (options->normalize) { clay_beta_normalize(scop); } #if defined(CANDL_LINKED) osl_scop_p orig_scop = NULL; if (!options->nocandl && scop != NULL) { orig_scop = osl_scop_clone(scop); } #endif // Execute the script ... // do nothing if the scop is NULL if (scop != NULL) { // Read the script file if (!options->from_tag) { parsing_result = clay_parser_file(scop, options->script, options); if (parsing_result != 0) { fprintf(stderr, "[Clay] %s\n", clay_get_error_message()); } fclose(options->script); // Read the script from the extension clay } else { // equivalent to osl_generic_lookup, but we need the last extension // to remove the clay extension in the list x = scop->extension; last = NULL; while (x != NULL) { if (osl_generic_has_URI(x, OSL_URI_CLAY)) break; last = x; x = x->next; } if (x != NULL) { // parse the clay string clay_tag = x->data; parsing_result = clay_parser_string(scop, clay_tag->script, options); if (parsing_result != 0) { fprintf(stderr, "[Clay] %s\n", clay_get_error_message()); } // remove the extension clay osl_generic_remove(&scop->extension, OSL_URI_CLAY); } } } #ifdef CANDL_LINKED int is_violated = 0; // Check dependencies if (!options->nocandl && scop != NULL && parsing_result == 0) { candl_options_p candl_opt = candl_options_malloc(); if (options->candl_fullcheck) candl_opt->fullcheck = 1; candl_scop_usr_init(orig_scop); candl_violation_p violation = candl_violation(orig_scop, scop, 0, candl_opt); is_violated = (violation != NULL); if (is_violated) { candl_violation_pprint(stdout, violation); if (options->candl_structure) candl_violation_dump(stdout, violation); } candl_scop_usr_cleanup(orig_scop); candl_options_free(candl_opt); candl_violation_free(violation); osl_scop_free(orig_scop); } if (!is_violated) // print the scop or the .c file by cloog #endif { #ifdef CLOOG_LINKED if (options->printc && scop != NULL && parsing_result == 0) { clay_util_scop_export_body(scop); CloogState *state = cloog_state_malloc(); CloogOptions *cloogoptions = cloog_options_malloc(state); cloogoptions->openscop = 1; CloogInput *clooginput = cloog_input_from_osl_scop(cloogoptions->state, scop); cloog_options_copy_from_osl_scop(scop, cloogoptions); CloogProgram *program = cloog_program_alloc(clooginput->context, clooginput->ud, cloogoptions); free(clooginput); cloog_program_generate(program, cloogoptions); cloog_program_pprint(stdout, program, cloogoptions); cloog_program_free(program); cloogoptions->scop = NULL; // don't free the scop cloog_options_free(cloogoptions); cloog_state_free(state); } else #endif { if (parsing_result == 0) { if (!options->keep_extbody) clay_util_scop_export_body(scop); osl_scop_print(stdout, scop); } } } osl_scop_free(scop); clay_options_free(options); return parsing_result; }
/** * @brief Allocate and construct the vectorization profile by analyzing the * osl_statement. * * @param[in] scop The scop of the analyzed osl_statement. * @param[in] statement The analyzed osl_statement. * * @return A constructed vectorization profile. */ struct substrate_vectorization_profile substrate_vectorization_profile_constructor( struct osl_scop * scop, struct osl_statement * statement) { struct substrate_vectorization_profile res = {NULL,0}; unsigned int i = 0; struct osl_relation_list *relation_list_cursor = NULL; struct osl_relation *relation_cursor = NULL; unsigned col = 0; unsigned line = 0; osl_int_t val; unsigned common_iterators_vectorized_dim[statement->domain->nb_output_dims]; int precision = statement->domain->precision; struct candl_options *candl_options = NULL; struct osl_dependence *candl_dep = NULL, *candl_dep_cursor = NULL; struct osl_scop *candl_scop = NULL; //Preparing and allocating the vectorization structure. res.size = statement->domain->nb_output_dims; res.vectorizable_loops = (bool*) malloc(res.size * sizeof(bool)); memset(res.vectorizable_loops,false,res.size); //For every possible iterator, we select only those that are used in the //vectorized output dimension (the first if column major, last if row major). // //If an access relation of the statement doesn't used the i^th iterator, //then this iterator can be used to vectorize the statement. for(i=0 ; i<res.size ; i++) { common_iterators_vectorized_dim[i] = true; relation_list_cursor = statement->access; while((relation_list_cursor != NULL) && (common_iterators_vectorized_dim[i])) { relation_cursor = relation_list_cursor->elt; while((relation_cursor != NULL) && (common_iterators_vectorized_dim[i])) { col = g_substrate_options.row_major ? relation_cursor->nb_output_dims-1 : 1; line = candl_util_relation_get_line(relation_cursor, col); val = relation_cursor->m[line][1 + relation_cursor->nb_output_dims + i]; common_iterators_vectorized_dim[i] = !osl_int_zero(precision, val); relation_cursor = relation_cursor->next; } relation_list_cursor = relation_list_cursor->next; } } //Creating a dummy scop with only the current analyzed statement for candl. //Also reset the beta depth of the statement, because it's supposed to be //alone now. candl_scop = substrate_osl_scop_nclone_except_statement(scop, 1); candl_scop->statement = osl_statement_nclone(statement,1); substrate_reset_beta_depth(candl_scop->statement); //Initiating candl, then using it to generate the dependences, //and finally extracting them to use later. candl_options = candl_options_malloc(); candl_scop_usr_init(candl_scop); candl_dependence_add_extension(candl_scop, candl_options); candl_dep = osl_generic_lookup(candl_scop->extension, OSL_URI_DEPENDENCE); for(i=0 ; i<res.size; i++) { if( common_iterators_vectorized_dim[i] == false ) continue; res.vectorizable_loops[i] = true; candl_dep_cursor = candl_dep; while( (candl_dep_cursor != NULL) && (res.vectorizable_loops[i]) ) { if(candl_dependence_is_loop_carried(candl_dep_cursor, i)) { switch(candl_dep_cursor->type) { //If the dependence is RaR (which should not be encountered because //we only analyze the self-dependence of the statement) or WaR, //then we don't care : these types doesn't prevent vectorization. case OSL_DEPENDENCE_RAR : case OSL_DEPENDENCE_WAR : break; //If a dependence is RaW or WaW, the i^th cannot be vectorized //because these type of dependence prevent it. case OSL_DEPENDENCE_RAW : case OSL_DEPENDENCE_WAW : res.vectorizable_loops[i] = false; break; default : OSL_error("In function substrate_vectorization_profile_constructor :" " an osl_dependence without a type has been encountered"); break; } } candl_dep_cursor = candl_dep_cursor->next; } } candl_options_free(candl_options); candl_scop_usr_cleanup(candl_scop); osl_scop_free(candl_scop); return res; }