mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: optimize signed non-negative div/mod by a power of 2
This CL optimizes assembly for len() or cap() division
by a power of 2 constants:
func lenDiv(s []int) int {
return len(s) / 16
}
amd64 assembly before the CL:
MOVQ "".s+16(SP), AX
MOVQ AX, CX
SARQ $63, AX
SHRQ $60, AX
ADDQ CX, AX
SARQ $4, AX
MOVQ AX, "".~r1+32(SP)
RET
amd64 assembly after the CL:
MOVQ "".s+16(SP), AX
SHRQ $4, AX
MOVQ AX, "".~r1+32(SP)
RET
The CL relies on the fact that len() and cap() result cannot
be negative.
Trigger stats for the added SSA rules on linux/amd64 when running
make.bash:
46 Div64
12 Mod64
The added SSA rules may trigger on more cases in the future
when SSA values will be populated with the info on their
lower bounds.
For instance:
func f(i int16) int16 {
if i < 3 {
return -1
}
// Lower bound of i is 3 here -> i is non-negative,
// so unsigned arithmetics may be used here.
return i % 16
}
Change-Id: I8bc6be5a03e71157ced533c01416451ff6f1a7f0
Reviewed-on: https://go-review.googlesource.com/65530
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
2e8545531e
commit
0011cfbe2b
3 changed files with 331 additions and 0 deletions
|
|
@ -1140,6 +1140,58 @@ var linuxAMD64Tests = []*asmTest{
|
|||
`,
|
||||
pos: []string{"\tSETHI\t\\("},
|
||||
},
|
||||
// Check that len() and cap() div by a constant power of two
|
||||
// are compiled into SHRQ.
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return len(a) / 1024
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRQ\t\\$10,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(s string) int {
|
||||
return len(s) / (4097 >> 1)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRQ\t\\$11,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return cap(a) / ((1 << 11) + 2048)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRQ\t\\$12,"},
|
||||
},
|
||||
// Check that len() and cap() mod by a constant power of two
|
||||
// are compiled into ANDQ.
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return len(a) % 1024
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDQ\t\\$1023,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(s string) int {
|
||||
return len(s) % (4097 >> 1)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDQ\t\\$2047,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return cap(a) % ((1 << 11) + 2048)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDQ\t\\$4095,"},
|
||||
},
|
||||
}
|
||||
|
||||
var linux386Tests = []*asmTest{
|
||||
|
|
@ -1219,6 +1271,58 @@ var linux386Tests = []*asmTest{
|
|||
}`,
|
||||
pos: []string{"\tADDL\t[$]-19", "\tIMULL"}, // (n-19)*a
|
||||
},
|
||||
// Check that len() and cap() div by a constant power of two
|
||||
// are compiled into SHRL.
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return len(a) / 1024
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRL\t\\$10,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(s string) int {
|
||||
return len(s) / (4097 >> 1)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRL\t\\$11,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return cap(a) / ((1 << 11) + 2048)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tSHRL\t\\$12,"},
|
||||
},
|
||||
// Check that len() and cap() mod by a constant power of two
|
||||
// are compiled into ANDL.
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return len(a) % 1024
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDL\t\\$1023,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(s string) int {
|
||||
return len(s) % (4097 >> 1)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDL\t\\$2047,"},
|
||||
},
|
||||
{
|
||||
fn: `
|
||||
func $(a []int) int {
|
||||
return cap(a) % ((1 << 11) + 2048)
|
||||
}
|
||||
`,
|
||||
pos: []string{"\tANDL\t\\$4095,"},
|
||||
},
|
||||
}
|
||||
|
||||
var linuxS390XTests = []*asmTest{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue