2015-06-10 10:39:57 -07:00
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package ssa
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"testing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestShiftConstAMD64(t *testing.T) {
|
2015-07-30 11:03:05 -07:00
|
|
|
c := testConfig(t)
|
2017-03-16 22:42:10 -07:00
|
|
|
fe := DummyFrontend{t}
|
|
|
|
|
fun := makeConstShiftFunc(c, fe, 18, OpLsh64x64, TypeUInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
fun = makeConstShiftFunc(c, fe, 66, OpLsh64x64, TypeUInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHLQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
fun = makeConstShiftFunc(c, fe, 18, OpRsh64Ux64, TypeUInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 1, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
fun = makeConstShiftFunc(c, fe, 66, OpRsh64Ux64, TypeUInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SHRQconst: 0, OpAMD64CMPQconst: 0, OpAMD64ANDQconst: 0})
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
fun = makeConstShiftFunc(c, fe, 18, OpRsh64x64, TypeInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
|
cmd/compile: rearrange fields between ssa.Func, ssa.Cache, and ssa.Config
This makes ssa.Func, ssa.Cache, and ssa.Config fulfill
the roles laid out for them in CL 38160.
The only non-trivial change in this CL is how cached
values and blocks get IDs. Prior to this CL, their IDs were
assigned as part of resetting the cache, and only modified
IDs were reset. This required knowing how many values and
blocks were modified, which required a tight coupling between
ssa.Func and ssa.Config. To eliminate that coupling,
we now zero values and blocks during reset,
and assign their IDs when they are used.
Since unused values and blocks have ID == 0,
we can efficiently find the last used value/block,
to avoid zeroing everything.
Bulk zeroing is efficient, but not efficient enough
to obviate the need to avoid zeroing everything every time.
As a happy side-effect, ssa.Func.Free is no longer necessary.
DebugHashMatch and friends now belong in func.go.
They have been left in place for clarity and review.
I will move them in a subsequent CL.
Passes toolstash -cmp. No compiler performance impact.
No change in 'go test cmd/compile/internal/ssa' execution time.
Change-Id: I2eb7af58da067ef6a36e815a6f386cfe8634d098
Reviewed-on: https://go-review.googlesource.com/38167
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2017-03-15 11:15:13 -07:00
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
fun = makeConstShiftFunc(c, fe, 66, OpRsh64x64, TypeInt64)
|
2015-06-10 10:39:57 -07:00
|
|
|
checkOpcodeCounts(t, fun.f, map[Op]int{OpAMD64SARQconst: 1, OpAMD64CMPQconst: 0})
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-16 22:42:10 -07:00
|
|
|
func makeConstShiftFunc(c *Config, fe Frontend, amount int64, op Op, typ Type) fun {
|
2015-06-10 10:39:57 -07:00
|
|
|
ptyp := &TypeImpl{Size_: 8, Ptr: true, Name: "ptr"}
|
2017-03-16 22:42:10 -07:00
|
|
|
fun := Fun(c, fe, "entry",
|
2015-06-10 10:39:57 -07:00
|
|
|
Bloc("entry",
|
2016-01-31 11:39:39 -08:00
|
|
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
2015-06-19 21:02:28 -07:00
|
|
|
Valu("SP", OpSP, TypeUInt64, 0, nil),
|
|
|
|
|
Valu("argptr", OpOffPtr, ptyp, 8, nil, "SP"),
|
|
|
|
|
Valu("resptr", OpOffPtr, ptyp, 16, nil, "SP"),
|
2015-06-11 21:29:25 -07:00
|
|
|
Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"),
|
2015-07-28 14:19:20 -07:00
|
|
|
Valu("c", OpConst64, TypeUInt64, amount, nil),
|
2015-06-11 21:29:25 -07:00
|
|
|
Valu("shift", op, typ, 0, nil, "load", "c"),
|
2017-03-13 21:51:08 -04:00
|
|
|
Valu("store", OpStore, TypeMem, 0, TypeUInt64, "resptr", "shift", "mem"),
|
2015-06-10 10:39:57 -07:00
|
|
|
Exit("store")))
|
|
|
|
|
Compile(fun.f)
|
|
|
|
|
return fun
|
|
|
|
|
}
|
2017-02-20 15:54:43 -05:00
|
|
|
|
|
|
|
|
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)
|
2017-03-16 22:42:10 -07:00
|
|
|
fe := DummyFrontend{t}
|
2017-02-20 15:54:43 -05:00
|
|
|
for _, tc := range tests {
|
2017-03-16 22:42:10 -07:00
|
|
|
fun := makeShiftExtensionFunc(c, fe, tc.amount, tc.left, tc.right, tc.typ)
|
2017-02-20 15:54:43 -05:00
|
|
|
checkOpcodeCounts(t, fun.f, ops)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// makeShiftExtensionFunc generates a function containing:
|
|
|
|
|
//
|
|
|
|
|
// (rshift (lshift (Const64 [amount])) (Const64 [amount]))
|
|
|
|
|
//
|
|
|
|
|
// This may be equivalent to a sign or zero extension.
|
2017-03-16 22:42:10 -07:00
|
|
|
func makeShiftExtensionFunc(c *Config, fe Frontend, amount int64, lshift, rshift Op, typ Type) fun {
|
2017-02-20 15:54:43 -05:00
|
|
|
ptyp := &TypeImpl{Size_: 8, Ptr: true, Name: "ptr"}
|
2017-03-16 22:42:10 -07:00
|
|
|
fun := Fun(c, fe, "entry",
|
2017-02-20 15:54:43 -05:00
|
|
|
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"),
|
2017-03-13 21:51:08 -04:00
|
|
|
Valu("store", OpStore, TypeMem, 0, TypeUInt64, "resptr", "rshift", "mem"),
|
2017-02-20 15:54:43 -05:00
|
|
|
Exit("store")))
|
|
|
|
|
Compile(fun.f)
|
|
|
|
|
return fun
|
|
|
|
|
}
|