Example #1
0
File: util.c Project: ArtemL/GCC
/**
 * osl_util_read_string function:
 * reads a string on the input 'file' or the input string 'str' depending on
 * which one is not NULL (exactly one of them must not be NULL).
 * \param[in]     file The file where to read a string (if not NULL).
 * \param[in,out] str  The string where to read a string (if not NULL). This
 *                     pointer is updated to reflect the read and points
 *                     after the string in the input string.
 * \return The string that has been read.
 */
char * osl_util_read_string(FILE * file, char ** str) {
  char s[OSL_MAX_STRING], * start;
  char * res;
  int i = 0;

  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
    OSL_error("one and only one of the two parameters can be non-NULL");

  OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char));
  if (file != NULL) {
    // Parse from a file.
    start = osl_util_skip_blank_and_comments(file, s);
    if (sscanf(start, " %s", res) != 1)
      OSL_error("a string was expected");
  }
  else {
    // Parse from a string.
    // Skip blank/commented lines.
    osl_util_sskip_blank_and_comments(str);
    
    // Build the chain to analyze.
    while (**str && !isspace(**str) && **str != '\n' && **str != '#')
      s[i++] = *((*str)++);
    s[i] = '\0';
    if (sscanf(s, "%s", res) != 1)
      OSL_error("a string was expected");
  }

  OSL_realloc(res, char *, strlen(res) + 1);
  return res;
}
Example #2
0
/**
 * osl_scop_check_compatible_scoplib function:
 * This function checks that a scop is "well formed". It returns 0 if the
 * check failed or 1 if no problem has been detected.
 * \param scop  The scop we want to check.
 * \return 0 if the integrity check fails, 1 otherwise.
 */
int osl_scop_check_compatible_scoplib(osl_scop_p scop) {

    if (!osl_scop_integrity_check(scop))
        return 0;
    if (scop->next != NULL)
        return 0;
    if (scop == NULL || scop->statement == NULL)
        return 1;

    osl_relation_p domain;
    osl_statement_p statement;
    osl_relation_p scattering;
    int precision = scop->statement->scattering->precision;
    int i, j;

    statement = scop->statement;
    while (statement != NULL) {
        scattering = statement->scattering;

        if (scattering->nb_local_dims != 0) {
            OSL_error("Local dims in scattering matrix");
            return 0;
        }

        domain = statement->domain;
        while (domain != NULL) {
            if (domain->nb_local_dims != 0) {
                OSL_error("Local dims in domain matrix");
                return 0;
            }
            domain = domain->next;
        }

        // Check if there is only the -Identity in the output_dims
        // and the lines MUST be in the right order
        for (i = 0 ; i < scattering->nb_rows ; i++) {
            for (j = 0 ; j < scattering->nb_output_dims ; j++) {
                if (i == j) { // -1
                    if (!osl_int_mone(precision, scattering->m[i][j+1])) {
                        OSL_error("Wrong -Identity");
                        return 0;
                    }
                } else { // 0
                    if (!osl_int_zero(precision, scattering->m[i][j+1])) {
                        OSL_error("Wrong -Identity");
                        return 0;
                    }
                }
            }
        }

        statement = statement->next;
    }

    return 1;
}
Example #3
0
File: util.c Project: ArtemL/GCC
/**
 * osl_util_read_int internal function:
 * reads a tag (the form of a tag with name "name" is \<name\>) on the input
 * 'file' or the input string 'str' depending on which one is not NULL (exactly
 * one of them must not be NULL). It returns the name of the tag (thus without
 * the < and > as a string. Note that in the case of an ending tag, e.g.,
 * \</foo\>, the slash is returned as a part of the name, e.g., /foo. If no
 * tag is found the function returns NULL.
 * \param[in]     file The file where to read a tag (if not NULL).
 * \param[in,out] str  The string where to read a tag (if not NULL). This
 *                     pointer is updated to reflect the read and points
 *                     after the tag in the input string.
 * \return The tag name that has been read.
 */
char * osl_util_read_tag(FILE * file, char ** str) {
  char s[OSL_MAX_STRING], * start;
  char * res;
  int i = 0;

  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
    OSL_error("one and only one of the two parameters can be non-NULL");

  // Skip blank/commented lines.
  if (file != NULL) {
    start = osl_util_skip_blank_and_comments(file, s);
    str = &start;
  }
  else {
    osl_util_sskip_blank_and_comments(str);
  }

  // If the end of the input has been reached, return NULL.
  if (((file != NULL) && (feof(file))) ||
      ((str  != NULL) && (**str == '\0')))
    return NULL;
  
  // Pass the starting '<'.
  if (**str != '<')
    OSL_error("a \"<\" to start a tag was expected");
  (*str)++;

  // Read the tag.
  OSL_malloc(res, char *, (OSL_MAX_STRING + 1) * sizeof(char));
  res[OSL_MAX_STRING] = '\0';
  
  while (**str && **str != '>') {
    if (((**str >= 'A') && (**str <= 'Z')) ||
        ((**str >= 'a') && (**str <= 'z')) ||
        ((**str == '/') && (i == 0))       ||
        (**str == '_')) {
      res[i++] = *((*str)++);
      res[i] = '\0';
    }
    else {
      OSL_error("illegal character in the tag name");
    }
  }

  // Check we actually end up with a '>' and pass it.
  if (**str != '>')
    OSL_error("a \">\" to end a tag was expected");
  (*str)++;

  return res;
}
Example #4
0
/**
 * osl_textual_sprint function:
 * this function prints the content of an osl_textual_t structure
 * (*textual) into a string (returned) in the OpenScop textual format.
 * \param[in]  textual The textual structure to be printed.
 * \return A string containing the OpenScop dump of the textual structure.
 */
char * osl_textual_sprint(osl_textual_p textual) {
  char * string = NULL;

  if ((textual != NULL) && (textual->textual != NULL)) {
    if (strlen(textual->textual) > OSL_MAX_STRING) 
      OSL_error("textual too long");
    
    string = strdup(textual->textual);
    if (string == NULL)
      OSL_error("memory overflow");
  }

  return string;
}
Example #5
0
File: util.c Project: ArtemL/GCC
/**
 * osl_util_read_uptoflag function:
 * this function reads a string up to a given flag (the flag is read)
 * on the input 'file' or the input string 'str' depending on which one is
 * not NULL (exactly one of them must not be NULL) and returns that string
 * without the flag. It returns NULL if the flag is not found.
 * \param[in]     file The file where to read up to flag (if not NULL).
 * \param[in,out] str  The string where to read up to flag (if not NULL). This
 *                     pointer is updated to reflect the read and points
 *                     after the flag in the input string.
 * \param[in]     flag The flag which, when reached, stops the reading.
 * \return The string that has been read.
 */
