github.com/gopherd/gonum@v0.0.4/internal/asm/f32/ddotinc_amd64.s (about)

     1  // Copyright ©2017 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build !noasm,!gccgo,!safe
     6  
     7  #include "textflag.h"
     8  
     9  #define X_PTR SI
    10  #define Y_PTR DI
    11  #define LEN CX
    12  #define TAIL BX
    13  #define INC_X R8
    14  #define INCx3_X R10
    15  #define INC_Y R9
    16  #define INCx3_Y R11
    17  #define SUM X0
    18  #define P_SUM X1
    19  
    20  // func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64)
    21  TEXT ·DdotInc(SB), NOSPLIT, $0
    22  	MOVQ x_base+0(FP), X_PTR  // X_PTR = &x
    23  	MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y
    24  	MOVQ n+48(FP), LEN        // LEN = n
    25  	PXOR SUM, SUM             // SUM = 0
    26  	CMPQ LEN, $0
    27  	JE   dot_end
    28  
    29  	MOVQ ix+72(FP), INC_X        // INC_X = ix
    30  	MOVQ iy+80(FP), INC_Y        // INC_Y = iy
    31  	LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(x[ix])
    32  	LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(y[iy])
    33  
    34  	MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(float32)
    35  	SHLQ $2, INC_X
    36  	MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(float32)
    37  	SHLQ $2, INC_Y
    38  
    39  	MOVQ LEN, TAIL
    40  	ANDQ $3, TAIL  // TAIL = LEN % 4
    41  	SHRQ $2, LEN   // LEN = floor( LEN / 4 )
    42  	JZ   dot_tail  // if LEN == 0 { goto dot_tail }
    43  
    44  	PXOR P_SUM, P_SUM              // P_SUM = 0  for pipelining
    45  	LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3
    46  	LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3
    47  
    48  dot_loop: // Loop unrolled 4x  do {
    49  	CVTSS2SD (X_PTR), X2            // X_i = x[i:i+1]
    50  	CVTSS2SD (X_PTR)(INC_X*1), X3
    51  	CVTSS2SD (X_PTR)(INC_X*2), X4
    52  	CVTSS2SD (X_PTR)(INCx3_X*1), X5
    53  
    54  	CVTSS2SD (Y_PTR), X6            // X_j = y[i:i+1]
    55  	CVTSS2SD (Y_PTR)(INC_Y*1), X7
    56  	CVTSS2SD (Y_PTR)(INC_Y*2), X8
    57  	CVTSS2SD (Y_PTR)(INCx3_Y*1), X9
    58  
    59  	MULSD X6, X2 // X_i *= X_j
    60  	MULSD X7, X3
    61  	MULSD X8, X4
    62  	MULSD X9, X5
    63  
    64  	ADDSD X2, SUM   // SUM += X_i
    65  	ADDSD X3, P_SUM
    66  	ADDSD X4, SUM
    67  	ADDSD X5, P_SUM
    68  
    69  	LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X * 4])
    70  	LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y * 4])
    71  
    72  	DECQ LEN
    73  	JNZ  dot_loop // } while --LEN > 0
    74  
    75  	ADDSD P_SUM, SUM // SUM += P_SUM
    76  	CMPQ  TAIL, $0   // if TAIL == 0 { return }
    77  	JE    dot_end
    78  
    79  dot_tail: // do {
    80  	CVTSS2SD (X_PTR), X2  // X2 = x[i]
    81  	CVTSS2SD (Y_PTR), X3  // X2 *= y[i]
    82  	MULSD    X3, X2
    83  	ADDSD    X2, SUM      // SUM += X2
    84  	ADDQ     INC_X, X_PTR // X_PTR += INC_X
    85  	ADDQ     INC_Y, Y_PTR // Y_PTR += INC_Y
    86  	DECQ     TAIL
    87  	JNZ      dot_tail     // } while --TAIL > 0
    88  
    89  dot_end:
    90  	MOVSD SUM, sum+88(FP) // return SUM
    91  	RET