cmd/compile: move mips32 over to new bounds check strategy

Change-Id: Ied54ea7bf68c4c943c621ca059aca1048903c041
Reviewed-on: https://go-review.googlesource.com/c/go/+/682497
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Julian Zhu <jz531210@gmail.com>
Reviewed-by: Mark Freeman <mark@golang.org>
This commit is contained in:
Keith Randall 2025-06-18 15:49:52 -07:00
parent 9f9d7b50e8
commit 8330fb48a6
6 changed files with 434 additions and 362 deletions

View file

@ -15,6 +15,7 @@ import (
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/obj/mips"
"internal/abi"
)
// isFPreg reports whether r is an FP register.
@ -486,18 +487,167 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
p.To.Name = obj.NAME_EXTERN
// AuxInt encodes how many buffer entries we need.
p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
case ssa.OpMIPSLoweredPanicBoundsA, ssa.OpMIPSLoweredPanicBoundsB, ssa.OpMIPSLoweredPanicBoundsC:
p := s.Prog(obj.ACALL)
case ssa.OpMIPSLoweredPanicBoundsRR, ssa.OpMIPSLoweredPanicBoundsRC, ssa.OpMIPSLoweredPanicBoundsCR, ssa.OpMIPSLoweredPanicBoundsCC,
ssa.OpMIPSLoweredPanicExtendRR, ssa.OpMIPSLoweredPanicExtendRC:
// Compute the constant we put in the PCData entry for this call.
code, signed := ssa.BoundsKind(v.AuxInt).Code()
xIsReg := false
yIsReg := false
xVal := 0
yVal := 0
extend := false
switch v.Op {
case ssa.OpMIPSLoweredPanicBoundsRR:
xIsReg = true
xVal = int(v.Args[0].Reg() - mips.REG_R1)
yIsReg = true
yVal = int(v.Args[1].Reg() - mips.REG_R1)
case ssa.OpMIPSLoweredPanicExtendRR:
extend = true
xIsReg = true
hi := int(v.Args[0].Reg() - mips.REG_R1)
lo := int(v.Args[1].Reg() - mips.REG_R1)
xVal = hi<<2 + lo // encode 2 register numbers
yIsReg = true
yVal = int(v.Args[2].Reg() - mips.REG_R1)
case ssa.OpMIPSLoweredPanicBoundsRC:
xIsReg = true
xVal = int(v.Args[0].Reg() - mips.REG_R1)
c := v.Aux.(ssa.PanicBoundsC).C
if c >= 0 && c <= abi.BoundsMaxConst {
yVal = int(c)
} else {
// Move constant to a register
yIsReg = true
if yVal == xVal {
yVal = 1
}
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(yVal)
}
case ssa.OpMIPSLoweredPanicExtendRC:
extend = true
xIsReg = true
hi := int(v.Args[0].Reg() - mips.REG_R1)
lo := int(v.Args[1].Reg() - mips.REG_R1)
xVal = hi<<2 + lo // encode 2 register numbers
c := v.Aux.(ssa.PanicBoundsC).C
if c >= 0 && c <= abi.BoundsMaxConst {
yVal = int(c)
} else {
// Move constant to a register
for yVal == hi || yVal == lo {
yVal++
}
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(yVal)
}
case ssa.OpMIPSLoweredPanicBoundsCR:
yIsReg = true
yVal := int(v.Args[0].Reg() - mips.REG_R1)
c := v.Aux.(ssa.PanicBoundsC).C
if c >= 0 && c <= abi.BoundsMaxConst {
xVal = int(c)
} else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
// Move constant to a register
xIsReg = true
if xVal == yVal {
xVal = 1
}
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(xVal)
} else {
// Move constant to two registers
extend = true
xIsReg = true
hi := 0
lo := 1
if hi == yVal {
hi = 2
}
if lo == yVal {
lo = 2
}
xVal = hi<<2 + lo
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c >> 32
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(hi)
p = s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(int32(c))
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(lo)
}
case ssa.OpMIPSLoweredPanicBoundsCC:
c := v.Aux.(ssa.PanicBoundsCC).Cx
if c >= 0 && c <= abi.BoundsMaxConst {
xVal = int(c)
} else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
// Move constant to a register
xIsReg = true
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(xVal)
} else {
// Move constant to two registers
extend = true
xIsReg = true
hi := 0
lo := 1
xVal = hi<<2 + lo
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c >> 32
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(hi)
p = s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(int32(c))
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(lo)
}
c = v.Aux.(ssa.PanicBoundsCC).Cy
if c >= 0 && c <= abi.BoundsMaxConst {
yVal = int(c)
} else {
// Move constant to a register
yIsReg = true
yVal = 2
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = c
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1 + int16(yVal)
}
}
c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
p := s.Prog(obj.APCDATA)
p.From.SetConst(abi.PCDATA_PanicBounds)
p.To.SetConst(int64(c))
p = s.Prog(obj.ACALL)
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_EXTERN
p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
s.UseArgs(8) // space used in callee args area by assembly stubs
case ssa.OpMIPSLoweredPanicExtendA, ssa.OpMIPSLoweredPanicExtendB, ssa.OpMIPSLoweredPanicExtendC:
p := s.Prog(obj.ACALL)
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_EXTERN
p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
s.UseArgs(12) // space used in callee args area by assembly stubs
if extend {
p.To.Sym = ir.Syms.PanicExtend
} else {
p.To.Sym = ir.Syms.PanicBounds
}
case ssa.OpMIPSLoweredAtomicLoad8,
ssa.OpMIPSLoweredAtomicLoad32:
s.Prog(mips.ASYNC)

View file

@ -423,13 +423,17 @@
// Publication barrier as intrinsic
(PubBarrier ...) => (LoweredPubBarrier ...)
(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 => (LoweredPanicExtendA [kind] hi lo y mem)
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 => (LoweredPanicExtendB [kind] hi lo y mem)
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 => (LoweredPanicExtendC [kind] hi lo y mem)
(PanicBounds ...) => (LoweredPanicBoundsRR ...)
(PanicExtend ...) => (LoweredPanicExtendRR ...)
(LoweredPanicBoundsRR [kind] x (MOVWconst [c]) mem) => (LoweredPanicBoundsRC [kind] x {PanicBoundsC{C:int64(c)}} mem)
(LoweredPanicBoundsRR [kind] (MOVWconst [c]) y mem) => (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(c)}} y mem)
(LoweredPanicBoundsRC [kind] {p} (MOVWconst [c]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(c), Cy:p.C}} mem)
(LoweredPanicExtendRR [kind] hi lo (MOVWconst [c]) mem) => (LoweredPanicExtendRC [kind] hi lo {PanicBoundsC{C:int64(c)}} mem)
(LoweredPanicExtendRR [kind] (MOVWconst [hi]) (MOVWconst [lo]) y mem) => (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(hi)<<32 + int64(uint32(lo))}} y mem)
(LoweredPanicExtendRC [kind] {p} (MOVWconst [hi]) (MOVWconst [lo]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(hi)<<32+int64(uint32(lo)), Cy:p.C}} mem)
// Optimizations

View file

@ -120,11 +120,8 @@ func init() {
lo = buildReg("LO")
hi = buildReg("HI")
callerSave = gp | fp | lo | hi | buildReg("g") // runtime.setg (and anything calling it) may clobber g
r1 = buildReg("R1")
r2 = buildReg("R2")
r3 = buildReg("R3")
r4 = buildReg("R4")
r5 = buildReg("R5")
first16 = buildReg("R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16")
first4 = buildReg("R1 R2 R3 R4")
)
// Common regInfo
var (
@ -411,16 +408,19 @@ func init() {
// Do data barrier. arg0=memorys
{name: "LoweredPubBarrier", argLength: 1, asm: "SYNC", hasSideEffects: true},
// There are three of these functions so that they can have three different register inputs.
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
// default registers to match so we don't need to copy registers around unnecessarily.
{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
// Extend ops are the same as Bounds ops except the indexes are 64-bit.
{name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r3, r4}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
{name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r2, r3}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
{name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r1, r2}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
// LoweredPanicBoundsRR takes x and y, two values that caused a bounds check to fail.
// the RC and CR versions are used when one of the arguments is a constant. CC is used
// when both are constant (normally both 0, as prove derives the fact that a [0] bounds
// failure means the length must have also been 0).
// AuxInt contains a report code (see PanicBounds in genericOps.go).
{name: "LoweredPanicBoundsRR", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{first16, first16}}, typ: "Mem", call: true}, // arg0=x, arg1=y, arg2=mem, returns memory.
{name: "LoweredPanicBoundsRC", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{first16}}, typ: "Mem", call: true}, // arg0=x, arg1=mem, returns memory.
{name: "LoweredPanicBoundsCR", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{first16}}, typ: "Mem", call: true}, // arg0=y, arg1=mem, returns memory.
{name: "LoweredPanicBoundsCC", argLength: 1, aux: "PanicBoundsCC", reg: regInfo{}, typ: "Mem", call: true}, // arg0=mem, returns memory.
// Same as above, but the x value is 64 bits.
{name: "LoweredPanicExtendRR", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{first4, first4, first16}}, typ: "Mem", call: true}, // arg0=x_hi, arg1=x_lo, arg2=y, arg3=mem, returns memory.
{name: "LoweredPanicExtendRC", argLength: 3, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{first4, first4}}, typ: "Mem", call: true}, // arg0=x_hi, arg1=x_lo, arg2=mem, returns memory.
}
blocks := []blockData{

View file

@ -2080,12 +2080,12 @@ const (
OpMIPSLoweredGetCallerPC
OpMIPSLoweredWB
OpMIPSLoweredPubBarrier
OpMIPSLoweredPanicBoundsA
OpMIPSLoweredPanicBoundsB
OpMIPSLoweredPanicBoundsC
OpMIPSLoweredPanicExtendA
OpMIPSLoweredPanicExtendB
OpMIPSLoweredPanicExtendC
OpMIPSLoweredPanicBoundsRR
OpMIPSLoweredPanicBoundsRC
OpMIPSLoweredPanicBoundsCR
OpMIPSLoweredPanicBoundsCC
OpMIPSLoweredPanicExtendRR
OpMIPSLoweredPanicExtendRC
OpMIPS64ADDV
OpMIPS64ADDVconst
@ -27994,77 +27994,68 @@ var opcodeTable = [...]opInfo{
reg: regInfo{},
},
{
name: "LoweredPanicBoundsA",
name: "LoweredPanicBoundsRR",
auxType: auxInt64,
argLen: 3,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 8}, // R3
{1, 16}, // R4
{0, 131070}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
{1, 131070}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
},
},
},
{
name: "LoweredPanicBoundsB",
name: "LoweredPanicBoundsRC",
auxType: auxPanicBoundsC,
argLen: 2,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 131070}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
},
},
},
{
name: "LoweredPanicBoundsCR",
auxType: auxPanicBoundsC,
argLen: 2,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 131070}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
},
},
},
{
name: "LoweredPanicBoundsCC",
auxType: auxPanicBoundsCC,
argLen: 1,
call: true,
reg: regInfo{},
},
{
name: "LoweredPanicExtendRR",
auxType: auxInt64,
argLen: 4,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 30}, // R1 R2 R3 R4
{1, 30}, // R1 R2 R3 R4
{2, 131070}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
},
},
},
{
name: "LoweredPanicExtendRC",
auxType: auxPanicBoundsC,
argLen: 3,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 4}, // R2
{1, 8}, // R3
},
},
},
{
name: "LoweredPanicBoundsC",
auxType: auxInt64,
argLen: 3,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 2}, // R1
{1, 4}, // R2
},
},
},
{
name: "LoweredPanicExtendA",
auxType: auxInt64,
argLen: 4,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 32}, // R5
{1, 8}, // R3
{2, 16}, // R4
},
},
},
{
name: "LoweredPanicExtendB",
auxType: auxInt64,
argLen: 4,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 32}, // R5
{1, 4}, // R2
{2, 8}, // R3
},
},
},
{
name: "LoweredPanicExtendC",
auxType: auxInt64,
argLen: 4,
call: true,
reg: regInfo{
inputs: []inputInfo{
{0, 32}, // R5
{1, 2}, // R1
{2, 4}, // R2
{0, 30}, // R1 R2 R3 R4
{1, 30}, // R1 R2 R3 R4
},
},
},

View file