char * osl_util_read_uptoflag(FILE * file, char ** str, char * flag) {
  int high_water_mark = OSL_MAX_STRING;
  int nb_chars = 0;
  int lenflag = strlen(flag), lenstr;
  int flag_found = 0;
  char * res;

  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
    OSL_error("one and only one of the two parameters can be non-NULL");
  
  OSL_malloc(res, char *, high_water_mark * sizeof(char));

  // Copy everything to the res string.
  if (str != NULL)
    lenstr = strlen(*str);
  while (((str  != NULL) && (nb_chars != lenstr)) ||
         ((file != NULL) && (!feof(file)))) {
    res[nb_chars++] = (str != NULL) ? *((*str)++) : fgetc(file);

    if ((nb_chars >= lenflag) &&
        (!strncmp(&res[nb_chars - lenflag], flag, lenflag))) {
      flag_found = 1;
      break;
    }

    if (nb_chars >= high_water_mark) {
      high_water_mark += high_water_mark;
      OSL_realloc(res, char *, high_water_mark * sizeof(char));
    }
  }
Example #6
0
File: util.c Project: ArtemL/GCC
/**
 * osl_util_read_line function:
 * reads a line on the input 'file' or the input string 'str' depending on
 * which one is not NULL (exactly one of them must not be NULL). A line
 * is defined as the array of characters before the comment tag or the end of
 * line (it may include spaces).
 * \param[in]     file The file where to read a line (if not NULL).
 * \param[in,out] str  The string where to read a line (if not NULL). This
 *                     pointer is updated to reflect the read and points
 *                     after the line in the input string.
 * \return The line that has been read.
 */
char * osl_util_read_line(FILE * file, char ** str) {
  char s[OSL_MAX_STRING], * start;
  char * res;
  int i = 0;

  if ((file != NULL && str != NULL) || (file == NULL && str == NULL))
    OSL_error("one and only one of the two parameters can be non-NULL");

  OSL_malloc(res, char *, OSL_MAX_STRING * sizeof(char));
  if (file != NULL) {
    // Parse from a file.
    start = osl_util_skip_blank_and_comments(file, s);
    while (*start && *start != '\n' && *start != '#' && i < OSL_MAX_STRING)
      res[i++] = *start++;
  }
  else {
    // Parse from a string.
    osl_util_sskip_blank_and_comments(str);
    while (**str && **str != '\n' && **str != '#' && i < OSL_MAX_STRING)
      res[i++] = *((*str)++);
  }

  res[i] = '\0';
  OSL_realloc(res, char *, strlen(res) + 1);
  return res;
}
Example #7
0
/**
 * @brief Fusion two osl_body into a third one.
 * The two osl_body must have the same iterators or the program will fail.
 *
 * @param body1 The first osl_body.
 * @param body2 The second osl_body.
 *
 * @return An osl_body with the same iteratar as the parameters, but with
 * their "code" fusionned.
 */
struct osl_body * substrate_osl_body_fusion(
        struct osl_body * body1,
        struct osl_body * body2)
{
    struct osl_body * res = NULL;
    size_t body1_size = 0, body2_size = 0;

    body1_size = osl_strings_size(body1->iterators);
    body2_size = osl_strings_size(body2->iterators);

    res = osl_body_malloc();
    if((osl_strings_equal(body1->iterators, body2->iterators)) || (body1_size==0) || (body2_size==0))
    {
        res->iterators = osl_strings_clone(body1->iterators);
        substrate_osl_strings_concat(
                &res->expression,
                body1->expression,
                body2->expression);
    }
    else
    {
        //TODO Maybe fuse when iterators don't match ? (I'm not really sure).
        OSL_error("Can't fusion body");
    }

    return res;
}
Example #8
0
static void printf_in_buf(char **buf, size_t *buf_size, size_t *offset,
                          const char *fmt, ...) {
  va_list va;
  va_start(va, fmt);
  do {
    int printed = vsnprintf((*buf) + *offset, *buf_size - *offset, fmt, va);
    if (printed < 0)
      OSL_error(
          "snprintf encountered an error while writing inside a local buffer");
    size_t retval = (size_t)printed;
    if (retval < *buf_size - *offset) {
      *offset += retval;
      break;
    }
    OSL_realloc(*buf, char *, *buf_size * 2);
    *buf_size *= 2;
  } while (1);
  va_end(va);
}
Example #9
0
/**
 * osl_scop_pread function ("precision read"):
 * this function reads a list of scop structures from a file (possibly stdin)
 * complying to the OpenScop textual format and returns a pointer to this
 * scop list. If some relation properties (number of input/output/local
 * dimensions and number of parameters) are undefined, it will define them
 * according to the available information. 
 * \param[in] file      The file where the scop has to be read.
 * \param[in] registry  The list of known interfaces (others are ignored).
 * \param[in] precision The precision of the relation elements.
 * \return A pointer to the scop structure that has been read.
 */
osl_scop_p osl_scop_pread(FILE * file, osl_interface_p registry,
                          int precision) {
  osl_scop_p list = NULL, current = NULL, scop;
  osl_statement_p stmt = NULL;
  osl_statement_p prev = NULL;
  osl_strings_p language;
  int nb_statements;
  char * tmp;
  int first = 1;
  int i;

  if (file == NULL)
    return NULL;

  while(1) {
    //
    // I. START TAG
    //
    tmp = osl_util_read_uptotag(file, OSL_TAG_START_SCOP);
    if (tmp == NULL) {
      OSL_debug("no more scop in the file");
      break;
    }
    else {
      free(tmp);
    }

    scop = osl_scop_malloc();
    scop->registry = osl_interface_clone(registry);

    //
    // II. CONTEXT PART
    //

    // Read the language.
    language = osl_strings_read(file);
    if (osl_strings_size(language) == 0)
      OSL_error("no language (backend) specified");

    if (osl_strings_size(language) > 1)
      OSL_warning("uninterpreted information (after language)");

    if (language != NULL) {
      scop->language = strdup(language->string[0]);
      osl_strings_free(language);
    }

    // Read the context domain.
    scop->context = osl_relation_pread(file, precision);

    // Read the parameters.
    if (osl_util_read_int(file, NULL) > 0)
      scop->parameters = osl_generic_read_one(file, scop->registry);

    //
    // III. STATEMENT PART
    //

    // Read the number of statements.
    nb_statements = osl_util_read_int(file, NULL);

    for (i = 0; i < nb_statements; i++) {
      // Read each statement.
      stmt = osl_statement_pread(file, scop->registry, precision);
      if (scop->statement == NULL)
        scop->statement = stmt;
      else
        prev->next = stmt;
      prev = stmt;
    }

    //
    // IV. EXTENSION PART (TO THE END TAG)
    //

    // Read up the end tag (if any), and store extensions.
    scop->extension = osl_generic_read(file, scop->registry);

    // Add the new scop to the list.
    if (first) {
      list = scop;
      first = 0;
    }
    else {
      current->next = scop;
    }
    current = scop;    
  }
  
  if (!osl_scop_integrity_check(list))
    OSL_warning("scop integrity check failed");

  return list;
}
Example #10
0
/**
 * osl_scop_print_scoplib function:
 * this function prints the content of an osl_scop_t structure (*scop)
 * into a file (file, possibly stdout) in the ScopLib textual format.
 * \param file The file where the information has to be printed.
 * \param scop The scop structure whose information has to be printed.
 */
void osl_scop_print_scoplib(FILE * file, osl_scop_p scop) {
    int parameters_backedup = 0;
    int arrays_backedup = 0;
    osl_strings_p parameters_backup = NULL;
    osl_strings_p arrays_backup = NULL;
    osl_names_p names;
    osl_arrays_p arrays;

    if (scop == NULL) {
        fprintf(file, "# NULL scop\n");
        return;
    }
    else {
        fprintf(file, "# [File generated by the OpenScop Library %s]\n"
                "# [SCoPLib format]\n",
                OSL_RELEASE);
    }

    if (osl_scop_check_compatible_scoplib(scop) == 0) {
        OSL_error("SCoP integrity check failed. Something may go wrong.");
        exit(1);
    }

    // Generate the names for the various dimensions.
    names = osl_scop_names(scop);

    while (scop != NULL) {
        // If possible, replace parameter names with scop parameter names.
        if (osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS)) {
            parameters_backedup = 1;
            parameters_backup = names->parameters;
            names->parameters = scop->parameters->data;
        }

        // If possible, replace array names with arrays extension names.
        arrays = osl_generic_lookup(scop->extension, OSL_URI_ARRAYS);
        if (arrays != NULL) {
            arrays_backedup = 1;
            arrays_backup = names->arrays;
            names->arrays = osl_arrays_to_strings(arrays);
        }

        fprintf(file, "\nSCoP\n\n");
        fprintf(file, "# =============================================== "
                "Global\n");
        fprintf(file, "# Language\n");
        fprintf(file, "%s\n\n", scop->language);

        fprintf(file, "# Context\n");

        osl_relation_pprint_scoplib(file, scop->context, names, 0, 0);
        fprintf(file, "\n");

        osl_util_print_provided(file,
                                osl_generic_has_URI(scop->parameters, OSL_URI_STRINGS),
                                "Parameters are");

        if (scop->parameters) {
            fprintf(file, "# Parameter names\n");
            osl_strings_print(file, scop->parameters->data);
        }

        fprintf(file, "\n# Number of statements\n");
        fprintf(file, "%d\n\n",osl_statement_number(scop->statement));

        osl_statement_pprint_scoplib(file, scop->statement, names);

        if (scop->extension) {
            fprintf(file, "# =============================================== "
                    "Options\n");
            osl_generic_print_options_scoplib(file, scop->extension);
        }

        // If necessary, switch back parameter names.
        if (parameters_backedup) {
            parameters_backedup = 0;
            names->parameters = parameters_backup;
        }

        // If necessary, switch back array names.
        if (arrays_backedup) {
            arrays_backedup = 0;
            osl_strings_free(names->arrays);
            names->arrays = arrays_backup;
        }

        scop = scop->next;
    }

    osl_names_free(names);
}
Example #11
0
/**
 * @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;
}