mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: rewrite pairs of shifts to extensions
Replaces pairs of shifts with sign/zero extension where possible.
For example:
(uint64(x) << 32) >> 32 -> uint64(uint32(x))
Reduces the execution time of the following code by ~4.5% on s390x:
for i := 0; i < N; i++ {
x += (uint64(i)<<32)>>32
}
Change-Id: Idb2d56f27e80a2e1366bc995922ad3fd958c51a7
Reviewed-on: https://go-review.googlesource.com/37292
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
8321be6339
commit
72a071c1da
3 changed files with 424 additions and 0 deletions
|
|
@ -46,3 +46,63 @@ func makeConstShiftFunc(c *Config, amount int64, op Op, typ Type) fun {
|
|||
Compile(fun.f)
|
||||
return fun
|
||||
}
|
||||
|
||||
func TestShiftToExtensionAMD64(t *testing.T) {
|
||||
// Test that eligible pairs of constant shifts are converted to extensions.
|
||||
// For example:
|
||||
// (uint64(x) << 32) >> 32 -> uint64(uint32(x))
|
||||
ops := map[Op]int{
|
||||
OpAMD64SHLQconst: 0, OpAMD64SHLLconst: 0,
|
||||
OpAMD64SHRQconst: 0, OpAMD64SHRLconst: 0,
|
||||
OpAMD64SARQconst: 0, OpAMD64SARLconst: 0,
|
||||
}
|
||||
tests := [...]struct {
|
||||
amount int64
|
||||
left, right Op
|
||||
typ Type
|
||||
}{
|
||||
// unsigned
|
||||
{56, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
|
||||
{48, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
|
||||
{32, OpLsh64x64, OpRsh64Ux64, TypeUInt64},
|
||||
{24, OpLsh32x64, OpRsh32Ux64, TypeUInt32},
|
||||
{16, OpLsh32x64, OpRsh32Ux64, TypeUInt32},
|
||||
{8, OpLsh16x64, OpRsh16Ux64, TypeUInt16},
|
||||
// signed
|
||||
{56, OpLsh64x64, OpRsh64x64, TypeInt64},
|
||||
{48, OpLsh64x64, OpRsh64x64, TypeInt64},
|
||||
{32, OpLsh64x64, OpRsh64x64, TypeInt64},
|
||||
{24, OpLsh32x64, OpRsh32x64, TypeInt32},
|
||||
{16, OpLsh32x64, OpRsh32x64, TypeInt32},
|
||||
{8, OpLsh16x64, OpRsh16x64, TypeInt16},
|
||||
}
|
||||
c := testConfig(t)
|
||||
for _, tc := range tests {
|
||||
fun := makeShiftExtensionFunc(c, tc.amount, tc.left, tc.right, tc.typ)
|
||||
checkOpcodeCounts(t, fun.f, ops)
|
||||
fun.f.Free()
|
||||
}
|
||||
}
|
||||
|
||||
// makeShiftExtensionFunc generates a function containing:
|
||||
//
|
||||
// (rshift (lshift (Const64 [amount])) (Const64 [amount]))
|
||||
//
|
||||
// This may be equivalent to a sign or zero extension.
|
||||
func makeShiftExtensionFunc(c *Config, amount int64, lshift, rshift Op, typ Type) fun {
|
||||
ptyp := &TypeImpl{Size_: 8, Ptr: true, Name: "ptr"}
|
||||
fun := Fun(c, "entry",
|
||||
Bloc("entry",
|
||||
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
||||
Valu("SP", OpSP, TypeUInt64, 0, nil),
|
||||
Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
|
||||
Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
|
||||
Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
|
||||
Valu("c", OpConst64, TypeUInt64, amount, nil),
|
||||
Valu("lshift", lshift, typ, 0, nil, "load", "c"),
|
||||
Valu("rshift", rshift, typ, 0, nil, "lshift", "c"),
|
||||
Valu("store", OpStore, TypeMem, 8, nil, "resptr", "rshift", "mem"),
|
||||
Exit("store")))
|
||||
Compile(fun.f)
|
||||
return fun
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue