mirror of
https://github.com/golang/go.git
synced 2025-05-06 08:03:03 +00:00
cmd/compile: add anchored version of SP
The SPanchored opcode is identical to SP, except that it takes a memory argument so that it (and more importantly, anything that uses it) must be scheduled at or after that memory argument. This opcode ensures that a LEAQ of a variable gets scheduled after the corresponding VARDEF for that variable. This may lead to less CSE of LEAQ operations. The effect is very small. The go binary is only 80 bytes bigger after this CL. Usually LEAQs get folded into load/store operations, so the effect is only for pointerful types, large enough to need a duffzero, and have their address passed somewhere. Even then, usually the CSEd LEAQs will be un-CSEd because the two uses are on different sides of a function call and the LEAQ ends up being rematerialized at the second use anyway. Change-Id: Ib893562cd05369b91dd563b48fb83f5250950293 Reviewed-on: https://go-review.googlesource.com/c/go/+/452916 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Martin Möhrmann <moehrmann@google.com> Reviewed-by: Martin Möhrmann <martin@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
47a0d46716
commit
f959fb3872
@ -333,7 +333,8 @@
|
|||||||
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
||||||
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
||||||
(Addr {sym} base) => (LEAL {sym} base)
|
(Addr {sym} base) => (LEAL {sym} base)
|
||||||
(LocalAddr {sym} base _) => (LEAL {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (LEAL {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (LEAL {sym} base)
|
||||||
|
|
||||||
// block rewrites
|
// block rewrites
|
||||||
(If (SETL cmp) yes no) => (LT cmp yes no)
|
(If (SETL cmp) yes no) => (LT cmp yes no)
|
||||||
|
@ -480,7 +480,8 @@
|
|||||||
|
|
||||||
(HasCPUFeature {s}) => (SETNE (CMPLconst [0] (LoweredHasCPUFeature {s})))
|
(HasCPUFeature {s}) => (SETNE (CMPLconst [0] (LoweredHasCPUFeature {s})))
|
||||||
(Addr {sym} base) => (LEAQ {sym} base)
|
(Addr {sym} base) => (LEAQ {sym} base)
|
||||||
(LocalAddr {sym} base _) => (LEAQ {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (LEAQ {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (LEAQ {sym} base)
|
||||||
|
|
||||||
(MOVBstore [off] {sym} ptr y:(SETL x) mem) && y.Uses == 1 => (SETLstore [off] {sym} ptr x mem)
|
(MOVBstore [off] {sym} ptr y:(SETL x) mem) && y.Uses == 1 => (SETLstore [off] {sym} ptr x mem)
|
||||||
(MOVBstore [off] {sym} ptr y:(SETLE x) mem) && y.Uses == 1 => (SETLEstore [off] {sym} ptr x mem)
|
(MOVBstore [off] {sym} ptr y:(SETLE x) mem) && y.Uses == 1 => (SETLEstore [off] {sym} ptr x mem)
|
||||||
|
@ -248,7 +248,8 @@
|
|||||||
(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
|
(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVWaddr {sym} base)
|
(Addr {sym} base) => (MOVWaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVWaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVWaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVWaddr {sym} base)
|
||||||
|
|
||||||
// loads
|
// loads
|
||||||
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
||||||
|
@ -350,7 +350,8 @@
|
|||||||
(OffPtr [off] ptr) => (ADDconst [off] ptr)
|
(OffPtr [off] ptr) => (ADDconst [off] ptr)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVDaddr {sym} base)
|
(Addr {sym} base) => (MOVDaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVDaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVDaddr {sym} base)
|
||||||
|
|
||||||
// loads
|
// loads
|
||||||
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
||||||
|
@ -227,7 +227,8 @@
|
|||||||
(OffPtr [off] ptr) => (ADDVconst [off] ptr)
|
(OffPtr [off] ptr) => (ADDVconst [off] ptr)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVVaddr {sym} base)
|
(Addr {sym} base) => (MOVVaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVVaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVVaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVVaddr {sym} base)
|
||||||
|
|
||||||
// loads
|
// loads
|
||||||
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
||||||
|
@ -210,7 +210,8 @@
|
|||||||
(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
|
(OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVWaddr {sym} base)
|
(Addr {sym} base) => (MOVWaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVWaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVWaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVWaddr {sym} base)
|
||||||
|
|
||||||
// loads
|
// loads
|
||||||
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
||||||
|
@ -219,7 +219,8 @@
|
|||||||
(OffPtr [off] ptr) => (ADDVconst [off] ptr)
|
(OffPtr [off] ptr) => (ADDVconst [off] ptr)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVVaddr {sym} base)
|
(Addr {sym} base) => (MOVVaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVVaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVVaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVVaddr {sym} base)
|
||||||
|
|
||||||
// loads
|
// loads
|
||||||
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
(Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
|
||||||
|
@ -233,7 +233,8 @@
|
|||||||
(S(RAW|RW|LW) x (MOVDconst [c])) => (S(RAW|RW|LW)const [c&31 | (c>>5&1*31)] x)
|
(S(RAW|RW|LW) x (MOVDconst [c])) => (S(RAW|RW|LW)const [c&31 | (c>>5&1*31)] x)
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVDaddr {sym} [0] base)
|
(Addr {sym} base) => (MOVDaddr {sym} [0] base)
|
||||||
(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVDaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVDaddr {sym} base)
|
||||||
(OffPtr [off] ptr) => (ADD (MOVDconst <typ.Int64> [off]) ptr)
|
(OffPtr [off] ptr) => (ADD (MOVDconst <typ.Int64> [off]) ptr)
|
||||||
|
|
||||||
// TODO: optimize these cases?
|
// TODO: optimize these cases?
|
||||||
|
@ -547,7 +547,8 @@
|
|||||||
(ConstBool [val]) => (MOVDconst [int64(b2i(val))])
|
(ConstBool [val]) => (MOVDconst [int64(b2i(val))])
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVaddr {sym} [0] base)
|
(Addr {sym} base) => (MOVaddr {sym} [0] base)
|
||||||
(LocalAddr {sym} base _) => (MOVaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVaddr {sym} base)
|
||||||
|
|
||||||
// Calls
|
// Calls
|
||||||
(StaticCall ...) => (CALLstatic ...)
|
(StaticCall ...) => (CALLstatic ...)
|
||||||
|
@ -446,7 +446,8 @@
|
|||||||
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
||||||
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
||||||
(Addr {sym} base) => (MOVDaddr {sym} base)
|
(Addr {sym} base) => (MOVDaddr {sym} base)
|
||||||
(LocalAddr {sym} base _) => (MOVDaddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (MOVDaddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (MOVDaddr {sym} base)
|
||||||
(ITab (Load ptr mem)) => (MOVDload ptr mem)
|
(ITab (Load ptr mem)) => (MOVDload ptr mem)
|
||||||
|
|
||||||
// block rewrites
|
// block rewrites
|
||||||
|
@ -304,7 +304,8 @@
|
|||||||
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
||||||
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
||||||
(Addr {sym} base) => (LoweredAddr {sym} [0] base)
|
(Addr {sym} base) => (LoweredAddr {sym} [0] base)
|
||||||
(LocalAddr {sym} base _) => (LoweredAddr {sym} base)
|
(LocalAddr <t> {sym} base mem) && t.Elem().HasPointers() => (LoweredAddr {sym} (SPanchored base mem))
|
||||||
|
(LocalAddr <t> {sym} base _) && !t.Elem().HasPointers() => (LoweredAddr {sym} base)
|
||||||
|
|
||||||
// Write barrier.
|
// Write barrier.
|
||||||
(WB ...) => (LoweredWB ...)
|
(WB ...) => (LoweredWB ...)
|
||||||
|
@ -352,6 +352,7 @@ var genericOps = []opData{
|
|||||||
{name: "SP", zeroWidth: true}, // stack pointer
|
{name: "SP", zeroWidth: true}, // stack pointer
|
||||||
{name: "SB", typ: "Uintptr", zeroWidth: true}, // static base pointer (a.k.a. globals pointer)
|
{name: "SB", typ: "Uintptr", zeroWidth: true}, // static base pointer (a.k.a. globals pointer)
|
||||||
{name: "Invalid"}, // unused value
|
{name: "Invalid"}, // unused value
|
||||||
|
{name: "SPanchored", typ: "Uintptr", argLength: 2, zeroWidth: true}, // arg0 = SP, arg1 = mem. Result is identical to arg0, but cannot be scheduled before memory state arg1.
|
||||||
|
|
||||||
// Memory operations
|
// Memory operations
|
||||||
{name: "Load", argLength: 2}, // Load from arg0. arg1=memory
|
{name: "Load", argLength: 2}, // Load from arg0. arg1=memory
|
||||||
|
@ -29,7 +29,7 @@ func checkLower(f *Func) {
|
|||||||
continue // lowered
|
continue // lowered
|
||||||
}
|
}
|
||||||
switch v.Op {
|
switch v.Op {
|
||||||
case OpSP, OpSB, OpInitMem, OpArg, OpArgIntReg, OpArgFloatReg, OpPhi, OpVarDef, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpSelectN, OpConvert, OpInlMark:
|
case OpSP, OpSPanchored, OpSB, OpInitMem, OpArg, OpArgIntReg, OpArgFloatReg, OpPhi, OpVarDef, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpSelectN, OpConvert, OpInlMark:
|
||||||
continue // ok not to lower
|
continue // ok not to lower
|
||||||
case OpMakeResult:
|
case OpMakeResult:
|
||||||
if b.Controls[0] == v {
|
if b.Controls[0] == v {
|
||||||
|
@ -3008,6 +3008,7 @@ const (
|
|||||||
OpLocalAddr
|
OpLocalAddr
|
||||||
OpSP
|
OpSP
|
||||||
OpSB
|
OpSB
|
||||||
|
OpSPanchored
|
||||||
OpLoad
|
OpLoad
|
||||||
OpDereference
|
OpDereference
|
||||||
OpStore
|
OpStore
|
||||||
@ -38818,6 +38819,12 @@ var opcodeTable = [...]opInfo{
|
|||||||
zeroWidth: true,
|
zeroWidth: true,
|
||||||
generic: true,
|
generic: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "SPanchored",
|
||||||
|
argLen: 2,
|
||||||
|
zeroWidth: true,
|
||||||
|
generic: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Load",
|
name: "Load",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
|
@ -839,9 +839,7 @@ func isSamePtr(p1, p2 *Value) bool {
|
|||||||
case OpOffPtr:
|
case OpOffPtr:
|
||||||
return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0])
|
return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0])
|
||||||
case OpAddr, OpLocalAddr:
|
case OpAddr, OpLocalAddr:
|
||||||
// OpAddr's 0th arg is either OpSP or OpSB, which means that it is uniquely identified by its Op.
|
return p1.Aux == p2.Aux
|
||||||
// Checking for value equality only works after [z]cse has run.
|
|
||||||
return p1.Aux == p2.Aux && p1.Args[0].Op == p2.Args[0].Op
|
|
||||||
case OpAddPtr:
|
case OpAddPtr:
|
||||||
return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0])
|
return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0])
|
||||||
}
|
}
|
||||||
|
@ -9050,17 +9050,44 @@ func rewriteValue386_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValue386_OpLocalAddr(v *Value) bool {
|
func rewriteValue386_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (LEAL {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (LEAL {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(Op386LEAL)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (LEAL {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(Op386LEAL)
|
v.reset(Op386LEAL)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValue386_OpLsh16x16(v *Value) bool {
|
func rewriteValue386_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -29388,17 +29388,44 @@ func rewriteValueAMD64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueAMD64_OpLocalAddr(v *Value) bool {
|
func rewriteValueAMD64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (LEAQ {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (LEAQ {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAMD64LEAQ)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (LEAQ {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpAMD64LEAQ)
|
v.reset(OpAMD64LEAQ)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueAMD64_OpLsh16x16(v *Value) bool {
|
func rewriteValueAMD64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -14047,17 +14047,44 @@ func rewriteValueARM_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM_OpLocalAddr(v *Value) bool {
|
func rewriteValueARM_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVWaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVWaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARMMOVWaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVWaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpARMMOVWaddr)
|
v.reset(OpARMMOVWaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM_OpLsh16x16(v *Value) bool {
|
func rewriteValueARM_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -24790,17 +24790,44 @@ func rewriteValueARM64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpLocalAddr(v *Value) bool {
|
func rewriteValueARM64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVDaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64MOVDaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpARM64MOVDaddr)
|
v.reset(OpARM64MOVDaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpLsh16x16(v *Value) bool {
|
func rewriteValueARM64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -4628,17 +4628,44 @@ func rewriteValueLOONG64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueLOONG64_OpLocalAddr(v *Value) bool {
|
func rewriteValueLOONG64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVVaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVVaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpLOONG64MOVVaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVVaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpLOONG64MOVVaddr)
|
v.reset(OpLOONG64MOVVaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueLOONG64_OpLsh16x16(v *Value) bool {
|
func rewriteValueLOONG64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -1653,17 +1653,44 @@ func rewriteValueMIPS_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueMIPS_OpLocalAddr(v *Value) bool {
|
func rewriteValueMIPS_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVWaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVWaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpMIPSMOVWaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVWaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpMIPSMOVWaddr)
|
v.reset(OpMIPSMOVWaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueMIPS_OpLsh16x16(v *Value) bool {
|
func rewriteValueMIPS_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -1848,17 +1848,44 @@ func rewriteValueMIPS64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueMIPS64_OpLocalAddr(v *Value) bool {
|
func rewriteValueMIPS64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVVaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVVaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpMIPS64MOVVaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVVaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpMIPS64MOVVaddr)
|
v.reset(OpMIPS64MOVVaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueMIPS64_OpLsh16x16(v *Value) bool {
|
func rewriteValueMIPS64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -2352,17 +2352,44 @@ func rewriteValuePPC64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpLocalAddr(v *Value) bool {
|
func rewriteValuePPC64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVDaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpPPC64MOVDaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpPPC64MOVDaddr)
|
v.reset(OpPPC64MOVDaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpLsh16x16(v *Value) bool {
|
func rewriteValuePPC64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -1607,17 +1607,44 @@ func rewriteValueRISCV64_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpLocalAddr(v *Value) bool {
|
func rewriteValueRISCV64_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64MOVaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpRISCV64MOVaddr)
|
v.reset(OpRISCV64MOVaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpLsh16x16(v *Value) bool {
|
func rewriteValueRISCV64_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -2460,17 +2460,44 @@ func rewriteValueS390X_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueS390X_OpLocalAddr(v *Value) bool {
|
func rewriteValueS390X_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (MOVDaddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpS390XMOVDaddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (MOVDaddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpS390XMOVDaddr)
|
v.reset(OpS390XMOVDaddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueS390X_OpLsh16x16(v *Value) bool {
|
func rewriteValueS390X_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -1487,17 +1487,44 @@ func rewriteValueWasm_OpLoad(v *Value) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueWasm_OpLocalAddr(v *Value) bool {
|
func rewriteValueWasm_OpLocalAddr(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (LocalAddr {sym} base _)
|
b := v.Block
|
||||||
// result: (LoweredAddr {sym} base)
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (LocalAddr <t> {sym} base mem)
|
||||||
|
// cond: t.Elem().HasPointers()
|
||||||
|
// result: (LoweredAddr {sym} (SPanchored base mem))
|
||||||
for {
|
for {
|
||||||
|
t := v.Type
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
base := v_0
|
base := v_0
|
||||||
|
mem := v_1
|
||||||
|
if !(t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpWasmLoweredAddr)
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpSPanchored, typ.Uintptr)
|
||||||
|
v0.AddArg2(base, mem)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LocalAddr <t> {sym} base _)
|
||||||
|
// cond: !t.Elem().HasPointers()
|
||||||
|
// result: (LoweredAddr {sym} base)
|
||||||
|
for {
|
||||||
|
t := v.Type
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
base := v_0
|
||||||
|
if !(!t.Elem().HasPointers()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
v.reset(OpWasmLoweredAddr)
|
v.reset(OpWasmLoweredAddr)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v.AddArg(base)
|
v.AddArg(base)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueWasm_OpLsh16x16(v *Value) bool {
|
func rewriteValueWasm_OpLsh16x16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"container/heap"
|
"container/heap"
|
||||||
"sort"
|
"sort"
|
||||||
@ -365,6 +366,34 @@ func schedule(f *Func) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove SPanchored now that we've scheduled.
|
||||||
|
for _, b := range f.Blocks {
|
||||||
|
for _, v := range b.Values {
|
||||||
|
for i, a := range v.Args {
|
||||||
|
if a.Op == OpSPanchored {
|
||||||
|
v.SetArg(i, a.Args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, b := range f.Blocks {
|
||||||
|
i := 0
|
||||||
|
for _, v := range b.Values {
|
||||||
|
if v.Op == OpSPanchored {
|
||||||
|
// Free this value
|
||||||
|
if v.Uses != 0 {
|
||||||
|
base.Fatalf("SPAnchored still has %d uses", v.Uses)
|
||||||
|
}
|
||||||
|
v.resetArgs()
|
||||||
|
f.freeValue(v)
|
||||||
|
} else {
|
||||||
|
b.Values[i] = v
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.truncateValues(i)
|
||||||
|
}
|
||||||
|
|
||||||
f.scheduled = true
|
f.scheduled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,14 +316,14 @@ func ConstMods(n1 uint, n2 int) (uint, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that divisibility checks x%c==0 are converted to MULs and rotates
|
// Check that divisibility checks x%c==0 are converted to MULs and rotates
|
||||||
func Divisible(n1 uint, n2 int) (bool, bool, bool, bool) {
|
func DivisibleU(n uint) (bool, bool) {
|
||||||
// amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ"
|
// amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ"
|
||||||
// 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
|
// 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
|
||||||
// arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ROR",-"DIV"
|
// arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ROR",-"DIV"
|
||||||
// arm:"MUL","CMP\t[$]715827882",-".*udiv"
|
// arm:"MUL","CMP\t[$]715827882",-".*udiv"
|
||||||
// ppc64:"MULLD","ROTL\t[$]63"
|
// ppc64:"MULLD","ROTL\t[$]63"
|
||||||
// ppc64le:"MULLD","ROTL\t[$]63"
|
// ppc64le:"MULLD","ROTL\t[$]63"
|
||||||
evenU := n1%6 == 0
|
even := n%6 == 0
|
||||||
|
|
||||||
// amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ"
|
// amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ"
|
||||||
// 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ"
|
// 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ"
|
||||||
@ -331,17 +331,21 @@ func Divisible(n1 uint, n2 int) (bool, bool, bool, bool) {
|
|||||||
// arm:"MUL","CMP\t[$]226050910",-".*udiv"
|
// arm:"MUL","CMP\t[$]226050910",-".*udiv"
|
||||||
// ppc64:"MULLD",-"ROTL"
|
// ppc64:"MULLD",-"ROTL"
|
||||||
// ppc64le:"MULLD",-"ROTL"
|
// ppc64le:"MULLD",-"ROTL"
|
||||||
oddU := n1%19 == 0
|
odd := n%19 == 0
|
||||||
|
|
||||||
|
return even, odd
|
||||||
|
}
|
||||||
|
|
||||||
|
func Divisible(n int) (bool, bool) {
|
||||||
// amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ"
|
// amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ"
|
||||||
// 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ"
|
// 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ"
|
||||||
// arm64:"MUL","ADD\tR","ROR",-"DIV"
|
// arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ADD\tR","ROR",-"DIV"
|
||||||
// arm:"MUL","ADD\t[$]715827882",-".*udiv"
|
// arm:"MUL","ADD\t[$]715827882",-".*udiv"
|
||||||
// ppc64/power8:"MULLD","ADD","ROTL\t[$]63"
|
// ppc64/power8:"MULLD","ADD","ROTL\t[$]63"
|
||||||
// ppc64le/power8:"MULLD","ADD","ROTL\t[$]63"
|
// ppc64le/power8:"MULLD","ADD","ROTL\t[$]63"
|
||||||
// ppc64/power9:"MADDLD","ROTL\t[$]63"
|
// ppc64/power9:"MADDLD","ROTL\t[$]63"
|
||||||
// ppc64le/power9:"MADDLD","ROTL\t[$]63"
|
// ppc64le/power9:"MADDLD","ROTL\t[$]63"
|
||||||
evenS := n2%6 == 0
|
even := n%6 == 0
|
||||||
|
|
||||||
// amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ"
|
// amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ"
|
||||||
// 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ"
|
// 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ"
|
||||||
@ -351,9 +355,9 @@ func Divisible(n1 uint, n2 int) (bool, bool, bool, bool) {
|
|||||||
// ppc64/power9:"MADDLD",-"ROTL"
|
// ppc64/power9:"MADDLD",-"ROTL"
|
||||||
// ppc64le/power8:"MULLD","ADD",-"ROTL"
|
// ppc64le/power8:"MULLD","ADD",-"ROTL"
|
||||||
// ppc64le/power9:"MADDLD",-"ROTL"
|
// ppc64le/power9:"MADDLD",-"ROTL"
|
||||||
oddS := n2%19 == 0
|
odd := n%19 == 0
|
||||||
|
|
||||||
return evenU, oddU, evenS, oddS
|
return even, odd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that fix-up code is not generated for divisions where it has been proven that
|
// Check that fix-up code is not generated for divisions where it has been proven that
|
||||||
|
@ -6,16 +6,12 @@
|
|||||||
|
|
||||||
package codegen
|
package codegen
|
||||||
|
|
||||||
var gx, gy int
|
|
||||||
|
|
||||||
// Test to make sure that (CMPQ (ANDQ x y) [0]) does not get rewritten to
|
// Test to make sure that (CMPQ (ANDQ x y) [0]) does not get rewritten to
|
||||||
// (TESTQ x y) if the ANDQ has other uses. If that rewrite happens, then one
|
// (TESTQ x y) if the ANDQ has other uses. If that rewrite happens, then one
|
||||||
// of the args of the ANDQ needs to be saved so it can be used as the arg to TESTQ.
|
// of the args of the ANDQ needs to be saved so it can be used as the arg to TESTQ.
|
||||||
func andWithUse(x, y int) int {
|
func andWithUse(x, y int) int {
|
||||||
// Load x,y into registers, so those MOVQ will not appear at the z := x&y line.
|
|
||||||
gx, gy = x, y
|
|
||||||
// amd64:-"MOVQ"
|
|
||||||
z := x & y
|
z := x & y
|
||||||
|
// amd64:`TESTQ\s(AX, AX|BX, BX|CX, CX|DX, DX|SI, SI|DI, DI|R8, R8|R9, R9|R10, R10|R11, R11|R12, R12|R13, R13|R15, R15)`
|
||||||
if z == 0 {
|
if z == 0 {
|
||||||
return 77
|
return 77
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user