From: Xiaolin Zhao Date: Wed, 3 Sep 2025 01:41:08 +0000 (+0800) Subject: cmd/compile: simplify memory load and store operations on loong64 X-Git-Tag: go1.26rc1~973 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c552ad913f;p=gostls13.git cmd/compile: simplify memory load and store operations on loong64 If the memory load and store operations use the same ptr, they are combined into a direct move operation between registers, like riscv64. Change-Id: I889e51a5146aee7f15340114bc4abd12eb6b8a1f Reviewed-on: https://go-review.googlesource.com/c/go/+/700535 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: abner chenc Reviewed-by: Michael Pratt Auto-Submit: Keith Randall --- diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules index a4a6e901e3..cb55c16c3e 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules @@ -455,6 +455,10 @@ (MOVWUload [off] {sym} ptr (MOVFstore [off] {sym} ptr val _)) => (ZeroExt32to64 (MOVWfpgp val)) (MOVFload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _)) => (MOVWgpfp val) +// If the memory load and store operations use the same ptr, they are combined into a direct move operation between registers. +(MOV(V|W|H|B)load [off] {sym} ptr (MOV(V|W|H|B)store [off] {sym} ptr x _)) => (MOV(V|W|H|B)reg x) +(MOV(W|H|B)Uload [off] {sym} ptr (MOV(W|H|B)store [off] {sym} ptr x _)) => (MOV(W|H|B)Ureg x) + // Similarly for stores, if we see a store after FPR <=> GPR move, then redirect store to use the other register set. (MOVVstore [off] {sym} ptr (MOVVfpgp val) mem) => (MOVDstore [off] {sym} ptr val mem) (MOVDstore [off] {sym} ptr (MOVVgpfp val) mem) => (MOVVstore [off] {sym} ptr val mem) diff --git a/src/cmd/compile/internal/ssa/rewriteLOONG64.go b/src/cmd/compile/internal/ssa/rewriteLOONG64.go index 00731f4b51..ae3358e5e5 100644 --- a/src/cmd/compile/internal/ssa/rewriteLOONG64.go +++ b/src/cmd/compile/internal/ssa/rewriteLOONG64.go @@ -2329,6 +2329,23 @@ func rewriteValueLOONG64_OpLOONG64MOVBUload(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (MOVBUload [off] {sym} ptr (MOVBstore [off] {sym} ptr x _)) + // result: (MOVBUreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVBstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVBUreg) + v.AddArg(x) + return true + } // match: (MOVBUload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVBUload [off1+int32(off2)] {sym} ptr mem) @@ -2606,6 +2623,23 @@ func rewriteValueLOONG64_OpLOONG64MOVBload(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (MOVBload [off] {sym} ptr (MOVBstore [off] {sym} ptr x _)) + // result: (MOVBreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVBstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVBreg) + v.AddArg(x) + return true + } // match: (MOVBload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVBload [off1+int32(off2)] {sym} ptr mem) @@ -3526,6 +3560,23 @@ func rewriteValueLOONG64_OpLOONG64MOVHUload(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (MOVHUload [off] {sym} ptr (MOVHstore [off] {sym} ptr x _)) + // result: (MOVHUreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVHstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVHUreg) + v.AddArg(x) + return true + } // match: (MOVHUload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVHUload [off1+int32(off2)] {sym} ptr mem) @@ -3765,6 +3816,23 @@ func rewriteValueLOONG64_OpLOONG64MOVHload(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (MOVHload [off] {sym} ptr (MOVHstore [off] {sym} ptr x _)) + // result: (MOVHreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVHstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVHreg) + v.AddArg(x) + return true + } // match: (MOVHload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVHload [off1+int32(off2)] {sym} ptr mem) @@ -4208,6 +4276,23 @@ func rewriteValueLOONG64_OpLOONG64MOVVload(v *Value) bool { v.AddArg(val) return true } + // match: (MOVVload [off] {sym} ptr (MOVVstore [off] {sym} ptr x _)) + // result: (MOVVreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVVstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVVreg) + v.AddArg(x) + return true + } // match: (MOVVload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVVload [off1+int32(off2)] {sym} ptr mem) @@ -4516,6 +4601,23 @@ func rewriteValueLOONG64_OpLOONG64MOVWUload(v *Value) bool { v.AddArg(v0) return true } + // match: (MOVWUload [off] {sym} ptr (MOVWstore [off] {sym} ptr x _)) + // result: (MOVWUreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVWUreg) + v.AddArg(x) + return true + } // match: (MOVWUload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVWUload [off1+int32(off2)] {sym} ptr mem) @@ -4788,6 +4890,23 @@ func rewriteValueLOONG64_OpLOONG64MOVWload(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (MOVWload [off] {sym} ptr (MOVWstore [off] {sym} ptr x _)) + // result: (MOVWreg x) + for { + off := auxIntToInt32(v.AuxInt) + sym := auxToSym(v.Aux) + ptr := v_0 + if v_1.Op != OpLOONG64MOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym { + break + } + x := v_1.Args[1] + if ptr != v_1.Args[0] { + break + } + v.reset(OpLOONG64MOVWreg) + v.AddArg(x) + return true + } // match: (MOVWload [off1] {sym} (ADDVconst [off2] ptr) mem) // cond: is32Bit(int64(off1)+off2) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) // result: (MOVWload [off1+int32(off2)] {sym} ptr mem)