mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
cmd/compile: introduce CCMP generation
Introduce new aux type "ARM64ConditionalParams", which contains condition code, NZCV flags and constant with indicator of using it for CCMP instructions Updates #71268 Change-Id: I322a6cb7077c9a2c4415893c5eb7ff7692d5a2de Reviewed-on: https://go-review.googlesource.com/c/go/+/698037 Reviewed-by: Mark Freeman <markfreeman@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Keith Randall <khr@golang.org>
This commit is contained in:
parent
3b3b16957c
commit
10ac80de77
8 changed files with 235 additions and 7 deletions
|
@ -1050,6 +1050,27 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
p.From.Offset = int64(condCode)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpARM64CCMP,
|
||||
ssa.OpARM64CCMN,
|
||||
ssa.OpARM64CCMPconst,
|
||||
ssa.OpARM64CCMNconst,
|
||||
ssa.OpARM64CCMPW,
|
||||
ssa.OpARM64CCMNW,
|
||||
ssa.OpARM64CCMPWconst,
|
||||
ssa.OpARM64CCMNWconst:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.Reg = v.Args[0].Reg()
|
||||
params := v.AuxArm64ConditionalParams()
|
||||
p.From.Type = obj.TYPE_SPECIAL // assembler encodes conditional bits in Offset
|
||||
p.From.Offset = int64(condBits[params.Cond()])
|
||||
constValue, ok := params.ConstValue()
|
||||
if ok {
|
||||
p.AddRestSourceConst(constValue)
|
||||
} else {
|
||||
p.AddRestSourceReg(v.Args[1].Reg())
|
||||
}
|
||||
p.To.Type = obj.TYPE_CONST
|
||||
p.To.Offset = params.Nzcv()
|
||||
case ssa.OpARM64LoweredZero:
|
||||
ptrReg := v.Args[0].Reg()
|
||||
n := v.AuxInt
|
||||
|
|
|
@ -156,12 +156,14 @@ func init() {
|
|||
gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
|
||||
gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
|
||||
gp1flags = regInfo{inputs: []regMask{gpg}}
|
||||
gp1flagsflags = regInfo{inputs: []regMask{gpg}}
|
||||
gp1flags1 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
|
||||
gp11flags = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
|
||||
gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
|
||||
gp21nog = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
|
||||
gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
|
||||
gp2flags = regInfo{inputs: []regMask{gpg, gpg}}
|
||||
gp2flagsflags = regInfo{inputs: []regMask{gpg, gpg}}
|
||||
gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
|
||||
gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
|
||||
gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
||||
|
@ -508,6 +510,22 @@ func init() {
|
|||
{name: "CSNEG", argLength: 3, reg: gp2flags1, asm: "CSNEG", aux: "CCop"}, // auxint(flags) ? arg0 : -arg1
|
||||
{name: "CSETM", argLength: 1, reg: readflags, asm: "CSETM", aux: "CCop"}, // auxint(flags) ? -1 : 0
|
||||
|
||||
// conditional comparison instructions; auxint is
|
||||
// combination of Cond, Nzcv and optional ConstValue
|
||||
// Behavior:
|
||||
// If the condition 'Cond' evaluates to true against current flags,
|
||||
// flags are set to the result of the comparison operation.
|
||||
// Otherwise, flags are set to the fallback value 'Nzcv'.
|
||||
{name: "CCMP", argLength: 3, reg: gp2flagsflags, asm: "CCMP", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMP arg0 arg1 else flags = Nzcv
|
||||
{name: "CCMN", argLength: 3, reg: gp2flagsflags, asm: "CCMN", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMN arg0 arg1 else flags = Nzcv
|
||||
{name: "CCMPconst", argLength: 2, reg: gp1flagsflags, asm: "CCMP", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMPconst [ConstValue] arg0 else flags = Nzcv
|
||||
{name: "CCMNconst", argLength: 2, reg: gp1flagsflags, asm: "CCMN", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMNconst [ConstValue] arg0 else flags = Nzcv
|
||||
|
||||
{name: "CCMPW", argLength: 3, reg: gp2flagsflags, asm: "CCMPW", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMPW arg0 arg1 else flags = Nzcv
|
||||
{name: "CCMNW", argLength: 3, reg: gp2flagsflags, asm: "CCMNW", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CMNW arg0 arg1 else flags = Nzcv
|
||||
{name: "CCMPWconst", argLength: 2, reg: gp1flagsflags, asm: "CCMPW", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CCMPWconst [ConstValue] arg0 else flags = Nzcv
|
||||
{name: "CCMNWconst", argLength: 2, reg: gp1flagsflags, asm: "CCMNW", aux: "ARM64ConditionalParams", typ: "Flag"}, // If Cond then flags = CCMNWconst [ConstValue] arg0 else flags = Nzcv
|
||||
|
||||
// function calls
|
||||
{name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem
|
||||
{name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true}, // tail call static function aux.(*obj.LSym). last arg=mem, auxint=argsize, returns mem
|
||||
|
|
|
@ -1439,7 +1439,7 @@ func opHasAuxInt(op opData) bool {
|
|||
switch op.aux {
|
||||
case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "UInt8", "Float32", "Float64",
|
||||
"SymOff", "CallOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop",
|
||||
"PanicBoundsC", "PanicBoundsCC":
|
||||
"PanicBoundsC", "PanicBoundsCC", "ARM64ConditionalParams":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -1847,6 +1847,8 @@ func (op opData) auxIntType() string {
|
|||
return "flagConstant"
|
||||
case "ARM64BitField":
|
||||
return "arm64BitField"
|
||||
case "ARM64ConditionalParams":
|
||||
return "arm64ConditionalParams"
|
||||
case "PanicBoundsC", "PanicBoundsCC":
|
||||
return "int64"
|
||||
default:
|
||||
|
|
|
@ -145,7 +145,7 @@ func checkFunc(f *Func) {
|
|||
f.Fatalf("bad int32 AuxInt value for %v", v)
|
||||
}
|
||||
canHaveAuxInt = true
|
||||
case auxInt64, auxARM64BitField:
|
||||
case auxInt64, auxARM64BitField, auxARM64ConditionalParams:
|
||||
canHaveAuxInt = true
|
||||
case auxInt128:
|
||||
// AuxInt must be zero, so leave canHaveAuxInt set to false.
|
||||
|
|
|
@ -375,11 +375,12 @@ const (
|
|||
auxPanicBoundsCC // two constants for a bounds failure
|
||||
|
||||
// architecture specific aux types
|
||||
auxARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt
|
||||
auxS390XRotateParams // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount
|
||||
auxS390XCCMask // aux is a s390x 4-bit condition code mask
|
||||
auxS390XCCMaskInt8 // aux is a s390x 4-bit condition code mask, auxInt is an int8 immediate
|
||||
auxS390XCCMaskUint8 // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate
|
||||
auxARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt
|
||||
auxARM64ConditionalParams // aux is a structure, which contains condition, NZCV flags and constant with indicator of using it
|
||||
auxS390XRotateParams // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount
|
||||
auxS390XCCMask // aux is a s390x 4-bit condition code mask
|
||||
auxS390XCCMaskInt8 // aux is a s390x 4-bit condition code mask, auxInt is an int8 immediate
|
||||
auxS390XCCMaskUint8 // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate
|
||||
)
|
||||
|
||||
// A SymEffect describes the effect that an SSA Value has on the variable
|
||||
|
@ -534,3 +535,11 @@ func (b BoundsKind) Code() (rtabi.BoundsErrorCode, bool) {
|
|||
// width+lsb<64 for 64-bit variant, width+lsb<32 for 32-bit variant.
|
||||
// the meaning of width and lsb are instruction-dependent.
|
||||
type arm64BitField int16
|
||||
|
||||
// arm64ConditionalParams is the GO type of ARM64ConditionalParams auxInt.
|
||||
type arm64ConditionalParams struct {
|
||||
cond Op // Condition code to evaluate
|
||||
nzcv uint8 // Fallback NZCV flags value when condition is false
|
||||
constValue uint8 // Immediate value for constant comparisons
|
||||
ind bool // Constant comparison indicator
|
||||
}
|
||||
|
|
|
@ -1693,6 +1693,14 @@ const (
|
|||
OpARM64CSINV
|
||||
OpARM64CSNEG
|
||||
OpARM64CSETM
|
||||
OpARM64CCMP
|
||||
OpARM64CCMN
|
||||
OpARM64CCMPconst
|
||||
OpARM64CCMNconst
|
||||
OpARM64CCMPW
|
||||
OpARM64CCMNW
|
||||
OpARM64CCMPWconst
|
||||
OpARM64CCMNWconst
|
||||
OpARM64CALLstatic
|
||||
OpARM64CALLtail
|
||||
OpARM64CALLclosure
|
||||
|
@ -22829,6 +22837,98 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMP",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 3,
|
||||
asm: arm64.ACCMP,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{1, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMN",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 3,
|
||||
asm: arm64.ACCMN,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{1, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMPconst",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 2,
|
||||
asm: arm64.ACCMP,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMNconst",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 2,
|
||||
asm: arm64.ACCMN,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMPW",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 3,
|
||||
asm: arm64.ACCMPW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{1, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMNW",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 3,
|
||||
asm: arm64.ACCMNW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
{1, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMPWconst",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 2,
|
||||
asm: arm64.ACCMPW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CCMNWconst",
|
||||
auxType: auxARM64ConditionalParams,
|
||||
argLen: 2,
|
||||
asm: arm64.ACCMNW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 402653183}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CALLstatic",
|
||||
auxType: auxCallOff,
|
||||
|
|
|
@ -669,6 +669,17 @@ func auxIntToValAndOff(i int64) ValAndOff {
|
|||
func auxIntToArm64BitField(i int64) arm64BitField {
|
||||
return arm64BitField(i)
|
||||
}
|
||||
func auxIntToArm64ConditionalParams(i int64) arm64ConditionalParams {
|
||||
var params arm64ConditionalParams
|
||||
params.cond = Op(i & 0xffff)
|
||||
i >>= 16
|
||||
params.nzcv = uint8(i & 0x0f)
|
||||
i >>= 4
|
||||
params.constValue = uint8(i & 0x1f)
|
||||
i >>= 5
|
||||
params.ind = i == 1
|
||||
return params
|
||||
}
|
||||
func auxIntToFlagConstant(x int64) flagConstant {
|
||||
return flagConstant(x)
|
||||
}
|
||||
|
@ -710,6 +721,20 @@ func valAndOffToAuxInt(v ValAndOff) int64 {
|
|||
func arm64BitFieldToAuxInt(v arm64BitField) int64 {
|
||||
return int64(v)
|
||||
}
|
||||
func arm64ConditionalParamsToAuxInt(v arm64ConditionalParams) int64 {
|
||||
if v.cond&^0xffff != 0 {
|
||||
panic("condition value exceeds 16 bits")
|
||||
}
|
||||
|
||||
var i int64
|
||||
if v.ind {
|
||||
i = 1 << 25
|
||||
}
|
||||
i |= int64(v.constValue) << 20
|
||||
i |= int64(v.nzcv) << 16
|
||||
i |= int64(v.cond)
|
||||
return i
|
||||
}
|
||||
func flagConstantToAuxInt(x flagConstant) int64 {
|
||||
return int64(x)
|
||||
}
|
||||
|
@ -1899,6 +1924,43 @@ func arm64BFWidth(mask, rshift int64) int64 {
|
|||
return nto(shiftedMask)
|
||||
}
|
||||
|
||||
// encodes condition code and NZCV flags into auxint.
|
||||
func arm64ConditionalParamsAuxInt(cond Op, nzcv uint8) arm64ConditionalParams {
|
||||
if cond < OpARM64Equal || cond > OpARM64GreaterEqualU {
|
||||
panic("Wrong conditional operation")
|
||||
}
|
||||
if nzcv&0x0f != nzcv {
|
||||
panic("Wrong value of NZCV flag")
|
||||
}
|
||||
return arm64ConditionalParams{cond, nzcv, 0, false}
|
||||
}
|
||||
|
||||
// encodes condition code, NZCV flags and constant value into auxint.
|
||||
func arm64ConditionalParamsAuxIntWithValue(cond Op, nzcv uint8, value uint8) arm64ConditionalParams {
|
||||
if value&0x1f != value {
|
||||
panic("Wrong value of constant")
|
||||
}
|
||||
params := arm64ConditionalParamsAuxInt(cond, nzcv)
|
||||
params.constValue = value
|
||||
params.ind = true
|
||||
return params
|
||||
}
|
||||
|
||||
// extracts condition code from auxint.
|
||||
func (condParams arm64ConditionalParams) Cond() Op {
|
||||
return condParams.cond
|
||||
}
|
||||
|
||||
// extracts NZCV flags from auxint.
|
||||
func (condParams arm64ConditionalParams) Nzcv() int64 {
|
||||
return int64(condParams.nzcv)
|
||||
}
|
||||
|
||||
// extracts constant value from auxint if present.
|
||||
func (condParams arm64ConditionalParams) ConstValue() (int64, bool) {
|
||||
return int64(condParams.constValue), condParams.ind
|
||||
}
|
||||
|
||||
// registerizable reports whether t is a primitive type that fits in
|
||||
// a register. It assumes float64 values will always fit into registers
|
||||
// even if that isn't strictly true.
|
||||
|
|
|
@ -144,6 +144,13 @@ func (v *Value) AuxArm64BitField() arm64BitField {
|
|||
return arm64BitField(v.AuxInt)
|
||||
}
|
||||
|
||||
func (v *Value) AuxArm64ConditionalParams() arm64ConditionalParams {
|
||||
if opcodeTable[v.Op].auxType != auxARM64ConditionalParams {
|
||||
v.Fatalf("op %s doesn't have a ARM64ConditionalParams aux field", v.Op)
|
||||
}
|
||||
return auxIntToArm64ConditionalParams(v.AuxInt)
|
||||
}
|
||||
|
||||
// long form print. v# = opcode <type> [aux] args [: reg] (names)
|
||||
func (v *Value) LongString() string {
|
||||
if v == nil {
|
||||
|
@ -203,6 +210,15 @@ func (v *Value) auxString() string {
|
|||
lsb := v.AuxArm64BitField().lsb()
|
||||
width := v.AuxArm64BitField().width()
|
||||
return fmt.Sprintf(" [lsb=%d,width=%d]", lsb, width)
|
||||
case auxARM64ConditionalParams:
|
||||
params := v.AuxArm64ConditionalParams()
|
||||
cond := params.Cond()
|
||||
nzcv := params.Nzcv()
|
||||
imm, ok := params.ConstValue()
|
||||
if ok {
|
||||
return fmt.Sprintf(" [cond=%s,nzcv=%d,imm=%d]", cond, nzcv, imm)
|
||||
}
|
||||
return fmt.Sprintf(" [cond=%s,nzcv=%d]", cond, nzcv)
|
||||
case auxFloat32, auxFloat64:
|
||||
return fmt.Sprintf(" [%g]", v.AuxFloat())
|
||||
case auxString:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue