cmd/internal/obj, cmd/compile: refactor encoding arm64 RegisterArrangement
Refactor cmd/internal/obj/arm64 and cmd/compile to use common helper
function arm64.RegisterArrangement.
diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go
index 43ecb6b..77280f0 100644
--- a/src/cmd/compile/internal/arm64/ssa.go
+++ b/src/cmd/compile/internal/arm64/ssa.go
@@ -162,6 +162,38 @@
return mop
}
+// simdRegArng encodes ssa value's register with specified simd arrangement
+func simdRegArng(reg int16, arng int16) int16 {
+ if reg < arm64.REG_F0 || arm64.REG_F31 < reg {
+ base.Fatalf("expected fp register: r%d", reg)
+ }
+ var err error
+ if reg, err = arm64.RegisterArrangement(reg, arng, false); err != nil {
+ base.Fatalf("bad simd register arrangement: %v", err)
+ }
+ return reg
+}
+
+// simdV11 generates element-wise unary vector operations, e.g. VCNT V1.B8, V0.B8
+func simdV11(s *ssagen.State, v *ssa.Value, arrangement int16) *obj.Prog {
+ p := s.Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = simdRegArng(v.Args[0].Reg(), arrangement)
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = simdRegArng(v.Reg(), arrangement)
+ return p
+}
+
+// simdV11Scalar generates vector-to-scalar reduction operations, e.g. VUADDLV V1.B8, V0
+func simdV11Scalar(s *ssagen.State, v *ssa.Value, arrangement int16) *obj.Prog {
+ p := s.Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = simdRegArng(v.Args[0].Reg(), arrangement)
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = v.Reg() - arm64.REG_F0 + arm64.REG_V0
+ return p
+}
+
func ssaGenValue(s *ssagen.State, v *ssa.Value) {
switch v.Op {
case ssa.OpCopy, ssa.OpARM64MOVDreg:
@@ -1010,17 +1042,9 @@
case ssa.OpARM64LoweredRound32F, ssa.OpARM64LoweredRound64F:
// input is already rounded
case ssa.OpARM64VCNT:
- p := s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_REG
- p.From.Reg = (v.Args[0].Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
- p.To.Type = obj.TYPE_REG
- p.To.Reg = (v.Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
+ simdV11(s, v, arm64.ARNG_8B)
case ssa.OpARM64VUADDLV:
- p := s.Prog(v.Op.Asm())
- p.From.Type = obj.TYPE_REG
- p.From.Reg = (v.Args[0].Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
- p.To.Type = obj.TYPE_REG
- p.To.Reg = v.Reg() - arm64.REG_F0 + arm64.REG_V0
+ simdV11Scalar(s, v, arm64.ARNG_8B)
case ssa.OpARM64CSEL, ssa.OpARM64CSEL0:
r1 := int16(arm64.REGZERO)
if v.Op != ssa.OpARM64CSEL0 {
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 8ff38d3..6683706 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -7921,85 +7921,82 @@
}
} else if reg <= REG_V31 && reg >= REG_V0 {
- switch ext {
- case "B8":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8B & 15) << 5)
- case "B16":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_16B & 15) << 5)
- case "H4":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4H & 15) << 5)
- case "H8":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8H & 15) << 5)
- case "S2":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2S & 15) << 5)
- case "S4":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4S & 15) << 5)
- case "D1":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1D & 15) << 5)
- case "D2":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2D & 15) << 5)
- case "Q1":
- if isIndex {
- return errors.New("invalid register extension")
- }
- a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1Q & 15) << 5)
- case "B":
- if !isIndex {
- return nil
- }
- a.Reg = REG_ELEM + (reg & 31) + ((ARNG_B & 15) << 5)
- a.Index = num
- case "H":
- if !isIndex {
- return nil
- }
- a.Reg = REG_ELEM + (reg & 31) + ((ARNG_H & 15) << 5)
- a.Index = num
- case "S":
- if !isIndex {
- return nil
- }
- a.Reg = REG_ELEM + (reg & 31) + ((ARNG_S & 15) << 5)
- a.Index = num
- case "D":
- if !isIndex {
- return nil
- }
- a.Reg = REG_ELEM + (reg & 31) + ((ARNG_D & 15) << 5)
- a.Index = num
- default:
+ arng, elem := readArrangement(ext)
+ if arng == -1 {
return errors.New("unsupported simd register extension type: " + ext)
}
+ if elem && !isIndex {
+ return nil
+ }
+ var err error
+ if reg, err = RegisterArrangement(reg, arng, isIndex); err != nil {
+ return err
+ }
+ a.Reg = reg
+ if isIndex {
+ a.Index = num
+ }
} else {
return errors.New("invalid register and extension combination")
}
return nil
}
+// readArrangement returns arrangement constant (or -1 for unknown arrangement)
+// and a boolean flag specifying whether it refers to a vector element.
+func readArrangement(name string) (arng int16, elem bool) {
+ switch name {
+ case "B8":
+ return ARNG_8B, false
+ case "B16":
+ return ARNG_16B, false
+ case "H4":
+ return ARNG_4H, false
+ case "H8":
+ return ARNG_8H, false
+ case "S2":
+ return ARNG_2S, false
+ case "S4":
+ return ARNG_4S, false
+ case "D1":
+ return ARNG_1D, false
+ case "D2":
+ return ARNG_2D, false
+ case "B":
+ return ARNG_B, true
+ case "H":
+ return ARNG_H, true
+ case "S":
+ return ARNG_S, true
+ case "D":
+ return ARNG_D, true
+ case "Q1":
+ return ARNG_1Q, false
+ default:
+ return -1, false
+ }
+}
+
+// RegisterArrangement encodes specified simd register number and arrangement.
+func RegisterArrangement(reg int16, arng int16, isIndex bool) (int16, error) {
+ arng &= 15
+ arrangement := arng << 5
+ switch arng {
+ case ARNG_B, ARNG_H, ARNG_S, ARNG_D:
+ if !isIndex {
+ return reg, nil
+ }
+ return REG_ELEM + (reg & 31) + arrangement, nil
+ case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D,
+ ARNG_8B, ARNG_4H, ARNG_2S, ARNG_1D, ARNG_1Q:
+ if isIndex {
+ return 0, errors.New("invalid register extension")
+ }
+ return REG_ARNG + (reg & 31) + arrangement, nil
+ }
+ return 0, errors.New("unsupported simd register arrangement: " + fmt.Sprint(arng))
+}
+
// RegisterListOffset generates offset encoding according to AArch64 specification.
func RegisterListOffset(firstReg, regCnt int, arrangement int64) (int64, error) {
offset := int64(firstReg)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Just checking, do we have an immediate use for this? Someone, I think it was you, was looking at doing/helping the arm64 SIMD support, but right now we're overly focused on the 1.26 freeze deadline.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Just checking, do we have an immediate use for this? Someone, I think it was you, was looking at doing/helping the arm64 SIMD support, but right now we're overly focused on the 1.26 freeze deadline.
Yes, I did a modification for instructions like `VADDV` in simdgen using this name. Still need some clean-up of these changes (it's not yet in the review chain https://go-review.googlesource.com/c/go/+/711056/1 ), and I'm not sure, do we want to add such instructions (add, min/max across all lanes with result in single lane) as intrinsics for arm64? In my opinion they would be useful.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Alexander MusmanJust checking, do we have an immediate use for this? Someone, I think it was you, was looking at doing/helping the arm64 SIMD support, but right now we're overly focused on the 1.26 freeze deadline.
Yes, I did a modification for instructions like `VADDV` in simdgen using this name. Still need some clean-up of these changes (it's not yet in the review chain https://go-review.googlesource.com/c/go/+/711056/1 ), and I'm not sure, do we want to add such instructions (add, min/max across all lanes with result in single lane) as intrinsics for arm64? In my opinion they would be useful.
OMG. I think we need to so some reviewing work, superficially that is interesting.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Alexander MusmanJust checking, do we have an immediate use for this? Someone, I think it was you, was looking at doing/helping the arm64 SIMD support, but right now we're overly focused on the 1.26 freeze deadline.
David ChaseYes, I did a modification for instructions like `VADDV` in simdgen using this name. Still need some clean-up of these changes (it's not yet in the review chain https://go-review.googlesource.com/c/go/+/711056/1 ), and I'm not sure, do we want to add such instructions (add, min/max across all lanes with result in single lane) as intrinsics for arm64? In my opinion they would be useful.
OMG. I think we need to so some reviewing work, superficially that is interesting.
CL https://go-review.googlesource.com/c/go/+/718400 adds an example of possible use of `simdV11Scalar` for `ADDV` instruction.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |