...

Text file src/cmd/compile/internal/ssa/gen/MIPS64.rules

     1	// Copyright 2016 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	(Add(Ptr|64|32|16|8) x y) -> (ADDV x y)
     6	(Add(32|64)F x y) -> (ADD(F|D) x y)
     7	
     8	(Sub(Ptr|64|32|16|8) x y) -> (SUBV x y)
     9	(Sub(32|64)F x y) -> (SUB(F|D) x y)
    10	
    11	(Mul(64|32|16|8) x y) -> (Select1 (MULVU x y))
    12	(Mul(32|64)F x y) -> (MUL(F|D) x y)
    13	
    14	(Hmul64 x y) -> (Select0 (MULV x y))
    15	(Hmul64u x y) -> (Select0 (MULVU x y))
    16	(Hmul32 x y) -> (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
    17	(Hmul32u x y) -> (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
    18	
    19	(Div64 x y) -> (Select1 (DIVV x y))
    20	(Div64u x y) -> (Select1 (DIVVU x y))
    21	(Div32 x y) -> (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
    22	(Div32u x y) -> (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
    23	(Div16 x y) -> (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
    24	(Div16u x y) -> (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
    25	(Div8 x y) -> (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
    26	(Div8u x y) -> (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
    27	(Div(32|64)F x y) -> (DIV(F|D) x y)
    28	
    29	(Mod64 x y) -> (Select0 (DIVV x y))
    30	(Mod64u x y) -> (Select0 (DIVVU x y))
    31	(Mod32 x y) -> (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
    32	(Mod32u x y) -> (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
    33	(Mod16 x y) -> (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
    34	(Mod16u x y) -> (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
    35	(Mod8 x y) -> (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
    36	(Mod8u x y) -> (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
    37	
    38	// (x + y) / 2 with x>=y -> (x - y) / 2 + y
    39	(Avg64u <t> x y) -> (ADDV (SRLVconst <t> (SUBV <t> x y) [1]) y)
    40	
    41	(And(64|32|16|8) x y) -> (AND x y)
    42	(Or(64|32|16|8) x y) -> (OR x y)
    43	(Xor(64|32|16|8) x y) -> (XOR x y)
    44	
    45	// shifts
    46	// hardware instruction uses only the low 6 bits of the shift
    47	// we compare to 64 to ensure Go semantics for large shifts
    48	(Lsh64x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
    49	(Lsh64x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
    50	(Lsh64x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
    51	(Lsh64x8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SLLV <t> x (ZeroExt8to64  y)))
    52	
    53	(Lsh32x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
    54	(Lsh32x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
    55	(Lsh32x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
    56	(Lsh32x8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SLLV <t> x (ZeroExt8to64  y)))
    57	
    58	(Lsh16x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
    59	(Lsh16x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
    60	(Lsh16x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
    61	(Lsh16x8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SLLV <t> x (ZeroExt8to64  y)))
    62	
    63	(Lsh8x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
    64	(Lsh8x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
    65	(Lsh8x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
    66	(Lsh8x8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SLLV <t> x (ZeroExt8to64  y)))
    67	
    68	(Rsh64Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> x y))
    69	(Rsh64Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> x (ZeroExt32to64 y)))
    70	(Rsh64Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> x (ZeroExt16to64 y)))
    71	(Rsh64Ux8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SRLV <t> x (ZeroExt8to64  y)))
    72	
    73	(Rsh32Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt32to64 x) y))
    74	(Rsh32Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt32to64 y)))
    75	(Rsh32Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt16to64 y)))
    76	(Rsh32Ux8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt8to64  y)))
    77	
    78	(Rsh16Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt16to64 x) y))
    79	(Rsh16Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt32to64 y)))
    80	(Rsh16Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt16to64 y)))
    81	(Rsh16Ux8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt8to64  y)))
    82	
    83	(Rsh8Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt8to64 x) y))
    84	(Rsh8Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt32to64 y)))
    85	(Rsh8Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt16to64 y)))
    86	(Rsh8Ux8  <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64  y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt8to64  y)))
    87	
    88	(Rsh64x64 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
    89	(Rsh64x32 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
    90	(Rsh64x16 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
    91	(Rsh64x8  <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt8to64  y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64  y)))
    92	
    93	(Rsh32x64 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
    94	(Rsh32x32 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
    95	(Rsh32x16 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
    96	(Rsh32x8  <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64  y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64  y)))
    97	
    98	(Rsh16x64 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
    99	(Rsh16x32 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
   100	(Rsh16x16 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
   101	(Rsh16x8  <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64  y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64  y)))
   102	
   103	(Rsh8x64 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
   104	(Rsh8x32 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
   105	(Rsh8x16 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
   106	(Rsh8x8  <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64  y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64  y)))
   107	
   108	// rotates
   109	(RotateLeft8 <t> x (MOVVconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVVconst [c&7])) (Rsh8Ux64 <t> x (MOVVconst [-c&7])))
   110	(RotateLeft16 <t> x (MOVVconst [c])) -> (Or16 (Lsh16x64 <t> x (MOVVconst [c&15])) (Rsh16Ux64 <t> x (MOVVconst [-c&15])))
   111	(RotateLeft32 <t> x (MOVVconst [c])) -> (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
   112	(RotateLeft64 <t> x (MOVVconst [c])) -> (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
   113	
   114	// unary ops
   115	(Neg(64|32|16|8) x) -> (NEGV x)
   116	(Neg(32|64)F x) -> (NEG(F|D) x)
   117	
   118	(Com(64|32|16|8) x) -> (NOR (MOVVconst [0]) x)
   119	
   120	(Sqrt x) -> (SQRTD x)
   121	
   122	// boolean ops -- booleans are represented with 0=false, 1=true
   123	(AndB x y) -> (AND x y)
   124	(OrB x y) -> (OR x y)
   125	(EqB x y) -> (XOR (MOVVconst [1]) (XOR <typ.Bool> x y))
   126	(NeqB x y) -> (XOR x y)
   127	(Not x) -> (XORconst [1] x)
   128	
   129	// constants
   130	(Const(64|32|16|8) [val]) -> (MOVVconst [val])
   131	(Const(32|64)F [val]) -> (MOV(F|D)const [val])
   132	(ConstNil) -> (MOVVconst [0])
   133	(ConstBool [b]) -> (MOVVconst [b])
   134	
   135	(Slicemask <t> x) -> (SRAVconst (NEGV <t> x) [63])
   136	
   137	// truncations
   138	// Because we ignore high parts of registers, truncates are just copies.
   139	(Trunc16to8 x) -> x
   140	(Trunc32to8 x) -> x
   141	(Trunc32to16 x) -> x
   142	(Trunc64to8 x) -> x
   143	(Trunc64to16 x) -> x
   144	(Trunc64to32 x) -> x
   145	
   146	// Zero-/Sign-extensions
   147	(ZeroExt8to16 x) -> (MOVBUreg x)
   148	(ZeroExt8to32 x) -> (MOVBUreg x)
   149	(ZeroExt16to32 x) -> (MOVHUreg x)
   150	(ZeroExt8to64 x) -> (MOVBUreg x)
   151	(ZeroExt16to64 x) -> (MOVHUreg x)
   152	(ZeroExt32to64 x) -> (MOVWUreg x)
   153	
   154	(SignExt8to16 x) -> (MOVBreg x)
   155	(SignExt8to32 x) -> (MOVBreg x)
   156	(SignExt16to32 x) -> (MOVHreg x)
   157	(SignExt8to64 x) -> (MOVBreg x)
   158	(SignExt16to64 x) -> (MOVHreg x)
   159	(SignExt32to64 x) -> (MOVWreg x)
   160	
   161	// float <-> int conversion
   162	(Cvt32to32F x) -> (MOVWF x)
   163	(Cvt32to64F x) -> (MOVWD x)
   164	(Cvt64to32F x) -> (MOVVF x)
   165	(Cvt64to64F x) -> (MOVVD x)
   166	(Cvt32Fto32 x) -> (TRUNCFW x)
   167	(Cvt64Fto32 x) -> (TRUNCDW x)
   168	(Cvt32Fto64 x) -> (TRUNCFV x)
   169	(Cvt64Fto64 x) -> (TRUNCDV x)
   170	(Cvt32Fto64F x) -> (MOVFD x)
   171	(Cvt64Fto32F x) -> (MOVDF x)
   172	
   173	(Round(32|64)F x) -> x
   174	
   175	// comparisons
   176	(Eq8 x y)  -> (SGTU (MOVVconst [1]) (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)))
   177	(Eq16 x y) -> (SGTU (MOVVconst [1]) (XOR (ZeroExt16to64 x) (ZeroExt16to64 y)))
   178	(Eq32 x y) -> (SGTU (MOVVconst [1]) (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)))
   179	(Eq64 x y) -> (SGTU (MOVVconst [1]) (XOR x y))
   180	(EqPtr x y) -> (SGTU (MOVVconst [1]) (XOR x y))
   181	(Eq(32|64)F x y) -> (FPFlagTrue (CMPEQ(F|D) x y))
   182	
   183	(Neq8 x y)  -> (SGTU (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)) (MOVVconst [0]))
   184	(Neq16 x y) -> (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to64 y)) (MOVVconst [0]))
   185	(Neq32 x y) -> (SGTU (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)) (MOVVconst [0]))
   186	(Neq64 x y) -> (SGTU (XOR x y) (MOVVconst [0]))
   187	(NeqPtr x y) -> (SGTU (XOR x y) (MOVVconst [0]))
   188	(Neq(32|64)F x y) -> (FPFlagFalse (CMPEQ(F|D) x y))
   189	
   190	(Less8 x y)  -> (SGT (SignExt8to64 y) (SignExt8to64 x))
   191	(Less16 x y) -> (SGT (SignExt16to64 y) (SignExt16to64 x))
   192	(Less32 x y) -> (SGT (SignExt32to64 y) (SignExt32to64 x))
   193	(Less64 x y) -> (SGT y x)
   194	(Less(32|64)F x y) -> (FPFlagTrue (CMPGT(F|D) y x)) // reverse operands to work around NaN
   195	
   196	(Less8U x y)  -> (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x))
   197	(Less16U x y) -> (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x))
   198	(Less32U x y) -> (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x))
   199	(Less64U x y) -> (SGTU y x)
   200	
   201	(Leq8 x y)  -> (XOR (MOVVconst [1]) (SGT (SignExt8to64 x) (SignExt8to64 y)))
   202	(Leq16 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt16to64 x) (SignExt16to64 y)))
   203	(Leq32 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt32to64 x) (SignExt32to64 y)))
   204	(Leq64 x y) -> (XOR (MOVVconst [1]) (SGT x y))
   205	(Leq(32|64)F x y) -> (FPFlagTrue (CMPGE(F|D) y x)) // reverse operands to work around NaN
   206	
   207	(Leq8U x y)  -> (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y)))
   208	(Leq16U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y)))
   209	(Leq32U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y)))
   210	(Leq64U x y) -> (XOR (MOVVconst [1]) (SGTU x y))
   211	
   212	(Greater8 x y)  -> (SGT (SignExt8to64 x) (SignExt8to64 y))
   213	(Greater16 x y) -> (SGT (SignExt16to64 x) (SignExt16to64 y))
   214	(Greater32 x y) -> (SGT (SignExt32to64 x) (SignExt32to64 y))
   215	(Greater64 x y) -> (SGT x y)
   216	(Greater(32|64)F x y) -> (FPFlagTrue (CMPGT(F|D) x y))
   217	
   218	(Greater8U x y)  -> (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y))
   219	(Greater16U x y) -> (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y))
   220	(Greater32U x y) -> (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y))
   221	(Greater64U x y) -> (SGTU x y)
   222	
   223	(Geq8 x y)  -> (XOR (MOVVconst [1]) (SGT (SignExt8to64 y) (SignExt8to64 x)))
   224	(Geq16 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt16to64 y) (SignExt16to64 x)))
   225	(Geq32 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt32to64 y) (SignExt32to64 x)))
   226	(Geq64 x y) -> (XOR (MOVVconst [1]) (SGT y x))
   227	(Geq(32|64)F x y) -> (FPFlagTrue (CMPGE(F|D) x y))
   228	
   229	(Geq8U x y)  -> (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x)))
   230	(Geq16U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x)))
   231	(Geq32U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x)))
   232	(Geq64U x y) -> (XOR (MOVVconst [1]) (SGTU y x))
   233	
   234	(OffPtr [off] ptr:(SP)) -> (MOVVaddr [off] ptr)
   235	(OffPtr [off] ptr) -> (ADDVconst [off] ptr)
   236	
   237	(Addr {sym} base) -> (MOVVaddr {sym} base)
   238	(LocalAddr {sym} base _) -> (MOVVaddr {sym} base)
   239	
   240	// loads
   241	(Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
   242	(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
   243	(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
   244	(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
   245	(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
   246	(Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem)
   247	(Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem)
   248	(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVVload ptr mem)
   249	(Load <t> ptr mem) && is32BitFloat(t) -> (MOVFload ptr mem)
   250	(Load <t> ptr mem) && is64BitFloat(t) -> (MOVDload ptr mem)
   251	
   252	// stores
   253	(Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
   254	(Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
   255	(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
   256	(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && !is64BitFloat(val.Type) -> (MOVVstore ptr val mem)
   257	(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (MOVFstore ptr val mem)
   258	(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
   259	
   260	// zeroing
   261	(Zero [0] _ mem) -> mem
   262	(Zero [1] ptr mem) -> (MOVBstore ptr (MOVVconst [0]) mem)
   263	(Zero [2] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   264		(MOVHstore ptr (MOVVconst [0]) mem)
   265	(Zero [2] ptr mem) ->
   266		(MOVBstore [1] ptr (MOVVconst [0])
   267			(MOVBstore [0] ptr (MOVVconst [0]) mem))
   268	(Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
   269		(MOVWstore ptr (MOVVconst [0]) mem)
   270	(Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   271		(MOVHstore [2] ptr (MOVVconst [0])
   272			(MOVHstore [0] ptr (MOVVconst [0]) mem))
   273	(Zero [4] ptr mem) ->
   274		(MOVBstore [3] ptr (MOVVconst [0])
   275			(MOVBstore [2] ptr (MOVVconst [0])
   276				(MOVBstore [1] ptr (MOVVconst [0])
   277					(MOVBstore [0] ptr (MOVVconst [0]) mem))))
   278	(Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
   279		(MOVVstore ptr (MOVVconst [0]) mem)
   280	(Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
   281		(MOVWstore [4] ptr (MOVVconst [0])
   282			(MOVWstore [0] ptr (MOVVconst [0]) mem))
   283	(Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   284		(MOVHstore [6] ptr (MOVVconst [0])
   285			(MOVHstore [4] ptr (MOVVconst [0])
   286				(MOVHstore [2] ptr (MOVVconst [0])
   287					(MOVHstore [0] ptr (MOVVconst [0]) mem))))
   288	
   289	(Zero [3] ptr mem) ->
   290		(MOVBstore [2] ptr (MOVVconst [0])
   291			(MOVBstore [1] ptr (MOVVconst [0])
   292				(MOVBstore [0] ptr (MOVVconst [0]) mem)))
   293	(Zero [6] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   294		(MOVHstore [4] ptr (MOVVconst [0])
   295			(MOVHstore [2] ptr (MOVVconst [0])
   296				(MOVHstore [0] ptr (MOVVconst [0]) mem)))
   297	(Zero [12] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
   298		(MOVWstore [8] ptr (MOVVconst [0])
   299			(MOVWstore [4] ptr (MOVVconst [0])
   300				(MOVWstore [0] ptr (MOVVconst [0]) mem)))
   301	(Zero [16] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
   302		(MOVVstore [8] ptr (MOVVconst [0])
   303			(MOVVstore [0] ptr (MOVVconst [0]) mem))
   304	(Zero [24] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
   305		(MOVVstore [16] ptr (MOVVconst [0])
   306			(MOVVstore [8] ptr (MOVVconst [0])
   307				(MOVVstore [0] ptr (MOVVconst [0]) mem)))
   308	
   309	// medium zeroing uses a duff device
   310	// 8, and 128 are magic constants, see runtime/mkduff.go
   311	(Zero [s] {t} ptr mem)
   312		&& s%8 == 0 && s > 24 && s <= 8*128
   313		&& t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice ->
   314		(DUFFZERO [8 * (128 - s/8)] ptr mem)
   315	
   316	// large or unaligned zeroing uses a loop
   317	(Zero [s] {t} ptr mem)
   318		&& (s > 8*128 || config.noDuffDevice) || t.(*types.Type).Alignment()%8 != 0 ->
   319		(LoweredZero [t.(*types.Type).Alignment()]
   320			ptr
   321			(ADDVconst <ptr.Type> ptr [s-moveSize(t.(*types.Type).Alignment(), config)])
   322			mem)
   323	
   324	// moves
   325	(Move [0] _ _ mem) -> mem
   326	(Move [1] dst src mem) -> (MOVBstore dst (MOVBload src mem) mem)
   327	(Move [2] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   328		(MOVHstore dst (MOVHload src mem) mem)
   329	(Move [2] dst src mem) ->
   330		(MOVBstore [1] dst (MOVBload [1] src mem)
   331			(MOVBstore dst (MOVBload src mem) mem))
   332	(Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
   333		(MOVWstore dst (MOVWload src mem) mem)
   334	(Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   335		(MOVHstore [2] dst (MOVHload [2] src mem)
   336			(MOVHstore dst (MOVHload src mem) mem))
   337	(Move [4] dst src mem) ->
   338		(MOVBstore [3] dst (MOVBload [3] src mem)
   339			(MOVBstore [2] dst (MOVBload [2] src mem)
   340				(MOVBstore [1] dst (MOVBload [1] src mem)
   341					(MOVBstore dst (MOVBload src mem) mem))))
   342	(Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
   343		(MOVVstore dst (MOVVload src mem) mem)
   344	(Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
   345		(MOVWstore [4] dst (MOVWload [4] src mem)
   346			(MOVWstore dst (MOVWload src mem) mem))
   347	(Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   348		(MOVHstore [6] dst (MOVHload [6] src mem)
   349			(MOVHstore [4] dst (MOVHload [4] src mem)
   350				(MOVHstore [2] dst (MOVHload [2] src mem)
   351					(MOVHstore dst (MOVHload src mem) mem))))
   352	
   353	(Move [3] dst src mem) ->
   354		(MOVBstore [2] dst (MOVBload [2] src mem)
   355			(MOVBstore [1] dst (MOVBload [1] src mem)
   356				(MOVBstore dst (MOVBload src mem) mem)))
   357	(Move [6] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   358		(MOVHstore [4] dst (MOVHload [4] src mem)
   359			(MOVHstore [2] dst (MOVHload [2] src mem)
   360				(MOVHstore dst (MOVHload src mem) mem)))
   361	(Move [12] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
   362		(MOVWstore [8] dst (MOVWload [8] src mem)
   363			(MOVWstore [4] dst (MOVWload [4] src mem)
   364				(MOVWstore dst (MOVWload src mem) mem)))
   365	(Move [16] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
   366		(MOVVstore [8] dst (MOVVload [8] src mem)
   367			(MOVVstore dst (MOVVload src mem) mem))
   368	(Move [24] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
   369		(MOVVstore [16] dst (MOVVload [16] src mem)
   370			(MOVVstore [8] dst (MOVVload [8] src mem)
   371				(MOVVstore dst (MOVVload src mem) mem)))
   372	
   373	// large or unaligned move uses a loop
   374	(Move [s] {t} dst src mem)
   375		&& s > 24 || t.(*types.Type).Alignment()%8 != 0 ->
   376		(LoweredMove [t.(*types.Type).Alignment()]
   377			dst
   378			src
   379			(ADDVconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)])
   380			mem)
   381	
   382	// calls
   383	(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
   384	(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
   385	(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
   386	
   387	// atomic intrinsics
   388	(AtomicLoad8   ptr mem) -> (LoweredAtomicLoad8  ptr mem)
   389	(AtomicLoad32  ptr mem) -> (LoweredAtomicLoad32 ptr mem)
   390	(AtomicLoad64  ptr mem) -> (LoweredAtomicLoad64 ptr mem)
   391	(AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad64 ptr mem)
   392	
   393	(AtomicStore32      ptr val mem) -> (LoweredAtomicStore32 ptr val mem)
   394	(AtomicStore64      ptr val mem) -> (LoweredAtomicStore64 ptr val mem)
   395	(AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore64 ptr val mem)
   396	
   397	(AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange32 ptr val mem)
   398	(AtomicExchange64 ptr val mem) -> (LoweredAtomicExchange64 ptr val mem)
   399	
   400	(AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd32 ptr val mem)
   401	(AtomicAdd64 ptr val mem) -> (LoweredAtomicAdd64 ptr val mem)
   402	
   403	(AtomicCompareAndSwap32 ptr old new_ mem) -> (LoweredAtomicCas32 ptr old new_ mem)
   404	(AtomicCompareAndSwap64 ptr old new_ mem) -> (LoweredAtomicCas64 ptr old new_ mem)
   405	
   406	// checks
   407	(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
   408	(IsNonNil ptr) -> (SGTU ptr (MOVVconst [0]))
   409	(IsInBounds idx len) -> (SGTU len idx)
   410	(IsSliceInBounds idx len) -> (XOR (MOVVconst [1]) (SGTU idx len))
   411	
   412	// pseudo-ops
   413	(GetClosurePtr) -> (LoweredGetClosurePtr)
   414	(GetCallerSP) -> (LoweredGetCallerSP)
   415	(GetCallerPC) -> (LoweredGetCallerPC)
   416	
   417	(If cond yes no) -> (NE cond yes no)
   418	
   419	// Write barrier.
   420	(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
   421	
   422	(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
   423	(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
   424	(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
   425	
   426	// Optimizations
   427	
   428	// Absorb boolean tests into block
   429	(NE (FPFlagTrue cmp) yes no) -> (FPT cmp yes no)
   430	(NE (FPFlagFalse cmp) yes no) -> (FPF cmp yes no)
   431	(EQ (FPFlagTrue cmp) yes no) -> (FPF cmp yes no)
   432	(EQ (FPFlagFalse cmp) yes no) -> (FPT cmp yes no)
   433	(NE (XORconst [1] cmp:(SGT _ _)) yes no) -> (EQ cmp yes no)
   434	(NE (XORconst [1] cmp:(SGTU _ _)) yes no) -> (EQ cmp yes no)
   435	(NE (XORconst [1] cmp:(SGTconst _)) yes no) -> (EQ cmp yes no)
   436	(NE (XORconst [1] cmp:(SGTUconst _)) yes no) -> (EQ cmp yes no)
   437	(EQ (XORconst [1] cmp:(SGT _ _)) yes no) -> (NE cmp yes no)
   438	(EQ (XORconst [1] cmp:(SGTU _ _)) yes no) -> (NE cmp yes no)
   439	(EQ (XORconst [1] cmp:(SGTconst _)) yes no) -> (NE cmp yes no)
   440	(EQ (XORconst [1] cmp:(SGTUconst _)) yes no) -> (NE cmp yes no)
   441	(NE (SGTUconst [1] x) yes no) -> (EQ x yes no)
   442	(EQ (SGTUconst [1] x) yes no) -> (NE x yes no)
   443	(NE (SGTU x (MOVVconst [0])) yes no) -> (NE x yes no)
   444	(EQ (SGTU x (MOVVconst [0])) yes no) -> (EQ x yes no)
   445	(NE (SGTconst [0] x) yes no) -> (LTZ x yes no)
   446	(EQ (SGTconst [0] x) yes no) -> (GEZ x yes no)
   447	(NE (SGT x (MOVVconst [0])) yes no) -> (GTZ x yes no)
   448	(EQ (SGT x (MOVVconst [0])) yes no) -> (LEZ x yes no)
   449	
   450	// fold offset into address
   451	(ADDVconst [off1] (MOVVaddr [off2] {sym} ptr)) -> (MOVVaddr [off1+off2] {sym} ptr)
   452	
   453	// fold address into load/store
   454	(MOVBload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBload  [off1+off2] {sym} ptr mem)
   455	(MOVBUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBUload [off1+off2] {sym} ptr mem)
   456	(MOVHload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHload  [off1+off2] {sym} ptr mem)
   457	(MOVHUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHUload [off1+off2] {sym} ptr mem)
   458	(MOVWload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWload  [off1+off2] {sym} ptr mem)
   459	(MOVWUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWUload [off1+off2] {sym} ptr mem)
   460	(MOVVload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVVload  [off1+off2] {sym} ptr mem)
   461	(MOVFload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVFload  [off1+off2] {sym} ptr mem)
   462	(MOVDload  [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVDload  [off1+off2] {sym} ptr mem)
   463	
   464	(MOVBstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} ptr val mem)
   465	(MOVHstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} ptr val mem)
   466	(MOVWstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} ptr val mem)
   467	(MOVVstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVVstore [off1+off2] {sym} ptr val mem)
   468	(MOVFstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVFstore [off1+off2] {sym} ptr val mem)
   469	(MOVDstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} ptr val mem)
   470	(MOVBstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
   471	(MOVHstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHstorezero [off1+off2] {sym} ptr mem)
   472	(MOVWstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWstorezero [off1+off2] {sym} ptr mem)
   473	(MOVVstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVVstorezero [off1+off2] {sym} ptr mem)
   474	
   475	(MOVBload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   476		(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   477	(MOVBUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   478		(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   479	(MOVHload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   480		(MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   481	(MOVHUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   482		(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   483	(MOVWload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   484		(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   485	(MOVWUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   486		(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   487	(MOVVload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   488		(MOVVload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   489	(MOVFload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   490		(MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   491	(MOVDload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   492		(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   493	
   494	(MOVBstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   495		(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   496	(MOVHstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   497		(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   498	(MOVWstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   499		(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   500	(MOVVstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   501		(MOVVstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   502	(MOVFstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   503		(MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   504	(MOVDstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   505		(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   506	(MOVBstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   507		(MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   508	(MOVHstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   509		(MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   510	(MOVWstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   511		(MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   512	(MOVVstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
   513		(MOVVstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   514	
   515	// store zero
   516	(MOVBstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
   517	(MOVHstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem)
   518	(MOVWstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
   519	(MOVVstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVVstorezero [off] {sym} ptr mem)
   520	
   521	// don't extend after proper load
   522	(MOVBreg x:(MOVBload _ _)) -> (MOVVreg x)
   523	(MOVBUreg x:(MOVBUload _ _)) -> (MOVVreg x)
   524	(MOVHreg x:(MOVBload _ _)) -> (MOVVreg x)
   525	(MOVHreg x:(MOVBUload _ _)) -> (MOVVreg x)
   526	(MOVHreg x:(MOVHload _ _)) -> (MOVVreg x)
   527	(MOVHUreg x:(MOVBUload _ _)) -> (MOVVreg x)
   528	(MOVHUreg x:(MOVHUload _ _)) -> (MOVVreg x)
   529	(MOVWreg x:(MOVBload _ _)) -> (MOVVreg x)
   530	(MOVWreg x:(MOVBUload _ _)) -> (MOVVreg x)
   531	(MOVWreg x:(MOVHload _ _)) -> (MOVVreg x)
   532	(MOVWreg x:(MOVHUload _ _)) -> (MOVVreg x)
   533	(MOVWreg x:(MOVWload _ _)) -> (MOVVreg x)
   534	(MOVWUreg x:(MOVBUload _ _)) -> (MOVVreg x)
   535	(MOVWUreg x:(MOVHUload _ _)) -> (MOVVreg x)
   536	(MOVWUreg x:(MOVWUload _ _)) -> (MOVVreg x)
   537	
   538	// fold double extensions
   539	(MOVBreg x:(MOVBreg _)) -> (MOVVreg x)
   540	(MOVBUreg x:(MOVBUreg _)) -> (MOVVreg x)
   541	(MOVHreg x:(MOVBreg _)) -> (MOVVreg x)
   542	(MOVHreg x:(MOVBUreg _)) -> (MOVVreg x)
   543	(MOVHreg x:(MOVHreg _)) -> (MOVVreg x)
   544	(MOVHUreg x:(MOVBUreg _)) -> (MOVVreg x)
   545	(MOVHUreg x:(MOVHUreg _)) -> (MOVVreg x)
   546	(MOVWreg x:(MOVBreg _)) -> (MOVVreg x)
   547	(MOVWreg x:(MOVBUreg _)) -> (MOVVreg x)
   548	(MOVWreg x:(MOVHreg _)) -> (MOVVreg x)
   549	(MOVWreg x:(MOVHreg _)) -> (MOVVreg x)
   550	(MOVWreg x:(MOVWreg _)) -> (MOVVreg x)
   551	(MOVWUreg x:(MOVBUreg _)) -> (MOVVreg x)
   552	(MOVWUreg x:(MOVHUreg _)) -> (MOVVreg x)
   553	(MOVWUreg x:(MOVWUreg _)) -> (MOVVreg x)
   554	
   555	// don't extend before store
   556	(MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   557	(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   558	(MOVBstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   559	(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   560	(MOVBstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   561	(MOVBstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   562	(MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   563	(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   564	(MOVHstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   565	(MOVHstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   566	(MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
   567	(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
   568	
   569	// if a register move has only 1 use, just use the same register without emitting instruction
   570	// MOVVnop doesn't emit instruction, only for ensuring the type.
   571	(MOVVreg x) && x.Uses == 1 -> (MOVVnop x)
   572	
   573	// fold constant into arithmatic ops
   574	(ADDV x (MOVVconst [c])) && is32Bit(c) -> (ADDVconst [c] x)
   575	(SUBV x (MOVVconst [c])) && is32Bit(c) -> (SUBVconst [c] x)
   576	(AND x (MOVVconst [c])) && is32Bit(c) -> (ANDconst [c] x)
   577	(OR  x (MOVVconst [c])) && is32Bit(c) -> (ORconst  [c] x)
   578	(XOR x (MOVVconst [c])) && is32Bit(c) -> (XORconst [c] x)
   579	(NOR x (MOVVconst [c])) && is32Bit(c) -> (NORconst [c] x)
   580	
   581	(SLLV _ (MOVVconst [c])) && uint64(c)>=64 -> (MOVVconst [0])
   582	(SRLV _ (MOVVconst [c])) && uint64(c)>=64 -> (MOVVconst [0])
   583	(SRAV x (MOVVconst [c])) && uint64(c)>=64 -> (SRAVconst x [63])
   584	(SLLV x (MOVVconst [c])) -> (SLLVconst x [c])
   585	(SRLV x (MOVVconst [c])) -> (SRLVconst x [c])
   586	(SRAV x (MOVVconst [c])) -> (SRAVconst x [c])
   587	
   588	(SGT  (MOVVconst [c]) x) && is32Bit(c) -> (SGTconst  [c] x)
   589	(SGTU (MOVVconst [c]) x) && is32Bit(c) -> (SGTUconst [c] x)
   590	
   591	// mul by constant
   592	(Select1 (MULVU x (MOVVconst [-1]))) -> (NEGV x)
   593	(Select1 (MULVU _ (MOVVconst [0]))) -> (MOVVconst [0])
   594	(Select1 (MULVU x (MOVVconst [1]))) -> x
   595	(Select1 (MULVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (SLLVconst [log2(c)] x)
   596	
   597	(Select1 (MULVU (MOVVconst [-1]) x)) -> (NEGV x)
   598	(Select1 (MULVU (MOVVconst [0]) _)) -> (MOVVconst [0])
   599	(Select1 (MULVU (MOVVconst [1]) x)) -> x
   600	(Select1 (MULVU (MOVVconst [c]) x)) && isPowerOfTwo(c) -> (SLLVconst [log2(c)] x)
   601	
   602	// div by constant
   603	(Select1 (DIVVU x (MOVVconst [1]))) -> x
   604	(Select1 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (SRLVconst [log2(c)] x)
   605	(Select0 (DIVVU _ (MOVVconst [1]))) -> (MOVVconst [0])                       // mod
   606	(Select0 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (ANDconst [c-1] x) // mod
   607	
   608	// generic simplifications
   609	(ADDV x (NEGV y)) -> (SUBV x y)
   610	(SUBV x x) -> (MOVVconst [0])
   611	(SUBV (MOVVconst [0]) x) -> (NEGV x)
   612	(AND x x) -> x
   613	(OR  x x) -> x
   614	(XOR x x) -> (MOVVconst [0])
   615	
   616	// remove redundant *const ops
   617	(ADDVconst [0]  x) -> x
   618	(SUBVconst [0]  x) -> x
   619	(ANDconst [0]  _) -> (MOVVconst [0])
   620	(ANDconst [-1] x) -> x
   621	(ORconst  [0]  x) -> x
   622	(ORconst  [-1] _) -> (MOVVconst [-1])
   623	(XORconst [0]  x) -> x
   624	(XORconst [-1] x) -> (NORconst [0] x)
   625	
   626	// generic constant folding
   627	(ADDVconst [c] (MOVVconst [d]))  -> (MOVVconst [c+d])
   628	(ADDVconst [c] (ADDVconst [d] x)) && is32Bit(c+d) -> (ADDVconst [c+d] x)
   629	(ADDVconst [c] (SUBVconst [d] x)) && is32Bit(c-d) -> (ADDVconst [c-d] x)
   630	(SUBVconst [c] (MOVVconst [d]))  -> (MOVVconst [d-c])
   631	(SUBVconst [c] (SUBVconst [d] x)) && is32Bit(-c-d) -> (ADDVconst [-c-d] x)
   632	(SUBVconst [c] (ADDVconst [d] x)) && is32Bit(-c+d) -> (ADDVconst [-c+d] x)
   633	(SLLVconst [c] (MOVVconst [d]))  -> (MOVVconst [d<<uint64(c)])
   634	(SRLVconst [c] (MOVVconst [d]))  -> (MOVVconst [int64(uint64(d)>>uint64(c))])
   635	(SRAVconst [c] (MOVVconst [d]))  -> (MOVVconst [d>>uint64(c)])
   636	(Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c*d])
   637	(Select1 (DIVV  (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c/d])
   638	(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [int64(uint64(c)/uint64(d))])
   639	(Select0 (DIVV  (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c%d])   // mod
   640	(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
   641	(ANDconst [c] (MOVVconst [d])) -> (MOVVconst [c&d])
   642	(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
   643	(ORconst [c] (MOVVconst [d])) -> (MOVVconst [c|d])
   644	(ORconst [c] (ORconst [d] x)) && is32Bit(c|d) -> (ORconst [c|d] x)
   645	(XORconst [c] (MOVVconst [d])) -> (MOVVconst [c^d])
   646	(XORconst [c] (XORconst [d] x)) && is32Bit(c^d) -> (XORconst [c^d] x)
   647	(NORconst [c] (MOVVconst [d])) -> (MOVVconst [^(c|d)])
   648	(NEGV (MOVVconst [c])) -> (MOVVconst [-c])
   649	(MOVBreg  (MOVVconst [c])) -> (MOVVconst [int64(int8(c))])
   650	(MOVBUreg (MOVVconst [c])) -> (MOVVconst [int64(uint8(c))])
   651	(MOVHreg  (MOVVconst [c])) -> (MOVVconst [int64(int16(c))])
   652	(MOVHUreg (MOVVconst [c])) -> (MOVVconst [int64(uint16(c))])
   653	(MOVWreg  (MOVVconst [c])) -> (MOVVconst [int64(int32(c))])
   654	(MOVWUreg (MOVVconst [c])) -> (MOVVconst [int64(uint32(c))])
   655	(MOVVreg  (MOVVconst [c])) -> (MOVVconst [c])
   656	(LoweredAtomicStore32 ptr (MOVVconst [0]) mem) -> (LoweredAtomicStorezero32 ptr mem)
   657	(LoweredAtomicStore64 ptr (MOVVconst [0]) mem) -> (LoweredAtomicStorezero64 ptr mem)
   658	(LoweredAtomicAdd32 ptr (MOVVconst [c]) mem) && is32Bit(c) -> (LoweredAtomicAddconst32 [c] ptr mem)
   659	(LoweredAtomicAdd64 ptr (MOVVconst [c]) mem) && is32Bit(c) -> (LoweredAtomicAddconst64 [c] ptr mem)
   660	
   661	// constant comparisons
   662	(SGTconst [c] (MOVVconst [d])) && c>d -> (MOVVconst [1])
   663	(SGTconst [c] (MOVVconst [d])) && c<=d -> (MOVVconst [0])
   664	(SGTUconst [c] (MOVVconst [d])) && uint64(c)>uint64(d) -> (MOVVconst [1])
   665	(SGTUconst [c] (MOVVconst [d])) && uint64(c)<=uint64(d) -> (MOVVconst [0])
   666	
   667	// other known comparisons
   668	(SGTconst [c] (MOVBreg _)) && 0x7f < c -> (MOVVconst [1])
   669	(SGTconst [c] (MOVBreg _)) && c <= -0x80 -> (MOVVconst [0])
   670	(SGTconst [c] (MOVBUreg _)) && 0xff < c -> (MOVVconst [1])
   671	(SGTconst [c] (MOVBUreg _)) && c < 0 -> (MOVVconst [0])
   672	(SGTUconst [c] (MOVBUreg _)) && 0xff < uint64(c) -> (MOVVconst [1])
   673	(SGTconst [c] (MOVHreg _)) && 0x7fff < c -> (MOVVconst [1])
   674	(SGTconst [c] (MOVHreg _)) && c <= -0x8000 -> (MOVVconst [0])
   675	(SGTconst [c] (MOVHUreg _)) && 0xffff < c -> (MOVVconst [1])
   676	(SGTconst [c] (MOVHUreg _)) && c < 0 -> (MOVVconst [0])
   677	(SGTUconst [c] (MOVHUreg _)) && 0xffff < uint64(c) -> (MOVVconst [1])
   678	(SGTconst [c] (MOVWUreg _)) && c < 0 -> (MOVVconst [0])
   679	(SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c -> (MOVVconst [1])
   680	(SGTUconst [c] (ANDconst [m] _)) && uint64(m) < uint64(c) -> (MOVVconst [1])
   681	(SGTconst [c] (SRLVconst _ [d])) && 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
   682	(SGTUconst [c] (SRLVconst _ [d])) && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
   683	
   684	// absorb constants into branches
   685	(EQ  (MOVVconst [0]) yes no) -> (First nil yes no)
   686	(EQ  (MOVVconst [c]) yes no) && c != 0 -> (First nil no yes)
   687	(NE  (MOVVconst [0]) yes no) -> (First nil no yes)
   688	(NE  (MOVVconst [c]) yes no) && c != 0 -> (First nil yes no)
   689	(LTZ (MOVVconst [c]) yes no) && c <  0 -> (First nil yes no)
   690	(LTZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil no yes)
   691	(LEZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil yes no)
   692	(LEZ (MOVVconst [c]) yes no) && c >  0 -> (First nil no yes)
   693	(GTZ (MOVVconst [c]) yes no) && c >  0 -> (First nil yes no)
   694	(GTZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil no yes)
   695	(GEZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil yes no)
   696	(GEZ (MOVVconst [c]) yes no) && c <  0 -> (First nil no yes)

View as plain text