Esempio n. 1
0
void clay_relation_normalize_alpha(osl_relation_p relation) {
  int row, col;
  osl_int_t gcd;

  osl_int_init(relation->precision, &gcd);

  // Normalize equalities.
  clay_relation_output_form(relation);

  // Normalize inequalities.
  for (row = 0; row < relation->nb_rows; row++) {
    if (osl_int_zero(relation->precision, relation->m[row][0])) {
      continue; // ignore equalities
    }
    gcd = clay_relation_line_gcd(relation, row, 1, relation->nb_columns);
    for (col = 1; col < relation->nb_columns; col++) {
      if (col >= 1 && col < relation->nb_output_dims + 1 && (col % 2) == 1) {
        continue; // ignore beta dimensions
      }
      osl_int_div_exact(relation->precision, &relation->m[row][col],
                        relation->m[row][col], gcd);
    }
  }

  clay_relation_sort_rows(relation);

  osl_int_clear(relation->precision, &gcd);
}
Esempio n. 2
0
void clay_relation_substitute(osl_relation_p relation,
                              int original_col,
                              int target_col,
                              int factor) {
  int row;
  osl_int_t tmp;

  // Do not allow substituting e/i flag or the constant and
  // do not allow substituting by e/i flag (but allow by constant).
  if (original_col <= 0 || original_col > relation->nb_columns - 1 ||
      target_col <= 0 || target_col > relation->nb_columns)
    return;

  osl_int_init(relation->precision, &tmp);
  for (row = 0; row < relation->nb_rows; row++) {
    if (osl_int_zero(relation->precision, relation->m[row][original_col])) {
      continue;
    }
    osl_int_mul_si(relation->precision, &tmp, relation->m[row][original_col],
                   factor);
    osl_int_add(relation->precision, &relation->m[row][target_col],
                relation->m[row][target_col], tmp);
  }

  osl_int_clear(relation->precision, &tmp);
}
Esempio n. 3
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;
}
Esempio n. 4
0
static bool isParametricBoundary(int row, osl_relation_p scattering) {
  int firstParameterDim = scattering->nb_input_dims +
      scattering->nb_output_dims +
      scattering->nb_local_dims + 1;
  for (int i = 0; i < scattering->nb_parameters; i++) {
    if (!osl_int_zero(scattering->precision, scattering->m[row][firstParameterDim + i]))
      return true;
  }
  return false;
}
Esempio n. 5
0
static bool isVariableBoundary(int row, osl_relation_p scattering, int dimIdx) {
  bool variable = false;
  for (int i = 0; i < scattering->nb_input_dims + scattering->nb_output_dims + scattering->nb_local_dims; i++) {
    if (i + 1 == dimIdx)
      continue;
    if (!osl_int_zero(scattering->precision, scattering->m[row][1 + i]))
      variable = true;
  }

  return variable;
}
Esempio n. 6
0
File: util.c Progetto: tajkhan/clay
/**
 * clay_util_relation_get_line function:
 * Because the lines in the scattering matrix may have not ordered, we have to
 * search the corresponding line. It returns the first line where the value is
 * different from zero in the `column'. `column' is between 0 and 
 * nb_output_dims-1
 * \param[in] relation
 * \param[in] column        Line to search
 * \return                  Return the real line
 */
