]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: add anchored version of SP
authorKeith Randall <khr@golang.org>
Tue, 22 Nov 2022 06:22:36 +0000 (22:22 -0800)
committerKeith Randall <khr@google.com>
Thu, 19 Jan 2023 22:43:12 +0000 (22:43 +0000)
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>
29 files changed:
src/cmd/compile/internal/ssa/_gen/386.rules
src/cmd/compile/internal/ssa/_gen/AMD64.rules
src/cmd/compile/internal/ssa/_gen/ARM.rules
src/cmd/compile/internal/ssa/_gen/ARM64.rules
src/cmd/compile/internal/ssa/_gen/LOONG64.rules
src/cmd/compile/internal/ssa/_gen/MIPS.rules
src/cmd/compile/internal/ssa/_gen/MIPS64.rules
src/cmd/compile/internal/ssa/_gen/PPC64.rules
src/cmd/compile/internal/ssa/_gen/RISCV64.rules
src/cmd/compile/internal/ssa/_gen/S390X.rules
src/cmd/compile/internal/ssa/_gen/Wasm.rules
src/cmd/compile/internal/ssa/_gen/genericOps.go
src/cmd/compile/internal/ssa/lower.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewrite386.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/cmd/compile/internal/ssa/rewriteARM.go
src/cmd/compile/internal/ssa/rewriteARM64.go
src/cmd/compile/internal/ssa/rewriteLOONG64.go
src/cmd/compile/internal/ssa/rewriteMIPS.go
src/cmd/compile/internal/ssa/rewriteMIPS64.go
src/cmd/compile/internal/ssa/rewritePPC64.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go
src/cmd/compile/internal/ssa/rewriteS390X.go
src/cmd/compile/internal/ssa/rewriteWasm.go
src/cmd/compile/internal/ssa/schedule.go
test/codegen/arithmetic.go
test/codegen/logic.go

