Skip to content

cmd/6g: range loops are slower than handmade loops #3909

Closed
@remyoudompheng

Description

@remyoudompheng
1. What is a short input program that triggers the error?

package p

import (
    "testing"
)

var slice = make([]byte, 256)

func loop() (t byte) {
    for i := 0; i < len(slice); i++ {
        t ^= slice[i]
    }
    return
}

func rangeloop() (t byte) {
    for _, b := range slice {
        t ^= b
    }
    return
}

func BenchmarkLoop(b *testing.B) {
    for i := 0; i < b.N; i++ {
        loop()
    }
}

func BenchmarkRange(b *testing.B) {
    for i := 0; i < b.N; i++ {
        rangeloop()
    }
}


2. What is the full compiler output?

GOARCH=386:
BenchmarkLoop    1000000          1239 ns/op
BenchmarkRange   5000000           695 ns/op

The generated range code is nearly optimal:

--- prog list "rangeloop" ---
[...]
0032 (loop_test.go:17) LEAL    autotmp_0005+-12(SP),BX
0033 (loop_test.go:17) MOVL    (BX),CX
0034 (loop_test.go:17) JMP     ,36
0035 (loop_test.go:17) INCL    ,AX
0036 (loop_test.go:17) CMPL    AX,SI
0037 (loop_test.go:17) JGE     $0,42
0038 (loop_test.go:17) MOVBLZX (CX),BP
0039 (loop_test.go:17) INCL    ,CX
0040 (loop_test.go:18) XORB    BP,t+0(FP)
0041 (loop_test.go:17) JMP     ,35
0042 (loop_test.go:20) RET     ,

GOARCH=amd64:
BenchmarkLoop    5000000           341 ns/op
BenchmarkRange   5000000           533 ns/op

The generate code for the loop body is quite shocking:

--- prog list "rangeloop" ---
[...]
0031 (loop_test.go:17) LEAQ    autotmp_0000+-16(SP),BX
0032 (loop_test.go:17) MOVQ    (BX),CX
0033 (loop_test.go:17) JMP     ,35
0034 (loop_test.go:17) INCL    ,AX
0035 (loop_test.go:17) MOVL    DI,BP
0036 (loop_test.go:17) CMPL    AX,DI
0037 (loop_test.go:17) JGE     ,49
0038 (loop_test.go:17) MOVQ    CX,BX
0039 (loop_test.go:17) MOVB    (CX),BP
0040 (loop_test.go:17) MOVB    BP,SI
0041 (loop_test.go:17) MOVB    SI,BX
0042 (loop_test.go:17) MOVB    BX,DX // 4 mov to do MOVB (CX), DX ?
0043 (loop_test.go:17) INCQ    ,CX
0044 (loop_test.go:17) MOVQ    CX,BX // BX is clobbered below
0045 (loop_test.go:18) MOVB    DX,BX
0046 (loop_test.go:18) XORB    BX,R8
0047 (loop_test.go:18) MOVB    R8,t+0(FP)
0048 (loop_test.go:17) JMP     ,34
0049 (loop_test.go:20) RET     ,


3. What version of the compiler are you using?  (Run it with the -V flag.)

$ /usr/bin/go tool 6g -V
6g version go1.0.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions