mirror of
https://github.com/golang/go
synced 2024-11-20 01:54:41 -07:00
[dev.ssa] cmd/compile: use shifted and indexed ops in SSA for ARM
This CL implements the following optimizations for ARM: - use shifted ops (e.g. ADD R1<<2, R2) and indexed load/stores - break up shift ops. Shifts used to be one SSA op that generates multiple instructions. We break them up to multiple ops, which allows constant folding and CSE for comparisons. Conditional moves are introduced for this. - simplify zero/sign-extension ops. Updates #15365. Change-Id: I55e262a776a7ef2a1505d75e04d1208913c35d39 Reviewed-on: https://go-review.googlesource.com/24512 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
14cf6e2083
commit
8cc3f4a17e
@ -5,6 +5,7 @@
|
||||
package arm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"cmd/compile/internal/gc"
|
||||
@ -108,6 +109,57 @@ func storeByType(t ssa.Type) obj.As {
|
||||
panic("bad store type")
|
||||
}
|
||||
|
||||
// shift type is used as Offset in obj.TYPE_SHIFT operands to encode shifted register operands
|
||||
type shift int64
|
||||
|
||||
// copied from ../../../internal/obj/util.go:/TYPE_SHIFT
|
||||
func (v shift) String() string {
|
||||
op := "<<>>->@>"[((v>>5)&3)<<1:]
|
||||
if v&(1<<4) != 0 {
|
||||
// register shift
|
||||
return fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
|
||||
} else {
|
||||
// constant shift
|
||||
return fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
|
||||
}
|
||||
}
|
||||
|
||||
// makeshift encodes a register shifted by a constant
|
||||
func makeshift(reg int16, typ int64, s int64) shift {
|
||||
return shift(int64(reg&0xf) | typ | (s&31)<<7)
|
||||
}
|
||||
|
||||
// genshift generates a Prog for r = r0 op (r1 shifted by s)
|
||||
func genshift(as obj.As, r0, r1, r int16, typ int64, s int64) *obj.Prog {
|
||||
p := gc.Prog(as)
|
||||
p.From.Type = obj.TYPE_SHIFT
|
||||
p.From.Offset = int64(makeshift(r1, typ, s))
|
||||
p.Reg = r0
|
||||
if r != 0 {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// makeregshift encodes a register shifted by a register
|
||||
func makeregshift(r1 int16, typ int64, r2 int16) shift {
|
||||
return shift(int64(r1&0xf) | typ | int64(r2&0xf)<<8 | 1<<4)
|
||||
}
|
||||
|
||||
// genregshift generates a Prog for r = r0 op (r1 shifted by r2)
|
||||
func genregshift(as obj.As, r0, r1, r2, r int16, typ int64) *obj.Prog {
|
||||
p := gc.Prog(as)
|
||||
p.From.Type = obj.TYPE_SHIFT
|
||||
p.From.Offset = int64(makeregshift(r1, typ, r2))
|
||||
p.Reg = r0
|
||||
if r != 0 {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
s.SetLineno(v.Line)
|
||||
switch v.Op {
|
||||
@ -237,45 +289,27 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
case ssa.OpARMSLL,
|
||||
ssa.OpARMSRL:
|
||||
// ARM shift instructions uses only the low-order byte of the shift amount
|
||||
// generate conditional instructions to deal with large shifts
|
||||
// CMP $32, Rarg1
|
||||
// SLL Rarg1, Rarg0, Rdst
|
||||
// MOVW.HS $0, Rdst
|
||||
ssa.OpARMSRL,
|
||||
ssa.OpARMSRA:
|
||||
r := gc.SSARegNum(v)
|
||||
r1 := gc.SSARegNum(v.Args[0])
|
||||
r2 := gc.SSARegNum(v.Args[1])
|
||||
p := gc.Prog(arm.ACMP)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 32
|
||||
p.Reg = r2
|
||||
p = gc.Prog(v.Op.Asm())
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r2
|
||||
p.Reg = r1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
p = gc.Prog(arm.AMOVW)
|
||||
p.Scond = arm.C_SCOND_HS
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
case ssa.OpARMSRA:
|
||||
case ssa.OpARMSRAcond:
|
||||
// ARM shift instructions uses only the low-order byte of the shift amount
|
||||
// generate conditional instructions to deal with large shifts
|
||||
// CMP $32, Rarg1
|
||||
// flag is already set
|
||||
// SRA.HS $31, Rarg0, Rdst // shift 31 bits to get the sign bit
|
||||
// SRA.LO Rarg1, Rarg0, Rdst
|
||||
r := gc.SSARegNum(v)
|
||||
r1 := gc.SSARegNum(v.Args[0])
|
||||
r2 := gc.SSARegNum(v.Args[1])
|
||||
p := gc.Prog(arm.ACMP)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 32
|
||||
p.Reg = r2
|
||||
p = gc.Prog(arm.ASRA)
|
||||
p := gc.Prog(arm.ASRA)
|
||||
p.Scond = arm.C_SCOND_HS
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 31
|
||||
@ -319,11 +353,115 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
case ssa.OpARMSRRconst:
|
||||
p := gc.Prog(arm.AMOVW)
|
||||
p.From.Type = obj.TYPE_SHIFT
|
||||
p.From.Offset = int64(gc.SSARegNum(v.Args[0])&0xf) | arm.SHIFT_RR | (v.AuxInt&31)<<7
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
genshift(arm.AMOVW, 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_RR, v.AuxInt)
|
||||
case ssa.OpARMADDshiftLL,
|
||||
ssa.OpARMADCshiftLL,
|
||||
ssa.OpARMSUBshiftLL,
|
||||
ssa.OpARMSBCshiftLL,
|
||||
ssa.OpARMRSBshiftLL,
|
||||
ssa.OpARMRSCshiftLL,
|
||||
ssa.OpARMANDshiftLL,
|
||||
ssa.OpARMORshiftLL,
|
||||
ssa.OpARMXORshiftLL,
|
||||
ssa.OpARMBICshiftLL:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
|
||||
case ssa.OpARMADDSshiftLL,
|
||||
ssa.OpARMSUBSshiftLL,
|
||||
ssa.OpARMRSBSshiftLL:
|
||||
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMADDshiftRL,
|
||||
ssa.OpARMADCshiftRL,
|
||||
ssa.OpARMSUBshiftRL,
|
||||
ssa.OpARMSBCshiftRL,
|
||||
ssa.OpARMRSBshiftRL,
|
||||
ssa.OpARMRSCshiftRL,
|
||||
ssa.OpARMANDshiftRL,
|
||||
ssa.OpARMORshiftRL,
|
||||
ssa.OpARMXORshiftRL,
|
||||
ssa.OpARMBICshiftRL:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
|
||||
case ssa.OpARMADDSshiftRL,
|
||||
ssa.OpARMSUBSshiftRL,
|
||||
ssa.OpARMRSBSshiftRL:
|
||||
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMADDshiftRA,
|
||||
ssa.OpARMADCshiftRA,
|
||||
ssa.OpARMSUBshiftRA,
|
||||
ssa.OpARMSBCshiftRA,
|
||||
ssa.OpARMRSBshiftRA,
|
||||
ssa.OpARMRSCshiftRA,
|
||||
ssa.OpARMANDshiftRA,
|
||||
ssa.OpARMORshiftRA,
|
||||
ssa.OpARMXORshiftRA,
|
||||
ssa.OpARMBICshiftRA:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
|
||||
case ssa.OpARMADDSshiftRA,
|
||||
ssa.OpARMSUBSshiftRA,
|
||||
ssa.OpARMRSBSshiftRA:
|
||||
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMMVNshiftLL:
|
||||
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
|
||||
case ssa.OpARMMVNshiftRL:
|
||||
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
|
||||
case ssa.OpARMMVNshiftRA:
|
||||
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
|
||||
case ssa.OpARMMVNshiftLLreg:
|
||||
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL)
|
||||
case ssa.OpARMMVNshiftRLreg:
|
||||
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR)
|
||||
case ssa.OpARMMVNshiftRAreg:
|
||||
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR)
|
||||
case ssa.OpARMADDshiftLLreg,
|
||||
ssa.OpARMADCshiftLLreg,
|
||||
ssa.OpARMSUBshiftLLreg,
|
||||
ssa.OpARMSBCshiftLLreg,
|
||||
ssa.OpARMRSBshiftLLreg,
|
||||
ssa.OpARMRSCshiftLLreg,
|
||||
ssa.OpARMANDshiftLLreg,
|
||||
ssa.OpARMORshiftLLreg,
|
||||
ssa.OpARMXORshiftLLreg,
|
||||
ssa.OpARMBICshiftLLreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LL)
|
||||
case ssa.OpARMADDSshiftLLreg,
|
||||
ssa.OpARMSUBSshiftLLreg,
|
||||
ssa.OpARMRSBSshiftLLreg:
|
||||
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LL)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMADDshiftRLreg,
|
||||
ssa.OpARMADCshiftRLreg,
|
||||
ssa.OpARMSUBshiftRLreg,
|
||||
ssa.OpARMSBCshiftRLreg,
|
||||
ssa.OpARMRSBshiftRLreg,
|
||||
ssa.OpARMRSCshiftRLreg,
|
||||
ssa.OpARMANDshiftRLreg,
|
||||
ssa.OpARMORshiftRLreg,
|
||||
ssa.OpARMXORshiftRLreg,
|
||||
ssa.OpARMBICshiftRLreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LR)
|
||||
case ssa.OpARMADDSshiftRLreg,
|
||||
ssa.OpARMSUBSshiftRLreg,
|
||||
ssa.OpARMRSBSshiftRLreg:
|
||||
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LR)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMADDshiftRAreg,
|
||||
ssa.OpARMADCshiftRAreg,
|
||||
ssa.OpARMSUBshiftRAreg,
|
||||
ssa.OpARMSBCshiftRAreg,
|
||||
ssa.OpARMRSBshiftRAreg,
|
||||
ssa.OpARMRSCshiftRAreg,
|
||||
ssa.OpARMANDshiftRAreg,
|
||||
ssa.OpARMORshiftRAreg,
|
||||
ssa.OpARMXORshiftRAreg,
|
||||
ssa.OpARMBICshiftRAreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_AR)
|
||||
case ssa.OpARMADDSshiftRAreg,
|
||||
ssa.OpARMSUBSshiftRAreg,
|
||||
ssa.OpARMRSBSshiftRAreg:
|
||||
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_AR)
|
||||
p.Scond = arm.C_SBIT
|
||||
case ssa.OpARMHMUL,
|
||||
ssa.OpARMHMULU:
|
||||
// 32-bit high multiplication
|
||||
@ -385,6 +523,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = v.AuxInt
|
||||
p.Reg = gc.SSARegNum(v.Args[0])
|
||||
case ssa.OpARMCMPshiftLL:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_LL, v.AuxInt)
|
||||
case ssa.OpARMCMPshiftRL:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_LR, v.AuxInt)
|
||||
case ssa.OpARMCMPshiftRA:
|
||||
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_AR, v.AuxInt)
|
||||
case ssa.OpARMCMPshiftLLreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_LL)
|
||||
case ssa.OpARMCMPshiftRLreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_LR)
|
||||
case ssa.OpARMCMPshiftRAreg:
|
||||
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_AR)
|
||||
case ssa.OpARMMOVWaddr:
|
||||
p := gc.Prog(arm.AMOVW)
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
@ -440,11 +590,72 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = gc.SSARegNum(v.Args[0])
|
||||
gc.AddAux(&p.To, v)
|
||||
case ssa.OpARMMOVWloadidx:
|
||||
// this is just shift 0 bits
|
||||
fallthrough
|
||||
case ssa.OpARMMOVWloadshiftLL:
|
||||
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
case ssa.OpARMMOVWloadshiftRL:
|
||||
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
case ssa.OpARMMOVWloadshiftRA:
|
||||
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
case ssa.OpARMMOVWstoreidx:
|
||||
// this is just shift 0 bits
|
||||
fallthrough
|
||||
case ssa.OpARMMOVWstoreshiftLL:
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = gc.SSARegNum(v.Args[2])
|
||||
p.To.Type = obj.TYPE_SHIFT
|
||||
p.To.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_LL, v.AuxInt))
|
||||
case ssa.OpARMMOVWstoreshiftRL:
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = gc.SSARegNum(v.Args[2])
|
||||
p.To.Type = obj.TYPE_SHIFT
|
||||
p.To.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_LR, v.AuxInt))
|
||||
case ssa.OpARMMOVWstoreshiftRA:
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = gc.SSARegNum(v.Args[2])
|
||||
p.To.Type = obj.TYPE_SHIFT
|
||||
p.To.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_AR, v.AuxInt))
|
||||
case ssa.OpARMMOVBreg,
|
||||
ssa.OpARMMOVBUreg,
|
||||
ssa.OpARMMOVHreg,
|
||||
ssa.OpARMMOVHUreg,
|
||||
ssa.OpARMMVN,
|
||||
ssa.OpARMMOVHUreg:
|
||||
a := v.Args[0]
|
||||
for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg {
|
||||
a = a.Args[0]
|
||||
}
|
||||
if a.Op == ssa.OpLoadReg {
|
||||
t := a.Type
|
||||
switch {
|
||||
case v.Op == ssa.OpARMMOVBreg && t.Size() == 1 && t.IsSigned(),
|
||||
v.Op == ssa.OpARMMOVBUreg && t.Size() == 1 && !t.IsSigned(),
|
||||
v.Op == ssa.OpARMMOVHreg && t.Size() == 2 && t.IsSigned(),
|
||||
v.Op == ssa.OpARMMOVHUreg && t.Size() == 2 && !t.IsSigned():
|
||||
// arg is a proper-typed load, already zero/sign-extended, don't extend again
|
||||
if gc.SSARegNum(v) == gc.SSARegNum(v.Args[0]) {
|
||||
return
|
||||
}
|
||||
p := gc.Prog(arm.AMOVW)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
fallthrough
|
||||
case ssa.OpARMMVN,
|
||||
ssa.OpARMSQRTD,
|
||||
ssa.OpARMMOVWF,
|
||||
ssa.OpARMMOVWD,
|
||||
@ -467,6 +678,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
case ssa.OpARMCMOVWHSconst:
|
||||
p := gc.Prog(arm.AMOVW)
|
||||
p.Scond = arm.C_SCOND_HS
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = v.AuxInt
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
case ssa.OpARMCMOVWLSconst:
|
||||
p := gc.Prog(arm.AMOVW)
|
||||
p.Scond = arm.C_SCOND_LS
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = v.AuxInt
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
case ssa.OpARMCALLstatic:
|
||||
if v.Aux.(*gc.Sym) == gc.Deferreturn.Sym {
|
||||
// Deferred calls will appear to be returning to
|
||||
@ -657,24 +882,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p4 := gc.Prog(arm.ABLT)
|
||||
p4.To.Type = obj.TYPE_BRANCH
|
||||
gc.Patch(p4, p)
|
||||
case ssa.OpARMLoweredZeromask:
|
||||
// int32(arg0>>1 - arg0) >> 31
|
||||
// RSB r0>>1, r0, r
|
||||
// SRA $31, r, r
|
||||
r0 := gc.SSARegNum(v.Args[0])
|
||||
r := gc.SSARegNum(v)
|
||||
p := gc.Prog(arm.ARSB)
|
||||
p.From.Type = obj.TYPE_SHIFT
|
||||
p.From.Offset = int64(r0&0xf) | arm.SHIFT_LR | 1<<7 // unsigned r0>>1
|
||||
p.Reg = r0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
p = gc.Prog(arm.ASRA)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 31
|
||||
p.Reg = r
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = r
|
||||
case ssa.OpVarDef:
|
||||
gc.Gvardef(v.Aux.(*gc.Node))
|
||||
case ssa.OpVarKill:
|
||||
|
440
src/cmd/compile/internal/gc/testdata/arith_ssa.go
vendored
440
src/cmd/compile/internal/gc/testdata/arith_ssa.go
vendored
@ -553,6 +553,445 @@ func testOrPhi() {
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a + b<<3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a - b<<3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a<<3 - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a & (b << 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a | b<<3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a ^ b<<3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftLL_ssa(a, b uint32) uint32 {
|
||||
return a &^ (b << 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftLL_ssa(a uint32) uint32 {
|
||||
return ^(a << 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a + b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a - b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a>>3 - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a & (b >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a | b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a ^ b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftRL_ssa(a, b uint32) uint32 {
|
||||
return a &^ (b >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftRL_ssa(a uint32) uint32 {
|
||||
return ^(a >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftRA_ssa(a, b int32) int32 {
|
||||
return a + b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftRA_ssa(a, b int32) int32 {
|
||||
return a - b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftRA_ssa(a, b int32) int32 {
|
||||
return a>>3 - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftRA_ssa(a, b int32) int32 {
|
||||
return a & (b >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftRA_ssa(a, b int32) int32 {
|
||||
return a | b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftRA_ssa(a, b int32) int32 {
|
||||
return a ^ b>>3
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftRA_ssa(a, b int32) int32 {
|
||||
return a &^ (b >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftRA_ssa(a int32) int32 {
|
||||
return ^(a >> 3)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a + b<<s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a - b<<s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a<<s - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a & (b << s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a | b<<s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a ^ b<<s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a &^ (b << s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftLLreg_ssa(a uint32, s uint8) uint32 {
|
||||
return ^(a << s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a + b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a - b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a>>s - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a & (b >> s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a | b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a ^ b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
|
||||
return a &^ (b >> s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftRLreg_ssa(a uint32, s uint8) uint32 {
|
||||
return ^(a >> s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func addshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a + b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func subshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a - b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func rsbshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a>>s - b
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func andshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a & (b >> s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a | b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func xorshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a ^ b>>s
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func bicshiftRAreg_ssa(a, b int32, s uint8) int32 {
|
||||
return a &^ (b >> s)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func notshiftRAreg_ssa(a int32, s uint8) int32 {
|
||||
return ^(a >> s)
|
||||
}
|
||||
|
||||
// test ARM shifted ops
|
||||
func testShiftedOps() {
|
||||
a, b := uint32(10), uint32(42)
|
||||
if want, got := a+b<<3, addshiftLL_ssa(a, b); got != want {
|
||||
println("addshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a-b<<3, subshiftLL_ssa(a, b); got != want {
|
||||
println("subshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a<<3-b, rsbshiftLL_ssa(a, b); got != want {
|
||||
println("rsbshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&(b<<3), andshiftLL_ssa(a, b); got != want {
|
||||
println("andshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a|b<<3, orshiftLL_ssa(a, b); got != want {
|
||||
println("orshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a^b<<3, xorshiftLL_ssa(a, b); got != want {
|
||||
println("xorshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&^(b<<3), bicshiftLL_ssa(a, b); got != want {
|
||||
println("bicshiftLL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(a << 3), notshiftLL_ssa(a); got != want {
|
||||
println("notshiftLL_ssa(10) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a+b>>3, addshiftRL_ssa(a, b); got != want {
|
||||
println("addshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a-b>>3, subshiftRL_ssa(a, b); got != want {
|
||||
println("subshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a>>3-b, rsbshiftRL_ssa(a, b); got != want {
|
||||
println("rsbshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&(b>>3), andshiftRL_ssa(a, b); got != want {
|
||||
println("andshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a|b>>3, orshiftRL_ssa(a, b); got != want {
|
||||
println("orshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a^b>>3, xorshiftRL_ssa(a, b); got != want {
|
||||
println("xorshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&^(b>>3), bicshiftRL_ssa(a, b); got != want {
|
||||
println("bicshiftRL_ssa(10, 42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(a >> 3), notshiftRL_ssa(a); got != want {
|
||||
println("notshiftRL_ssa(10) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
c, d := int32(10), int32(-42)
|
||||
if want, got := c+d>>3, addshiftRA_ssa(c, d); got != want {
|
||||
println("addshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c-d>>3, subshiftRA_ssa(c, d); got != want {
|
||||
println("subshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c>>3-d, rsbshiftRA_ssa(c, d); got != want {
|
||||
println("rsbshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c&(d>>3), andshiftRA_ssa(c, d); got != want {
|
||||
println("andshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c|d>>3, orshiftRA_ssa(c, d); got != want {
|
||||
println("orshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c^d>>3, xorshiftRA_ssa(c, d); got != want {
|
||||
println("xorshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c&^(d>>3), bicshiftRA_ssa(c, d); got != want {
|
||||
println("bicshiftRA_ssa(10, -42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(d >> 3), notshiftRA_ssa(d); got != want {
|
||||
println("notshiftRA_ssa(-42) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
s := uint8(3)
|
||||
if want, got := a+b<<s, addshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("addshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a-b<<s, subshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("subshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a<<s-b, rsbshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("rsbshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&(b<<s), andshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("andshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a|b<<s, orshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("orshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a^b<<s, xorshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("xorshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&^(b<<s), bicshiftLLreg_ssa(a, b, s); got != want {
|
||||
println("bicshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(a << s), notshiftLLreg_ssa(a, s); got != want {
|
||||
println("notshiftLLreg_ssa(10) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a+b>>s, addshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("addshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a-b>>s, subshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("subshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a>>s-b, rsbshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("rsbshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&(b>>s), andshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("andshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a|b>>s, orshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("orshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a^b>>s, xorshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("xorshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := a&^(b>>s), bicshiftRLreg_ssa(a, b, s); got != want {
|
||||
println("bicshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(a >> s), notshiftRLreg_ssa(a, s); got != want {
|
||||
println("notshiftRLreg_ssa(10) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c+d>>s, addshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("addshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c-d>>s, subshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("subshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c>>s-d, rsbshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("rsbshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c&(d>>s), andshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("andshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c|d>>s, orshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("orshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c^d>>s, xorshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("xorshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := c&^(d>>s), bicshiftRAreg_ssa(c, d, s); got != want {
|
||||
println("bicshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
if want, got := ^(d >> s), notshiftRAreg_ssa(d, s); got != want {
|
||||
println("notshiftRAreg_ssa(-42, 3) =", got, " want ", want)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
|
||||
var failed = false
|
||||
|
||||
func main() {
|
||||
@ -573,6 +1012,7 @@ func main() {
|
||||
testLoadCombine()
|
||||
testLoadSymCombine()
|
||||
testShiftRemoval()
|
||||
testShiftedOps()
|
||||
|
||||
if failed {
|
||||
panic("failed")
|
||||
|
@ -87,40 +87,42 @@
|
||||
(Not x) -> (XORconst [1] x)
|
||||
|
||||
// shifts
|
||||
(Lsh32x32 x y) -> (SLL x y)
|
||||
(Lsh32x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
// hardware instruction uses only the low byte of the shift
|
||||
// we compare to 256 to ensure Go semantics for large shifts
|
||||
(Lsh32x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
|
||||
(Lsh32x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Lsh32x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Lsh16x32 x y) -> (SLL x y)
|
||||
(Lsh16x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
(Lsh16x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
|
||||
(Lsh16x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Lsh16x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Lsh8x32 x y) -> (SLL x y)
|
||||
(Lsh8x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
(Lsh8x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
|
||||
(Lsh8x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Lsh8x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh32Ux32 x y) -> (SRL x y)
|
||||
(Rsh32Ux16 x y) -> (SRL x (ZeroExt16to32 y))
|
||||
(Rsh32Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> x y) (CMPconst [256] y) [0])
|
||||
(Rsh32Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Rsh32Ux8 x y) -> (SRL x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh16Ux32 x y) -> (SRL (ZeroExt16to32 x) y)
|
||||
(Rsh16Ux16 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||
(Rsh16Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) y) (CMPconst [256] y) [0])
|
||||
(Rsh16Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Rsh16Ux8 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh8Ux32 x y) -> (SRL (ZeroExt8to32 x) y)
|
||||
(Rsh8Ux16 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt16to32 y))
|
||||
(Rsh8Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) y) (CMPconst [256] y) [0])
|
||||
(Rsh8Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
|
||||
(Rsh8Ux8 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh32x32 x y) -> (SRA x y)
|
||||
(Rsh32x16 x y) -> (SRA x (ZeroExt16to32 y))
|
||||
(Rsh32x32 x y) -> (SRAcond x y (CMPconst [256] y))
|
||||
(Rsh32x16 x y) -> (SRAcond x (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
|
||||
(Rsh32x8 x y) -> (SRA x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh16x32 x y) -> (SRA (SignExt16to32 x) y)
|
||||
(Rsh16x16 x y) -> (SRA (SignExt16to32 x) (ZeroExt16to32 y))
|
||||
(Rsh16x32 x y) -> (SRAcond (SignExt16to32 x) y (CMPconst [256] y))
|
||||
(Rsh16x16 x y) -> (SRAcond (SignExt16to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
|
||||
(Rsh16x8 x y) -> (SRA (SignExt16to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh8x32 x y) -> (SRA (SignExt8to32 x) y)
|
||||
(Rsh8x16 x y) -> (SRA (SignExt8to32 x) (ZeroExt16to32 y))
|
||||
(Rsh8x32 x y) -> (SRAcond (SignExt8to32 x) y (CMPconst [256] y))
|
||||
(Rsh8x16 x y) -> (SRAcond (SignExt8to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
|
||||
(Rsh8x8 x y) -> (SRA (SignExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
// constant shifts
|
||||
@ -177,7 +179,7 @@
|
||||
(SignExt16to32 x) -> (MOVHreg x)
|
||||
|
||||
(Signmask x) -> (SRAconst x [31])
|
||||
(Zeromask x) -> (LoweredZeromask x)
|
||||
(Zeromask x) -> (SRAconst (RSBshiftRL <config.fe.TypeInt32()> x x [1]) [31]) // sign bit of uint32(x)>>1 - x
|
||||
|
||||
// float <-> int conversion
|
||||
(Cvt32to32F x) -> (MOVWF x)
|
||||
@ -452,6 +454,11 @@
|
||||
(MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
|
||||
(MOVWloadidx ptr idx (MOVWstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWloadshiftLL ptr idx [c] (MOVWstoreshiftLL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWloadshiftRL ptr idx [c] (MOVWstoreshiftRL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWloadshiftRA ptr idx [c] (MOVWstoreshiftRA ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
|
||||
|
||||
// fold constant into arithmatic ops
|
||||
(ADD (MOVWconst [c]) x) -> (ADDconst [c] x)
|
||||
(ADD x (MOVWconst [c])) -> (ADDconst [c] x)
|
||||
@ -485,9 +492,6 @@
|
||||
(CMP x (MOVWconst [c])) -> (CMPconst [c] x)
|
||||
(CMP (MOVWconst [c]) x) -> (InvertFlags (CMPconst [c] x))
|
||||
|
||||
(LoweredZeromask (MOVWconst [0])) -> (MOVWconst [0])
|
||||
(LoweredZeromask (MOVWconst [c])) && c != 0 -> (MOVWconst [0xffffffff])
|
||||
|
||||
// don't extend after proper load
|
||||
// MOVWreg instruction is not emitted if src and dst registers are same, but it ensures the type.
|
||||
(MOVBreg x:(MOVBload _ _)) -> (MOVWreg x)
|
||||
@ -504,6 +508,15 @@
|
||||
(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c&0x7f] x)
|
||||
(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c&0x7fff] x)
|
||||
|
||||
// fold double extensions
|
||||
(MOVBreg x:(MOVBreg _)) -> (MOVWreg x)
|
||||
(MOVBUreg x:(MOVBUreg _)) -> (MOVWreg x)
|
||||
(MOVHreg x:(MOVBreg _)) -> (MOVWreg x)
|
||||
(MOVHreg x:(MOVBUreg _)) -> (MOVWreg x)
|
||||
(MOVHreg x:(MOVHreg _)) -> (MOVWreg x)
|
||||
(MOVHUreg x:(MOVBUreg _)) -> (MOVWreg x)
|
||||
(MOVHUreg x:(MOVHUreg _)) -> (MOVWreg x)
|
||||
|
||||
// don't extend before store
|
||||
(MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
|
||||
(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
|
||||
@ -513,25 +526,49 @@
|
||||
(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
|
||||
|
||||
// mul by constant
|
||||
(MUL x (MOVWconst [-1])) -> (RSBconst [0] x)
|
||||
(MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x)
|
||||
(MUL _ (MOVWconst [0])) -> (MOVWconst [0])
|
||||
(MUL x (MOVWconst [1])) -> x
|
||||
(MUL x (MOVWconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
|
||||
(MUL x (MOVWconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
|
||||
(MUL x (MOVWconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSBshiftLL x x [log2(c+1)])
|
||||
(MUL x (MOVWconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
|
||||
(MUL x (MOVWconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
|
||||
(MUL x (MOVWconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (RSBshiftLL <x.Type> x x [3]))
|
||||
(MUL x (MOVWconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
|
||||
|
||||
(MUL (MOVWconst [-1]) x) -> (RSBconst [0] x)
|
||||
(MUL (MOVWconst [c]) x) && int32(c) == -1 -> (RSBconst [0] x)
|
||||
(MUL (MOVWconst [0]) _) -> (MOVWconst [0])
|
||||
(MUL (MOVWconst [1]) x) -> x
|
||||
(MUL (MOVWconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
|
||||
(MUL (MOVWconst [c]) x) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
|
||||
(MUL (MOVWconst [c]) x) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSBshiftLL x x [log2(c+1)])
|
||||
(MUL (MOVWconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
|
||||
(MUL (MOVWconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
|
||||
(MUL (MOVWconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (RSBshiftLL <x.Type> x x [3]))
|
||||
(MUL (MOVWconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
|
||||
|
||||
(MULA x (MOVWconst [-1]) a) -> (SUB a x)
|
||||
(MULA x (MOVWconst [c]) a) && int32(c) == -1 -> (SUB a x)
|
||||
(MULA _ (MOVWconst [0]) a) -> a
|
||||
(MULA x (MOVWconst [1]) a) -> (ADD x a)
|
||||
(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
|
||||
(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
|
||||
(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
|
||||
(MULA x (MOVWconst [c]) a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
|
||||
(MULA x (MOVWconst [c]) a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
|
||||
(MULA x (MOVWconst [c]) a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
|
||||
(MULA x (MOVWconst [c]) a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
|
||||
|
||||
(MULA (MOVWconst [-1]) x a) -> (SUB a x)
|
||||
(MULA (MOVWconst [c]) x a) && int32(c) == -1 -> (SUB a x)
|
||||
(MULA (MOVWconst [0]) _ a) -> a
|
||||
(MULA (MOVWconst [1]) x a) -> (ADD x a)
|
||||
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
|
||||
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
|
||||
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
|
||||
(MULA (MOVWconst [c]) x a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
|
||||
(MULA (MOVWconst [c]) x a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
|
||||
(MULA (MOVWconst [c]) x a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
|
||||
(MULA (MOVWconst [c]) x a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
|
||||
|
||||
// div by constant
|
||||
(DIVU x (MOVWconst [1])) -> x
|
||||
@ -696,6 +733,28 @@
|
||||
(GreaterEqual (InvertFlags x)) -> (LessEqual x)
|
||||
(GreaterEqualU (InvertFlags x)) -> (LessEqualU x)
|
||||
|
||||
// absorb flag constants into conditional instructions
|
||||
(CMOVWLSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
|
||||
(CMOVWLSconst _ (FlagLT_ULT) [c]) -> (MOVWconst [c])
|
||||
(CMOVWLSconst x (FlagLT_UGT)) -> x
|
||||
(CMOVWLSconst _ (FlagGT_ULT) [c]) -> (MOVWconst [c])
|
||||
(CMOVWLSconst x (FlagGT_UGT)) -> x
|
||||
|
||||
(CMOVWHSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
|
||||
(CMOVWHSconst x (FlagLT_ULT)) -> x
|
||||
(CMOVWHSconst _ (FlagLT_UGT) [c]) -> (MOVWconst [c])
|
||||
(CMOVWHSconst x (FlagGT_ULT)) -> x
|
||||
(CMOVWHSconst _ (FlagGT_UGT) [c]) -> (MOVWconst [c])
|
||||
|
||||
(CMOVWLSconst x (InvertFlags flags) [c]) -> (CMOVWHSconst x flags [c])
|
||||
(CMOVWHSconst x (InvertFlags flags) [c]) -> (CMOVWLSconst x flags [c])
|
||||
|
||||
(SRAcond x _ (FlagEQ)) -> (SRAconst x [31])
|
||||
(SRAcond x y (FlagLT_ULT)) -> (SRA x y)
|
||||
(SRAcond x _ (FlagLT_UGT)) -> (SRAconst x [31])
|
||||
(SRAcond x y (FlagGT_ULT)) -> (SRA x y)
|
||||
(SRAcond x _ (FlagGT_UGT)) -> (SRAconst x [31])
|
||||
|
||||
// remove redundant *const ops
|
||||
(ADDconst [0] x) -> x
|
||||
(SUBconst [0] x) -> x
|
||||
@ -741,10 +800,377 @@
|
||||
(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
|
||||
(BICconst [c] (MOVWconst [d])) -> (MOVWconst [d&^c])
|
||||
(MVN (MOVWconst [c])) -> (MOVWconst [^c])
|
||||
(MOVBreg (MOVWconst [c])) -> (MOVWconst [int64(int8(c))])
|
||||
(MOVBUreg (MOVWconst [c])) -> (MOVWconst [int64(uint8(c))])
|
||||
(MOVHreg (MOVWconst [c])) -> (MOVWconst [int64(int16(c))])
|
||||
(MOVHUreg (MOVWconst [c])) -> (MOVWconst [int64(uint16(c))])
|
||||
(MOVWreg (MOVWconst [c])) -> (MOVWconst [c])
|
||||
|
||||
// absorb shifts into ops
|
||||
(ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c])
|
||||
(ADD (SLLconst [c] y) x) -> (ADDshiftLL x y [c])
|
||||
(ADD x (SRLconst [c] y)) -> (ADDshiftRL x y [c])
|
||||
(ADD (SRLconst [c] y) x) -> (ADDshiftRL x y [c])
|
||||
(ADD x (SRAconst [c] y)) -> (ADDshiftRA x y [c])
|
||||
(ADD (SRAconst [c] y) x) -> (ADDshiftRA x y [c])
|
||||
(ADD x (SLL y z)) -> (ADDshiftLLreg x y z)
|
||||
(ADD (SLL y z) x) -> (ADDshiftLLreg x y z)
|
||||
(ADD x (SRL y z)) -> (ADDshiftRLreg x y z)
|
||||
(ADD (SRL y z) x) -> (ADDshiftRLreg x y z)
|
||||
(ADD x (SRA y z)) -> (ADDshiftRAreg x y z)
|
||||
(ADD (SRA y z) x) -> (ADDshiftRAreg x y z)
|
||||
(ADC x (SLLconst [c] y) flags) -> (ADCshiftLL x y [c] flags)
|
||||
(ADC (SLLconst [c] y) x flags) -> (ADCshiftLL x y [c] flags)
|
||||
(ADC x (SRLconst [c] y) flags) -> (ADCshiftRL x y [c] flags)
|
||||
(ADC (SRLconst [c] y) x flags) -> (ADCshiftRL x y [c] flags)
|
||||
(ADC x (SRAconst [c] y) flags) -> (ADCshiftRA x y [c] flags)
|
||||
(ADC (SRAconst [c] y) x flags) -> (ADCshiftRA x y [c] flags)
|
||||
(ADC x (SLL y z) flags) -> (ADCshiftLLreg x y z flags)
|
||||
(ADC (SLL y z) x flags) -> (ADCshiftLLreg x y z flags)
|
||||
(ADC x (SRL y z) flags) -> (ADCshiftRLreg x y z flags)
|
||||
(ADC (SRL y z) x flags) -> (ADCshiftRLreg x y z flags)
|
||||
(ADC x (SRA y z) flags) -> (ADCshiftRAreg x y z flags)
|
||||
(ADC (SRA y z) x flags) -> (ADCshiftRAreg x y z flags)
|
||||
(ADDS x (SLLconst [c] y)) -> (ADDSshiftLL x y [c])
|
||||
(ADDS (SLLconst [c] y) x) -> (ADDSshiftLL x y [c])
|
||||
(ADDS x (SRLconst [c] y)) -> (ADDSshiftRL x y [c])
|
||||
(ADDS (SRLconst [c] y) x) -> (ADDSshiftRL x y [c])
|
||||
(ADDS x (SRAconst [c] y)) -> (ADDSshiftRA x y [c])
|
||||
(ADDS (SRAconst [c] y) x) -> (ADDSshiftRA x y [c])
|
||||
(ADDS x (SLL y z)) -> (ADDSshiftLLreg x y z)
|
||||
(ADDS (SLL y z) x) -> (ADDSshiftLLreg x y z)
|
||||
(ADDS x (SRL y z)) -> (ADDSshiftRLreg x y z)
|
||||
(ADDS (SRL y z) x) -> (ADDSshiftRLreg x y z)
|
||||
(ADDS x (SRA y z)) -> (ADDSshiftRAreg x y z)
|
||||
(ADDS (SRA y z) x) -> (ADDSshiftRAreg x y z)
|
||||
(SUB x (SLLconst [c] y)) -> (SUBshiftLL x y [c])
|
||||
(SUB (SLLconst [c] y) x) -> (RSBshiftLL x y [c])
|
||||
(SUB x (SRLconst [c] y)) -> (SUBshiftRL x y [c])
|
||||
(SUB (SRLconst [c] y) x) -> (RSBshiftRL x y [c])
|
||||
(SUB x (SRAconst [c] y)) -> (SUBshiftRA x y [c])
|
||||
(SUB (SRAconst [c] y) x) -> (RSBshiftRA x y [c])
|
||||
(SUB x (SLL y z)) -> (SUBshiftLLreg x y z)
|
||||
(SUB (SLL y z) x) -> (RSBshiftLLreg x y z)
|
||||
(SUB x (SRL y z)) -> (SUBshiftRLreg x y z)
|
||||
(SUB (SRL y z) x) -> (RSBshiftRLreg x y z)
|
||||
(SUB x (SRA y z)) -> (SUBshiftRAreg x y z)
|
||||
(SUB (SRA y z) x) -> (RSBshiftRAreg x y z)
|
||||
(SBC x (SLLconst [c] y) flags) -> (SBCshiftLL x y [c] flags)
|
||||
(SBC (SLLconst [c] y) x flags) -> (RSCshiftLL x y [c] flags)
|
||||
(SBC x (SRLconst [c] y) flags) -> (SBCshiftRL x y [c] flags)
|
||||
(SBC (SRLconst [c] y) x flags) -> (RSCshiftRL x y [c] flags)
|
||||
(SBC x (SRAconst [c] y) flags) -> (SBCshiftRA x y [c] flags)
|
||||
(SBC (SRAconst [c] y) x flags) -> (RSCshiftRA x y [c] flags)
|
||||
(SBC x (SLL y z) flags) -> (SBCshiftLLreg x y z flags)
|
||||
(SBC (SLL y z) x flags) -> (RSCshiftLLreg x y z flags)
|
||||
(SBC x (SRL y z) flags) -> (SBCshiftRLreg x y z flags)
|
||||
(SBC (SRL y z) x flags) -> (RSCshiftRLreg x y z flags)
|
||||
(SBC x (SRA y z) flags) -> (SBCshiftRAreg x y z flags)
|
||||
(SBC (SRA y z) x flags) -> (RSCshiftRAreg x y z flags)
|
||||
(SUBS x (SLLconst [c] y)) -> (SUBSshiftLL x y [c])
|
||||
(SUBS (SLLconst [c] y) x) -> (RSBSshiftLL x y [c])
|
||||
(SUBS x (SRLconst [c] y)) -> (SUBSshiftRL x y [c])
|
||||
(SUBS (SRLconst [c] y) x) -> (RSBSshiftRL x y [c])
|
||||
(SUBS x (SRAconst [c] y)) -> (SUBSshiftRA x y [c])
|
||||
(SUBS (SRAconst [c] y) x) -> (RSBSshiftRA x y [c])
|
||||
(SUBS x (SLL y z)) -> (SUBSshiftLLreg x y z)
|
||||
(SUBS (SLL y z) x) -> (RSBSshiftLLreg x y z)
|
||||
(SUBS x (SRL y z)) -> (SUBSshiftRLreg x y z)
|
||||
(SUBS (SRL y z) x) -> (RSBSshiftRLreg x y z)
|
||||
(SUBS x (SRA y z)) -> (SUBSshiftRAreg x y z)
|
||||
(SUBS (SRA y z) x) -> (RSBSshiftRAreg x y z)
|
||||
(RSB x (SLLconst [c] y)) -> (RSBshiftLL x y [c])
|
||||
(RSB (SLLconst [c] y) x) -> (SUBshiftLL x y [c])
|
||||
(RSB x (SRLconst [c] y)) -> (RSBshiftRL x y [c])
|
||||
(RSB (SRLconst [c] y) x) -> (SUBshiftRL x y [c])
|
||||
(RSB x (SRAconst [c] y)) -> (RSBshiftRA x y [c])
|
||||
(RSB (SRAconst [c] y) x) -> (SUBshiftRA x y [c])
|
||||
(RSB x (SLL y z)) -> (RSBshiftLLreg x y z)
|
||||
(RSB (SLL y z) x) -> (SUBshiftLLreg x y z)
|
||||
(RSB x (SRL y z)) -> (RSBshiftRLreg x y z)
|
||||
(RSB (SRL y z) x) -> (SUBshiftRLreg x y z)
|
||||
(RSB x (SRA y z)) -> (RSBshiftRAreg x y z)
|
||||
(RSB (SRA y z) x) -> (SUBshiftRAreg x y z)
|
||||
(AND x (SLLconst [c] y)) -> (ANDshiftLL x y [c])
|
||||
(AND (SLLconst [c] y) x) -> (ANDshiftLL x y [c])
|
||||
(AND x (SRLconst [c] y)) -> (ANDshiftRL x y [c])
|
||||
(AND (SRLconst [c] y) x) -> (ANDshiftRL x y [c])
|
||||
(AND x (SRAconst [c] y)) -> (ANDshiftRA x y [c])
|
||||
(AND (SRAconst [c] y) x) -> (ANDshiftRA x y [c])
|
||||
(AND x (SLL y z)) -> (ANDshiftLLreg x y z)
|
||||
(AND (SLL y z) x) -> (ANDshiftLLreg x y z)
|
||||
(AND x (SRL y z)) -> (ANDshiftRLreg x y z)
|
||||
(AND (SRL y z) x) -> (ANDshiftRLreg x y z)
|
||||
(AND x (SRA y z)) -> (ANDshiftRAreg x y z)
|
||||
(AND (SRA y z) x) -> (ANDshiftRAreg x y z)
|
||||
(OR x (SLLconst [c] y)) -> (ORshiftLL x y [c])
|
||||
(OR (SLLconst [c] y) x) -> (ORshiftLL x y [c])
|
||||
(OR x (SRLconst [c] y)) -> (ORshiftRL x y [c])
|
||||
(OR (SRLconst [c] y) x) -> (ORshiftRL x y [c])
|
||||
(OR x (SRAconst [c] y)) -> (ORshiftRA x y [c])
|
||||
(OR (SRAconst [c] y) x) -> (ORshiftRA x y [c])
|
||||
(OR x (SLL y z)) -> (ORshiftLLreg x y z)
|
||||
(OR (SLL y z) x) -> (ORshiftLLreg x y z)
|
||||
(OR x (SRL y z)) -> (ORshiftRLreg x y z)
|
||||
(OR (SRL y z) x) -> (ORshiftRLreg x y z)
|
||||
(OR x (SRA y z)) -> (ORshiftRAreg x y z)
|
||||
(OR (SRA y z) x) -> (ORshiftRAreg x y z)
|
||||
(XOR x (SLLconst [c] y)) -> (XORshiftLL x y [c])
|
||||
(XOR (SLLconst [c] y) x) -> (XORshiftLL x y [c])
|
||||
(XOR x (SRLconst [c] y)) -> (XORshiftRL x y [c])
|
||||
(XOR (SRLconst [c] y) x) -> (XORshiftRL x y [c])
|
||||
(XOR x (SRAconst [c] y)) -> (XORshiftRA x y [c])
|
||||
(XOR (SRAconst [c] y) x) -> (XORshiftRA x y [c])
|
||||
(XOR x (SLL y z)) -> (XORshiftLLreg x y z)
|
||||
(XOR (SLL y z) x) -> (XORshiftLLreg x y z)
|
||||
(XOR x (SRL y z)) -> (XORshiftRLreg x y z)
|
||||
(XOR (SRL y z) x) -> (XORshiftRLreg x y z)
|
||||
(XOR x (SRA y z)) -> (XORshiftRAreg x y z)
|
||||
(XOR (SRA y z) x) -> (XORshiftRAreg x y z)
|
||||
(BIC x (SLLconst [c] y)) -> (BICshiftLL x y [c])
|
||||
(BIC x (SRLconst [c] y)) -> (BICshiftRL x y [c])
|
||||
(BIC x (SRAconst [c] y)) -> (BICshiftRA x y [c])
|
||||
(BIC x (SLL y z)) -> (BICshiftLLreg x y z)
|
||||
(BIC x (SRL y z)) -> (BICshiftRLreg x y z)
|
||||
(BIC x (SRA y z)) -> (BICshiftRAreg x y z)
|
||||
(MVN (SLLconst [c] x)) -> (MVNshiftLL x [c])
|
||||
(MVN (SRLconst [c] x)) -> (MVNshiftRL x [c])
|
||||
(MVN (SRAconst [c] x)) -> (MVNshiftRA x [c])
|
||||
(MVN (SLL x y)) -> (MVNshiftLLreg x y)
|
||||
(MVN (SRL x y)) -> (MVNshiftRLreg x y)
|
||||
(MVN (SRA x y)) -> (MVNshiftRAreg x y)
|
||||
|
||||
(CMP x (SLLconst [c] y)) -> (CMPshiftLL x y [c])
|
||||
(CMP (SLLconst [c] y) x) -> (InvertFlags (CMPshiftLL x y [c]))
|
||||
(CMP x (SRLconst [c] y)) -> (CMPshiftRL x y [c])
|
||||
(CMP (SRLconst [c] y) x) -> (InvertFlags (CMPshiftRL x y [c]))
|
||||
(CMP x (SRAconst [c] y)) -> (CMPshiftRA x y [c])
|
||||
(CMP (SRAconst [c] y) x) -> (InvertFlags (CMPshiftRA x y [c]))
|
||||
(CMP x (SLL y z)) -> (CMPshiftLLreg x y z)
|
||||
(CMP (SLL y z) x) -> (InvertFlags (CMPshiftLLreg x y z))
|
||||
(CMP x (SRL y z)) -> (CMPshiftRLreg x y z)
|
||||
(CMP (SRL y z) x) -> (InvertFlags (CMPshiftRLreg x y z))
|
||||
(CMP x (SRA y z)) -> (CMPshiftRAreg x y z)
|
||||
(CMP (SRA y z) x) -> (InvertFlags (CMPshiftRAreg x y z))
|
||||
|
||||
// prefer *const ops to *shift ops
|
||||
(ADDshiftLL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d]))
|
||||
(ADDshiftRL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRLconst <x.Type> x [d]))
|
||||
(ADDshiftRA (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRAconst <x.Type> x [d]))
|
||||
(ADCshiftLL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SLLconst <x.Type> x [d]) flags)
|
||||
(ADCshiftRL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRLconst <x.Type> x [d]) flags)
|
||||
(ADCshiftRA (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRAconst <x.Type> x [d]) flags)
|
||||
(ADDSshiftLL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SLLconst <x.Type> x [d]))
|
||||
(ADDSshiftRL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRLconst <x.Type> x [d]))
|
||||
(ADDSshiftRA (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRAconst <x.Type> x [d]))
|
||||
(SUBshiftLL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SLLconst <x.Type> x [d]))
|
||||
(SUBshiftRL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRLconst <x.Type> x [d]))
|
||||
(SUBshiftRA (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRAconst <x.Type> x [d]))
|
||||
(SBCshiftLL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SLLconst <x.Type> x [d]) flags)
|
||||
(SBCshiftRL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRLconst <x.Type> x [d]) flags)
|
||||
(SBCshiftRA (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRAconst <x.Type> x [d]) flags)
|
||||
(SUBSshiftLL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SLLconst <x.Type> x [d]))
|
||||
(SUBSshiftRL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRLconst <x.Type> x [d]))
|
||||
(SUBSshiftRA (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRAconst <x.Type> x [d]))
|
||||
(RSBshiftLL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SLLconst <x.Type> x [d]))
|
||||
(RSBshiftRL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRLconst <x.Type> x [d]))
|
||||
(RSBshiftRA (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRAconst <x.Type> x [d]))
|
||||
(RSCshiftLL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SLLconst <x.Type> x [d]) flags)
|
||||
(RSCshiftRL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRLconst <x.Type> x [d]) flags)
|
||||
(RSCshiftRA (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRAconst <x.Type> x [d]) flags)
|
||||
(RSBSshiftLL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SLLconst <x.Type> x [d]))
|
||||
(RSBSshiftRL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRLconst <x.Type> x [d]))
|
||||
(RSBSshiftRA (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRAconst <x.Type> x [d]))
|
||||
(ANDshiftLL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SLLconst <x.Type> x [d]))
|
||||
(ANDshiftRL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRLconst <x.Type> x [d]))
|
||||
(ANDshiftRA (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRAconst <x.Type> x [d]))
|
||||
(ORshiftLL (MOVWconst [c]) x [d]) -> (ORconst [c] (SLLconst <x.Type> x [d]))
|
||||
(ORshiftRL (MOVWconst [c]) x [d]) -> (ORconst [c] (SRLconst <x.Type> x [d]))
|
||||
(ORshiftRA (MOVWconst [c]) x [d]) -> (ORconst [c] (SRAconst <x.Type> x [d]))
|
||||
(XORshiftLL (MOVWconst [c]) x [d]) -> (XORconst [c] (SLLconst <x.Type> x [d]))
|
||||
(XORshiftRL (MOVWconst [c]) x [d]) -> (XORconst [c] (SRLconst <x.Type> x [d]))
|
||||
(XORshiftRA (MOVWconst [c]) x [d]) -> (XORconst [c] (SRAconst <x.Type> x [d]))
|
||||
(CMPshiftLL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
|
||||
(CMPshiftRL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
|
||||
(CMPshiftRA (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
|
||||
|
||||
(ADDshiftLLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SLL <x.Type> x y))
|
||||
(ADDshiftRLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRL <x.Type> x y))
|
||||
(ADDshiftRAreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRA <x.Type> x y))
|
||||
(ADCshiftLLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SLL <x.Type> x y) flags)
|
||||
(ADCshiftRLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRL <x.Type> x y) flags)
|
||||
(ADCshiftRAreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRA <x.Type> x y) flags)
|
||||
(ADDSshiftLLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SLL <x.Type> x y))
|
||||
(ADDSshiftRLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRL <x.Type> x y))
|
||||
(ADDSshiftRAreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRA <x.Type> x y))
|
||||
(SUBshiftLLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SLL <x.Type> x y))
|
||||
(SUBshiftRLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRL <x.Type> x y))
|
||||
(SUBshiftRAreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRA <x.Type> x y))
|
||||
(SBCshiftLLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SLL <x.Type> x y) flags)
|
||||
(SBCshiftRLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRL <x.Type> x y) flags)
|
||||
(SBCshiftRAreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRA <x.Type> x y) flags)
|
||||
(SUBSshiftLLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SLL <x.Type> x y))
|
||||
(SUBSshiftRLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRL <x.Type> x y))
|
||||
(SUBSshiftRAreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRA <x.Type> x y))
|
||||
(RSBshiftLLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SLL <x.Type> x y))
|
||||
(RSBshiftRLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRL <x.Type> x y))
|
||||
(RSBshiftRAreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRA <x.Type> x y))
|
||||
(RSCshiftLLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SLL <x.Type> x y) flags)
|
||||
(RSCshiftRLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRL <x.Type> x y) flags)
|
||||
(RSCshiftRAreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRA <x.Type> x y) flags)
|
||||
(RSBSshiftLLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SLL <x.Type> x y))
|
||||
(RSBSshiftRLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRL <x.Type> x y))
|
||||
(RSBSshiftRAreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRA <x.Type> x y))
|
||||
(ANDshiftLLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SLL <x.Type> x y))
|
||||
(ANDshiftRLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRL <x.Type> x y))
|
||||
(ANDshiftRAreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRA <x.Type> x y))
|
||||
(ORshiftLLreg (MOVWconst [c]) x y) -> (ORconst [c] (SLL <x.Type> x y))
|
||||
(ORshiftRLreg (MOVWconst [c]) x y) -> (ORconst [c] (SRL <x.Type> x y))
|
||||
(ORshiftRAreg (MOVWconst [c]) x y) -> (ORconst [c] (SRA <x.Type> x y))
|
||||
(XORshiftLLreg (MOVWconst [c]) x y) -> (XORconst [c] (SLL <x.Type> x y))
|
||||
(XORshiftRLreg (MOVWconst [c]) x y) -> (XORconst [c] (SRL <x.Type> x y))
|
||||
(XORshiftRAreg (MOVWconst [c]) x y) -> (XORconst [c] (SRA <x.Type> x y))
|
||||
(CMPshiftLLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SLL <x.Type> x y)))
|
||||
(CMPshiftRLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRL <x.Type> x y)))
|
||||
(CMPshiftRAreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRA <x.Type> x y)))
|
||||
|
||||
// constant folding in *shift ops
|
||||
(ADDshiftLL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(uint32(c)<<uint64(d))])
|
||||
(ADDshiftRL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(uint32(c)>>uint64(d))])
|
||||
(ADDshiftRA x (MOVWconst [c]) [d]) -> (ADDconst x [int64(int32(c)>>uint64(d))])
|
||||
(ADCshiftLL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(uint32(c)<<uint64(d))] flags)
|
||||
(ADCshiftRL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(uint32(c)>>uint64(d))] flags)
|
||||
(ADCshiftRA x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(int32(c)>>uint64(d))] flags)
|
||||
(ADDSshiftLL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(uint32(c)<<uint64(d))])
|
||||
(ADDSshiftRL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(uint32(c)>>uint64(d))])
|
||||
(ADDSshiftRA x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(int32(c)>>uint64(d))])
|
||||
(SUBshiftLL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(uint32(c)<<uint64(d))])
|
||||
(SUBshiftRL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(uint32(c)>>uint64(d))])
|
||||
(SUBshiftRA x (MOVWconst [c]) [d]) -> (SUBconst x [int64(int32(c)>>uint64(d))])
|
||||
(SBCshiftLL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(uint32(c)<<uint64(d))] flags)
|
||||
(SBCshiftRL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(uint32(c)>>uint64(d))] flags)
|
||||
(SBCshiftRA x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(int32(c)>>uint64(d))] flags)
|
||||
(SUBSshiftLL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(uint32(c)<<uint64(d))])
|
||||
(SUBSshiftRL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(uint32(c)>>uint64(d))])
|
||||
(SUBSshiftRA x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(int32(c)>>uint64(d))])
|
||||
(RSBshiftLL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(uint32(c)<<uint64(d))])
|
||||
(RSBshiftRL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(uint32(c)>>uint64(d))])
|
||||
(RSBshiftRA x (MOVWconst [c]) [d]) -> (RSBconst x [int64(int32(c)>>uint64(d))])
|
||||
(RSCshiftLL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(uint32(c)<<uint64(d))] flags)
|
||||
(RSCshiftRL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(uint32(c)>>uint64(d))] flags)
|
||||
(RSCshiftRA x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(int32(c)>>uint64(d))] flags)
|
||||
(RSBSshiftLL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(uint32(c)<<uint64(d))])
|
||||
(RSBSshiftRL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(uint32(c)>>uint64(d))])
|
||||
(RSBSshiftRA x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(int32(c)>>uint64(d))])
|
||||
(ANDshiftLL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(uint32(c)<<uint64(d))])
|
||||
(ANDshiftRL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(uint32(c)>>uint64(d))])
|
||||
(ANDshiftRA x (MOVWconst [c]) [d]) -> (ANDconst x [int64(int32(c)>>uint64(d))])
|
||||
(ORshiftLL x (MOVWconst [c]) [d]) -> (ORconst x [int64(uint32(c)<<uint64(d))])
|
||||
(ORshiftRL x (MOVWconst [c]) [d]) -> (ORconst x [int64(uint32(c)>>uint64(d))])
|
||||
(ORshiftRA x (MOVWconst [c]) [d]) -> (ORconst x [int64(int32(c)>>uint64(d))])
|
||||
(XORshiftLL x (MOVWconst [c]) [d]) -> (XORconst x [int64(uint32(c)<<uint64(d))])
|
||||
(XORshiftRL x (MOVWconst [c]) [d]) -> (XORconst x [int64(uint32(c)>>uint64(d))])
|
||||
(XORshiftRA x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(c)>>uint64(d))])
|
||||
(BICshiftLL x (MOVWconst [c]) [d]) -> (BICconst x [int64(uint32(c)<<uint64(d))])
|
||||
(BICshiftRL x (MOVWconst [c]) [d]) -> (BICconst x [int64(uint32(c)>>uint64(d))])
|
||||
(BICshiftRA x (MOVWconst [c]) [d]) -> (BICconst x [int64(int32(c)>>uint64(d))])
|
||||
(MVNshiftLL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)<<uint64(d))])
|
||||
(MVNshiftRL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)>>uint64(d))])
|
||||
(MVNshiftRA (MOVWconst [c]) [d]) -> (MOVWconst [^int64(int32(c)>>uint64(d))])
|
||||
(CMPshiftLL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(uint32(c)<<uint64(d))])
|
||||
(CMPshiftRL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(uint32(c)>>uint64(d))])
|
||||
(CMPshiftRA x (MOVWconst [c]) [d]) -> (CMPconst x [int64(int32(c)>>uint64(d))])
|
||||
|
||||
(ADDshiftLLreg x y (MOVWconst [c])) -> (ADDshiftLL x y [c])
|
||||
(ADDshiftRLreg x y (MOVWconst [c])) -> (ADDshiftRL x y [c])
|
||||
(ADDshiftRAreg x y (MOVWconst [c])) -> (ADDshiftRA x y [c])
|
||||
(ADCshiftLLreg x y (MOVWconst [c]) flags) -> (ADCshiftLL x y [c] flags)
|
||||
(ADCshiftRLreg x y (MOVWconst [c]) flags) -> (ADCshiftRL x y [c] flags)
|
||||
(ADCshiftRAreg x y (MOVWconst [c]) flags) -> (ADCshiftRA x y [c] flags)
|
||||
(ADDSshiftLLreg x y (MOVWconst [c])) -> (ADDSshiftLL x y [c])
|
||||
(ADDSshiftRLreg x y (MOVWconst [c])) -> (ADDSshiftRL x y [c])
|
||||
(ADDSshiftRAreg x y (MOVWconst [c])) -> (ADDSshiftRA x y [c])
|
||||
(SUBshiftLLreg x y (MOVWconst [c])) -> (SUBshiftLL x y [c])
|
||||
(SUBshiftRLreg x y (MOVWconst [c])) -> (SUBshiftRL x y [c])
|
||||
(SUBshiftRAreg x y (MOVWconst [c])) -> (SUBshiftRA x y [c])
|
||||
(SBCshiftLLreg x y (MOVWconst [c]) flags) -> (SBCshiftLL x y [c] flags)
|
||||
(SBCshiftRLreg x y (MOVWconst [c]) flags) -> (SBCshiftRL x y [c] flags)
|
||||
(SBCshiftRAreg x y (MOVWconst [c]) flags) -> (SBCshiftRA x y [c] flags)
|
||||
(SUBSshiftLLreg x y (MOVWconst [c])) -> (SUBSshiftLL x y [c])
|
||||
(SUBSshiftRLreg x y (MOVWconst [c])) -> (SUBSshiftRL x y [c])
|
||||
(SUBSshiftRAreg x y (MOVWconst [c])) -> (SUBSshiftRA x y [c])
|
||||
(RSBshiftLLreg x y (MOVWconst [c])) -> (RSBshiftLL x y [c])
|
||||
(RSBshiftRLreg x y (MOVWconst [c])) -> (RSBshiftRL x y [c])
|
||||
(RSBshiftRAreg x y (MOVWconst [c])) -> (RSBshiftRA x y [c])
|
||||
(RSCshiftLLreg x y (MOVWconst [c]) flags) -> (RSCshiftLL x y [c] flags)
|
||||
(RSCshiftRLreg x y (MOVWconst [c]) flags) -> (RSCshiftRL x y [c] flags)
|
||||
(RSCshiftRAreg x y (MOVWconst [c]) flags) -> (RSCshiftRA x y [c] flags)
|
||||
(RSBSshiftLLreg x y (MOVWconst [c])) -> (RSBSshiftLL x y [c])
|
||||
(RSBSshiftRLreg x y (MOVWconst [c])) -> (RSBSshiftRL x y [c])
|
||||
(RSBSshiftRAreg x y (MOVWconst [c])) -> (RSBSshiftRA x y [c])
|
||||
(ANDshiftLLreg x y (MOVWconst [c])) -> (ANDshiftLL x y [c])
|
||||
(ANDshiftRLreg x y (MOVWconst [c])) -> (ANDshiftRL x y [c])
|
||||
(ANDshiftRAreg x y (MOVWconst [c])) -> (ANDshiftRA x y [c])
|
||||
(ORshiftLLreg x y (MOVWconst [c])) -> (ORshiftLL x y [c])
|
||||
(ORshiftRLreg x y (MOVWconst [c])) -> (ORshiftRL x y [c])
|
||||
(ORshiftRAreg x y (MOVWconst [c])) -> (ORshiftRA x y [c])
|
||||
(XORshiftLLreg x y (MOVWconst [c])) -> (XORshiftLL x y [c])
|
||||
(XORshiftRLreg x y (MOVWconst [c])) -> (XORshiftRL x y [c])
|
||||
(XORshiftRAreg x y (MOVWconst [c])) -> (XORshiftRA x y [c])
|
||||
(BICshiftLLreg x y (MOVWconst [c])) -> (BICshiftLL x y [c])
|
||||
(BICshiftRLreg x y (MOVWconst [c])) -> (BICshiftRL x y [c])
|
||||
(BICshiftRAreg x y (MOVWconst [c])) -> (BICshiftRA x y [c])
|
||||
(MVNshiftLLreg x (MOVWconst [c])) -> (MVNshiftLL x [c])
|
||||
(MVNshiftRLreg x (MOVWconst [c])) -> (MVNshiftRL x [c])
|
||||
(MVNshiftRAreg x (MOVWconst [c])) -> (MVNshiftRA x [c])
|
||||
(CMPshiftLLreg x y (MOVWconst [c])) -> (CMPshiftLL x y [c])
|
||||
(CMPshiftRLreg x y (MOVWconst [c])) -> (CMPshiftRL x y [c])
|
||||
(CMPshiftRAreg x y (MOVWconst [c])) -> (CMPshiftRA x y [c])
|
||||
|
||||
// use indexed loads and stores
|
||||
(MOVWload [0] {sym} (ADD ptr idx) mem) && sym == nil -> (MOVWloadidx ptr idx mem)
|
||||
(MOVWstore [0] {sym} (ADD ptr idx) val mem) && sym == nil -> (MOVWstoreidx ptr idx val mem)
|
||||
(MOVWload [0] {sym} (ADDshiftLL ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftLL ptr idx [c] mem)
|
||||
(MOVWload [0] {sym} (ADDshiftRL ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftRL ptr idx [c] mem)
|
||||
(MOVWload [0] {sym} (ADDshiftRA ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftRA ptr idx [c] mem)
|
||||
(MOVWstore [0] {sym} (ADDshiftLL ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftLL ptr idx [c] val mem)
|
||||
(MOVWstore [0] {sym} (ADDshiftRL ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftRL ptr idx [c] val mem)
|
||||
(MOVWstore [0] {sym} (ADDshiftRA ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftRA ptr idx [c] val mem)
|
||||
|
||||
// constant folding in indexed loads and stores
|
||||
(MOVWloadidx ptr (MOVWconst [c]) mem) -> (MOVWload [c] ptr mem)
|
||||
(MOVWloadidx (MOVWconst [c]) ptr mem) -> (MOVWload [c] ptr mem)
|
||||
|
||||
(MOVWstoreidx ptr (MOVWconst [c]) val mem) -> (MOVWstore [c] ptr val mem)
|
||||
(MOVWstoreidx (MOVWconst [c]) ptr val mem) -> (MOVWstore [c] ptr val mem)
|
||||
|
||||
(MOVWloadidx ptr (SLLconst idx [c]) mem) -> (MOVWloadshiftLL ptr idx [c] mem)
|
||||
(MOVWloadidx (SLLconst idx [c]) ptr mem) -> (MOVWloadshiftLL ptr idx [c] mem)
|
||||
(MOVWloadidx ptr (SRLconst idx [c]) mem) -> (MOVWloadshiftRL ptr idx [c] mem)
|
||||
(MOVWloadidx (SRLconst idx [c]) ptr mem) -> (MOVWloadshiftRL ptr idx [c] mem)
|
||||
(MOVWloadidx ptr (SRAconst idx [c]) mem) -> (MOVWloadshiftRA ptr idx [c] mem)
|
||||
(MOVWloadidx (SRAconst idx [c]) ptr mem) -> (MOVWloadshiftRA ptr idx [c] mem)
|
||||
|
||||
(MOVWstoreidx ptr (SLLconst idx [c]) val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
|
||||
(MOVWstoreidx (SLLconst idx [c]) ptr val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
|
||||
(MOVWstoreidx ptr (SRLconst idx [c]) val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
|
||||
(MOVWstoreidx (SRLconst idx [c]) ptr val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
|
||||
(MOVWstoreidx ptr (SRAconst idx [c]) val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
|
||||
(MOVWstoreidx (SRAconst idx [c]) ptr val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
|
||||
|
||||
(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)<<uint64(d))] ptr mem)
|
||||
(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
|
||||
(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(int32(c)>>uint64(d))] ptr mem)
|
||||
|
||||
(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)<<uint64(d))] ptr val mem)
|
||||
(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
|
||||
(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(int32(c)>>uint64(d))] ptr val mem)
|
||||
|
||||
// generic simplifications
|
||||
(ADD x (RSBconst [0] y)) -> (SUB x y)
|
||||
(ADD (RSBconst [0] y) x) -> (SUB x y)
|
||||
(SUB x x) -> (MOVWconst [0])
|
||||
(RSB x x) -> (MOVWconst [0])
|
||||
(AND x x) -> x
|
||||
(OR x x) -> x
|
||||
(XOR x x) -> (MOVWconst [0])
|
||||
@ -754,3 +1180,26 @@
|
||||
(ADD a (MUL x y)) -> (MULA x y a)
|
||||
|
||||
(AND x (MVN y)) -> (BIC x y)
|
||||
|
||||
// simplification with *shift ops
|
||||
(SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(SUBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(SUBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(RSBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(RSBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(RSBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
|
||||
(ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
|
||||
(ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
|
||||
(ORshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
|
||||
(ORshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
|
||||
(ORshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
|
||||
(XORshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(XORshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(XORshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(BICshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(BICshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(BICshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
|
||||
(AND x (MVNshiftLL y [c])) -> (BICshiftLL x y [c])
|
||||
(AND x (MVNshiftRL y [c])) -> (BICshiftRL x y [c])
|
||||
(AND x (MVNshiftRA y [c])) -> (BICshiftRA x y [c])
|
||||
|
@ -110,8 +110,13 @@ func init() {
|
||||
gp2flags = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{flags}}
|
||||
gp2flags1 = regInfo{inputs: []regMask{gp, gp, flags}, outputs: []regMask{gp}}
|
||||
gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
|
||||
gp31cf = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}, clobbers: flags} // cf: clobbers flags
|
||||
gp3flags = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{flags}}
|
||||
gp3flags1 = regInfo{inputs: []regMask{gp, gp, gp, flags}, outputs: []regMask{gp}}
|
||||
gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
|
||||
gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{}}
|
||||
gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
||||
gp2store = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{}}
|
||||
fp01 = regInfo{inputs: []regMask{}, outputs: []regMask{fp}}
|
||||
fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
|
||||
fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
|
||||
@ -176,14 +181,105 @@ func init() {
|
||||
{name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
|
||||
|
||||
// shifts
|
||||
{name: "SLL", argLength: 2, reg: gp21cf, asm: "SLL"}, // arg0 << arg1, results 0 for large shift
|
||||
{name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << arg1, shift amount is mod 256
|
||||
{name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt
|
||||
{name: "SRL", argLength: 2, reg: gp21cf, asm: "SRL"}, // arg0 >> arg1, unsigned, results 0 for large shift
|
||||
{name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> arg1, unsigned, shift amount is mod 256
|
||||
{name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned
|
||||
{name: "SRA", argLength: 2, reg: gp21cf, asm: "SRA"}, // arg0 >> arg1, signed, results 0/-1 for large shift
|
||||
{name: "SRA", argLength: 2, reg: gp21cf, asm: "SRA"}, // arg0 >> arg1, signed, shift amount is mod 256
|
||||
{name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed
|
||||
{name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits
|
||||
|
||||
{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt
|
||||
{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift
|
||||
{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift
|
||||
{name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt
|
||||
{name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift
|
||||
{name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift
|
||||
{name: "RSBshiftLL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0
|
||||
{name: "RSBshiftRL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift
|
||||
{name: "RSBshiftRA", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift
|
||||
{name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1<<auxInt)
|
||||
{name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), unsigned shift
|
||||
{name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), signed shift
|
||||
{name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1<<auxInt
|
||||
{name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, unsigned shift
|
||||
{name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, signed shift
|
||||
{name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1<<auxInt
|
||||
{name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, unsigned shift
|
||||
{name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, signed shift
|
||||
{name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1<<auxInt)
|
||||
{name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), unsigned shift
|
||||
{name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), signed shift
|
||||
{name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0<<auxInt)
|
||||
{name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), unsigned shift
|
||||
{name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), signed shift
|
||||
|
||||
{name: "ADCshiftLL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1<<auxInt + carry, arg2=flags
|
||||
{name: "ADCshiftRL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, unsigned shift, arg2=flags
|
||||
{name: "ADCshiftRA", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, signed shift, arg2=flags
|
||||
{name: "SBCshiftLL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1<<auxInt - carry, arg2=flags
|
||||
{name: "SBCshiftRL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, unsigned shift, arg2=flags
|
||||
{name: "SBCshiftRA", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, signed shift, arg2=flags
|
||||
{name: "RSCshiftLL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1<<auxInt - arg0 - carry, arg2=flags
|
||||
{name: "RSCshiftRL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, unsigned shift, arg2=flags
|
||||
{name: "RSCshiftRA", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, signed shift, arg2=flags
|
||||
|
||||
{name: "ADDSshiftLL", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt, set carry flag
|
||||
{name: "ADDSshiftRL", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift, set carry flag
|
||||
{name: "ADDSshiftRA", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift, set carry flag
|
||||
{name: "SUBSshiftLL", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt, set carry flag
|
||||
{name: "SUBSshiftRL", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift, set carry flag
|
||||
{name: "SUBSshiftRA", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift, set carry flag
|
||||
{name: "RSBSshiftLL", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0, set carry flag
|
||||
{name: "RSBSshiftRL", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift, set carry flag
|
||||
{name: "RSBSshiftRA", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift, set carry flag
|
||||
|
||||
{name: "ADDshiftLLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1<<arg2
|
||||
{name: "ADDshiftRLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift
|
||||
{name: "ADDshiftRAreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift
|
||||
{name: "SUBshiftLLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1<<arg2
|
||||
{name: "SUBshiftRLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift
|
||||
{name: "SUBshiftRAreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift
|
||||
{name: "RSBshiftLLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1<<arg2 - arg0
|
||||
{name: "RSBshiftRLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift
|
||||
{name: "RSBshiftRAreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift
|
||||
{name: "ANDshiftLLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1<<arg2)
|
||||
{name: "ANDshiftRLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), unsigned shift
|
||||
{name: "ANDshiftRAreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), signed shift
|
||||
{name: "ORshiftLLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1<<arg2
|
||||
{name: "ORshiftRLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, unsigned shift
|
||||
{name: "ORshiftRAreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, signed shift
|
||||
{name: "XORshiftLLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1<<arg2
|
||||
{name: "XORshiftRLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, unsigned shift
|
||||
{name: "XORshiftRAreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, signed shift
|
||||
{name: "BICshiftLLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1<<arg2)
|
||||
{name: "BICshiftRLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), unsigned shift
|
||||
{name: "BICshiftRAreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), signed shift
|
||||
{name: "MVNshiftLLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0<<arg1)
|
||||
{name: "MVNshiftRLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), unsigned shift
|
||||
{name: "MVNshiftRAreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), signed shift
|
||||
|
||||
{name: "ADCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1<<arg2 + carry, arg3=flags
|
||||
{name: "ADCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, unsigned shift, arg3=flags
|
||||
{name: "ADCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, signed shift, arg3=flags
|
||||
{name: "SBCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1<<arg2 - carry, arg3=flags
|
||||
{name: "SBCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, unsigned shift, arg3=flags
|
||||
{name: "SBCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, signed shift, arg3=flags
|
||||
{name: "RSCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1<<arg2 - arg0 - carry, arg3=flags
|
||||
{name: "RSCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, unsigned shift, arg3=flags
|
||||
{name: "RSCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, signed shift, arg3=flags
|
||||
|
||||
{name: "ADDSshiftLLreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1<<arg2, set carry flag
|
||||
{name: "ADDSshiftRLreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift, set carry flag
|
||||
{name: "ADDSshiftRAreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift, set carry flag
|
||||
{name: "SUBSshiftLLreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1<<arg2, set carry flag
|
||||
{name: "SUBSshiftRLreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift, set carry flag
|
||||
{name: "SUBSshiftRAreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift, set carry flag
|
||||
{name: "RSBSshiftLLreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1<<arg2 - arg0, set carry flag
|
||||
{name: "RSBSshiftRLreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift, set carry flag
|
||||
{name: "RSBSshiftRAreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift, set carry flag
|
||||
|
||||
// comparisons
|
||||
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
|
||||
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
|
||||
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags"}, // arg0 compare to -arg1
|
||||
@ -195,6 +291,15 @@ func init() {
|
||||
{name: "CMPF", argLength: 2, reg: fp2flags, asm: "CMPF", typ: "Flags"}, // arg0 compare to arg1, float32
|
||||
{name: "CMPD", argLength: 2, reg: fp2flags, asm: "CMPD", typ: "Flags"}, // arg0 compare to arg1, float64
|
||||
|
||||
{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1<<auxInt
|
||||
{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, unsigned shift
|
||||
{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift
|
||||
|
||||
{name: "CMPshiftLLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1<<arg2
|
||||
{name: "CMPshiftRLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, unsigned shift
|
||||
{name: "CMPshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, signed shift
|
||||
|
||||
// moves
|
||||
{name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", typ: "UInt32", rematerializeable: true}, // 32 low bits of auxint
|
||||
{name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
|
||||
{name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
|
||||
@ -215,6 +320,16 @@ func init() {
|
||||
{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||
{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||
|
||||
{name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW"}, // load from arg0 + arg1. arg2=mem
|
||||
{name: "MOVWloadshiftLL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1<<auxInt. arg2=mem
|
||||
{name: "MOVWloadshiftRL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1>>auxInt, unsigned shift. arg2=mem
|
||||
{name: "MOVWloadshiftRA", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1>>auxInt, signed shift. arg2=mem
|
||||
|
||||
{name: "MOVWstoreidx", argLength: 4, reg: gp2store, asm: "MOVW"}, // store arg2 to arg0 + arg1. arg3=mem
|
||||
{name: "MOVWstoreshiftLL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1<<auxInt. arg3=mem
|
||||
{name: "MOVWstoreshiftRL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1>>auxInt, unsigned shift. arg3=mem
|
||||
{name: "MOVWstoreshiftRA", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1>>auxInt, signed shift. arg3=mem
|
||||
|
||||
{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVBS"}, // move from arg0, sign-extended from byte
|
||||
{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
|
||||
{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half
|
||||
@ -232,6 +347,12 @@ func init() {
|
||||
{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
|
||||
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
|
||||
|
||||
// conditional instructions, for lowering shifts
|
||||
{name: "CMOVWHSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates HS, arg1=flags
|
||||
{name: "CMOVWLSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates LS, arg1=flags
|
||||
{name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags
|
||||
|
||||
// function calls
|
||||
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
|
||||
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64"}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
|
||||
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64"}, // call deferproc. arg0=mem, auxint=argsize, returns mem
|
||||
@ -256,8 +377,6 @@ func init() {
|
||||
{name: "LoweredSelect0", argLength: 1, reg: regInfo{inputs: []regMask{}, outputs: []regMask{buildReg("R0")}}}, // the first component of a tuple, implicitly in R0, arg0=tuple
|
||||
{name: "LoweredSelect1", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // the second component of a tuple, arg0=tuple
|
||||
|
||||
{name: "LoweredZeromask", argLength: 1, reg: gp11}, // 0 if arg0 == 1, 0xffffffff if arg0 != 0
|
||||
|
||||
// duffzero (must be 4-byte aligned)
|
||||
// arg0 = address of memory to zero (in R1, changed as side effect)
|
||||
// arg1 = value to store (always zero)
|
||||
|
@ -157,7 +157,13 @@ func (op Op) isTupleGenerator() bool {
|
||||
switch op {
|
||||
case OpAdd32carry, OpSub32carry, OpMul32uhilo,
|
||||
OpARMADDS, OpARMSUBS, OpARMMULLU,
|
||||
OpARMADDSconst, OpARMSUBSconst, OpARMRSBSconst:
|
||||
OpARMADDSconst, OpARMSUBSconst, OpARMRSBSconst,
|
||||
OpARMADDSshiftLL, OpARMSUBSshiftLL, OpARMRSBSshiftLL,
|
||||
OpARMADDSshiftRL, OpARMSUBSshiftRL, OpARMRSBSshiftRL,
|
||||
OpARMADDSshiftRA, OpARMSUBSshiftRA, OpARMRSBSshiftRA,
|
||||
OpARMADDSshiftLLreg, OpARMSUBSshiftLLreg, OpARMRSBSshiftLLreg,
|
||||
OpARMADDSshiftRLreg, OpARMSUBSshiftRLreg, OpARMRSBSshiftRLreg,
|
||||
OpARMADDSshiftRAreg, OpARMSUBSshiftRAreg, OpARMRSBSshiftRAreg:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user