index 5e30ca9fd74a12d9ad8100c79ee54ddb92d2af8a..88074e5fd081301115be1fbb14f7a1cf72ccb5ca 100644 (file)
 (GetCallerPC ...) => (LoweredGetCallerPC ...)
 (GetCallerSP ...) => (LoweredGetCallerSP ...)
 (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
 (If (SETL  cmp) yes no) => (LT  cmp yes no)
index ccb52956224bf81c5fcac44be6ee57d45dd67626..c50710ec90c6d39aa91d22f1754e224a5a953ee5 100644 (file)
 
 (HasCPUFeature {s}) => (SETNE (CMPLconst [0] (LoweredHasCPUFeature {s})))
 (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:(SETLE x) mem) && y.Uses == 1 => (SETLEstore [off] {sym} ptr x mem)
index e5898b036913fbb033f46e04bf72aa1c72d64139..d8fbf41754e74f1dfaf8f15e39d90263ef1a9716 100644 (file)
 (OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
 
 (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
 (Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
index 0c5a2e66a8ca7545d0d2187c145fc1dd77aa4a2e..0ae02f5de370c88874cdf491561908fd178df407 100644 (file)
 (OffPtr [off] ptr) => (ADDconst [off] ptr)
 
 (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
 (Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
index 1caaf13600d47429d337281e42b00e8ae3ee2374..7e445e506e55480e227f90a021a39d699b1e4b6e 100644 (file)
 (OffPtr [off] ptr) => (ADDVconst [off] ptr)
 
 (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
 (Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
index 6f696da3cc847237f9792fb9751af98897b458dd..9cd5a1618e0b03e4fba9ee6d868ec6a3697d678e 100644 (file)
 (OffPtr [off] ptr) => (ADDconst [int32(off)] ptr)
 
 (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
 (Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
index a594df2b266838bfcbd677f5f4fb5b383b81f00a..b0d0dd8e665dbc9e35fcf31f24d0911cc8f655d9 100644 (file)
 (OffPtr [off] ptr) => (ADDVconst [off] ptr)
 
 (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
 (Load <t> ptr mem) && t.IsBoolean() => (MOVBUload ptr mem)
index 5a68de0ca4dadff18c19b4c37b09094998b9ecee..2eda1af3bfc943f172b003fffb4ef83fb639977f 100644 (file)
 (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)
-(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)
 
 // TODO: optimize these cases?
index 59f71be5bafd6e88a990024390729610c7f890af..802b1dd1fd64393e3e327b92e52976884772fce4 100644 (file)
 (ConstBool [val]) => (MOVDconst [int64(b2i(val))])
 
 (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
 (StaticCall  ...) => (CALLstatic  ...)
index e9becb2e17f32d0882810aa2e36edf7628123360..9495010a736bad75f909c2cc95f57b2bb7f5974a 100644 (file)
 (GetCallerSP ...) => (LoweredGetCallerSP ...)
 (GetCallerPC ...) => (LoweredGetCallerPC ...)
 (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)
 
 // block rewrites
index a9ed82e45669d54e450b4913598ada1b81c9929d..e31808ebe175a3ac37f0ce7c7a83613483481193 100644 (file)
 (GetCallerPC ...) => (LoweredGetCallerPC ...)
 (GetCallerSP ...) => (LoweredGetCallerSP ...)
 (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.
 (WB ...) => (LoweredWB ...)
index a4c8fc9c6925daefd8e4533b424985e3fb51e3fd..40c9baf5f1e82bcae4586b111689822de84a4206 100644 (file)
@@ -349,9 +349,10 @@ var genericOps = []opData{
        {name: "Addr", argLength: 1, aux: "Sym", symEffect: "Addr"},      // Address of a variable.  Arg0=SB.  Aux identifies the variable.
        {name: "LocalAddr", argLength: 2, aux: "Sym", symEffect: "Addr"}, // Address of a variable.  Arg0=SP. Arg1=mem. Aux identifies the variable.
 
-       {name: "SP", zeroWidth: true},                 // stack pointer
-       {name: "SB", typ: "Uintptr", zeroWidth: true}, // static base pointer (a.k.a. globals pointer)
-       {name: "Invalid"},                             // unused value
+       {name: "SP", zeroWidth: true},                                       // stack pointer
+       {name: "SB", typ: "Uintptr", zeroWidth: true},                       // static base pointer (a.k.a. globals pointer)
+       {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
        {name: "Load", argLength: 2},                          // Load from arg0.  arg1=memory
index 0b79d77c504b73c3e6107da34680e7da5771d0b2..88eb6748e86f8c0461a0381b0747252f1985b5c0 100644 (file)
@@ -29,7 +29,7 @@ func checkLower(f *Func) {
                                continue // lowered
                        }
                        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
                        case OpMakeResult:
                                if b.Controls[0] == v {
index 9ff0ad353e0718e482e53119550ba64ab63127d3..c59cfdd9ef1933e7db3f62286d04cef55e7bc2f1 100644 (file)
@@ -3008,6 +3008,7 @@ const (
        OpLocalAddr
        OpSP
        OpSB
+       OpSPanchored
        OpLoad
        OpDereference
        OpStore
@@ -38818,6 +38819,12 @@ var opcodeTable = [...]opInfo{
                zeroWidth: true,
                generic:   true,
        },
+       {
+               name:      "SPanchored",
+               argLen:    2,
+               zeroWidth: true,
+               generic:   true,
+       },
        {
                name:    "Load",
                argLen:  2,
index f4ac97c5eb7afcb8c066c58735fe1a5655fbc6d2..84bf2047d42d97f9bbfd030bc880539c8c7989a6 100644 (file)
@@ -839,9 +839,7 @@ func isSamePtr(p1, p2 *Value) bool {
        case OpOffPtr:
                return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0])
        case OpAddr, OpLocalAddr:
-               // OpAddr's 0th arg is either OpSP or OpSB, which means that it is uniquely identified by its Op.
-               // Checking for value equality only works after [z]cse has run.
-               return p1.Aux == p2.Aux && p1.Args[0].Op == p2.Args[0].Op
+               return p1.Aux == p2.Aux
        case OpAddPtr:
                return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0])
        }
index a7671e919060fe1495403b38822ee548542aea20..064173a946bbf97c5e3e4d18232774ef188ceb8b 100644 (file)
@@ -9050,17 +9050,44 @@ func rewriteValue386_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValue386_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (LEAL {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValue386_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 395b2b1e6e396ee299812305d540ce159d915b69..fa00bd4f5fbd9cd91af2fc3ef1bb9fb438afbb4c 100644 (file)
@@ -29388,17 +29388,44 @@ func rewriteValueAMD64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueAMD64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (LEAQ {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueAMD64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index c31d89c1fd2e6ea52e2c3da94e7feea0819651e2..6ea1a7e4b26afaad386d53b9223d68f91d324ddf 100644 (file)
@@ -14047,17 +14047,44 @@ func rewriteValueARM_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueARM_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVWaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueARM_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 88c690be1f6788f31d96251cba7a69d741b2f3f9..6f02b507e823f8d6f32a1b72733896fc77943f18 100644 (file)
@@ -24790,17 +24790,44 @@ func rewriteValueARM64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueARM64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVDaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueARM64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 451b8313ebdeb66fd6a1d7b92631b6f3632bb8f7..3c783a3037bbded85c1aeb6f433cada31b133adb 100644 (file)
@@ -4628,17 +4628,44 @@ func rewriteValueLOONG64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueLOONG64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVVaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueLOONG64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index f1e4970af832599f287ed3cd03d626676e3648ca..a8cda7644a7c1fff0faa1efe2f334f74d324c0d9 100644 (file)
@@ -1653,17 +1653,44 @@ func rewriteValueMIPS_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueMIPS_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVWaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueMIPS_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 14d39babf2a7987fb936c4696538a9032a72a7a0..82d52f0b3f3479b03b8f0f06fb9f4c4d06c5db07 100644 (file)
@@ -1848,17 +1848,44 @@ func rewriteValueMIPS64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueMIPS64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVVaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueMIPS64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 192ec49d824a119f9e9123f8caf9ba716c4f450b..aee570df7a68fa66e0489035c462f6d451078f0b 100644 (file)
@@ -2352,17 +2352,44 @@ func rewriteValuePPC64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValuePPC64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVDaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValuePPC64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 5107b9a96fd481cc2d48b7736feaefe4f94c2353..66a6967db4cd0aa78f37524a95af1eaca09c8633 100644 (file)
@@ -1607,17 +1607,44 @@ func rewriteValueRISCV64_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueRISCV64_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueRISCV64_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 597941c26d40168819361b6e3830971ca8f39a5e..b766156b437051f747a3a2d7e3ad958ee8b34bff 100644 (file)
@@ -2460,17 +2460,44 @@ func rewriteValueS390X_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueS390X_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (MOVDaddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueS390X_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 818003c4a75afe926d55981a52744288d171e25e..bb35d8e663ce93d6de66cd9674dc66f609f3822f 100644 (file)
@@ -1487,17 +1487,44 @@ func rewriteValueWasm_OpLoad(v *Value) bool {
        return false
 }
 func rewriteValueWasm_OpLocalAddr(v *Value) bool {
+       v_1 := v.Args[1]
        v_0 := v.Args[0]
-       // match: (LocalAddr {sym} base _)
+       b := v.Block
+       typ := &b.Func.Config.Types
+       // match: (LocalAddr <t> {sym} base mem)
+       // cond: t.Elem().HasPointers()
+       // result: (LoweredAddr {sym} (SPanchored base mem))
+       for {
+               t := v.Type
+               sym := auxToSym(v.Aux)
+               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.Aux = symToAux(sym)
                v.AddArg(base)
                return true
        }
+       return false
 }
 func rewriteValueWasm_OpLsh16x16(v *Value) bool {
        v_1 := v.Args[1]
index 4e762f7b3fd223a4808f2103b3e1d64f743b63a1..d88c33f3046bf5c5334ce37d7ce5a500b002212a 100644 (file)
@@ -5,6 +5,7 @@
 package ssa
 
 import (
+       "cmd/compile/internal/base"
        "cmd/compile/internal/types"
        "container/heap"
        "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
 }
 
index 327be24db8125f7ea9aaa98556c62e40130e10f3..5139d1340a392096fdc7c2ae275c8951cbaaa4bc 100644 (file)
@@ -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
-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"
        // 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
        // arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ROR",-"DIV"
        // arm:"MUL","CMP\t[$]715827882",-".*udiv"
        // ppc64:"MULLD","ROTL\t[$]63"
        // ppc64le:"MULLD","ROTL\t[$]63"
-       evenU := n1%6 == 0
+       even := n%6 == 0
 
        // amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"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"
        // ppc64:"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"
        // 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"
        // ppc64/power8:"MULLD","ADD","ROTL\t[$]63"
        // ppc64le/power8:"MULLD","ADD","ROTL\t[$]63"
        // ppc64/power9:"MADDLD","ROTL\t[$]63"
        // ppc64le/power9:"MADDLD","ROTL\t[$]63"
-       evenS := n2%6 == 0
+       even := n%6 == 0
 
        // amd64:"IMULQ","ADD",-"ROLQ",-"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"
        // ppc64le/power8:"MULLD","ADD",-"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
index 50ce5f0cca87821d685c535467ab4bbf7a80fdef..f761e7bb9ae6e009711c72488f9078d080d52e1a 100644 (file)
@@ -6,16 +6,12 @@
 
 package codegen
 
-var gx, gy int
-
 // 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
 // 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 {
-       // 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
+       // 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 {
                return 77
        }