mirror of
https://github.com/golang/go
synced 2024-11-22 21:20:03 -07:00
Revert "cmd/compile: implement CMOV on amd64"
This reverts commit 080187f4f7
.
It broke build of golang.org/x/exp/shiny/iconvg
See issue 24395 for details
Change-Id: Ifd6134f6214e6cee40bd3c63c32941d5fc96ae8b
Reviewed-on: https://go-review.googlesource.com/100755
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
44e65f2c94
commit
644d14ea0f
@ -398,18 +398,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
|
||||
case ssa.OpAMD64CMOVQEQ, ssa.OpAMD64CMOVLEQ, ssa.OpAMD64CMOVWEQ,
|
||||
ssa.OpAMD64CMOVQLT, ssa.OpAMD64CMOVLLT, ssa.OpAMD64CMOVWLT,
|
||||
ssa.OpAMD64CMOVQNE, ssa.OpAMD64CMOVLNE, ssa.OpAMD64CMOVWNE,
|
||||
ssa.OpAMD64CMOVQGT, ssa.OpAMD64CMOVLGT, ssa.OpAMD64CMOVWGT,
|
||||
ssa.OpAMD64CMOVQLE, ssa.OpAMD64CMOVLLE, ssa.OpAMD64CMOVWLE,
|
||||
ssa.OpAMD64CMOVQGE, ssa.OpAMD64CMOVLGE, ssa.OpAMD64CMOVWGE,
|
||||
ssa.OpAMD64CMOVQHI, ssa.OpAMD64CMOVLHI, ssa.OpAMD64CMOVWHI,
|
||||
ssa.OpAMD64CMOVQLS, ssa.OpAMD64CMOVLLS, ssa.OpAMD64CMOVWLS,
|
||||
ssa.OpAMD64CMOVQCC, ssa.OpAMD64CMOVLCC, ssa.OpAMD64CMOVWCC,
|
||||
ssa.OpAMD64CMOVQCS, ssa.OpAMD64CMOVLCS, ssa.OpAMD64CMOVWCS,
|
||||
ssa.OpAMD64CMOVQGTF, ssa.OpAMD64CMOVLGTF, ssa.OpAMD64CMOVWGTF,
|
||||
ssa.OpAMD64CMOVQGEF, ssa.OpAMD64CMOVLGEF, ssa.OpAMD64CMOVWGEF:
|
||||
case ssa.OpAMD64CMOVQEQ, ssa.OpAMD64CMOVLEQ:
|
||||
r := v.Reg()
|
||||
if r != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
@ -420,71 +409,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
|
||||
case ssa.OpAMD64CMOVQNEF, ssa.OpAMD64CMOVLNEF, ssa.OpAMD64CMOVWNEF:
|
||||
r := v.Reg()
|
||||
if r != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
}
|
||||
// Flag condition: ^ZERO || PARITY
|
||||
// Generate:
|
||||
// CMOV*NE SRC,DST
|
||||
// CMOV*PS SRC,DST
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = v.Args[1].Reg()
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
var q *obj.Prog
|
||||
if v.Op == ssa.OpAMD64CMOVQNEF {
|
||||
q = s.Prog(x86.ACMOVQPS)
|
||||
} else if v.Op == ssa.OpAMD64CMOVLNEF {
|
||||
q = s.Prog(x86.ACMOVLPS)
|
||||
} else {
|
||||
q = s.Prog(x86.ACMOVWPS)
|
||||
}
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = v.Args[1].Reg()
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = r
|
||||
|
||||
case ssa.OpAMD64CMOVQEQF, ssa.OpAMD64CMOVLEQF, ssa.OpAMD64CMOVWEQF:
|
||||
r := v.Reg()
|
||||
if r != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
}
|
||||
|
||||
// Flag condition: ZERO && !PARITY
|
||||
// Generate:
|
||||
// MOV SRC,AX
|
||||
// CMOV*NE DST,AX
|
||||
// CMOV*PC AX,DST
|
||||
//
|
||||
// TODO(rasky): we could generate:
|
||||
// CMOV*NE DST,SRC
|
||||
// CMOV*PC SRC,DST
|
||||
// But this requires a way for regalloc to know that SRC might be
|
||||
// clobbered by this instruction.
|
||||
if v.Args[1].Reg() != x86.REG_AX {
|
||||
opregreg(s, moveByType(v.Type), x86.REG_AX, v.Args[1].Reg())
|
||||
}
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = x86.REG_AX
|
||||
var q *obj.Prog
|
||||
if v.Op == ssa.OpAMD64CMOVQEQF {
|
||||
q = s.Prog(x86.ACMOVQPC)
|
||||
} else if v.Op == ssa.OpAMD64CMOVLEQF {
|
||||
q = s.Prog(x86.ACMOVLPC)
|
||||
} else {
|
||||
q = s.Prog(x86.ACMOVWPC)
|
||||
}
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = x86.REG_AX
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = r
|
||||
|
||||
case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst:
|
||||
r := v.Reg()
|
||||
p := s.Prog(v.Op.Asm())
|
||||
|
@ -19,10 +19,7 @@ package ssa
|
||||
// rewrite Phis in the postdominator as CondSelects.
|
||||
func branchelim(f *Func) {
|
||||
// FIXME: add support for lowering CondSelects on more architectures
|
||||
switch f.Config.arch {
|
||||
case "arm64", "amd64":
|
||||
// implemented
|
||||
default:
|
||||
if f.Config.arch != "arm64" {
|
||||
return
|
||||
}
|
||||
|
||||
@ -35,22 +32,10 @@ func branchelim(f *Func) {
|
||||
}
|
||||
}
|
||||
|
||||
func canCondSelect(v *Value, arch string) bool {
|
||||
func canCondSelect(v *Value) bool {
|
||||
// For now, stick to simple scalars that fit in registers
|
||||
switch {
|
||||
case v.Type.Size() > v.Block.Func.Config.RegSize:
|
||||
return false
|
||||
case v.Type.IsPtrShaped():
|
||||
return true
|
||||
case v.Type.IsInteger():
|
||||
if arch == "amd64" && v.Type.Size() < 2 {
|
||||
// amd64 doesn't support CMOV with byte registers
|
||||
return false
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
sz := v.Type.Size()
|
||||
return sz <= v.Block.Func.Config.RegSize && (v.Type.IsInteger() || v.Type.IsPtrShaped())
|
||||
}
|
||||
|
||||
func elimIf(f *Func, dom *Block) bool {
|
||||
@ -83,7 +68,7 @@ func elimIf(f *Func, dom *Block) bool {
|
||||
for _, v := range post.Values {
|
||||
if v.Op == OpPhi {
|
||||
hasphis = true
|
||||
if !canCondSelect(v, f.Config.arch) {
|
||||
if !canCondSelect(v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -184,7 +169,7 @@ func elimIfElse(f *Func, b *Block) bool {
|
||||
for _, v := range post.Values {
|
||||
if v.Op == OpPhi {
|
||||
hasphis = true
|
||||
if !canCondSelect(v, f.Config.arch) {
|
||||
if !canCondSelect(v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -11,162 +11,128 @@ import (
|
||||
|
||||
// Test that a trivial 'if' is eliminated
|
||||
func TestBranchElimIf(t *testing.T) {
|
||||
var testData = []struct {
|
||||
arch string
|
||||
intType string
|
||||
ok bool
|
||||
}{
|
||||
{"arm64", "int32", true},
|
||||
{"amd64", "int32", true},
|
||||
{"amd64", "int8", false},
|
||||
c := testConfig(t)
|
||||
c.config.arch = "arm64" // FIXME
|
||||
boolType := types.New(types.TBOOL)
|
||||
intType := types.New(types.TINT32)
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const1", OpConst32, intType, 1, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
If("cond", "b2", "b3")),
|
||||
Bloc("b2",
|
||||
Goto("b3")),
|
||||
Bloc("b3",
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
|
||||
Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
|
||||
Exit("retstore")))
|
||||
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
Deadcode(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
|
||||
if len(fun.f.Blocks) != 1 {
|
||||
t.Errorf("expected 1 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
|
||||
for _, data := range testData {
|
||||
t.Run(data.arch+"/"+data.intType, func(t *testing.T) {
|
||||
c := testConfigArch(t, data.arch)
|
||||
boolType := c.config.Types.Bool
|
||||
var intType *types.Type
|
||||
switch data.intType {
|
||||
case "int32":
|
||||
intType = c.config.Types.Int32
|
||||
case "int8":
|
||||
intType = c.config.Types.Int8
|
||||
default:
|
||||
t.Fatal("invalid integer type:", data.intType)
|
||||
}
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const1", OpConst32, intType, 1, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
If("cond", "b2", "b3")),
|
||||
Bloc("b2",
|
||||
Goto("b3")),
|
||||
Bloc("b3",
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
|
||||
Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
|
||||
Exit("retstore")))
|
||||
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
Deadcode(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
|
||||
if data.ok {
|
||||
|
||||
if len(fun.f.Blocks) != 1 {
|
||||
t.Fatalf("expected 1 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
if fun.values["phi"].Op != OpCondSelect {
|
||||
t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
if fun.values["phi"].Args[2] != fun.values["cond"] {
|
||||
t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
|
||||
}
|
||||
if fun.blocks["entry"].Kind != BlockExit {
|
||||
t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
|
||||
}
|
||||
} else {
|
||||
if len(fun.f.Blocks) != 3 {
|
||||
t.Fatalf("expected 3 block after branchelim and deadcode; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
}
|
||||
})
|
||||
if fun.values["phi"].Op != OpCondSelect {
|
||||
t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
if fun.values["phi"].Args[2] != fun.values["cond"] {
|
||||
t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
|
||||
}
|
||||
if fun.blocks["entry"].Kind != BlockExit {
|
||||
t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a trivial if/else is eliminated
|
||||
func TestBranchElimIfElse(t *testing.T) {
|
||||
for _, arch := range []string{"arm64", "amd64"} {
|
||||
t.Run(arch, func(t *testing.T) {
|
||||
c := testConfigArch(t, arch)
|
||||
boolType := c.config.Types.Bool
|
||||
intType := c.config.Types.Int32
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const1", OpConst32, intType, 1, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
If("cond", "b2", "b3")),
|
||||
Bloc("b2",
|
||||
Goto("b4")),
|
||||
Bloc("b3",
|
||||
Goto("b4")),
|
||||
Bloc("b4",
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
|
||||
Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
|
||||
Exit("retstore")))
|
||||
c := testConfig(t)
|
||||
c.config.arch = "arm64" // FIXME
|
||||
boolType := types.New(types.TBOOL)
|
||||
intType := types.New(types.TINT32)
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const1", OpConst32, intType, 1, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
If("cond", "b2", "b3")),
|
||||
Bloc("b2",
|
||||
Goto("b4")),
|
||||
Bloc("b3",
|
||||
Goto("b4")),
|
||||
Bloc("b4",
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"),
|
||||
Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"),
|
||||
Exit("retstore")))
|
||||
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
Deadcode(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
Deadcode(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
|
||||
if len(fun.f.Blocks) != 1 {
|
||||
t.Fatalf("expected 1 block after branchelim; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
if fun.values["phi"].Op != OpCondSelect {
|
||||
t.Fatalf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
if fun.values["phi"].Args[2] != fun.values["cond"] {
|
||||
t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
|
||||
}
|
||||
if fun.blocks["entry"].Kind != BlockExit {
|
||||
t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
|
||||
}
|
||||
})
|
||||
if len(fun.f.Blocks) != 1 {
|
||||
t.Errorf("expected 1 block after branchelim; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
if fun.values["phi"].Op != OpCondSelect {
|
||||
t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
if fun.values["phi"].Args[2] != fun.values["cond"] {
|
||||
t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2])
|
||||
}
|
||||
if fun.blocks["entry"].Kind != BlockExit {
|
||||
t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Test that an if/else CFG that loops back
|
||||
// into itself does *not* get eliminated.
|
||||
func TestNoBranchElimLoop(t *testing.T) {
|
||||
for _, arch := range []string{"arm64", "amd64"} {
|
||||
t.Run(arch, func(t *testing.T) {
|
||||
c := testConfigArch(t, arch)
|
||||
boolType := c.config.Types.Bool
|
||||
intType := c.config.Types.Int32
|
||||
c := testConfig(t)
|
||||
c.config.arch = "arm64" // FIXME
|
||||
boolType := types.New(types.TBOOL)
|
||||
intType := types.New(types.TINT32)
|
||||
|
||||
// The control flow here is totally bogus,
|
||||
// but a dead cycle seems like the only plausible
|
||||
// way to arrive at a diamond CFG that is also a loop.
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("const3", OpConst32, intType, 3, nil),
|
||||
Goto("b5")),
|
||||
Bloc("b2",
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const2", "const3"),
|
||||
If("cond", "b3", "b4")),
|
||||
Bloc("b3",
|
||||
Goto("b2")),
|
||||
Bloc("b4",
|
||||
Goto("b2")),
|
||||
Bloc("b5",
|
||||
Exit("start")))
|
||||
// The control flow here is totally bogus,
|
||||
// but a dead cycle seems like the only plausible
|
||||
// way to arrive at a diamond CFG that is also a loop.
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
Valu("start", OpInitMem, types.TypeMem, 0, nil),
|
||||
Valu("sb", OpSB, types.TypeInvalid, 0, nil),
|
||||
Valu("const2", OpConst32, intType, 2, nil),
|
||||
Valu("const3", OpConst32, intType, 3, nil),
|
||||
Goto("b5")),
|
||||
Bloc("b2",
|
||||
Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"),
|
||||
Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"),
|
||||
Valu("phi", OpPhi, intType, 0, nil, "const2", "const3"),
|
||||
If("cond", "b3", "b4")),
|
||||
Bloc("b3",
|
||||
Goto("b2")),
|
||||
Bloc("b4",
|
||||
Goto("b2")),
|
||||
Bloc("b5",
|
||||
Exit("start")))
|
||||
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
branchelim(fun.f)
|
||||
CheckFunc(fun.f)
|
||||
|
||||
if len(fun.f.Blocks) != 5 {
|
||||
t.Errorf("expected 5 block after branchelim; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
if fun.values["phi"].Op != OpPhi {
|
||||
t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
})
|
||||
if len(fun.f.Blocks) != 5 {
|
||||
t.Errorf("expected 5 block after branchelim; found %d", len(fun.f.Blocks))
|
||||
}
|
||||
if fun.values["phi"].Op != OpPhi {
|
||||
t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op)
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package ssa
|
||||
import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/arm64"
|
||||
"cmd/internal/obj/s390x"
|
||||
"cmd/internal/obj/x86"
|
||||
"cmd/internal/src"
|
||||
@ -23,7 +22,6 @@ var Copyelim = copyelim
|
||||
var testCtxts = map[string]*obj.Link{
|
||||
"amd64": obj.Linknew(&x86.Linkamd64),
|
||||
"s390x": obj.Linknew(&s390x.Links390x),
|
||||
"arm64": obj.Linknew(&arm64.Linkarm64),
|
||||
}
|
||||
|
||||
func testConfig(tb testing.TB) *Conf { return testConfigArch(tb, "amd64") }
|
||||
|
@ -475,52 +475,6 @@
|
||||
(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
|
||||
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
|
||||
|
||||
// Lowering conditional moves
|
||||
// If the condition is a SETxx, we can just run a CMOV from the comparison that was
|
||||
// setting the flags.
|
||||
// Legend: HI=unsigned ABOVE, CS=unsigned BELOW, CC=unsigned ABOVE EQUAL, LS=unsigned BELOW EQUAL
|
||||
(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && (is64BitInt(t) || isPtr(t))
|
||||
-> (CMOVQ(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
|
||||
(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && is32BitInt(t)
|
||||
-> (CMOVL(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
|
||||
(CondSelect <t> x y (SET(EQ|NE|L|G|LE|GE|A|B|AE|BE|EQF|NEF|GF|GEF) cond)) && is16BitInt(t)
|
||||
-> (CMOVW(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS|EQF|NEF|GTF|GEF) y x cond)
|
||||
|
||||
// If the condition does not set the flags, we need to generate a comparison.
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 1
|
||||
-> (CondSelect <t> x y (MOVBQZX <typ.UInt64> check))
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 2
|
||||
-> (CondSelect <t> x y (MOVWQZX <typ.UInt64> check))
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 4
|
||||
-> (CondSelect <t> x y (MOVLQZX <typ.UInt64> check))
|
||||
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && (is64BitInt(t) || isPtr(t))
|
||||
-> (CMOVQNE y x (CMPQconst [0] check))
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && is32BitInt(t)
|
||||
-> (CMOVLNE y x (CMPQconst [0] check))
|
||||
(CondSelect <t> x y check) && !check.Type.IsFlags() && check.Type.Size() == 8 && is16BitInt(t)
|
||||
-> (CMOVWNE y x (CMPQconst [0] check))
|
||||
|
||||
// Absorb InvertFlags
|
||||
(CMOVQ(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
|
||||
-> (CMOVQ(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
|
||||
(CMOVL(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
|
||||
-> (CMOVL(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
|
||||
(CMOVW(EQ|NE|LT|GT|LE|GE|HI|CS|CC|LS) x y (InvertFlags cond))
|
||||
-> (CMOVW(EQ|NE|GT|LT|GE|LE|CS|HI|LS|CC) x y cond)
|
||||
|
||||
// Absorb constants generated during lower
|
||||
(CMOVQ(EQ|LE|GE|CC|LS) _ x (FlagEQ)) -> x
|
||||
(CMOVQ(NE|LT|GT|CS|HI) y _ (FlagEQ)) -> y
|
||||
(CMOVQ(NE|GT|GE|HI|CC) _ x (FlagGT_UGT)) -> x
|
||||
(CMOVQ(EQ|LE|LT|LS|CS) y _ (FlagGT_UGT)) -> y
|
||||
(CMOVQ(NE|GT|GE|LS|CS) _ x (FlagGT_ULT)) -> x
|
||||
(CMOVQ(EQ|LE|LT|HI|CC) y _ (FlagGT_ULT)) -> y
|
||||
(CMOVQ(NE|LT|LE|CS|LS) _ x (FlagLT_ULT)) -> x
|
||||
(CMOVQ(EQ|GT|GE|HI|CC) y _ (FlagLT_ULT)) -> y
|
||||
(CMOVQ(NE|LT|LE|HI|CC) _ x (FlagLT_UGT)) -> x
|
||||
(CMOVQ(EQ|GT|GE|CS|LS) y _ (FlagLT_ULT)) -> y
|
||||
|
||||
// Miscellaneous
|
||||
(Convert <t> x mem) && config.PtrSize == 8 -> (MOVQconvert <t> x mem)
|
||||
(Convert <t> x mem) && config.PtrSize == 4 -> (MOVLconvert <t> x mem)
|
||||
@ -1396,10 +1350,6 @@
|
||||
(CMPLconst x [0]) -> (TESTL x x)
|
||||
(CMPWconst x [0]) -> (TESTW x x)
|
||||
(CMPBconst x [0]) -> (TESTB x x)
|
||||
(TESTQconst [-1] x) -> (TESTQ x x)
|
||||
(TESTLconst [-1] x) -> (TESTL x x)
|
||||
(TESTWconst [-1] x) -> (TESTW x x)
|
||||
(TESTBconst [-1] x) -> (TESTB x x)
|
||||
|
||||
// Combining byte loads into larger (unaligned) loads.
|
||||
// There are many ways these combinations could occur. This is
|
||||
|
@ -132,7 +132,6 @@ func init() {
|
||||
gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly}
|
||||
gp21load = regInfo{inputs: []regMask{gp, gpspsb, 0}, outputs: gponly}
|
||||
gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly}
|
||||
gp21pax = regInfo{inputs: []regMask{gp &^ ax, gp}, outputs: []regMask{gp &^ ax}, clobbers: ax}
|
||||
|
||||
gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}}
|
||||
gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}}
|
||||
@ -341,57 +340,10 @@ func init() {
|
||||
{name: "BSRQ", argLength: 1, reg: gp11flags, asm: "BSRQ", typ: "(UInt64,Flags)"}, // # of high-order zeroes in 64-bit arg
|
||||
{name: "BSRL", argLength: 1, reg: gp11flags, asm: "BSRL", typ: "(UInt32,Flags)"}, // # of high-order zeroes in 32-bit arg
|
||||
|
||||
// CMOV instructions: 64, 32 and 16-bit sizes.
|
||||
// if arg2 encodes a true result, return arg1, else arg0
|
||||
{name: "CMOVQEQ", argLength: 3, reg: gp21, asm: "CMOVQEQ", resultInArg0: true},
|
||||
{name: "CMOVQNE", argLength: 3, reg: gp21, asm: "CMOVQNE", resultInArg0: true},
|
||||
{name: "CMOVQLT", argLength: 3, reg: gp21, asm: "CMOVQLT", resultInArg0: true},
|
||||
{name: "CMOVQGT", argLength: 3, reg: gp21, asm: "CMOVQGT", resultInArg0: true},
|
||||
{name: "CMOVQLE", argLength: 3, reg: gp21, asm: "CMOVQLE", resultInArg0: true},
|
||||
{name: "CMOVQGE", argLength: 3, reg: gp21, asm: "CMOVQGE", resultInArg0: true},
|
||||
{name: "CMOVQLS", argLength: 3, reg: gp21, asm: "CMOVQLS", resultInArg0: true},
|
||||
{name: "CMOVQHI", argLength: 3, reg: gp21, asm: "CMOVQHI", resultInArg0: true},
|
||||
{name: "CMOVQCC", argLength: 3, reg: gp21, asm: "CMOVQCC", resultInArg0: true},
|
||||
{name: "CMOVQCS", argLength: 3, reg: gp21, asm: "CMOVQCS", resultInArg0: true},
|
||||
|
||||
{name: "CMOVLEQ", argLength: 3, reg: gp21, asm: "CMOVLEQ", resultInArg0: true},
|
||||
{name: "CMOVLNE", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLLT", argLength: 3, reg: gp21, asm: "CMOVLLT", resultInArg0: true},
|
||||
{name: "CMOVLGT", argLength: 3, reg: gp21, asm: "CMOVLGT", resultInArg0: true},
|
||||
{name: "CMOVLLE", argLength: 3, reg: gp21, asm: "CMOVLLE", resultInArg0: true},
|
||||
{name: "CMOVLGE", argLength: 3, reg: gp21, asm: "CMOVLGE", resultInArg0: true},
|
||||
{name: "CMOVLLS", argLength: 3, reg: gp21, asm: "CMOVLLS", resultInArg0: true},
|
||||
{name: "CMOVLHI", argLength: 3, reg: gp21, asm: "CMOVLHI", resultInArg0: true},
|
||||
{name: "CMOVLCC", argLength: 3, reg: gp21, asm: "CMOVLCC", resultInArg0: true},
|
||||
{name: "CMOVLCS", argLength: 3, reg: gp21, asm: "CMOVLCS", resultInArg0: true},
|
||||
|
||||
{name: "CMOVWEQ", argLength: 3, reg: gp21, asm: "CMOVWEQ", resultInArg0: true},
|
||||
{name: "CMOVWNE", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWLT", argLength: 3, reg: gp21, asm: "CMOVWLT", resultInArg0: true},
|
||||
{name: "CMOVWGT", argLength: 3, reg: gp21, asm: "CMOVWGT", resultInArg0: true},
|
||||
{name: "CMOVWLE", argLength: 3, reg: gp21, asm: "CMOVWLE", resultInArg0: true},
|
||||
{name: "CMOVWGE", argLength: 3, reg: gp21, asm: "CMOVWGE", resultInArg0: true},
|
||||
{name: "CMOVWLS", argLength: 3, reg: gp21, asm: "CMOVWLS", resultInArg0: true},
|
||||
{name: "CMOVWHI", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
|
||||
{name: "CMOVWCC", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
|
||||
{name: "CMOVWCS", argLength: 3, reg: gp21, asm: "CMOVWCS", resultInArg0: true},
|
||||
|
||||
// CMOV with floating point instructions. We need separate pseudo-op to handle
|
||||
// InvertFlags correctly, and to generate special code that handles NaN (unordered flag).
|
||||
// NOTE: the fact that CMOV*EQF here is marked to generate CMOV*NE is not a bug. See
|
||||
// code generation in amd64/ssa.go.
|
||||
{name: "CMOVQEQF", argLength: 3, reg: gp21pax, asm: "CMOVQNE", resultInArg0: true},
|
||||
{name: "CMOVQNEF", argLength: 3, reg: gp21, asm: "CMOVQNE", resultInArg0: true},
|
||||
{name: "CMOVQGTF", argLength: 3, reg: gp21, asm: "CMOVQHI", resultInArg0: true},
|
||||
{name: "CMOVQGEF", argLength: 3, reg: gp21, asm: "CMOVQCC", resultInArg0: true},
|
||||
{name: "CMOVLEQF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLNEF", argLength: 3, reg: gp21, asm: "CMOVLNE", resultInArg0: true},
|
||||
{name: "CMOVLGTF", argLength: 3, reg: gp21, asm: "CMOVLHI", resultInArg0: true},
|
||||
{name: "CMOVLGEF", argLength: 3, reg: gp21, asm: "CMOVLCC", resultInArg0: true},
|
||||
{name: "CMOVWEQF", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWNEF", argLength: 3, reg: gp21, asm: "CMOVWNE", resultInArg0: true},
|
||||
{name: "CMOVWGTF", argLength: 3, reg: gp21, asm: "CMOVWHI", resultInArg0: true},
|
||||
{name: "CMOVWGEF", argLength: 3, reg: gp21, asm: "CMOVWCC", resultInArg0: true},
|
||||
// Note ASM for ops moves whole register
|
||||
//
|
||||
{name: "CMOVQEQ", argLength: 3, reg: gp21, asm: "CMOVQEQ", resultInArg0: true}, // if arg2 encodes "equal" return arg1 else arg0
|
||||
{name: "CMOVLEQ", argLength: 3, reg: gp21, asm: "CMOVLEQ", resultInArg0: true}, // if arg2 encodes "equal" return arg1 else arg0
|
||||
|
||||
{name: "BSWAPQ", argLength: 1, reg: gp11, asm: "BSWAPQ", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
|
||||
{name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true, clobberFlags: true}, // arg0 swap bytes
|
||||
@ -626,6 +578,7 @@ func init() {
|
||||
{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
|
||||
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
|
||||
|
||||
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
|
||||
// It saves all GP registers if necessary, but may clobber others.
|
||||
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("DI"), ax}, clobbers: callerSave &^ gp}, clobberFlags: true, aux: "Sym", symEffect: "None"},
|
||||
|
@ -560,47 +560,7 @@ const (
|
||||
OpAMD64BSRQ
|
||||
OpAMD64BSRL
|
||||
OpAMD64CMOVQEQ
|
||||
OpAMD64CMOVQNE
|
||||
OpAMD64CMOVQLT
|
||||
OpAMD64CMOVQGT
|
||||
OpAMD64CMOVQLE
|
||||
OpAMD64CMOVQGE
|
||||
OpAMD64CMOVQLS
|
||||
OpAMD64CMOVQHI
|
||||
OpAMD64CMOVQCC
|
||||
OpAMD64CMOVQCS
|
||||
OpAMD64CMOVLEQ
|
||||
OpAMD64CMOVLNE
|
||||
OpAMD64CMOVLLT
|
||||
OpAMD64CMOVLGT
|
||||
OpAMD64CMOVLLE
|
||||
OpAMD64CMOVLGE
|
||||
OpAMD64CMOVLLS
|
||||
OpAMD64CMOVLHI
|
||||
OpAMD64CMOVLCC
|
||||
OpAMD64CMOVLCS
|
||||
OpAMD64CMOVWEQ
|
||||
OpAMD64CMOVWNE
|
||||
OpAMD64CMOVWLT
|
||||
OpAMD64CMOVWGT
|
||||
OpAMD64CMOVWLE
|
||||
OpAMD64CMOVWGE
|
||||
OpAMD64CMOVWLS
|
||||
OpAMD64CMOVWHI
|
||||
OpAMD64CMOVWCC
|
||||
OpAMD64CMOVWCS
|
||||
OpAMD64CMOVQEQF
|
||||
OpAMD64CMOVQNEF
|
||||
OpAMD64CMOVQGTF
|
||||
OpAMD64CMOVQGEF
|
||||
OpAMD64CMOVLEQF
|
||||
OpAMD64CMOVLNEF
|
||||
OpAMD64CMOVLGTF
|
||||
OpAMD64CMOVLGEF
|
||||
OpAMD64CMOVWEQF
|
||||
OpAMD64CMOVWNEF
|
||||
OpAMD64CMOVWGTF
|
||||
OpAMD64CMOVWGEF
|
||||
OpAMD64BSWAPQ
|
||||
OpAMD64BSWAPL
|
||||
OpAMD64POPCNTQ
|
||||
@ -6840,141 +6800,6 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQNE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQLT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQLT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQGT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQGT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQLE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQLE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQGE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQGE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQLS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQLS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQHI",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQCC",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQCS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQCS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLEQ",
|
||||
argLen: 3,
|
||||
@ -6990,472 +6815,6 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLNE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLLT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLLT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLGT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLGT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLLE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLLE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLGE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLGE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLLS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLLS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLHI",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLCC",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLCS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLCS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWEQ",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWEQ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWNE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWLT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWLT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWGT",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWGT,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWLE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWLE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWGE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWGE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWLS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWLS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWHI",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWCC",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWCS",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWCS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQEQF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
clobbers: 1, // AX
|
||||
outputs: []outputInfo{
|
||||
{0, 65518}, // CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQNEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQGTF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVQGEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVQCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLEQF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLNEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLGTF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVLGEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVLCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWEQF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWNEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWNE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWGTF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWHI,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMOVWGEF",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: x86.ACMOVWCC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
{1, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "BSWAPQ",
|
||||
argLen: 1,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,178 +0,0 @@
|
||||
// asmcheck
|
||||
|
||||
package codegen
|
||||
|
||||
func cmovint(c int) int {
|
||||
x := c + 4
|
||||
if x < 0 {
|
||||
x = 182
|
||||
}
|
||||
// amd64:"CMOVQLT"
|
||||
// arm64:"CSEL\tLT"
|
||||
return x
|
||||
}
|
||||
|
||||
func cmovchan(x, y chan int) chan int {
|
||||
if x != y {
|
||||
x = y
|
||||
}
|
||||
// amd64:"CMOVQNE"
|
||||
// arm64:"CSEL\tNE"
|
||||
return x
|
||||
}
|
||||
|
||||
func cmovuintptr(x, y uintptr) uintptr {
|
||||
if x < y {
|
||||
x = -y
|
||||
}
|
||||
// amd64:"CMOVQCS"
|
||||
// arm64:"CSEL\tLO"
|
||||
return x
|
||||
}
|
||||
|
||||
func cmov32bit(x, y uint32) uint32 {
|
||||
if x < y {
|
||||
x = -y
|
||||
}
|
||||
// amd64:"CMOVLCS"
|
||||
// arm64:"CSEL\tLO"
|
||||
return x
|
||||
}
|
||||
|
||||
func cmov16bit(x, y uint16) uint16 {
|
||||
if x < y {
|
||||
x = -y
|
||||
}
|
||||
// amd64:"CMOVWCS"
|
||||
// arm64:"CSEL\tLO"
|
||||
return x
|
||||
}
|
||||
|
||||
// Floating point comparison. For EQ/NE, we must
|
||||
// generate special code to handle NaNs.
|
||||
func cmovfloateq(x, y float64) int {
|
||||
a := 128
|
||||
if x == y {
|
||||
a = 256
|
||||
}
|
||||
// amd64:"CMOVQNE","CMOVQPC"
|
||||
// arm64:"CSEL\tEQ"
|
||||
return a
|
||||
}
|
||||
|
||||
func cmovfloatne(x, y float64) int {
|
||||
a := 128
|
||||
if x != y {
|
||||
a = 256
|
||||
}
|
||||
// amd64:"CMOVQNE","CMOVQPS"
|
||||
// arm64:"CSEL\tNE"
|
||||
return a
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func frexp(f float64) (frac float64, exp int) {
|
||||
return 1.0, 4
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func ldexp(frac float64, exp int) float64 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
// Generate a CMOV with a floating comparison and integer move.
|
||||
func cmovfloatint2(x, y float64) float64 {
|
||||
yfr, yexp := 4.0, 5
|
||||
|
||||
r := x
|
||||
for r >= y {
|
||||
rfr, rexp := frexp(r)
|
||||
if rfr < yfr {
|
||||
rexp = rexp - 1
|
||||
}
|
||||
// amd64:"CMOVQHI"
|
||||
// arm64:"CSEL\tGT"
|
||||
r = r - ldexp(y, (rexp-yexp))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func cmovloaded(x [4]int, y int) int {
|
||||
if x[2] != 0 {
|
||||
y = x[2]
|
||||
} else {
|
||||
y = y >> 2
|
||||
}
|
||||
// amd64:"CMOVQNE"
|
||||
// arm64:"CSEL\tNE"
|
||||
return y
|
||||
}
|
||||
|
||||
func cmovuintptr2(x, y uintptr) uintptr {
|
||||
a := x * 2
|
||||
if a == 0 {
|
||||
a = 256
|
||||
}
|
||||
// amd64:"CMOVQEQ"
|
||||
// arm64:"CSEL\tEQ"
|
||||
return a
|
||||
}
|
||||
|
||||
// Floating point CMOVs are not supported by amd64/arm64
|
||||
func cmovfloatmove(x, y int) float64 {
|
||||
a := 1.0
|
||||
if x <= y {
|
||||
a = 2.0
|
||||
}
|
||||
// amd64:-"CMOV"
|
||||
// arm64:-"CSEL"
|
||||
return a
|
||||
}
|
||||
|
||||
// On amd64, the following patterns trigger comparison inversion.
|
||||
// Test that we correctly invert the CMOV condition
|
||||
var gsink int64
|
||||
var gusink uint64
|
||||
|
||||
func cmovinvert1(x, y int64) int64 {
|
||||
if x < gsink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQGT"
|
||||
return y
|
||||
}
|
||||
func cmovinvert2(x, y int64) int64 {
|
||||
if x <= gsink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQGE"
|
||||
return y
|
||||
}
|
||||
func cmovinvert3(x, y int64) int64 {
|
||||
if x == gsink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQEQ"
|
||||
return y
|
||||
}
|
||||
func cmovinvert4(x, y int64) int64 {
|
||||
if x != gsink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQNE"
|
||||
return y
|
||||
}
|
||||
func cmovinvert5(x, y uint64) uint64 {
|
||||
if x > gusink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQCS"
|
||||
return y
|
||||
}
|
||||
func cmovinvert6(x, y uint64) uint64 {
|
||||
if x >= gusink {
|
||||
y = -y
|
||||
}
|
||||
// amd64:"CMOVQLS"
|
||||
return y
|
||||
}
|
Loading…
Reference in New Issue
Block a user