mirror of https://github.com/golang/go.git
[dev.ssa] cmd/compile: handle 64-bit shifts on ARM
Also fix a mistake in previous CL about x8 and x16 shifts: the shift needs ZeroExt. Progress on SSA for ARM. Still not complete. Updates #15365. Change-Id: Ibc352760023d38bc6b9c5251e929fe26e016637a Reviewed-on: https://go-review.googlesource.com/23486 Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
90883091ff
commit
4636d02244
|
|
@ -277,6 +277,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p.Reg = gc.SSARegNum(v.Args[0])
|
||||
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)
|
||||
case ssa.OpARMHMUL,
|
||||
ssa.OpARMHMULU:
|
||||
// 32-bit high multiplication
|
||||
|
|
@ -483,6 +489,24 @@ 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:
|
||||
|
|
|
|||
|
|
@ -61,40 +61,40 @@
|
|||
|
||||
// shifts
|
||||
(Lsh32x32 x y) -> (SLL x y)
|
||||
(Lsh32x16 x y) -> (SLL x y)
|
||||
(Lsh32x8 x y) -> (SLL x y)
|
||||
(Lsh32x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
(Lsh32x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Lsh16x32 x y) -> (SLL x y)
|
||||
(Lsh16x16 x y) -> (SLL x y)
|
||||
(Lsh16x8 x y) -> (SLL x y)
|
||||
(Lsh16x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
(Lsh16x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Lsh8x32 x y) -> (SLL x y)
|
||||
(Lsh8x16 x y) -> (SLL x y)
|
||||
(Lsh8x8 x y) -> (SLL x y)
|
||||
(Lsh8x16 x y) -> (SLL x (ZeroExt16to32 y))
|
||||
(Lsh8x8 x y) -> (SLL x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh32Ux32 x y) -> (SRL x y)
|
||||
(Rsh32Ux16 x y) -> (SRL x y)
|
||||
(Rsh32Ux8 x y) -> (SRL x y)
|
||||
(Rsh32Ux16 x y) -> (SRL x (ZeroExt16to32 y))
|
||||
(Rsh32Ux8 x y) -> (SRL x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh16Ux32 x y) -> (SRL (ZeroExt16to32 x) y)
|
||||
(Rsh16Ux16 x y) -> (SRL (ZeroExt16to32 x) y)
|
||||
(Rsh16Ux8 x y) -> (SRL (ZeroExt16to32 x) y)
|
||||
(Rsh16Ux16 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||
(Rsh16Ux8 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh8Ux32 x y) -> (SRL (ZeroExt8to32 x) y)
|
||||
(Rsh8Ux16 x y) -> (SRL (ZeroExt8to32 x) y)
|
||||
(Rsh8Ux8 x y) -> (SRL (ZeroExt8to32 x) y)
|
||||
(Rsh8Ux16 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt16to32 y))
|
||||
(Rsh8Ux8 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh32x32 x y) -> (SRA x y)
|
||||
(Rsh32x16 x y) -> (SRA x y)
|
||||
(Rsh32x8 x y) -> (SRA x y)
|
||||
(Rsh32x16 x y) -> (SRA x (ZeroExt16to32 y))
|
||||
(Rsh32x8 x y) -> (SRA x (ZeroExt8to32 y))
|
||||
|
||||
(Rsh16x32 x y) -> (SRA (SignExt16to32 x) y)
|
||||
(Rsh16x16 x y) -> (SRA (SignExt16to32 x) y)
|
||||
(Rsh16x8 x y) -> (SRA (SignExt16to32 x) y)
|
||||
(Rsh16x16 x y) -> (SRA (SignExt16to32 x) (ZeroExt16to32 y))
|
||||
(Rsh16x8 x y) -> (SRA (SignExt16to32 x) (ZeroExt8to32 y))
|
||||
|
||||
(Rsh8x32 x y) -> (SRA (SignExt8to32 x) y)
|
||||
(Rsh8x16 x y) -> (SRA (SignExt8to32 x) y)
|
||||
(Rsh8x8 x y) -> (SRA (SignExt8to32 x) y)
|
||||
(Rsh8x16 x y) -> (SRA (SignExt8to32 x) (ZeroExt16to32 y))
|
||||
(Rsh8x8 x y) -> (SRA (SignExt8to32 x) (ZeroExt8to32 y))
|
||||
|
||||
// constant shifts
|
||||
// generic opt rewrites all constant shifts to shift by Const64
|
||||
|
|
@ -121,6 +121,10 @@
|
|||
(Rsh16x64 <t> x (Const64 [c])) && uint64(c) >= 16 -> (SRAconst (SLLconst <t> x [16]) [31])
|
||||
(Rsh8x64 <t> x (Const64 [c])) && uint64(c) >= 8 -> (SRAconst (SLLconst <t> x [24]) [31])
|
||||
|
||||
(Lrot32 x [c]) -> (SRRconst x [32-c&31])
|
||||
(Lrot16 <t> x [c]) -> (OR (SLLconst <t> x [c&15]) (SRLconst <t> x [16-c&15]))
|
||||
(Lrot8 <t> x [c]) -> (OR (SLLconst <t> x [c&7]) (SRLconst <t> x [8-c&7]))
|
||||
|
||||
// constants
|
||||
(Const8 [val]) -> (MOVWconst [val])
|
||||
(Const16 [val]) -> (MOVWconst [val])
|
||||
|
|
@ -144,6 +148,7 @@
|
|||
(SignExt16to32 x) -> (MOVHreg x)
|
||||
|
||||
(Signmask x) -> (SRAconst x [31])
|
||||
(Zeromask x) -> (LoweredZeromask x)
|
||||
|
||||
// comparisons
|
||||
(Eq8 x y) -> (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ func init() {
|
|||
{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: "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: "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
|
||||
|
|
@ -180,6 +181,8 @@ 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: gp11, 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
|
||||
// arg0 = address of memory to zero (in R1, changed as side effect)
|
||||
// arg1 = value to store (always zero)
|
||||
|
|
|
|||
|
|
@ -113,6 +113,231 @@
|
|||
(Rsh8x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh8x32 x lo)
|
||||
(Rsh8Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh8Ux32 x lo)
|
||||
|
||||
(Lsh64x64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const64 [0])
|
||||
(Rsh64x64 x (Int64Make (Const32 [c]) _)) && c != 0 -> (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x)))
|
||||
(Rsh64Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const64 [0])
|
||||
|
||||
(Lsh64x64 x (Int64Make (Const32 [0]) lo)) -> (Lsh64x32 x lo)
|
||||
(Rsh64x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh64x32 x lo)
|
||||
(Rsh64Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh64Ux32 x lo)
|
||||
|
||||
// turn x64 non-constant shifts to x32 shifts
|
||||
// if high 32-bit of the shift is nonzero, make a huge shift
|
||||
(Lsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Lsh64x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh64x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh64Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh64Ux32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Lsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Lsh32x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh32x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh32Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh32Ux32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Lsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Lsh16x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh16x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh16Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh16Ux32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Lsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Lsh8x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh8x32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
(Rsh8Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 ->
|
||||
(Rsh8Ux32 x (Or32 <config.fe.TypeUInt32()> (Zeromask hi) lo))
|
||||
|
||||
// 64x left shift
|
||||
// result.hi = hi<<s | lo>>(32-s) | lo<<(s-32) // >> is unsigned, large shifts result 0
|
||||
// result.lo = lo<<s
|
||||
(Lsh64x32 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Lsh32x32 <config.fe.TypeUInt32()> hi s)
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub32 <config.fe.TypeUInt32()> (Const32 <config.fe.TypeUInt32()> [32]) s)))
|
||||
(Lsh32x32 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub32 <config.fe.TypeUInt32()> s (Const32 <config.fe.TypeUInt32()> [32]))))
|
||||
(Lsh32x32 <config.fe.TypeUInt32()> lo s))
|
||||
(Lsh64x16 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Lsh32x16 <config.fe.TypeUInt32()> hi s)
|
||||
(Rsh32Ux16 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub16 <config.fe.TypeUInt16()> (Const16 <config.fe.TypeUInt16()> [32]) s)))
|
||||
(Lsh32x16 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub16 <config.fe.TypeUInt16()> s (Const16 <config.fe.TypeUInt16()> [32]))))
|
||||
(Lsh32x16 <config.fe.TypeUInt32()> lo s))
|
||||
(Lsh64x8 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Lsh32x8 <config.fe.TypeUInt32()> hi s)
|
||||
(Rsh32Ux8 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub8 <config.fe.TypeUInt8()> (Const8 <config.fe.TypeUInt8()> [32]) s)))
|
||||
(Lsh32x8 <config.fe.TypeUInt32()>
|
||||
lo
|
||||
(Sub8 <config.fe.TypeUInt8()> s (Const8 <config.fe.TypeUInt8()> [32]))))
|
||||
(Lsh32x8 <config.fe.TypeUInt32()> lo s))
|
||||
|
||||
// 64x unsigned right shift
|
||||
// result.hi = hi>>s
|
||||
// result.lo = lo>>s | hi<<(32-s) | hi>>(s-32) // >> is unsigned, large shifts result 0
|
||||
(Rsh64Ux32 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x32 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub32 <config.fe.TypeUInt32()> (Const32 <config.fe.TypeUInt32()> [32]) s)))
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub32 <config.fe.TypeUInt32()> s (Const32 <config.fe.TypeUInt32()> [32])))))
|
||||
(Rsh64Ux16 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32Ux16 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux16 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x16 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub16 <config.fe.TypeUInt16()> (Const16 <config.fe.TypeUInt16()> [32]) s)))
|
||||
(Rsh32Ux16 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub16 <config.fe.TypeUInt16()> s (Const16 <config.fe.TypeUInt16()> [32])))))
|
||||
(Rsh64Ux8 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32Ux8 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux8 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x8 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub8 <config.fe.TypeUInt8()> (Const8 <config.fe.TypeUInt8()> [32]) s)))
|
||||
(Rsh32Ux8 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub8 <config.fe.TypeUInt8()> s (Const8 <config.fe.TypeUInt8()> [32])))))
|
||||
|
||||
// 64x signed right shift
|
||||
// result.hi = hi>>s
|
||||
// result.lo = lo>>s | hi<<(32-s) | (hi>>(s-32))&^signmask(s-32) // hi>>(s-32) is signed, large shifts result 0/-1
|
||||
(Rsh64x32 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32x32 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x32 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub32 <config.fe.TypeUInt32()> (Const32 <config.fe.TypeUInt32()> [32]) s)))
|
||||
(And32 <config.fe.TypeUInt32()>
|
||||
(Rsh32x32 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub32 <config.fe.TypeUInt32()> s (Const32 <config.fe.TypeUInt32()> [32])))
|
||||
(Com32 <config.fe.TypeUInt32()>
|
||||
(Signmask
|
||||
(Sub32 <config.fe.TypeUInt32()> s (Const32 <config.fe.TypeUInt32()> [32])))))))
|
||||
(Rsh64x16 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32x16 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux16 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x16 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub16 <config.fe.TypeUInt16()> (Const16 <config.fe.TypeUInt16()> [32]) s)))
|
||||
(And32 <config.fe.TypeUInt32()>
|
||||
(Rsh32x16 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub16 <config.fe.TypeUInt16()> s (Const16 <config.fe.TypeUInt16()> [32])))
|
||||
(Com32 <config.fe.TypeUInt32()>
|
||||
(Signmask
|
||||
(SignExt16to32
|
||||
(Sub16 <config.fe.TypeUInt16()> s (Const16 <config.fe.TypeUInt16()> [32]))))))))
|
||||
(Rsh64x8 (Int64Make hi lo) s) ->
|
||||
(Int64Make
|
||||
(Rsh32x8 <config.fe.TypeUInt32()> hi s)
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Rsh32Ux8 <config.fe.TypeUInt32()> lo s)
|
||||
(Lsh32x8 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub8 <config.fe.TypeUInt8()> (Const8 <config.fe.TypeUInt8()> [32]) s)))
|
||||
(And32 <config.fe.TypeUInt32()>
|
||||
(Rsh32x8 <config.fe.TypeUInt32()>
|
||||
hi
|
||||
(Sub8 <config.fe.TypeUInt8()> s (Const8 <config.fe.TypeUInt8()> [32])))
|
||||
(Com32 <config.fe.TypeUInt32()>
|
||||
(Signmask
|
||||
(SignExt8to32
|
||||
(Sub8 <config.fe.TypeUInt8()> s (Const8 <config.fe.TypeUInt8()> [32]))))))))
|
||||
|
||||
// 64xConst32 shifts
|
||||
// we probably do not need them -- lateopt may take care of them just fine
|
||||
//(Lsh64x32 _ (Const32 [c])) && uint32(c) >= 64 -> (Const64 [0])
|
||||
//(Rsh64x32 x (Const32 [c])) && uint32(c) >= 64 -> (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x)))
|
||||
//(Rsh64Ux32 _ (Const32 [c])) && uint32(c) >= 64 -> (Const64 [0])
|
||||
//
|
||||
//(Lsh64x32 x (Const32 [c])) && c < 64 && c > 32 ->
|
||||
// (Int64Make
|
||||
// (Lsh32x32 <config.fe.TypeUInt32()> (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [c-32]))
|
||||
// (Const32 <config.fe.TypeUInt32()> [0]))
|
||||
//(Rsh64x32 x (Const32 [c])) && c < 64 && c > 32 ->
|
||||
// (Int64Make
|
||||
// (Signmask (Int64Hi x))
|
||||
// (Rsh32x32 <config.fe.TypeInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [c-32])))
|
||||
//(Rsh64Ux32 x (Const32 [c])) && c < 64 && c > 32 ->
|
||||
// (Int64Make
|
||||
// (Const32 <config.fe.TypeUInt32()> [0])
|
||||
// (Rsh32Ux32 <config.fe.TypeUInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [c-32])))
|
||||
//
|
||||
//(Lsh64x32 x (Const32 [32])) -> (Int64Make (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [0]))
|
||||
//(Rsh64x32 x (Const32 [32])) -> (Int64Make (Signmask (Int64Hi x)) (Int64Hi x))
|
||||
//(Rsh64Ux32 x (Const32 [32])) -> (Int64Make (Const32 <config.fe.TypeUInt32()> [0]) (Int64Hi x))
|
||||
//
|
||||
//(Lsh64x32 x (Const32 [c])) && c < 32 && c > 0 ->
|
||||
// (Int64Make
|
||||
// (Or32 <config.fe.TypeUInt32()>
|
||||
// (Lsh32x32 <config.fe.TypeUInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
// (Rsh32Ux32 <config.fe.TypeUInt32()> (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [32-c])))
|
||||
// (Lsh32x32 <config.fe.TypeUInt32()> (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [c])))
|
||||
//(Rsh64x32 x (Const32 [c])) && c < 32 && c > 0 ->
|
||||
// (Int64Make
|
||||
// (Rsh32x32 <config.fe.TypeInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
// (Or32 <config.fe.TypeUInt32()>
|
||||
// (Rsh32Ux32 <config.fe.TypeUInt32()> (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
// (Lsh32x32 <config.fe.TypeUInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [32-c]))))
|
||||
//(Rsh64Ux32 x (Const32 [c])) && c < 32 && c > 0 ->
|
||||
// (Int64Make
|
||||
// (Rsh32Ux32 <config.fe.TypeUInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
// (Or32 <config.fe.TypeUInt32()>
|
||||
// (Rsh32Ux32 <config.fe.TypeUInt32()> (Int64Lo x) (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
// (Lsh32x32 <config.fe.TypeUInt32()> (Int64Hi x) (Const32 <config.fe.TypeUInt32()> [32-c]))))
|
||||
//
|
||||
//(Lsh64x32 x (Const32 [0])) -> x
|
||||
//(Rsh64x32 x (Const32 [0])) -> x
|
||||
//(Rsh64Ux32 x (Const32 [0])) -> x
|
||||
|
||||
(Lrot64 (Int64Make hi lo) [c]) && c <= 32 ->
|
||||
(Int64Make
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Lsh32x32 <config.fe.TypeUInt32()> hi (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()> lo (Const32 <config.fe.TypeUInt32()> [32-c])))
|
||||
(Or32 <config.fe.TypeUInt32()>
|
||||
(Lsh32x32 <config.fe.TypeUInt32()> lo (Const32 <config.fe.TypeUInt32()> [c]))
|
||||
(Rsh32Ux32 <config.fe.TypeUInt32()> hi (Const32 <config.fe.TypeUInt32()> [32-c]))))
|
||||
(Lrot64 (Int64Make hi lo) [c]) && c > 32 -> (Lrot64 (Int64Make lo hi) [c-32])
|
||||
|
||||
(Const64 <t> [c]) && t.IsSigned() ->
|
||||
(Int64Make (Const32 <config.fe.TypeInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [c&0xffffffff]))
|
||||
(Const64 <t> [c]) && !t.IsSigned() ->
|
||||
|
|
|
|||
|
|
@ -430,7 +430,8 @@ var genericOps = []opData{
|
|||
|
||||
{name: "Mul32uhilo", argLength: 2, typ: "(UInt32,UInt32)"}, // arg0 * arg1, returns (hi, lo)
|
||||
|
||||
{name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0
|
||||
{name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0
|
||||
{name: "Zeromask", argLength: 1, typ: "UInt32"}, // 0 if arg0 == 0, 0xffffffff if arg0 != 0
|
||||
|
||||
// pseudo-ops for breaking Tuple
|
||||
{name: "Select0", argLength: 1}, // the first component of a tuple
|
||||
|
|
|
|||
|
|
@ -353,6 +353,7 @@ const (
|
|||
OpARMSRLconst
|
||||
OpARMSRA
|
||||
OpARMSRAconst
|
||||
OpARMSRRconst
|
||||
OpARMCMP
|
||||
OpARMCMPconst
|
||||
OpARMCMN
|
||||
|
|
@ -393,6 +394,7 @@ const (
|
|||
OpARMCarry
|
||||
OpARMLoweredSelect0
|
||||
OpARMLoweredSelect1
|
||||
OpARMLoweredZeromask
|
||||
OpARMDUFFZERO
|
||||
OpARMDUFFCOPY
|
||||
OpARMLoweredZero
|
||||
|
|
@ -693,6 +695,7 @@ const (
|
|||
OpSub32withcarry
|
||||
OpMul32uhilo
|
||||
OpSignmask
|
||||
OpZeromask
|
||||
OpSelect0
|
||||
OpSelect1
|
||||
)
|
||||
|
|
@ -4313,6 +4316,19 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SRRconst",
|
||||
auxType: auxInt32,
|
||||
argLen: 1,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||
},
|
||||
outputs: []regMask{
|
||||
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMP",
|
||||
argLen: 2,
|
||||
|
|
@ -4805,6 +4821,18 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "LoweredZeromask",
|
||||
argLen: 1,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||
},
|
||||
outputs: []regMask{
|
||||
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DUFFZERO",
|
||||
auxType: auxInt64,
|
||||
|
|
@ -6391,6 +6419,11 @@ var opcodeTable = [...]opInfo{
|
|||
argLen: 1,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Zeromask",
|
||||
argLen: 1,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Select0",
|
||||
argLen: 1,
|
||||
|
|
|
|||
|
|
@ -134,6 +134,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
|
|||
return rewriteValueARM_OpLess8U(v, config)
|
||||
case OpLoad:
|
||||
return rewriteValueARM_OpLoad(v, config)
|
||||
case OpLrot16:
|
||||
return rewriteValueARM_OpLrot16(v, config)
|
||||
case OpLrot32:
|
||||
return rewriteValueARM_OpLrot32(v, config)
|
||||
case OpLrot8:
|
||||
return rewriteValueARM_OpLrot8(v, config)
|
||||
case OpLsh16x16:
|
||||
return rewriteValueARM_OpLsh16x16(v, config)
|
||||
case OpLsh16x32:
|
||||
|
|
@ -310,6 +316,8 @@ func rewriteValueARM(v *Value, config *Config) bool {
|
|||
return rewriteValueARM_OpZeroExt8to16(v, config)
|
||||
case OpZeroExt8to32:
|
||||
return rewriteValueARM_OpZeroExt8to32(v, config)
|
||||
case OpZeromask:
|
||||
return rewriteValueARM_OpZeromask(v, config)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -1547,18 +1555,79 @@ func rewriteValueARM_OpLoad(v *Value, config *Config) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueARM_OpLrot16(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Lrot16 <t> x [c])
|
||||
// cond:
|
||||
// result: (OR (SLLconst <t> x [c&15]) (SRLconst <t> x [16-c&15]))
|
||||
for {
|
||||
t := v.Type
|
||||
x := v.Args[0]
|
||||
c := v.AuxInt
|
||||
v.reset(OpARMOR)
|
||||
v0 := b.NewValue0(v.Line, OpARMSLLconst, t)
|
||||
v0.AddArg(x)
|
||||
v0.AuxInt = c & 15
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
|
||||
v1.AddArg(x)
|
||||
v1.AuxInt = 16 - c&15
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM_OpLrot32(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Lrot32 x [c])
|
||||
// cond:
|
||||
// result: (SRRconst x [32-c&31])
|
||||
for {
|
||||
x := v.Args[0]
|
||||
c := v.AuxInt
|
||||
v.reset(OpARMSRRconst)
|
||||
v.AddArg(x)
|
||||
v.AuxInt = 32 - c&31
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM_OpLrot8(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Lrot8 <t> x [c])
|
||||
// cond:
|
||||
// result: (OR (SLLconst <t> x [c&7]) (SRLconst <t> x [8-c&7]))
|
||||
for {
|
||||
t := v.Type
|
||||
x := v.Args[0]
|
||||
c := v.AuxInt
|
||||
v.reset(OpARMOR)
|
||||
v0 := b.NewValue0(v.Line, OpARMSLLconst, t)
|
||||
v0.AddArg(x)
|
||||
v0.AuxInt = c & 7
|
||||
v.AddArg(v0)
|
||||
v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
|
||||
v1.AddArg(x)
|
||||
v1.AuxInt = 8 - c&7
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM_OpLsh16x16(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Lsh16x16 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1621,13 +1690,15 @@ func rewriteValueARM_OpLsh16x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Lsh16x8 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1636,13 +1707,15 @@ func rewriteValueARM_OpLsh32x16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Lsh32x16 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1705,13 +1778,15 @@ func rewriteValueARM_OpLsh32x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Lsh32x8 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1720,13 +1795,15 @@ func rewriteValueARM_OpLsh8x16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Lsh8x16 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1789,13 +1866,15 @@ func rewriteValueARM_OpLsh8x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Lsh8x8 x y)
|
||||
// cond:
|
||||
// result: (SLL x y)
|
||||
// result: (SLL x (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSLL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2512,7 +2591,7 @@ func rewriteValueARM_OpRsh16Ux16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh16Ux16 x y)
|
||||
// cond:
|
||||
// result: (SRL (ZeroExt16to32 x) y)
|
||||
// result: (SRL (ZeroExt16to32 x) (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2520,7 +2599,9 @@ func rewriteValueARM_OpRsh16Ux16(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2589,7 +2670,7 @@ func rewriteValueARM_OpRsh16Ux8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh16Ux8 x y)
|
||||
// cond:
|
||||
// result: (SRL (ZeroExt16to32 x) y)
|
||||
// result: (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2597,7 +2678,9 @@ func rewriteValueARM_OpRsh16Ux8(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2606,7 +2689,7 @@ func rewriteValueARM_OpRsh16x16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh16x16 x y)
|
||||
// cond:
|
||||
// result: (SRA (SignExt16to32 x) y)
|
||||
// result: (SRA (SignExt16to32 x) (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2614,7 +2697,9 @@ func rewriteValueARM_OpRsh16x16(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2689,7 +2774,7 @@ func rewriteValueARM_OpRsh16x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh16x8 x y)
|
||||
// cond:
|
||||
// result: (SRA (SignExt16to32 x) y)
|
||||
// result: (SRA (SignExt16to32 x) (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2697,7 +2782,9 @@ func rewriteValueARM_OpRsh16x8(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpSignExt16to32, config.fe.TypeInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2706,13 +2793,15 @@ func rewriteValueARM_OpRsh32Ux16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh32Ux16 x y)
|
||||
// cond:
|
||||
// result: (SRL x y)
|
||||
// result: (SRL x (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSRL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2775,13 +2864,15 @@ func rewriteValueARM_OpRsh32Ux8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh32Ux8 x y)
|
||||
// cond:
|
||||
// result: (SRL x y)
|
||||
// result: (SRL x (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSRL)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2790,13 +2881,15 @@ func rewriteValueARM_OpRsh32x16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh32x16 x y)
|
||||
// cond:
|
||||
// result: (SRA x y)
|
||||
// result: (SRA x (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSRA)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2861,13 +2954,15 @@ func rewriteValueARM_OpRsh32x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh32x8 x y)
|
||||
// cond:
|
||||
// result: (SRA x y)
|
||||
// result: (SRA x (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v.reset(OpARMSRA)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(y)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2876,7 +2971,7 @@ func rewriteValueARM_OpRsh8Ux16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh8Ux16 x y)
|
||||
// cond:
|
||||
// result: (SRL (ZeroExt8to32 x) y)
|
||||
// result: (SRL (ZeroExt8to32 x) (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2884,7 +2979,9 @@ func rewriteValueARM_OpRsh8Ux16(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2953,7 +3050,7 @@ func rewriteValueARM_OpRsh8Ux8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh8Ux8 x y)
|
||||
// cond:
|
||||
// result: (SRL (ZeroExt8to32 x) y)
|
||||
// result: (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2961,7 +3058,9 @@ func rewriteValueARM_OpRsh8Ux8(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -2970,7 +3069,7 @@ func rewriteValueARM_OpRsh8x16(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh8x16 x y)
|
||||
// cond:
|
||||
// result: (SRA (SignExt8to32 x) y)
|
||||
// result: (SRA (SignExt8to32 x) (ZeroExt16to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -2978,7 +3077,9 @@ func rewriteValueARM_OpRsh8x16(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -3053,7 +3154,7 @@ func rewriteValueARM_OpRsh8x8(v *Value, config *Config) bool {
|
|||
_ = b
|
||||
// match: (Rsh8x8 x y)
|
||||
// cond:
|
||||
// result: (SRA (SignExt8to32 x) y)
|
||||
// result: (SRA (SignExt8to32 x) (ZeroExt8to32 y))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
|
|
@ -3061,7 +3162,9 @@ func rewriteValueARM_OpRsh8x8(v *Value, config *Config) bool {
|
|||
v0 := b.NewValue0(v.Line, OpSignExt8to32, config.fe.TypeInt32())
|
||||
v0.AddArg(x)
|
||||
v.AddArg(v0)
|
||||
v.AddArg(y)
|
||||
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
|
||||
v1.AddArg(y)
|
||||
v.AddArg(v1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -3608,6 +3711,19 @@ func rewriteValueARM_OpZeroExt8to32(v *Value, config *Config) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
func rewriteValueARM_OpZeromask(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Zeromask x)
|
||||
// cond:
|
||||
// result: (LoweredZeromask x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
v.reset(OpARMLoweredZeromask)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
}
|
||||
func rewriteBlockARM(b *Block) bool {
|
||||
switch b.Kind {
|
||||
case BlockIf:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue