Exemplo n.º 1
0
void MPII_Segment_manipulate(struct MPIR_Segment *segp,
                             MPI_Aint first,
                             MPI_Aint * lastp,
                             int (*contigfn) (MPI_Aint * blocks_p,
                                              MPI_Datatype el_type,
                                              MPI_Aint rel_off,
                                              void *bufp,
                                              void *v_paramp),
                             int (*vectorfn) (MPI_Aint * blocks_p,
                                              MPI_Aint count,
                                              MPI_Aint blklen,
                                              MPI_Aint stride,
                                              MPI_Datatype el_type,
                                              MPI_Aint rel_off,
                                              void *bufp,
                                              void *v_paramp),
                             int (*blkidxfn) (MPI_Aint * blocks_p,
                                              MPI_Aint count,
                                              MPI_Aint blklen,
                                              MPI_Aint * offsetarray,
                                              MPI_Datatype el_type,
                                              MPI_Aint rel_off,
                                              void *bufp,
                                              void *v_paramp),
                             int (*indexfn) (MPI_Aint * blocks_p,
                                             MPI_Aint count,
                                             MPI_Aint * blockarray,
                                             MPI_Aint * offsetarray,
                                             MPI_Datatype el_type,
                                             MPI_Aint rel_off,
                                             void *bufp,
                                             void *v_paramp),
                             MPI_Aint(*sizefn) (MPI_Datatype el_type), void *pieceparams)
{
    /* these four are the "local values": cur_sp, valid_sp, last, stream_off */
    int cur_sp, valid_sp;
    MPI_Aint last, stream_off;

    struct MPII_Dataloop_stackelm *cur_elmp;
    enum { PF_NULL, PF_CONTIG, PF_VECTOR, PF_BLOCKINDEXED, PF_INDEXED } piecefn_type = PF_NULL;

    SEGMENT_LOAD_LOCAL_VALUES;

    if (first == *lastp) {
        /* nothing to do */
        MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                        (MPL_DBG_FDEST,
                         "dloop_segment_manipulate: warning: first == last ("
                         MPI_AINT_FMT_DEC_SPEC ")\n", first));
        return;
    }

    /* first we ensure that stream_off and first are in the same spot */
    if (first != stream_off) {
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
        MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                        (MPL_DBG_FDEST,
                         "first=" MPI_AINT_FMT_DEC_SPEC "; stream_off="
                         MPI_AINT_FMT_DEC_SPEC "; resetting.\n", first, stream_off));
#endif

        if (first < stream_off) {
            SEGMENT_RESET_VALUES;
            stream_off = 0;
        }

        if (first != stream_off) {
            MPI_Aint tmp_last = first;

            /* use manipulate function with a NULL piecefn to advance
             * stream offset
             */
            MPII_Segment_manipulate(segp, stream_off, &tmp_last, NULL,  /* contig fn */
                                    NULL,       /* vector fn */
                                    NULL,       /* blkidx fn */
                                    NULL,       /* index fn */
                                    sizefn, NULL);

            /* --BEGIN ERROR HANDLING-- */
            /* verify that we're in the right location */
            MPIR_Assert(tmp_last == first);
            /* --END ERROR HANDLING-- */
        }

        SEGMENT_LOAD_LOCAL_VALUES;

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
        MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                        (MPL_DBG_FDEST,
                         "done repositioning stream_off; first=" MPI_AINT_FMT_DEC_SPEC
                         ", stream_off=" MPI_AINT_FMT_DEC_SPEC ", last="
                         MPI_AINT_FMT_DEC_SPEC "\n", first, stream_off, last));
#endif
    }

    for (;;) {
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
#if 0
        MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                        (MPL_DBG_FDEST, "looptop; cur_sp=%d, cur_elmp=%x\n", cur_sp,
                         (unsigned) cur_elmp));
#endif
#endif

        if (cur_elmp->loop_p->kind & MPII_DATALOOP_FINAL_MASK) {
            int piecefn_indicated_exit = -1;
            MPI_Aint myblocks, local_el_size, stream_el_size;
            MPI_Datatype el_type;

            /* structs are never finals (leaves) */
            MPIR_Assert((cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) !=
                        MPII_DATALOOP_KIND_STRUCT);

            /* pop immediately on zero count */
            if (cur_elmp->curcount == 0)
                SEGMENT_POP_AND_MAYBE_EXIT;

            /* size on this system of the int, double, etc. that is
             * the elementary type.
             */
            local_el_size = cur_elmp->loop_p->el_size;
            el_type = cur_elmp->loop_p->el_type;
            stream_el_size = (sizefn) ? sizefn(el_type) : local_el_size;

            /* calculate number of elem. types to work on and function to use.
             * default is to use the contig piecefn (if there is one).
             */
            myblocks = cur_elmp->curblock;
            piecefn_type = (contigfn ? PF_CONTIG : PF_NULL);

            /* check for opportunities to use other piecefns */
            switch (cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                case MPII_DATALOOP_KIND_CONTIG:
                    break;
                case MPII_DATALOOP_KIND_BLOCKINDEXED:
                    /* only use blkidx piecefn if at start of blkidx type */
                    if (blkidxfn &&
                        cur_elmp->orig_block == cur_elmp->curblock &&
                        cur_elmp->orig_count == cur_elmp->curcount) {
                        /* TODO: RELAX CONSTRAINTS */
                        myblocks = cur_elmp->curblock * cur_elmp->curcount;
                        piecefn_type = PF_BLOCKINDEXED;
                    }
                    break;
                case MPII_DATALOOP_KIND_INDEXED:
                    /* only use index piecefn if at start of the index type.
                     *   count test checks that we're on first block.
                     *   block test checks that we haven't made progress on first block.
                     */
                    if (indexfn &&
                        cur_elmp->orig_count == cur_elmp->curcount &&
                        cur_elmp->curblock == STACKELM_INDEXED_BLOCKSIZE(cur_elmp, 0)) {
                        /* TODO: RELAX CONSTRAINT ON COUNT? */
                        myblocks = cur_elmp->loop_p->loop_params.i_t.total_blocks;
                        piecefn_type = PF_INDEXED;
                    }
                    break;
                case MPII_DATALOOP_KIND_VECTOR:
                    /* only use the vector piecefn if at the start of a
                     * contiguous block.
                     */
                    if (vectorfn && cur_elmp->orig_block == cur_elmp->curblock) {
                        myblocks = cur_elmp->curblock * cur_elmp->curcount;
                        piecefn_type = PF_VECTOR;
                    }
                    break;
                default:
                    /* --BEGIN ERROR HANDLING-- */
                    MPIR_Assert(0);
                    break;
                    /* --END ERROR HANDLING-- */
            }

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
            MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                            (MPL_DBG_FDEST,
                             "\thit leaf; cur_sp=%d, elmp=%x, piece_sz=" MPI_AINT_FMT_DEC_SPEC
                             "\n", cur_sp, (unsigned) cur_elmp, myblocks * local_el_size));
#endif

            /* enforce the last parameter if necessary by reducing myblocks */
            if (last != MPIR_SEGMENT_IGNORE_LAST &&
                (stream_off + (myblocks * stream_el_size) > last)) {
                myblocks = ((last - stream_off) / stream_el_size);
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
                MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                                (MPL_DBG_FDEST,
                                 "\tpartial block count=" MPI_AINT_FMT_DEC_SPEC " ("
                                 MPI_AINT_FMT_DEC_SPEC " bytes)\n", myblocks,
                                 myblocks * stream_el_size));
