"internal/abi"
"internal/buildcfg"
"log"
+ "math"
"math/bits"
"strings"
)
}
}
+// Try converting FMOVD/FMOVS to XXSPLTIDP. If it is converted,
+// return true.
+func convertFMOVtoXXSPLTIDP(p *obj.Prog) bool {
+ if p.From.Type != obj.TYPE_FCONST || buildcfg.GOPPC64 < 10 {
+ return false
+ }
+ v := p.From.Val.(float64)
+ if float64(float32(v)) != v {
+ return false
+ }
+ // Secondly, is this value a normal value?
+ ival := int64(math.Float32bits(float32(v)))
+ isDenorm := ival&0x7F800000 == 0 && ival&0x007FFFFF != 0
+ if !isDenorm {
+ p.As = AXXSPLTIDP
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = ival
+ // Convert REG_Fx into equivalent REG_VSx
+ p.To.Reg = REG_VS0 + (p.To.Reg & 31)
+ }
+ return !isDenorm
+}
+
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p.From.Class = 0
p.To.Class = 0
// Rewrite float constants to values stored in memory.
switch p.As {
case AFMOVS:
- if p.From.Type == obj.TYPE_FCONST {
+ if p.From.Type == obj.TYPE_FCONST && !convertFMOVtoXXSPLTIDP(p) {
f32 := float32(p.From.Val.(float64))
p.From.Type = obj.TYPE_MEM
p.From.Sym = ctxt.Float32Sym(f32)
if p.From.Type == obj.TYPE_FCONST {
f64 := p.From.Val.(float64)
// Constant not needed in memory for float +/- 0
- if f64 != 0 {
+ if f64 != 0 && !convertFMOVtoXXSPLTIDP(p) {
p.From.Type = obj.TYPE_MEM
p.From.Sym = ctxt.Float64Sym(f64)
p.From.Name = obj.NAME_EXTERN
// ppc64/power10:"XSMAXJDP"
return max(a, b)
}
+
+// ------------------------ //
+// Constant Optimizations //
+// ------------------------ //
+
+func Float32Constant() float32 {
+ // ppc64x/power8:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
+ // ppc64x/power9:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
+ // ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
+ return 49.0
+}
+
+func Float64Constant() float64 {
+ // ppc64x/power8:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
+ // ppc64x/power9:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
+ // ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
+ return 49.0
+}
+
+func Float32DenormalConstant() float32 {
+ // ppc64x:"FMOVS\t[$]f32\\.00400000\\(SB\\)"
+ return 0x1p-127
+}
+
+// A float64 constant which can be exactly represented as a
+// denormal float32 value. On ppc64x, denormal values cannot
+// be used with XXSPLTIDP.
+func Float64DenormalFloat32Constant() float64 {
+ // ppc64x:"FMOVD\t[$]f64\\.3800000000000000\\(SB\\)"
+ return 0x1p-127
+}
func constantConvert32(x float32) float32 {
// amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
// s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
- // ppc64x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
+ // ppc64x/power8:"FMOVS\t[$]f32.3f800000\\(SB\\)"
+ // ppc64x/power9:"FMOVS\t[$]f32.3f800000\\(SB\\)"
+ // ppc64x/power10:"XXSPLTIDP\t[$]1065353216, VS0"
// arm64:"FMOVS\t[$]\\(1.0\\)"
if x > math.Float32frombits(0x3f800000) {
return -x