nb_kernel010nf_ia64_single.s
来自「最著名最快的分子模拟软件」· S 代码 · 共 795 行 · 第 1/2 页
S
795 行
mov JINDEX = In_JINDEX fadd fTWELVE = fSIX, fSIX } ;; // INIT 10 { .mfi ld8 OuterIter = [argPtr], INNERITER_STK_OFFSET - OUTERITER_STK_OFFSET nop 0x0 nop 0x0 } ;;// INIT 11 { .mfi ld8 InnerIter = [argPtr] nop 0x0 nop 0x0 } ;;// 18 bundles used for init - still aligned. threadLoop_nf:// THREAD PROLOGUE 1 { .mfi fetchadd4.rel NN0 = [COUNT], THREAD_CHUNK_SIZE nop 0x0 nop 0x0 } { .mfi setf.sig f33 = NTYPE nop 0x0 nop 0x0 } ;; // THREAD PROLOGUE 2 - at least 12 cycle latency hole before this bundle (fetchadd4) { .mmi cmp.lt pCont, pDone = NN0, NRI shladd gidPtr = NN0, 2, GID adds NN1 = THREAD_CHUNK_SIZE, NN0 } { .mmi shladd jindexPtr = NN0, 2, JINDEX shladd shiftPtr = NN0, 2, SHIFT shladd iinrPtr = NN0, 2, IINR } ;; // THREAD PROLOGUE 3 { .mmi (pCont) ld4 II = [iinrPtr], 4 (pCont) ld4 IS = [shiftPtr], 4 cmp.ge pLast, pMore = NN1, NRI } { .mib (pCont) ld4 NJ0 = [jindexPtr], 4 (pCont) adds Tmp2 = 1, NN0 (pDone) br.cond.spnt.few finish_nf } ;; // THREAD PROLOGUE 4 { .mmi ld4 ggid = [gidPtr], 4 shladd II3 = II, 1, II shladd IS3 = IS, 1, IS } { .mfi ld4 NJ1 = [jindexPtr], 4 nop 0x0 shladd jjnrPtr = NJ0, 2, JJNR } ;;// THREAD PROLOGUE 5 { .mmi cmp.lt pCont, pDone = Tmp2, NRI nop 0x0 shladd typePtr = II, 2, TYPE } { .mmi shladd posPtr = II3, 2, POSITION nop 0x0 shladd shiftVPtr = IS3, 2, SHIFTVEC } ;;// THREAD PROLOGUE 6 { .mmi ld4 jnr = [jjnrPtr], 4 (pCont) ld4 IS = [shiftPtr], 4 nop 0x0 } { .mmi (pCont) ld4 II = [iinrPtr], 4 ld4 NTI = [typePtr] (pLast) mov NN1 = NRI } ;;// 12 bundles in thread prologue - still alignedouterLoop_nf: // At this point in the outer loop, the following values are ready // // FActII Pointer to FACTION XYZ for II // FShiftIS Pointer to FSHIFT XYZ for IS // shiftVPtr Pointer to current shift XYZ values // posPtr Pointer to current XYZ position // chargePtr Pointer to current atom charge // ggid Index for Vc array // jjnr Pointer to next neighbor index // jnr Current jnr value // NJ0, NJ1 Bounds of current neighbor list // // Load up all the floating-point values (yes, McKinley can do 4 FP loads // per cycle) and initialize the loop counters and predicates. Compute // the initial position <x, y, z> and charge. If this isn't the last time // through the loop, start loading the next value for NJ1 - we already // moved the previous NJ1 -> NJ0.// OUTER PROLOGUE 1 { .mfi nop 0x0 nop 0x0 nop 0x0 } { .mmf ldfs shX = [shiftVPtr], 4 ldfs PosX = [posPtr], 4 nop 0x0 } ;;// OUTER PROLOGUE 2 { .mmi setf.sig f32 = NTI ldfs shY = [shiftVPtr], 4 nop 0x0 } { .mii ldfs PosY = [posPtr], 4 add Nouter = 1, Nouter sub InnerCnt = NJ1, NJ0, 1 } ;;// OUTER PROLOGUE 3 { .mmf ldfs shZ = [shiftVPtr] ldfs PosZ = [posPtr] nop 0x0 } { .mmi nop 0x0 nop 0x0 shladd VNBPtr = ggid, 2, VNB } ;;// OUTER PROLOGUE 4 { .mmf nop 0x0 nop 0x0 xma.l f32 = f32, f33, fZero };;// OUTER PROLOGUE 5 { .mmi nop 0x0 nop 0x0 mov NJ0 = NJ1 } ;;// OUTER PROLOGUE 6 { .mfi ldfs VNBTotal = [VNBPtr] fadd IX = shX, PosX add NN0 = 1, NN0 } { .mfi (pCont) ld4 NJ1 = [jindexPtr], 4 // This may seem strange, but we set the first stage of the // pipe to execute this way because setting pr.rot doesn't take // into account how much the predicates have rotated. If this is // the first time through, we cleared all the pipeline predicates // in the initialization. If not, flushing the pipeline set all // the pipeline predicates to 0 cmp.eq pPipe[0], p0 = zero, zero } ;;// OUTER PROLOGUE 7 { .mfi cmp.lt pCont, pDone = NN0, NN1 fadd IY = shY, PosY mov ar.lc = InnerCnt } ;;// OUTER PROLOGUE 8 { .mfi getf.sig NTI = f32 fadd IZ = shZ, PosZ mov ar.ec = PIPE_DEPTH } ;;// 12 bundles in outer loop - still aligned. // The inner loop is a 6-stage pipeline. The serial sequence of float ops // is folded into a 17-cycle loop (17 * 2 = 34 float ops, one empty), // then divided // into 5 stages. innerLoop_nf:// INNER LOOP 1 { .mfi nop 0x0 (pPipe[2]) fsub DY[2] = IY, DY[2] (pPipe[0]) shladd jnr3 = jnr, 1, jnr } // We march through jjnr[] sequentially, so it's usually a good idea // to preload the next value. However, we don't want to do this if // (1) we're in the epilogue or (2) this is the last time through and // there are no more atoms to inspect. Thus, we keep track of the loop // trip and use the logic below to see if we should load ahead .pred.rel "mutex", pCont, pDone { .mfi (pCont) cmp.ge pJJNR, p0 = InnerCnt, zero (pPipe[4]) frcpa RInv2[0], p0 = fOne, RSqr[2] (pDone) cmp.gt pJJNR, p0 = InnerCnt, zero } ;;// INNER LOOP 2 { .mfi (pPipe[1]) ld4 TypeJ[1] = [TypeJ[1]] (pPipe[2]) fsub DZ[2] = IZ, DZ[2] (pPipe[0]) add InnerCnt = -1, InnerCnt } { .mfi (pPipe[0]) shladd posPtr = jnr3, 2, POSITION (pPipe[5]) fma RInv2Err[1] = RInv2Err[1], RInv2Err[1], RInv2Err[1] (pPipe[0]) add Ninner = 1, Ninner } ;;// INNER LOOP 3 { .mfi (pPipe[0]) ldfs JX = [posPtr], 4 (pPipe[6]) fmpy RInv6[0] = RInv2[2], RInv2[2] (pPipe[0]) shladd TypeJ[0] = jnr, 2, TYPE } { .mfi (pJJNR) ld4 jnr = [jjnrPtr], 4 (pPipe[7]) fnma VNBTotal = C6[5], RInv6[1], VNBTotal nop 0x0 } ;;// INNER LOOP 4 { .mfi (pPipe[0]) ldfs JY = [posPtr], 4 (pPipe[2]) fmpy RSqr[0] = DX[2], DX[2] nop 0x0 } { .mfi nop 0x0 (pPipe[7]) fmpy RInv6[1] = RInv6[1], RInv6[1] (pPipe[2]) add TypeJ[2] = NTI, TypeJ[2] } ;;// INNER LOOP 5 { .mfi (pPipe[0]) ldfs JZ = [posPtr], 4 (pPipe[4]) fnma RInv2Err[0] = RInv2[0], RSqr[2], fOne (pJJNR) add jjnrPtr = JJNR_PREFETCH_DISTANCE, jjnrPtr } { .mfi nop 0x0 (pPipe[3]) fma RSqr[1] = DZ[3], DZ[3], RSqr[1] nop 0x0 } ;;// INNER LOOP 6 { .mfi nop 0x0 (pPipe[5]) fma.s RInv2[1] = RInv2[1], RInv2Err[1], RInv2[1] nop 0x0 } { .mfi nop 0x0 nop 0x0 (pPipe[2]) shladd TypeJ[2] = TypeJ[2], 3, NBFP } ;;// INNER LOOP 7 { .mfi (pJJNR) lfetch.nta [jjnrPtr] (pPipe[6]) fmpy RInv6[0] = RInv6[0], RInv2[2] nop 0x0 } { .mfi (pPipe[2]) ldfs C6[0] = [TypeJ[2]], 4 (pPipe[1]) fsub DX[1] = IX, DX[1] nop 0x0 } ;;// INNER LOOP 8 { .mfi (pPipe[2]) ldfs C12[0] = [TypeJ[2]] (pPipe[7]) fma VNBTotal = C12[5], RInv6[1], VNBTotal (pJJNR) add jjnrPtr = -JJNR_PREFETCH_DISTANCE, jjnrPtr } { .mfb nop 0x0 (pPipe[2]) fma RSqr[0] = DY[2], DY[2], RSqr[0] br.ctop.sptk.many innerLoop_nf } ;;// End of modulo-scheduled inner loop // Having finshed the loop, we now compute various quantities to // store. In paralllel, start computing computing some of the values // for the next loop trip, if we're going there.// OUTER EPILOGUE 1 { .mfi (pCont) shladd typePtr = II, 2, TYPE fnorm.s VNBTotal = VNBTotal (pCont) shladd II3 = II, 1, II } { .mfi nop 0x0 nop 0x0 (pCont) shladd IS3 = IS, 1, IS } ;;// OUTER EPILOGUE 2 { .mfi (pCont) ld4 IS = [shiftPtr], 4 nop 0x0 nop 0x0 } { .mmf (pCont) setf.sig f33 = NTYPE (pCont) ld4 II = [iinrPtr] ,4 nop 0x0 } ;;// OUTER EPILOGUE 3 { .mfi (pCont) ld4 NTI = [typePtr] nop 0x0 (pCont) shladd shiftVPtr = IS3, 2, SHIFTVEC } { .mfi nop 0x0 nop 0x0 (pCont) shladd posPtr = II3, 2, POSITION } ;;// OUTER EPILOGUE 5 { .mmb stfs [VNBPtr] = VNBTotal (pCont) ld4 ggid = [gidPtr], 4 (pCont) br.cond.sptk.many outerLoop_nf } ;; // Finish if this was the last chunk, or do another thread-loop iteration// THREAD EPILOGUE 1 { .mib nop 0x0 nop 0x0 (pMore) br.cond.sptk.many threadLoop_nf } ;; // Ready to exit - restore the floating-point registers we saved, the // loop counter, and the predicates, then we're done. Note that the // stack pointer has the address of the last saved FP register.finish_nf:// EXIT 1 { .mmi mov fillP0 = sp add fillP1 = 16, sp mov ar.lc = LCSave } { .mmi st4 [OuterIter] = Nouter st4 [InnerIter] = Ninner nop 0x0 } ;;// EXIT 2 { .mmi ldf.fill fs4 = [fillP0], 32 ldf.fill fs3 = [fillP1], 32 mov pr = PRSave, 0x1ffff } ;;// EXIT 3 { .mmi ldf.fill fs2 = [fillP0], 32 ldf.fill fs1 = [fillP1], 32 add sp = 4 * 16, sp } ;;// EXIT 4 { .mmb ldf.fill fs0 = [fillP0] nop 0x0 br.ret.sptk.few rp } ;; .endp nb_kernel010nf_ia64_single
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?