diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules index 3232af1e55c..9d0ad0148fd 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules @@ -750,10 +750,10 @@ (SRLVconst [rc] (MOVBUreg x)) && rc >= 8 => (MOVVconst [0]) // mul by constant -(MULV x (MOVVconst [-1])) => (NEGV x) (MULV _ (MOVVconst [0])) => (MOVVconst [0]) (MULV x (MOVVconst [1])) => x -(MULV x (MOVVconst [c])) && isPowerOfTwo(c) => (SLLVconst [log64(c)] x) + +(MULV x (MOVVconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)} // div by constant (DIVVU x (MOVVconst [1])) => x diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64latelower.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64latelower.rules new file mode 100644 index 00000000000..95844381c28 --- /dev/null +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64latelower.rules @@ -0,0 +1,6 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Prefer addition when shifting left by one. +(SLLVconst [1] x) => (ADDV x x) diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index d4cd32a0d7b..50ec2ec177a 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -283,6 +283,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo c.RegSize = 8 c.lowerBlock = rewriteBlockLOONG64 c.lowerValue = rewriteValueLOONG64 + c.lateLowerBlock = rewriteBlockLOONG64latelower + c.lateLowerValue = rewriteValueLOONG64latelower c.registers = registersLOONG64[:] c.gpRegMask = gpRegMaskLOONG64 c.fpRegMask = fpRegMaskLOONG64 @@ -562,6 +564,43 @@ func (c *Config) buildRecipes(arch string) { return m.Block.NewValue2I(m.Pos, OpARM64SUBshiftLL, m.Type, int64(i), x, y) }) } + case "loong64": + // - multiply is 4 cycles. + // - add/sub/shift are 1 cycle. + // On loong64, using a multiply also needs to load the constant into a register. + // TODO: figure out a happy medium. + mulCost = 45 + + // add + r(1, 1, 10, + func(m, x, y *Value) *Value { + return m.Block.NewValue2(m.Pos, OpLOONG64ADDV, m.Type, x, y) + }) + // neg + r(-1, 0, 10, + func(m, x, y *Value) *Value { + return m.Block.NewValue1(m.Pos, OpLOONG64NEGV, m.Type, x) + }) + // sub + r(1, -1, 10, + func(m, x, y *Value) *Value { + return m.Block.NewValue2(m.Pos, OpLOONG64SUBV, m.Type, x, y) + }) + + // regular shifts + for i := 1; i < 64; i++ { + c := 10 + if i == 1 { + // Prefer x<<1 over x+x. + // Note that we eventually reverse this decision in LOONG64latelower.rules, + // but this makes shift combining rules in LOONG64.rules simpler. + c-- + } + r(1<