int clay_util_relation_get_line(osl_relation_p relation, int column) {
  if (column < 0 || column > relation->nb_output_dims)
    return -1;
  int i;
  int precision = relation->precision;
  for (i = 0 ; i < relation->nb_rows ; i++) {
    if (!osl_int_zero(precision, relation->m[i][column+1])) {
      break;
    }
  }
  return (i == relation->nb_rows ? -1 : i );
}
Esempio n. 7
0
void clay_relation_alpha_equation_rows(clay_array_p equation_rows,
                                       osl_relation_p relation) {
  int i;

  // Take only alpha equations.
  for (i = 0; i < relation->nb_rows; i++) {
    if (osl_int_zero(relation->precision, relation->m[i][0])) {
      if (!clay_util_is_row_beta_definition(relation, i)) {
        clay_array_add(equation_rows, i);
      }
    }
  }
}
Esempio n. 8
0
// assumes beta-structure; depth 1-based
// TODO: do not return, possible leak
osl_int_t clay_relation_gcd(osl_relation_p relation, int depth) {
  osl_int_t gcd;
  int row, col;
  int gcd_assigned = 0;
  int column = 2*depth;

  osl_int_init(relation->precision, &gcd);
  if (depth < -1 || depth == 0 || depth > relation->nb_output_dims / 2) {
  CLAY_debug("Called clay_relation_gcd with column outside bounds");
    osl_int_set_si(relation->precision, &gcd, 0);
    return gcd;
  }

  for (row = 0; row < relation->nb_rows; row++) {
    if (depth != -1 && osl_int_zero(relation->precision, relation->m[row][column])) {
      continue;
    }

    for (col = 2; col < relation->nb_columns; col++) {
      // if beta, ignore
      if (col >= 1 && col < relation->nb_output_dims + 1 && (col % 2) == 1) {
        continue;
      }
      if (col == column) {
        continue;
      }
      if (gcd_assigned) {
        osl_int_gcd(relation->precision, &gcd, gcd, relation->m[row][col]);
      } else {
        if (!osl_int_zero(relation->precision, relation->m[row][col])) {
          osl_int_assign(relation->precision, &gcd, relation->m[row][col]);
          gcd_assigned = 1;
        }
      }
    }
  }
  return gcd;
}
Esempio n. 9
0
// aware of beta structure
static int clay_relation_line_is_zero(osl_relation_p relation, int row,
                                      int begin, int end) {
  int i;
  int all_zero = 1;
  for (i = begin; i < end; i++) {
    if (i >= 1 && i < 1 + relation->nb_output_dims && (i % 2) == 1) {
      continue; // ignore betas
    }
    all_zero = all_zero && osl_int_zero(relation->precision,
                                        relation->m[row][i]);
    if (!all_zero) {
      break;
    }
  }
  return all_zero;
}
Esempio n. 10
0
// aware of beta structure
osl_int_t clay_relation_line_gcd(osl_relation_p relation, int line, int column_start, int column_end) {
  osl_int_t gcd, tmp;
  int i;
  int gcd_assigned = 0;

  osl_int_init(relation->precision, &gcd);
  osl_int_init(relation->precision, &tmp);

  if (column_end - column_start < 1 ||
      column_start >= relation->nb_columns ||
      column_end > relation->nb_columns) {
    osl_int_set_si(relation->precision, &gcd, 0);
    return gcd;
  } else if (column_end - column_start == 1) {
    osl_int_assign(relation->precision, &gcd, relation->m[line][column_start]);
    return gcd;
  }

  for (i = column_start; i < column_end; i++) {
    if (i >= 1 && i < relation->nb_output_dims + 1 && (i % 2) == 1) {
      continue; // ignore betas
    }
    if (osl_int_zero(relation->precision, relation->m[line][i])) {
      continue; // ignore zeros
    }
    osl_int_abs(relation->precision, &tmp, relation->m[line][i]);

    if (!gcd_assigned) {
      osl_int_assign(relation->precision, &gcd, tmp);
      gcd_assigned = 1;
    } else {
      osl_int_gcd(relation->precision, &gcd, gcd, tmp);
    }
  }

  if (!gcd_assigned) { // if gcd zero or not found, default to 1.
    osl_int_set_si(relation->precision, &gcd, 1);
  }

  osl_int_clear(relation->precision, &tmp);
  return gcd;
}
Esempio n. 11
0
File: util.c Progetto: tajkhan/clay
/**
 * clay_util_body_regenerate_access function:
 * Read the access array and re-generate the code in the body
 * \param[in] ebody     An extbody structure
 * \param[in] access    The relation to regenerate the code
 * \param[in] index     nth access (needed to access to the array start and 
 *                      length of the extbody structure)
 */
void clay_util_body_regenerate_access(osl_extbody_p ebody,
                                      osl_relation_p access,
                                      int index,
                                      osl_arrays_p arrays,
                                      osl_scatnames_p scatnames,
                                      osl_strings_p params) {

  if (!arrays || !scatnames || !params || access->nb_output_dims == 0 ||
      index >= ebody->nb_access)
    return;

  const int precision = access->precision;
  int i, j, k, row, val, print_plus;

  // check if there are no inequ
  for (i = 0 ; i < access->nb_rows ; i++) {
    if (!osl_int_zero(precision, access->m[i][0]))
      CLAY_error("I don't know how to regenerate access with inequalities");
  }

  // check identity matrix in output dims
  int n;
  for (j = 0 ; j < access->nb_output_dims ; j++) {
    n = 0;
    for (i = 0 ; i < access->nb_rows ; i++)
      if (!osl_int_zero(precision, access->m[i][j+1])) {
        if (n >= 1)
          CLAY_error("I don't know how to regenerate access with "
                     "dependences in output dims");
        n++;
      }
  }

  char *body = ebody->body->expression->string[0];
  int body_len = strlen(body);
  int start = ebody->start[index];
  int len = ebody->length[index];
  int is_zero; // if the line contains only zeros

  if (start >= body_len || start + len >= body_len || (start == -1 && len == -1))
    return;

  char *new_body;
  char end_body[OSL_MAX_STRING];
  int hwm = OSL_MAX_STRING;

  CLAY_malloc(new_body, char *, OSL_MAX_STRING * sizeof(char));

  // copy the beginning of the body
  if (start+1 >= OSL_MAX_STRING)
    CLAY_error("memcpy: please recompile osl with a higher OSL_MAX_STRING");
  memcpy(new_body, body, start);
  new_body[start] = '\0';

  // save the end in a buffer
  int sz = body_len - start - len;
  if (sz + 1 >= OSL_MAX_STRING)
    CLAY_error("memcpy: please recompile osl with a higher OSL_MAX_STRING");
  memcpy(end_body, body + start + len, sz);
  end_body[sz] = '\0';


  // copy access name string
  val = osl_relation_get_array_id(access);
  val = clay_util_arrays_search(arrays, val); // get the index in th array
  osl_util_safe_strcat(&new_body, arrays->names[val], &hwm);


  // generate each dims
  for (i = 1 ; i < access->nb_output_dims ; i++) {
    row = clay_util_relation_get_line(access, i);
    if (row == -1)
      continue;

    osl_util_safe_strcat(&new_body, "[", &hwm);

    is_zero = 1;
    print_plus = 0;
    k = 1 + access->nb_output_dims;

    // iterators
    for (j = 0 ; j < access->nb_input_dims ; j++, k++) {
      val = osl_int_get_si(precision, access->m[row][k]);
      if (val != 0) {
        clay_util_name_sprint(&new_body,
                              &hwm, 
                              &print_plus,
                              val,
                              scatnames->names->string[j*2+1]);
        is_zero = 0;
      }
    }

    // params
    for (j = 0 ; j < access->nb_parameters ; j++, k++) {
      val = osl_int_get_si(precision, access->m[row][k]);
      if (val != 0) {
        clay_util_name_sprint(&new_body,
                              &hwm, 
                              &print_plus,
                              val,
                              params->string[j]);
        is_zero = 0;
      }
    }

    // const
    val = osl_int_get_si(precision, access->m[row][k]);
    if (val != 0 || is_zero)
      clay_util_name_sprint(&new_body,
                            &hwm, 
                            &print_plus,
                            val,
                            NULL);

    osl_util_safe_strcat(&new_body, "]", &hwm);
  }

  // length of the generated access
  ebody->length[index] = strlen(new_body) - start;

  // concat the end
  osl_util_safe_strcat(&new_body, end_body, &hwm);

  // update ebody
  free(ebody->body->expression->string[0]);
  ebody->body->expression->string[0] = new_body;

  // shift the start
  int diff = ebody->length[index] - len;
  for (i = index+1 ; i < ebody->nb_access ; i++)
    if (ebody->start[i] != -1)
      ebody->start[i] += diff;
}
Esempio n. 12
0
File: util.c Progetto: tajkhan/clay
/** 
 * clay_util_statement_set_vector function:
 * Set the equation on each line where the column of the output dim is
 * different of zero
 * \param[in,out] statement
 * \param[in] vector           {(([output, ...],) [param, ..],) [const]}
 * \param[in] column           column on the output dim
 */
void clay_util_statement_set_vector(
                        osl_statement_p statement,
                        clay_list_p vector, int column) {
  
  osl_relation_p scattering = statement->scattering;
  clay_array_p arr_dims = NULL, arr_params = NULL, arr_const = NULL;
  int i, j, k;
  int precision = scattering->precision;
  osl_int_p tmp;

  tmp = osl_int_malloc(precision);

  if (vector->size > 3) {
    CLAY_error("list with more than 3 arrays not supported");
  } else if (vector->size == 3) {
    arr_dims   = vector->data[0];
    arr_params = vector->data[1];
    arr_const  = vector->data[2];
  } else if (vector->size == 2) {
    arr_params = vector->data[0];
    arr_const  = vector->data[1];
  } else {
    arr_const  = vector->data[0];
  }

  // for each line where there is a number different from zero on the
  // column
  for (k = 0 ; k < scattering->nb_rows ; k++) {
    if (!osl_int_zero(precision, scattering->m[k][1+column])) {

      // scattering = coeff_outputdim * shifting

      // affect output dims
      if (vector->size >= 3) {
        i = 1;
        for (j = 0 ; j < arr_dims->size ; j++) {
          osl_int_mul_si(precision,
                         &scattering->m[k][i],
                         scattering->m[k][1+column],
                         arr_dims->data[j]);
          i++;
        }
      }

      // here we add we the last value
      // scattering += coeff_outputdim * shifting

      // affects parameters
      if (vector->size >= 2) {
        i = 1 + scattering->nb_output_dims + scattering->nb_input_dims + 
            scattering->nb_local_dims;
        for (j = 0 ; j < arr_params->size ; j++) {
          osl_int_mul_si(precision,
                         tmp,
                         scattering->m[k][1+column],
                         arr_params->data[j]);
          osl_int_add(precision,
                      &scattering->m[k][i],
                      scattering->m[k][i],
                      *tmp);
          i++;
        }
      }

      // set the constant
      if (vector->size >= 1 && arr_const->size == 1) {
        osl_int_mul_si(precision,
                       tmp,
                       scattering->m[k][1+column],
                       arr_const->data[0]);
        osl_int_add(precision,
                    &scattering->m[k][scattering->nb_columns-1],
                    scattering->m[k][scattering->nb_columns-1],
                    *tmp);
      }
    }
  }
  
  osl_int_free(precision, tmp);
}
Esempio n. 13
0
// make i-th coefficient in the row_i zero by subtracting row_j multiplied by
// a constant factor from row_i.
void clay_relation_zero_coefficient(osl_relation_p relation,
                                    int row_i, int row_j, int col) {
  int k;
  osl_int_t lcm, multiplier_i, multiplier_j;

  osl_int_init(relation->precision, &lcm);
  osl_int_init(relation->precision, &multiplier_i);
  osl_int_init(relation->precision, &multiplier_j);

  // If the target coefficient is already zero,
  if (osl_int_zero(relation->precision, relation->m[row_j][col])) {
    // do nothing.
  }
  // If the source coefficient is zero, but the target one is not,
  else if (osl_int_zero(relation->precision, relation->m[row_i][col])) {
    // swap lines.
    for (k = 1; k < relation->nb_columns; k++) {
      osl_int_swap(relation->precision, &relation->m[row_i][k],
                   &relation->m[row_j][k]);
    }
  } else {
    osl_int_lcm(relation->precision, &lcm,
                relation->m[row_i][col], relation->m[row_j][col]);
    osl_int_div_exact(relation->precision, &multiplier_i,
                      lcm, relation->m[row_i][col]);
    osl_int_div_exact(relation->precision, &multiplier_j,
                      lcm, relation->m[row_j][col]);
    for (k = 1; k < relation->nb_columns; k++) {
      if (k < relation->nb_output_dims + 1 && (k % 2) == 1) {
        // ignore beta dimensions
        continue;
      }
      osl_int_mul(relation->precision, &relation->m[row_i][k],
                  relation->m[row_i][k], multiplier_i);
      osl_int_mul(relation->precision, &relation->m[row_j][k],
                  relation->m[row_j][k], multiplier_j);
      osl_int_sub(relation->precision, &relation->m[row_j][k],
                  relation->m[row_j][k], relation->m[row_i][k]);
    }
  }
  // Divide by constant factor if possible (similar to densify transformation).
  multiplier_i = clay_relation_line_gcd(relation, row_i, 1,
                                        relation->nb_columns);
  multiplier_j = clay_relation_line_gcd(relation, row_j, 1,
                                        relation->nb_columns);
  for (k = 1; k < relation->nb_columns; k++) {
    if (k < relation->nb_output_dims + 1 && (k % 2) == 1) {
      // ignore beta dimensions
      continue;
    }
    if (!osl_int_zero(relation->precision, multiplier_i)) {
      osl_int_div_exact(relation->precision, &relation->m[row_i][k],
                        relation->m[row_i][k], multiplier_i);
    }
    if (!osl_int_zero(relation->precision, multiplier_j)) {
      osl_int_div_exact(relation->precision, &relation->m[row_j][k],
                        relation->m[row_j][k], multiplier_j);
    }
  }

  osl_int_clear(relation->precision, &lcm);
  osl_int_clear(relation->precision, &multiplier_i);
  osl_int_clear(relation->precision, &multiplier_j);
}
Esempio n. 14
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;
}