github.com/gopherd/gonum@v0.0.4/internal/asm/f32/ddotunitary_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 HADDPD_SUM_SUM    LONG $0xC07C0F66 // @ HADDPD X0, X0
    10  
    11  #define X_PTR SI
    12  #define Y_PTR DI
    13  #define LEN CX
    14  #define TAIL BX
    15  #define IDX AX
    16  #define SUM X0
    17  #define P_SUM X1
    18  
    19  // func DdotUnitary(x, y []float32) (sum float32)
    20  TEXT ·DdotUnitary(SB), NOSPLIT, $0
    21  	MOVQ    x_base+0(FP), X_PTR  // X_PTR = &x
    22  	MOVQ    y_base+24(FP), Y_PTR // Y_PTR = &y
    23  	MOVQ    x_len+8(FP), LEN     // LEN = min( len(x), len(y) )
    24  	CMPQ    y_len+32(FP), LEN
    25  	CMOVQLE y_len+32(FP), LEN
    26  	PXOR    SUM, SUM             // psum = 0
    27  	CMPQ    LEN, $0
    28  	JE      dot_end
    29  
    30  	XORQ IDX, IDX
    31  	MOVQ Y_PTR, DX
    32  	ANDQ $0xF, DX    // Align on 16-byte boundary for ADDPS
    33  	JZ   dot_no_trim // if DX == 0 { goto dot_no_trim }
    34  
    35  	SUBQ $16, DX
    36  
    37  dot_align: // Trim first value(s) in unaligned buffer  do {
    38  	CVTSS2SD (X_PTR)(IDX*4), X2 // X2 = float64(x[i])
    39  	CVTSS2SD (Y_PTR)(IDX*4), X3 // X3 = float64(y[i])
    40  	MULSD    X3, X2
    41  	ADDSD    X2, SUM            // SUM += X2
    42  	INCQ     IDX                // IDX++
    43  	DECQ     LEN
    44  	JZ       dot_end            // if --TAIL == 0 { return }
    45  	ADDQ     $4, DX
    46  	JNZ      dot_align          // } while --LEN > 0
    47  
    48  dot_no_trim:
    49  	PXOR P_SUM, P_SUM   // P_SUM = 0  for pipelining
    50  	MOVQ LEN, TAIL
    51  	ANDQ $0x7, TAIL     // TAIL = LEN % 8
    52  	SHRQ $3, LEN        // LEN = floor( LEN / 8 )
    53  	JZ   dot_tail_start // if LEN == 0 { goto dot_tail_start }
    54  
    55  dot_loop: // Loop unrolled 8x  do {
    56  	CVTPS2PD (X_PTR)(IDX*4), X2   // X_i = x[i:i+1]
    57  	CVTPS2PD 8(X_PTR)(IDX*4), X3
    58  	CVTPS2PD 16(X_PTR)(IDX*4), X4
    59  	CVTPS2PD 24(X_PTR)(IDX*4), X5
    60  
    61  	CVTPS2PD (Y_PTR)(IDX*4), X6   // X_j = y[i:i+1]
    62  	CVTPS2PD 8(Y_PTR)(IDX*4), X7
    63  	CVTPS2PD 16(Y_PTR)(IDX*4), X8
    64  	CVTPS2PD 24(Y_PTR)(IDX*4), X9
    65  
    66  	MULPD X6, X2 // X_i *= X_j
    67  	MULPD X7, X3
    68  	MULPD X8, X4
    69  	MULPD X9, X5
    70  
    71  	ADDPD X2, SUM   // SUM += X_i
    72  	ADDPD X3, P_SUM
    73  	ADDPD X4, SUM
    74  	ADDPD X5, P_SUM
    75  
    76  	ADDQ $8, IDX  // IDX += 8
    77  	DECQ LEN
    78  	JNZ  dot_loop // } while --LEN > 0
    79  
    80  	ADDPD P_SUM, SUM // SUM += P_SUM
    81  	CMPQ  TAIL, $0   // if TAIL == 0 { return }
    82  	JE    dot_end
    83  
    84  dot_tail_start:
    85  	MOVQ TAIL, LEN
    86  	SHRQ $1, LEN
    87  	JZ   dot_tail_one
    88  
    89  dot_tail_two:
    90  	CVTPS2PD (X_PTR)(IDX*4), X2 // X_i = x[i:i+1]
    91  	CVTPS2PD (Y_PTR)(IDX*4), X6 // X_j = y[i:i+1]
    92  	MULPD    X6, X2             // X_i *= X_j
    93  	ADDPD    X2, SUM            // SUM += X_i
    94  	ADDQ     $2, IDX            // IDX += 2
    95  	DECQ     LEN
    96  	JNZ      dot_tail_two       // } while --LEN > 0
    97  
    98  	ANDQ $1, TAIL
    99  	JZ   dot_end
   100  
   101  dot_tail_one:
   102  	CVTSS2SD (X_PTR)(IDX*4), X2 // X2 = float64(x[i])
   103  	CVTSS2SD (Y_PTR)(IDX*4), X3 // X3 = float64(y[i])
   104  	MULSD    X3, X2             // X2 *= X3
   105  	ADDSD    X2, SUM            // SUM += X2
   106  
   107  dot_end:
   108  	HADDPD_SUM_SUM        // SUM = \sum{ SUM[i] }
   109  	MOVSD SUM, sum+48(FP) // return SUM
   110  	RET