p.To.Sym = gc.Duffcopy
p.To.Offset = v.AuxInt
- case ssa.OpAMD64MOVQconvert, ssa.OpAMD64MOVLconvert:
- if v.Args[0].Reg() != v.Reg() {
- v.Fatalf("MOVXconvert should be a no-op")
- }
case ssa.OpCopy: // TODO: use MOVQreg for reg->reg copies instead of OpCopy?
if v.Type.IsMemory() {
return
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
- case ssa.OpCopy, ssa.OpARMMOVWconvert, ssa.OpARMMOVWreg:
+ case ssa.OpCopy, ssa.OpARMMOVWreg:
if v.Type.IsMemory() {
return
}
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
- case ssa.OpCopy, ssa.OpARM64MOVDconvert, ssa.OpARM64MOVDreg:
+ case ssa.OpCopy, ssa.OpARM64MOVDreg:
if v.Type.IsMemory() {
return
}
}
case ssa.OpPhi:
CheckLoweredPhi(v)
+ case ssa.OpConvert:
+ // nothing to do; no-op conversion for liveness
+ if v.Args[0].Reg() != v.Reg() {
+ v.Fatalf("OpConvert should be a no-op: %s; %s", v.Args[0].LongString(), v.LongString())
+ }
default:
// let the backend handle it
// Special case for first line in function; move it to the start.
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
- case ssa.OpCopy, ssa.OpMIPSMOVWconvert, ssa.OpMIPSMOVWreg:
+ case ssa.OpCopy, ssa.OpMIPSMOVWreg:
t := v.Type
if t.IsMemory() {
return
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
- case ssa.OpCopy, ssa.OpMIPS64MOVVconvert, ssa.OpMIPS64MOVVreg:
+ case ssa.OpCopy, ssa.OpMIPS64MOVVreg:
if v.Type.IsMemory() {
return
}
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
switch v.Op {
- case ssa.OpCopy, ssa.OpPPC64MOVDconvert:
+ case ssa.OpCopy:
t := v.Type
if t.IsMemory() {
return
p.To.Type = obj.TYPE_MEM
p.To.Reg = v.Args[0].Reg()
gc.AddAux2(&p.To, v, sc.Off())
- case ssa.OpCopy, ssa.OpS390XMOVDconvert, ssa.OpS390XMOVDreg:
+ case ssa.OpCopy, ssa.OpS390XMOVDreg:
if v.Type.IsMemory() {
return
}
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
// Miscellaneous
-(Convert <t> x mem) -> (MOVLconvert <t> x mem)
(IsNonNil p) -> (SETNE (TESTL p p))
(IsInBounds idx len) -> (SETB (CMPL idx len))
(IsSliceInBounds idx len) -> (SETBE (CMPL idx len))
// It saves all GP registers if necessary, but may clobber others.
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("DI"), ax}, clobbers: callerSave &^ gp}, clobberFlags: true, aux: "Sym", symEffect: "None"},
- // MOVLconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVLconvert", argLength: 2, reg: gp11, asm: "MOVL", resultInArg0: true, zeroWidth: true},
-
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
(CMOV(QEQ|QGT|QGE|QCS|QLS|LEQ|LGT|LGE|LCS|LLS|WEQ|WGT|WGE|WCS|WLS) y _ (FlagLT_UGT)) -> y
// Miscellaneous
-(Convert <t> x mem) && config.PtrSize == 8 -> (MOVQconvert <t> x mem)
-(Convert <t> x mem) && config.PtrSize == 4 -> (MOVLconvert <t> x mem)
(IsNonNil p) && config.PtrSize == 8 -> (SETNE (TESTQ p p))
(IsNonNil p) && config.PtrSize == 4 -> (SETNE (TESTL p p))
(IsInBounds idx len) && config.PtrSize == 8 -> (SETB (CMPQ idx len))
// It saves all GP registers if necessary, but may clobber others.
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("DI"), ax}, clobbers: callerSave &^ gp}, clobberFlags: true, aux: "Sym", symEffect: "None"},
- // MOVQconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVQconvert", argLength: 2, reg: gp11, asm: "MOVQ", resultInArg0: true, zeroWidth: true},
- {name: "MOVLconvert", argLength: 2, reg: gp11, asm: "MOVL", resultInArg0: true, zeroWidth: true}, // amd64p32 equivalent
-
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
// pseudo-ops
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerSP) -> (LoweredGetCallerSP)
-(Convert x mem) -> (MOVWconvert x mem)
// Absorb pseudo-ops into blocks.
(If (Equal cc) yes no) -> (EQ cc yes no)
// pseudo-ops
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerSP) -> (LoweredGetCallerSP)
-(Convert x mem) -> (MOVDconvert x mem)
// Absorb pseudo-ops into blocks.
(If (Equal cc) yes no) -> (EQ cc yes no)
// LoweredGetCallerSP returns the SP of the caller of the current function.
{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
- // MOVDconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
-
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
// LoweredGetCallerSP returns the SP of the caller of the current function.
{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
- // MOVWconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVWconvert", argLength: 2, reg: gp11, asm: "MOVW"},
-
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
// pseudo-ops
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerSP) -> (LoweredGetCallerSP)
-(Convert x mem) -> (MOVWconvert x mem)
(If cond yes no) -> (NE cond yes no)
// pseudo-ops
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerSP) -> (LoweredGetCallerSP)
-(Convert x mem) -> (MOVVconvert x mem)
(If cond yes no) -> (NE cond yes no)
// but clobbers R31 (LR) because it's a call
// and R23 (REGTMP).
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ gpg) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
-
- // MOVDconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVVconvert", argLength: 2, reg: gp11, asm: "MOVV"},
}
blocks := []blockData{
// but clobbers R31 (LR) because it's a call
// and R23 (REGTMP).
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ gpg) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
-
- // MOVWconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVWconvert", argLength: 2, reg: gp11, asm: "MOVW"},
}
blocks := []blockData{
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
// Miscellaneous
-(Convert <t> x mem) -> (MOVDconvert <t> x mem)
(GetClosurePtr) -> (LoweredGetClosurePtr)
(GetCallerSP) -> (LoweredGetCallerSP)
(IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr))
{name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
{name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
- // Convert pointer to integer, takes a memory operand for ordering.
- {name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
-
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true, call: true, symEffect: "None"}, // call static function aux.(*obj.LSym). arg0=mem, auxint=argsize, returns mem
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{callptr, ctxt, 0}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{callptr}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
// Miscellaneous
-(Convert <t> x mem) -> (MOVDconvert <t> x mem)
(IsNonNil p) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0]))
(IsInBounds idx len) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
(IsSliceInBounds idx len) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
// but clobbers R14 (LR) because it's a call.
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
- // MOVDconvert converts between pointers and integers.
- // We have a special op for this so as to not confuse GC
- // (particularly stack maps). It takes a memory arg so it
- // gets correctly ordered with respect to GC safepoints.
- // arg0=ptr/int arg1=mem, output=int/ptr
- {name: "MOVDconvert", argLength: 2, reg: gp11sp, asm: "MOVD"},
-
// Constant flag values. For any comparison, there are 5 possible
// outcomes: the three from the signed total order (<,==,>) and the
// three from the unsigned total order. The == cases overlap.
// We have a special op for this so as to not confuse GC
// (particularly stack maps). It takes a memory arg so it
// gets correctly ordered with respect to GC safepoints.
+ // It gets compiled to nothing, so its result must in the same
+ // register as its argument. regalloc knows it can use any
+ // allocatable integer register for OpConvert.
// arg0=ptr/int arg1=mem, output=int/ptr
- {name: "Convert", argLength: 2},
+ {name: "Convert", argLength: 2, zeroWidth: true, resultInArg0: true},
// constants. Constant values are stored in the aux or
// auxint fields.
}
if v.resultInArg0 {
fmt.Fprintln(w, "resultInArg0: true,")
- if v.reg.inputs[0] != v.reg.outputs[0] {
+ // OpConvert's register mask is selected dynamically,
+ // so don't try to check it in the static table.
+ if v.name != "Convert" && v.reg.inputs[0] != v.reg.outputs[0] {
log.Fatalf("%s: input[0] and output[0] must use the same registers for %s", a.name, v.name)
}
- if v.commutative && v.reg.inputs[1] != v.reg.outputs[0] {
+ if v.name != "Convert" && v.commutative && v.reg.inputs[1] != v.reg.outputs[0] {
log.Fatalf("%s: input[1] and output[0] must use the same registers for %s", a.name, v.name)
}
}
continue // lowered
}
switch v.Op {
- case OpSP, OpSB, OpInitMem, OpArg, OpPhi, OpVarDef, OpVarKill, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1:
+ case OpSP, OpSB, OpInitMem, OpArg, OpPhi, OpVarDef, OpVarKill, OpVarLive, OpKeepAlive, OpSelect0, OpSelect1, OpConvert:
continue // ok not to lower
case OpGetG:
if f.Config.hasGReg {
Op386LoweredGetCallerSP
Op386LoweredNilCheck
Op386LoweredWB
- Op386MOVLconvert
Op386FlagEQ
Op386FlagLT_ULT
Op386FlagLT_UGT
OpAMD64LoweredGetCallerSP
OpAMD64LoweredNilCheck
OpAMD64LoweredWB
- OpAMD64MOVQconvert
- OpAMD64MOVLconvert
OpAMD64FlagEQ
OpAMD64FlagLT_ULT
OpAMD64FlagLT_UGT
OpARMLoweredMove
OpARMLoweredGetClosurePtr
OpARMLoweredGetCallerSP
- OpARMMOVWconvert
OpARMFlagEQ
OpARMFlagLT_ULT
OpARMFlagLT_UGT
OpARM64LoweredMove
OpARM64LoweredGetClosurePtr
OpARM64LoweredGetCallerSP
- OpARM64MOVDconvert
OpARM64FlagEQ
OpARM64FlagLT_ULT
OpARM64FlagLT_UGT
OpMIPSLoweredGetClosurePtr
OpMIPSLoweredGetCallerSP
OpMIPSLoweredWB
- OpMIPSMOVWconvert
OpMIPS64ADDV
OpMIPS64ADDVconst
OpMIPS64LoweredGetClosurePtr
OpMIPS64LoweredGetCallerSP
OpMIPS64LoweredWB
- OpMIPS64MOVVconvert
OpPPC64ADD
OpPPC64ADDconst
OpPPC64LoweredNilCheck
OpPPC64LoweredRound32F
OpPPC64LoweredRound64F
- OpPPC64MOVDconvert
OpPPC64CALLstatic
OpPPC64CALLclosure
OpPPC64CALLinter
OpS390XLoweredRound32F
OpS390XLoweredRound64F
OpS390XLoweredWB
- OpS390XMOVDconvert
OpS390XFlagEQ
OpS390XFlagLT
OpS390XFlagGT
clobbers: 65280, // X0 X1 X2 X3 X4 X5 X6 X7
},
},
- {
- name: "MOVLconvert",
- argLen: 2,
- resultInArg0: true,
- zeroWidth: true,
- asm: x86.AMOVL,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 239}, // AX CX DX BX BP SI DI
- },
- outputs: []outputInfo{
- {0, 239}, // AX CX DX BX BP SI DI
- },
- },
- },
{
name: "FlagEQ",
argLen: 0,
clobbers: 4294901760, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
},
},
- {
- name: "MOVQconvert",
- argLen: 2,
- resultInArg0: true,
- zeroWidth: true,
- asm: x86.AMOVQ,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
- },
- outputs: []outputInfo{
- {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
- },
- },
- },
- {
- name: "MOVLconvert",
- argLen: 2,
- resultInArg0: true,
- zeroWidth: true,
- asm: x86.AMOVL,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
- },
- outputs: []outputInfo{
- {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
- },
- },
- },
{
name: "FlagEQ",
argLen: 0,
},
},
},
- {
- name: "MOVWconvert",
- argLen: 2,
- asm: arm.AMOVW,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 22527}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 R14
- },
- outputs: []outputInfo{
- {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
- },
- },
- },
{
name: "FlagEQ",
argLen: 0,
},
},
},
- {
- name: "MOVDconvert",
- argLen: 2,
- asm: arm64.AMOVD,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 805044223}, // 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
- },
- outputs: []outputInfo{
- {0, 670826495}, // 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 R30
- },
- },
- },
{
name: "FlagEQ",
argLen: 0,
clobbers: 140737219919872, // R31 F0 F2 F4 F6 F8 F10 F12 F14 F16 F18 F20 F22 F24 F26 F28 F30 HI LO
},
},
- {
- name: "MOVWconvert",
- argLen: 2,
- asm: mips.AMOVW,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 469762046}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
- },
- outputs: []outputInfo{
- {0, 335544318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 R31
- },
- },
- },
{
name: "ADDV",
clobbers: 4611686018293170176, // R31 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 HI LO
},
},
- {
- name: "MOVVconvert",
- argLen: 2,
- asm: mips.AMOVV,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 234881022}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g R31
- },
- outputs: []outputInfo{
- {0, 167772158}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31
- },
- },
- },
{
name: "ADD",
},
},
},
- {
- name: "MOVDconvert",
- argLen: 2,
- asm: ppc64.AMOVD,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
- },
- outputs: []outputInfo{
- {0, 1073733624}, // R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
- },
- },
- },
{
name: "CALLstatic",
auxType: auxSymOff,
clobbers: 4294918144, // R14 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
- {
- name: "MOVDconvert",
- argLen: 2,
- asm: s390x.AMOVD,
- reg: regInfo{
- inputs: []inputInfo{
- {0, 54271}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14 SP
- },
- outputs: []outputInfo{
- {0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
- },
- },
- },
{
name: "FlagEQ",
argLen: 0,
generic: true,
},
{
- name: "Convert",
- argLen: 2,
- generic: true,
+ name: "Convert",
+ argLen: 2,
+ resultInArg0: true,
+ zeroWidth: true,
+ generic: true,
},
{
name: "ConstBool",
return m & s.allocatable
}
+// regspec returns the regInfo for operation op.
+func (s *regAllocState) regspec(op Op) regInfo {
+ if op == OpConvert {
+ // OpConvert is a generic op, so it doesn't have a
+ // register set in the static table. It can use any
+ // allocatable integer register.
+ m := s.allocatable & s.f.Config.gpRegMask
+ return regInfo{inputs: []inputInfo{{regs: m}}, outputs: []outputInfo{{regs: m}}}
+ }
+ return opcodeTable[op].reg
+}
+
func (s *regAllocState) regalloc(f *Func) {
regValLiveSet := f.newSparseSet(f.NumValues()) // set of values that may be live in register
defer f.retSparseSet(regValLiveSet)
for i := len(oldSched) - 1; i >= 0; i-- {
v := oldSched[i]
prefs := desired.remove(v.ID)
- desired.clobber(opcodeTable[v.Op].reg.clobbers)
- for _, j := range opcodeTable[v.Op].reg.inputs {
+ regspec := s.regspec(v.Op)
+ desired.clobber(regspec.clobbers)
+ for _, j := range regspec.inputs {
if countRegs(j.regs) != 1 {
continue
}
if s.f.pass.debug > regDebug {
fmt.Printf(" processing %s\n", v.LongString())
}
- regspec := opcodeTable[v.Op].reg
+ regspec := s.regspec(v.Op)
if v.Op == OpPhi {
f.Fatalf("phi %s not at start of block", v)
}
// desired registers back though phi nodes.
continue
}
+ regspec := s.regspec(v.Op)
// Cancel desired registers if they get clobbered.
- desired.clobber(opcodeTable[v.Op].reg.clobbers)
+ desired.clobber(regspec.clobbers)
// Update desired registers if there are any fixed register inputs.
- for _, j := range opcodeTable[v.Op].reg.inputs {
+ for _, j := range regspec.inputs {
if countRegs(j.regs) != 1 {
continue
}
return rewriteValue386_OpConstBool_0(v)
case OpConstNil:
return rewriteValue386_OpConstNil_0(v)
- case OpConvert:
- return rewriteValue386_OpConvert_0(v)
case OpCvt32Fto32:
return rewriteValue386_OpCvt32Fto32_0(v)
case OpCvt32Fto64F:
return true
}
}
-func rewriteValue386_OpConvert_0(v *Value) bool {
- // match: (Convert <t> x mem)
- // cond:
- // result: (MOVLconvert <t> x mem)
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(Op386MOVLconvert)
- v.Type = t
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValue386_OpCvt32Fto32_0(v *Value) bool {
// match: (Cvt32Fto32 x)
// cond:
return rewriteValueAMD64_OpConstBool_0(v)
case OpConstNil:
return rewriteValueAMD64_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueAMD64_OpConvert_0(v)
case OpCtz32:
return rewriteValueAMD64_OpCtz32_0(v)
case OpCtz64:
}
return false
}
-func rewriteValueAMD64_OpConvert_0(v *Value) bool {
- b := v.Block
- _ = b
- config := b.Func.Config
- _ = config
- // match: (Convert <t> x mem)
- // cond: config.PtrSize == 8
- // result: (MOVQconvert <t> x mem)
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- if !(config.PtrSize == 8) {
- break
- }
- v.reset(OpAMD64MOVQconvert)
- v.Type = t
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
- // match: (Convert <t> x mem)
- // cond: config.PtrSize == 4
- // result: (MOVLconvert <t> x mem)
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- if !(config.PtrSize == 4) {
- break
- }
- v.reset(OpAMD64MOVLconvert)
- v.Type = t
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
- return false
-}
func rewriteValueAMD64_OpCtz32_0(v *Value) bool {
b := v.Block
_ = b
return rewriteValueARM_OpConstBool_0(v)
case OpConstNil:
return rewriteValueARM_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueARM_OpConvert_0(v)
case OpCtz32:
return rewriteValueARM_OpCtz32_0(v)
case OpCvt32Fto32:
return true
}
}
-func rewriteValueARM_OpConvert_0(v *Value) bool {
- // match: (Convert x mem)
- // cond:
- // result: (MOVWconvert x mem)
- for {
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpARMMOVWconvert)
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValueARM_OpCtz32_0(v *Value) bool {
b := v.Block
_ = b
return rewriteValueARM64_OpConstBool_0(v)
case OpConstNil:
return rewriteValueARM64_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueARM64_OpConvert_0(v)
case OpCtz32:
return rewriteValueARM64_OpCtz32_0(v)
case OpCtz64:
return true
}
}
-func rewriteValueARM64_OpConvert_0(v *Value) bool {
- // match: (Convert x mem)
- // cond:
- // result: (MOVDconvert x mem)
- for {
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpARM64MOVDconvert)
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValueARM64_OpCtz32_0(v *Value) bool {
b := v.Block
_ = b
return rewriteValueMIPS_OpConstBool_0(v)
case OpConstNil:
return rewriteValueMIPS_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueMIPS_OpConvert_0(v)
case OpCtz32:
return rewriteValueMIPS_OpCtz32_0(v)
case OpCvt32Fto32:
return true
}
}
-func rewriteValueMIPS_OpConvert_0(v *Value) bool {
- // match: (Convert x mem)
- // cond:
- // result: (MOVWconvert x mem)
- for {
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpMIPSMOVWconvert)
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValueMIPS_OpCtz32_0(v *Value) bool {
b := v.Block
_ = b
return rewriteValueMIPS64_OpConstBool_0(v)
case OpConstNil:
return rewriteValueMIPS64_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueMIPS64_OpConvert_0(v)
case OpCvt32Fto32:
return rewriteValueMIPS64_OpCvt32Fto32_0(v)
case OpCvt32Fto64:
return true
}
}
-func rewriteValueMIPS64_OpConvert_0(v *Value) bool {
- // match: (Convert x mem)
- // cond:
- // result: (MOVVconvert x mem)
- for {
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpMIPS64MOVVconvert)
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValueMIPS64_OpCvt32Fto32_0(v *Value) bool {
// match: (Cvt32Fto32 x)
// cond:
return rewriteValuePPC64_OpConstBool_0(v)
case OpConstNil:
return rewriteValuePPC64_OpConstNil_0(v)
- case OpConvert:
- return rewriteValuePPC64_OpConvert_0(v)
case OpCopysign:
return rewriteValuePPC64_OpCopysign_0(v)
case OpCtz32:
return true
}
}
-func rewriteValuePPC64_OpConvert_0(v *Value) bool {
- // match: (Convert <t> x mem)
- // cond:
- // result: (MOVDconvert <t> x mem)
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpPPC64MOVDconvert)
- v.Type = t
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValuePPC64_OpCopysign_0(v *Value) bool {
// match: (Copysign x y)
// cond:
return rewriteValueS390X_OpConstBool_0(v)
case OpConstNil:
return rewriteValueS390X_OpConstNil_0(v)
- case OpConvert:
- return rewriteValueS390X_OpConvert_0(v)
case OpCtz32:
return rewriteValueS390X_OpCtz32_0(v)
case OpCtz64:
return true
}
}
-func rewriteValueS390X_OpConvert_0(v *Value) bool {
- // match: (Convert <t> x mem)
- // cond:
- // result: (MOVDconvert <t> x mem)
- for {
- t := v.Type
- _ = v.Args[1]
- x := v.Args[0]
- mem := v.Args[1]
- v.reset(OpS390XMOVDconvert)
- v.Type = t
- v.AddArg(x)
- v.AddArg(mem)
- return true
- }
-}
func rewriteValueS390X_OpCtz32_0(v *Value) bool {
b := v.Block
_ = b
p.To.Sym = gc.Duffcopy
p.To.Offset = v.AuxInt
- case ssa.Op386MOVLconvert:
- if v.Args[0].Reg() != v.Reg() {
- v.Fatalf("MOVLconvert should be a no-op")
- }
case ssa.OpCopy: // TODO: use MOVLreg for reg->reg copies instead of OpCopy?
if v.Type.IsMemory() {
return