#endif
                if (myblocks == 0) {
                    SEGMENT_SAVE_LOCAL_VALUES;
                    return;
                }
            }

            /* call piecefn to perform data manipulation */
            switch (piecefn_type) {
                case PF_NULL:
                    piecefn_indicated_exit = 0;
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
                    MPL_DBG_MSG("\tNULL piecefn for this piece\n");
#endif
                    break;
                case PF_CONTIG:
                    MPIR_Assert(myblocks <= cur_elmp->curblock);
                    piecefn_indicated_exit = contigfn(&myblocks, el_type, cur_elmp->curoffset,  /* relative to segp->ptr */
                                                      segp->ptr,        /* start of buffer (from segment) */
                                                      pieceparams);
                    break;
                case PF_VECTOR:
                    piecefn_indicated_exit =
                        vectorfn(&myblocks,
                                 cur_elmp->curcount,
                                 cur_elmp->orig_block,
                                 cur_elmp->loop_p->loop_params.v_t.stride,
                                 el_type, cur_elmp->curoffset, segp->ptr, pieceparams);
                    break;
                case PF_BLOCKINDEXED:
                    piecefn_indicated_exit = blkidxfn(&myblocks, cur_elmp->curcount, cur_elmp->orig_block, cur_elmp->loop_p->loop_params.bi_t.offset_array, el_type, cur_elmp->orig_offset,     /* blkidxfn adds offset */
                                                      segp->ptr, pieceparams);
                    break;
                case PF_INDEXED:
                    piecefn_indicated_exit = indexfn(&myblocks, cur_elmp->curcount, cur_elmp->loop_p->loop_params.i_t.blocksize_array, cur_elmp->loop_p->loop_params.i_t.offset_array, el_type, cur_elmp->orig_offset,  /* indexfn adds offset value */
                                                     segp->ptr, pieceparams);
                    break;
            }

            /* update local values based on piecefn returns (myblocks and
             * piecefn_indicated_exit)
             */
            MPIR_Assert(piecefn_indicated_exit >= 0);
            MPIR_Assert(myblocks >= 0);
            stream_off += myblocks * stream_el_size;

            /* myblocks of 0 or less than cur_elmp->curblock indicates
             * that we should stop processing and return.
             */
            if (myblocks == 0) {
                SEGMENT_SAVE_LOCAL_VALUES;
                return;
            } else if (myblocks < (MPI_Aint) (cur_elmp->curblock)) {
                cur_elmp->curoffset += myblocks * local_el_size;
                cur_elmp->curblock -= myblocks;

                SEGMENT_SAVE_LOCAL_VALUES;
                return;
            } else {    /* myblocks >= cur_elmp->curblock */

                MPI_Aint count_index = 0;

                /* this assumes we're either *just* processing the last parts
                 * of the current block, or we're processing as many blocks as
                 * we like starting at the beginning of one.
                 */

                switch (cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                    case MPII_DATALOOP_KIND_INDEXED:
                        while (myblocks > 0 && myblocks >= (MPI_Aint) (cur_elmp->curblock)) {
                            myblocks -= (MPI_Aint) (cur_elmp->curblock);
                            cur_elmp->curcount--;
                            MPIR_Assert(cur_elmp->curcount >= 0);

                            count_index = cur_elmp->orig_count - cur_elmp->curcount;
                            cur_elmp->curblock = STACKELM_INDEXED_BLOCKSIZE(cur_elmp, count_index);
                        }

                        if (cur_elmp->curcount == 0) {
                            /* don't bother to fill in values; we're popping anyway */
                            MPIR_Assert(myblocks == 0);
                            SEGMENT_POP_AND_MAYBE_EXIT;
                        } else {
                            cur_elmp->orig_block = cur_elmp->curblock;
                            cur_elmp->curoffset = cur_elmp->orig_offset +
                                STACKELM_INDEXED_OFFSET(cur_elmp, count_index);

                            cur_elmp->curblock -= myblocks;
                            cur_elmp->curoffset += myblocks * local_el_size;
                        }
                        break;
                    case MPII_DATALOOP_KIND_VECTOR:
                        /* this math relies on assertions at top of code block */
                        cur_elmp->curcount -= myblocks / (MPI_Aint) (cur_elmp->curblock);
                        if (cur_elmp->curcount == 0) {
                            MPIR_Assert(myblocks % ((MPI_Aint) (cur_elmp->curblock)) == 0);
                            SEGMENT_POP_AND_MAYBE_EXIT;
                        } else {
                            /* this math relies on assertions at top of code
                             * block
                             */
                            cur_elmp->curblock = cur_elmp->orig_block -
                                (myblocks % (MPI_Aint) (cur_elmp->curblock));
                            /* new offset = original offset +
                             *              stride * whole blocks +
                             *              leftover bytes
                             */
                            cur_elmp->curoffset = cur_elmp->orig_offset +
                                (((MPI_Aint) (cur_elmp->orig_count - cur_elmp->curcount)) *
                                 cur_elmp->loop_p->loop_params.v_t.stride) +
                                (((MPI_Aint) (cur_elmp->orig_block - cur_elmp->curblock)) *
                                 local_el_size);
                        }
                        break;
                    case MPII_DATALOOP_KIND_CONTIG:
                        /* contigs that reach this point have always been
                         * completely processed
                         */
                        MPIR_Assert(myblocks == (MPI_Aint) (cur_elmp->curblock) &&
                                    cur_elmp->curcount == 1);
                        SEGMENT_POP_AND_MAYBE_EXIT;
                        break;
                    case MPII_DATALOOP_KIND_BLOCKINDEXED:
                        while (myblocks > 0 && myblocks >= (MPI_Aint) (cur_elmp->curblock)) {
                            myblocks -= (MPI_Aint) (cur_elmp->curblock);
                            cur_elmp->curcount--;
                            MPIR_Assert(cur_elmp->curcount >= 0);

                            count_index = cur_elmp->orig_count - cur_elmp->curcount;
                            cur_elmp->curblock = cur_elmp->orig_block;
                        }
                        if (cur_elmp->curcount == 0) {
                            /* popping */
                            MPIR_Assert(myblocks == 0);
                            SEGMENT_POP_AND_MAYBE_EXIT;
                        } else {
                            /* cur_elmp->orig_block = cur_elmp->curblock; */
                            cur_elmp->curoffset = cur_elmp->orig_offset +
                                STACKELM_BLOCKINDEXED_OFFSET(cur_elmp, count_index);
                            cur_elmp->curblock -= myblocks;
                            cur_elmp->curoffset += myblocks * local_el_size;
                        }
                        break;
                }
            }

            if (piecefn_indicated_exit) {
                /* piece function indicated that we should quit processing */
                SEGMENT_SAVE_LOCAL_VALUES;
                return;
            }
        } /* end of if leaf */
        else if (cur_elmp->curblock == 0) {
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
            MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                            (MPL_DBG_FDEST, "\thit end of block; elmp=%x [%d]\n",
                             (unsigned) cur_elmp, cur_sp));
#endif
            cur_elmp->curcount--;

            /* new block.  for indexed and struct reset orig_block.
             * reset curblock for all types
             */
            switch (cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                case MPII_DATALOOP_KIND_CONTIG:
                case MPII_DATALOOP_KIND_VECTOR:
                case MPII_DATALOOP_KIND_BLOCKINDEXED:
                    break;
                case MPII_DATALOOP_KIND_INDEXED:
                    cur_elmp->orig_block =
                        STACKELM_INDEXED_BLOCKSIZE(cur_elmp,
                                                   cur_elmp->curcount ? cur_elmp->orig_count -
                                                   cur_elmp->curcount : 0);
                    break;
                case MPII_DATALOOP_KIND_STRUCT:
                    cur_elmp->orig_block =
                        STACKELM_STRUCT_BLOCKSIZE(cur_elmp,
                                                  cur_elmp->curcount ? cur_elmp->orig_count -
                                                  cur_elmp->curcount : 0);
                    break;
                default:
                    /* --BEGIN ERROR HANDLING-- */
                    MPIR_Assert(0);
                    break;
                    /* --END ERROR HANDLING-- */
            }
            cur_elmp->curblock = cur_elmp->orig_block;

            if (cur_elmp->curcount == 0) {
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
                MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                                (MPL_DBG_FDEST, "\talso hit end of count; elmp=%x [%d]\n",
                                 (unsigned) cur_elmp, cur_sp));
#endif
                SEGMENT_POP_AND_MAYBE_EXIT;
            }
        } else {        /* push the stackelm */

            MPII_Dataloop_stackelm *next_elmp;
            MPI_Aint count_index, block_index;

            count_index = cur_elmp->orig_count - cur_elmp->curcount;
            block_index = cur_elmp->orig_block - cur_elmp->curblock;

            /* reload the next stackelm if necessary */
            next_elmp = &(segp->stackelm[cur_sp + 1]);
            if (cur_elmp->may_require_reloading) {
                MPIR_Dataloop *load_dlp = NULL;
                switch (cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                    case MPII_DATALOOP_KIND_CONTIG:
                    case MPII_DATALOOP_KIND_VECTOR:
                    case MPII_DATALOOP_KIND_BLOCKINDEXED:
                    case MPII_DATALOOP_KIND_INDEXED:
                        load_dlp = cur_elmp->loop_p->loop_params.cm_t.dataloop;
                        break;
                    case MPII_DATALOOP_KIND_STRUCT:
                        load_dlp = STACKELM_STRUCT_DATALOOP(cur_elmp, count_index);
                        break;
                    default:
                        /* --BEGIN ERROR HANDLING-- */
                        MPIR_Assert(0);
                        break;
                        /* --END ERROR HANDLING-- */
                }

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
                MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                                (MPL_DBG_FDEST, "\tloading dlp=%x, elmp=%x [%d]\n",
                                 (unsigned) load_dlp, (unsigned) next_elmp, cur_sp + 1));
#endif

                MPII_Dataloop_stackelm_load(next_elmp, load_dlp, 1);
            }
#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
            MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                            (MPL_DBG_FDEST, "\tpushing type, elmp=%x [%d], count=%d, block=%d\n",
                             (unsigned) cur_elmp, cur_sp, count_index, block_index));
#endif
            /* set orig_offset and all cur values for new stackelm.
             * this is done in two steps: first set orig_offset based on
             * current stackelm, then set cur values based on new stackelm.
             */
            switch (cur_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                case MPII_DATALOOP_KIND_CONTIG:
                    next_elmp->orig_offset = cur_elmp->curoffset +
                        (MPI_Aint) block_index *cur_elmp->loop_p->el_extent;
                    break;
                case MPII_DATALOOP_KIND_VECTOR:
                    /* note: stride is in bytes */
                    next_elmp->orig_offset = cur_elmp->orig_offset +
                        (MPI_Aint) count_index *cur_elmp->loop_p->loop_params.v_t.stride +
                        (MPI_Aint) block_index *cur_elmp->loop_p->el_extent;
                    break;
                case MPII_DATALOOP_KIND_BLOCKINDEXED:
                    next_elmp->orig_offset = cur_elmp->orig_offset +
                        (MPI_Aint) block_index *cur_elmp->loop_p->el_extent +
                        STACKELM_BLOCKINDEXED_OFFSET(cur_elmp, count_index);
                    break;
                case MPII_DATALOOP_KIND_INDEXED:
                    next_elmp->orig_offset = cur_elmp->orig_offset +
                        (MPI_Aint) block_index *cur_elmp->loop_p->el_extent +
                        STACKELM_INDEXED_OFFSET(cur_elmp, count_index);
                    break;
                case MPII_DATALOOP_KIND_STRUCT:
                    next_elmp->orig_offset = cur_elmp->orig_offset +
                        (MPI_Aint) block_index *STACKELM_STRUCT_EL_EXTENT(cur_elmp,
                                                                          count_index) +
                        STACKELM_STRUCT_OFFSET(cur_elmp, count_index);
                    break;
                default:
                    /* --BEGIN ERROR HANDLING-- */
                    MPIR_Assert(0);
                    break;
                    /* --END ERROR HANDLING-- */
            }

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
            MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                            (MPL_DBG_FDEST,
                             "\tstep 1: next orig_offset = " MPI_AINT_FMT_DEC_SPEC " (0x"
                             MPI_AINT_FMT_HEX_SPEC ")\n", next_elmp->orig_offset,
                             next_elmp->orig_offset));
#endif

            switch (next_elmp->loop_p->kind & MPII_DATALOOP_KIND_MASK) {
                case MPII_DATALOOP_KIND_CONTIG:
                case MPII_DATALOOP_KIND_VECTOR:
                    next_elmp->curcount = next_elmp->orig_count;
                    next_elmp->curblock = next_elmp->orig_block;
                    next_elmp->curoffset = next_elmp->orig_offset;
                    break;
                case MPII_DATALOOP_KIND_BLOCKINDEXED:
                    next_elmp->curcount = next_elmp->orig_count;
                    next_elmp->curblock = next_elmp->orig_block;
                    next_elmp->curoffset = next_elmp->orig_offset +
                        STACKELM_BLOCKINDEXED_OFFSET(next_elmp, 0);
                    break;
                case MPII_DATALOOP_KIND_INDEXED:
                    next_elmp->curcount = next_elmp->orig_count;
                    next_elmp->curblock = STACKELM_INDEXED_BLOCKSIZE(next_elmp, 0);
                    next_elmp->curoffset = next_elmp->orig_offset +
                        STACKELM_INDEXED_OFFSET(next_elmp, 0);
                    break;
                case MPII_DATALOOP_KIND_STRUCT:
                    next_elmp->curcount = next_elmp->orig_count;
                    next_elmp->curblock = STACKELM_STRUCT_BLOCKSIZE(next_elmp, 0);
                    next_elmp->curoffset = next_elmp->orig_offset +
                        STACKELM_STRUCT_OFFSET(next_elmp, 0);
                    break;
                default:
                    /* --BEGIN ERROR HANDLING-- */
                    MPIR_Assert(0);
                    break;
                    /* --END ERROR HANDLING-- */
            }

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
            MPL_DBG_MSG_FMT(MPIR_DBG_DATATYPE, VERBOSE,
                            (MPL_DBG_FDEST,
                             "\tstep 2: next curoffset = " MPI_AINT_FMT_DEC_SPEC " (0x"
                             MPI_AINT_FMT_HEX_SPEC ")\n", next_elmp->curoffset,
                             next_elmp->curoffset));
