/* DLOOP_Leaf_vector_mpi_flatten * * Input Parameters: * blocks_p - [inout] pointer to a count of blocks (total, for all noncontiguous pieces) * count - # of noncontiguous regions * blksz - size of each noncontiguous region * stride - distance in bytes from start of one region to start of next * el_type - elemental type (e.g. MPI_INT) * ... * * Note: this is only called when the starting position is at the beginning * of a whole block in a vector type. * * TODO: MAKE THIS CODE SMARTER, USING THE SAME GENERAL APPROACH AS IN THE * COUNT BLOCK CODE ABOVE. */ static int DLOOP_Leaf_vector_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count blksz, DLOOP_Offset stride, DLOOP_Type el_type, DLOOP_Offset rel_off, /* offset into buffer */ void *bufp, /* start of buffer */ void *v_paramp) { int i; DLOOP_Size size, blocks_left; DLOOP_Offset el_size; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); blocks_left = *blocks_p; for (i=0; i < count && blocks_left > 0; i++) { int last_idx; char *last_end = NULL; if (blocks_left > blksz) { size = blksz * el_size; blocks_left -= blksz; } else { /* last pass */ size = blocks_left * el_size; blocks_left = 0; } last_idx = paramp->index - 1; if (last_idx >= 0) { /* Since disps can be negative, we cannot use * DLOOP_Ensure_Offset_fits_in_pointer to verify that disps + * blklens fits in a pointer. Nor can we use * DLOOP_OFFSET_CAST_TO_VOID_PTR to cast the sum to a pointer. * Just let it truncate, if the sizeof a pointer is less * than the sizeof an MPI_Aint. */ last_end = (char *) DLOOP_OFFSET_CAST_TO_VOID_PTR (paramp->disps[last_idx] + (MPI_Aint)(paramp->blklens[last_idx])); } /* Since bufp can be a displacement and can be negative, we cannot use * DLOOP_Ensure_Offset_fits_in_pointer to ensure the sum fits in a pointer. * Just let it truncate. */ if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off))) { /* we have used up all our entries, and this one doesn't fit on * the end of the last one. */ *blocks_p -= (blocks_left + (size / el_size)); #ifdef MPID_SP_VERBOSE MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE,VERBOSE,(MPL_DBG_FDEST,"\t[vector to vec exiting (1): next ind = %d, " DLOOP_OFFSET_FMT_DEC_SPEC " blocks processed.\n", paramp->u.pack_vector.index, *blocks_p)); #endif return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off))) { /* add this size to the last vector rather than using up new one */ paramp->blklens[last_idx] += size; } else { /* Since bufp can be a displacement and can be negative, we cannot use * DLOOP_VOID_PTR_CAST_TO_OFFSET to cast the sum to a pointer. Just let it * sign extend. */ paramp->disps[last_idx+1] = DLOOP_PTR_DISP_CAST_TO_OFFSET bufp + rel_off; paramp->blklens[last_idx+1] = size; paramp->index++; } rel_off += stride; } #ifdef MPID_SP_VERBOSE MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE,VERBOSE,(MPL_DBG_FDEST,"\t[vector to vec exiting (2): next ind = %d, " DLOOP_OFFSET_FMT_DEC_SPEC " blocks processed.\n", paramp->u.pack_vector.index, *blocks_p)); #endif /* if we get here then we processed ALL the blocks; don't need to update * blocks_p */ DLOOP_Assert(blocks_left == 0); return 0; }
static int DLOOP_Leaf_index_mpi_flatten(DLOOP_Offset *blocks_p, DLOOP_Count count, DLOOP_Count *blockarray, DLOOP_Offset *offsetarray, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, void *v_paramp) { int i; DLOOP_Size size, blocks_left; DLOOP_Offset el_size; struct PREPEND_PREFIX(mpi_flatten_params) *paramp = v_paramp; DLOOP_Handle_get_size_macro(el_type, el_size); blocks_left = *blocks_p; for (i=0; i < count && blocks_left > 0; i++) { int last_idx; char *last_end = NULL; if (blocks_left > blockarray[i]) { size = blockarray[i] * el_size; blocks_left -= blockarray[i]; } else { /* last pass */ size = blocks_left * el_size; blocks_left = 0; } last_idx = paramp->index - 1; if (last_idx >= 0) { /* Since disps can be negative, we cannot use * DLOOP_Ensure_Offset_fits_in_pointer to verify that disps + * blklens fits in a pointer. Nor can we use * DLOOP_OFFSET_CAST_TO_VOID_PTR to cast the sum to a pointer. * Just let it truncate, if the sizeof a pointer is less * than the sizeof an MPI_Aint. */ last_end = (char *) DLOOP_OFFSET_CAST_TO_VOID_PTR (paramp->disps[last_idx] + (MPI_Aint)(paramp->blklens[last_idx])); } /* Since bufp can be a displacement and can be negative, we * cannot use DLOOP_Ensure_Offset_fits_in_pointer to ensure the * sum fits in a pointer. Just let it truncate. */ if ((last_idx == paramp->length-1) && (last_end != ((char *) bufp + rel_off + offsetarray[i]))) { /* we have used up all our entries, and this one doesn't fit on * the end of the last one. */ *blocks_p -= (blocks_left + (size / el_size)); return 1; } else if (last_idx >= 0 && (last_end == ((char *) bufp + rel_off + offsetarray[i]))) { /* add this size to the last vector rather than using up new one */ paramp->blklens[last_idx] += size; } else { /* Since bufp can be a displacement and can be negative, we cannot * use DLOOP_VOID_PTR_CAST_TO_OFFSET to cast the sum to a pointer. * Just let it sign extend. */ paramp->disps[last_idx+1] = DLOOP_PTR_DISP_CAST_TO_OFFSET bufp + rel_off + offsetarray[i]; paramp->blklens[last_idx+1] = size; /* these blocks are in bytes */ paramp->index++; } } /* if we get here then we processed ALL the blocks; don't need to update * blocks_p */ DLOOP_Assert(blocks_left == 0); return 0; }
/*@ Dataloop_update - update pointers after a copy operation Input Parameters: + dataloop - pointer to loop to update - ptrdiff - value indicating offset between old and new pointer values This function is used to recursively update all the pointers in a dataloop tree. @*/ void PREPEND_PREFIX(Dataloop_update)(DLOOP_Dataloop *dataloop, DLOOP_Offset ptrdiff) { /* OPT: only declare these variables down in the Struct case */ int i; DLOOP_Dataloop **looparray; switch(dataloop->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: case DLOOP_KIND_VECTOR: /* * All these really ugly assignments are really of the form: * * ((char *) dataloop->loop_params.c_t.loop) += ptrdiff; * * However, some compilers spit out warnings about casting on the * LHS, so we get this much nastier form instead (using common * struct for contig and vector): */ if (!(dataloop->kind & DLOOP_FINAL_MASK)) { DLOOP_Assert(dataloop->loop_params.cm_t.dataloop); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.cm_t.dataloop + ptrdiff); dataloop->loop_params.cm_t.dataloop = (DLOOP_Dataloop *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.cm_t.dataloop + ptrdiff); PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.cm_t.dataloop, ptrdiff); } break; case DLOOP_KIND_BLOCKINDEXED: DLOOP_Assert(dataloop->loop_params.bi_t.offset_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.bi_t.offset_array + ptrdiff); dataloop->loop_params.bi_t.offset_array = (DLOOP_Offset *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.bi_t.offset_array + ptrdiff); if (!(dataloop->kind & DLOOP_FINAL_MASK)) { DLOOP_Assert(dataloop->loop_params.bi_t.dataloop); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.bi_t.dataloop + ptrdiff); dataloop->loop_params.bi_t.dataloop = (DLOOP_Dataloop *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.bi_t.dataloop + ptrdiff); PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.bi_t.dataloop, ptrdiff); } break; case DLOOP_KIND_INDEXED: DLOOP_Assert(dataloop->loop_params.i_t.blocksize_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.blocksize_array + ptrdiff); dataloop->loop_params.i_t.blocksize_array = (DLOOP_Count *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.blocksize_array + ptrdiff); DLOOP_Assert(dataloop->loop_params.i_t.offset_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.offset_array + ptrdiff); dataloop->loop_params.i_t.offset_array = (DLOOP_Offset *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.offset_array + ptrdiff); if (!(dataloop->kind & DLOOP_FINAL_MASK)) { DLOOP_Assert(dataloop->loop_params.i_t.dataloop); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.dataloop + ptrdiff); dataloop->loop_params.i_t.dataloop = (DLOOP_Dataloop *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.i_t.dataloop + ptrdiff); PREPEND_PREFIX(Dataloop_update)(dataloop->loop_params.i_t.dataloop, ptrdiff); } break; case DLOOP_KIND_STRUCT: DLOOP_Assert(dataloop->loop_params.s_t.blocksize_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.blocksize_array + ptrdiff); dataloop->loop_params.s_t.blocksize_array = (DLOOP_Count *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.blocksize_array + ptrdiff); DLOOP_Assert(dataloop->loop_params.s_t.offset_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.offset_array + ptrdiff); dataloop->loop_params.s_t.offset_array = (DLOOP_Offset *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.offset_array + ptrdiff); if (dataloop->kind & DLOOP_FINAL_MASK) break; DLOOP_Assert(dataloop->loop_params.s_t.dataloop_array); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.dataloop_array + ptrdiff); dataloop->loop_params.s_t.dataloop_array = (DLOOP_Dataloop **) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) dataloop->loop_params.s_t.dataloop_array + ptrdiff); /* fix the N dataloop pointers too */ looparray = dataloop->loop_params.s_t.dataloop_array; for (i=0; i < dataloop->loop_params.s_t.count; i++) { DLOOP_Assert(looparray[i]); DLOOP_Ensure_Offset_fits_in_pointer(DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) looparray[i] + ptrdiff); looparray[i] = (DLOOP_Dataloop *) DLOOP_OFFSET_CAST_TO_VOID_PTR (DLOOP_VOID_PTR_CAST_TO_OFFSET (char *) looparray[i] + ptrdiff); } for (i=0; i < dataloop->loop_params.s_t.count; i++) { PREPEND_PREFIX(Dataloop_update)(looparray[i], ptrdiff); } break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ } return; }