From 14cf6e20832dd64d79c345e0fd59169c5bd0eb35 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 13 Jul 2016 13:43:08 -0700 Subject: [PATCH] [dev.ssa] cmd/compile: initial 386 SSA port Basically just copied all the amd64 files, removed all the *Q ops, and rebuilt. Compiles fib successfully. Still need to do: - all the 64->32 bit op translations. - audit for instructions that aren't available on 386. - GO386=387? Update #16358 Change-Id: Ib8c684586416a554a527a5eefa0cff71424e36f5 Reviewed-on: https://go-review.googlesource.com/24912 Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/ssa/config.go | 10 +- src/cmd/compile/internal/ssa/gen/386.rules | 1181 ++ src/cmd/compile/internal/ssa/gen/386Ops.go | 477 + src/cmd/compile/internal/ssa/opGen.go | 2521 ++++ src/cmd/compile/internal/ssa/rewrite386.go | 14189 +++++++++++++++++++ src/cmd/compile/internal/x86/galign.go | 5 + src/cmd/compile/internal/x86/ssa.go | 959 ++ 7 files changed, 19340 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/ssa/gen/386.rules create mode 100644 src/cmd/compile/internal/ssa/gen/386Ops.go create mode 100644 src/cmd/compile/internal/ssa/rewrite386.go create mode 100644 src/cmd/compile/internal/x86/ssa.go diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index a27b6ce798..b7535cb4e9 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -142,8 +142,14 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config case "386": c.IntSize = 4 c.PtrSize = 4 - c.lowerBlock = rewriteBlockAMD64 - c.lowerValue = rewriteValueAMD64 // TODO(khr): full 32-bit support + c.lowerBlock = rewriteBlock386 + c.lowerValue = rewriteValue386 + c.registers = registers386[:] + c.gpRegMask = gpRegMask386 + c.fpRegMask = fpRegMask386 + c.flagRegMask = flagRegMask386 + c.FPReg = framepointerReg386 + c.hasGReg = false case "arm": c.IntSize = 4 c.PtrSize = 4 diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules new file mode 100644 index 0000000000..d5229a1c71 --- /dev/null +++ b/src/cmd/compile/internal/ssa/gen/386.rules @@ -0,0 +1,1181 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Lowering arithmetic +(AddPtr x y) -> (ADDL x y) +(Add32 x y) -> (ADDL x y) +(Add16 x y) -> (ADDL x y) +(Add8 x y) -> (ADDL x y) +(Add32F x y) -> (ADDSS x y) +(Add64F x y) -> (ADDSD x y) + +(SubPtr x y) -> (SUBL x y) +(Sub32 x y) -> (SUBL x y) +(Sub16 x y) -> (SUBL x y) +(Sub8 x y) -> (SUBL x y) +(Sub32F x y) -> (SUBSS x y) +(Sub64F x y) -> (SUBSD x y) + +(Mul32 x y) -> (MULL x y) +(Mul16 x y) -> (MULL x y) +(Mul8 x y) -> (MULL x y) +(Mul32F x y) -> (MULSS x y) +(Mul64F x y) -> (MULSD x y) + +(Div32F x y) -> (DIVSS x y) +(Div64F x y) -> (DIVSD x y) + +(Div32 x y) -> (DIVL x y) +(Div32u x y) -> (DIVLU x y) +(Div16 x y) -> (DIVW x y) +(Div16u x y) -> (DIVWU x y) +(Div8 x y) -> (DIVW (SignExt8to16 x) (SignExt8to16 y)) +(Div8u x y) -> (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + +(Hmul32 x y) -> (HMULL x y) +(Hmul32u x y) -> (HMULLU x y) +(Hmul16 x y) -> (HMULW x y) +(Hmul16u x y) -> (HMULWU x y) +(Hmul8 x y) -> (HMULB x y) +(Hmul8u x y) -> (HMULBU x y) + +(Mod32 x y) -> (MODL x y) +(Mod32u x y) -> (MODLU x y) +(Mod16 x y) -> (MODW x y) +(Mod16u x y) -> (MODWU x y) +(Mod8 x y) -> (MODW (SignExt8to16 x) (SignExt8to16 y)) +(Mod8u x y) -> (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + +(And32 x y) -> (ANDL x y) +(And16 x y) -> (ANDL x y) +(And8 x y) -> (ANDL x y) + +(Or32 x y) -> (ORL x y) +(Or16 x y) -> (ORL x y) +(Or8 x y) -> (ORL x y) + +(Xor32 x y) -> (XORL x y) +(Xor16 x y) -> (XORL x y) +(Xor8 x y) -> (XORL x y) + +(Neg32 x) -> (NEGL x) +(Neg16 x) -> (NEGL x) +(Neg8 x) -> (NEGL x) +(Neg32F x) -> (PXOR x (MOVSSconst [f2i(math.Copysign(0, -1))])) +(Neg64F x) -> (PXOR x (MOVSDconst [f2i(math.Copysign(0, -1))])) + +(Com32 x) -> (NOTL x) +(Com16 x) -> (NOTL x) +(Com8 x) -> (NOTL x) + +// Lowering boolean ops +(AndB x y) -> (ANDL x y) +(OrB x y) -> (ORL x y) +(Not x) -> (XORLconst [1] x) + +// Lowering pointer arithmetic +(OffPtr [off] ptr) && is32Bit(off) -> (ADDLconst [off] ptr) +(OffPtr [off] ptr) -> (ADDL (MOVLconst [off]) ptr) + +(Bswap32 x) -> (BSWAPL x) + +(Sqrt x) -> (SQRTSD x) + +// Lowering extension +(SignExt8to16 x) -> (MOVBLSX x) +(SignExt8to32 x) -> (MOVBLSX x) +(SignExt16to32 x) -> (MOVWLSX x) + +(ZeroExt8to16 x) -> (MOVBLZX x) +(ZeroExt8to32 x) -> (MOVBLZX x) +(ZeroExt16to32 x) -> (MOVWLZX x) + +// Lowering truncation +// Because we ignore high parts of registers, truncates are just copies. +(Trunc16to8 x) -> x +(Trunc32to8 x) -> x +(Trunc32to16 x) -> x + +// Lowering float <-> int +(Cvt32to32F x) -> (CVTSL2SS x) +(Cvt32to64F x) -> (CVTSL2SD x) + +(Cvt32Fto32 x) -> (CVTTSS2SL x) +(Cvt64Fto32 x) -> (CVTTSD2SL x) + +(Cvt32Fto64F x) -> (CVTSS2SD x) +(Cvt64Fto32F x) -> (CVTSD2SS x) + +// Lowering shifts +// Unsigned shifts need to return 0 if shift amount is >= width of shifted value. +// result = (arg << shift) & (shift >= argbits ? 0 : 0xffffffffffffffff) +(Lsh32x32 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) +(Lsh32x16 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) +(Lsh32x8 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + +(Lsh16x32 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) +(Lsh16x16 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) +(Lsh16x8 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + +(Lsh8x32 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) +(Lsh8x16 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) +(Lsh8x8 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + +(Lrot32 x [c]) -> (ROLLconst [c&31] x) +(Lrot16 x [c]) -> (ROLWconst [c&15] x) +(Lrot8 x [c]) -> (ROLBconst [c&7] x) + +(Rsh32Ux32 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPLconst y [32]))) +(Rsh32Ux16 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPWconst y [32]))) +(Rsh32Ux8 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPBconst y [32]))) + +(Rsh16Ux32 x y) -> (ANDL (SHRW x y) (SBBLcarrymask (CMPLconst y [16]))) +(Rsh16Ux16 x y) -> (ANDL (SHRW x y) (SBBLcarrymask (CMPWconst y [16]))) +(Rsh16Ux8 x y) -> (ANDL (SHRW x y) (SBBLcarrymask (CMPBconst y [16]))) + +(Rsh8Ux32 x y) -> (ANDL (SHRB x y) (SBBLcarrymask (CMPLconst y [8]))) +(Rsh8Ux16 x y) -> (ANDL (SHRB x y) (SBBLcarrymask (CMPWconst y [8]))) +(Rsh8Ux8 x y) -> (ANDL (SHRB x y) (SBBLcarrymask (CMPBconst y [8]))) + +// Signed right shift needs to return 0/-1 if shift amount is >= width of shifted value. +// We implement this by setting the shift value to -1 (all ones) if the shift value is >= width. + +(Rsh32x32 x y) -> (SARL x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [32]))))) +(Rsh32x16 x y) -> (SARL x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [32]))))) +(Rsh32x8 x y) -> (SARL x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [32]))))) + +(Rsh16x32 x y) -> (SARW x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [16]))))) +(Rsh16x16 x y) -> (SARW x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [16]))))) +(Rsh16x8 x y) -> (SARW x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [16]))))) + +(Rsh8x32 x y) -> (SARB x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [8]))))) +(Rsh8x16 x y) -> (SARB x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [8]))))) +(Rsh8x8 x y) -> (SARB x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [8]))))) + +// Lowering comparisons +(Less32 x y) -> (SETL (CMPL x y)) +(Less16 x y) -> (SETL (CMPW x y)) +(Less8 x y) -> (SETL (CMPB x y)) +(Less32U x y) -> (SETB (CMPL x y)) +(Less16U x y) -> (SETB (CMPW x y)) +(Less8U x y) -> (SETB (CMPB x y)) +// Use SETGF with reversed operands to dodge NaN case +(Less64F x y) -> (SETGF (UCOMISD y x)) +(Less32F x y) -> (SETGF (UCOMISS y x)) + +(Leq32 x y) -> (SETLE (CMPL x y)) +(Leq16 x y) -> (SETLE (CMPW x y)) +(Leq8 x y) -> (SETLE (CMPB x y)) +(Leq32U x y) -> (SETBE (CMPL x y)) +(Leq16U x y) -> (SETBE (CMPW x y)) +(Leq8U x y) -> (SETBE (CMPB x y)) +// Use SETGEF with reversed operands to dodge NaN case +(Leq64F x y) -> (SETGEF (UCOMISD y x)) +(Leq32F x y) -> (SETGEF (UCOMISS y x)) + +(Greater32 x y) -> (SETG (CMPL x y)) +(Greater16 x y) -> (SETG (CMPW x y)) +(Greater8 x y) -> (SETG (CMPB x y)) +(Greater32U x y) -> (SETA (CMPL x y)) +(Greater16U x y) -> (SETA (CMPW x y)) +(Greater8U x y) -> (SETA (CMPB x y)) +// Note Go assembler gets UCOMISx operand order wrong, but it is right here +// Bug is accommodated at generation of assembly language. +(Greater64F x y) -> (SETGF (UCOMISD x y)) +(Greater32F x y) -> (SETGF (UCOMISS x y)) + +(Geq32 x y) -> (SETGE (CMPL x y)) +(Geq16 x y) -> (SETGE (CMPW x y)) +(Geq8 x y) -> (SETGE (CMPB x y)) +(Geq32U x y) -> (SETAE (CMPL x y)) +(Geq16U x y) -> (SETAE (CMPW x y)) +(Geq8U x y) -> (SETAE (CMPB x y)) +// Note Go assembler gets UCOMISx operand order wrong, but it is right here +// Bug is accommodated at generation of assembly language. +(Geq64F x y) -> (SETGEF (UCOMISD x y)) +(Geq32F x y) -> (SETGEF (UCOMISS x y)) + +(Eq32 x y) -> (SETEQ (CMPL x y)) +(Eq16 x y) -> (SETEQ (CMPW x y)) +(Eq8 x y) -> (SETEQ (CMPB x y)) +(EqB x y) -> (SETEQ (CMPB x y)) +(EqPtr x y) -> (SETEQ (CMPL x y)) +(Eq64F x y) -> (SETEQF (UCOMISD x y)) +(Eq32F x y) -> (SETEQF (UCOMISS x y)) + +(Neq32 x y) -> (SETNE (CMPL x y)) +(Neq16 x y) -> (SETNE (CMPW x y)) +(Neq8 x y) -> (SETNE (CMPB x y)) +(NeqB x y) -> (SETNE (CMPB x y)) +(NeqPtr x y) -> (SETNE (CMPL x y)) +(Neq64F x y) -> (SETNEF (UCOMISD x y)) +(Neq32F x y) -> (SETNEF (UCOMISS x y)) + +// Lowering loads +(Load ptr mem) && is32BitInt(t) -> (MOVLload ptr mem) +(Load ptr mem) && is16BitInt(t) -> (MOVWload ptr mem) +(Load ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBload ptr mem) +(Load ptr mem) && is32BitFloat(t) -> (MOVSSload ptr mem) +(Load ptr mem) && is64BitFloat(t) -> (MOVSDload ptr mem) + +// Lowering stores +// These more-specific FP versions of Store pattern should come first. +(Store [8] ptr val mem) && is64BitFloat(val.Type) -> (MOVSDstore ptr val mem) +(Store [4] ptr val mem) && is32BitFloat(val.Type) -> (MOVSSstore ptr val mem) + +(Store [4] ptr val mem) -> (MOVLstore ptr val mem) +(Store [2] ptr val mem) -> (MOVWstore ptr val mem) +(Store [1] ptr val mem) -> (MOVBstore ptr val mem) + +// Lowering moves +(Move [s] _ _ mem) && SizeAndAlign(s).Size() == 0 -> mem +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstore dst (MOVBload src mem) mem) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 2 -> (MOVWstore dst (MOVWload src mem) mem) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 4 -> (MOVLstore dst (MOVLload src mem) mem) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 16 -> (MOVOstore dst (MOVOload src mem) mem) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 3 -> + (MOVBstore [2] dst (MOVBload [2] src mem) + (MOVWstore dst (MOVWload src mem) mem)) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 5 -> + (MOVBstore [4] dst (MOVBload [4] src mem) + (MOVLstore dst (MOVLload src mem) mem)) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 6 -> + (MOVWstore [4] dst (MOVWload [4] src mem) + (MOVLstore dst (MOVLload src mem) mem)) +(Move [s] dst src mem) && SizeAndAlign(s).Size() == 7 -> + (MOVLstore [3] dst (MOVLload [3] src mem) + (MOVLstore dst (MOVLload src mem) mem)) + +// Medium copying uses a duff device. +(Move [s] dst src mem) + && SizeAndAlign(s).Size() >= 32 && SizeAndAlign(s).Size() <= 16*64 && SizeAndAlign(s).Size()%16 == 0 + && !config.noDuffDevice -> + (DUFFCOPY [14*(64-SizeAndAlign(s).Size()/16)] dst src mem) +// 14 and 64 are magic constants. 14 is the number of bytes to encode: +// MOVUPS (SI), X0 +// ADDL $16, SI +// MOVUPS X0, (DI) +// ADDL $16, DI +// and 64 is the number of such blocks. See src/runtime/duff_amd64.s:duffcopy. + +// Large copying uses REP MOVSL. +(Move [s] dst src mem) && (SizeAndAlign(s).Size() > 16*64 || config.noDuffDevice) && SizeAndAlign(s).Size()%8 == 0 -> + (REPMOVSL dst src (MOVLconst [SizeAndAlign(s).Size()/4]) mem) + +// Lowering Zero instructions +(Zero [s] _ mem) && SizeAndAlign(s).Size() == 0 -> mem +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstoreconst [0] destptr mem) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 2 -> (MOVWstoreconst [0] destptr mem) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 4 -> (MOVLstoreconst [0] destptr mem) + +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 3 -> + (MOVBstoreconst [makeValAndOff(0,2)] destptr + (MOVWstoreconst [0] destptr mem)) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 5 -> + (MOVBstoreconst [makeValAndOff(0,4)] destptr + (MOVLstoreconst [0] destptr mem)) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 6 -> + (MOVWstoreconst [makeValAndOff(0,4)] destptr + (MOVLstoreconst [0] destptr mem)) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 7 -> + (MOVLstoreconst [makeValAndOff(0,3)] destptr + (MOVLstoreconst [0] destptr mem)) + +// Strip off any fractional word zeroing. +(Zero [s] destptr mem) && SizeAndAlign(s).Size()%4 != 0 && SizeAndAlign(s).Size() > 4 -> + (Zero [SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%4] (ADDLconst destptr [SizeAndAlign(s).Size()%4]) + (MOVLstoreconst [0] destptr mem)) + +// Zero small numbers of words directly. +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 8 -> + (MOVLstoreconst [makeValAndOff(0,4)] destptr + (MOVLstoreconst [0] destptr mem)) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 12 -> + (MOVLstoreconst [makeValAndOff(0,8)] destptr + (MOVLstoreconst [makeValAndOff(0,4)] destptr + (MOVLstoreconst [0] destptr mem))) +(Zero [s] destptr mem) && SizeAndAlign(s).Size() == 16 -> + (MOVLstoreconst [makeValAndOff(0,12)] destptr + (MOVLstoreconst [makeValAndOff(0,8)] destptr + (MOVLstoreconst [makeValAndOff(0,4)] destptr + (MOVLstoreconst [0] destptr mem)))) + +// Large zeroing uses REP STOSQ. +(Zero [s] destptr mem) + && (SizeAndAlign(s).Size() > 1024 || (config.noDuffDevice && SizeAndAlign(s).Size() > 32)) + && SizeAndAlign(s).Size()%8 == 0 -> + (REPSTOSL destptr (MOVLconst [SizeAndAlign(s).Size()/8]) (MOVLconst [0]) mem) + +// Lowering constants +(Const8 [val]) -> (MOVLconst [val]) +(Const16 [val]) -> (MOVLconst [val]) +(Const32 [val]) -> (MOVLconst [val]) +(Const32F [val]) -> (MOVSSconst [val]) +(Const64F [val]) -> (MOVSDconst [val]) +(ConstNil) -> (MOVLconst [0]) +(ConstBool [b]) -> (MOVLconst [b]) + +// Lowering calls +(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) +(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem) +(DeferCall [argwid] mem) -> (CALLdefer [argwid] mem) +(GoCall [argwid] mem) -> (CALLgo [argwid] mem) +(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem) + +// Miscellaneous +(Convert x mem) -> (MOVLconvert x mem) +(IsNonNil p) -> (SETNE (TESTL p p)) +(IsInBounds idx len) -> (SETB (CMPL idx len)) +(IsSliceInBounds idx len) -> (SETBE (CMPL idx len)) +(NilCheck ptr mem) -> (LoweredNilCheck ptr mem) +(GetG mem) -> (LoweredGetG mem) +(GetClosurePtr) -> (LoweredGetClosurePtr) +(Addr {sym} base) -> (LEAL {sym} base) + +// block rewrites +(If (SETL cmp) yes no) -> (LT cmp yes no) +(If (SETLE cmp) yes no) -> (LE cmp yes no) +(If (SETG cmp) yes no) -> (GT cmp yes no) +(If (SETGE cmp) yes no) -> (GE cmp yes no) +(If (SETEQ cmp) yes no) -> (EQ cmp yes no) +(If (SETNE cmp) yes no) -> (NE cmp yes no) +(If (SETB cmp) yes no) -> (ULT cmp yes no) +(If (SETBE cmp) yes no) -> (ULE cmp yes no) +(If (SETA cmp) yes no) -> (UGT cmp yes no) +(If (SETAE cmp) yes no) -> (UGE cmp yes no) + +// Special case for floating point - LF/LEF not generated +(If (SETGF cmp) yes no) -> (UGT cmp yes no) +(If (SETGEF cmp) yes no) -> (UGE cmp yes no) +(If (SETEQF cmp) yes no) -> (EQF cmp yes no) +(If (SETNEF cmp) yes no) -> (NEF cmp yes no) + +(If cond yes no) -> (NE (TESTB cond cond) yes no) + +// *************************** +// Above: lowering rules +// Below: optimizations +// *************************** +// TODO: Should the optimizations be a separate pass? + +// Fold boolean tests into blocks +(NE (TESTB (SETL cmp) (SETL cmp)) yes no) -> (LT cmp yes no) +(NE (TESTB (SETLE cmp) (SETLE cmp)) yes no) -> (LE cmp yes no) +(NE (TESTB (SETG cmp) (SETG cmp)) yes no) -> (GT cmp yes no) +(NE (TESTB (SETGE cmp) (SETGE cmp)) yes no) -> (GE cmp yes no) +(NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no) -> (EQ cmp yes no) +(NE (TESTB (SETNE cmp) (SETNE cmp)) yes no) -> (NE cmp yes no) +(NE (TESTB (SETB cmp) (SETB cmp)) yes no) -> (ULT cmp yes no) +(NE (TESTB (SETBE cmp) (SETBE cmp)) yes no) -> (ULE cmp yes no) +(NE (TESTB (SETA cmp) (SETA cmp)) yes no) -> (UGT cmp yes no) +(NE (TESTB (SETAE cmp) (SETAE cmp)) yes no) -> (UGE cmp yes no) + +// Special case for floating point - LF/LEF not generated +(NE (TESTB (SETGF cmp) (SETGF cmp)) yes no) -> (UGT cmp yes no) +(NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no) -> (UGE cmp yes no) +(NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no) -> (EQF cmp yes no) +(NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no) -> (NEF cmp yes no) + +// fold constants into instructions +(ADDL x (MOVLconst [c])) -> (ADDLconst [c] x) +(ADDL (MOVLconst [c]) x) -> (ADDLconst [c] x) + +(SUBL x (MOVLconst [c])) -> (SUBLconst x [c]) +(SUBL (MOVLconst [c]) x) -> (NEGL (SUBLconst x [c])) + +(MULL x (MOVLconst [c])) -> (MULLconst [c] x) +(MULL (MOVLconst [c]) x) -> (MULLconst [c] x) + +(ANDL x (MOVLconst [c])) -> (ANDLconst [c] x) +(ANDL (MOVLconst [c]) x) -> (ANDLconst [c] x) + +(ANDLconst [c] (ANDLconst [d] x)) -> (ANDLconst [c & d] x) + +(XORLconst [c] (XORLconst [d] x)) -> (XORLconst [c ^ d] x) + +(MULLconst [c] (MULLconst [d] x)) -> (MULLconst [int64(int32(c * d))] x) + +(ORL x (MOVLconst [c])) -> (ORLconst [c] x) +(ORL (MOVLconst [c]) x) -> (ORLconst [c] x) + +(XORL x (MOVLconst [c])) -> (XORLconst [c] x) +(XORL (MOVLconst [c]) x) -> (XORLconst [c] x) + +(SHLL x (MOVLconst [c])) -> (SHLLconst [c&31] x) +(SHLL x (MOVLconst [c])) -> (SHLLconst [c&31] x) + +(SHRL x (MOVLconst [c])) -> (SHRLconst [c&31] x) +(SHRL x (MOVLconst [c])) -> (SHRLconst [c&31] x) + +(SHRW x (MOVLconst [c])) -> (SHRWconst [c&31] x) +(SHRW x (MOVLconst [c])) -> (SHRWconst [c&31] x) + +(SHRB x (MOVLconst [c])) -> (SHRBconst [c&31] x) +(SHRB x (MOVLconst [c])) -> (SHRBconst [c&31] x) + +(SARL x (MOVLconst [c])) -> (SARLconst [c&31] x) +(SARL x (MOVLconst [c])) -> (SARLconst [c&31] x) + +(SARW x (MOVLconst [c])) -> (SARWconst [c&31] x) +(SARW x (MOVLconst [c])) -> (SARWconst [c&31] x) + +(SARB x (MOVLconst [c])) -> (SARBconst [c&31] x) +(SARB x (MOVLconst [c])) -> (SARBconst [c&31] x) + +(SARL x (ANDLconst [31] y)) -> (SARL x y) + +(SHLL x (ANDLconst [31] y)) -> (SHLL x y) + +(SHRL x (ANDLconst [31] y)) -> (SHRL x y) + +(ROLLconst [c] (ROLLconst [d] x)) -> (ROLLconst [(c+d)&31] x) +(ROLWconst [c] (ROLWconst [d] x)) -> (ROLWconst [(c+d)&15] x) +(ROLBconst [c] (ROLBconst [d] x)) -> (ROLBconst [(c+d)& 7] x) + +(ROLLconst [0] x) -> x +(ROLWconst [0] x) -> x +(ROLBconst [0] x) -> x + +// Note: the word and byte shifts keep the low 5 bits (not the low 4 or 3 bits) +// because the x86 instructions are defined to use all 5 bits of the shift even +// for the small shifts. I don't think we'll ever generate a weird shift (e.g. +// (SHRW x (MOVLconst [24])), but just in case. + +(CMPL x (MOVLconst [c])) -> (CMPLconst x [c]) +(CMPL (MOVLconst [c]) x) -> (InvertFlags (CMPLconst x [c])) +(CMPW x (MOVLconst [c])) -> (CMPWconst x [int64(int16(c))]) +(CMPW (MOVLconst [c]) x) -> (InvertFlags (CMPWconst x [int64(int16(c))])) +(CMPB x (MOVLconst [c])) -> (CMPBconst x [int64(int8(c))]) +(CMPB (MOVLconst [c]) x) -> (InvertFlags (CMPBconst x [int64(int8(c))])) + +// strength reduction +// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf: +// 1 - addq, shlq, leaq, negq +// 3 - imulq +// This limits the rewrites to two instructions. +// TODO: 27, 81 +(MULLconst [-1] x) -> (NEGL x) +(MULLconst [0] _) -> (MOVLconst [0]) +(MULLconst [1] x) -> x +(MULLconst [3] x) -> (LEAL2 x x) +(MULLconst [5] x) -> (LEAL4 x x) +(MULLconst [7] x) -> (LEAL8 (NEGL x) x) +(MULLconst [9] x) -> (LEAL8 x x) +(MULLconst [11] x) -> (LEAL2 x (LEAL4 x x)) +(MULLconst [13] x) -> (LEAL4 x (LEAL2 x x)) +(MULLconst [21] x) -> (LEAL4 x (LEAL4 x x)) +(MULLconst [25] x) -> (LEAL8 x (LEAL2 x x)) +(MULLconst [37] x) -> (LEAL4 x (LEAL8 x x)) +(MULLconst [41] x) -> (LEAL8 x (LEAL4 x x)) +(MULLconst [73] x) -> (LEAL8 x (LEAL8 x x)) + +(MULLconst [c] x) && isPowerOfTwo(c) -> (SHLLconst [log2(c)] x) +(MULLconst [c] x) && isPowerOfTwo(c+1) && c >= 15 -> (SUBL (SHLLconst [log2(c+1)] x) x) +(MULLconst [c] x) && isPowerOfTwo(c-1) && c >= 17 -> (LEAL1 (SHLLconst [log2(c-1)] x) x) +(MULLconst [c] x) && isPowerOfTwo(c-2) && c >= 34 -> (LEAL2 (SHLLconst [log2(c-2)] x) x) +(MULLconst [c] x) && isPowerOfTwo(c-4) && c >= 68 -> (LEAL4 (SHLLconst [log2(c-4)] x) x) +(MULLconst [c] x) && isPowerOfTwo(c-8) && c >= 136 -> (LEAL8 (SHLLconst [log2(c-8)] x) x) +(MULLconst [c] x) && c%3 == 0 && isPowerOfTwo(c/3)-> (SHLLconst [log2(c/3)] (LEAL2 x x)) +(MULLconst [c] x) && c%5 == 0 && isPowerOfTwo(c/5)-> (SHLLconst [log2(c/5)] (LEAL4 x x)) +(MULLconst [c] x) && c%9 == 0 && isPowerOfTwo(c/9)-> (SHLLconst [log2(c/9)] (LEAL8 x x)) + +// combine add/shift into LEAL +(ADDL x (SHLLconst [3] y)) -> (LEAL8 x y) +(ADDL x (SHLLconst [2] y)) -> (LEAL4 x y) +(ADDL x (SHLLconst [1] y)) -> (LEAL2 x y) +(ADDL x (ADDL y y)) -> (LEAL2 x y) +(ADDL x (ADDL x y)) -> (LEAL2 y x) +(ADDL x (ADDL y x)) -> (LEAL2 y x) + +// combine ADDL/ADDLconst into LEAL1 +(ADDLconst [c] (ADDL x y)) -> (LEAL1 [c] x y) +(ADDL (ADDLconst [c] x) y) -> (LEAL1 [c] x y) +(ADDL x (ADDLconst [c] y)) -> (LEAL1 [c] x y) + +// fold ADDL into LEAL +(ADDLconst [c] (LEAL [d] {s} x)) && is32Bit(c+d) -> (LEAL [c+d] {s} x) +(LEAL [c] {s} (ADDLconst [d] x)) && is32Bit(c+d) -> (LEAL [c+d] {s} x) +(LEAL [c] {s} (ADDL x y)) && x.Op != OpSB && y.Op != OpSB -> (LEAL1 [c] {s} x y) +(ADDL x (LEAL [c] {s} y)) && x.Op != OpSB && y.Op != OpSB -> (LEAL1 [c] {s} x y) +(ADDL (LEAL [c] {s} x) y) && x.Op != OpSB && y.Op != OpSB -> (LEAL1 [c] {s} x y) + +// fold ADDLconst into LEALx +(ADDLconst [c] (LEAL1 [d] {s} x y)) && is32Bit(c+d) -> (LEAL1 [c+d] {s} x y) +(ADDLconst [c] (LEAL2 [d] {s} x y)) && is32Bit(c+d) -> (LEAL2 [c+d] {s} x y) +(ADDLconst [c] (LEAL4 [d] {s} x y)) && is32Bit(c+d) -> (LEAL4 [c+d] {s} x y) +(ADDLconst [c] (LEAL8 [d] {s} x y)) && is32Bit(c+d) -> (LEAL8 [c+d] {s} x y) +(LEAL1 [c] {s} (ADDLconst [d] x) y) && is32Bit(c+d) && x.Op != OpSB -> (LEAL1 [c+d] {s} x y) +(LEAL1 [c] {s} x (ADDLconst [d] y)) && is32Bit(c+d) && y.Op != OpSB -> (LEAL1 [c+d] {s} x y) +(LEAL2 [c] {s} (ADDLconst [d] x) y) && is32Bit(c+d) && x.Op != OpSB -> (LEAL2 [c+d] {s} x y) +(LEAL2 [c] {s} x (ADDLconst [d] y)) && is32Bit(c+2*d) && y.Op != OpSB -> (LEAL2 [c+2*d] {s} x y) +(LEAL4 [c] {s} (ADDLconst [d] x) y) && is32Bit(c+d) && x.Op != OpSB -> (LEAL4 [c+d] {s} x y) +(LEAL4 [c] {s} x (ADDLconst [d] y)) && is32Bit(c+4*d) && y.Op != OpSB -> (LEAL4 [c+4*d] {s} x y) +(LEAL8 [c] {s} (ADDLconst [d] x) y) && is32Bit(c+d) && x.Op != OpSB -> (LEAL8 [c+d] {s} x y) +(LEAL8 [c] {s} x (ADDLconst [d] y)) && is32Bit(c+8*d) && y.Op != OpSB -> (LEAL8 [c+8*d] {s} x y) + +// fold shifts into LEALx +(LEAL1 [c] {s} x (SHLLconst [1] y)) -> (LEAL2 [c] {s} x y) +(LEAL1 [c] {s} (SHLLconst [1] x) y) -> (LEAL2 [c] {s} y x) +(LEAL1 [c] {s} x (SHLLconst [2] y)) -> (LEAL4 [c] {s} x y) +(LEAL1 [c] {s} (SHLLconst [2] x) y) -> (LEAL4 [c] {s} y x) +(LEAL1 [c] {s} x (SHLLconst [3] y)) -> (LEAL8 [c] {s} x y) +(LEAL1 [c] {s} (SHLLconst [3] x) y) -> (LEAL8 [c] {s} y x) + +(LEAL2 [c] {s} x (SHLLconst [1] y)) -> (LEAL4 [c] {s} x y) +(LEAL2 [c] {s} x (SHLLconst [2] y)) -> (LEAL8 [c] {s} x y) +(LEAL4 [c] {s} x (SHLLconst [1] y)) -> (LEAL8 [c] {s} x y) + +// reverse ordering of compare instruction +(SETL (InvertFlags x)) -> (SETG x) +(SETG (InvertFlags x)) -> (SETL x) +(SETB (InvertFlags x)) -> (SETA x) +(SETA (InvertFlags x)) -> (SETB x) +(SETLE (InvertFlags x)) -> (SETGE x) +(SETGE (InvertFlags x)) -> (SETLE x) +(SETBE (InvertFlags x)) -> (SETAE x) +(SETAE (InvertFlags x)) -> (SETBE x) +(SETEQ (InvertFlags x)) -> (SETEQ x) +(SETNE (InvertFlags x)) -> (SETNE x) + +// sign extended loads +// Note: The combined instruction must end up in the same block +// as the original load. If not, we end up making a value with +// memory type live in two different blocks, which can lead to +// multiple memory values alive simultaneously. +// Make sure we don't combine these ops if the load has another use. +// This prevents a single load from being split into multiple loads +// which then might return different values. See test/atomicload.go. +(MOVBLSX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBLSXload [off] {sym} ptr mem) +(MOVBLZX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBload [off] {sym} ptr mem) +(MOVWLSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWLSXload [off] {sym} ptr mem) +(MOVWLZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWload [off] {sym} ptr mem) + +(MOVBLZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) +(MOVWLZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) +(MOVWLZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) + +// replace load from same location as preceding store with copy +(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x +(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x +(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x + +// Fold extensions and ANDs together. +(MOVBLZX (ANDLconst [c] x)) -> (ANDLconst [c & 0xff] x) +(MOVWLZX (ANDLconst [c] x)) -> (ANDLconst [c & 0xffff] x) +(MOVBLSX (ANDLconst [c] x)) && c & 0x80 == 0 -> (ANDLconst [c & 0x7f] x) +(MOVWLSX (ANDLconst [c] x)) && c & 0x8000 == 0 -> (ANDLconst [c & 0x7fff] x) + +// Don't extend before storing +(MOVWstore [off] {sym} ptr (MOVWLSX x) mem) -> (MOVWstore [off] {sym} ptr x mem) +(MOVBstore [off] {sym} ptr (MOVBLSX x) mem) -> (MOVBstore [off] {sym} ptr x mem) +(MOVWstore [off] {sym} ptr (MOVWLZX x) mem) -> (MOVWstore [off] {sym} ptr x mem) +(MOVBstore [off] {sym} ptr (MOVBLZX x) mem) -> (MOVBstore [off] {sym} ptr x mem) + +// fold constants into memory operations +// Note that this is not always a good idea because if not all the uses of +// the ADDQconst get eliminated, we still have to compute the ADDQconst and we now +// have potentially two live values (ptr and (ADDQconst [off] ptr)) instead of one. +// Nevertheless, let's do it! +(MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVLload [off1+off2] {sym} ptr mem) +(MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWload [off1+off2] {sym} ptr mem) +(MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBload [off1+off2] {sym} ptr mem) +(MOVSSload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVSSload [off1+off2] {sym} ptr mem) +(MOVSDload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVSDload [off1+off2] {sym} ptr mem) +(MOVOload [off1] {sym} (ADDLconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVOload [off1+off2] {sym} ptr mem) + +(MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVLstore [off1+off2] {sym} ptr val mem) +(MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} ptr val mem) +(MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} ptr val mem) +(MOVSSstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVSSstore [off1+off2] {sym} ptr val mem) +(MOVSDstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVSDstore [off1+off2] {sym} ptr val mem) +(MOVOstore [off1] {sym} (ADDLconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVOstore [off1+off2] {sym} ptr val mem) + +// Fold constants into stores. +(MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) -> + (MOVLstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem) +(MOVWstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) -> + (MOVWstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem) +(MOVBstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) -> + (MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem) + +// Fold address offsets into constant stores. +(MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) -> + (MOVLstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) +(MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) -> + (MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) +(MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) -> + (MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) + +// We need to fold LEAQ into the MOVx ops so that the live variable analysis knows +// what variables are being read/written by the ops. +(MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVSSload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVSDload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVOload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVOload [off1+off2] {mergeSym(sym1,sym2)} base mem) + +(MOVBLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVBLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem) +(MOVWLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem) + +(MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVSSstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVSDstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) +(MOVOstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVOstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + +(MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) -> + (MOVLstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) +(MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) -> + (MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) +(MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) -> + (MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) + +// generating indexed loads and stores +(MOVBload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVBloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVWload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVWload [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVLload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVLload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVSSload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVSSload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVSDload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVSDload [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + +(MOVBstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVBstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVWstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVWstore [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVLstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVLstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVLstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVSSstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVSSstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSSstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVSDstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) +(MOVSDstore [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (MOVSDstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + +(MOVBload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVBloadidx1 [off] {sym} ptr idx mem) +(MOVWload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVWloadidx1 [off] {sym} ptr idx mem) +(MOVLload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVLloadidx1 [off] {sym} ptr idx mem) +(MOVSSload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVSSloadidx1 [off] {sym} ptr idx mem) +(MOVSDload [off] {sym} (ADDL ptr idx) mem) && ptr.Op != OpSB -> (MOVSDloadidx1 [off] {sym} ptr idx mem) +(MOVBstore [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOVBstoreidx1 [off] {sym} ptr idx val mem) +(MOVWstore [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOVWstoreidx1 [off] {sym} ptr idx val mem) +(MOVLstore [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOVLstoreidx1 [off] {sym} ptr idx val mem) +(MOVSSstore [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOVSSstoreidx1 [off] {sym} ptr idx val mem) +(MOVSDstore [off] {sym} (ADDL ptr idx) val mem) && ptr.Op != OpSB -> (MOVSDstoreidx1 [off] {sym} ptr idx val mem) + +(MOVBstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVBstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVWstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVWstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVWstoreconst [x] {sym1} (LEAL2 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVLstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVLstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVLstoreconst [x] {sym1} (LEAL4 [off] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + +(MOVBstoreconst [x] {sym} (ADDL ptr idx) mem) -> (MOVBstoreconstidx1 [x] {sym} ptr idx mem) +(MOVWstoreconst [x] {sym} (ADDL ptr idx) mem) -> (MOVWstoreconstidx1 [x] {sym} ptr idx mem) +(MOVLstoreconst [x] {sym} (ADDL ptr idx) mem) -> (MOVLstoreconstidx1 [x] {sym} ptr idx mem) + +// combine SHLL into indexed loads and stores +(MOVWloadidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) -> (MOVWloadidx2 [c] {sym} ptr idx mem) +(MOVLloadidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLloadidx4 [c] {sym} ptr idx mem) +(MOVWstoreidx1 [c] {sym} ptr (SHLLconst [1] idx) val mem) -> (MOVWstoreidx2 [c] {sym} ptr idx val mem) +(MOVLstoreidx1 [c] {sym} ptr (SHLLconst [2] idx) val mem) -> (MOVLstoreidx4 [c] {sym} ptr idx val mem) +(MOVWstoreconstidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) -> (MOVWstoreconstidx2 [c] {sym} ptr idx mem) +(MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLstoreconstidx4 [c] {sym} ptr idx mem) + +// combine ADDL into indexed loads and stores +(MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem) +(MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem) +(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [c+d] {sym} ptr idx mem) +(MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem) +(MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx4 [c+d] {sym} ptr idx mem) +(MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem) +(MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx4 [c+d] {sym} ptr idx mem) +(MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem) +(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [c+d] {sym} ptr idx mem) + +(MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [c+d] {sym} ptr idx val mem) +(MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [c+d] {sym} ptr idx val mem) +(MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem) +(MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem) + +(MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem) +(MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem) +(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [c+2*d] {sym} ptr idx mem) +(MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem) +(MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx4 [c+4*d] {sym} ptr idx mem) +(MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem) +(MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem) +(MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem) +(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem) + +(MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem) +(MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem) +(MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem) +(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) +(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem) + +(MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) -> + (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVWstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) -> + (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVWstoreconstidx2 [x] {sym} (ADDLconst [c] ptr) idx mem) -> + (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVLstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) -> + (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVLstoreconstidx4 [x] {sym} (ADDLconst [c] ptr) idx mem) -> + (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) + +(MOVBstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) -> + (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVWstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) -> + (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVWstoreconstidx2 [x] {sym} ptr (ADDLconst [c] idx) mem) -> + (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) +(MOVLstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) -> + (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) +(MOVLstoreconstidx4 [x] {sym} ptr (ADDLconst [c] idx) mem) -> + (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) + +// fold LEALs together +(LEAL [off1] {sym1} (LEAL [off2] {sym2} x)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL [off1+off2] {mergeSym(sym1,sym2)} x) + +// LEAL into LEAL1 +(LEAL1 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB -> + (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) +(LEAL1 [off1] {sym1} x (LEAL [off2] {sym2} y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && y.Op != OpSB -> + (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) + +// LEAL1 into LEAL +(LEAL [off1] {sym1} (LEAL1 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) + +// LEAL into LEAL[248] +(LEAL2 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB -> + (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y) +(LEAL4 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB -> + (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y) +(LEAL8 [off1] {sym1} (LEAL [off2] {sym2} x) y) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB -> + (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y) + +// LEAL[248] into LEAL +(LEAL [off1] {sym1} (LEAL2 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y) +(LEAL [off1] {sym1} (LEAL4 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y) +(LEAL [off1] {sym1} (LEAL8 [off2] {sym2} x y)) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) -> + (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y) + +// Absorb InvertFlags into branches. +(LT (InvertFlags cmp) yes no) -> (GT cmp yes no) +(GT (InvertFlags cmp) yes no) -> (LT cmp yes no) +(LE (InvertFlags cmp) yes no) -> (GE cmp yes no) +(GE (InvertFlags cmp) yes no) -> (LE cmp yes no) +(ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no) +(UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no) +(ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no) +(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) +(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) +(NE (InvertFlags cmp) yes no) -> (NE cmp yes no) + +// Constant comparisons. +(CMPLconst (MOVLconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ) +(CMPLconst (MOVLconst [x]) [y]) && int32(x) (FlagLT_ULT) +(CMPLconst (MOVLconst [x]) [y]) && int32(x)uint32(y) -> (FlagLT_UGT) +(CMPLconst (MOVLconst [x]) [y]) && int32(x)>int32(y) && uint32(x) (FlagGT_ULT) +(CMPLconst (MOVLconst [x]) [y]) && int32(x)>int32(y) && uint32(x)>uint32(y) -> (FlagGT_UGT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)==int16(y) -> (FlagEQ) +(CMPWconst (MOVLconst [x]) [y]) && int16(x) (FlagLT_ULT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)uint16(y) -> (FlagLT_UGT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)>int16(y) && uint16(x) (FlagGT_ULT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)>int16(y) && uint16(x)>uint16(y) -> (FlagGT_UGT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)==int8(y) -> (FlagEQ) +(CMPBconst (MOVLconst [x]) [y]) && int8(x) (FlagLT_ULT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)uint8(y) -> (FlagLT_UGT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)>int8(y) && uint8(x) (FlagGT_ULT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)>int8(y) && uint8(x)>uint8(y) -> (FlagGT_UGT) + +// Other known comparisons. +(CMPLconst (SHRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1< (FlagLT_ULT) +(CMPLconst (ANDLconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) -> (FlagLT_ULT) +(CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < int16(n) -> (FlagLT_ULT) +(CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < int8(n) -> (FlagLT_ULT) +// TODO: DIVxU also. + +// Absorb flag constants into SBB ops. +(SBBLcarrymask (FlagEQ)) -> (MOVLconst [0]) +(SBBLcarrymask (FlagLT_ULT)) -> (MOVLconst [-1]) +(SBBLcarrymask (FlagLT_UGT)) -> (MOVLconst [0]) +(SBBLcarrymask (FlagGT_ULT)) -> (MOVLconst [-1]) +(SBBLcarrymask (FlagGT_UGT)) -> (MOVLconst [0]) + +// Absorb flag constants into branches. +(EQ (FlagEQ) yes no) -> (First nil yes no) +(EQ (FlagLT_ULT) yes no) -> (First nil no yes) +(EQ (FlagLT_UGT) yes no) -> (First nil no yes) +(EQ (FlagGT_ULT) yes no) -> (First nil no yes) +(EQ (FlagGT_UGT) yes no) -> (First nil no yes) + +(NE (FlagEQ) yes no) -> (First nil no yes) +(NE (FlagLT_ULT) yes no) -> (First nil yes no) +(NE (FlagLT_UGT) yes no) -> (First nil yes no) +(NE (FlagGT_ULT) yes no) -> (First nil yes no) +(NE (FlagGT_UGT) yes no) -> (First nil yes no) + +(LT (FlagEQ) yes no) -> (First nil no yes) +(LT (FlagLT_ULT) yes no) -> (First nil yes no) +(LT (FlagLT_UGT) yes no) -> (First nil yes no) +(LT (FlagGT_ULT) yes no) -> (First nil no yes) +(LT (FlagGT_UGT) yes no) -> (First nil no yes) + +(LE (FlagEQ) yes no) -> (First nil yes no) +(LE (FlagLT_ULT) yes no) -> (First nil yes no) +(LE (FlagLT_UGT) yes no) -> (First nil yes no) +(LE (FlagGT_ULT) yes no) -> (First nil no yes) +(LE (FlagGT_UGT) yes no) -> (First nil no yes) + +(GT (FlagEQ) yes no) -> (First nil no yes) +(GT (FlagLT_ULT) yes no) -> (First nil no yes) +(GT (FlagLT_UGT) yes no) -> (First nil no yes) +(GT (FlagGT_ULT) yes no) -> (First nil yes no) +(GT (FlagGT_UGT) yes no) -> (First nil yes no) + +(GE (FlagEQ) yes no) -> (First nil yes no) +(GE (FlagLT_ULT) yes no) -> (First nil no yes) +(GE (FlagLT_UGT) yes no) -> (First nil no yes) +(GE (FlagGT_ULT) yes no) -> (First nil yes no) +(GE (FlagGT_UGT) yes no) -> (First nil yes no) + +(ULT (FlagEQ) yes no) -> (First nil no yes) +(ULT (FlagLT_ULT) yes no) -> (First nil yes no) +(ULT (FlagLT_UGT) yes no) -> (First nil no yes) +(ULT (FlagGT_ULT) yes no) -> (First nil yes no) +(ULT (FlagGT_UGT) yes no) -> (First nil no yes) + +(ULE (FlagEQ) yes no) -> (First nil yes no) +(ULE (FlagLT_ULT) yes no) -> (First nil yes no) +(ULE (FlagLT_UGT) yes no) -> (First nil no yes) +(ULE (FlagGT_ULT) yes no) -> (First nil yes no) +(ULE (FlagGT_UGT) yes no) -> (First nil no yes) + +(UGT (FlagEQ) yes no) -> (First nil no yes) +(UGT (FlagLT_ULT) yes no) -> (First nil no yes) +(UGT (FlagLT_UGT) yes no) -> (First nil yes no) +(UGT (FlagGT_ULT) yes no) -> (First nil no yes) +(UGT (FlagGT_UGT) yes no) -> (First nil yes no) + +(UGE (FlagEQ) yes no) -> (First nil yes no) +(UGE (FlagLT_ULT) yes no) -> (First nil no yes) +(UGE (FlagLT_UGT) yes no) -> (First nil yes no) +(UGE (FlagGT_ULT) yes no) -> (First nil no yes) +(UGE (FlagGT_UGT) yes no) -> (First nil yes no) + +// Absorb flag constants into SETxx ops. +(SETEQ (FlagEQ)) -> (MOVLconst [1]) +(SETEQ (FlagLT_ULT)) -> (MOVLconst [0]) +(SETEQ (FlagLT_UGT)) -> (MOVLconst [0]) +(SETEQ (FlagGT_ULT)) -> (MOVLconst [0]) +(SETEQ (FlagGT_UGT)) -> (MOVLconst [0]) + +(SETNE (FlagEQ)) -> (MOVLconst [0]) +(SETNE (FlagLT_ULT)) -> (MOVLconst [1]) +(SETNE (FlagLT_UGT)) -> (MOVLconst [1]) +(SETNE (FlagGT_ULT)) -> (MOVLconst [1]) +(SETNE (FlagGT_UGT)) -> (MOVLconst [1]) + +(SETL (FlagEQ)) -> (MOVLconst [0]) +(SETL (FlagLT_ULT)) -> (MOVLconst [1]) +(SETL (FlagLT_UGT)) -> (MOVLconst [1]) +(SETL (FlagGT_ULT)) -> (MOVLconst [0]) +(SETL (FlagGT_UGT)) -> (MOVLconst [0]) + +(SETLE (FlagEQ)) -> (MOVLconst [1]) +(SETLE (FlagLT_ULT)) -> (MOVLconst [1]) +(SETLE (FlagLT_UGT)) -> (MOVLconst [1]) +(SETLE (FlagGT_ULT)) -> (MOVLconst [0]) +(SETLE (FlagGT_UGT)) -> (MOVLconst [0]) + +(SETG (FlagEQ)) -> (MOVLconst [0]) +(SETG (FlagLT_ULT)) -> (MOVLconst [0]) +(SETG (FlagLT_UGT)) -> (MOVLconst [0]) +(SETG (FlagGT_ULT)) -> (MOVLconst [1]) +(SETG (FlagGT_UGT)) -> (MOVLconst [1]) + +(SETGE (FlagEQ)) -> (MOVLconst [1]) +(SETGE (FlagLT_ULT)) -> (MOVLconst [0]) +(SETGE (FlagLT_UGT)) -> (MOVLconst [0]) +(SETGE (FlagGT_ULT)) -> (MOVLconst [1]) +(SETGE (FlagGT_UGT)) -> (MOVLconst [1]) + +(SETB (FlagEQ)) -> (MOVLconst [0]) +(SETB (FlagLT_ULT)) -> (MOVLconst [1]) +(SETB (FlagLT_UGT)) -> (MOVLconst [0]) +(SETB (FlagGT_ULT)) -> (MOVLconst [1]) +(SETB (FlagGT_UGT)) -> (MOVLconst [0]) + +(SETBE (FlagEQ)) -> (MOVLconst [1]) +(SETBE (FlagLT_ULT)) -> (MOVLconst [1]) +(SETBE (FlagLT_UGT)) -> (MOVLconst [0]) +(SETBE (FlagGT_ULT)) -> (MOVLconst [1]) +(SETBE (FlagGT_UGT)) -> (MOVLconst [0]) + +(SETA (FlagEQ)) -> (MOVLconst [0]) +(SETA (FlagLT_ULT)) -> (MOVLconst [0]) +(SETA (FlagLT_UGT)) -> (MOVLconst [1]) +(SETA (FlagGT_ULT)) -> (MOVLconst [0]) +(SETA (FlagGT_UGT)) -> (MOVLconst [1]) + +(SETAE (FlagEQ)) -> (MOVLconst [1]) +(SETAE (FlagLT_ULT)) -> (MOVLconst [0]) +(SETAE (FlagLT_UGT)) -> (MOVLconst [1]) +(SETAE (FlagGT_ULT)) -> (MOVLconst [0]) +(SETAE (FlagGT_UGT)) -> (MOVLconst [1]) + +// Remove redundant *const ops +(ADDLconst [c] x) && int32(c)==0 -> x +(SUBLconst [c] x) && int32(c) == 0 -> x +(ANDLconst [c] _) && int32(c)==0 -> (MOVLconst [0]) +(ANDLconst [c] x) && int32(c)==-1 -> x +(ORLconst [c] x) && int32(c)==0 -> x +(ORLconst [c] _) && int32(c)==-1 -> (MOVLconst [-1]) +(XORLconst [c] x) && int32(c)==0 -> x +// TODO: since we got rid of the W/B versions, we might miss +// things like (ANDLconst [0x100] x) which were formerly +// (ANDBconst [0] x). Probably doesn't happen very often. +// If we cared, we might do: +// (ANDLconst [c] x) && t.Size()==1 && int8(x)==0 -> (MOVLconst [0]) + +// Convert constant subtracts to constant adds +(SUBLconst [c] x) -> (ADDLconst [int64(int32(-c))] x) + +// generic constant folding +// TODO: more of this +(ADDLconst [c] (MOVLconst [d])) -> (MOVLconst [int64(int32(c+d))]) +(ADDLconst [c] (ADDLconst [d] x)) -> (ADDLconst [int64(int32(c+d))] x) +(SARLconst [c] (MOVLconst [d])) -> (MOVLconst [d>>uint64(c)]) +(SARWconst [c] (MOVLconst [d])) -> (MOVLconst [d>>uint64(c)]) +(SARBconst [c] (MOVLconst [d])) -> (MOVLconst [d>>uint64(c)]) +(NEGL (MOVLconst [c])) -> (MOVLconst [int64(int32(-c))]) +(MULLconst [c] (MOVLconst [d])) -> (MOVLconst [int64(int32(c*d))]) +(ANDLconst [c] (MOVLconst [d])) -> (MOVLconst [c&d]) +(ORLconst [c] (MOVLconst [d])) -> (MOVLconst [c|d]) +(XORLconst [c] (MOVLconst [d])) -> (MOVLconst [c^d]) +(NOTL (MOVLconst [c])) -> (MOVLconst [^c]) + +// generic simplifications +// TODO: more of this +(ADDL x (NEGL y)) -> (SUBL x y) +(SUBL x x) -> (MOVLconst [0]) +(ANDL x x) -> x +(ORL x x) -> x +(XORL x x) -> (MOVLconst [0]) + +// checking AND against 0. +(CMPLconst (ANDL x y) [0]) -> (TESTL x y) +(CMPWconst (ANDL x y) [0]) -> (TESTW x y) +(CMPBconst (ANDL x y) [0]) -> (TESTB x y) +(CMPLconst (ANDLconst [c] x) [0]) -> (TESTLconst [c] x) +(CMPWconst (ANDLconst [c] x) [0]) -> (TESTWconst [int64(int16(c))] x) +(CMPBconst (ANDLconst [c] x) [0]) -> (TESTBconst [int64(int8(c))] x) + +// TEST %reg,%reg is shorter than CMP +(CMPLconst x [0]) -> (TESTL x x) +(CMPWconst x [0]) -> (TESTW x x) +(CMPBconst x [0]) -> (TESTB x x) + +// Combining byte loads into larger (unaligned) loads. +// There are many ways these combinations could occur. This is +// designed to match the way encoding/binary.LittleEndian does it. +(ORL x0:(MOVBload [i] {s} p mem) + s0:(SHLLconst [8] x1:(MOVBload [i+1] {s} p mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && s0.Uses == 1 + && mergePoint(b,x0,x1) != nil + && clobber(x0) + && clobber(x1) + && clobber(s0) + -> @mergePoint(b,x0,x1) (MOVWload [i] {s} p mem) + +(ORL o0:(ORL o1:(ORL + x0:(MOVBload [i] {s} p mem) + s0:(SHLLconst [8] x1:(MOVBload [i+1] {s} p mem))) + s1:(SHLLconst [16] x2:(MOVBload [i+2] {s} p mem))) + s2:(SHLLconst [24] x3:(MOVBload [i+3] {s} p mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && x2.Uses == 1 + && x3.Uses == 1 + && s0.Uses == 1 + && s1.Uses == 1 + && s2.Uses == 1 + && o0.Uses == 1 + && o1.Uses == 1 + && mergePoint(b,x0,x1,x2,x3) != nil + && clobber(x0) + && clobber(x1) + && clobber(x2) + && clobber(x3) + && clobber(s0) + && clobber(s1) + && clobber(s2) + && clobber(o0) + && clobber(o1) + -> @mergePoint(b,x0,x1,x2,x3) (MOVLload [i] {s} p mem) + +(ORL x0:(MOVBloadidx1 [i] {s} p idx mem) + s0:(SHLLconst [8] x1:(MOVBloadidx1 [i+1] {s} p idx mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && s0.Uses == 1 + && mergePoint(b,x0,x1) != nil + && clobber(x0) + && clobber(x1) + && clobber(s0) + -> @mergePoint(b,x0,x1) (MOVWloadidx1 [i] {s} p idx mem) + +(ORL o0:(ORL o1:(ORL + x0:(MOVBloadidx1 [i] {s} p idx mem) + s0:(SHLLconst [8] x1:(MOVBloadidx1 [i+1] {s} p idx mem))) + s1:(SHLLconst [16] x2:(MOVBloadidx1 [i+2] {s} p idx mem))) + s2:(SHLLconst [24] x3:(MOVBloadidx1 [i+3] {s} p idx mem))) + && x0.Uses == 1 + && x1.Uses == 1 + && x2.Uses == 1 + && x3.Uses == 1 + && s0.Uses == 1 + && s1.Uses == 1 + && s2.Uses == 1 + && o0.Uses == 1 + && o1.Uses == 1 + && mergePoint(b,x0,x1,x2,x3) != nil + && clobber(x0) + && clobber(x1) + && clobber(x2) + && clobber(x3) + && clobber(s0) + && clobber(s1) + && clobber(s2) + && clobber(o0) + && clobber(o1) + -> @mergePoint(b,x0,x1,x2,x3) (MOVLloadidx1 [i] {s} p idx mem) + +// Combine constant stores into larger (unaligned) stores. +(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) + && x.Uses == 1 + && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() + && clobber(x) + -> (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) +(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) + && x.Uses == 1 + && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() + && clobber(x) + -> (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + +(MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) + && x.Uses == 1 + && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() + && clobber(x) + -> (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) +(MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) + && x.Uses == 1 + && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() + && clobber(x) + -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) + +(MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) + && x.Uses == 1 + && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() + && clobber(x) + -> (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLLconst [1] i) mem) + +// Combine stores into larger (unaligned) stores. +(MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVWstore [i-1] {s} p w mem) +(MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVWstore [i-1] {s} p w0 mem) +(MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstore [i-2] {s} p w mem) +(MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstore [i-2] {s} p w0 mem) + +(MOVBstoreidx1 [i] {s} p idx (SHRLconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVWstoreidx1 [i-1] {s} p idx w mem) +(MOVBstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRLconst [j-8] w) mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVWstoreidx1 [i-1] {s} p idx w0 mem) +(MOVWstoreidx1 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstoreidx1 [i-2] {s} p idx w mem) +(MOVWstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstoreidx1 [i-2] {s} p idx w0 mem) + +(MOVWstoreidx2 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w mem) +(MOVWstoreidx2 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) + && x.Uses == 1 + && clobber(x) + -> (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w0 mem) diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go new file mode 100644 index 0000000000..b5221d291e --- /dev/null +++ b/src/cmd/compile/internal/ssa/gen/386Ops.go @@ -0,0 +1,477 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import "strings" + +// Notes: +// - Integer types live in the low portion of registers. Upper portions are junk. +// - Boolean types use the low-order byte of a register. 0=false, 1=true. +// Upper bytes are junk. +// - Floating-point types live in the low natural slot of an sse2 register. +// Unused portions are junk. +// - We do not use AH,BH,CH,DH registers. +// - When doing sub-register operations, we try to write the whole +// destination register to avoid a partial-register write. +// - Unused portions of AuxInt (or the Val portion of ValAndOff) are +// filled by sign-extending the used portion. Users of AuxInt which interpret +// AuxInt as unsigned (e.g. shifts) must be careful. + +// Suffixes encode the bit width of various instructions. +// L (long word) = 32 bit +// W (word) = 16 bit +// B (byte) = 8 bit + +// copied from ../../x86/reg.go +var regNames386 = []string{ + "AX", + "CX", + "DX", + "BX", + "SP", + "BP", + "SI", + "DI", + "X0", + "X1", + "X2", + "X3", + "X4", + "X5", + "X6", + "X7", + + // pseudo-registers + "SB", + "FLAGS", +} + +func init() { + // Make map from reg names to reg integers. + if len(regNames386) > 64 { + panic("too many registers") + } + num := map[string]int{} + for i, name := range regNames386 { + num[name] = i + } + buildReg := func(s string) regMask { + m := regMask(0) + for _, r := range strings.Split(s, " ") { + if n, ok := num[r]; ok { + m |= regMask(1) << uint(n) + continue + } + panic("register " + r + " not found") + } + return m + } + + // Common individual register masks + var ( + ax = buildReg("AX") + cx = buildReg("CX") + dx = buildReg("DX") + gp = buildReg("AX CX DX BX BP SI DI") + fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7") + x7 = buildReg("X7") + gpsp = gp | buildReg("SP") + gpspsb = gpsp | buildReg("SB") + flags = buildReg("FLAGS") + callerSave = gp | fp | flags + ) + // Common slices of register masks + var ( + gponly = []regMask{gp} + fponly = []regMask{fp} + flagsonly = []regMask{flags} + ) + + // Common regInfo + var ( + gp01 = regInfo{inputs: []regMask{}, outputs: gponly} + gp11 = regInfo{inputs: []regMask{gp}, outputs: gponly, clobbers: flags} + gp11sp = regInfo{inputs: []regMask{gpsp}, outputs: gponly, clobbers: flags} + gp11nf = regInfo{inputs: []regMask{gpsp}, outputs: gponly} // nf: no flags clobbered + gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly} + gp21 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly, clobbers: flags} + gp21sp = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly, clobbers: flags} + gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly} + gp21shift = regInfo{inputs: []regMask{gp, cx}, outputs: []regMask{gp}, clobbers: flags} + gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax}, + clobbers: dx | flags} + gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, + clobbers: ax | flags} + gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx}, + clobbers: ax | flags} + + gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} + gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} + flagsgp = regInfo{inputs: flagsonly, outputs: gponly} + + readflags = regInfo{inputs: flagsonly, outputs: gponly} + flagsgpax = regInfo{inputs: flagsonly, clobbers: ax | flags, outputs: []regMask{gp &^ ax}} + + gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly} + gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly} + + gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}} + gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}} + gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}} + gpstoreconstidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}} + + fp01 = regInfo{inputs: []regMask{}, outputs: fponly} + fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} + fp21x7 = regInfo{inputs: []regMask{fp &^ x7, fp &^ x7}, + clobbers: x7, outputs: []regMask{fp &^ x7}} + fpgp = regInfo{inputs: fponly, outputs: gponly} + gpfp = regInfo{inputs: gponly, outputs: fponly} + fp11 = regInfo{inputs: fponly, outputs: fponly} + fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly} + + fpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly} + fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly} + + fpstore = regInfo{inputs: []regMask{gpspsb, fp, 0}} + fpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, fp, 0}} + ) + + var _386ops = []opData{ + // fp ops + {name: "ADDSS", argLength: 2, reg: fp21, asm: "ADDSS", commutative: true, resultInArg0: true}, // fp32 add + {name: "ADDSD", argLength: 2, reg: fp21, asm: "ADDSD", commutative: true, resultInArg0: true}, // fp64 add + {name: "SUBSS", argLength: 2, reg: fp21x7, asm: "SUBSS", resultInArg0: true}, // fp32 sub + {name: "SUBSD", argLength: 2, reg: fp21x7, asm: "SUBSD", resultInArg0: true}, // fp64 sub + {name: "MULSS", argLength: 2, reg: fp21, asm: "MULSS", commutative: true, resultInArg0: true}, // fp32 mul + {name: "MULSD", argLength: 2, reg: fp21, asm: "MULSD", commutative: true, resultInArg0: true}, // fp64 mul + {name: "DIVSS", argLength: 2, reg: fp21x7, asm: "DIVSS", resultInArg0: true}, // fp32 div + {name: "DIVSD", argLength: 2, reg: fp21x7, asm: "DIVSD", resultInArg0: true}, // fp64 div + + {name: "MOVSSload", argLength: 2, reg: fpload, asm: "MOVSS", aux: "SymOff"}, // fp32 load + {name: "MOVSDload", argLength: 2, reg: fpload, asm: "MOVSD", aux: "SymOff"}, // fp64 load + {name: "MOVSSconst", reg: fp01, asm: "MOVSS", aux: "Float32", rematerializeable: true}, // fp32 constant + {name: "MOVSDconst", reg: fp01, asm: "MOVSD", aux: "Float64", rematerializeable: true}, // fp64 constant + {name: "MOVSSloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSS", aux: "SymOff"}, // fp32 load indexed by i + {name: "MOVSSloadidx4", argLength: 3, reg: fploadidx, asm: "MOVSS", aux: "SymOff"}, // fp32 load indexed by 4*i + {name: "MOVSDloadidx1", argLength: 3, reg: fploadidx, asm: "MOVSD", aux: "SymOff"}, // fp64 load indexed by i + {name: "MOVSDloadidx8", argLength: 3, reg: fploadidx, asm: "MOVSD", aux: "SymOff"}, // fp64 load indexed by 8*i + + {name: "MOVSSstore", argLength: 3, reg: fpstore, asm: "MOVSS", aux: "SymOff"}, // fp32 store + {name: "MOVSDstore", argLength: 3, reg: fpstore, asm: "MOVSD", aux: "SymOff"}, // fp64 store + {name: "MOVSSstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSS", aux: "SymOff"}, // fp32 indexed by i store + {name: "MOVSSstoreidx4", argLength: 4, reg: fpstoreidx, asm: "MOVSS", aux: "SymOff"}, // fp32 indexed by 4i store + {name: "MOVSDstoreidx1", argLength: 4, reg: fpstoreidx, asm: "MOVSD", aux: "SymOff"}, // fp64 indexed by i store + {name: "MOVSDstoreidx8", argLength: 4, reg: fpstoreidx, asm: "MOVSD", aux: "SymOff"}, // fp64 indexed by 8i store + + // binary ops + {name: "ADDL", argLength: 2, reg: gp21sp, asm: "ADDL", commutative: true}, // arg0 + arg1 + {name: "ADDLconst", argLength: 1, reg: gp11sp, asm: "ADDL", aux: "Int32", typ: "UInt32"}, // arg0 + auxint + + {name: "SUBL", argLength: 2, reg: gp21, asm: "SUBL", resultInArg0: true}, // arg0 - arg1 + {name: "SUBLconst", argLength: 1, reg: gp11, asm: "SUBL", aux: "Int32", resultInArg0: true}, // arg0 - auxint + + {name: "MULL", argLength: 2, reg: gp21, asm: "IMULL", commutative: true, resultInArg0: true}, // arg0 * arg1 + {name: "MULLconst", argLength: 1, reg: gp11, asm: "IMULL", aux: "Int32", resultInArg0: true}, // arg0 * auxint + + {name: "HMULL", argLength: 2, reg: gp11hmul, asm: "IMULL"}, // (arg0 * arg1) >> width + {name: "HMULW", argLength: 2, reg: gp11hmul, asm: "IMULW"}, // (arg0 * arg1) >> width + {name: "HMULB", argLength: 2, reg: gp11hmul, asm: "IMULB"}, // (arg0 * arg1) >> width + {name: "HMULLU", argLength: 2, reg: gp11hmul, asm: "MULL"}, // (arg0 * arg1) >> width + {name: "HMULWU", argLength: 2, reg: gp11hmul, asm: "MULW"}, // (arg0 * arg1) >> width + {name: "HMULBU", argLength: 2, reg: gp11hmul, asm: "MULB"}, // (arg0 * arg1) >> width + + {name: "DIVL", argLength: 2, reg: gp11div, asm: "IDIVL"}, // arg0 / arg1 + {name: "DIVW", argLength: 2, reg: gp11div, asm: "IDIVW"}, // arg0 / arg1 + {name: "DIVLU", argLength: 2, reg: gp11div, asm: "DIVL"}, // arg0 / arg1 + {name: "DIVWU", argLength: 2, reg: gp11div, asm: "DIVW"}, // arg0 / arg1 + + {name: "MODL", argLength: 2, reg: gp11mod, asm: "IDIVL"}, // arg0 % arg1 + {name: "MODW", argLength: 2, reg: gp11mod, asm: "IDIVW"}, // arg0 % arg1 + {name: "MODLU", argLength: 2, reg: gp11mod, asm: "DIVL"}, // arg0 % arg1 + {name: "MODWU", argLength: 2, reg: gp11mod, asm: "DIVW"}, // arg0 % arg1 + + {name: "ANDL", argLength: 2, reg: gp21, asm: "ANDL", commutative: true, resultInArg0: true}, // arg0 & arg1 + {name: "ANDLconst", argLength: 1, reg: gp11, asm: "ANDL", aux: "Int32", resultInArg0: true}, // arg0 & auxint + + {name: "ORL", argLength: 2, reg: gp21, asm: "ORL", commutative: true, resultInArg0: true}, // arg0 | arg1 + {name: "ORLconst", argLength: 1, reg: gp11, asm: "ORL", aux: "Int32", resultInArg0: true}, // arg0 | auxint + + {name: "XORL", argLength: 2, reg: gp21, asm: "XORL", commutative: true, resultInArg0: true}, // arg0 ^ arg1 + {name: "XORLconst", argLength: 1, reg: gp11, asm: "XORL", aux: "Int32", resultInArg0: true}, // arg0 ^ auxint + + {name: "CMPL", argLength: 2, reg: gp2flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPB", argLength: 2, reg: gp2flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPLconst", argLength: 1, reg: gp1flags, asm: "CMPL", typ: "Flags", aux: "Int32"}, // arg0 compare to auxint + {name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int16"}, // arg0 compare to auxint + {name: "CMPBconst", argLength: 1, reg: gp1flags, asm: "CMPB", typ: "Flags", aux: "Int8"}, // arg0 compare to auxint + + {name: "UCOMISS", argLength: 2, reg: fp2flags, asm: "UCOMISS", typ: "Flags"}, // arg0 compare to arg1, f32 + {name: "UCOMISD", argLength: 2, reg: fp2flags, asm: "UCOMISD", typ: "Flags"}, // arg0 compare to arg1, f64 + + {name: "TESTL", argLength: 2, reg: gp2flags, asm: "TESTL", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTW", argLength: 2, reg: gp2flags, asm: "TESTW", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTB", argLength: 2, reg: gp2flags, asm: "TESTB", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTLconst", argLength: 1, reg: gp1flags, asm: "TESTL", typ: "Flags", aux: "Int32"}, // (arg0 & auxint) compare to 0 + {name: "TESTWconst", argLength: 1, reg: gp1flags, asm: "TESTW", typ: "Flags", aux: "Int16"}, // (arg0 & auxint) compare to 0 + {name: "TESTBconst", argLength: 1, reg: gp1flags, asm: "TESTB", typ: "Flags", aux: "Int8"}, // (arg0 & auxint) compare to 0 + + {name: "SHLL", argLength: 2, reg: gp21shift, asm: "SHLL", resultInArg0: true}, // arg0 << arg1, shift amount is mod 32 + {name: "SHLLconst", argLength: 1, reg: gp11, asm: "SHLL", aux: "Int32", resultInArg0: true}, // arg0 << auxint, shift amount 0-31 + // Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount! + + {name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int32", resultInArg0: true}, // unsigned arg0 >> auxint, shift amount 0-31 + {name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int16", resultInArg0: true}, // unsigned arg0 >> auxint, shift amount 0-31 + {name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true}, // unsigned arg0 >> auxint, shift amount 0-31 + + {name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int32", resultInArg0: true}, // signed arg0 >> auxint, shift amount 0-31 + {name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int16", resultInArg0: true}, // signed arg0 >> auxint, shift amount 0-31 + {name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true}, // signed arg0 >> auxint, shift amount 0-31 + + {name: "ROLLconst", argLength: 1, reg: gp11, asm: "ROLL", aux: "Int32", resultInArg0: true}, // arg0 rotate left auxint, rotate amount 0-31 + {name: "ROLWconst", argLength: 1, reg: gp11, asm: "ROLW", aux: "Int16", resultInArg0: true}, // arg0 rotate left auxint, rotate amount 0-15 + {name: "ROLBconst", argLength: 1, reg: gp11, asm: "ROLB", aux: "Int8", resultInArg0: true}, // arg0 rotate left auxint, rotate amount 0-7 + + // unary ops + {name: "NEGL", argLength: 1, reg: gp11, asm: "NEGL", resultInArg0: true}, // -arg0 + + {name: "NOTL", argLength: 1, reg: gp11, asm: "NOTL", resultInArg0: true}, // ^arg0 + + {name: "BSFL", argLength: 1, reg: gp11, asm: "BSFL"}, // arg0 # of low-order zeroes ; undef if zero + {name: "BSFW", argLength: 1, reg: gp11, asm: "BSFW"}, // arg0 # of low-order zeroes ; undef if zero + + {name: "BSRL", argLength: 1, reg: gp11, asm: "BSRL"}, // arg0 # of high-order zeroes ; undef if zero + {name: "BSRW", argLength: 1, reg: gp11, asm: "BSRW"}, // arg0 # of high-order zeroes ; undef if zero + + {name: "BSWAPL", argLength: 1, reg: gp11, asm: "BSWAPL", resultInArg0: true}, // arg0 swap bytes + + {name: "SQRTSD", argLength: 1, reg: fp11, asm: "SQRTSD"}, // sqrt(arg0) + + {name: "SBBLcarrymask", argLength: 1, reg: flagsgp, asm: "SBBL"}, // (int32)(-1) if carry is set, 0 if carry is clear. + // Note: SBBW and SBBB are subsumed by SBBL + + {name: "SETEQ", argLength: 1, reg: readflags, asm: "SETEQ"}, // extract == condition from arg0 + {name: "SETNE", argLength: 1, reg: readflags, asm: "SETNE"}, // extract != condition from arg0 + {name: "SETL", argLength: 1, reg: readflags, asm: "SETLT"}, // extract signed < condition from arg0 + {name: "SETLE", argLength: 1, reg: readflags, asm: "SETLE"}, // extract signed <= condition from arg0 + {name: "SETG", argLength: 1, reg: readflags, asm: "SETGT"}, // extract signed > condition from arg0 + {name: "SETGE", argLength: 1, reg: readflags, asm: "SETGE"}, // extract signed >= condition from arg0 + {name: "SETB", argLength: 1, reg: readflags, asm: "SETCS"}, // extract unsigned < condition from arg0 + {name: "SETBE", argLength: 1, reg: readflags, asm: "SETLS"}, // extract unsigned <= condition from arg0 + {name: "SETA", argLength: 1, reg: readflags, asm: "SETHI"}, // extract unsigned > condition from arg0 + {name: "SETAE", argLength: 1, reg: readflags, asm: "SETCC"}, // extract unsigned >= condition from arg0 + // Need different opcodes for floating point conditions because + // any comparison involving a NaN is always FALSE and thus + // the patterns for inverting conditions cannot be used. + {name: "SETEQF", argLength: 1, reg: flagsgpax, asm: "SETEQ"}, // extract == condition from arg0 + {name: "SETNEF", argLength: 1, reg: flagsgpax, asm: "SETNE"}, // extract != condition from arg0 + {name: "SETORD", argLength: 1, reg: flagsgp, asm: "SETPC"}, // extract "ordered" (No Nan present) condition from arg0 + {name: "SETNAN", argLength: 1, reg: flagsgp, asm: "SETPS"}, // extract "unordered" (Nan present) condition from arg0 + + {name: "SETGF", argLength: 1, reg: flagsgp, asm: "SETHI"}, // extract floating > condition from arg0 + {name: "SETGEF", argLength: 1, reg: flagsgp, asm: "SETCC"}, // extract floating >= condition from arg0 + + {name: "MOVBLSX", argLength: 1, reg: gp11nf, asm: "MOVBLSX"}, // sign extend arg0 from int8 to int32 + {name: "MOVBLZX", argLength: 1, reg: gp11nf, asm: "MOVBLZX"}, // zero extend arg0 from int8 to int32 + {name: "MOVWLSX", argLength: 1, reg: gp11nf, asm: "MOVWLSX"}, // sign extend arg0 from int16 to int32 + {name: "MOVWLZX", argLength: 1, reg: gp11nf, asm: "MOVWLZX"}, // zero extend arg0 from int16 to int32 + + {name: "MOVLconst", reg: gp01, asm: "MOVL", typ: "UInt32", aux: "Int32", rematerializeable: true}, // 32 low bits of auxint + + {name: "CVTTSD2SL", argLength: 1, reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32 + {name: "CVTTSS2SL", argLength: 1, reg: fpgp, asm: "CVTTSS2SL"}, // convert float32 to int32 + {name: "CVTSL2SS", argLength: 1, reg: gpfp, asm: "CVTSL2SS"}, // convert int32 to float32 + {name: "CVTSL2SD", argLength: 1, reg: gpfp, asm: "CVTSL2SD"}, // convert int32 to float64 + {name: "CVTSD2SS", argLength: 1, reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32 + {name: "CVTSS2SD", argLength: 1, reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64 + + {name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation. + + {name: "LEAL", argLength: 1, reg: gp11sb, aux: "SymOff", rematerializeable: true}, // arg0 + auxint + offset encoded in aux + {name: "LEAL1", argLength: 2, reg: gp21sb, aux: "SymOff"}, // arg0 + arg1 + auxint + aux + {name: "LEAL2", argLength: 2, reg: gp21sb, aux: "SymOff"}, // arg0 + 2*arg1 + auxint + aux + {name: "LEAL4", argLength: 2, reg: gp21sb, aux: "SymOff"}, // arg0 + 4*arg1 + auxint + aux + {name: "LEAL8", argLength: 2, reg: gp21sb, aux: "SymOff"}, // arg0 + 8*arg1 + auxint + aux + // Note: LEAL{1,2,4,8} must not have OpSB as either argument. + + // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address + {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVBLZX", aux: "SymOff", typ: "UInt8"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVBLSXload", argLength: 2, reg: gpload, asm: "MOVBLSX", aux: "SymOff"}, // ditto, sign extend to int32 + {name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVWLZX", aux: "SymOff", typ: "UInt16"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVWLSXload", argLength: 2, reg: gpload, asm: "MOVWLSX", aux: "SymOff"}, // ditto, sign extend to int32 + {name: "MOVLload", argLength: 2, reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend. + {name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVLstore", argLength: 3, reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVOload", argLength: 2, reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128"}, // load 16 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVOstore", argLength: 3, reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem"}, // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem + + // indexed loads/stores + {name: "MOVBloadidx1", argLength: 3, reg: gploadidx, asm: "MOVBLZX", aux: "SymOff"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem + {name: "MOVWloadidx1", argLength: 3, reg: gploadidx, asm: "MOVWLZX", aux: "SymOff"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem + {name: "MOVWloadidx2", argLength: 3, reg: gploadidx, asm: "MOVWLZX", aux: "SymOff"}, // load 2 bytes from arg0+2*arg1+auxint+aux. arg2=mem + {name: "MOVLloadidx1", argLength: 3, reg: gploadidx, asm: "MOVL", aux: "SymOff"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem + {name: "MOVLloadidx4", argLength: 3, reg: gploadidx, asm: "MOVL", aux: "SymOff"}, // load 4 bytes from arg0+4*arg1+auxint+aux. arg2=mem + // TODO: sign-extending indexed loads + {name: "MOVBstoreidx1", argLength: 4, reg: gpstoreidx, asm: "MOVB", aux: "SymOff"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem + {name: "MOVWstoreidx1", argLength: 4, reg: gpstoreidx, asm: "MOVW", aux: "SymOff"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem + {name: "MOVWstoreidx2", argLength: 4, reg: gpstoreidx, asm: "MOVW", aux: "SymOff"}, // store 2 bytes in arg2 to arg0+2*arg1+auxint+aux. arg3=mem + {name: "MOVLstoreidx1", argLength: 4, reg: gpstoreidx, asm: "MOVL", aux: "SymOff"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem + {name: "MOVLstoreidx4", argLength: 4, reg: gpstoreidx, asm: "MOVL", aux: "SymOff"}, // store 4 bytes in arg2 to arg0+4*arg1+auxint+aux. arg3=mem + // TODO: add size-mismatched indexed loads, like MOVBstoreidx4. + + // For storeconst ops, the AuxInt field encodes both + // the value to store and an address offset of the store. + // Cast AuxInt to a ValAndOff to extract Val and Off fields. + {name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem + {name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem"}, // store low 2 bytes of ... + {name: "MOVLstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVL", aux: "SymValAndOff", typ: "Mem"}, // store low 4 bytes of ... + + {name: "MOVBstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVB", aux: "SymValAndOff", typ: "Mem"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+1*arg1+ValAndOff(AuxInt).Off()+aux. arg2=mem + {name: "MOVWstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVW", aux: "SymValAndOff", typ: "Mem"}, // store low 2 bytes of ... arg1 ... + {name: "MOVWstoreconstidx2", argLength: 3, reg: gpstoreconstidx, asm: "MOVW", aux: "SymValAndOff", typ: "Mem"}, // store low 2 bytes of ... 2*arg1 ... + {name: "MOVLstoreconstidx1", argLength: 3, reg: gpstoreconstidx, asm: "MOVL", aux: "SymValAndOff", typ: "Mem"}, // store low 4 bytes of ... arg1 ... + {name: "MOVLstoreconstidx4", argLength: 3, reg: gpstoreconstidx, asm: "MOVL", aux: "SymValAndOff", typ: "Mem"}, // store low 4 bytes of ... 4*arg1 ... + + // arg0 = (duff-adjusted) pointer to start of memory to zero + // arg1 = value to store (will always be zero) + // arg2 = mem + // auxint = offset into duffzero code to start executing + // returns mem + { + name: "DUFFZERO", + aux: "Int64", + argLength: 3, + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("X0")}, + clobbers: buildReg("DI FLAGS"), + }, + }, + {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Int128", aux: "Int128", rematerializeable: true}, + + // arg0 = address of memory to zero + // arg1 = # of 4-byte words to zero + // arg2 = value to store (will always be zero) + // arg3 = mem + // returns mem + { + name: "REPSTOSL", + argLength: 4, + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("CX"), buildReg("AX")}, + clobbers: buildReg("DI CX"), + }, + }, + + {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{[]regMask{gpsp, buildReg("DX"), 0}, callerSave, nil}, 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 + {name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64"}, // call newproc. arg0=mem, auxint=argsize, returns mem + {name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64"}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem + + // arg0 = destination pointer + // arg1 = source pointer + // arg2 = mem + // auxint = offset from duffcopy symbol to call + // returns memory + { + name: "DUFFCOPY", + aux: "Int64", + argLength: 3, + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("SI")}, + clobbers: buildReg("DI SI X0 FLAGS"), // uses X0 as a temporary + }, + }, + + // arg0 = destination pointer + // arg1 = source pointer + // arg2 = # of 8-byte words to copy + // arg3 = mem + // returns memory + { + name: "REPMOVSL", + argLength: 4, + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")}, + clobbers: buildReg("DI SI CX"), + }, + }, + + // (InvertFlags (CMPL a b)) == (CMPL b a) + // So if we want (SETL (CMPL a b)) but we can't do that because a is a constant, + // then we do (SETL (InvertFlags (CMPL b a))) instead. + // Rewrites will convert this to (SETG (CMPL b a)). + // InvertFlags is a pseudo-op which can't appear in assembly output. + {name: "InvertFlags", argLength: 1}, // reverse direction of arg0 + + // Pseudo-ops + {name: "LoweredGetG", argLength: 1, reg: gp01}, // arg0=mem + // Scheduler ensures LoweredGetClosurePtr occurs only in entry block, + // and sorts it to the very beginning of the block to prevent other + // use of DX (the closure pointer) + {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}}, + //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil. + {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}, clobbers: flags}}, + + // MOVLconvert converts between pointers and integers. + // We have a special op for this so as to not confuse GC + // (particularly stack maps). It takes a memory arg so it + // gets correctly ordered with respect to GC safepoints. + // arg0=ptr/int arg1=mem, output=int/ptr + {name: "MOVLconvert", argLength: 2, reg: gp11nf, asm: "MOVL"}, + + // Constant flag values. For any comparison, there are 5 possible + // outcomes: the three from the signed total order (<,==,>) and the + // three from the unsigned total order. The == cases overlap. + // Note: there's a sixth "unordered" outcome for floating-point + // comparisons, but we don't use such a beast yet. + // These ops are for temporary use by rewrite rules. They + // cannot appear in the generated assembly. + {name: "FlagEQ"}, // equal + {name: "FlagLT_ULT"}, // signed < and unsigned < + {name: "FlagLT_UGT"}, // signed < and unsigned > + {name: "FlagGT_UGT"}, // signed > and unsigned < + {name: "FlagGT_ULT"}, // signed > and unsigned > + } + + var _386blocks = []blockData{ + {name: "EQ"}, + {name: "NE"}, + {name: "LT"}, + {name: "LE"}, + {name: "GT"}, + {name: "GE"}, + {name: "ULT"}, + {name: "ULE"}, + {name: "UGT"}, + {name: "UGE"}, + {name: "EQF"}, + {name: "NEF"}, + {name: "ORD"}, // FP, ordered comparison (parity zero) + {name: "NAN"}, // FP, unordered comparison (parity one) + } + + archs = append(archs, arch{ + name: "386", + pkg: "cmd/internal/obj/x86", + genfile: "../../x86/ssa.go", + ops: _386ops, + blocks: _386blocks, + regnames: regNames386, + gpregmask: gp, + fpregmask: fp, + flagmask: flags, + framepointerreg: int8(num["BP"]), + }) +} diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 99982c0aab..7ea67a99b9 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -13,6 +13,21 @@ import ( const ( BlockInvalid BlockKind = iota + Block386EQ + Block386NE + Block386LT + Block386LE + Block386GT + Block386GE + Block386ULT + Block386ULE + Block386UGT + Block386UGE + Block386EQF + Block386NEF + Block386ORD + Block386NAN + BlockAMD64EQ BlockAMD64NE BlockAMD64LT @@ -64,6 +79,21 @@ const ( var blockString = [...]string{ BlockInvalid: "BlockInvalid", + Block386EQ: "EQ", + Block386NE: "NE", + Block386LT: "LT", + Block386LE: "LE", + Block386GT: "GT", + Block386GE: "GE", + Block386ULT: "ULT", + Block386ULE: "ULE", + Block386UGT: "UGT", + Block386UGE: "UGE", + Block386EQF: "EQF", + Block386NEF: "NEF", + Block386ORD: "ORD", + Block386NAN: "NAN", + BlockAMD64EQ: "EQ", BlockAMD64NE: "NE", BlockAMD64LT: "LT", @@ -117,6 +147,176 @@ func (k BlockKind) String() string { return blockString[k] } const ( OpInvalid Op = iota + Op386ADDSS + Op386ADDSD + Op386SUBSS + Op386SUBSD + Op386MULSS + Op386MULSD + Op386DIVSS + Op386DIVSD + Op386MOVSSload + Op386MOVSDload + Op386MOVSSconst + Op386MOVSDconst + Op386MOVSSloadidx1 + Op386MOVSSloadidx4 + Op386MOVSDloadidx1 + Op386MOVSDloadidx8 + Op386MOVSSstore + Op386MOVSDstore + Op386MOVSSstoreidx1 + Op386MOVSSstoreidx4 + Op386MOVSDstoreidx1 + Op386MOVSDstoreidx8 + Op386ADDL + Op386ADDLconst + Op386SUBL + Op386SUBLconst + Op386MULL + Op386MULLconst + Op386HMULL + Op386HMULW + Op386HMULB + Op386HMULLU + Op386HMULWU + Op386HMULBU + Op386DIVL + Op386DIVW + Op386DIVLU + Op386DIVWU + Op386MODL + Op386MODW + Op386MODLU + Op386MODWU + Op386ANDL + Op386ANDLconst + Op386ORL + Op386ORLconst + Op386XORL + Op386XORLconst + Op386CMPL + Op386CMPW + Op386CMPB + Op386CMPLconst + Op386CMPWconst + Op386CMPBconst + Op386UCOMISS + Op386UCOMISD + Op386TESTL + Op386TESTW + Op386TESTB + Op386TESTLconst + Op386TESTWconst + Op386TESTBconst + Op386SHLL + Op386SHLLconst + Op386SHRL + Op386SHRW + Op386SHRB + Op386SHRLconst + Op386SHRWconst + Op386SHRBconst + Op386SARL + Op386SARW + Op386SARB + Op386SARLconst + Op386SARWconst + Op386SARBconst + Op386ROLLconst + Op386ROLWconst + Op386ROLBconst + Op386NEGL + Op386NOTL + Op386BSFL + Op386BSFW + Op386BSRL + Op386BSRW + Op386BSWAPL + Op386SQRTSD + Op386SBBLcarrymask + Op386SETEQ + Op386SETNE + Op386SETL + Op386SETLE + Op386SETG + Op386SETGE + Op386SETB + Op386SETBE + Op386SETA + Op386SETAE + Op386SETEQF + Op386SETNEF + Op386SETORD + Op386SETNAN + Op386SETGF + Op386SETGEF + Op386MOVBLSX + Op386MOVBLZX + Op386MOVWLSX + Op386MOVWLZX + Op386MOVLconst + Op386CVTTSD2SL + Op386CVTTSS2SL + Op386CVTSL2SS + Op386CVTSL2SD + Op386CVTSD2SS + Op386CVTSS2SD + Op386PXOR + Op386LEAL + Op386LEAL1 + Op386LEAL2 + Op386LEAL4 + Op386LEAL8 + Op386MOVBload + Op386MOVBLSXload + Op386MOVWload + Op386MOVWLSXload + Op386MOVLload + Op386MOVBstore + Op386MOVWstore + Op386MOVLstore + Op386MOVOload + Op386MOVOstore + Op386MOVBloadidx1 + Op386MOVWloadidx1 + Op386MOVWloadidx2 + Op386MOVLloadidx1 + Op386MOVLloadidx4 + Op386MOVBstoreidx1 + Op386MOVWstoreidx1 + Op386MOVWstoreidx2 + Op386MOVLstoreidx1 + Op386MOVLstoreidx4 + Op386MOVBstoreconst + Op386MOVWstoreconst + Op386MOVLstoreconst + Op386MOVBstoreconstidx1 + Op386MOVWstoreconstidx1 + Op386MOVWstoreconstidx2 + Op386MOVLstoreconstidx1 + Op386MOVLstoreconstidx4 + Op386DUFFZERO + Op386MOVOconst + Op386REPSTOSL + Op386CALLstatic + Op386CALLclosure + Op386CALLdefer + Op386CALLgo + Op386CALLinter + Op386DUFFCOPY + Op386REPMOVSL + Op386InvertFlags + Op386LoweredGetG + Op386LoweredGetClosurePtr + Op386LoweredNilCheck + Op386MOVLconvert + Op386FlagEQ + Op386FlagLT_ULT + Op386FlagLT_UGT + Op386FlagGT_UGT + Op386FlagGT_ULT + OpAMD64ADDSS OpAMD64ADDSD OpAMD64SUBSS @@ -844,6 +1044,2303 @@ const ( var opcodeTable = [...]opInfo{ {name: "OpInvalid"}, + { + name: "ADDSS", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AADDSS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "ADDSD", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AADDSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "SUBSS", + argLen: 2, + resultInArg0: true, + asm: x86.ASUBSS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 32512}, // X0 X1 X2 X3 X4 X5 X6 + {1, 32512}, // X0 X1 X2 X3 X4 X5 X6 + }, + clobbers: 32768, // X7 + outputs: []regMask{ + 32512, // X0 X1 X2 X3 X4 X5 X6 + }, + }, + }, + { + name: "SUBSD", + argLen: 2, + resultInArg0: true, + asm: x86.ASUBSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 32512}, // X0 X1 X2 X3 X4 X5 X6 + {1, 32512}, // X0 X1 X2 X3 X4 X5 X6 + }, + clobbers: 32768, // X7 + outputs: []regMask{ + 32512, // X0 X1 X2 X3 X4 X5 X6 + }, + }, + }, + { + name: "MULSS", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AMULSS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MULSD", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AMULSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "DIVSS", + argLen: 2, + resultInArg0: true, + asm: x86.ADIVSS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 32512}, // X0 X1 X2 X3 X4 X5 X6 + {1, 32512}, // X0 X1 X2 X3 X4 X5 X6 + }, + clobbers: 32768, // X7 + outputs: []regMask{ + 32512, // X0 X1 X2 X3 X4 X5 X6 + }, + }, + }, + { + name: "DIVSD", + argLen: 2, + resultInArg0: true, + asm: x86.ADIVSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 32512}, // X0 X1 X2 X3 X4 X5 X6 + {1, 32512}, // X0 X1 X2 X3 X4 X5 X6 + }, + clobbers: 32768, // X7 + outputs: []regMask{ + 32512, // X0 X1 X2 X3 X4 X5 X6 + }, + }, + }, + { + name: "MOVSSload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSDload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSSconst", + auxType: auxFloat32, + argLen: 0, + rematerializeable: true, + asm: x86.AMOVSS, + reg: regInfo{ + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSDconst", + auxType: auxFloat64, + argLen: 0, + rematerializeable: true, + asm: x86.AMOVSD, + reg: regInfo{ + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSSloadidx1", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSSloadidx4", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSDloadidx1", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSDloadidx8", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVSSstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVSDstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVSSstoreidx1", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVSSstoreidx4", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVSDstoreidx1", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVSDstoreidx8", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "ADDL", + argLen: 2, + commutative: true, + asm: x86.AADDL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 239}, // AX CX DX BX BP SI DI + {0, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ADDLconst", + auxType: auxInt32, + argLen: 1, + asm: x86.AADDL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SUBL", + argLen: 2, + resultInArg0: true, + asm: x86.ASUBL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + {1, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SUBLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.ASUBL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MULL", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AIMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + {1, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MULLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.AIMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "HMULL", + argLen: 2, + asm: x86.AIMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "HMULW", + argLen: 2, + asm: x86.AIMULW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "HMULB", + argLen: 2, + asm: x86.AIMULB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "HMULLU", + argLen: 2, + asm: x86.AMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "HMULWU", + argLen: 2, + asm: x86.AMULW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "HMULBU", + argLen: 2, + asm: x86.AMULB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "DIVL", + argLen: 2, + asm: x86.AIDIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131076, // DX FLAGS + outputs: []regMask{ + 1, // AX + }, + }, + }, + { + name: "DIVW", + argLen: 2, + asm: x86.AIDIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131076, // DX FLAGS + outputs: []regMask{ + 1, // AX + }, + }, + }, + { + name: "DIVLU", + argLen: 2, + asm: x86.ADIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131076, // DX FLAGS + outputs: []regMask{ + 1, // AX + }, + }, + }, + { + name: "DIVWU", + argLen: 2, + asm: x86.ADIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131076, // DX FLAGS + outputs: []regMask{ + 1, // AX + }, + }, + }, + { + name: "MODL", + argLen: 2, + asm: x86.AIDIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "MODW", + argLen: 2, + asm: x86.AIDIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "MODLU", + argLen: 2, + asm: x86.ADIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "MODWU", + argLen: 2, + asm: x86.ADIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // AX + {1, 251}, // AX CX BX SP BP SI DI + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "ANDL", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AANDL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + {1, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ANDLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.AANDL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ORL", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AORL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + {1, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ORLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.AORL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "XORL", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.AXORL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + {1, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "XORLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.AXORL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "CMPL", + argLen: 2, + asm: x86.ACMPL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "CMPW", + argLen: 2, + asm: x86.ACMPW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "CMPB", + argLen: 2, + asm: x86.ACMPB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "CMPLconst", + auxType: auxInt32, + argLen: 1, + asm: x86.ACMPL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "CMPWconst", + auxType: auxInt16, + argLen: 1, + asm: x86.ACMPW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "CMPBconst", + auxType: auxInt8, + argLen: 1, + asm: x86.ACMPB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "UCOMISS", + argLen: 2, + asm: x86.AUCOMISS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "UCOMISD", + argLen: 2, + asm: x86.AUCOMISD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTL", + argLen: 2, + asm: x86.ATESTL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTW", + argLen: 2, + asm: x86.ATESTW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTB", + argLen: 2, + asm: x86.ATESTB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + {1, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTLconst", + auxType: auxInt32, + argLen: 1, + asm: x86.ATESTL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTWconst", + auxType: auxInt16, + argLen: 1, + asm: x86.ATESTW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "TESTBconst", + auxType: auxInt8, + argLen: 1, + asm: x86.ATESTB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 131072, // FLAGS + }, + }, + }, + { + name: "SHLL", + argLen: 2, + resultInArg0: true, + asm: x86.ASHLL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHLLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.ASHLL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRL", + argLen: 2, + resultInArg0: true, + asm: x86.ASHRL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRW", + argLen: 2, + resultInArg0: true, + asm: x86.ASHRW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRB", + argLen: 2, + resultInArg0: true, + asm: x86.ASHRB, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.ASHRL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRWconst", + auxType: auxInt16, + argLen: 1, + resultInArg0: true, + asm: x86.ASHRW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SHRBconst", + auxType: auxInt8, + argLen: 1, + resultInArg0: true, + asm: x86.ASHRB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARL", + argLen: 2, + resultInArg0: true, + asm: x86.ASARL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARW", + argLen: 2, + resultInArg0: true, + asm: x86.ASARW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARB", + argLen: 2, + resultInArg0: true, + asm: x86.ASARB, + reg: regInfo{ + inputs: []inputInfo{ + {1, 2}, // CX + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.ASARL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARWconst", + auxType: auxInt16, + argLen: 1, + resultInArg0: true, + asm: x86.ASARW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SARBconst", + auxType: auxInt8, + argLen: 1, + resultInArg0: true, + asm: x86.ASARB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ROLLconst", + auxType: auxInt32, + argLen: 1, + resultInArg0: true, + asm: x86.AROLL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ROLWconst", + auxType: auxInt16, + argLen: 1, + resultInArg0: true, + asm: x86.AROLW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "ROLBconst", + auxType: auxInt8, + argLen: 1, + resultInArg0: true, + asm: x86.AROLB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "NEGL", + argLen: 1, + resultInArg0: true, + asm: x86.ANEGL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "NOTL", + argLen: 1, + resultInArg0: true, + asm: x86.ANOTL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "BSFL", + argLen: 1, + asm: x86.ABSFL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "BSFW", + argLen: 1, + asm: x86.ABSFW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "BSRL", + argLen: 1, + asm: x86.ABSRL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "BSRW", + argLen: 1, + asm: x86.ABSRW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "BSWAPL", + argLen: 1, + resultInArg0: true, + asm: x86.ABSWAPL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 131072, // FLAGS + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SQRTSD", + argLen: 1, + asm: x86.ASQRTSD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "SBBLcarrymask", + argLen: 1, + asm: x86.ASBBL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETEQ", + argLen: 1, + asm: x86.ASETEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETNE", + argLen: 1, + asm: x86.ASETNE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETL", + argLen: 1, + asm: x86.ASETLT, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETLE", + argLen: 1, + asm: x86.ASETLE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETG", + argLen: 1, + asm: x86.ASETGT, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETGE", + argLen: 1, + asm: x86.ASETGE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETB", + argLen: 1, + asm: x86.ASETCS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETBE", + argLen: 1, + asm: x86.ASETLS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETA", + argLen: 1, + asm: x86.ASETHI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETAE", + argLen: 1, + asm: x86.ASETCC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETEQF", + argLen: 1, + asm: x86.ASETEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 238, // CX DX BX BP SI DI + }, + }, + }, + { + name: "SETNEF", + argLen: 1, + asm: x86.ASETNE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + clobbers: 131073, // AX FLAGS + outputs: []regMask{ + 238, // CX DX BX BP SI DI + }, + }, + }, + { + name: "SETORD", + argLen: 1, + asm: x86.ASETPC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETNAN", + argLen: 1, + asm: x86.ASETPS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETGF", + argLen: 1, + asm: x86.ASETHI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "SETGEF", + argLen: 1, + asm: x86.ASETCC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 131072}, // FLAGS + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBLSX", + argLen: 1, + asm: x86.AMOVBLSX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBLZX", + argLen: 1, + asm: x86.AMOVBLZX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWLSX", + argLen: 1, + asm: x86.AMOVWLSX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWLZX", + argLen: 1, + asm: x86.AMOVWLZX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVLconst", + auxType: auxInt32, + argLen: 0, + rematerializeable: true, + asm: x86.AMOVL, + reg: regInfo{ + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "CVTTSD2SL", + argLen: 1, + asm: x86.ACVTTSD2SL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "CVTTSS2SL", + argLen: 1, + asm: x86.ACVTTSS2SL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "CVTSL2SS", + argLen: 1, + asm: x86.ACVTSL2SS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "CVTSL2SD", + argLen: 1, + asm: x86.ACVTSL2SD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "CVTSD2SS", + argLen: 1, + asm: x86.ACVTSD2SS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "CVTSS2SD", + argLen: 1, + asm: x86.ACVTSS2SD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "PXOR", + argLen: 2, + commutative: true, + resultInArg0: true, + asm: x86.APXOR, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "LEAL", + auxType: auxSymOff, + argLen: 1, + rematerializeable: true, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "LEAL1", + auxType: auxSymOff, + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "LEAL2", + auxType: auxSymOff, + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "LEAL4", + auxType: auxSymOff, + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "LEAL8", + auxType: auxSymOff, + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVBLZX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBLSXload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVBLSX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVWLZX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWLSXload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVWLSX, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVLload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVB, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVOload", + auxType: auxSymOff, + argLen: 2, + asm: x86.AMOVUPS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "MOVOstore", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVUPS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7 + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVBloadidx1", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVBLZX, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWloadidx1", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVWLZX, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVWloadidx2", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVWLZX, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVLloadidx1", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVLloadidx4", + auxType: auxSymOff, + argLen: 3, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "MOVBstoreidx1", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVB, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstoreidx1", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstoreidx2", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstoreidx1", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstoreidx4", + auxType: auxSymOff, + argLen: 4, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {2, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVBstoreconst", + auxType: auxSymValAndOff, + argLen: 2, + asm: x86.AMOVB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstoreconst", + auxType: auxSymValAndOff, + argLen: 2, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstoreconst", + auxType: auxSymValAndOff, + argLen: 2, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVBstoreconstidx1", + auxType: auxSymValAndOff, + argLen: 3, + asm: x86.AMOVB, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstoreconstidx1", + auxType: auxSymValAndOff, + argLen: 3, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVWstoreconstidx2", + auxType: auxSymValAndOff, + argLen: 3, + asm: x86.AMOVW, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstoreconstidx1", + auxType: auxSymValAndOff, + argLen: 3, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "MOVLstoreconstidx4", + auxType: auxSymValAndOff, + argLen: 3, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {1, 255}, // AX CX DX BX SP BP SI DI + {0, 65791}, // AX CX DX BX SP BP SI DI SB + }, + }, + }, + { + name: "DUFFZERO", + auxType: auxInt64, + argLen: 3, + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // DI + {1, 256}, // X0 + }, + clobbers: 131200, // DI FLAGS + }, + }, + { + name: "MOVOconst", + auxType: auxInt128, + argLen: 0, + rematerializeable: true, + reg: regInfo{ + outputs: []regMask{ + 65280, // X0 X1 X2 X3 X4 X5 X6 X7 + }, + }, + }, + { + name: "REPSTOSL", + argLen: 4, + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // DI + {1, 2}, // CX + {2, 1}, // AX + }, + clobbers: 130, // CX DI + }, + }, + { + name: "CALLstatic", + auxType: auxSymOff, + argLen: 1, + reg: regInfo{ + clobbers: 196591, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 FLAGS + }, + }, + { + name: "CALLclosure", + auxType: auxInt64, + argLen: 3, + reg: regInfo{ + inputs: []inputInfo{ + {1, 4}, // DX + {0, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 196591, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 FLAGS + }, + }, + { + name: "CALLdefer", + auxType: auxInt64, + argLen: 1, + reg: regInfo{ + clobbers: 196591, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 FLAGS + }, + }, + { + name: "CALLgo", + auxType: auxInt64, + argLen: 1, + reg: regInfo{ + clobbers: 196591, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 FLAGS + }, + }, + { + name: "CALLinter", + auxType: auxInt64, + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {0, 239}, // AX CX DX BX BP SI DI + }, + clobbers: 196591, // AX CX DX BX BP SI DI X0 X1 X2 X3 X4 X5 X6 X7 FLAGS + }, + }, + { + name: "DUFFCOPY", + auxType: auxInt64, + argLen: 3, + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // DI + {1, 64}, // SI + }, + clobbers: 131520, // SI DI X0 FLAGS + }, + }, + { + name: "REPMOVSL", + argLen: 4, + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // DI + {1, 64}, // SI + {2, 2}, // CX + }, + clobbers: 194, // CX SI DI + }, + }, + { + name: "InvertFlags", + argLen: 1, + reg: regInfo{}, + }, + { + name: "LoweredGetG", + argLen: 1, + reg: regInfo{ + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "LoweredGetClosurePtr", + argLen: 0, + reg: regInfo{ + outputs: []regMask{ + 4, // DX + }, + }, + }, + { + name: "LoweredNilCheck", + argLen: 2, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + clobbers: 131072, // FLAGS + }, + }, + { + name: "MOVLconvert", + argLen: 2, + asm: x86.AMOVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 255}, // AX CX DX BX SP BP SI DI + }, + outputs: []regMask{ + 239, // AX CX DX BX BP SI DI + }, + }, + }, + { + name: "FlagEQ", + argLen: 0, + reg: regInfo{}, + }, + { + name: "FlagLT_ULT", + argLen: 0, + reg: regInfo{}, + }, + { + name: "FlagLT_UGT", + argLen: 0, + reg: regInfo{}, + }, + { + name: "FlagGT_UGT", + argLen: 0, + reg: regInfo{}, + }, + { + name: "FlagGT_ULT", + argLen: 0, + reg: regInfo{}, + }, + { name: "ADDSS", argLen: 2, @@ -8053,6 +10550,30 @@ var opcodeTable = [...]opInfo{ func (o Op) Asm() obj.As { return opcodeTable[o].asm } func (o Op) String() string { return opcodeTable[o].name } +var registers386 = [...]Register{ + {0, "AX"}, + {1, "CX"}, + {2, "DX"}, + {3, "BX"}, + {4, "SP"}, + {5, "BP"}, + {6, "SI"}, + {7, "DI"}, + {8, "X0"}, + {9, "X1"}, + {10, "X2"}, + {11, "X3"}, + {12, "X4"}, + {13, "X5"}, + {14, "X6"}, + {15, "X7"}, + {16, "SB"}, + {17, "FLAGS"}, +} +var gpRegMask386 = regMask(239) +var fpRegMask386 = regMask(65280) +var flagRegMask386 = regMask(131072) +var framepointerReg386 = int8(5) var registersAMD64 = [...]Register{ {0, "AX"}, {1, "CX"}, diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go new file mode 100644 index 0000000000..7e7e088c0b --- /dev/null +++ b/src/cmd/compile/internal/ssa/rewrite386.go @@ -0,0 +1,14189 @@ +// autogenerated from gen/386.rules: do not edit! +// generated with: cd gen; go run *.go + +package ssa + +import "math" + +var _ = math.MinInt8 // in case not otherwise used +func rewriteValue386(v *Value, config *Config) bool { + switch v.Op { + case Op386ADDL: + return rewriteValue386_Op386ADDL(v, config) + case Op386ADDLconst: + return rewriteValue386_Op386ADDLconst(v, config) + case Op386ANDL: + return rewriteValue386_Op386ANDL(v, config) + case Op386ANDLconst: + return rewriteValue386_Op386ANDLconst(v, config) + case OpAdd16: + return rewriteValue386_OpAdd16(v, config) + case OpAdd32: + return rewriteValue386_OpAdd32(v, config) + case OpAdd32F: + return rewriteValue386_OpAdd32F(v, config) + case OpAdd64F: + return rewriteValue386_OpAdd64F(v, config) + case OpAdd8: + return rewriteValue386_OpAdd8(v, config) + case OpAddPtr: + return rewriteValue386_OpAddPtr(v, config) + case OpAddr: + return rewriteValue386_OpAddr(v, config) + case OpAnd16: + return rewriteValue386_OpAnd16(v, config) + case OpAnd32: + return rewriteValue386_OpAnd32(v, config) + case OpAnd8: + return rewriteValue386_OpAnd8(v, config) + case OpAndB: + return rewriteValue386_OpAndB(v, config) + case OpBswap32: + return rewriteValue386_OpBswap32(v, config) + case Op386CMPB: + return rewriteValue386_Op386CMPB(v, config) + case Op386CMPBconst: + return rewriteValue386_Op386CMPBconst(v, config) + case Op386CMPL: + return rewriteValue386_Op386CMPL(v, config) + case Op386CMPLconst: + return rewriteValue386_Op386CMPLconst(v, config) + case Op386CMPW: + return rewriteValue386_Op386CMPW(v, config) + case Op386CMPWconst: + return rewriteValue386_Op386CMPWconst(v, config) + case OpClosureCall: + return rewriteValue386_OpClosureCall(v, config) + case OpCom16: + return rewriteValue386_OpCom16(v, config) + case OpCom32: + return rewriteValue386_OpCom32(v, config) + case OpCom8: + return rewriteValue386_OpCom8(v, config) + case OpConst16: + return rewriteValue386_OpConst16(v, config) + case OpConst32: + return rewriteValue386_OpConst32(v, config) + case OpConst32F: + return rewriteValue386_OpConst32F(v, config) + case OpConst64F: + return rewriteValue386_OpConst64F(v, config) + case OpConst8: + return rewriteValue386_OpConst8(v, config) + case OpConstBool: + return rewriteValue386_OpConstBool(v, config) + case OpConstNil: + return rewriteValue386_OpConstNil(v, config) + case OpConvert: + return rewriteValue386_OpConvert(v, config) + case OpCvt32Fto32: + return rewriteValue386_OpCvt32Fto32(v, config) + case OpCvt32Fto64F: + return rewriteValue386_OpCvt32Fto64F(v, config) + case OpCvt32to32F: + return rewriteValue386_OpCvt32to32F(v, config) + case OpCvt32to64F: + return rewriteValue386_OpCvt32to64F(v, config) + case OpCvt64Fto32: + return rewriteValue386_OpCvt64Fto32(v, config) + case OpCvt64Fto32F: + return rewriteValue386_OpCvt64Fto32F(v, config) + case OpDeferCall: + return rewriteValue386_OpDeferCall(v, config) + case OpDiv16: + return rewriteValue386_OpDiv16(v, config) + case OpDiv16u: + return rewriteValue386_OpDiv16u(v, config) + case OpDiv32: + return rewriteValue386_OpDiv32(v, config) + case OpDiv32F: + return rewriteValue386_OpDiv32F(v, config) + case OpDiv32u: + return rewriteValue386_OpDiv32u(v, config) + case OpDiv64F: + return rewriteValue386_OpDiv64F(v, config) + case OpDiv8: + return rewriteValue386_OpDiv8(v, config) + case OpDiv8u: + return rewriteValue386_OpDiv8u(v, config) + case OpEq16: + return rewriteValue386_OpEq16(v, config) + case OpEq32: + return rewriteValue386_OpEq32(v, config) + case OpEq32F: + return rewriteValue386_OpEq32F(v, config) + case OpEq64F: + return rewriteValue386_OpEq64F(v, config) + case OpEq8: + return rewriteValue386_OpEq8(v, config) + case OpEqB: + return rewriteValue386_OpEqB(v, config) + case OpEqPtr: + return rewriteValue386_OpEqPtr(v, config) + case OpGeq16: + return rewriteValue386_OpGeq16(v, config) + case OpGeq16U: + return rewriteValue386_OpGeq16U(v, config) + case OpGeq32: + return rewriteValue386_OpGeq32(v, config) + case OpGeq32F: + return rewriteValue386_OpGeq32F(v, config) + case OpGeq32U: + return rewriteValue386_OpGeq32U(v, config) + case OpGeq64F: + return rewriteValue386_OpGeq64F(v, config) + case OpGeq8: + return rewriteValue386_OpGeq8(v, config) + case OpGeq8U: + return rewriteValue386_OpGeq8U(v, config) + case OpGetClosurePtr: + return rewriteValue386_OpGetClosurePtr(v, config) + case OpGetG: + return rewriteValue386_OpGetG(v, config) + case OpGoCall: + return rewriteValue386_OpGoCall(v, config) + case OpGreater16: + return rewriteValue386_OpGreater16(v, config) + case OpGreater16U: + return rewriteValue386_OpGreater16U(v, config) + case OpGreater32: + return rewriteValue386_OpGreater32(v, config) + case OpGreater32F: + return rewriteValue386_OpGreater32F(v, config) + case OpGreater32U: + return rewriteValue386_OpGreater32U(v, config) + case OpGreater64F: + return rewriteValue386_OpGreater64F(v, config) + case OpGreater8: + return rewriteValue386_OpGreater8(v, config) + case OpGreater8U: + return rewriteValue386_OpGreater8U(v, config) + case OpHmul16: + return rewriteValue386_OpHmul16(v, config) + case OpHmul16u: + return rewriteValue386_OpHmul16u(v, config) + case OpHmul32: + return rewriteValue386_OpHmul32(v, config) + case OpHmul32u: + return rewriteValue386_OpHmul32u(v, config) + case OpHmul8: + return rewriteValue386_OpHmul8(v, config) + case OpHmul8u: + return rewriteValue386_OpHmul8u(v, config) + case OpInterCall: + return rewriteValue386_OpInterCall(v, config) + case OpIsInBounds: + return rewriteValue386_OpIsInBounds(v, config) + case OpIsNonNil: + return rewriteValue386_OpIsNonNil(v, config) + case OpIsSliceInBounds: + return rewriteValue386_OpIsSliceInBounds(v, config) + case Op386LEAL: + return rewriteValue386_Op386LEAL(v, config) + case Op386LEAL1: + return rewriteValue386_Op386LEAL1(v, config) + case Op386LEAL2: + return rewriteValue386_Op386LEAL2(v, config) + case Op386LEAL4: + return rewriteValue386_Op386LEAL4(v, config) + case Op386LEAL8: + return rewriteValue386_Op386LEAL8(v, config) + case OpLeq16: + return rewriteValue386_OpLeq16(v, config) + case OpLeq16U: + return rewriteValue386_OpLeq16U(v, config) + case OpLeq32: + return rewriteValue386_OpLeq32(v, config) + case OpLeq32F: + return rewriteValue386_OpLeq32F(v, config) + case OpLeq32U: + return rewriteValue386_OpLeq32U(v, config) + case OpLeq64F: + return rewriteValue386_OpLeq64F(v, config) + case OpLeq8: + return rewriteValue386_OpLeq8(v, config) + case OpLeq8U: + return rewriteValue386_OpLeq8U(v, config) + case OpLess16: + return rewriteValue386_OpLess16(v, config) + case OpLess16U: + return rewriteValue386_OpLess16U(v, config) + case OpLess32: + return rewriteValue386_OpLess32(v, config) + case OpLess32F: + return rewriteValue386_OpLess32F(v, config) + case OpLess32U: + return rewriteValue386_OpLess32U(v, config) + case OpLess64F: + return rewriteValue386_OpLess64F(v, config) + case OpLess8: + return rewriteValue386_OpLess8(v, config) + case OpLess8U: + return rewriteValue386_OpLess8U(v, config) + case OpLoad: + return rewriteValue386_OpLoad(v, config) + case OpLrot16: + return rewriteValue386_OpLrot16(v, config) + case OpLrot32: + return rewriteValue386_OpLrot32(v, config) + case OpLrot8: + return rewriteValue386_OpLrot8(v, config) + case OpLsh16x16: + return rewriteValue386_OpLsh16x16(v, config) + case OpLsh16x32: + return rewriteValue386_OpLsh16x32(v, config) + case OpLsh16x8: + return rewriteValue386_OpLsh16x8(v, config) + case OpLsh32x16: + return rewriteValue386_OpLsh32x16(v, config) + case OpLsh32x32: + return rewriteValue386_OpLsh32x32(v, config) + case OpLsh32x8: + return rewriteValue386_OpLsh32x8(v, config) + case OpLsh8x16: + return rewriteValue386_OpLsh8x16(v, config) + case OpLsh8x32: + return rewriteValue386_OpLsh8x32(v, config) + case OpLsh8x8: + return rewriteValue386_OpLsh8x8(v, config) + case Op386MOVBLSX: + return rewriteValue386_Op386MOVBLSX(v, config) + case Op386MOVBLSXload: + return rewriteValue386_Op386MOVBLSXload(v, config) + case Op386MOVBLZX: + return rewriteValue386_Op386MOVBLZX(v, config) + case Op386MOVBload: + return rewriteValue386_Op386MOVBload(v, config) + case Op386MOVBloadidx1: + return rewriteValue386_Op386MOVBloadidx1(v, config) + case Op386MOVBstore: + return rewriteValue386_Op386MOVBstore(v, config) + case Op386MOVBstoreconst: + return rewriteValue386_Op386MOVBstoreconst(v, config) + case Op386MOVBstoreconstidx1: + return rewriteValue386_Op386MOVBstoreconstidx1(v, config) + case Op386MOVBstoreidx1: + return rewriteValue386_Op386MOVBstoreidx1(v, config) + case Op386MOVLload: + return rewriteValue386_Op386MOVLload(v, config) + case Op386MOVLloadidx1: + return rewriteValue386_Op386MOVLloadidx1(v, config) + case Op386MOVLloadidx4: + return rewriteValue386_Op386MOVLloadidx4(v, config) + case Op386MOVLstore: + return rewriteValue386_Op386MOVLstore(v, config) + case Op386MOVLstoreconst: + return rewriteValue386_Op386MOVLstoreconst(v, config) + case Op386MOVLstoreconstidx1: + return rewriteValue386_Op386MOVLstoreconstidx1(v, config) + case Op386MOVLstoreconstidx4: + return rewriteValue386_Op386MOVLstoreconstidx4(v, config) + case Op386MOVLstoreidx1: + return rewriteValue386_Op386MOVLstoreidx1(v, config) + case Op386MOVLstoreidx4: + return rewriteValue386_Op386MOVLstoreidx4(v, config) + case Op386MOVOload: + return rewriteValue386_Op386MOVOload(v, config) + case Op386MOVOstore: + return rewriteValue386_Op386MOVOstore(v, config) + case Op386MOVSDload: + return rewriteValue386_Op386MOVSDload(v, config) + case Op386MOVSDloadidx1: + return rewriteValue386_Op386MOVSDloadidx1(v, config) + case Op386MOVSDloadidx8: + return rewriteValue386_Op386MOVSDloadidx8(v, config) + case Op386MOVSDstore: + return rewriteValue386_Op386MOVSDstore(v, config) + case Op386MOVSDstoreidx1: + return rewriteValue386_Op386MOVSDstoreidx1(v, config) + case Op386MOVSDstoreidx8: + return rewriteValue386_Op386MOVSDstoreidx8(v, config) + case Op386MOVSSload: + return rewriteValue386_Op386MOVSSload(v, config) + case Op386MOVSSloadidx1: + return rewriteValue386_Op386MOVSSloadidx1(v, config) + case Op386MOVSSloadidx4: + return rewriteValue386_Op386MOVSSloadidx4(v, config) + case Op386MOVSSstore: + return rewriteValue386_Op386MOVSSstore(v, config) + case Op386MOVSSstoreidx1: + return rewriteValue386_Op386MOVSSstoreidx1(v, config) + case Op386MOVSSstoreidx4: + return rewriteValue386_Op386MOVSSstoreidx4(v, config) + case Op386MOVWLSX: + return rewriteValue386_Op386MOVWLSX(v, config) + case Op386MOVWLSXload: + return rewriteValue386_Op386MOVWLSXload(v, config) + case Op386MOVWLZX: + return rewriteValue386_Op386MOVWLZX(v, config) + case Op386MOVWload: + return rewriteValue386_Op386MOVWload(v, config) + case Op386MOVWloadidx1: + return rewriteValue386_Op386MOVWloadidx1(v, config) + case Op386MOVWloadidx2: + return rewriteValue386_Op386MOVWloadidx2(v, config) + case Op386MOVWstore: + return rewriteValue386_Op386MOVWstore(v, config) + case Op386MOVWstoreconst: + return rewriteValue386_Op386MOVWstoreconst(v, config) + case Op386MOVWstoreconstidx1: + return rewriteValue386_Op386MOVWstoreconstidx1(v, config) + case Op386MOVWstoreconstidx2: + return rewriteValue386_Op386MOVWstoreconstidx2(v, config) + case Op386MOVWstoreidx1: + return rewriteValue386_Op386MOVWstoreidx1(v, config) + case Op386MOVWstoreidx2: + return rewriteValue386_Op386MOVWstoreidx2(v, config) + case Op386MULL: + return rewriteValue386_Op386MULL(v, config) + case Op386MULLconst: + return rewriteValue386_Op386MULLconst(v, config) + case OpMod16: + return rewriteValue386_OpMod16(v, config) + case OpMod16u: + return rewriteValue386_OpMod16u(v, config) + case OpMod32: + return rewriteValue386_OpMod32(v, config) + case OpMod32u: + return rewriteValue386_OpMod32u(v, config) + case OpMod8: + return rewriteValue386_OpMod8(v, config) + case OpMod8u: + return rewriteValue386_OpMod8u(v, config) + case OpMove: + return rewriteValue386_OpMove(v, config) + case OpMul16: + return rewriteValue386_OpMul16(v, config) + case OpMul32: + return rewriteValue386_OpMul32(v, config) + case OpMul32F: + return rewriteValue386_OpMul32F(v, config) + case OpMul64F: + return rewriteValue386_OpMul64F(v, config) + case OpMul8: + return rewriteValue386_OpMul8(v, config) + case Op386NEGL: + return rewriteValue386_Op386NEGL(v, config) + case Op386NOTL: + return rewriteValue386_Op386NOTL(v, config) + case OpNeg16: + return rewriteValue386_OpNeg16(v, config) + case OpNeg32: + return rewriteValue386_OpNeg32(v, config) + case OpNeg32F: + return rewriteValue386_OpNeg32F(v, config) + case OpNeg64F: + return rewriteValue386_OpNeg64F(v, config) + case OpNeg8: + return rewriteValue386_OpNeg8(v, config) + case OpNeq16: + return rewriteValue386_OpNeq16(v, config) + case OpNeq32: + return rewriteValue386_OpNeq32(v, config) + case OpNeq32F: + return rewriteValue386_OpNeq32F(v, config) + case OpNeq64F: + return rewriteValue386_OpNeq64F(v, config) + case OpNeq8: + return rewriteValue386_OpNeq8(v, config) + case OpNeqB: + return rewriteValue386_OpNeqB(v, config) + case OpNeqPtr: + return rewriteValue386_OpNeqPtr(v, config) + case OpNilCheck: + return rewriteValue386_OpNilCheck(v, config) + case OpNot: + return rewriteValue386_OpNot(v, config) + case Op386ORL: + return rewriteValue386_Op386ORL(v, config) + case Op386ORLconst: + return rewriteValue386_Op386ORLconst(v, config) + case OpOffPtr: + return rewriteValue386_OpOffPtr(v, config) + case OpOr16: + return rewriteValue386_OpOr16(v, config) + case OpOr32: + return rewriteValue386_OpOr32(v, config) + case OpOr8: + return rewriteValue386_OpOr8(v, config) + case OpOrB: + return rewriteValue386_OpOrB(v, config) + case Op386ROLBconst: + return rewriteValue386_Op386ROLBconst(v, config) + case Op386ROLLconst: + return rewriteValue386_Op386ROLLconst(v, config) + case Op386ROLWconst: + return rewriteValue386_Op386ROLWconst(v, config) + case OpRsh16Ux16: + return rewriteValue386_OpRsh16Ux16(v, config) + case OpRsh16Ux32: + return rewriteValue386_OpRsh16Ux32(v, config) + case OpRsh16Ux8: + return rewriteValue386_OpRsh16Ux8(v, config) + case OpRsh16x16: + return rewriteValue386_OpRsh16x16(v, config) + case OpRsh16x32: + return rewriteValue386_OpRsh16x32(v, config) + case OpRsh16x8: + return rewriteValue386_OpRsh16x8(v, config) + case OpRsh32Ux16: + return rewriteValue386_OpRsh32Ux16(v, config) + case OpRsh32Ux32: + return rewriteValue386_OpRsh32Ux32(v, config) + case OpRsh32Ux8: + return rewriteValue386_OpRsh32Ux8(v, config) + case OpRsh32x16: + return rewriteValue386_OpRsh32x16(v, config) + case OpRsh32x32: + return rewriteValue386_OpRsh32x32(v, config) + case OpRsh32x8: + return rewriteValue386_OpRsh32x8(v, config) + case OpRsh8Ux16: + return rewriteValue386_OpRsh8Ux16(v, config) + case OpRsh8Ux32: + return rewriteValue386_OpRsh8Ux32(v, config) + case OpRsh8Ux8: + return rewriteValue386_OpRsh8Ux8(v, config) + case OpRsh8x16: + return rewriteValue386_OpRsh8x16(v, config) + case OpRsh8x32: + return rewriteValue386_OpRsh8x32(v, config) + case OpRsh8x8: + return rewriteValue386_OpRsh8x8(v, config) + case Op386SARB: + return rewriteValue386_Op386SARB(v, config) + case Op386SARBconst: + return rewriteValue386_Op386SARBconst(v, config) + case Op386SARL: + return rewriteValue386_Op386SARL(v, config) + case Op386SARLconst: + return rewriteValue386_Op386SARLconst(v, config) + case Op386SARW: + return rewriteValue386_Op386SARW(v, config) + case Op386SARWconst: + return rewriteValue386_Op386SARWconst(v, config) + case Op386SBBLcarrymask: + return rewriteValue386_Op386SBBLcarrymask(v, config) + case Op386SETA: + return rewriteValue386_Op386SETA(v, config) + case Op386SETAE: + return rewriteValue386_Op386SETAE(v, config) + case Op386SETB: + return rewriteValue386_Op386SETB(v, config) + case Op386SETBE: + return rewriteValue386_Op386SETBE(v, config) + case Op386SETEQ: + return rewriteValue386_Op386SETEQ(v, config) + case Op386SETG: + return rewriteValue386_Op386SETG(v, config) + case Op386SETGE: + return rewriteValue386_Op386SETGE(v, config) + case Op386SETL: + return rewriteValue386_Op386SETL(v, config) + case Op386SETLE: + return rewriteValue386_Op386SETLE(v, config) + case Op386SETNE: + return rewriteValue386_Op386SETNE(v, config) + case Op386SHLL: + return rewriteValue386_Op386SHLL(v, config) + case Op386SHRB: + return rewriteValue386_Op386SHRB(v, config) + case Op386SHRL: + return rewriteValue386_Op386SHRL(v, config) + case Op386SHRW: + return rewriteValue386_Op386SHRW(v, config) + case Op386SUBL: + return rewriteValue386_Op386SUBL(v, config) + case Op386SUBLconst: + return rewriteValue386_Op386SUBLconst(v, config) + case OpSignExt16to32: + return rewriteValue386_OpSignExt16to32(v, config) + case OpSignExt8to16: + return rewriteValue386_OpSignExt8to16(v, config) + case OpSignExt8to32: + return rewriteValue386_OpSignExt8to32(v, config) + case OpSqrt: + return rewriteValue386_OpSqrt(v, config) + case OpStaticCall: + return rewriteValue386_OpStaticCall(v, config) + case OpStore: + return rewriteValue386_OpStore(v, config) + case OpSub16: + return rewriteValue386_OpSub16(v, config) + case OpSub32: + return rewriteValue386_OpSub32(v, config) + case OpSub32F: + return rewriteValue386_OpSub32F(v, config) + case OpSub64F: + return rewriteValue386_OpSub64F(v, config) + case OpSub8: + return rewriteValue386_OpSub8(v, config) + case OpSubPtr: + return rewriteValue386_OpSubPtr(v, config) + case OpTrunc16to8: + return rewriteValue386_OpTrunc16to8(v, config) + case OpTrunc32to16: + return rewriteValue386_OpTrunc32to16(v, config) + case OpTrunc32to8: + return rewriteValue386_OpTrunc32to8(v, config) + case Op386XORL: + return rewriteValue386_Op386XORL(v, config) + case Op386XORLconst: + return rewriteValue386_Op386XORLconst(v, config) + case OpXor16: + return rewriteValue386_OpXor16(v, config) + case OpXor32: + return rewriteValue386_OpXor32(v, config) + case OpXor8: + return rewriteValue386_OpXor8(v, config) + case OpZero: + return rewriteValue386_OpZero(v, config) + case OpZeroExt16to32: + return rewriteValue386_OpZeroExt16to32(v, config) + case OpZeroExt8to16: + return rewriteValue386_OpZeroExt8to16(v, config) + case OpZeroExt8to32: + return rewriteValue386_OpZeroExt8to32(v, config) + } + return false +} +func rewriteValue386_Op386ADDL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ADDL x (MOVLconst [c])) + // cond: + // result: (ADDLconst [c] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386ADDLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ADDL (MOVLconst [c]) x) + // cond: + // result: (ADDLconst [c] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386ADDLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ADDL x (SHLLconst [3] y)) + // cond: + // result: (LEAL8 x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 3 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL8) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (SHLLconst [2] y)) + // cond: + // result: (LEAL4 x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL4) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (SHLLconst [1] y)) + // cond: + // result: (LEAL2 x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (ADDL y y)) + // cond: + // result: (LEAL2 x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDL { + break + } + y := v_1.Args[0] + if y != v_1.Args[1] { + break + } + v.reset(Op386LEAL2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (ADDL x y)) + // cond: + // result: (LEAL2 y x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDL { + break + } + if x != v_1.Args[0] { + break + } + y := v_1.Args[1] + v.reset(Op386LEAL2) + v.AddArg(y) + v.AddArg(x) + return true + } + // match: (ADDL x (ADDL y x)) + // cond: + // result: (LEAL2 y x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDL { + break + } + y := v_1.Args[0] + if x != v_1.Args[1] { + break + } + v.reset(Op386LEAL2) + v.AddArg(y) + v.AddArg(x) + return true + } + // match: (ADDL (ADDLconst [c] x) y) + // cond: + // result: (LEAL1 [c] x y) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + y := v.Args[1] + v.reset(Op386LEAL1) + v.AuxInt = c + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (ADDLconst [c] y)) + // cond: + // result: (LEAL1 [c] x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + y := v_1.Args[0] + v.reset(Op386LEAL1) + v.AuxInt = c + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (LEAL [c] {s} y)) + // cond: x.Op != OpSB && y.Op != OpSB + // result: (LEAL1 [c] {s} x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386LEAL { + break + } + c := v_1.AuxInt + s := v_1.Aux + y := v_1.Args[0] + if !(x.Op != OpSB && y.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL (LEAL [c] {s} x) y) + // cond: x.Op != OpSB && y.Op != OpSB + // result: (LEAL1 [c] {s} x y) + for { + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + c := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + y := v.Args[1] + if !(x.Op != OpSB && y.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDL x (NEGL y)) + // cond: + // result: (SUBL x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386NEGL { + break + } + y := v_1.Args[0] + v.reset(Op386SUBL) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386ADDLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ADDLconst [c] (ADDL x y)) + // cond: + // result: (LEAL1 [c] x y) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + x := v_0.Args[0] + y := v_0.Args[1] + v.reset(Op386LEAL1) + v.AuxInt = c + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDLconst [c] (LEAL [d] {s} x)) + // cond: is32Bit(c+d) + // result: (LEAL [c+d] {s} x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + d := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + return true + } + // match: (ADDLconst [c] (LEAL1 [d] {s} x y)) + // cond: is32Bit(c+d) + // result: (LEAL1 [c+d] {s} x y) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + d := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDLconst [c] (LEAL2 [d] {s} x y)) + // cond: is32Bit(c+d) + // result: (LEAL2 [c+d] {s} x y) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386LEAL2 { + break + } + d := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL2) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDLconst [c] (LEAL4 [d] {s} x y)) + // cond: is32Bit(c+d) + // result: (LEAL4 [c+d] {s} x y) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + d := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDLconst [c] (LEAL8 [d] {s} x y)) + // cond: is32Bit(c+d) + // result: (LEAL8 [c+d] {s} x y) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386LEAL8 { + break + } + d := v_0.AuxInt + s := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (ADDLconst [c] x) + // cond: int32(c)==0 + // result: x + for { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == 0) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (ADDLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [int64(int32(c+d))]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = int64(int32(c + d)) + return true + } + // match: (ADDLconst [c] (ADDLconst [d] x)) + // cond: + // result: (ADDLconst [int64(int32(c+d))] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ADDLconst) + v.AuxInt = int64(int32(c + d)) + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386ANDL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ANDL x (MOVLconst [c])) + // cond: + // result: (ANDLconst [c] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386ANDLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ANDL (MOVLconst [c]) x) + // cond: + // result: (ANDLconst [c] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386ANDLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ANDL x x) + // cond: + // result: x + for { + x := v.Args[0] + if x != v.Args[1] { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386ANDLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ANDLconst [c] (ANDLconst [d] x)) + // cond: + // result: (ANDLconst [c & d] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ANDLconst) + v.AuxInt = c & d + v.AddArg(x) + return true + } + // match: (ANDLconst [c] _) + // cond: int32(c)==0 + // result: (MOVLconst [0]) + for { + c := v.AuxInt + if !(int32(c) == 0) { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (ANDLconst [c] x) + // cond: int32(c)==-1 + // result: x + for { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == -1) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (ANDLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c&d]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = c & d + return true + } + return false +} +func rewriteValue386_OpAdd16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Add16 x y) + // cond: + // result: (ADDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAdd32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Add32 x y) + // cond: + // result: (ADDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAdd32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Add32F x y) + // cond: + // result: (ADDSS x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDSS) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAdd64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Add64F x y) + // cond: + // result: (ADDSD x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDSD) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAdd8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Add8 x y) + // cond: + // result: (ADDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAddPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (AddPtr x y) + // cond: + // result: (ADDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ADDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAddr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Addr {sym} base) + // cond: + // result: (LEAL {sym} base) + for { + sym := v.Aux + base := v.Args[0] + v.reset(Op386LEAL) + v.Aux = sym + v.AddArg(base) + return true + } +} +func rewriteValue386_OpAnd16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (And16 x y) + // cond: + // result: (ANDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAnd32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (And32 x y) + // cond: + // result: (ANDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAnd8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (And8 x y) + // cond: + // result: (ANDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpAndB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (AndB x y) + // cond: + // result: (ANDL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpBswap32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Bswap32 x) + // cond: + // result: (BSWAPL x) + for { + x := v.Args[0] + v.reset(Op386BSWAPL) + v.AddArg(x) + return true + } +} +func rewriteValue386_Op386CMPB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (CMPB x (MOVLconst [c])) + // cond: + // result: (CMPBconst x [int64(int8(c))]) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386CMPBconst) + v.AddArg(x) + v.AuxInt = int64(int8(c)) + return true + } + // match: (CMPB (MOVLconst [c]) x) + // cond: + // result: (InvertFlags (CMPBconst x [int64(int8(c))])) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386InvertFlags) + v0 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v0.AddArg(x) + v0.AuxInt = int64(int8(c)) + v.AddArg(v0) + return true + } + return false +} +func rewriteValue386_Op386CMPBconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (CMPBconst (MOVLconst [x]) [y]) + // cond: int8(x)==int8(y) + // result: (FlagEQ) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int8(x) == int8(y)) { + break + } + v.reset(Op386FlagEQ) + return true + } + // match: (CMPBconst (MOVLconst [x]) [y]) + // cond: int8(x)uint8(y) + // result: (FlagLT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int8(x) < int8(y) && uint8(x) > uint8(y)) { + break + } + v.reset(Op386FlagLT_UGT) + return true + } + // match: (CMPBconst (MOVLconst [x]) [y]) + // cond: int8(x)>int8(y) && uint8(x) int8(y) && uint8(x) < uint8(y)) { + break + } + v.reset(Op386FlagGT_ULT) + return true + } + // match: (CMPBconst (MOVLconst [x]) [y]) + // cond: int8(x)>int8(y) && uint8(x)>uint8(y) + // result: (FlagGT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int8(x) > int8(y) && uint8(x) > uint8(y)) { + break + } + v.reset(Op386FlagGT_UGT) + return true + } + // match: (CMPBconst (ANDLconst _ [m]) [n]) + // cond: 0 <= int8(m) && int8(m) < int8(n) + // result: (FlagLT_ULT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + m := v_0.AuxInt + n := v.AuxInt + if !(0 <= int8(m) && int8(m) < int8(n)) { + break + } + v.reset(Op386FlagLT_ULT) + return true + } + // match: (CMPBconst (ANDL x y) [0]) + // cond: + // result: (TESTB x y) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDL { + break + } + x := v_0.Args[0] + y := v_0.Args[1] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTB) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (CMPBconst (ANDLconst [c] x) [0]) + // cond: + // result: (TESTBconst [int64(int8(c))] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTBconst) + v.AuxInt = int64(int8(c)) + v.AddArg(x) + return true + } + // match: (CMPBconst x [0]) + // cond: + // result: (TESTB x x) + for { + x := v.Args[0] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTB) + v.AddArg(x) + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386CMPL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (CMPL x (MOVLconst [c])) + // cond: + // result: (CMPLconst x [c]) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386CMPLconst) + v.AddArg(x) + v.AuxInt = c + return true + } + // match: (CMPL (MOVLconst [c]) x) + // cond: + // result: (InvertFlags (CMPLconst x [c])) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386InvertFlags) + v0 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + return false +} +func rewriteValue386_Op386CMPLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (CMPLconst (MOVLconst [x]) [y]) + // cond: int32(x)==int32(y) + // result: (FlagEQ) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int32(x) == int32(y)) { + break + } + v.reset(Op386FlagEQ) + return true + } + // match: (CMPLconst (MOVLconst [x]) [y]) + // cond: int32(x)uint32(y) + // result: (FlagLT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int32(x) < int32(y) && uint32(x) > uint32(y)) { + break + } + v.reset(Op386FlagLT_UGT) + return true + } + // match: (CMPLconst (MOVLconst [x]) [y]) + // cond: int32(x)>int32(y) && uint32(x) int32(y) && uint32(x) < uint32(y)) { + break + } + v.reset(Op386FlagGT_ULT) + return true + } + // match: (CMPLconst (MOVLconst [x]) [y]) + // cond: int32(x)>int32(y) && uint32(x)>uint32(y) + // result: (FlagGT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int32(x) > int32(y) && uint32(x) > uint32(y)) { + break + } + v.reset(Op386FlagGT_UGT) + return true + } + // match: (CMPLconst (SHRLconst _ [c]) [n]) + // cond: 0 <= n && 0 < c && c <= 32 && (1<uint16(y) + // result: (FlagLT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int16(x) < int16(y) && uint16(x) > uint16(y)) { + break + } + v.reset(Op386FlagLT_UGT) + return true + } + // match: (CMPWconst (MOVLconst [x]) [y]) + // cond: int16(x)>int16(y) && uint16(x) int16(y) && uint16(x) < uint16(y)) { + break + } + v.reset(Op386FlagGT_ULT) + return true + } + // match: (CMPWconst (MOVLconst [x]) [y]) + // cond: int16(x)>int16(y) && uint16(x)>uint16(y) + // result: (FlagGT_UGT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + x := v_0.AuxInt + y := v.AuxInt + if !(int16(x) > int16(y) && uint16(x) > uint16(y)) { + break + } + v.reset(Op386FlagGT_UGT) + return true + } + // match: (CMPWconst (ANDLconst _ [m]) [n]) + // cond: 0 <= int16(m) && int16(m) < int16(n) + // result: (FlagLT_ULT) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + m := v_0.AuxInt + n := v.AuxInt + if !(0 <= int16(m) && int16(m) < int16(n)) { + break + } + v.reset(Op386FlagLT_ULT) + return true + } + // match: (CMPWconst (ANDL x y) [0]) + // cond: + // result: (TESTW x y) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDL { + break + } + x := v_0.Args[0] + y := v_0.Args[1] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTW) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (CMPWconst (ANDLconst [c] x) [0]) + // cond: + // result: (TESTWconst [int64(int16(c))] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTWconst) + v.AuxInt = int64(int16(c)) + v.AddArg(x) + return true + } + // match: (CMPWconst x [0]) + // cond: + // result: (TESTW x x) + for { + x := v.Args[0] + if v.AuxInt != 0 { + break + } + v.reset(Op386TESTW) + v.AddArg(x) + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_OpClosureCall(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ClosureCall [argwid] entry closure mem) + // cond: + // result: (CALLclosure [argwid] entry closure mem) + for { + argwid := v.AuxInt + entry := v.Args[0] + closure := v.Args[1] + mem := v.Args[2] + v.reset(Op386CALLclosure) + v.AuxInt = argwid + v.AddArg(entry) + v.AddArg(closure) + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpCom16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Com16 x) + // cond: + // result: (NOTL x) + for { + x := v.Args[0] + v.reset(Op386NOTL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCom32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Com32 x) + // cond: + // result: (NOTL x) + for { + x := v.Args[0] + v.reset(Op386NOTL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCom8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Com8 x) + // cond: + // result: (NOTL x) + for { + x := v.Args[0] + v.reset(Op386NOTL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpConst16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Const16 [val]) + // cond: + // result: (MOVLconst [val]) + for { + val := v.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = val + return true + } +} +func rewriteValue386_OpConst32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Const32 [val]) + // cond: + // result: (MOVLconst [val]) + for { + val := v.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = val + return true + } +} +func rewriteValue386_OpConst32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Const32F [val]) + // cond: + // result: (MOVSSconst [val]) + for { + val := v.AuxInt + v.reset(Op386MOVSSconst) + v.AuxInt = val + return true + } +} +func rewriteValue386_OpConst64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Const64F [val]) + // cond: + // result: (MOVSDconst [val]) + for { + val := v.AuxInt + v.reset(Op386MOVSDconst) + v.AuxInt = val + return true + } +} +func rewriteValue386_OpConst8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Const8 [val]) + // cond: + // result: (MOVLconst [val]) + for { + val := v.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = val + return true + } +} +func rewriteValue386_OpConstBool(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ConstBool [b]) + // cond: + // result: (MOVLconst [b]) + for { + b := v.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = b + return true + } +} +func rewriteValue386_OpConstNil(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ConstNil) + // cond: + // result: (MOVLconst [0]) + for { + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } +} +func rewriteValue386_OpConvert(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Convert x mem) + // cond: + // result: (MOVLconvert x mem) + for { + t := v.Type + x := v.Args[0] + mem := v.Args[1] + v.reset(Op386MOVLconvert) + v.Type = t + v.AddArg(x) + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpCvt32Fto32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt32Fto32 x) + // cond: + // result: (CVTTSS2SL x) + for { + x := v.Args[0] + v.reset(Op386CVTTSS2SL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCvt32Fto64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt32Fto64F x) + // cond: + // result: (CVTSS2SD x) + for { + x := v.Args[0] + v.reset(Op386CVTSS2SD) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCvt32to32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt32to32F x) + // cond: + // result: (CVTSL2SS x) + for { + x := v.Args[0] + v.reset(Op386CVTSL2SS) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCvt32to64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt32to64F x) + // cond: + // result: (CVTSL2SD x) + for { + x := v.Args[0] + v.reset(Op386CVTSL2SD) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCvt64Fto32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt64Fto32 x) + // cond: + // result: (CVTTSD2SL x) + for { + x := v.Args[0] + v.reset(Op386CVTTSD2SL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpCvt64Fto32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Cvt64Fto32F x) + // cond: + // result: (CVTSD2SS x) + for { + x := v.Args[0] + v.reset(Op386CVTSD2SS) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpDeferCall(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (DeferCall [argwid] mem) + // cond: + // result: (CALLdefer [argwid] mem) + for { + argwid := v.AuxInt + mem := v.Args[0] + v.reset(Op386CALLdefer) + v.AuxInt = argwid + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpDiv16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div16 x y) + // cond: + // result: (DIVW x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVW) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv16u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div16u x y) + // cond: + // result: (DIVWU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVWU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div32 x y) + // cond: + // result: (DIVL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div32F x y) + // cond: + // result: (DIVSS x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVSS) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv32u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div32u x y) + // cond: + // result: (DIVLU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVLU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div64F x y) + // cond: + // result: (DIVSD x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVSD) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpDiv8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div8 x y) + // cond: + // result: (DIVW (SignExt8to16 x) (SignExt8to16 y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVW) + v0 := b.NewValue0(v.Line, OpSignExt8to16, config.fe.TypeInt16()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, config.fe.TypeInt16()) + v1.AddArg(y) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpDiv8u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Div8u x y) + // cond: + // result: (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386DIVWU) + v0 := b.NewValue0(v.Line, OpZeroExt8to16, config.fe.TypeUInt16()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, config.fe.TypeUInt16()) + v1.AddArg(y) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpEq16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Eq16 x y) + // cond: + // result: (SETEQ (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQ) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEq32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Eq32 x y) + // cond: + // result: (SETEQ (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQ) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEq32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Eq32F x y) + // cond: + // result: (SETEQF (UCOMISS x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEq64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Eq64F x y) + // cond: + // result: (SETEQF (UCOMISD x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEq8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Eq8 x y) + // cond: + // result: (SETEQ (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQ) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEqB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (EqB x y) + // cond: + // result: (SETEQ (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQ) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpEqPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (EqPtr x y) + // cond: + // result: (SETEQ (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETEQ) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq16 x y) + // cond: + // result: (SETGE (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGE) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq16U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq16U x y) + // cond: + // result: (SETAE (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETAE) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq32 x y) + // cond: + // result: (SETGE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq32F x y) + // cond: + // result: (SETGEF (UCOMISS x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGEF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq32U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq32U x y) + // cond: + // result: (SETAE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETAE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq64F x y) + // cond: + // result: (SETGEF (UCOMISD x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGEF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq8 x y) + // cond: + // result: (SETGE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGeq8U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Geq8U x y) + // cond: + // result: (SETAE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETAE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGetClosurePtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (GetClosurePtr) + // cond: + // result: (LoweredGetClosurePtr) + for { + v.reset(Op386LoweredGetClosurePtr) + return true + } +} +func rewriteValue386_OpGetG(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (GetG mem) + // cond: + // result: (LoweredGetG mem) + for { + mem := v.Args[0] + v.reset(Op386LoweredGetG) + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpGoCall(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (GoCall [argwid] mem) + // cond: + // result: (CALLgo [argwid] mem) + for { + argwid := v.AuxInt + mem := v.Args[0] + v.reset(Op386CALLgo) + v.AuxInt = argwid + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpGreater16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater16 x y) + // cond: + // result: (SETG (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETG) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater16U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater16U x y) + // cond: + // result: (SETA (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETA) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater32 x y) + // cond: + // result: (SETG (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETG) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater32F x y) + // cond: + // result: (SETGF (UCOMISS x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater32U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater32U x y) + // cond: + // result: (SETA (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETA) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater64F x y) + // cond: + // result: (SETGF (UCOMISD x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater8 x y) + // cond: + // result: (SETG (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETG) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpGreater8U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Greater8U x y) + // cond: + // result: (SETA (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETA) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpHmul16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul16 x y) + // cond: + // result: (HMULW x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULW) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpHmul16u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul16u x y) + // cond: + // result: (HMULWU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULWU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpHmul32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul32 x y) + // cond: + // result: (HMULL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpHmul32u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul32u x y) + // cond: + // result: (HMULLU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULLU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpHmul8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul8 x y) + // cond: + // result: (HMULB x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULB) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpHmul8u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Hmul8u x y) + // cond: + // result: (HMULBU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386HMULBU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpInterCall(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (InterCall [argwid] entry mem) + // cond: + // result: (CALLinter [argwid] entry mem) + for { + argwid := v.AuxInt + entry := v.Args[0] + mem := v.Args[1] + v.reset(Op386CALLinter) + v.AuxInt = argwid + v.AddArg(entry) + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpIsInBounds(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (IsInBounds idx len) + // cond: + // result: (SETB (CMPL idx len)) + for { + idx := v.Args[0] + len := v.Args[1] + v.reset(Op386SETB) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(idx) + v0.AddArg(len) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpIsNonNil(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (IsNonNil p) + // cond: + // result: (SETNE (TESTL p p)) + for { + p := v.Args[0] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386TESTL, TypeFlags) + v0.AddArg(p) + v0.AddArg(p) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpIsSliceInBounds(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (IsSliceInBounds idx len) + // cond: + // result: (SETBE (CMPL idx len)) + for { + idx := v.Args[0] + len := v.Args[1] + v.reset(Op386SETBE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(idx) + v0.AddArg(len) + v.AddArg(v0) + return true + } +} +func rewriteValue386_Op386LEAL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (LEAL [c] {s} (ADDLconst [d] x)) + // cond: is32Bit(c+d) + // result: (LEAL [c+d] {s} x) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + if !(is32Bit(c + d)) { + break + } + v.reset(Op386LEAL) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + return true + } + // match: (LEAL [c] {s} (ADDL x y)) + // cond: x.Op != OpSB && y.Op != OpSB + // result: (LEAL1 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + x := v_0.Args[0] + y := v_0.Args[1] + if !(x.Op != OpSB && y.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL [off1] {sym1} (LEAL [off2] {sym2} x)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL [off1+off2] {mergeSym(sym1,sym2)} x) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386LEAL) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + return true + } + // match: (LEAL [off1] {sym1} (LEAL1 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL [off1] {sym1} (LEAL2 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL2 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386LEAL2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL [off1] {sym1} (LEAL4 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL [off1] {sym1} (LEAL8 [off2] {sym2} x y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL8 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v_0.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386LEAL1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (LEAL1 [c] {s} (ADDLconst [d] x) y) + // cond: is32Bit(c+d) && x.Op != OpSB + // result: (LEAL1 [c+d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(c+d) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [c] {s} x (ADDLconst [d] y)) + // cond: is32Bit(c+d) && y.Op != OpSB + // result: (LEAL1 [c+d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + y := v_1.Args[0] + if !(is32Bit(c+d) && y.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [c] {s} x (SHLLconst [1] y)) + // cond: + // result: (LEAL2 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL2) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [c] {s} (SHLLconst [1] x) y) + // cond: + // result: (LEAL2 [c] {s} y x) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386SHLLconst { + break + } + if v_0.AuxInt != 1 { + break + } + x := v_0.Args[0] + y := v.Args[1] + v.reset(Op386LEAL2) + v.AuxInt = c + v.Aux = s + v.AddArg(y) + v.AddArg(x) + return true + } + // match: (LEAL1 [c] {s} x (SHLLconst [2] y)) + // cond: + // result: (LEAL4 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL4) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [c] {s} (SHLLconst [2] x) y) + // cond: + // result: (LEAL4 [c] {s} y x) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386SHLLconst { + break + } + if v_0.AuxInt != 2 { + break + } + x := v_0.Args[0] + y := v.Args[1] + v.reset(Op386LEAL4) + v.AuxInt = c + v.Aux = s + v.AddArg(y) + v.AddArg(x) + return true + } + // match: (LEAL1 [c] {s} x (SHLLconst [3] y)) + // cond: + // result: (LEAL8 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 3 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL8) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [c] {s} (SHLLconst [3] x) y) + // cond: + // result: (LEAL8 [c] {s} y x) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386SHLLconst { + break + } + if v_0.AuxInt != 3 { + break + } + x := v_0.Args[0] + y := v.Args[1] + v.reset(Op386LEAL8) + v.AuxInt = c + v.Aux = s + v.AddArg(y) + v.AddArg(x) + return true + } + // match: (LEAL1 [off1] {sym1} (LEAL [off2] {sym2} x) y) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB + // result: (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL1 [off1] {sym1} x (LEAL [off2] {sym2} y)) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && y.Op != OpSB + // result: (LEAL1 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386LEAL { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + y := v_1.Args[0] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && y.Op != OpSB) { + break + } + v.reset(Op386LEAL1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386LEAL2(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (LEAL2 [c] {s} (ADDLconst [d] x) y) + // cond: is32Bit(c+d) && x.Op != OpSB + // result: (LEAL2 [c+d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(c+d) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL2) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL2 [c] {s} x (ADDLconst [d] y)) + // cond: is32Bit(c+2*d) && y.Op != OpSB + // result: (LEAL2 [c+2*d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + y := v_1.Args[0] + if !(is32Bit(c+2*d) && y.Op != OpSB) { + break + } + v.reset(Op386LEAL2) + v.AuxInt = c + 2*d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL2 [c] {s} x (SHLLconst [1] y)) + // cond: + // result: (LEAL4 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL4) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL2 [c] {s} x (SHLLconst [2] y)) + // cond: + // result: (LEAL8 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL8) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL2 [off1] {sym1} (LEAL [off2] {sym2} x) y) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB + // result: (LEAL2 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386LEAL4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (LEAL4 [c] {s} (ADDLconst [d] x) y) + // cond: is32Bit(c+d) && x.Op != OpSB + // result: (LEAL4 [c+d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(c+d) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL4 [c] {s} x (ADDLconst [d] y)) + // cond: is32Bit(c+4*d) && y.Op != OpSB + // result: (LEAL4 [c+4*d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + y := v_1.Args[0] + if !(is32Bit(c+4*d) && y.Op != OpSB) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = c + 4*d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL4 [c] {s} x (SHLLconst [1] y)) + // cond: + // result: (LEAL8 [c] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + y := v_1.Args[0] + v.reset(Op386LEAL8) + v.AuxInt = c + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL4 [off1] {sym1} (LEAL [off2] {sym2} x) y) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB + // result: (LEAL4 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386LEAL8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (LEAL8 [c] {s} (ADDLconst [d] x) y) + // cond: is32Bit(c+d) && x.Op != OpSB + // result: (LEAL8 [c+d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(c+d) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = c + d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL8 [c] {s} x (ADDLconst [d] y)) + // cond: is32Bit(c+8*d) && y.Op != OpSB + // result: (LEAL8 [c+8*d] {s} x y) + for { + c := v.AuxInt + s := v.Aux + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + y := v_1.Args[0] + if !(is32Bit(c+8*d) && y.Op != OpSB) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = c + 8*d + v.Aux = s + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (LEAL8 [off1] {sym1} (LEAL [off2] {sym2} x) y) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB + // result: (LEAL8 [off1+off2] {mergeSym(sym1,sym2)} x y) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + x := v_0.Args[0] + y := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2) && x.Op != OpSB) { + break + } + v.reset(Op386LEAL8) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_OpLeq16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq16 x y) + // cond: + // result: (SETLE (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETLE) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq16U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq16U x y) + // cond: + // result: (SETBE (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETBE) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq32 x y) + // cond: + // result: (SETLE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETLE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq32F x y) + // cond: + // result: (SETGEF (UCOMISS y x)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGEF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq32U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq32U x y) + // cond: + // result: (SETBE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETBE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq64F x y) + // cond: + // result: (SETGEF (UCOMISD y x)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGEF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq8 x y) + // cond: + // result: (SETLE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETLE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLeq8U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Leq8U x y) + // cond: + // result: (SETBE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETBE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less16 x y) + // cond: + // result: (SETL (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETL) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess16U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less16U x y) + // cond: + // result: (SETB (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETB) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less32 x y) + // cond: + // result: (SETL (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETL) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less32F x y) + // cond: + // result: (SETGF (UCOMISS y x)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess32U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less32U x y) + // cond: + // result: (SETB (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETB) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less64F x y) + // cond: + // result: (SETGF (UCOMISD y x)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETGF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less8 x y) + // cond: + // result: (SETL (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETL) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLess8U(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Less8U x y) + // cond: + // result: (SETB (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETB) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpLoad(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Load ptr mem) + // cond: is32BitInt(t) + // result: (MOVLload ptr mem) + for { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is32BitInt(t)) { + break + } + v.reset(Op386MOVLload) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (Load ptr mem) + // cond: is16BitInt(t) + // result: (MOVWload ptr mem) + for { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is16BitInt(t)) { + break + } + v.reset(Op386MOVWload) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (Load ptr mem) + // cond: (t.IsBoolean() || is8BitInt(t)) + // result: (MOVBload ptr mem) + for { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsBoolean() || is8BitInt(t)) { + break + } + v.reset(Op386MOVBload) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (Load ptr mem) + // cond: is32BitFloat(t) + // result: (MOVSSload ptr mem) + for { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is32BitFloat(t)) { + break + } + v.reset(Op386MOVSSload) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (Load ptr mem) + // cond: is64BitFloat(t) + // result: (MOVSDload ptr mem) + for { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is64BitFloat(t)) { + break + } + v.reset(Op386MOVSDload) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_OpLrot16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lrot16 x [c]) + // cond: + // result: (ROLWconst [c&15] x) + for { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.reset(Op386ROLWconst) + v.Type = t + v.AuxInt = c & 15 + v.AddArg(x) + return true + } +} +func rewriteValue386_OpLrot32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lrot32 x [c]) + // cond: + // result: (ROLLconst [c&31] x) + for { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.reset(Op386ROLLconst) + v.Type = t + v.AuxInt = c & 31 + v.AddArg(x) + return true + } +} +func rewriteValue386_OpLrot8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lrot8 x [c]) + // cond: + // result: (ROLBconst [c&7] x) + for { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.reset(Op386ROLBconst) + v.Type = t + v.AuxInt = c & 7 + v.AddArg(x) + return true + } +} +func rewriteValue386_OpLsh16x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh16x16 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh16x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh16x32 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh16x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh16x8 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh32x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh32x16 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh32x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh32x32 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh32x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh32x8 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh8x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x16 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh8x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x32 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpLsh8x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x8 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHLL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_Op386MOVBLSX(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBLSX x:(MOVBload [off] {sym} ptr mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVBLSXload [off] {sym} ptr mem) + for { + x := v.Args[0] + if x.Op != Op386MOVBload { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + mem := x.Args[1] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVBLSXload, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + // match: (MOVBLSX (ANDLconst [c] x)) + // cond: c & 0x80 == 0 + // result: (ANDLconst [c & 0x7f] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + if !(c&0x80 == 0) { + break + } + v.reset(Op386ANDLconst) + v.AuxInt = c & 0x7f + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386MOVBLSXload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVBLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBLSXload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBLZX(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBLZX x:(MOVBload [off] {sym} ptr mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVBload [off] {sym} ptr mem) + for { + x := v.Args[0] + if x.Op != Op386MOVBload { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + mem := x.Args[1] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVBload, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + // match: (MOVBLZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVBloadidx1 [off] {sym} ptr idx mem) + for { + x := v.Args[0] + if x.Op != Op386MOVBloadidx1 { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + idx := x.Args[1] + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVBloadidx1, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(idx) + v0.AddArg(mem) + return true + } + // match: (MOVBLZX (ANDLconst [c] x)) + // cond: + // result: (ANDLconst [c & 0xff] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ANDLconst) + v.AuxInt = c & 0xff + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386MOVBload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) + // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) + // result: x + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVBstore { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + ptr2 := v_1.Args[0] + x := v_1.Args[1] + if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (MOVBload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVBload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVBload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVBload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + // match: (MOVBload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVBloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBloadidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBload [off] {sym} (ADDL ptr idx) mem) + // cond: ptr.Op != OpSB + // result: (MOVBloadidx1 [off] {sym} ptr idx mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVBloadidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBloadidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVBloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVBloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVBloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVBloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBstore [off] {sym} ptr (MOVBLSX x) mem) + // cond: + // result: (MOVBstore [off] {sym} ptr x mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVBLSX { + break + } + x := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVBstore) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off] {sym} ptr (MOVBLZX x) mem) + // cond: + // result: (MOVBstore [off] {sym} ptr x mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVBLZX { + break + } + x := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVBstore) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVBstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off] {sym} ptr (MOVLconst [c]) mem) + // cond: validOff(off) + // result: (MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + mem := v.Args[2] + if !(validOff(off)) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = makeValAndOff(int64(int8(c)), off) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVBstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBstoreidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstore [off] {sym} (ADDL ptr idx) val mem) + // cond: ptr.Op != OpSB + // result: (MOVBstoreidx1 [off] {sym} ptr idx val mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVBstoreidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstore [i] {s} p (SHRLconst [8] w) x:(MOVBstore [i-1] {s} p w mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVWstore [i-1] {s} p w mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHRLconst { + break + } + if v_1.AuxInt != 8 { + break + } + w := v_1.Args[0] + x := v.Args[2] + if x.Op != Op386MOVBstore { + break + } + if x.AuxInt != i-1 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if w != x.Args[1] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i - 1 + v.Aux = s + v.AddArg(p) + v.AddArg(w) + v.AddArg(mem) + return true + } + // match: (MOVBstore [i] {s} p (SHRLconst [j] w) x:(MOVBstore [i-1] {s} p w0:(SHRLconst [j-8] w) mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVWstore [i-1] {s} p w0 mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHRLconst { + break + } + j := v_1.AuxInt + w := v_1.Args[0] + x := v.Args[2] + if x.Op != Op386MOVBstore { + break + } + if x.AuxInt != i-1 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + w0 := x.Args[1] + if w0.Op != Op386SHRLconst { + break + } + if w0.AuxInt != j-8 { + break + } + if w != w0.Args[0] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = i - 1 + v.Aux = s + v.AddArg(p) + v.AddArg(w0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBstoreconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBstoreconst [sc] {s} (ADDLconst [off] ptr) mem) + // cond: ValAndOff(sc).canAdd(off) + // result: (MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) + for { + sc := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = s + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) + // result: (MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVBstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + for { + x := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVBstoreconstidx1) + v.AuxInt = ValAndOff(x).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconst [x] {sym} (ADDL ptr idx) mem) + // cond: + // result: (MOVBstoreconstidx1 [x] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + v.reset(Op386MOVBstoreconstidx1) + v.AuxInt = x + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) + // result: (MOVWstoreconst [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p mem) + for { + c := v.AuxInt + s := v.Aux + p := v.Args[0] + x := v.Args[1] + if x.Op != Op386MOVBstoreconst { + break + } + a := x.AuxInt + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + mem := x.Args[1] + if !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) + v.Aux = s + v.AddArg(p) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBstoreconstidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) + // cond: + // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVBstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) + // cond: + // result: (MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVBstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVBstoreconstidx1 [c] {s} p i x:(MOVBstoreconstidx1 [a] {s} p i mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 1 == ValAndOff(c).Off() && clobber(x) + // result: (MOVWstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xff | ValAndOff(c).Val()<<8, ValAndOff(a).Off())] {s} p i mem) + for { + c := v.AuxInt + s := v.Aux + p := v.Args[0] + i := v.Args[1] + x := v.Args[2] + if x.Op != Op386MOVBstoreconstidx1 { + break + } + a := x.AuxInt + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if i != x.Args[1] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && ValAndOff(a).Off()+1 == ValAndOff(c).Off() && clobber(x)) { + break + } + v.reset(Op386MOVWstoreconstidx1) + v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xff|ValAndOff(c).Val()<<8, ValAndOff(a).Off()) + v.Aux = s + v.AddArg(p) + v.AddArg(i) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVBstoreidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVBstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVBstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [8] w) x:(MOVBstoreidx1 [i-1] {s} p idx w mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVWstoreidx1 [i-1] {s} p idx w mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + if v_2.AuxInt != 8 { + break + } + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVBstoreidx1 { + break + } + if x.AuxInt != i-1 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + if w != x.Args[2] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVWstoreidx1) + v.AuxInt = i - 1 + v.Aux = s + v.AddArg(p) + v.AddArg(idx) + v.AddArg(w) + v.AddArg(mem) + return true + } + // match: (MOVBstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVBstoreidx1 [i-1] {s} p idx w0:(SHRLconst [j-8] w) mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVWstoreidx1 [i-1] {s} p idx w0 mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + j := v_2.AuxInt + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVBstoreidx1 { + break + } + if x.AuxInt != i-1 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + w0 := x.Args[2] + if w0.Op != Op386SHRLconst { + break + } + if w0.AuxInt != j-8 { + break + } + if w != w0.Args[0] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVWstoreidx1) + v.AuxInt = i - 1 + v.Aux = s + v.AddArg(p) + v.AddArg(idx) + v.AddArg(w0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) + // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) + // result: x + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLstore { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + ptr2 := v_1.Args[0] + x := v_1.Args[1] + if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (MOVLload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVLload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVLload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVLload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + // match: (MOVLload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLloadidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLloadidx4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLload [off] {sym} (ADDL ptr idx) mem) + // cond: ptr.Op != OpSB + // result: (MOVLloadidx1 [off] {sym} ptr idx mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVLloadidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLloadidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLloadidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) + // cond: + // result: (MOVLloadidx4 [c] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLloadidx4) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVLloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVLloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVLloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLloadidx4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVLloadidx4 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVLloadidx4) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVLloadidx4 [c+4*d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLloadidx4) + v.AuxInt = c + 4*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVLstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) + // cond: validOff(off) + // result: (MOVLstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + mem := v.Args[2] + if !(validOff(off)) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(int64(int32(c)), off) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVLstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVLstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLstoreidx4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstore [off] {sym} (ADDL ptr idx) val mem) + // cond: ptr.Op != OpSB + // result: (MOVLstoreidx1 [off] {sym} ptr idx val mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstoreconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstoreconst [sc] {s} (ADDLconst [off] ptr) mem) + // cond: ValAndOff(sc).canAdd(off) + // result: (MOVLstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) + for { + sc := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = s + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) + // result: (MOVLstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVLstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + for { + x := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = ValAndOff(x).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconst [x] {sym1} (LEAL4 [off] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVLstoreconstidx4 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + for { + x := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVLstoreconstidx4) + v.AuxInt = ValAndOff(x).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconst [x] {sym} (ADDL ptr idx) mem) + // cond: + // result: (MOVLstoreconstidx1 [x] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = x + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstoreconstidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) + // cond: + // result: (MOVLstoreconstidx4 [c] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLstoreconstidx4) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) + // cond: + // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) + // cond: + // result: (MOVLstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstoreconstidx4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstoreconstidx4 [x] {sym} (ADDLconst [c] ptr) idx mem) + // cond: + // result: (MOVLstoreconstidx4 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVLstoreconstidx4) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVLstoreconstidx4 [x] {sym} ptr (ADDLconst [c] idx) mem) + // cond: + // result: (MOVLstoreconstidx4 [ValAndOff(x).add(4*c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVLstoreconstidx4) + v.AuxInt = ValAndOff(x).add(4 * c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstoreidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstoreidx1 [c] {sym} ptr (SHLLconst [2] idx) val mem) + // cond: + // result: (MOVLstoreidx4 [c] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 2 { + break + } + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVLstoreidx4) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVLstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVLstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVLstoreidx4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVLstoreidx4 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVLstoreidx4) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVLstoreidx4) + v.AuxInt = c + 4*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVOload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVOload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVOload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVOload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVOload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVOload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVOload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVOstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVOstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVOstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVOstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVOstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVOstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVOstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVSDload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVSDload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVSDload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + // match: (MOVSDload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDloadidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSDload [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDloadidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL8 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDloadidx8) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSDload [off] {sym} (ADDL ptr idx) mem) + // cond: ptr.Op != OpSB + // result: (MOVSDloadidx1 [off] {sym} ptr idx mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVSDloadidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDloadidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVSDloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVSDloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDloadidx8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVSDloadidx8 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVSDloadidx8) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVSDloadidx8) + v.AuxInt = c + 8*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVSDstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVSDstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDstoreidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstore [off1] {sym1} (LEAL8 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSDstoreidx8 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL8 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSDstoreidx8) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstore [off] {sym} (ADDL ptr idx) val mem) + // cond: ptr.Op != OpSB + // result: (MOVSDstoreidx1 [off] {sym} ptr idx val mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVSDstoreidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDstoreidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSDstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSDstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSDstoreidx8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSDstoreidx8) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSDstoreidx8) + v.AuxInt = c + 8*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVSSload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVSSload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVSSload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + // match: (MOVSSload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSloadidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSSload [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSloadidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSloadidx4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSSload [off] {sym} (ADDL ptr idx) mem) + // cond: ptr.Op != OpSB + // result: (MOVSSloadidx1 [off] {sym} ptr idx mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVSSloadidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSloadidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVSSloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVSSloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSloadidx4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVSSloadidx4 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVSSloadidx4) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVSSloadidx4) + v.AuxInt = c + 4*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVSSstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVSSstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSstoreidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstore [off1] {sym1} (LEAL4 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVSSstoreidx4 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL4 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVSSstoreidx4) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstore [off] {sym} (ADDL ptr idx) val mem) + // cond: ptr.Op != OpSB + // result: (MOVSSstoreidx1 [off] {sym} ptr idx val mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVSSstoreidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSstoreidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSSstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSSstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVSSstoreidx4(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSSstoreidx4) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVSSstoreidx4) + v.AuxInt = c + 4*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWLSX(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWLSX x:(MOVWload [off] {sym} ptr mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVWLSXload [off] {sym} ptr mem) + for { + x := v.Args[0] + if x.Op != Op386MOVWload { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + mem := x.Args[1] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVWLSXload, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + // match: (MOVWLSX (ANDLconst [c] x)) + // cond: c & 0x8000 == 0 + // result: (ANDLconst [c & 0x7fff] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + if !(c&0x8000 == 0) { + break + } + v.reset(Op386ANDLconst) + v.AuxInt = c & 0x7fff + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386MOVWLSXload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWLSXload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWLZX(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWLZX x:(MOVWload [off] {sym} ptr mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVWload [off] {sym} ptr mem) + for { + x := v.Args[0] + if x.Op != Op386MOVWload { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + mem := x.Args[1] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVWload, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + // match: (MOVWLZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVWloadidx1 [off] {sym} ptr idx mem) + for { + x := v.Args[0] + if x.Op != Op386MOVWloadidx1 { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + idx := x.Args[1] + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVWloadidx1, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(idx) + v0.AddArg(mem) + return true + } + // match: (MOVWLZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) + // cond: x.Uses == 1 && clobber(x) + // result: @x.Block (MOVWloadidx2 [off] {sym} ptr idx mem) + for { + x := v.Args[0] + if x.Op != Op386MOVWloadidx2 { + break + } + off := x.AuxInt + sym := x.Aux + ptr := x.Args[0] + idx := x.Args[1] + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + b = x.Block + v0 := b.NewValue0(v.Line, Op386MOVWloadidx2, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(idx) + v0.AddArg(mem) + return true + } + // match: (MOVWLZX (ANDLconst [c] x)) + // cond: + // result: (ANDLconst [c & 0xffff] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386ANDLconst { + break + } + c := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ANDLconst) + v.AuxInt = c & 0xffff + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386MOVWload(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) + // cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) + // result: x + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVWstore { + break + } + off2 := v_1.AuxInt + sym2 := v_1.Aux + ptr2 := v_1.Args[0] + x := v_1.Args[1] + if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (MOVWload [off1] {sym} (ADDLconst [off2] ptr) mem) + // cond: is32Bit(off1+off2) + // result: (MOVWload [off1+off2] {sym} ptr mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVWload) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVWload [off1] {sym1} (LEAL [off2] {sym2} base) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWload) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + // match: (MOVWload [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWloadidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWloadidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWload [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWloadidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL2 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWloadidx2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWload [off] {sym} (ADDL ptr idx) mem) + // cond: ptr.Op != OpSB + // result: (MOVWloadidx1 [off] {sym} ptr idx mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVWloadidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWloadidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWloadidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) + // cond: + // result: (MOVWloadidx2 [c] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWloadidx2) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVWloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVWloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVWloadidx1 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWloadidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWloadidx2(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) + // cond: + // result: (MOVWloadidx2 [c+d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVWloadidx2) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) + // cond: + // result: (MOVWloadidx2 [c+2*d] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWloadidx2) + v.AuxInt = c + 2*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstore [off] {sym} ptr (MOVWLSX x) mem) + // cond: + // result: (MOVWstore [off] {sym} ptr x mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVWLSX { + break + } + x := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWstore) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off] {sym} ptr (MOVWLZX x) mem) + // cond: + // result: (MOVWstore [off] {sym} ptr x mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVWLZX { + break + } + x := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWstore) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off1] {sym} (ADDLconst [off2] ptr) val mem) + // cond: is32Bit(off1+off2) + // result: (MOVWstore [off1+off2] {sym} ptr val mem) + for { + off1 := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off2 := v_0.AuxInt + ptr := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1 + off2)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = off1 + off2 + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off] {sym} ptr (MOVLconst [c]) mem) + // cond: validOff(off) + // result: (MOVWstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem) + for { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + mem := v.Args[2] + if !(validOff(off)) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = makeValAndOff(int64(int16(c)), off) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off1] {sym1} (LEAL [off2] {sym2} base) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + base := v_0.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off1] {sym1} (LEAL1 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWstoreidx1 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWstoreidx1) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off1] {sym1} (LEAL2 [off2] {sym2} ptr idx) val mem) + // cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) + // result: (MOVWstoreidx2 [off1+off2] {mergeSym(sym1,sym2)} ptr idx val mem) + for { + off1 := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL2 { + break + } + off2 := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(is32Bit(off1+off2) && canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWstoreidx2) + v.AuxInt = off1 + off2 + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstore [off] {sym} (ADDL ptr idx) val mem) + // cond: ptr.Op != OpSB + // result: (MOVWstoreidx1 [off] {sym} ptr idx val mem) + for { + off := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(ptr.Op != OpSB) { + break + } + v.reset(Op386MOVWstoreidx1) + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstore [i] {s} p (SHRLconst [16] w) x:(MOVWstore [i-2] {s} p w mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstore [i-2] {s} p w mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHRLconst { + break + } + if v_1.AuxInt != 16 { + break + } + w := v_1.Args[0] + x := v.Args[2] + if x.Op != Op386MOVWstore { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if w != x.Args[1] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v.AddArg(w) + v.AddArg(mem) + return true + } + // match: (MOVWstore [i] {s} p (SHRLconst [j] w) x:(MOVWstore [i-2] {s} p w0:(SHRLconst [j-16] w) mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstore [i-2] {s} p w0 mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHRLconst { + break + } + j := v_1.AuxInt + w := v_1.Args[0] + x := v.Args[2] + if x.Op != Op386MOVWstore { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + w0 := x.Args[1] + if w0.Op != Op386SHRLconst { + break + } + if w0.AuxInt != j-16 { + break + } + if w != w0.Args[0] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v.AddArg(w0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstoreconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstoreconst [sc] {s} (ADDLconst [off] ptr) mem) + // cond: ValAndOff(sc).canAdd(off) + // result: (MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem) + for { + sc := v.AuxInt + s := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + off := v_0.AuxInt + ptr := v_0.Args[0] + mem := v.Args[1] + if !(ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = s + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconst [sc] {sym1} (LEAL [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) + // result: (MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = ValAndOff(sc).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconst [x] {sym1} (LEAL1 [off] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVWstoreconstidx1 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + for { + x := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL1 { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWstoreconstidx1) + v.AuxInt = ValAndOff(x).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconst [x] {sym1} (LEAL2 [off] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVWstoreconstidx2 [ValAndOff(x).add(off)] {mergeSym(sym1,sym2)} ptr idx mem) + for { + x := v.AuxInt + sym1 := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386LEAL2 { + break + } + off := v_0.AuxInt + sym2 := v_0.Aux + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + break + } + v.reset(Op386MOVWstoreconstidx2) + v.AuxInt = ValAndOff(x).add(off) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconst [x] {sym} (ADDL ptr idx) mem) + // cond: + // result: (MOVWstoreconstidx1 [x] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDL { + break + } + ptr := v_0.Args[0] + idx := v_0.Args[1] + mem := v.Args[1] + v.reset(Op386MOVWstoreconstidx1) + v.AuxInt = x + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) + // result: (MOVLstoreconst [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p mem) + for { + c := v.AuxInt + s := v.Aux + p := v.Args[0] + x := v.Args[1] + if x.Op != Op386MOVWstoreconst { + break + } + a := x.AuxInt + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + mem := x.Args[1] + if !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) + v.Aux = s + v.AddArg(p) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstoreconstidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstoreconstidx1 [c] {sym} ptr (SHLLconst [1] idx) mem) + // cond: + // result: (MOVWstoreconstidx2 [c] {sym} ptr idx mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWstoreconstidx2) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) + // cond: + // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVWstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconstidx1 [x] {sym} ptr (ADDLconst [c] idx) mem) + // cond: + // result: (MOVWstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWstoreconstidx1) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconstidx1 [c] {s} p i x:(MOVWstoreconstidx1 [a] {s} p i mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) + // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p i mem) + for { + c := v.AuxInt + s := v.Aux + p := v.Args[0] + i := v.Args[1] + x := v.Args[2] + if x.Op != Op386MOVWstoreconstidx1 { + break + } + a := x.AuxInt + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if i != x.Args[1] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + break + } + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) + v.Aux = s + v.AddArg(p) + v.AddArg(i) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstoreconstidx2(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstoreconstidx2 [x] {sym} (ADDLconst [c] ptr) idx mem) + // cond: + // result: (MOVWstoreconstidx2 [ValAndOff(x).add(c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + c := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVWstoreconstidx2) + v.AuxInt = ValAndOff(x).add(c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconstidx2 [x] {sym} ptr (ADDLconst [c] idx) mem) + // cond: + // result: (MOVWstoreconstidx2 [ValAndOff(x).add(2*c)] {sym} ptr idx mem) + for { + x := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + c := v_1.AuxInt + idx := v_1.Args[0] + mem := v.Args[2] + v.reset(Op386MOVWstoreconstidx2) + v.AuxInt = ValAndOff(x).add(2 * c) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + // match: (MOVWstoreconstidx2 [c] {s} p i x:(MOVWstoreconstidx2 [a] {s} p i mem)) + // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) + // result: (MOVLstoreconstidx1 [makeValAndOff(ValAndOff(a).Val()&0xffff | ValAndOff(c).Val()<<16, ValAndOff(a).Off())] {s} p (SHLLconst [1] i) mem) + for { + c := v.AuxInt + s := v.Aux + p := v.Args[0] + i := v.Args[1] + x := v.Args[2] + if x.Op != Op386MOVWstoreconstidx2 { + break + } + a := x.AuxInt + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if i != x.Args[1] { + break + } + mem := x.Args[2] + if !(x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) { + break + } + v.reset(Op386MOVLstoreconstidx1) + v.AuxInt = makeValAndOff(ValAndOff(a).Val()&0xffff|ValAndOff(c).Val()<<16, ValAndOff(a).Off()) + v.Aux = s + v.AddArg(p) + v0 := b.NewValue0(v.Line, Op386SHLLconst, i.Type) + v0.AuxInt = 1 + v0.AddArg(i) + v.AddArg(v0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstoreidx1(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstoreidx1 [c] {sym} ptr (SHLLconst [1] idx) val mem) + // cond: + // result: (MOVWstoreidx2 [c] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SHLLconst { + break + } + if v_1.AuxInt != 1 { + break + } + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVWstoreidx2) + v.AuxInt = c + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVWstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVWstoreidx1) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx1 [i-2] {s} p idx w mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstoreidx1 [i-2] {s} p idx w mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + if v_2.AuxInt != 16 { + break + } + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVWstoreidx1 { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + if w != x.Args[2] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v.AddArg(idx) + v.AddArg(w) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx1 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx1 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstoreidx1 [i-2] {s} p idx w0 mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + j := v_2.AuxInt + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVWstoreidx1 { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + w0 := x.Args[2] + if w0.Op != Op386SHRLconst { + break + } + if w0.AuxInt != j-16 { + break + } + if w != w0.Args[0] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v.AddArg(idx) + v.AddArg(w0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MOVWstoreidx2(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) + // cond: + // result: (MOVWstoreidx2 [c+d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + v_0 := v.Args[0] + if v_0.Op != Op386ADDLconst { + break + } + d := v_0.AuxInt + ptr := v_0.Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVWstoreidx2) + v.AuxInt = c + d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) + // cond: + // result: (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem) + for { + c := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ADDLconst { + break + } + d := v_1.AuxInt + idx := v_1.Args[0] + val := v.Args[2] + mem := v.Args[3] + v.reset(Op386MOVWstoreidx2) + v.AuxInt = c + 2*d + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx2 [i] {s} p idx (SHRLconst [16] w) x:(MOVWstoreidx2 [i-2] {s} p idx w mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + if v_2.AuxInt != 16 { + break + } + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVWstoreidx2 { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + if w != x.Args[2] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v0 := b.NewValue0(v.Line, Op386SHLLconst, idx.Type) + v0.AuxInt = 1 + v0.AddArg(idx) + v.AddArg(v0) + v.AddArg(w) + v.AddArg(mem) + return true + } + // match: (MOVWstoreidx2 [i] {s} p idx (SHRLconst [j] w) x:(MOVWstoreidx2 [i-2] {s} p idx w0:(SHRLconst [j-16] w) mem)) + // cond: x.Uses == 1 && clobber(x) + // result: (MOVLstoreidx1 [i-2] {s} p (SHLLconst [1] idx) w0 mem) + for { + i := v.AuxInt + s := v.Aux + p := v.Args[0] + idx := v.Args[1] + v_2 := v.Args[2] + if v_2.Op != Op386SHRLconst { + break + } + j := v_2.AuxInt + w := v_2.Args[0] + x := v.Args[3] + if x.Op != Op386MOVWstoreidx2 { + break + } + if x.AuxInt != i-2 { + break + } + if x.Aux != s { + break + } + if p != x.Args[0] { + break + } + if idx != x.Args[1] { + break + } + w0 := x.Args[2] + if w0.Op != Op386SHRLconst { + break + } + if w0.AuxInt != j-16 { + break + } + if w != w0.Args[0] { + break + } + mem := x.Args[3] + if !(x.Uses == 1 && clobber(x)) { + break + } + v.reset(Op386MOVLstoreidx1) + v.AuxInt = i - 2 + v.Aux = s + v.AddArg(p) + v0 := b.NewValue0(v.Line, Op386SHLLconst, idx.Type) + v0.AuxInt = 1 + v0.AddArg(idx) + v.AddArg(v0) + v.AddArg(w0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386MULL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MULL x (MOVLconst [c])) + // cond: + // result: (MULLconst [c] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386MULLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (MULL (MOVLconst [c]) x) + // cond: + // result: (MULLconst [c] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386MULLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386MULLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (MULLconst [c] (MULLconst [d] x)) + // cond: + // result: (MULLconst [int64(int32(c * d))] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MULLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386MULLconst) + v.AuxInt = int64(int32(c * d)) + v.AddArg(x) + return true + } + // match: (MULLconst [-1] x) + // cond: + // result: (NEGL x) + for { + if v.AuxInt != -1 { + break + } + x := v.Args[0] + v.reset(Op386NEGL) + v.AddArg(x) + return true + } + // match: (MULLconst [0] _) + // cond: + // result: (MOVLconst [0]) + for { + if v.AuxInt != 0 { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (MULLconst [1] x) + // cond: + // result: x + for { + if v.AuxInt != 1 { + break + } + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (MULLconst [3] x) + // cond: + // result: (LEAL2 x x) + for { + if v.AuxInt != 3 { + break + } + x := v.Args[0] + v.reset(Op386LEAL2) + v.AddArg(x) + v.AddArg(x) + return true + } + // match: (MULLconst [5] x) + // cond: + // result: (LEAL4 x x) + for { + if v.AuxInt != 5 { + break + } + x := v.Args[0] + v.reset(Op386LEAL4) + v.AddArg(x) + v.AddArg(x) + return true + } + // match: (MULLconst [7] x) + // cond: + // result: (LEAL8 (NEGL x) x) + for { + if v.AuxInt != 7 { + break + } + x := v.Args[0] + v.reset(Op386LEAL8) + v0 := b.NewValue0(v.Line, Op386NEGL, v.Type) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [9] x) + // cond: + // result: (LEAL8 x x) + for { + if v.AuxInt != 9 { + break + } + x := v.Args[0] + v.reset(Op386LEAL8) + v.AddArg(x) + v.AddArg(x) + return true + } + // match: (MULLconst [11] x) + // cond: + // result: (LEAL2 x (LEAL4 x x)) + for { + if v.AuxInt != 11 { + break + } + x := v.Args[0] + v.reset(Op386LEAL2) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL4, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [13] x) + // cond: + // result: (LEAL4 x (LEAL2 x x)) + for { + if v.AuxInt != 13 { + break + } + x := v.Args[0] + v.reset(Op386LEAL4) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL2, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [21] x) + // cond: + // result: (LEAL4 x (LEAL4 x x)) + for { + if v.AuxInt != 21 { + break + } + x := v.Args[0] + v.reset(Op386LEAL4) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL4, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [25] x) + // cond: + // result: (LEAL8 x (LEAL2 x x)) + for { + if v.AuxInt != 25 { + break + } + x := v.Args[0] + v.reset(Op386LEAL8) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL2, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [37] x) + // cond: + // result: (LEAL4 x (LEAL8 x x)) + for { + if v.AuxInt != 37 { + break + } + x := v.Args[0] + v.reset(Op386LEAL4) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL8, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [41] x) + // cond: + // result: (LEAL8 x (LEAL4 x x)) + for { + if v.AuxInt != 41 { + break + } + x := v.Args[0] + v.reset(Op386LEAL8) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL4, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [73] x) + // cond: + // result: (LEAL8 x (LEAL8 x x)) + for { + if v.AuxInt != 73 { + break + } + x := v.Args[0] + v.reset(Op386LEAL8) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386LEAL8, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c) + // result: (SHLLconst [log2(c)] x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c)) { + break + } + v.reset(Op386SHLLconst) + v.AuxInt = log2(c) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c+1) && c >= 15 + // result: (SUBL (SHLLconst [log2(c+1)] x) x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c+1) && c >= 15) { + break + } + v.reset(Op386SUBL) + v0 := b.NewValue0(v.Line, Op386SHLLconst, v.Type) + v0.AuxInt = log2(c + 1) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-1) && c >= 17 + // result: (LEAL1 (SHLLconst [log2(c-1)] x) x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c-1) && c >= 17) { + break + } + v.reset(Op386LEAL1) + v0 := b.NewValue0(v.Line, Op386SHLLconst, v.Type) + v0.AuxInt = log2(c - 1) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-2) && c >= 34 + // result: (LEAL2 (SHLLconst [log2(c-2)] x) x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c-2) && c >= 34) { + break + } + v.reset(Op386LEAL2) + v0 := b.NewValue0(v.Line, Op386SHLLconst, v.Type) + v0.AuxInt = log2(c - 2) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-4) && c >= 68 + // result: (LEAL4 (SHLLconst [log2(c-4)] x) x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c-4) && c >= 68) { + break + } + v.reset(Op386LEAL4) + v0 := b.NewValue0(v.Line, Op386SHLLconst, v.Type) + v0.AuxInt = log2(c - 4) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-8) && c >= 136 + // result: (LEAL8 (SHLLconst [log2(c-8)] x) x) + for { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c-8) && c >= 136) { + break + } + v.reset(Op386LEAL8) + v0 := b.NewValue0(v.Line, Op386SHLLconst, v.Type) + v0.AuxInt = log2(c - 8) + v0.AddArg(x) + v.AddArg(v0) + v.AddArg(x) + return true + } + // match: (MULLconst [c] x) + // cond: c%3 == 0 && isPowerOfTwo(c/3) + // result: (SHLLconst [log2(c/3)] (LEAL2 x x)) + for { + c := v.AuxInt + x := v.Args[0] + if !(c%3 == 0 && isPowerOfTwo(c/3)) { + break + } + v.reset(Op386SHLLconst) + v.AuxInt = log2(c / 3) + v0 := b.NewValue0(v.Line, Op386LEAL2, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] x) + // cond: c%5 == 0 && isPowerOfTwo(c/5) + // result: (SHLLconst [log2(c/5)] (LEAL4 x x)) + for { + c := v.AuxInt + x := v.Args[0] + if !(c%5 == 0 && isPowerOfTwo(c/5)) { + break + } + v.reset(Op386SHLLconst) + v.AuxInt = log2(c / 5) + v0 := b.NewValue0(v.Line, Op386LEAL4, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] x) + // cond: c%9 == 0 && isPowerOfTwo(c/9) + // result: (SHLLconst [log2(c/9)] (LEAL8 x x)) + for { + c := v.AuxInt + x := v.Args[0] + if !(c%9 == 0 && isPowerOfTwo(c/9)) { + break + } + v.reset(Op386SHLLconst) + v.AuxInt = log2(c / 9) + v0 := b.NewValue0(v.Line, Op386LEAL8, v.Type) + v0.AddArg(x) + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [int64(int32(c*d))]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = int64(int32(c * d)) + return true + } + return false +} +func rewriteValue386_OpMod16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod16 x y) + // cond: + // result: (MODW x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODW) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMod16u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod16u x y) + // cond: + // result: (MODWU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODWU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMod32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod32 x y) + // cond: + // result: (MODL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMod32u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod32u x y) + // cond: + // result: (MODLU x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODLU) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMod8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod8 x y) + // cond: + // result: (MODW (SignExt8to16 x) (SignExt8to16 y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODW) + v0 := b.NewValue0(v.Line, OpSignExt8to16, config.fe.TypeInt16()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, config.fe.TypeInt16()) + v1.AddArg(y) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpMod8u(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mod8u x y) + // cond: + // result: (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MODWU) + v0 := b.NewValue0(v.Line, OpZeroExt8to16, config.fe.TypeUInt16()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, config.fe.TypeUInt16()) + v1.AddArg(y) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpMove(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Move [s] _ _ mem) + // cond: SizeAndAlign(s).Size() == 0 + // result: mem + for { + s := v.AuxInt + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 0) { + break + } + v.reset(OpCopy) + v.Type = mem.Type + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 1 + // result: (MOVBstore dst (MOVBload src mem) mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 1) { + break + } + v.reset(Op386MOVBstore) + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVBload, config.fe.TypeUInt8()) + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 2 + // result: (MOVWstore dst (MOVWload src mem) mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 2) { + break + } + v.reset(Op386MOVWstore) + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVWload, config.fe.TypeUInt16()) + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 4 + // result: (MOVLstore dst (MOVLload src mem) mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 4) { + break + } + v.reset(Op386MOVLstore) + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 16 + // result: (MOVOstore dst (MOVOload src mem) mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 16) { + break + } + v.reset(Op386MOVOstore) + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVOload, TypeInt128) + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 3 + // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem)) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 3) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = 2 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVBload, config.fe.TypeUInt8()) + v0.AuxInt = 2 + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVWstore, TypeMem) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, Op386MOVWload, config.fe.TypeUInt16()) + v2.AddArg(src) + v2.AddArg(mem) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 5 + // result: (MOVBstore [4] dst (MOVBload [4] src mem) (MOVLstore dst (MOVLload src mem) mem)) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 5) { + break + } + v.reset(Op386MOVBstore) + v.AuxInt = 4 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVBload, config.fe.TypeUInt8()) + v0.AuxInt = 4 + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVLstore, TypeMem) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v2.AddArg(src) + v2.AddArg(mem) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 6 + // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVLstore dst (MOVLload src mem) mem)) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 6) { + break + } + v.reset(Op386MOVWstore) + v.AuxInt = 4 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVWload, config.fe.TypeUInt16()) + v0.AuxInt = 4 + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVLstore, TypeMem) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v2.AddArg(src) + v2.AddArg(mem) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() == 7 + // result: (MOVLstore [3] dst (MOVLload [3] src mem) (MOVLstore dst (MOVLload src mem) mem)) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() == 7) { + break + } + v.reset(Op386MOVLstore) + v.AuxInt = 3 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v0.AuxInt = 3 + v0.AddArg(src) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVLstore, TypeMem) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v2.AddArg(src) + v2.AddArg(mem) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + // match: (Move [s] dst src mem) + // cond: SizeAndAlign(s).Size() >= 32 && SizeAndAlign(s).Size() <= 16*64 && SizeAndAlign(s).Size()%16 == 0 && !config.noDuffDevice + // result: (DUFFCOPY [14*(64-SizeAndAlign(s).Size()/16)] dst src mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(SizeAndAlign(s).Size() >= 32 && SizeAndAlign(s).Size() <= 16*64 && SizeAndAlign(s).Size()%16 == 0 && !config.noDuffDevice) { + break + } + v.reset(Op386DUFFCOPY) + v.AuxInt = 14 * (64 - SizeAndAlign(s).Size()/16) + v.AddArg(dst) + v.AddArg(src) + v.AddArg(mem) + return true + } + // match: (Move [s] dst src mem) + // cond: (SizeAndAlign(s).Size() > 16*64 || config.noDuffDevice) && SizeAndAlign(s).Size()%8 == 0 + // result: (REPMOVSL dst src (MOVLconst [SizeAndAlign(s).Size()/4]) mem) + for { + s := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !((SizeAndAlign(s).Size() > 16*64 || config.noDuffDevice) && SizeAndAlign(s).Size()%8 == 0) { + break + } + v.reset(Op386REPMOVSL) + v.AddArg(dst) + v.AddArg(src) + v0 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32()) + v0.AuxInt = SizeAndAlign(s).Size() / 4 + v.AddArg(v0) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_OpMul16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul16 x y) + // cond: + // result: (MULL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MULL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMul32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul32 x y) + // cond: + // result: (MULL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MULL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMul32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul32F x y) + // cond: + // result: (MULSS x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MULSS) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMul64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul64F x y) + // cond: + // result: (MULSD x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MULSD) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpMul8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul8 x y) + // cond: + // result: (MULL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386MULL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_Op386NEGL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NEGL (MOVLconst [c])) + // cond: + // result: (MOVLconst [int64(int32(-c))]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = int64(int32(-c)) + return true + } + return false +} +func rewriteValue386_Op386NOTL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NOTL (MOVLconst [c])) + // cond: + // result: (MOVLconst [^c]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = ^c + return true + } + return false +} +func rewriteValue386_OpNeg16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neg16 x) + // cond: + // result: (NEGL x) + for { + x := v.Args[0] + v.reset(Op386NEGL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpNeg32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neg32 x) + // cond: + // result: (NEGL x) + for { + x := v.Args[0] + v.reset(Op386NEGL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpNeg32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neg32F x) + // cond: + // result: (PXOR x (MOVSSconst [f2i(math.Copysign(0, -1))])) + for { + x := v.Args[0] + v.reset(Op386PXOR) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386MOVSSconst, config.Frontend().TypeFloat32()) + v0.AuxInt = f2i(math.Copysign(0, -1)) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeg64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neg64F x) + // cond: + // result: (PXOR x (MOVSDconst [f2i(math.Copysign(0, -1))])) + for { + x := v.Args[0] + v.reset(Op386PXOR) + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386MOVSDconst, config.Frontend().TypeFloat64()) + v0.AuxInt = f2i(math.Copysign(0, -1)) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeg8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neg8 x) + // cond: + // result: (NEGL x) + for { + x := v.Args[0] + v.reset(Op386NEGL) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpNeq16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq16 x y) + // cond: + // result: (SETNE (CMPW x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386CMPW, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeq32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq32 x y) + // cond: + // result: (SETNE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeq32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq32F x y) + // cond: + // result: (SETNEF (UCOMISS x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNEF) + v0 := b.NewValue0(v.Line, Op386UCOMISS, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeq64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq64F x y) + // cond: + // result: (SETNEF (UCOMISD x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNEF) + v0 := b.NewValue0(v.Line, Op386UCOMISD, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeq8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq8 x y) + // cond: + // result: (SETNE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeqB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NeqB x y) + // cond: + // result: (SETNE (CMPB x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386CMPB, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNeqPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NeqPtr x y) + // cond: + // result: (SETNE (CMPL x y)) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SETNE) + v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpNilCheck(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NilCheck ptr mem) + // cond: + // result: (LoweredNilCheck ptr mem) + for { + ptr := v.Args[0] + mem := v.Args[1] + v.reset(Op386LoweredNilCheck) + v.AddArg(ptr) + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpNot(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Not x) + // cond: + // result: (XORLconst [1] x) + for { + x := v.Args[0] + v.reset(Op386XORLconst) + v.AuxInt = 1 + v.AddArg(x) + return true + } +} +func rewriteValue386_Op386ORL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ORL x (MOVLconst [c])) + // cond: + // result: (ORLconst [c] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386ORLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ORL (MOVLconst [c]) x) + // cond: + // result: (ORLconst [c] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386ORLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (ORL x x) + // cond: + // result: x + for { + x := v.Args[0] + if x != v.Args[1] { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (ORL x0:(MOVBload [i] {s} p mem) s0:(SHLLconst [8] x1:(MOVBload [i+1] {s} p mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(s0) + // result: @mergePoint(b,x0,x1) (MOVWload [i] {s} p mem) + for { + x0 := v.Args[0] + if x0.Op != Op386MOVBload { + break + } + i := x0.AuxInt + s := x0.Aux + p := x0.Args[0] + mem := x0.Args[1] + s0 := v.Args[1] + if s0.Op != Op386SHLLconst { + break + } + if s0.AuxInt != 8 { + break + } + x1 := s0.Args[0] + if x1.Op != Op386MOVBload { + break + } + if x1.AuxInt != i+1 { + break + } + if x1.Aux != s { + break + } + if p != x1.Args[0] { + break + } + if mem != x1.Args[1] { + break + } + if !(x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0) && clobber(x1) && clobber(s0)) { + break + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(v.Line, Op386MOVWload, config.fe.TypeUInt16()) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = i + v0.Aux = s + v0.AddArg(p) + v0.AddArg(mem) + return true + } + // match: (ORL o0:(ORL o1:(ORL x0:(MOVBload [i] {s} p mem) s0:(SHLLconst [8] x1:(MOVBload [i+1] {s} p mem))) s1:(SHLLconst [16] x2:(MOVBload [i+2] {s} p mem))) s2:(SHLLconst [24] x3:(MOVBload [i+3] {s} p mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1) + // result: @mergePoint(b,x0,x1,x2,x3) (MOVLload [i] {s} p mem) + for { + o0 := v.Args[0] + if o0.Op != Op386ORL { + break + } + o1 := o0.Args[0] + if o1.Op != Op386ORL { + break + } + x0 := o1.Args[0] + if x0.Op != Op386MOVBload { + break + } + i := x0.AuxInt + s := x0.Aux + p := x0.Args[0] + mem := x0.Args[1] + s0 := o1.Args[1] + if s0.Op != Op386SHLLconst { + break + } + if s0.AuxInt != 8 { + break + } + x1 := s0.Args[0] + if x1.Op != Op386MOVBload { + break + } + if x1.AuxInt != i+1 { + break + } + if x1.Aux != s { + break + } + if p != x1.Args[0] { + break + } + if mem != x1.Args[1] { + break + } + s1 := o0.Args[1] + if s1.Op != Op386SHLLconst { + break + } + if s1.AuxInt != 16 { + break + } + x2 := s1.Args[0] + if x2.Op != Op386MOVBload { + break + } + if x2.AuxInt != i+2 { + break + } + if x2.Aux != s { + break + } + if p != x2.Args[0] { + break + } + if mem != x2.Args[1] { + break + } + s2 := v.Args[1] + if s2.Op != Op386SHLLconst { + break + } + if s2.AuxInt != 24 { + break + } + x3 := s2.Args[0] + if x3.Op != Op386MOVBload { + break + } + if x3.AuxInt != i+3 { + break + } + if x3.Aux != s { + break + } + if p != x3.Args[0] { + break + } + if mem != x3.Args[1] { + break + } + if !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) { + break + } + b = mergePoint(b, x0, x1, x2, x3) + v0 := b.NewValue0(v.Line, Op386MOVLload, config.fe.TypeUInt32()) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = i + v0.Aux = s + v0.AddArg(p) + v0.AddArg(mem) + return true + } + // match: (ORL x0:(MOVBloadidx1 [i] {s} p idx mem) s0:(SHLLconst [8] x1:(MOVBloadidx1 [i+1] {s} p idx mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(s0) + // result: @mergePoint(b,x0,x1) (MOVWloadidx1 [i] {s} p idx mem) + for { + x0 := v.Args[0] + if x0.Op != Op386MOVBloadidx1 { + break + } + i := x0.AuxInt + s := x0.Aux + p := x0.Args[0] + idx := x0.Args[1] + mem := x0.Args[2] + s0 := v.Args[1] + if s0.Op != Op386SHLLconst { + break + } + if s0.AuxInt != 8 { + break + } + x1 := s0.Args[0] + if x1.Op != Op386MOVBloadidx1 { + break + } + if x1.AuxInt != i+1 { + break + } + if x1.Aux != s { + break + } + if p != x1.Args[0] { + break + } + if idx != x1.Args[1] { + break + } + if mem != x1.Args[2] { + break + } + if !(x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && mergePoint(b, x0, x1) != nil && clobber(x0) && clobber(x1) && clobber(s0)) { + break + } + b = mergePoint(b, x0, x1) + v0 := b.NewValue0(v.Line, Op386MOVWloadidx1, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = i + v0.Aux = s + v0.AddArg(p) + v0.AddArg(idx) + v0.AddArg(mem) + return true + } + // match: (ORL o0:(ORL o1:(ORL x0:(MOVBloadidx1 [i] {s} p idx mem) s0:(SHLLconst [8] x1:(MOVBloadidx1 [i+1] {s} p idx mem))) s1:(SHLLconst [16] x2:(MOVBloadidx1 [i+2] {s} p idx mem))) s2:(SHLLconst [24] x3:(MOVBloadidx1 [i+3] {s} p idx mem))) + // cond: x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b,x0,x1,x2,x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1) + // result: @mergePoint(b,x0,x1,x2,x3) (MOVLloadidx1 [i] {s} p idx mem) + for { + o0 := v.Args[0] + if o0.Op != Op386ORL { + break + } + o1 := o0.Args[0] + if o1.Op != Op386ORL { + break + } + x0 := o1.Args[0] + if x0.Op != Op386MOVBloadidx1 { + break + } + i := x0.AuxInt + s := x0.Aux + p := x0.Args[0] + idx := x0.Args[1] + mem := x0.Args[2] + s0 := o1.Args[1] + if s0.Op != Op386SHLLconst { + break + } + if s0.AuxInt != 8 { + break + } + x1 := s0.Args[0] + if x1.Op != Op386MOVBloadidx1 { + break + } + if x1.AuxInt != i+1 { + break + } + if x1.Aux != s { + break + } + if p != x1.Args[0] { + break + } + if idx != x1.Args[1] { + break + } + if mem != x1.Args[2] { + break + } + s1 := o0.Args[1] + if s1.Op != Op386SHLLconst { + break + } + if s1.AuxInt != 16 { + break + } + x2 := s1.Args[0] + if x2.Op != Op386MOVBloadidx1 { + break + } + if x2.AuxInt != i+2 { + break + } + if x2.Aux != s { + break + } + if p != x2.Args[0] { + break + } + if idx != x2.Args[1] { + break + } + if mem != x2.Args[2] { + break + } + s2 := v.Args[1] + if s2.Op != Op386SHLLconst { + break + } + if s2.AuxInt != 24 { + break + } + x3 := s2.Args[0] + if x3.Op != Op386MOVBloadidx1 { + break + } + if x3.AuxInt != i+3 { + break + } + if x3.Aux != s { + break + } + if p != x3.Args[0] { + break + } + if idx != x3.Args[1] { + break + } + if mem != x3.Args[2] { + break + } + if !(x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && s2.Uses == 1 && o0.Uses == 1 && o1.Uses == 1 && mergePoint(b, x0, x1, x2, x3) != nil && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(s0) && clobber(s1) && clobber(s2) && clobber(o0) && clobber(o1)) { + break + } + b = mergePoint(b, x0, x1, x2, x3) + v0 := b.NewValue0(v.Line, Op386MOVLloadidx1, v.Type) + v.reset(OpCopy) + v.AddArg(v0) + v0.AuxInt = i + v0.Aux = s + v0.AddArg(p) + v0.AddArg(idx) + v0.AddArg(mem) + return true + } + return false +} +func rewriteValue386_Op386ORLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ORLconst [c] x) + // cond: int32(c)==0 + // result: x + for { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == 0) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (ORLconst [c] _) + // cond: int32(c)==-1 + // result: (MOVLconst [-1]) + for { + c := v.AuxInt + if !(int32(c) == -1) { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = -1 + return true + } + // match: (ORLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c|d]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = c | d + return true + } + return false +} +func rewriteValue386_OpOffPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (OffPtr [off] ptr) + // cond: is32Bit(off) + // result: (ADDLconst [off] ptr) + for { + off := v.AuxInt + ptr := v.Args[0] + if !(is32Bit(off)) { + break + } + v.reset(Op386ADDLconst) + v.AuxInt = off + v.AddArg(ptr) + return true + } + // match: (OffPtr [off] ptr) + // cond: + // result: (ADDL (MOVLconst [off]) ptr) + for { + off := v.AuxInt + ptr := v.Args[0] + v.reset(Op386ADDL) + v0 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32()) + v0.AuxInt = off + v.AddArg(v0) + v.AddArg(ptr) + return true + } +} +func rewriteValue386_OpOr16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or16 x y) + // cond: + // result: (ORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpOr32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or32 x y) + // cond: + // result: (ORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpOr8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or8 x y) + // cond: + // result: (ORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpOrB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (OrB x y) + // cond: + // result: (ORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_Op386ROLBconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ROLBconst [c] (ROLBconst [d] x)) + // cond: + // result: (ROLBconst [(c+d)& 7] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ROLBconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ROLBconst) + v.AuxInt = (c + d) & 7 + v.AddArg(x) + return true + } + // match: (ROLBconst [0] x) + // cond: + // result: x + for { + if v.AuxInt != 0 { + break + } + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386ROLLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ROLLconst [c] (ROLLconst [d] x)) + // cond: + // result: (ROLLconst [(c+d)&31] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ROLLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ROLLconst) + v.AuxInt = (c + d) & 31 + v.AddArg(x) + return true + } + // match: (ROLLconst [0] x) + // cond: + // result: x + for { + if v.AuxInt != 0 { + break + } + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386ROLWconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ROLWconst [c] (ROLWconst [d] x)) + // cond: + // result: (ROLWconst [(c+d)&15] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386ROLWconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386ROLWconst) + v.AuxInt = (c + d) & 15 + v.AddArg(x) + return true + } + // match: (ROLWconst [0] x) + // cond: + // result: x + for { + if v.AuxInt != 0 { + break + } + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_OpRsh16Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux16 x y) + // cond: + // result: (ANDL (SHRW x y) (SBBLcarrymask (CMPWconst y [16]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRW, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 16 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh16Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux32 x y) + // cond: + // result: (ANDL (SHRW x y) (SBBLcarrymask (CMPLconst y [16]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRW, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 16 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh16Ux8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux8 x y) + // cond: + // result: (ANDL (SHRW x y) (SBBLcarrymask (CMPBconst y [16]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRW, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 16 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh16x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x16 x y) + // cond: + // result: (SARW x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [16]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARW) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 16 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh16x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x32 x y) + // cond: + // result: (SARW x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [16]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARW) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 16 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh16x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x8 x y) + // cond: + // result: (SARW x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [16]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARW) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 16 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh32Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux16 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPWconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh32Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux32 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPLconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh32Ux8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux8 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPBconst y [32]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRL, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 32 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh32x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x16 x y) + // cond: + // result: (SARL x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [32]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARL) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 32 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh32x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x32 x y) + // cond: + // result: (SARL x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [32]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARL) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 32 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh32x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x8 x y) + // cond: + // result: (SARL x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [32]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARL) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 32 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh8Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8Ux16 x y) + // cond: + // result: (ANDL (SHRB x y) (SBBLcarrymask (CMPWconst y [8]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRB, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 8 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh8Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8Ux32 x y) + // cond: + // result: (ANDL (SHRB x y) (SBBLcarrymask (CMPLconst y [8]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRB, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 8 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh8Ux8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8Ux8 x y) + // cond: + // result: (ANDL (SHRB x y) (SBBLcarrymask (CMPBconst y [8]))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386ANDL) + v0 := b.NewValue0(v.Line, Op386SHRB, t) + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386SBBLcarrymask, t) + v2 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v2.AddArg(y) + v2.AuxInt = 8 + v1.AddArg(v2) + v.AddArg(v1) + return true + } +} +func rewriteValue386_OpRsh8x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8x16 x y) + // cond: + // result: (SARB x (ORL y (NOTL (SBBLcarrymask (CMPWconst y [8]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARB) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPWconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 8 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh8x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8x32 x y) + // cond: + // result: (SARB x (ORL y (NOTL (SBBLcarrymask (CMPLconst y [8]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARB) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPLconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 8 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_OpRsh8x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8x8 x y) + // cond: + // result: (SARB x (ORL y (NOTL (SBBLcarrymask (CMPBconst y [8]))))) + for { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SARB) + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, Op386ORL, y.Type) + v0.AddArg(y) + v1 := b.NewValue0(v.Line, Op386NOTL, y.Type) + v2 := b.NewValue0(v.Line, Op386SBBLcarrymask, y.Type) + v3 := b.NewValue0(v.Line, Op386CMPBconst, TypeFlags) + v3.AddArg(y) + v3.AuxInt = 8 + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } +} +func rewriteValue386_Op386SARB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARB x (MOVLconst [c])) + // cond: + // result: (SARBconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARBconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SARB x (MOVLconst [c])) + // cond: + // result: (SARBconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARBconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386SARBconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARBconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [d>>uint64(c)]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = d >> uint64(c) + return true + } + return false +} +func rewriteValue386_Op386SARL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARL x (MOVLconst [c])) + // cond: + // result: (SARLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SARL x (MOVLconst [c])) + // cond: + // result: (SARLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SARL x (ANDLconst [31] y)) + // cond: + // result: (SARL x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ANDLconst { + break + } + if v_1.AuxInt != 31 { + break + } + y := v_1.Args[0] + v.reset(Op386SARL) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386SARLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [d>>uint64(c)]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = d >> uint64(c) + return true + } + return false +} +func rewriteValue386_Op386SARW(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARW x (MOVLconst [c])) + // cond: + // result: (SARWconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARWconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SARW x (MOVLconst [c])) + // cond: + // result: (SARWconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SARWconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386SARWconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SARWconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [d>>uint64(c)]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = d >> uint64(c) + return true + } + return false +} +func rewriteValue386_Op386SBBLcarrymask(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SBBLcarrymask (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SBBLcarrymask (FlagLT_ULT)) + // cond: + // result: (MOVLconst [-1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = -1 + return true + } + // match: (SBBLcarrymask (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SBBLcarrymask (FlagGT_ULT)) + // cond: + // result: (MOVLconst [-1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = -1 + return true + } + // match: (SBBLcarrymask (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETA(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETA (InvertFlags x)) + // cond: + // result: (SETB x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETB) + v.AddArg(x) + return true + } + // match: (SETA (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETA (FlagLT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETA (FlagLT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETA (FlagGT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETA (FlagGT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + return false +} +func rewriteValue386_Op386SETAE(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETAE (InvertFlags x)) + // cond: + // result: (SETBE x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETBE) + v.AddArg(x) + return true + } + // match: (SETAE (FlagEQ)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETAE (FlagLT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETAE (FlagLT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETAE (FlagGT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETAE (FlagGT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + return false +} +func rewriteValue386_Op386SETB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETB (InvertFlags x)) + // cond: + // result: (SETA x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETA) + v.AddArg(x) + return true + } + // match: (SETB (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETB (FlagLT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETB (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETB (FlagGT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETB (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETBE(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETBE (InvertFlags x)) + // cond: + // result: (SETAE x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETAE) + v.AddArg(x) + return true + } + // match: (SETBE (FlagEQ)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETBE (FlagLT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETBE (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETBE (FlagGT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETBE (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETEQ(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETEQ (InvertFlags x)) + // cond: + // result: (SETEQ x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETEQ) + v.AddArg(x) + return true + } + // match: (SETEQ (FlagEQ)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETEQ (FlagLT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETEQ (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETEQ (FlagGT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETEQ (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETG(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETG (InvertFlags x)) + // cond: + // result: (SETL x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETL) + v.AddArg(x) + return true + } + // match: (SETG (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETG (FlagLT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETG (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETG (FlagGT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETG (FlagGT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + return false +} +func rewriteValue386_Op386SETGE(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETGE (InvertFlags x)) + // cond: + // result: (SETLE x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETLE) + v.AddArg(x) + return true + } + // match: (SETGE (FlagEQ)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETGE (FlagLT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETGE (FlagLT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETGE (FlagGT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETGE (FlagGT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + return false +} +func rewriteValue386_Op386SETL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETL (InvertFlags x)) + // cond: + // result: (SETG x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETG) + v.AddArg(x) + return true + } + // match: (SETL (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETL (FlagLT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETL (FlagLT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETL (FlagGT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETL (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETLE(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETLE (InvertFlags x)) + // cond: + // result: (SETGE x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETGE) + v.AddArg(x) + return true + } + // match: (SETLE (FlagEQ)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETLE (FlagLT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETLE (FlagLT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETLE (FlagGT_ULT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETLE (FlagGT_UGT)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SETNE(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SETNE (InvertFlags x)) + // cond: + // result: (SETNE x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386InvertFlags { + break + } + x := v_0.Args[0] + v.reset(Op386SETNE) + v.AddArg(x) + return true + } + // match: (SETNE (FlagEQ)) + // cond: + // result: (MOVLconst [0]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagEQ { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + // match: (SETNE (FlagLT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETNE (FlagLT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagLT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETNE (FlagGT_ULT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_ULT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + // match: (SETNE (FlagGT_UGT)) + // cond: + // result: (MOVLconst [1]) + for { + v_0 := v.Args[0] + if v_0.Op != Op386FlagGT_UGT { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 1 + return true + } + return false +} +func rewriteValue386_Op386SHLL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SHLL x (MOVLconst [c])) + // cond: + // result: (SHLLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHLLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHLL x (MOVLconst [c])) + // cond: + // result: (SHLLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHLLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHLL x (ANDLconst [31] y)) + // cond: + // result: (SHLL x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ANDLconst { + break + } + if v_1.AuxInt != 31 { + break + } + y := v_1.Args[0] + v.reset(Op386SHLL) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386SHRB(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SHRB x (MOVLconst [c])) + // cond: + // result: (SHRBconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRBconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHRB x (MOVLconst [c])) + // cond: + // result: (SHRBconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRBconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386SHRL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SHRL x (MOVLconst [c])) + // cond: + // result: (SHRLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHRL x (MOVLconst [c])) + // cond: + // result: (SHRLconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRLconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHRL x (ANDLconst [31] y)) + // cond: + // result: (SHRL x y) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386ANDLconst { + break + } + if v_1.AuxInt != 31 { + break + } + y := v_1.Args[0] + v.reset(Op386SHRL) + v.AddArg(x) + v.AddArg(y) + return true + } + return false +} +func rewriteValue386_Op386SHRW(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SHRW x (MOVLconst [c])) + // cond: + // result: (SHRWconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRWconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + // match: (SHRW x (MOVLconst [c])) + // cond: + // result: (SHRWconst [c&31] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SHRWconst) + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + return false +} +func rewriteValue386_Op386SUBL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SUBL x (MOVLconst [c])) + // cond: + // result: (SUBLconst x [c]) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386SUBLconst) + v.AddArg(x) + v.AuxInt = c + return true + } + // match: (SUBL (MOVLconst [c]) x) + // cond: + // result: (NEGL (SUBLconst x [c])) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386NEGL) + v0 := b.NewValue0(v.Line, Op386SUBLconst, v.Type) + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + // match: (SUBL x x) + // cond: + // result: (MOVLconst [0]) + for { + x := v.Args[0] + if x != v.Args[1] { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386SUBLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SUBLconst [c] x) + // cond: int32(c) == 0 + // result: x + for { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == 0) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (SUBLconst [c] x) + // cond: + // result: (ADDLconst [int64(int32(-c))] x) + for { + c := v.AuxInt + x := v.Args[0] + v.reset(Op386ADDLconst) + v.AuxInt = int64(int32(-c)) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpSignExt16to32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SignExt16to32 x) + // cond: + // result: (MOVWLSX x) + for { + x := v.Args[0] + v.reset(Op386MOVWLSX) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpSignExt8to16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SignExt8to16 x) + // cond: + // result: (MOVBLSX x) + for { + x := v.Args[0] + v.reset(Op386MOVBLSX) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpSignExt8to32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SignExt8to32 x) + // cond: + // result: (MOVBLSX x) + for { + x := v.Args[0] + v.reset(Op386MOVBLSX) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpSqrt(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sqrt x) + // cond: + // result: (SQRTSD x) + for { + x := v.Args[0] + v.reset(Op386SQRTSD) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpStaticCall(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (StaticCall [argwid] {target} mem) + // cond: + // result: (CALLstatic [argwid] {target} mem) + for { + argwid := v.AuxInt + target := v.Aux + mem := v.Args[0] + v.reset(Op386CALLstatic) + v.AuxInt = argwid + v.Aux = target + v.AddArg(mem) + return true + } +} +func rewriteValue386_OpStore(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Store [8] ptr val mem) + // cond: is64BitFloat(val.Type) + // result: (MOVSDstore ptr val mem) + for { + if v.AuxInt != 8 { + break + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is64BitFloat(val.Type)) { + break + } + v.reset(Op386MOVSDstore) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (Store [4] ptr val mem) + // cond: is32BitFloat(val.Type) + // result: (MOVSSstore ptr val mem) + for { + if v.AuxInt != 4 { + break + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32BitFloat(val.Type)) { + break + } + v.reset(Op386MOVSSstore) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (Store [4] ptr val mem) + // cond: + // result: (MOVLstore ptr val mem) + for { + if v.AuxInt != 4 { + break + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVLstore) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (Store [2] ptr val mem) + // cond: + // result: (MOVWstore ptr val mem) + for { + if v.AuxInt != 2 { + break + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVWstore) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + // match: (Store [1] ptr val mem) + // cond: + // result: (MOVBstore ptr val mem) + for { + if v.AuxInt != 1 { + break + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + v.reset(Op386MOVBstore) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_OpSub16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sub16 x y) + // cond: + // result: (SUBL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpSub32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sub32 x y) + // cond: + // result: (SUBL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpSub32F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sub32F x y) + // cond: + // result: (SUBSS x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBSS) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpSub64F(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sub64F x y) + // cond: + // result: (SUBSD x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBSD) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpSub8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Sub8 x y) + // cond: + // result: (SUBL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpSubPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (SubPtr x y) + // cond: + // result: (SUBL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386SUBL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpTrunc16to8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Trunc16to8 x) + // cond: + // result: x + for { + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } +} +func rewriteValue386_OpTrunc32to16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Trunc32to16 x) + // cond: + // result: x + for { + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } +} +func rewriteValue386_OpTrunc32to8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Trunc32to8 x) + // cond: + // result: x + for { + x := v.Args[0] + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } +} +func rewriteValue386_Op386XORL(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (XORL x (MOVLconst [c])) + // cond: + // result: (XORLconst [c] x) + for { + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386MOVLconst { + break + } + c := v_1.AuxInt + v.reset(Op386XORLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (XORL (MOVLconst [c]) x) + // cond: + // result: (XORLconst [c] x) + for { + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(Op386XORLconst) + v.AuxInt = c + v.AddArg(x) + return true + } + // match: (XORL x x) + // cond: + // result: (MOVLconst [0]) + for { + x := v.Args[0] + if x != v.Args[1] { + break + } + v.reset(Op386MOVLconst) + v.AuxInt = 0 + return true + } + return false +} +func rewriteValue386_Op386XORLconst(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (XORLconst [c] (XORLconst [d] x)) + // cond: + // result: (XORLconst [c ^ d] x) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386XORLconst { + break + } + d := v_0.AuxInt + x := v_0.Args[0] + v.reset(Op386XORLconst) + v.AuxInt = c ^ d + v.AddArg(x) + return true + } + // match: (XORLconst [c] x) + // cond: int32(c)==0 + // result: x + for { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == 0) { + break + } + v.reset(OpCopy) + v.Type = x.Type + v.AddArg(x) + return true + } + // match: (XORLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c^d]) + for { + c := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != Op386MOVLconst { + break + } + d := v_0.AuxInt + v.reset(Op386MOVLconst) + v.AuxInt = c ^ d + return true + } + return false +} +func rewriteValue386_OpXor16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Xor16 x y) + // cond: + // result: (XORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386XORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpXor32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Xor32 x y) + // cond: + // result: (XORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386XORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpXor8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Xor8 x y) + // cond: + // result: (XORL x y) + for { + x := v.Args[0] + y := v.Args[1] + v.reset(Op386XORL) + v.AddArg(x) + v.AddArg(y) + return true + } +} +func rewriteValue386_OpZero(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Zero [s] _ mem) + // cond: SizeAndAlign(s).Size() == 0 + // result: mem + for { + s := v.AuxInt + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 0) { + break + } + v.reset(OpCopy) + v.Type = mem.Type + v.AddArg(mem) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 1 + // result: (MOVBstoreconst [0] destptr mem) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 1) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = 0 + v.AddArg(destptr) + v.AddArg(mem) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 2 + // result: (MOVWstoreconst [0] destptr mem) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 2) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = 0 + v.AddArg(destptr) + v.AddArg(mem) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 4 + // result: (MOVLstoreconst [0] destptr mem) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 4) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = 0 + v.AddArg(destptr) + v.AddArg(mem) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 3 + // result: (MOVBstoreconst [makeValAndOff(0,2)] destptr (MOVWstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 3) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = makeValAndOff(0, 2) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVWstoreconst, TypeMem) + v0.AuxInt = 0 + v0.AddArg(destptr) + v0.AddArg(mem) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 5 + // result: (MOVBstoreconst [makeValAndOff(0,4)] destptr (MOVLstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 5) { + break + } + v.reset(Op386MOVBstoreconst) + v.AuxInt = makeValAndOff(0, 4) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = 0 + v0.AddArg(destptr) + v0.AddArg(mem) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 6 + // result: (MOVWstoreconst [makeValAndOff(0,4)] destptr (MOVLstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 6) { + break + } + v.reset(Op386MOVWstoreconst) + v.AuxInt = makeValAndOff(0, 4) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = 0 + v0.AddArg(destptr) + v0.AddArg(mem) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 7 + // result: (MOVLstoreconst [makeValAndOff(0,3)] destptr (MOVLstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 7) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(0, 3) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = 0 + v0.AddArg(destptr) + v0.AddArg(mem) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size()%4 != 0 && SizeAndAlign(s).Size() > 4 + // result: (Zero [SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%4] (ADDLconst destptr [SizeAndAlign(s).Size()%4]) (MOVLstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size()%4 != 0 && SizeAndAlign(s).Size() > 4) { + break + } + v.reset(OpZero) + v.AuxInt = SizeAndAlign(s).Size() - SizeAndAlign(s).Size()%4 + v0 := b.NewValue0(v.Line, Op386ADDLconst, config.fe.TypeUInt32()) + v0.AddArg(destptr) + v0.AuxInt = SizeAndAlign(s).Size() % 4 + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v1.AuxInt = 0 + v1.AddArg(destptr) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 8 + // result: (MOVLstoreconst [makeValAndOff(0,4)] destptr (MOVLstoreconst [0] destptr mem)) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 8) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(0, 4) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = 0 + v0.AddArg(destptr) + v0.AddArg(mem) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 12 + // result: (MOVLstoreconst [makeValAndOff(0,8)] destptr (MOVLstoreconst [makeValAndOff(0,4)] destptr (MOVLstoreconst [0] destptr mem))) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 12) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(0, 8) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = makeValAndOff(0, 4) + v0.AddArg(destptr) + v1 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v1.AuxInt = 0 + v1.AddArg(destptr) + v1.AddArg(mem) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: SizeAndAlign(s).Size() == 16 + // result: (MOVLstoreconst [makeValAndOff(0,12)] destptr (MOVLstoreconst [makeValAndOff(0,8)] destptr (MOVLstoreconst [makeValAndOff(0,4)] destptr (MOVLstoreconst [0] destptr mem)))) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(SizeAndAlign(s).Size() == 16) { + break + } + v.reset(Op386MOVLstoreconst) + v.AuxInt = makeValAndOff(0, 12) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v0.AuxInt = makeValAndOff(0, 8) + v0.AddArg(destptr) + v1 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v1.AuxInt = makeValAndOff(0, 4) + v1.AddArg(destptr) + v2 := b.NewValue0(v.Line, Op386MOVLstoreconst, TypeMem) + v2.AuxInt = 0 + v2.AddArg(destptr) + v2.AddArg(mem) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + // match: (Zero [s] destptr mem) + // cond: (SizeAndAlign(s).Size() > 1024 || (config.noDuffDevice && SizeAndAlign(s).Size() > 32)) && SizeAndAlign(s).Size()%8 == 0 + // result: (REPSTOSL destptr (MOVLconst [SizeAndAlign(s).Size()/8]) (MOVLconst [0]) mem) + for { + s := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !((SizeAndAlign(s).Size() > 1024 || (config.noDuffDevice && SizeAndAlign(s).Size() > 32)) && SizeAndAlign(s).Size()%8 == 0) { + break + } + v.reset(Op386REPSTOSL) + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32()) + v0.AuxInt = SizeAndAlign(s).Size() / 8 + v.AddArg(v0) + v1 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32()) + v1.AuxInt = 0 + v.AddArg(v1) + v.AddArg(mem) + return true + } + return false +} +func rewriteValue386_OpZeroExt16to32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ZeroExt16to32 x) + // cond: + // result: (MOVWLZX x) + for { + x := v.Args[0] + v.reset(Op386MOVWLZX) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpZeroExt8to16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ZeroExt8to16 x) + // cond: + // result: (MOVBLZX x) + for { + x := v.Args[0] + v.reset(Op386MOVBLZX) + v.AddArg(x) + return true + } +} +func rewriteValue386_OpZeroExt8to32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (ZeroExt8to32 x) + // cond: + // result: (MOVBLZX x) + for { + x := v.Args[0] + v.reset(Op386MOVBLZX) + v.AddArg(x) + return true + } +} +func rewriteBlock386(b *Block) bool { + switch b.Kind { + case Block386EQ: + // match: (EQ (InvertFlags cmp) yes no) + // cond: + // result: (EQ cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386EQ + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (EQ (FlagEQ) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (EQ (FlagLT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (EQ (FlagLT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (EQ (FlagGT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (EQ (FlagGT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + case Block386GE: + // match: (GE (InvertFlags cmp) yes no) + // cond: + // result: (LE cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (GE (FlagEQ) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (GE (FlagLT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (GE (FlagLT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (GE (FlagGT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (GE (FlagGT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + case Block386GT: + // match: (GT (InvertFlags cmp) yes no) + // cond: + // result: (LT cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (GT (FlagEQ) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (GT (FlagLT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (GT (FlagLT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (GT (FlagGT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (GT (FlagGT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + case BlockIf: + // match: (If (SETL cmp) yes no) + // cond: + // result: (LT cmp yes no) + for { + v := b.Control + if v.Op != Op386SETL { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETLE cmp) yes no) + // cond: + // result: (LE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETLE { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETG cmp) yes no) + // cond: + // result: (GT cmp yes no) + for { + v := b.Control + if v.Op != Op386SETG { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETGE cmp) yes no) + // cond: + // result: (GE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETGE { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETEQ cmp) yes no) + // cond: + // result: (EQ cmp yes no) + for { + v := b.Control + if v.Op != Op386SETEQ { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386EQ + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETNE cmp) yes no) + // cond: + // result: (NE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETNE { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETB cmp) yes no) + // cond: + // result: (ULT cmp yes no) + for { + v := b.Control + if v.Op != Op386SETB { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETBE cmp) yes no) + // cond: + // result: (ULE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETBE { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETA cmp) yes no) + // cond: + // result: (UGT cmp yes no) + for { + v := b.Control + if v.Op != Op386SETA { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETAE cmp) yes no) + // cond: + // result: (UGE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETAE { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETGF cmp) yes no) + // cond: + // result: (UGT cmp yes no) + for { + v := b.Control + if v.Op != Op386SETGF { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETGEF cmp) yes no) + // cond: + // result: (UGE cmp yes no) + for { + v := b.Control + if v.Op != Op386SETGEF { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETEQF cmp) yes no) + // cond: + // result: (EQF cmp yes no) + for { + v := b.Control + if v.Op != Op386SETEQF { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386EQF + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If (SETNEF cmp) yes no) + // cond: + // result: (NEF cmp yes no) + for { + v := b.Control + if v.Op != Op386SETNEF { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NEF + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (If cond yes no) + // cond: + // result: (NE (TESTB cond cond) yes no) + for { + v := b.Control + cond := b.Control + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NE + v0 := b.NewValue0(v.Line, Op386TESTB, TypeFlags) + v0.AddArg(cond) + v0.AddArg(cond) + b.SetControl(v0) + _ = yes + _ = no + return true + } + case Block386LE: + // match: (LE (InvertFlags cmp) yes no) + // cond: + // result: (GE cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (LE (FlagEQ) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (LE (FlagLT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (LE (FlagLT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (LE (FlagGT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (LE (FlagGT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + case Block386LT: + // match: (LT (InvertFlags cmp) yes no) + // cond: + // result: (GT cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (LT (FlagEQ) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (LT (FlagLT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (LT (FlagLT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (LT (FlagGT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (LT (FlagGT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + case Block386NE: + // match: (NE (TESTB (SETL cmp) (SETL cmp)) yes no) + // cond: + // result: (LT cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETL { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETL { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETLE cmp) (SETLE cmp)) yes no) + // cond: + // result: (LE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETLE { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETLE { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386LE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETG cmp) (SETG cmp)) yes no) + // cond: + // result: (GT cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETG { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETG { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETGE cmp) (SETGE cmp)) yes no) + // cond: + // result: (GE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETGE { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETGE { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386GE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETEQ cmp) (SETEQ cmp)) yes no) + // cond: + // result: (EQ cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETEQ { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETEQ { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386EQ + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETNE cmp) (SETNE cmp)) yes no) + // cond: + // result: (NE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETNE { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETNE { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETB cmp) (SETB cmp)) yes no) + // cond: + // result: (ULT cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETB { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETB { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETBE cmp) (SETBE cmp)) yes no) + // cond: + // result: (ULE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETBE { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETBE { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETA cmp) (SETA cmp)) yes no) + // cond: + // result: (UGT cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETA { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETA { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETAE cmp) (SETAE cmp)) yes no) + // cond: + // result: (UGE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETAE { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETAE { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETGF cmp) (SETGF cmp)) yes no) + // cond: + // result: (UGT cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETGF { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETGF { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETGEF cmp) (SETGEF cmp)) yes no) + // cond: + // result: (UGE cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETGEF { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETGEF { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETEQF cmp) (SETEQF cmp)) yes no) + // cond: + // result: (EQF cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETEQF { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETEQF { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386EQF + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (TESTB (SETNEF cmp) (SETNEF cmp)) yes no) + // cond: + // result: (NEF cmp yes no) + for { + v := b.Control + if v.Op != Op386TESTB { + break + } + v_0 := v.Args[0] + if v_0.Op != Op386SETNEF { + break + } + cmp := v_0.Args[0] + v_1 := v.Args[1] + if v_1.Op != Op386SETNEF { + break + } + if cmp != v_1.Args[0] { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NEF + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (InvertFlags cmp) yes no) + // cond: + // result: (NE cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386NE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (NE (FlagEQ) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (NE (FlagLT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (NE (FlagLT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (NE (FlagGT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (NE (FlagGT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + case Block386UGE: + // match: (UGE (InvertFlags cmp) yes no) + // cond: + // result: (ULE cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (UGE (FlagEQ) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (UGE (FlagLT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (UGE (FlagLT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (UGE (FlagGT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (UGE (FlagGT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + case Block386UGT: + // match: (UGT (InvertFlags cmp) yes no) + // cond: + // result: (ULT cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386ULT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (UGT (FlagEQ) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (UGT (FlagLT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (UGT (FlagLT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (UGT (FlagGT_ULT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (UGT (FlagGT_UGT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + case Block386ULE: + // match: (ULE (InvertFlags cmp) yes no) + // cond: + // result: (UGE cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGE + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (ULE (FlagEQ) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (ULE (FlagLT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (ULE (FlagLT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (ULE (FlagGT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (ULE (FlagGT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + case Block386ULT: + // match: (ULT (InvertFlags cmp) yes no) + // cond: + // result: (UGT cmp yes no) + for { + v := b.Control + if v.Op != Op386InvertFlags { + break + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = Block386UGT + b.SetControl(cmp) + _ = yes + _ = no + return true + } + // match: (ULT (FlagEQ) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagEQ { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (ULT (FlagLT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagLT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (ULT (FlagLT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagLT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + // match: (ULT (FlagGT_ULT) yes no) + // cond: + // result: (First nil yes no) + for { + v := b.Control + if v.Op != Op386FlagGT_ULT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + _ = yes + _ = no + return true + } + // match: (ULT (FlagGT_UGT) yes no) + // cond: + // result: (First nil no yes) + for { + v := b.Control + if v.Op != Op386FlagGT_UGT { + break + } + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockFirst + b.SetControl(nil) + b.swapSuccessors() + _ = no + _ = yes + return true + } + } + return false +} diff --git a/src/cmd/compile/internal/x86/galign.go b/src/cmd/compile/internal/x86/galign.go index 738d887742..a28b28742d 100644 --- a/src/cmd/compile/internal/x86/galign.go +++ b/src/cmd/compile/internal/x86/galign.go @@ -77,6 +77,11 @@ func Main() { gc.Thearch.Doregbits = doregbits gc.Thearch.Regnames = regnames + gc.Thearch.SSARegToReg = ssaRegToReg + gc.Thearch.SSAMarkMoves = ssaMarkMoves + gc.Thearch.SSAGenValue = ssaGenValue + gc.Thearch.SSAGenBlock = ssaGenBlock + gc.Main() gc.Exit(0) } diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go new file mode 100644 index 0000000000..efd2e566f8 --- /dev/null +++ b/src/cmd/compile/internal/x86/ssa.go @@ -0,0 +1,959 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x86 + +import ( + "fmt" + "math" + + "cmd/compile/internal/gc" + "cmd/compile/internal/ssa" + "cmd/internal/obj" + "cmd/internal/obj/x86" +) + +// Smallest possible faulting page at address zero. +const minZeroPage = 4096 + +// ssaRegToReg maps ssa register numbers to obj register numbers. +var ssaRegToReg = []int16{ + x86.REG_AX, + x86.REG_CX, + x86.REG_DX, + x86.REG_BX, + x86.REG_SP, + x86.REG_BP, + x86.REG_SI, + x86.REG_DI, + x86.REG_X0, + x86.REG_X1, + x86.REG_X2, + x86.REG_X3, + x86.REG_X4, + x86.REG_X5, + x86.REG_X6, + x86.REG_X7, + 0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case. +} + +// markMoves marks any MOVXconst ops that need to avoid clobbering flags. +func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) { + flive := b.FlagsLiveAtEnd + if b.Control != nil && b.Control.Type.IsFlags() { + flive = true + } + for i := len(b.Values) - 1; i >= 0; i-- { + v := b.Values[i] + if flive && v.Op == ssa.Op386MOVLconst { + // The "mark" is any non-nil Aux value. + v.Aux = v + } + if v.Type.IsFlags() { + flive = false + } + for _, a := range v.Args { + if a.Type.IsFlags() { + flive = true + } + } + } +} + +// loadByType returns the load instruction of the given type. +func loadByType(t ssa.Type) obj.As { + // Avoid partial register write + if !t.IsFloat() && t.Size() <= 2 { + if t.Size() == 1 { + return x86.AMOVBLZX + } else { + return x86.AMOVWLZX + } + } + // Otherwise, there's no difference between load and store opcodes. + return storeByType(t) +} + +// storeByType returns the store instruction of the given type. +func storeByType(t ssa.Type) obj.As { + width := t.Size() + if t.IsFloat() { + switch width { + case 4: + return x86.AMOVSS + case 8: + return x86.AMOVSD + } + } else { + switch width { + case 1: + return x86.AMOVB + case 2: + return x86.AMOVW + case 4: + return x86.AMOVL + } + } + panic("bad store type") +} + +// moveByType returns the reg->reg move instruction of the given type. +func moveByType(t ssa.Type) obj.As { + if t.IsFloat() { + // Moving the whole sse2 register is faster + // than moving just the correct low portion of it. + // There is no xmm->xmm move with 1 byte opcode, + // so use movups, which has 2 byte opcode. + return x86.AMOVUPS + } else { + switch t.Size() { + case 1: + // Avoids partial register write + return x86.AMOVL + case 2: + return x86.AMOVL + case 4: + return x86.AMOVL + case 16: + return x86.AMOVUPS // int128s are in SSE registers + default: + panic(fmt.Sprintf("bad int register width %d:%s", t.Size(), t)) + } + } +} + +// opregreg emits instructions for +// dest := dest(To) op src(From) +// and also returns the created obj.Prog so it +// may be further adjusted (offset, scale, etc). +func opregreg(op obj.As, dest, src int16) *obj.Prog { + p := gc.Prog(op) + p.From.Type = obj.TYPE_REG + p.To.Type = obj.TYPE_REG + p.To.Reg = dest + p.From.Reg = src + return p +} + +func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { + s.SetLineno(v.Line) + switch v.Op { + case ssa.Op386ADDL: + r := gc.SSARegNum(v) + r1 := gc.SSARegNum(v.Args[0]) + r2 := gc.SSARegNum(v.Args[1]) + switch { + case r == r1: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r2 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case r == r2: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + default: + p := gc.Prog(x86.ALEAL) + p.From.Type = obj.TYPE_MEM + p.From.Reg = r1 + p.From.Scale = 1 + p.From.Index = r2 + p.To.Type = obj.TYPE_REG + p.To.Reg = r + } + // 2-address opcode arithmetic + case ssa.Op386SUBL, + ssa.Op386MULL, + ssa.Op386ANDL, + ssa.Op386ORL, + ssa.Op386XORL, + ssa.Op386SHLL, + ssa.Op386SHRL, ssa.Op386SHRW, ssa.Op386SHRB, + ssa.Op386SARL, ssa.Op386SARW, ssa.Op386SARB, + ssa.Op386ADDSS, ssa.Op386ADDSD, ssa.Op386SUBSS, ssa.Op386SUBSD, + ssa.Op386MULSS, ssa.Op386MULSD, ssa.Op386DIVSS, ssa.Op386DIVSD, + ssa.Op386PXOR: + r := gc.SSARegNum(v) + if r != gc.SSARegNum(v.Args[0]) { + v.Fatalf("input[0] and output not in same register %s", v.LongString()) + } + opregreg(v.Op.Asm(), r, gc.SSARegNum(v.Args[1])) + + case ssa.Op386DIVL, ssa.Op386DIVW, + ssa.Op386DIVLU, ssa.Op386DIVWU, + ssa.Op386MODL, ssa.Op386MODW, + ssa.Op386MODLU, ssa.Op386MODWU: + + // Arg[0] is already in AX as it's the only register we allow + // and AX is the only output + x := gc.SSARegNum(v.Args[1]) + + // CPU faults upon signed overflow, which occurs when most + // negative int is divided by -1. + var j *obj.Prog + if v.Op == ssa.Op386DIVL || v.Op == ssa.Op386DIVW || + v.Op == ssa.Op386MODL || v.Op == ssa.Op386MODW { + + var c *obj.Prog + switch v.Op { + case ssa.Op386DIVL, ssa.Op386MODL: + c = gc.Prog(x86.ACMPL) + j = gc.Prog(x86.AJEQ) + gc.Prog(x86.ACDQ) //TODO: fix + + case ssa.Op386DIVW, ssa.Op386MODW: + c = gc.Prog(x86.ACMPW) + j = gc.Prog(x86.AJEQ) + gc.Prog(x86.ACWD) + } + c.From.Type = obj.TYPE_REG + c.From.Reg = x + c.To.Type = obj.TYPE_CONST + c.To.Offset = -1 + + j.To.Type = obj.TYPE_BRANCH + } + + // for unsigned ints, we sign extend by setting DX = 0 + // signed ints were sign extended above + if v.Op == ssa.Op386DIVLU || v.Op == ssa.Op386MODLU || + v.Op == ssa.Op386DIVWU || v.Op == ssa.Op386MODWU { + c := gc.Prog(x86.AXORL) + c.From.Type = obj.TYPE_REG + c.From.Reg = x86.REG_DX + c.To.Type = obj.TYPE_REG + c.To.Reg = x86.REG_DX + } + + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = x + + // signed division, rest of the check for -1 case + if j != nil { + j2 := gc.Prog(obj.AJMP) + j2.To.Type = obj.TYPE_BRANCH + + var n *obj.Prog + if v.Op == ssa.Op386DIVL || v.Op == ssa.Op386DIVW { + // n * -1 = -n + n = gc.Prog(x86.ANEGL) + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_AX + } else { + // n % -1 == 0 + n = gc.Prog(x86.AXORL) + n.From.Type = obj.TYPE_REG + n.From.Reg = x86.REG_DX + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_DX + } + + j.To.Val = n + j2.To.Val = s.Pc() + } + + case ssa.Op386HMULL, ssa.Op386HMULW, ssa.Op386HMULB, + ssa.Op386HMULLU, ssa.Op386HMULWU, ssa.Op386HMULBU: + // the frontend rewrites constant division by 8/16/32 bit integers into + // HMUL by a constant + // SSA rewrites generate the 64 bit versions + + // Arg[0] is already in AX as it's the only register we allow + // and DX is the only output we care about (the high bits) + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = gc.SSARegNum(v.Args[1]) + + // IMULB puts the high portion in AH instead of DL, + // so move it to DL for consistency + if v.Type.Size() == 1 { + m := gc.Prog(x86.AMOVB) + m.From.Type = obj.TYPE_REG + m.From.Reg = x86.REG_AH + m.To.Type = obj.TYPE_REG + m.To.Reg = x86.REG_DX + } + + case ssa.Op386ADDLconst: + r := gc.SSARegNum(v) + a := gc.SSARegNum(v.Args[0]) + if r == a { + if v.AuxInt == 1 { + p := gc.Prog(x86.AINCL) + p.To.Type = obj.TYPE_REG + p.To.Reg = r + return + } + if v.AuxInt == -1 { + p := gc.Prog(x86.ADECL) + p.To.Type = obj.TYPE_REG + p.To.Reg = r + return + } + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + return + } + p := gc.Prog(x86.ALEAL) + p.From.Type = obj.TYPE_MEM + p.From.Reg = a + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + + case ssa.Op386MULLconst: + r := gc.SSARegNum(v) + if r != gc.SSARegNum(v.Args[0]) { + v.Fatalf("input[0] and output not in same register %s", v.LongString()) + } + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + // TODO: Teach doasm to compile the three-address multiply imul $c, r1, r2 + // then we don't need to use resultInArg0 for these ops. + //p.From3 = new(obj.Addr) + //p.From3.Type = obj.TYPE_REG + //p.From3.Reg = gc.SSARegNum(v.Args[0]) + + case ssa.Op386SUBLconst, + ssa.Op386ANDLconst, + ssa.Op386ORLconst, + ssa.Op386XORLconst, + ssa.Op386SHLLconst, + ssa.Op386SHRLconst, ssa.Op386SHRWconst, ssa.Op386SHRBconst, + ssa.Op386SARLconst, ssa.Op386SARWconst, ssa.Op386SARBconst, + ssa.Op386ROLLconst, ssa.Op386ROLWconst, ssa.Op386ROLBconst: + r := gc.SSARegNum(v) + if r != gc.SSARegNum(v.Args[0]) { + v.Fatalf("input[0] and output not in same register %s", v.LongString()) + } + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.Op386SBBLcarrymask: + r := gc.SSARegNum(v) + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.Op386LEAL1, ssa.Op386LEAL2, ssa.Op386LEAL4, ssa.Op386LEAL8: + r := gc.SSARegNum(v.Args[0]) + i := gc.SSARegNum(v.Args[1]) + p := gc.Prog(x86.ALEAL) + switch v.Op { + case ssa.Op386LEAL1: + p.From.Scale = 1 + if i == x86.REG_SP { + r, i = i, r + } + case ssa.Op386LEAL2: + p.From.Scale = 2 + case ssa.Op386LEAL4: + p.From.Scale = 4 + case ssa.Op386LEAL8: + p.From.Scale = 8 + } + p.From.Type = obj.TYPE_MEM + p.From.Reg = r + p.From.Index = i + gc.AddAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386LEAL: + p := gc.Prog(x86.ALEAL) + p.From.Type = obj.TYPE_MEM + p.From.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386CMPL, ssa.Op386CMPW, ssa.Op386CMPB, + ssa.Op386TESTL, ssa.Op386TESTW, ssa.Op386TESTB: + opregreg(v.Op.Asm(), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[0])) + case ssa.Op386UCOMISS, ssa.Op386UCOMISD: + // Go assembler has swapped operands for UCOMISx relative to CMP, + // must account for that right here. + opregreg(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1])) + case ssa.Op386CMPLconst, ssa.Op386CMPWconst, ssa.Op386CMPBconst: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = gc.SSARegNum(v.Args[0]) + p.To.Type = obj.TYPE_CONST + p.To.Offset = v.AuxInt + case ssa.Op386TESTLconst, ssa.Op386TESTWconst, ssa.Op386TESTBconst: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v.Args[0]) + case ssa.Op386MOVLconst: + x := gc.SSARegNum(v) + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = x + // If flags are live at this instruction, suppress the + // MOV $0,AX -> XOR AX,AX optimization. + if v.Aux != nil { + p.Mark |= x86.PRESERVEFLAGS + } + case ssa.Op386MOVSSconst, ssa.Op386MOVSDconst: + x := gc.SSARegNum(v) + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_FCONST + p.From.Val = math.Float64frombits(uint64(v.AuxInt)) + p.To.Type = obj.TYPE_REG + p.To.Reg = x + case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVLload, ssa.Op386MOVWload, ssa.Op386MOVBload, ssa.Op386MOVBLSXload, ssa.Op386MOVWLSXload, ssa.Op386MOVOload: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386MOVSDloadidx8: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.From, v) + p.From.Scale = 8 + p.From.Index = gc.SSARegNum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386MOVLloadidx4, ssa.Op386MOVSSloadidx4: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.From, v) + p.From.Scale = 4 + p.From.Index = gc.SSARegNum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386MOVWloadidx2: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.From, v) + p.From.Scale = 2 + p.From.Index = gc.SSARegNum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386MOVBloadidx1, ssa.Op386MOVWloadidx1, ssa.Op386MOVLloadidx1, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1: + r := gc.SSARegNum(v.Args[0]) + i := gc.SSARegNum(v.Args[1]) + if i == x86.REG_SP { + r, i = i, r + } + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = r + p.From.Scale = 1 + p.From.Index = i + gc.AddAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + case ssa.Op386MOVSSstore, ssa.Op386MOVSDstore, ssa.Op386MOVLstore, ssa.Op386MOVWstore, ssa.Op386MOVBstore, ssa.Op386MOVOstore: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = gc.SSARegNum(v.Args[1]) + p.To.Type = obj.TYPE_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.To, v) + case ssa.Op386MOVSDstoreidx8: + 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_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + p.To.Scale = 8 + p.To.Index = gc.SSARegNum(v.Args[1]) + gc.AddAux(&p.To, v) + case ssa.Op386MOVSSstoreidx4, ssa.Op386MOVLstoreidx4: + 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_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + p.To.Scale = 4 + p.To.Index = gc.SSARegNum(v.Args[1]) + gc.AddAux(&p.To, v) + case ssa.Op386MOVWstoreidx2: + 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_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + p.To.Scale = 2 + p.To.Index = gc.SSARegNum(v.Args[1]) + gc.AddAux(&p.To, v) + case ssa.Op386MOVBstoreidx1, ssa.Op386MOVWstoreidx1, ssa.Op386MOVLstoreidx1, ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1: + r := gc.SSARegNum(v.Args[0]) + i := gc.SSARegNum(v.Args[1]) + if i == x86.REG_SP { + r, i = i, r + } + 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_MEM + p.To.Reg = r + p.To.Scale = 1 + p.To.Index = i + gc.AddAux(&p.To, v) + case ssa.Op386MOVLstoreconst, ssa.Op386MOVWstoreconst, ssa.Op386MOVBstoreconst: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + sc := v.AuxValAndOff() + p.From.Offset = sc.Val() + p.To.Type = obj.TYPE_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux2(&p.To, v, sc.Off()) + case ssa.Op386MOVLstoreconstidx1, ssa.Op386MOVLstoreconstidx4, ssa.Op386MOVWstoreconstidx1, ssa.Op386MOVWstoreconstidx2, ssa.Op386MOVBstoreconstidx1: + p := gc.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + sc := v.AuxValAndOff() + p.From.Offset = sc.Val() + r := gc.SSARegNum(v.Args[0]) + i := gc.SSARegNum(v.Args[1]) + switch v.Op { + case ssa.Op386MOVBstoreconstidx1, ssa.Op386MOVWstoreconstidx1, ssa.Op386MOVLstoreconstidx1: + p.To.Scale = 1 + if i == x86.REG_SP { + r, i = i, r + } + case ssa.Op386MOVWstoreconstidx2: + p.To.Scale = 2 + case ssa.Op386MOVLstoreconstidx4: + p.To.Scale = 4 + } + p.To.Type = obj.TYPE_MEM + p.To.Reg = r + p.To.Index = i + gc.AddAux2(&p.To, v, sc.Off()) + case ssa.Op386MOVWLSX, ssa.Op386MOVBLSX, ssa.Op386MOVWLZX, ssa.Op386MOVBLZX, + ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD, + ssa.Op386CVTTSS2SL, ssa.Op386CVTTSD2SL, + ssa.Op386CVTSS2SD, ssa.Op386CVTSD2SS: + opregreg(v.Op.Asm(), gc.SSARegNum(v), gc.SSARegNum(v.Args[0])) + case ssa.Op386DUFFZERO: + p := gc.Prog(obj.ADUFFZERO) + p.To.Type = obj.TYPE_ADDR + p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg)) + p.To.Offset = v.AuxInt + case ssa.Op386MOVOconst: + if v.AuxInt != 0 { + v.Unimplementedf("MOVOconst can only do constant=0") + } + r := gc.SSARegNum(v) + opregreg(x86.AXORPS, r, r) + case ssa.Op386DUFFCOPY: + p := gc.Prog(obj.ADUFFCOPY) + p.To.Type = obj.TYPE_ADDR + p.To.Sym = gc.Linksym(gc.Pkglookup("duffcopy", gc.Runtimepkg)) + p.To.Offset = v.AuxInt + + case ssa.OpCopy, ssa.Op386MOVLconvert: // TODO: use MOVLreg for reg->reg copies instead of OpCopy? + if v.Type.IsMemory() { + return + } + x := gc.SSARegNum(v.Args[0]) + y := gc.SSARegNum(v) + if x != y { + opregreg(moveByType(v.Type), y, x) + } + case ssa.OpLoadReg: + if v.Type.IsFlags() { + v.Unimplementedf("load flags not implemented: %v", v.LongString()) + return + } + p := gc.Prog(loadByType(v.Type)) + n, off := gc.AutoVar(v.Args[0]) + p.From.Type = obj.TYPE_MEM + p.From.Node = n + p.From.Sym = gc.Linksym(n.Sym) + p.From.Offset = off + if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT { + p.From.Name = obj.NAME_PARAM + p.From.Offset += n.Xoffset + } else { + p.From.Name = obj.NAME_AUTO + } + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + + case ssa.OpStoreReg: + if v.Type.IsFlags() { + v.Unimplementedf("store flags not implemented: %v", v.LongString()) + return + } + p := gc.Prog(storeByType(v.Type)) + p.From.Type = obj.TYPE_REG + p.From.Reg = gc.SSARegNum(v.Args[0]) + n, off := gc.AutoVar(v) + p.To.Type = obj.TYPE_MEM + p.To.Node = n + p.To.Sym = gc.Linksym(n.Sym) + p.To.Offset = off + if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT { + p.To.Name = obj.NAME_PARAM + p.To.Offset += n.Xoffset + } else { + p.To.Name = obj.NAME_AUTO + } + case ssa.OpPhi: + gc.CheckLoweredPhi(v) + case ssa.OpInitMem: + // memory arg needs no code + case ssa.OpArg: + // input args need no code + case ssa.Op386LoweredGetClosurePtr: + // Closure pointer is DX. + gc.CheckLoweredGetClosurePtr(v) + case ssa.Op386LoweredGetG: + r := gc.SSARegNum(v) + // See the comments in cmd/internal/obj/x86/obj6.go + // near CanUse1InsnTLS for a detailed explanation of these instructions. + if x86.CanUse1InsnTLS(gc.Ctxt) { + // MOVQ (TLS), r + p := gc.Prog(x86.AMOVL) + p.From.Type = obj.TYPE_MEM + p.From.Reg = x86.REG_TLS + p.To.Type = obj.TYPE_REG + p.To.Reg = r + } else { + // MOVQ TLS, r + // MOVQ (r)(TLS*1), r + p := gc.Prog(x86.AMOVL) + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_TLS + p.To.Type = obj.TYPE_REG + p.To.Reg = r + q := gc.Prog(x86.AMOVL) + q.From.Type = obj.TYPE_MEM + q.From.Reg = r + q.From.Index = x86.REG_TLS + q.From.Scale = 1 + q.To.Type = obj.TYPE_REG + q.To.Reg = r + } + case ssa.Op386CALLstatic: + if v.Aux.(*gc.Sym) == gc.Deferreturn.Sym { + // Deferred calls will appear to be returning to + // the CALL deferreturn(SB) that we are about to emit. + // However, the stack trace code will show the line + // of the instruction byte before the return PC. + // To avoid that being an unrelated instruction, + // insert an actual hardware NOP that will have the right line number. + // This is different from obj.ANOP, which is a virtual no-op + // that doesn't make it into the instruction stream. + ginsnop() + } + p := gc.Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = gc.Linksym(v.Aux.(*gc.Sym)) + if gc.Maxarg < v.AuxInt { + gc.Maxarg = v.AuxInt + } + case ssa.Op386CALLclosure: + p := gc.Prog(obj.ACALL) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v.Args[0]) + if gc.Maxarg < v.AuxInt { + gc.Maxarg = v.AuxInt + } + case ssa.Op386CALLdefer: + p := gc.Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = gc.Linksym(gc.Deferproc.Sym) + if gc.Maxarg < v.AuxInt { + gc.Maxarg = v.AuxInt + } + case ssa.Op386CALLgo: + p := gc.Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = gc.Linksym(gc.Newproc.Sym) + if gc.Maxarg < v.AuxInt { + gc.Maxarg = v.AuxInt + } + case ssa.Op386CALLinter: + p := gc.Prog(obj.ACALL) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v.Args[0]) + if gc.Maxarg < v.AuxInt { + gc.Maxarg = v.AuxInt + } + case ssa.Op386NEGL, + ssa.Op386BSWAPL, + ssa.Op386NOTL: + r := gc.SSARegNum(v) + if r != gc.SSARegNum(v.Args[0]) { + v.Fatalf("input[0] and output not in same register %s", v.LongString()) + } + p := gc.Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.Op386BSFL, ssa.Op386BSFW, + ssa.Op386BSRL, ssa.Op386BSRW, + ssa.Op386SQRTSD: + p := gc.Prog(v.Op.Asm()) + 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) + case ssa.OpSP, ssa.OpSB: + // nothing to do + case ssa.Op386SETEQ, ssa.Op386SETNE, + ssa.Op386SETL, ssa.Op386SETLE, + ssa.Op386SETG, ssa.Op386SETGE, + ssa.Op386SETGF, ssa.Op386SETGEF, + ssa.Op386SETB, ssa.Op386SETBE, + ssa.Op386SETORD, ssa.Op386SETNAN, + ssa.Op386SETA, ssa.Op386SETAE: + p := gc.Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + + case ssa.Op386SETNEF: + p := gc.Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + q := gc.Prog(x86.ASETPS) + q.To.Type = obj.TYPE_REG + q.To.Reg = x86.REG_AX + opregreg(x86.AORL, gc.SSARegNum(v), x86.REG_AX) + + case ssa.Op386SETEQF: + p := gc.Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = gc.SSARegNum(v) + q := gc.Prog(x86.ASETPC) + q.To.Type = obj.TYPE_REG + q.To.Reg = x86.REG_AX + opregreg(x86.AANDL, gc.SSARegNum(v), x86.REG_AX) + + case ssa.Op386InvertFlags: + v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString()) + case ssa.Op386FlagEQ, ssa.Op386FlagLT_ULT, ssa.Op386FlagLT_UGT, ssa.Op386FlagGT_ULT, ssa.Op386FlagGT_UGT: + v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString()) + case ssa.Op386REPSTOSL: + gc.Prog(x86.AREP) + gc.Prog(x86.ASTOSL) + case ssa.Op386REPMOVSL: + gc.Prog(x86.AREP) + gc.Prog(x86.AMOVSL) + case ssa.OpVarDef: + gc.Gvardef(v.Aux.(*gc.Node)) + case ssa.OpVarKill: + gc.Gvarkill(v.Aux.(*gc.Node)) + case ssa.OpVarLive: + gc.Gvarlive(v.Aux.(*gc.Node)) + case ssa.OpKeepAlive: + if !v.Args[0].Type.IsPtrShaped() { + v.Fatalf("keeping non-pointer alive %v", v.Args[0]) + } + n, off := gc.AutoVar(v.Args[0]) + if n == nil { + v.Fatalf("KeepLive with non-spilled value %s %s", v, v.Args[0]) + } + if off != 0 { + v.Fatalf("KeepLive with non-zero offset spill location %s:%d", n, off) + } + gc.Gvarlive(n) + case ssa.Op386LoweredNilCheck: + // Optimization - if the subsequent block has a load or store + // at the same address, we don't need to issue this instruction. + mem := v.Args[1] + for _, w := range v.Block.Succs[0].Block().Values { + if w.Op == ssa.OpPhi { + if w.Type.IsMemory() { + mem = w + } + continue + } + if len(w.Args) == 0 || !w.Args[len(w.Args)-1].Type.IsMemory() { + // w doesn't use a store - can't be a memory op. + continue + } + if w.Args[len(w.Args)-1] != mem { + v.Fatalf("wrong store after nilcheck v=%s w=%s", v, w) + } + switch w.Op { + case ssa.Op386MOVLload, ssa.Op386MOVWload, ssa.Op386MOVBload, + ssa.Op386MOVLstore, ssa.Op386MOVWstore, ssa.Op386MOVBstore, + ssa.Op386MOVBLSXload, ssa.Op386MOVWLSXload, + ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVOload, + ssa.Op386MOVSSstore, ssa.Op386MOVSDstore, ssa.Op386MOVOstore: + if w.Args[0] == v.Args[0] && w.Aux == nil && w.AuxInt >= 0 && w.AuxInt < minZeroPage { + if gc.Debug_checknil != 0 && int(v.Line) > 1 { + gc.Warnl(v.Line, "removed nil check") + } + return + } + case ssa.Op386MOVLstoreconst, ssa.Op386MOVWstoreconst, ssa.Op386MOVBstoreconst: + off := ssa.ValAndOff(v.AuxInt).Off() + if w.Args[0] == v.Args[0] && w.Aux == nil && off >= 0 && off < minZeroPage { + if gc.Debug_checknil != 0 && int(v.Line) > 1 { + gc.Warnl(v.Line, "removed nil check") + } + return + } + } + if w.Type.IsMemory() { + if w.Op == ssa.OpVarDef || w.Op == ssa.OpVarKill || w.Op == ssa.OpVarLive { + // these ops are OK + mem = w + continue + } + // We can't delay the nil check past the next store. + break + } + } + // Issue a load which will fault if the input is nil. + // TODO: We currently use the 2-byte instruction TESTB AX, (reg). + // Should we use the 3-byte TESTB $0, (reg) instead? It is larger + // but it doesn't have false dependency on AX. + // Or maybe allocate an output register and use MOVL (reg),reg2 ? + // That trades clobbering flags for clobbering a register. + p := gc.Prog(x86.ATESTB) + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_AX + p.To.Type = obj.TYPE_MEM + p.To.Reg = gc.SSARegNum(v.Args[0]) + gc.AddAux(&p.To, v) + if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + gc.Warnl(v.Line, "generated nil check") + } + default: + v.Unimplementedf("genValue not implemented: %s", v.LongString()) + } +} + +var blockJump = [...]struct { + asm, invasm obj.As +}{ + ssa.Block386EQ: {x86.AJEQ, x86.AJNE}, + ssa.Block386NE: {x86.AJNE, x86.AJEQ}, + ssa.Block386LT: {x86.AJLT, x86.AJGE}, + ssa.Block386GE: {x86.AJGE, x86.AJLT}, + ssa.Block386LE: {x86.AJLE, x86.AJGT}, + ssa.Block386GT: {x86.AJGT, x86.AJLE}, + ssa.Block386ULT: {x86.AJCS, x86.AJCC}, + ssa.Block386UGE: {x86.AJCC, x86.AJCS}, + ssa.Block386UGT: {x86.AJHI, x86.AJLS}, + ssa.Block386ULE: {x86.AJLS, x86.AJHI}, + ssa.Block386ORD: {x86.AJPC, x86.AJPS}, + ssa.Block386NAN: {x86.AJPS, x86.AJPC}, +} + +var eqfJumps = [2][2]gc.FloatingEQNEJump{ + {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPS, Index: 1}}, // next == b.Succs[0] + {{Jump: x86.AJNE, Index: 1}, {Jump: x86.AJPC, Index: 0}}, // next == b.Succs[1] +} +var nefJumps = [2][2]gc.FloatingEQNEJump{ + {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPC, Index: 1}}, // next == b.Succs[0] + {{Jump: x86.AJNE, Index: 0}, {Jump: x86.AJPS, Index: 0}}, // next == b.Succs[1] +} + +func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) { + s.SetLineno(b.Line) + + switch b.Kind { + case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck: + if b.Succs[0].Block() != next { + p := gc.Prog(obj.AJMP) + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) + } + case ssa.BlockDefer: + // defer returns in rax: + // 0 if we should continue executing + // 1 if we should jump to deferreturn call + p := gc.Prog(x86.ATESTL) + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_AX + p.To.Type = obj.TYPE_REG + p.To.Reg = x86.REG_AX + p = gc.Prog(x86.AJNE) + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()}) + if b.Succs[0].Block() != next { + p := gc.Prog(obj.AJMP) + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) + } + case ssa.BlockExit: + gc.Prog(obj.AUNDEF) // tell plive.go that we never reach here + case ssa.BlockRet: + gc.Prog(obj.ARET) + case ssa.BlockRetJmp: + p := gc.Prog(obj.AJMP) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = gc.Linksym(b.Aux.(*gc.Sym)) + + case ssa.Block386EQF: + gc.SSAGenFPJump(s, b, next, &eqfJumps) + + case ssa.Block386NEF: + gc.SSAGenFPJump(s, b, next, &nefJumps) + + case ssa.Block386EQ, ssa.Block386NE, + ssa.Block386LT, ssa.Block386GE, + ssa.Block386LE, ssa.Block386GT, + ssa.Block386ULT, ssa.Block386UGT, + ssa.Block386ULE, ssa.Block386UGE: + jmp := blockJump[b.Kind] + likely := b.Likely + var p *obj.Prog + switch next { + case b.Succs[0].Block(): + p = gc.Prog(jmp.invasm) + likely *= -1 + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()}) + case b.Succs[1].Block(): + p = gc.Prog(jmp.asm) + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) + default: + p = gc.Prog(jmp.asm) + p.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()}) + q := gc.Prog(obj.AJMP) + q.To.Type = obj.TYPE_BRANCH + s.Branches = append(s.Branches, gc.Branch{P: q, B: b.Succs[1].Block()}) + } + + // liblink reorders the instruction stream as it sees fit. + // Pass along what we know so liblink can make use of it. + // TODO: Once we've fully switched to SSA, + // make liblink leave our output alone. + switch likely { + case ssa.BranchUnlikely: + p.From.Type = obj.TYPE_CONST + p.From.Offset = 0 + case ssa.BranchLikely: + p.From.Type = obj.TYPE_CONST + p.From.Offset = 1 + } + + default: + b.Unimplementedf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString()) + } +} -- 2.48.1