Skip to content

Commit 7dccd63

Browse files
committed
cmd/compile: move arm32 over to new bounds check strategy
Change-Id: I529edd805875a4833cabcf4692f0c6d4163b07d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/682398 Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: David Chase <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent d79405a commit 7dccd63

File tree

6 files changed

+407
-335
lines changed

6 files changed

+407
-335
lines changed

src/cmd/compile/internal/arm/ssa.go

Lines changed: 160 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"cmd/compile/internal/types"
1919
"cmd/internal/obj"
2020
"cmd/internal/obj/arm"
21+
"internal/abi"
2122
)
2223

2324
// loadByType returns the load instruction of the given type.
@@ -712,18 +713,167 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
712713
p.To.Name = obj.NAME_EXTERN
713714
// AuxInt encodes how many buffer entries we need.
714715
p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
715-
case ssa.OpARMLoweredPanicBoundsA, ssa.OpARMLoweredPanicBoundsB, ssa.OpARMLoweredPanicBoundsC:
716-
p := s.Prog(obj.ACALL)
717-
p.To.Type = obj.TYPE_MEM
718-
p.To.Name = obj.NAME_EXTERN
719-
p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
720-
s.UseArgs(8) // space used in callee args area by assembly stubs
721-
case ssa.OpARMLoweredPanicExtendA, ssa.OpARMLoweredPanicExtendB, ssa.OpARMLoweredPanicExtendC:
722-
p := s.Prog(obj.ACALL)
716+
717+
case ssa.OpARMLoweredPanicBoundsRR, ssa.OpARMLoweredPanicBoundsRC, ssa.OpARMLoweredPanicBoundsCR, ssa.OpARMLoweredPanicBoundsCC,
718+
ssa.OpARMLoweredPanicExtendRR, ssa.OpARMLoweredPanicExtendRC:
719+
// Compute the constant we put in the PCData entry for this call.
720+
code, signed := ssa.BoundsKind(v.AuxInt).Code()
721+
xIsReg := false
722+
yIsReg := false
723+
xVal := 0
724+
yVal := 0
725+
extend := false
726+
switch v.Op {
727+
case ssa.OpARMLoweredPanicBoundsRR:
728+
xIsReg = true
729+
xVal = int(v.Args[0].Reg() - arm.REG_R0)
730+
yIsReg = true
731+
yVal = int(v.Args[1].Reg() - arm.REG_R0)
732+
case ssa.OpARMLoweredPanicExtendRR:
733+
extend = true
734+
xIsReg = true
735+
hi := int(v.Args[0].Reg() - arm.REG_R0)
736+
lo := int(v.Args[1].Reg() - arm.REG_R0)
737+
xVal = hi<<2 + lo // encode 2 register numbers
738+
yIsReg = true
739+
yVal = int(v.Args[2].Reg() - arm.REG_R0)
740+
case ssa.OpARMLoweredPanicBoundsRC:
741+
xIsReg = true
742+
xVal = int(v.Args[0].Reg() - arm.REG_R0)
743+
c := v.Aux.(ssa.PanicBoundsC).C
744+
if c >= 0 && c <= abi.BoundsMaxConst {
745+
yVal = int(c)
746+
} else {
747+
// Move constant to a register
748+
yIsReg = true
749+
if yVal == xVal {
750+
yVal = 1
751+
}
752+
p := s.Prog(arm.AMOVW)
753+
p.From.Type = obj.TYPE_CONST
754+
p.From.Offset = c
755+
p.To.Type = obj.TYPE_REG
756+
p.To.Reg = arm.REG_R0 + int16(yVal)
757+
}
758+
case ssa.OpARMLoweredPanicExtendRC:
759+
extend = true
760+
xIsReg = true
761+
hi := int(v.Args[0].Reg() - arm.REG_R0)
762+
lo := int(v.Args[1].Reg() - arm.REG_R0)
763+
xVal = hi<<2 + lo // encode 2 register numbers
764+
c := v.Aux.(ssa.PanicBoundsC).C
765+
if c >= 0 && c <= abi.BoundsMaxConst {
766+
yVal = int(c)
767+
} else {
768+
// Move constant to a register
769+
for yVal == hi || yVal == lo {
770+
yVal++
771+
}
772+
p := s.Prog(arm.AMOVW)
773+
p.From.Type = obj.TYPE_CONST
774+
p.From.Offset = c
775+
p.To.Type = obj.TYPE_REG
776+
p.To.Reg = arm.REG_R0 + int16(yVal)
777+
}
778+
case ssa.OpARMLoweredPanicBoundsCR:
779+
yIsReg = true
780+
yVal := int(v.Args[0].Reg() - arm.REG_R0)
781+
c := v.Aux.(ssa.PanicBoundsC).C
782+
if c >= 0 && c <= abi.BoundsMaxConst {
783+
xVal = int(c)
784+
} else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
785+
// Move constant to a register
786+
xIsReg = true
787+
if xVal == yVal {
788+
xVal = 1
789+
}
790+
p := s.Prog(arm.AMOVW)
791+
p.From.Type = obj.TYPE_CONST
792+
p.From.Offset = c
793+
p.To.Type = obj.TYPE_REG
794+
p.To.Reg = arm.REG_R0 + int16(xVal)
795+
} else {
796+
// Move constant to two registers
797+
extend = true
798+
xIsReg = true
799+
hi := 0
800+
lo := 1
801+
if hi == yVal {
802+
hi = 2
803+
}
804+
if lo == yVal {
805+
lo = 2
806+
}
807+
xVal = hi<<2 + lo
808+
p := s.Prog(arm.AMOVW)
809+
p.From.Type = obj.TYPE_CONST
810+
p.From.Offset = c >> 32
811+
p.To.Type = obj.TYPE_REG
812+
p.To.Reg = arm.REG_R0 + int16(hi)
813+
p = s.Prog(arm.AMOVW)
814+
p.From.Type = obj.TYPE_CONST
815+
p.From.Offset = int64(int32(c))
816+
p.To.Type = obj.TYPE_REG
817+
p.To.Reg = arm.REG_R0 + int16(lo)
818+
}
819+
case ssa.OpARMLoweredPanicBoundsCC:
820+
c := v.Aux.(ssa.PanicBoundsCC).Cx
821+
if c >= 0 && c <= abi.BoundsMaxConst {
822+
xVal = int(c)
823+
} else if signed && int64(int32(c)) == c || !signed && int64(uint32(c)) == c {
824+
// Move constant to a register
825+
xIsReg = true
826+
p := s.Prog(arm.AMOVW)
827+
p.From.Type = obj.TYPE_CONST
828+
p.From.Offset = c
829+
p.To.Type = obj.TYPE_REG
830+
p.To.Reg = arm.REG_R0 + int16(xVal)
831+
} else {
832+
// Move constant to two registers
833+
extend = true
834+
xIsReg = true
835+
hi := 0
836+
lo := 1
837+
xVal = hi<<2 + lo
838+
p := s.Prog(arm.AMOVW)
839+
p.From.Type = obj.TYPE_CONST
840+
p.From.Offset = c >> 32
841+
p.To.Type = obj.TYPE_REG
842+
p.To.Reg = arm.REG_R0 + int16(hi)
843+
p = s.Prog(arm.AMOVW)
844+
p.From.Type = obj.TYPE_CONST
845+
p.From.Offset = int64(int32(c))
846+
p.To.Type = obj.TYPE_REG
847+
p.To.Reg = arm.REG_R0 + int16(lo)
848+
}
849+
c = v.Aux.(ssa.PanicBoundsCC).Cy
850+
if c >= 0 && c <= abi.BoundsMaxConst {
851+
yVal = int(c)
852+
} else {
853+
// Move constant to a register
854+
yIsReg = true
855+
yVal = 2
856+
p := s.Prog(arm.AMOVW)
857+
p.From.Type = obj.TYPE_CONST
858+
p.From.Offset = c
859+
p.To.Type = obj.TYPE_REG
860+
p.To.Reg = arm.REG_R0 + int16(yVal)
861+
}
862+
}
863+
c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
864+
865+
p := s.Prog(obj.APCDATA)
866+
p.From.SetConst(abi.PCDATA_PanicBounds)
867+
p.To.SetConst(int64(c))
868+
p = s.Prog(obj.ACALL)
723869
p.To.Type = obj.TYPE_MEM
724870
p.To.Name = obj.NAME_EXTERN
725-
p.To.Sym = ssagen.ExtendCheckFunc[v.AuxInt]
726-
s.UseArgs(12) // space used in callee args area by assembly stubs
871+
if extend {
872+
p.To.Sym = ir.Syms.PanicExtend
873+
} else {
874+
p.To.Sym = ir.Syms.PanicBounds
875+
}
876+
727877
case ssa.OpARMDUFFZERO:
728878
p := s.Prog(obj.ADUFFZERO)
729879
p.To.Type = obj.TYPE_MEM

src/cmd/compile/internal/ssa/_gen/ARM.rules

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,16 @@
395395
// Write barrier.
396396
(WB ...) => (LoweredWB ...)
397397

398-
(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
399-
(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
400-
(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
398+
(PanicBounds ...) => (LoweredPanicBoundsRR ...)
399+
(PanicExtend ...) => (LoweredPanicExtendRR ...)
401400

402-
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 => (LoweredPanicExtendA [kind] hi lo y mem)
403-
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 => (LoweredPanicExtendB [kind] hi lo y mem)
404-
(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 => (LoweredPanicExtendC [kind] hi lo y mem)
401+
(LoweredPanicBoundsRR [kind] x (MOVWconst [c]) mem) => (LoweredPanicBoundsRC [kind] x {PanicBoundsC{C:int64(c)}} mem)
402+
(LoweredPanicBoundsRR [kind] (MOVWconst [c]) y mem) => (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(c)}} y mem)
403+
(LoweredPanicBoundsRC [kind] {p} (MOVWconst [c]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(c), Cy:p.C}} mem)
404+
405+
(LoweredPanicExtendRR [kind] hi lo (MOVWconst [c]) mem) => (LoweredPanicExtendRC [kind] hi lo {PanicBoundsC{C:int64(c)}} mem)
406+
(LoweredPanicExtendRR [kind] (MOVWconst [hi]) (MOVWconst [lo]) y mem) => (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:int64(hi)<<32 + int64(uint32(lo))}} y mem)
407+
(LoweredPanicExtendRC [kind] {p} (MOVWconst [hi]) (MOVWconst [lo]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:int64(hi)<<32+int64(uint32(lo)), Cy:p.C}} mem)
405408

406409
// Optimizations
407410

src/cmd/compile/internal/ssa/_gen/ARMOps.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ func init() {
9494
gpspsbg = gpspg | buildReg("SB")
9595
fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
9696
callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
97+
lr = buildReg("R14")
9798
r0 = buildReg("R0")
9899
r1 = buildReg("R1")
99100
r2 = buildReg("R2")
100101
r3 = buildReg("R3")
101-
r4 = buildReg("R4")
102102
)
103103
// Common regInfo
104104
var (
@@ -540,16 +540,19 @@ func init() {
540540
// See runtime/stubs.go for a more detailed discussion.
541541
{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
542542

543-
// There are three of these functions so that they can have three different register inputs.
544-
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
545-
// default registers to match so we don't need to copy registers around unnecessarily.
546-
{name: "LoweredPanicBoundsA", 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).
547-
{name: "LoweredPanicBoundsB", 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).
548-
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
549-
// Extend ops are the same as Bounds ops except the indexes are 64-bit.
550-
{name: "LoweredPanicExtendA", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, 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).
551-
{name: "LoweredPanicExtendB", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, 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).
552-
{name: "LoweredPanicExtendC", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r0, r1}}, typ: "Mem", call: true}, // arg0=idxHi, arg1=idxLo, arg2=len, arg3=mem, returns memory. AuxInt contains report code (see PanicExtend in genericOps.go).
543+
// LoweredPanicBoundsRR takes x and y, two values that caused a bounds check to fail.
544+
// the RC and CR versions are used when one of the arguments is a constant. CC is used
545+
// when both are constant (normally both 0, as prove derives the fact that a [0] bounds
546+
// failure means the length must have also been 0).
547+
// AuxInt contains a report code (see PanicBounds in genericOps.go).
548+
{name: "LoweredPanicBoundsRR", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{gp &^ lr, gp &^ lr}}, typ: "Mem", call: true}, // arg0=x, arg1=y, arg2=mem, returns memory.
549+
{name: "LoweredPanicBoundsRC", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{gp &^ lr}}, typ: "Mem", call: true}, // arg0=x, arg1=mem, returns memory.
550+
{name: "LoweredPanicBoundsCR", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{gp &^ lr}}, typ: "Mem", call: true}, // arg0=y, arg1=mem, returns memory.
551+
{name: "LoweredPanicBoundsCC", argLength: 1, aux: "PanicBoundsCC", reg: regInfo{}, typ: "Mem", call: true}, // arg0=mem, returns memory.
552+
553+
// Same as above, but the x value is 64 bits.
554+
{name: "LoweredPanicExtendRR", argLength: 4, aux: "Int64", reg: regInfo{inputs: []regMask{r0 | r1 | r2 | r3, r0 | r1 | r2 | r3, gp}}, typ: "Mem", call: true}, // arg0=x_hi, arg1=x_lo, arg2=y, arg3=mem, returns memory.
555+
{name: "LoweredPanicExtendRC", argLength: 3, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{r0 | r1 | r2 | r3, r0 | r1 | r2 | r3}}, typ: "Mem", call: true}, // arg0=x_hi, arg1=x_lo, arg2=mem, returns memory.
553556

554557
// Constant flag value.
555558
// Note: there's an "unordered" outcome for floating-point

src/cmd/compile/internal/ssa/opGen.go

Lines changed: 30 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)