@ -279,6 +279,14 @@ func rewriteValueMIPS(v *Value) bool {
return rewriteValueMIPS_OpMIPSLoweredAtomicAdd(v)
case OpMIPSLoweredAtomicStore32:
return rewriteValueMIPS_OpMIPSLoweredAtomicStore32(v)
case OpMIPSLoweredPanicBoundsRC:
return rewriteValueMIPS_OpMIPSLoweredPanicBoundsRC(v)
case OpMIPSLoweredPanicBoundsRR:
return rewriteValueMIPS_OpMIPSLoweredPanicBoundsRR(v)
case OpMIPSLoweredPanicExtendRC:
return rewriteValueMIPS_OpMIPSLoweredPanicExtendRC(v)
case OpMIPSLoweredPanicExtendRR:
return rewriteValueMIPS_OpMIPSLoweredPanicExtendRR(v)
case OpMIPSMOVBUload:
return rewriteValueMIPS_OpMIPSMOVBUload(v)
case OpMIPSMOVBUreg:
@ -447,9 +455,11 @@ func rewriteValueMIPS(v *Value) bool {
v.Op = OpMIPSOR
return true
case OpPanicBounds:
return rewriteValueMIPS_OpPanicBounds(v)
v.Op = OpMIPSLoweredPanicBoundsRR
return true
case OpPanicExtend:
return rewriteValueMIPS_OpPanicExtend(v)
v.Op = OpMIPSLoweredPanicExtendRR
return true
case OpPubBarrier:
v.Op = OpMIPSLoweredPubBarrier
return true
@ -2435,6 +2445,135 @@ func rewriteValueMIPS_OpMIPSLoweredAtomicStore32(v *Value) bool {
}
return false
}
func rewriteValueMIPS_OpMIPSLoweredPanicBoundsRC(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (LoweredPanicBoundsRC [kind] {p} (MOVWconst [c]) mem)
// result: (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(c), Cy:p.C}} mem)
for {
kind := auxIntToInt64(v.AuxInt)
p := auxToPanicBoundsC(v.Aux)
if v_0.Op != OpMIPSMOVWconst {
break
}
c := auxIntToInt32(v_0.AuxInt)
mem := v_1
v.reset(OpMIPSLoweredPanicBoundsCC)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCCToAux(PanicBoundsCC{Cx: int64(c), Cy: p.C})
v.AddArg(mem)
return true
}
return false
}
func rewriteValueMIPS_OpMIPSLoweredPanicBoundsRR(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (LoweredPanicBoundsRR [kind] x (MOVWconst [c]) mem)
// result: (LoweredPanicBoundsRC [kind] x {PanicBoundsC{C:int64(c)}} mem)
for {
kind := auxIntToInt64(v.AuxInt)
x := v_0
if v_1.Op != OpMIPSMOVWconst {
break
}
c := auxIntToInt32(v_1.AuxInt)
mem := v_2
v.reset(OpMIPSLoweredPanicBoundsRC)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCToAux(PanicBoundsC{C: int64(c)})
v.AddArg2(x, mem)
return true
}
// match: (LoweredPanicBoundsRR [kind] (MOVWconst [c]) y mem)
// result: (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(c)}} y mem)
for {
kind := auxIntToInt64(v.AuxInt)
if v_0.Op != OpMIPSMOVWconst {
break
}
c := auxIntToInt32(v_0.AuxInt)
y := v_1
mem := v_2
v.reset(OpMIPSLoweredPanicBoundsCR)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCToAux(PanicBoundsC{C: int64(c)})
v.AddArg2(y, mem)
return true
}
return false
}
func rewriteValueMIPS_OpMIPSLoweredPanicExtendRC(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (LoweredPanicExtendRC [kind] {p} (MOVWconst [hi]) (MOVWconst [lo]) mem)
// result: (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(hi)<<32+int64(uint32(lo)), Cy:p.C}} mem)
for {
kind := auxIntToInt64(v.AuxInt)
p := auxToPanicBoundsC(v.Aux)
if v_0.Op != OpMIPSMOVWconst {
break
}
hi := auxIntToInt32(v_0.AuxInt)
if v_1.Op != OpMIPSMOVWconst {
break
}
lo := auxIntToInt32(v_1.AuxInt)
mem := v_2
v.reset(OpMIPSLoweredPanicBoundsCC)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCCToAux(PanicBoundsCC{Cx: int64(hi)<<32 + int64(uint32(lo)), Cy: p.C})
v.AddArg(mem)
return true
}
return false
}
func rewriteValueMIPS_OpMIPSLoweredPanicExtendRR(v *Value) bool {
v_3 := v.Args[3]
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (LoweredPanicExtendRR [kind] hi lo (MOVWconst [c]) mem)
// result: (LoweredPanicExtendRC [kind] hi lo {PanicBoundsC{C:int64(c)}} mem)
for {
kind := auxIntToInt64(v.AuxInt)
hi := v_0
lo := v_1
if v_2.Op != OpMIPSMOVWconst {
break
}
c := auxIntToInt32(v_2.AuxInt)
mem := v_3
v.reset(OpMIPSLoweredPanicExtendRC)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCToAux(PanicBoundsC{C: int64(c)})
v.AddArg3(hi, lo, mem)
return true
}
// match: (LoweredPanicExtendRR [kind] (MOVWconst [hi]) (MOVWconst [lo]) y mem)
// result: (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(hi)<<32 + int64(uint32(lo))}} y mem)
for {
kind := auxIntToInt64(v.AuxInt)
if v_0.Op != OpMIPSMOVWconst {
break
}
hi := auxIntToInt32(v_0.AuxInt)
if v_1.Op != OpMIPSMOVWconst {
break
}
lo := auxIntToInt32(v_1.AuxInt)
y := v_2
mem := v_3
v.reset(OpMIPSLoweredPanicBoundsCR)
v.AuxInt = int64ToAuxInt(kind)
v.Aux = panicBoundsCToAux(PanicBoundsC{C: int64(hi)<<32 + int64(uint32(lo))})
v.AddArg2(y, mem)
return true
}
return false
}
func rewriteValueMIPS_OpMIPSMOVBUload(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
@ -5586,118 +5725,6 @@ func rewriteValueMIPS_OpOffPtr(v *Value) bool {
return true
}
}
func rewriteValueMIPS_OpPanicBounds(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (PanicBounds [kind] x y mem)
// cond: boundsABI(kind) == 0
// result: (LoweredPanicBoundsA [kind] x y mem)
for {
kind := auxIntToInt64(v.AuxInt)
x := v_0
y := v_1
mem := v_2
if !(boundsABI(kind) == 0) {
break
}
v.reset(OpMIPSLoweredPanicBoundsA)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg3(x, y, mem)
return true
}
// match: (PanicBounds [kind] x y mem)
// cond: boundsABI(kind) == 1
// result: (LoweredPanicBoundsB [kind] x y mem)
for {
kind := auxIntToInt64(v.AuxInt)
x := v_0
y := v_1
mem := v_2
if !(boundsABI(kind) == 1) {
break
}
v.reset(OpMIPSLoweredPanicBoundsB)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg3(x, y, mem)
return true
}
// match: (PanicBounds [kind] x y mem)
// cond: boundsABI(kind) == 2
// result: (LoweredPanicBoundsC [kind] x y mem)
for {
kind := auxIntToInt64(v.AuxInt)
x := v_0
y := v_1
mem := v_2
if !(boundsABI(kind) == 2) {
break
}
v.reset(OpMIPSLoweredPanicBoundsC)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg3(x, y, mem)
return true
}
return false
}
func rewriteValueMIPS_OpPanicExtend(v *Value) bool {
v_3 := v.Args[3]
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (PanicExtend [kind] hi lo y mem)
// cond: boundsABI(kind) == 0
// result: (LoweredPanicExtendA [kind] hi lo y mem)
for {
kind := auxIntToInt64(v.AuxInt)
hi := v_0
lo := v_1
y := v_2
mem := v_3
if !(boundsABI(kind) == 0) {
break
}
v.reset(OpMIPSLoweredPanicExtendA)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg4(hi, lo, y, mem)
return true
}
// match: (PanicExtend [kind] hi lo y mem)
// cond: boundsABI(kind) == 1
// result: (LoweredPanicExtendB [kind] hi lo y mem)
for {
kind := auxIntToInt64(v.AuxInt)
hi := v_0
lo := v_1
y := v_2
mem := v_3
if !(boundsABI(kind) == 1) {
break
}
v.reset(OpMIPSLoweredPanicExtendB)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg4(hi, lo, y, mem)
return true
}
// match: (PanicExtend [kind] hi lo y mem)
// cond: boundsABI(kind) == 2
// result: (LoweredPanicExtendC [kind] hi lo y mem)
for {
kind := auxIntToInt64(v.AuxInt)
hi := v_0
lo := v_1
y := v_2
mem := v_3
if !(boundsABI(kind) == 2) {
break
}
v.reset(OpMIPSLoweredPanicExtendC)
v.AuxInt = int64ToAuxInt(kind)
v.AddArg4(hi, lo, y, mem)
return true
}
return false
}
func rewriteValueMIPS_OpRotateLeft16(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]

View file

@ -787,158 +787,58 @@ TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
MOVW $32, R25
JMP gcWriteBarrier<>(SB)
// Note: these functions use a special calling convention to save generated code space.
// Arguments are passed in registers, but the space for those arguments are allocated
// in the caller's stack frame. These stubs write the args into that stack space and
// then tail call to the corresponding runtime handler.
// The tail call makes these stubs disappear in backtraces.
TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicIndex(SB)
TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicIndexU(SB)
TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSliceAlen(SB)
TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSliceAlenU(SB)
TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSliceAcap(SB)
TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSliceAcapU(SB)
TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicSliceB(SB)
TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicSliceBU(SB)
TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
MOVW R3, x+0(FP)
MOVW R4, y+4(FP)
JMP runtime·goPanicSlice3Alen(SB)
TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
MOVW R3, x+0(FP)
MOVW R4, y+4(FP)
JMP runtime·goPanicSlice3AlenU(SB)
TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
MOVW R3, x+0(FP)
MOVW R4, y+4(FP)
JMP runtime·goPanicSlice3Acap(SB)
TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
MOVW R3, x+0(FP)
MOVW R4, y+4(FP)
JMP runtime·goPanicSlice3AcapU(SB)
TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSlice3B(SB)
TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
MOVW R2, x+0(FP)
MOVW R3, y+4(FP)
JMP runtime·goPanicSlice3BU(SB)
TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicSlice3C(SB)
TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
MOVW R1, x+0(FP)
MOVW R2, y+4(FP)
JMP runtime·goPanicSlice3CU(SB)
TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8
MOVW R3, x+0(FP)
MOVW R4, y+4(FP)
JMP runtime·goPanicSliceConvert(SB)
TEXT runtime·panicBounds<ABIInternal>(SB),NOSPLIT,$72-0
NO_LOCAL_POINTERS
// Save all 16 int registers that could have an index in them.
// They may be pointers, but if they are they are dead.
// Skip R0 aka ZERO.
MOVW R1, 12(R29)
MOVW R2, 16(R29)
MOVW R3, 20(R29)
MOVW R4, 24(R29)
MOVW R5, 28(R29)
MOVW R6, 32(R29)
MOVW R7, 36(R29)
MOVW R8, 40(R29)
MOVW R9, 44(R29)
MOVW R10, 48(R29)
MOVW R11, 52(R29)
MOVW R12, 56(R29)
MOVW R13, 60(R29)
MOVW R14, 64(R29)
MOVW R15, 68(R29)
MOVW R16, 72(R29)
// Extended versions for 64-bit indexes.
TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendIndex(SB)
TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendIndexU(SB)
TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSliceAlen(SB)
TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSliceAlenU(SB)
TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSliceAcap(SB)
TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSliceAcapU(SB)
TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendSliceB(SB)
TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendSliceBU(SB)
TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R3, lo+4(FP)
MOVW R4, y+8(FP)
JMP runtime·goPanicExtendSlice3Alen(SB)
TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R3, lo+4(FP)
MOVW R4, y+8(FP)
JMP runtime·goPanicExtendSlice3AlenU(SB)
TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R3, lo+4(FP)
MOVW R4, y+8(FP)
JMP runtime·goPanicExtendSlice3Acap(SB)
TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R3, lo+4(FP)
MOVW R4, y+8(FP)
JMP runtime·goPanicExtendSlice3AcapU(SB)
TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSlice3B(SB)
TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R2, lo+4(FP)
MOVW R3, y+8(FP)
JMP runtime·goPanicExtendSlice3BU(SB)
TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendSlice3C(SB)
TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
MOVW R5, hi+0(FP)
MOVW R1, lo+4(FP)
MOVW R2, y+8(FP)
JMP runtime·goPanicExtendSlice3CU(SB)
MOVW R31, 4(R29) // PC immediately after call to panicBounds
ADD $12, R29, R1 // pointer to save area
MOVW R1, 8(R29)
CALL runtime·panicBounds32<ABIInternal>(SB)
RET
TEXT runtime·panicExtend<ABIInternal>(SB),NOSPLIT,$72-0
NO_LOCAL_POINTERS
// Save all 16 int registers that could have an index in them.
// They may be pointers, but if they are they are dead.
// Skip R0 aka ZERO.
MOVW R1, 12(R29)
MOVW R2, 16(R29)
MOVW R3, 20(R29)
MOVW R4, 24(R29)
MOVW R5, 28(R29)
MOVW R6, 32(R29)
MOVW R7, 36(R29)
MOVW R8, 40(R29)
MOVW R9, 44(R29)
MOVW R10, 48(R29)
MOVW R11, 52(R29)
MOVW R12, 56(R29)
MOVW R13, 60(R29)
MOVW R14, 64(R29)
MOVW R15, 68(R29)
MOVW R16, 72(R29)
MOVW R31, 4(R29) // PC immediately after call to panicBounds
ADD $12, R29, R1 // pointer to save area
MOVW R1, 8(R29)
CALL runtime·panicBounds32X<ABIInternal>(SB)
RET