#endif

            cur_elmp->curblock--;
            SEGMENT_PUSH;
        }       /* end of else push the stackelm */
    }   /* end of for (;;) */

#ifdef MPII_DATALOOP_DEBUG_MANIPULATE
    MPL_DBG_MSG("hit end of datatype\n");
#endif

    SEGMENT_SAVE_LOCAL_VALUES;
    return;
}
Exemplo n.º 2
0
/*@
  Dataloop_stream_size - return the size of the data described by the dataloop

Input Parameters:
+ dl_p   - pointer to dataloop for which we will return the size
- sizefn - function for determining size of types in the corresponding stream
           (passing NULL will instead result in el_size values being used)

@*/
DLOOP_Offset
PREPEND_PREFIX(Dataloop_stream_size)(struct DLOOP_Dataloop *dl_p,
				     DLOOP_Offset (*sizefn)(DLOOP_Type el_type))
{
    DLOOP_Offset tmp_sz, tmp_ct = 1;

    for (;;)
    {
        if ((dl_p->kind & DLOOP_KIND_MASK) == DLOOP_KIND_STRUCT)
        {
            int i;

            tmp_sz = 0;
            for (i = 0; i < dl_p->loop_params.s_t.count; i++)
            {
                tmp_sz += (DLOOP_Offset)(dl_p->loop_params.s_t.blocksize_array[i]) *
                    PREPEND_PREFIX(Dataloop_stream_size)(dl_p->loop_params.s_t.dataloop_array[i], sizefn);
            }
            return tmp_sz * tmp_ct;
        }

        switch (dl_p->kind & DLOOP_KIND_MASK) {
        case DLOOP_KIND_CONTIG:
            tmp_ct *= (DLOOP_Offset)(dl_p->loop_params.c_t.count);
#ifdef DLOOP_DEBUG_SIZE
            DLOOP_dbg_printf("stream_size: contig: ct = %d; new tot_ct = " DLOOP_OFFSET_FMT_DEC_SPEC "\n",
                             (int) dl_p->loop_params.c_t.count, (DLOOP_Offset) tmp_ct);
#endif
            break;
        case DLOOP_KIND_VECTOR:
            tmp_ct *= (DLOOP_Offset)(dl_p->loop_params.v_t.count) *
		      (DLOOP_Offset)(dl_p->loop_params.v_t.blocksize);
#ifdef DLOOP_DEBUG_SIZE
            DLOOP_dbg_printf("stream_size: vector: ct = %d; blk = %d; new tot_ct = " DLOOP_OFFSET_FMT_DEC_SPEC "\n",
                             (int) dl_p->loop_params.v_t.count,
                             (int) dl_p->loop_params.v_t.blocksize,
                             (DLOOP_Offset) tmp_ct);
#endif
            break;
        case DLOOP_KIND_BLOCKINDEXED:
            tmp_ct *= (DLOOP_Offset)(dl_p->loop_params.bi_t.count) *
		      (DLOOP_Offset)(dl_p->loop_params.bi_t.blocksize);
#ifdef DLOOP_DEBUG_SIZE
            DLOOP_dbg_printf("stream_size: blkindexed: blks = %d; new tot_ct = " DLOOP_OFFSET_FMT_DEC_SPEC "\n",
                             (int) dl_p->loop_params.bi_t.count *
                             (int) dl_p->loop_params.bi_t.blocksize,
                             (DLOOP_Offset) tmp_ct);
#endif
            break;
        case DLOOP_KIND_INDEXED:
            tmp_ct *= (DLOOP_Offset)(dl_p->loop_params.i_t.total_blocks);
#ifdef DLOOP_DEBUG_SIZE
            DLOOP_dbg_printf("stream_size: contig: blks = %d; new tot_ct = " DLOOP_OFFSET_FMT_DEC_SPEC "\n",
                             (int) dl_p->loop_params.i_t.total_blocks,
                             (DLOOP_Offset) tmp_ct);
#endif
            break;
        default:
            /* --BEGIN ERROR HANDLING-- */
            DLOOP_Assert(0);
            break;
            /* --END ERROR HANDLING-- */
        }

        if (dl_p->kind & DLOOP_FINAL_MASK) break;
        else {
            DLOOP_Assert(dl_p->loop_params.cm_t.dataloop != NULL);
            dl_p = dl_p->loop_params.cm_t.dataloop;
        }
    }

    /* call fn for size using bottom type, or use size if fnptr is NULL */
    tmp_sz = ((sizefn) ? sizefn(dl_p->el_type) : dl_p->el_size);

    return tmp_sz * tmp_ct;
}
Exemplo n.º 3
0
Arquivo: fold.c Projeto: oridb/mc
Node *
fold(Node *n, int foldvar)
{
	Node **args, *r;
	Type *t;
	vlong a, b;
	Ucon *uc;
	size_t i;

	if (!n)
		return NULL;
	if (n->type != Nexpr)
		return n;

	r = NULL;
	args = n->expr.args;
	if (n->expr.idx)
		n->expr.idx = fold(n->expr.idx, foldvar);
	for (i = 0; i < n->expr.nargs; i++)
		args[i] = fold(args[i], foldvar);
	switch (exprop(n)) {
	case Outag:
		if (exprop(args[0]) != Oucon)
			break;
		uc = finducon(tybase(exprtype(args[0])), args[0]->expr.args[0]);
		r = val(n->loc, uc->id, exprtype(n));
		break;
	case Oudata:
		if (exprop(args[0]) != Oucon || args[0]->expr.nargs != 2)
			break;
		r = args[0]->expr.args[1];
		break;
	case Ovar:
		if (foldvar && issmallconst(decls[n->expr.did]))
			r = fold(decls[n->expr.did]->decl.init, foldvar);
		break;
	case Oadd:
		/* x + 0 = 0 */
		if (isintval(args[0], 0))
			r = args[1];
		if (isintval(args[1], 0))
			r = args[0];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a + b, exprtype(n));
		break;
	case Osub:
		/* x - 0 = 0 */
		if (isintval(args[1], 0))
			r = args[0];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, (uint64_t)a - b, exprtype(n));
		break;
	case Omul:
		/* 1 * x = x */
		if (isintval(args[0], 1))
			r = args[1];
		if (isintval(args[1], 1))
			r = args[0];
		/* 0 * x = 0 */
		if (isintval(args[0], 0))
			r = args[0];
		if (isintval(args[1], 0))
			r = args[1];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a * b, exprtype(n));
		break;
	case Odiv:
		/* x/0 = error */
		if (isintval(args[1], 0))
			fatal(args[1], "division by zero");
		/* x/1 = x */
		if (isintval(args[1], 1))
			r = args[0];
		/* 0/x = 0 */
		if (isintval(args[1], 0))
			r = args[1];
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a / b, exprtype(n));
		break;
	case Omod:
		/* x%0 = error */
		if (isintval(args[1], 0))
			fatal(args[1], "division by zero");
		/* x%1 = 0 */
		if (isintval(args[1], 1))
			r = val(n->loc, 0, exprtype(n));
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a % b, exprtype(n));
		break;
	case Oneg:
		if (getintlit(args[0], &a))
			r = val(n->loc, -a, exprtype(n));
		break;
	case Obsl:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, (uint64_t)a << b, exprtype(n));
		break;
	case Obsr:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a >> b, exprtype(n));
		break;
	case Obor:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a | b, exprtype(n));
		break;
	case Oband:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a & b, exprtype(n));
		break;
	case Obxor:
		if (getintlit(args[0], &a) && getintlit(args[1], &b))
			r = val(n->loc, a ^ b, exprtype(n));
		break;
	case Omemb:
		t = tybase(exprtype(args[0]));
		/* we only fold lengths right now */
		if (t->type == Tyarray && !strcmp(namestr(args[1]), "len")) {
			r = t->asize;
			r->expr.type = exprtype(n);
		}
		break;
	case Oarr:
                if (n->expr.nargs > 0)
                    qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
		break;
	case Ocast:
		r = foldcast(n);
		break;
	case Osize:
		if (sizefn)
			r = val(n->loc, sizefn(n->expr.args[0]), exprtype(n));
		break;
	default:
		break;
	}

	if (r && n->expr.idx)
		r->expr.idx = n->expr.idx;

	if (r)
		return r;
	else
		return n;
}