📄 segment.c
字号:
DLOOP_dbg_printf("\thit leaf; cur_sp=%d, elmp=%x, piece_sz=%d\n", cur_sp, (unsigned) cur_elmp, myblocks * local_el_size);#endif /* enforce the last parameter if necessary by reducing myblocks */ if (last != SEGMENT_IGNORE_LAST && (stream_off + (myblocks * stream_el_size) > last)) { myblocks = ((last - stream_off) / stream_el_size);#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\tpartial block count=%d (%d bytes)\n", myblocks, (int) myblocks * stream_el_size);#endif if (myblocks == 0) { DLOOP_SEGMENT_SAVE_LOCAL_VALUES; return; } } /* call piecefn to perform data manipulation */ switch (piecefn_type) { case PF_NULL: piecefn_indicated_exit = 0;#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\tNULL piecefn for this piece\n");#endif break; case PF_CONTIG: DLOOP_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) */ DLOOP_Assert(piecefn_indicated_exit >= 0); DLOOP_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) { DLOOP_SEGMENT_SAVE_LOCAL_VALUES; return; } else if (myblocks < cur_elmp->curblock) { cur_elmp->curoffset += myblocks * local_el_size; cur_elmp->curblock -= myblocks; DLOOP_SEGMENT_SAVE_LOCAL_VALUES; return; } else /* myblocks >= cur_elmp->curblock */ { int 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 & DLOOP_KIND_MASK) { case DLOOP_KIND_INDEXED: while (myblocks > 0 && myblocks >= cur_elmp->curblock) { myblocks -= cur_elmp->curblock; cur_elmp->curcount--; DLOOP_Assert(cur_elmp->curcount >= 0); count_index = cur_elmp->orig_count - cur_elmp->curcount; cur_elmp->curblock = DLOOP_STACKELM_INDEXED_BLOCKSIZE(cur_elmp, count_index); } if (cur_elmp->curcount == 0) { /* don't bother to fill in values; we're popping anyway */ DLOOP_Assert(myblocks == 0); DLOOP_SEGMENT_POP_AND_MAYBE_EXIT; } else { cur_elmp->orig_block = cur_elmp->curblock; cur_elmp->curoffset = cur_elmp->orig_offset + DLOOP_STACKELM_INDEXED_OFFSET(cur_elmp, count_index); cur_elmp->curblock -= myblocks; cur_elmp->curoffset += myblocks * local_el_size; } break; case DLOOP_KIND_VECTOR: /* this math relies on assertions at top of code block */ cur_elmp->curcount -= myblocks / cur_elmp->curblock; if (cur_elmp->curcount == 0) { DLOOP_Assert(myblocks % cur_elmp->curblock == 0); DLOOP_SEGMENT_POP_AND_MAYBE_EXIT; } else { /* this math relies on assertions at top of code * block */ cur_elmp->curblock = cur_elmp->orig_block - (myblocks % cur_elmp->curblock); /* new offset = original offset + * stride * whole blocks + * leftover bytes */ cur_elmp->curoffset = cur_elmp->orig_offset + ((cur_elmp->orig_count - cur_elmp->curcount) * cur_elmp->loop_p->loop_params.v_t.stride) + ((cur_elmp->orig_block - cur_elmp->curblock) * local_el_size); } break; case DLOOP_KIND_CONTIG: /* contigs that reach this point have always been * completely processed */ DLOOP_Assert(myblocks == cur_elmp->curblock && cur_elmp->curcount == 1); DLOOP_SEGMENT_POP_AND_MAYBE_EXIT; break; case DLOOP_KIND_BLOCKINDEXED: while (myblocks > 0 && myblocks >= cur_elmp->curblock) { myblocks -= cur_elmp->curblock; cur_elmp->curcount--; DLOOP_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 */ DLOOP_Assert(myblocks == 0); DLOOP_SEGMENT_POP_AND_MAYBE_EXIT; } else { /* cur_elmp->orig_block = cur_elmp->curblock; */ cur_elmp->curoffset = cur_elmp->orig_offset + DLOOP_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 */ DLOOP_SEGMENT_SAVE_LOCAL_VALUES; return; } } /* end of if leaf */ else if (cur_elmp->curblock == 0) {#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\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 & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: case DLOOP_KIND_VECTOR: case DLOOP_KIND_BLOCKINDEXED: break; case DLOOP_KIND_INDEXED: cur_elmp->orig_block = DLOOP_STACKELM_INDEXED_BLOCKSIZE(cur_elmp, cur_elmp->curcount ? cur_elmp->orig_count - cur_elmp->curcount : 0); break; case DLOOP_KIND_STRUCT: cur_elmp->orig_block = DLOOP_STACKELM_STRUCT_BLOCKSIZE(cur_elmp, cur_elmp->curcount ? cur_elmp->orig_count - cur_elmp->curcount : 0); break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ } cur_elmp->curblock = cur_elmp->orig_block; if (cur_elmp->curcount == 0) {#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\talso hit end of count; elmp=%x [%d]\n", (unsigned) cur_elmp, cur_sp);#endif DLOOP_SEGMENT_POP_AND_MAYBE_EXIT; } } else /* push the stackelm */ { DLOOP_Dataloop_stackelm *next_elmp; int 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) { DLOOP_Dataloop *load_dlp = NULL; switch (cur_elmp->loop_p->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: case DLOOP_KIND_VECTOR: case DLOOP_KIND_BLOCKINDEXED: case DLOOP_KIND_INDEXED: load_dlp = cur_elmp->loop_p->loop_params.cm_t.dataloop; break; case DLOOP_KIND_STRUCT: load_dlp = DLOOP_STACKELM_STRUCT_DATALOOP(cur_elmp, count_index); break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ }#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\tloading dlp=%x, elmp=%x [%d]\n", (unsigned) load_dlp, (unsigned) next_elmp, cur_sp+1);#endif DLOOP_Stackelm_load(next_elmp, load_dlp, 1); }#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\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 & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: next_elmp->orig_offset = cur_elmp->curoffset + block_index * cur_elmp->loop_p->el_extent; break; case DLOOP_KIND_VECTOR: /* note: stride is in bytes */ next_elmp->orig_offset = cur_elmp->orig_offset + count_index * cur_elmp->loop_p->loop_params.v_t.stride + block_index * cur_elmp->loop_p->el_extent; break; case DLOOP_KIND_BLOCKINDEXED: next_elmp->orig_offset = cur_elmp->orig_offset + block_index * cur_elmp->loop_p->el_extent + DLOOP_STACKELM_BLOCKINDEXED_OFFSET(cur_elmp, count_index); break; case DLOOP_KIND_INDEXED: next_elmp->orig_offset = cur_elmp->orig_offset + block_index * cur_elmp->loop_p->el_extent + DLOOP_STACKELM_INDEXED_OFFSET(cur_elmp, count_index); break; case DLOOP_KIND_STRUCT: next_elmp->orig_offset = cur_elmp->orig_offset + block_index * DLOOP_STACKELM_STRUCT_EL_EXTENT(cur_elmp, count_index) + DLOOP_STACKELM_STRUCT_OFFSET(cur_elmp, count_index); break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ }#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\tstep 1: next orig_offset = %d (0x%x)\n", next_elmp->orig_offset, next_elmp->orig_offset);#endif switch (next_elmp->loop_p->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: case DLOOP_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 DLOOP_KIND_BLOCKINDEXED: next_elmp->curcount = next_elmp->orig_count; next_elmp->curblock = next_elmp->orig_block; next_elmp->curoffset = next_elmp->orig_offset + DLOOP_STACKELM_BLOCKINDEXED_OFFSET(next_elmp, 0); break; case DLOOP_KIND_INDEXED: next_elmp->curcount = next_elmp->orig_count; next_elmp->curblock = DLOOP_STACKELM_INDEXED_BLOCKSIZE(next_elmp, 0); next_elmp->curoffset = next_elmp->orig_offset + DLOOP_STACKELM_INDEXED_OFFSET(next_elmp, 0); break; case DLOOP_KIND_STRUCT: next_elmp->curcount = next_elmp->orig_count; next_elmp->curblock = DLOOP_STACKELM_STRUCT_BLOCKSIZE(next_elmp, 0); next_elmp->curoffset = next_elmp->orig_offset + DLOOP_STACKELM_STRUCT_OFFSET(next_elmp, 0); break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ }#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("\tstep 2: next curoffset = %d (0x%x)\n", next_elmp->curoffset, next_elmp->curoffset);#endif cur_elmp->curblock--; DLOOP_SEGMENT_PUSH; } /* end of else push the stackelm */ } /* end of for (;;) */#ifdef DLOOP_DEBUG_MANIPULATE DLOOP_dbg_printf("hit end of datatype\n");#endif DLOOP_SEGMENT_SAVE_LOCAL_VALUES; return;}/* DLOOP_Stackelm_blocksize - returns block size for stackelm based on current * count in stackelm. * * NOTE: loop_p, orig_count, and curcount members of stackelm MUST be correct * before this is called! * */static inline DLOOP_Count DLOOP_Stackelm_blocksize(struct DLOOP_Dataloop_stackelm *elmp){ struct DLOOP_Dataloop *dlp = elmp->loop_p; switch(dlp->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_CONTIG: /* NOTE: we're dropping the count into the * blksize field for contigs, as described * in the init call. */ return dlp->loop_params.c_t.count; break; case DLOOP_KIND_VECTOR: return dlp->loop_params.v_t.blocksize; break; case DLOOP_KIND_BLOCKINDEXED: return dlp->loop_params.bi_t.blocksize; break; case DLOOP_KIND_INDEXED: return dlp->loop_params.i_t.blocksize_array[elmp->orig_count - elmp->curcount]; break; case DLOOP_KIND_STRUCT: return dlp->loop_params.s_t.blocksize_array[elmp->orig_count - elmp->curcount]; break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ } return -1;}/* DLOOP_Stackelm_offset - returns starting offset (displacement) for stackelm * based on current count in stackelm. * * NOTE: loop_p, orig_count, and curcount members of stackelm MUST be correct * before this is called! * * also, this really is only good at init time for vectors and contigs * (all the time for indexed) at the moment. * */static inline DLOOP_Offset DLOOP_Stackelm_offset(struct DLOOP_Dataloop_stackelm *elmp){ struct DLOOP_Dataloop *dlp = elmp->loop_p; switch(dlp->kind & DLOOP_KIND_MASK) { case DLOOP_KIND_VECTOR: case DLOOP_KIND_CONTIG: return 0; break; case DLOOP_KIND_BLOCKINDEXED: return dlp->loop_params.bi_t.offset_array[elmp->orig_count - elmp->curcount]; break; case DLOOP_KIND_INDEXED: return dlp->loop_params.i_t.offset_array[elmp->orig_count - elmp->curcount]; break; case DLOOP_KIND_STRUCT: return dlp->loop_params.s_t.offset_array[elmp->orig_count - elmp->curcount]; break; default: /* --BEGIN ERROR HANDLING-- */ DLOOP_Assert(0); break; /* --END ERROR HANDLING-- */ } return -1;}/* DLOOP_Stackelm_load * loop_p, orig_count, orig_block, and curcount are all filled by us now. * the rest are filled in at processing time. */static inline void DLOOP_Stackelm_load(struct DLOOP_Dataloop_stackelm *elmp, struct DLOOP_Dataloop *dlp, int branch_flag){ elmp->loop_p = dlp; if ((dlp->kind & DLOOP_KIND_MASK) == DLOOP_KIND_CONTIG) { elmp->orig_count = 1; /* put in blocksize instead */ } else { elmp->orig_count = dlp->loop_params.count; } if (branch_flag || (dlp->kind & DLOOP_KIND_MASK) == DLOOP_KIND_STRUCT) { elmp->may_require_reloading = 1; } else { elmp->may_require_reloading = 0; } /* required by DLOOP_Stackelm_blocksize */ elmp->curcount = elmp->orig_count; elmp->orig_block = DLOOP_Stackelm_blocksize(elmp); /* TODO: GO AHEAD AND FILL IN CURBLOCK? */}/* * Local variables: * c-indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -