github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/compile/internal/ssa/gen/PPC64.rules (about)

     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  // Lowering arithmetic
     6  (Add64  x y) -> (ADD  x y)
     7  (AddPtr x y) -> (ADD  x y)
     8  (Add32  x y) -> (ADD x y)
     9  (Add16  x y) -> (ADD x y)
    10  (Add8   x y) -> (ADD x y)
    11  (Add64F x y) -> (FADD x y)
    12  (Add32F x y) -> (FADDS x y)
    13  
    14  (Sub64  x y) -> (SUB  x y)
    15  (SubPtr x y) -> (SUB  x y)
    16  (Sub32  x y) -> (SUB x y)
    17  (Sub16  x y) -> (SUB x y)
    18  (Sub8   x y) -> (SUB x y)
    19  (Sub32F x y) -> (FSUBS x y)
    20  (Sub64F x y) -> (FSUB x y)
    21  
    22  (Mod16 x y) -> (Mod32 (SignExt16to32 x) (SignExt16to32 y))
    23  (Mod16u x y) -> (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
    24  (Mod8 x y) -> (Mod32 (SignExt8to32 x) (SignExt8to32 y))
    25  (Mod8u x y) -> (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
    26  (Mod64 x y) -> (SUB x (MULLD y (DIVD x y)))
    27  (Mod64u x y) -> (SUB x (MULLD y (DIVDU x y)))
    28  (Mod32 x y) -> (SUB x (MULLW y (DIVW x y)))
    29  (Mod32u x y) -> (SUB x (MULLW y (DIVWU x y)))
    30  
    31  (Avg64u <t> x y) -> (ADD (ADD <t> (SRD <t> x (MOVDconst <t> [1])) (SRD <t> y (MOVDconst <t> [1]))) (ANDconst <t> (AND <t> x y) [1]))
    32  
    33  (Mul64  x y) -> (MULLD  x y)
    34  (Mul32  x y) -> (MULLW  x y)
    35  (Mul16  x y) -> (MULLW x y)
    36  (Mul8   x y) -> (MULLW x y)
    37  
    38  (Div64  x y) -> (DIVD  x y)
    39  (Div64u x y) -> (DIVDU x y)
    40  (Div32  x y) -> (DIVW  x y)
    41  (Div32u x y) -> (DIVWU x y)
    42  (Div16  x y) -> (DIVW  (SignExt16to32 x) (SignExt16to32 y))
    43  (Div16u x y) -> (DIVWU (ZeroExt16to32 x) (ZeroExt16to32 y))
    44  (Div8   x y) -> (DIVW  (SignExt8to32 x) (SignExt8to32 y))
    45  (Div8u  x y) -> (DIVWU (ZeroExt8to32 x) (ZeroExt8to32 y))
    46  
    47  (Hmul64  x y) -> (MULHD  x y)
    48  (Hmul64u  x y) -> (MULHDU x y)
    49  (Hmul32  x y) -> (MULHW  x y)
    50  (Hmul32u  x y) -> (MULHWU x y)
    51  (Hmul16 x y) -> (SRAWconst (MULLW <config.fe.TypeInt32()> (SignExt16to32 x) (SignExt16to32 y)) [16])
    52  (Hmul16u x y) -> (SRWconst (MULLW <config.fe.TypeUInt32()> (ZeroExt16to32 x) (ZeroExt16to32 y)) [16])
    53  (Hmul8 x y) -> (SRAWconst (MULLW <config.fe.TypeInt16()> (SignExt8to32 x) (SignExt8to32 y)) [8])
    54  (Hmul8u x y) -> (SRWconst (MULLW <config.fe.TypeUInt16()> (ZeroExt8to32 x) (ZeroExt8to32 y)) [8])
    55  
    56  (Mul32F x y) -> (FMULS x y)
    57  (Mul64F x y) -> (FMUL x y)
    58  
    59  (Div32F x y) -> (FDIVS x y)
    60  (Div64F x y) -> (FDIV x y)
    61  
    62  // Lowering float <-> int
    63  (Cvt32to32F x) -> (FRSP (FCFID (Xi2f64 (SignExt32to64 x))))
    64  (Cvt32to64F x) -> (FCFID (Xi2f64 (SignExt32to64 x)))
    65  (Cvt64to32F x) -> (FRSP (FCFID (Xi2f64 x)))
    66  (Cvt64to64F x) -> (FCFID (Xi2f64 x))
    67  
    68  (Cvt32Fto32 x) -> (Xf2i64 (FCTIWZ x))
    69  (Cvt32Fto64 x) -> (Xf2i64 (FCTIDZ x))
    70  (Cvt64Fto32 x) -> (Xf2i64 (FCTIWZ x))
    71  (Cvt64Fto64 x) -> (Xf2i64 (FCTIDZ x))
    72  
    73  (Cvt32Fto64F x) -> x // Note x will have the wrong type for patterns dependent on Float32/Float64
    74  (Cvt64Fto32F x) -> (FRSP x)
    75  
    76  (Sqrt x) -> (FSQRT x)
    77  
    78  // Lowering constants
    79  (Const8   [val]) -> (MOVDconst [val])
    80  (Const16  [val]) -> (MOVDconst [val])
    81  (Const32  [val]) -> (MOVDconst [val])
    82  (Const64  [val]) -> (MOVDconst [val])
    83  (Const32F [val]) -> (FMOVSconst [val])
    84  (Const64F [val]) -> (FMOVDconst [val])
    85  (ConstNil) -> (MOVDconst [0])
    86  (ConstBool [b]) -> (MOVDconst [b])
    87  
    88  (Lsh64x64  x (Const64 [c])) && uint64(c) < 64 -> (SLDconst x [c])
    89  (Rsh64x64  x (Const64 [c])) && uint64(c) < 64 -> (SRADconst x [c])
    90  (Rsh64Ux64 x (Const64 [c])) && uint64(c) < 64 -> (SRDconst x [c])
    91  (Lsh32x64  x (Const64 [c])) && uint64(c) < 32 -> (SLWconst x [c])
    92  (Rsh32x64  x (Const64 [c])) && uint64(c) < 32 -> (SRAWconst x [c])
    93  (Rsh32Ux64 x (Const64 [c])) && uint64(c) < 32 -> (SRWconst x [c])
    94  (Lsh16x64  x (Const64 [c])) && uint64(c) < 16 -> (SLWconst x [c])
    95  (Rsh16x64  x (Const64 [c])) && uint64(c) < 16 -> (SRAWconst (SignExt16to32 x) [c])
    96  (Rsh16Ux64 x (Const64 [c])) && uint64(c) < 16 -> (SRWconst (ZeroExt16to32 x) [c])
    97  (Lsh8x64   x (Const64 [c])) && uint64(c) < 8  -> (SLWconst x [c])
    98  (Rsh8x64   x (Const64 [c])) && uint64(c) < 8  -> (SRAWconst (SignExt8to32  x) [c])
    99  (Rsh8Ux64  x (Const64 [c])) && uint64(c) < 8  -> (SRWconst (ZeroExt8to32  x) [c])
   100  
   101  (Lsh64x32  x (Const64 [c])) && uint32(c) < 64 -> (SLDconst x [c])
   102  (Rsh64x32  x (Const64 [c])) && uint32(c) < 64 -> (SRADconst x [c])
   103  (Rsh64Ux32 x (Const64 [c])) && uint32(c) < 64 -> (SRDconst x [c])
   104  (Lsh32x32  x (Const64 [c])) && uint32(c) < 32 -> (SLWconst x [c])
   105  (Rsh32x32  x (Const64 [c])) && uint32(c) < 32 -> (SRAWconst x [c])
   106  (Rsh32Ux32 x (Const64 [c])) && uint32(c) < 32 -> (SRWconst x [c])
   107  (Lsh16x32  x (Const64 [c])) && uint32(c) < 16 -> (SLWconst x [c])
   108  (Rsh16x32  x (Const64 [c])) && uint32(c) < 16 -> (SRAWconst (SignExt16to32 x) [c])
   109  (Rsh16Ux32 x (Const64 [c])) && uint32(c) < 16 -> (SRWconst (ZeroExt16to32 x) [c])
   110  (Lsh8x32   x (Const64 [c])) && uint32(c) < 8  -> (SLWconst x [c])
   111  (Rsh8x32   x (Const64 [c])) && uint32(c) < 8  -> (SRAWconst (SignExt8to32  x) [c])
   112  (Rsh8Ux32  x (Const64 [c])) && uint32(c) < 8  -> (SRWconst (ZeroExt8to32  x) [c])
   113  
   114  // large constant shifts
   115  (Lsh64x64  _ (Const64 [c])) && uint64(c) >= 64 -> (MOVDconst [0])
   116  (Rsh64Ux64 _ (Const64 [c])) && uint64(c) >= 64 -> (MOVDconst [0])
   117  (Lsh32x64  _ (Const64 [c])) && uint64(c) >= 32 -> (MOVDconst [0])
   118  (Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 -> (MOVDconst [0])
   119  (Lsh16x64  _ (Const64 [c])) && uint64(c) >= 16 -> (MOVDconst [0])
   120  (Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 -> (MOVDconst [0])
   121  (Lsh8x64   _ (Const64 [c])) && uint64(c) >= 8  -> (MOVDconst [0])
   122  (Rsh8Ux64  _ (Const64 [c])) && uint64(c) >= 8  -> (MOVDconst [0])
   123  
   124  // large constant signed right shift, we leave the sign bit
   125  (Rsh64x64 x (Const64 [c])) && uint64(c) >= 64 -> (SRADconst x [63])
   126  (Rsh32x64 x (Const64 [c])) && uint64(c) >= 32 -> (SRAWconst x [63])
   127  (Rsh16x64 x (Const64 [c])) && uint64(c) >= 16 -> (SRAWconst (SignExt16to32 x) [63])
   128  (Rsh8x64  x (Const64 [c])) && uint64(c) >= 8  -> (SRAWconst (SignExt8to32  x) [63])
   129  
   130  // constant shifts
   131  (Lsh64x64  x (MOVDconst [c])) && uint64(c) < 64 -> (SLDconst x [c])
   132  (Rsh64x64  x (MOVDconst [c])) && uint64(c) < 64 -> (SRADconst x [c])
   133  (Rsh64Ux64 x (MOVDconst [c])) && uint64(c) < 64 -> (SRDconst x [c])
   134  (Lsh32x64  x (MOVDconst [c])) && uint64(c) < 32 -> (SLWconst x [c])
   135  (Rsh32x64  x (MOVDconst [c])) && uint64(c) < 32 -> (SRAWconst x [c])
   136  (Rsh32Ux64 x (MOVDconst [c])) && uint64(c) < 32 -> (SRWconst x [c])
   137  (Lsh16x64  x (MOVDconst [c])) && uint64(c) < 16 -> (SLWconst x [c])
   138  (Rsh16x64  x (MOVDconst [c])) && uint64(c) < 16 -> (SRAWconst (SignExt16to32 x) [c])
   139  (Rsh16Ux64 x (MOVDconst [c])) && uint64(c) < 16 -> (SRWconst (ZeroExt16to32 x) [c])
   140  (Lsh8x64   x (MOVDconst [c])) && uint64(c) < 8  -> (SLWconst x [c])
   141  (Rsh8x64   x (MOVDconst [c])) && uint64(c) < 8  -> (SRAWconst (SignExt8to32  x) [c])
   142  (Rsh8Ux64  x (MOVDconst [c])) && uint64(c) < 8  -> (SRWconst (ZeroExt8to32  x) [c])
   143  
   144  (Lsh64x32  x (MOVDconst [c])) && uint32(c) < 64 -> (SLDconst x [c])
   145  (Rsh64x32  x (MOVDconst [c])) && uint32(c) < 64 -> (SRADconst x [c])
   146  (Rsh64Ux32 x (MOVDconst [c])) && uint32(c) < 64 -> (SRDconst x [c])
   147  (Lsh32x32  x (MOVDconst [c])) && uint32(c) < 32 -> (SLWconst x [c])
   148  (Rsh32x32  x (MOVDconst [c])) && uint32(c) < 32 -> (SRAWconst x [c])
   149  (Rsh32Ux32 x (MOVDconst [c])) && uint32(c) < 32 -> (SRWconst x [c])
   150  (Lsh16x32  x (MOVDconst [c])) && uint32(c) < 16 -> (SLWconst x [c])
   151  (Rsh16x32  x (MOVDconst [c])) && uint32(c) < 16 -> (SRAWconst (SignExt16to32 x) [c])
   152  (Rsh16Ux32 x (MOVDconst [c])) && uint32(c) < 16 -> (SRWconst (ZeroExt16to32 x) [c])
   153  (Lsh8x32   x (MOVDconst [c])) && uint32(c) < 8  -> (SLWconst x [c])
   154  (Rsh8x32   x (MOVDconst [c])) && uint32(c) < 8  -> (SRAWconst (SignExt8to32  x) [c])
   155  (Rsh8Ux32  x (MOVDconst [c])) && uint32(c) < 8  -> (SRWconst (ZeroExt8to32  x) [c])
   156  
   157  (Rsh64x64 x y)  -> (SRAD x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] y))))
   158  (Rsh64Ux64 x y) -> (SRD  x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] y))))
   159  (Lsh64x64 x y)  -> (SLD  x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] y))))
   160  
   161  (Rsh32x64 x y)  -> (SRAW x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] y))))
   162  (Rsh32Ux64 x y) -> (SRW  x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] y))))
   163  (Lsh32x64 x y)  -> (SLW  x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] y))))
   164  
   165  (Rsh16x64 x y)  -> (SRAW (SignExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
   166  (Rsh16Ux64 x y) -> (SRW  (ZeroExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
   167  (Lsh16x64 x y)  -> (SLW  x                 (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] y))))
   168  
   169  (Rsh8x64 x y)  -> (SRAW (SignExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
   170  (Rsh8Ux64 x y) -> (SRW  (ZeroExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
   171  (Lsh8x64 x y)  -> (SLW  x                (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] y))))
   172  
   173  
   174  (Rsh64x32 x y)  -> (SRAD x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
   175  (Rsh64Ux32 x y) -> (SRD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
   176  (Lsh64x32 x y)  -> (SLD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt32to64 y)))))
   177  
   178  (Rsh32x32 x y)  -> (SRAW x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
   179  (Rsh32Ux32 x y) -> (SRW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
   180  (Lsh32x32 x y)  -> (SLW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt32to64 y)))))
   181  
   182  (Rsh16x32 x y)  -> (SRAW (SignExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
   183  (Rsh16Ux32 x y) -> (SRW  (ZeroExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
   184  (Lsh16x32 x y)  -> (SLW  x                 (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt32to64 y)))))
   185  
   186  (Rsh8x32 x y)  -> (SRAW (SignExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
   187  (Rsh8Ux32 x y) -> (SRW  (ZeroExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
   188  (Lsh8x32 x y)  -> (SLW  x                (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt32to64 y)))))
   189  
   190  
   191  (Rsh64x16 x y)  -> (SRAD x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
   192  (Rsh64Ux16 x y) -> (SRD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
   193  (Lsh64x16 x y)  -> (SLD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt16to64 y)))))
   194  
   195  (Rsh32x16 x y)  -> (SRAW x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
   196  (Rsh32Ux16 x y) -> (SRW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
   197  (Lsh32x16 x y)  -> (SLW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt16to64 y)))))
   198  
   199  (Rsh16x16 x y)  -> (SRAW (SignExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
   200  (Rsh16Ux16 x y) -> (SRW  (ZeroExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
   201  (Lsh16x16 x y)  -> (SLW  x                 (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt16to64 y)))))
   202  
   203  (Rsh8x16 x y)  -> (SRAW (SignExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
   204  (Rsh8Ux16 x y) -> (SRW  (ZeroExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
   205  (Lsh8x16 x y)  -> (SLW  x                (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt16to64 y)))))
   206  
   207  
   208  (Rsh64x8 x y)  -> (SRAD x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
   209  (Rsh64Ux8 x y) -> (SRD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
   210  (Lsh64x8 x y)  -> (SLD x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-64] (ZeroExt8to64 y)))))
   211  
   212  (Rsh32x8 x y)  -> (SRAW x (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
   213  (Rsh32Ux8 x y) -> (SRW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
   214  (Lsh32x8 x y)  -> (SLW x  (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-32] (ZeroExt8to64 y)))))
   215  
   216  (Rsh16x8 x y)  -> (SRAW (SignExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
   217  (Rsh16Ux8 x y) -> (SRW  (ZeroExt16to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
   218  (Lsh16x8 x y)  -> (SLW  x                 (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-16] (ZeroExt8to64 y)))))
   219  
   220  (Rsh8x8 x y)  -> (SRAW (SignExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
   221  (Rsh8Ux8 x y) -> (SRW  (ZeroExt8to32 x) (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
   222  (Lsh8x8 x y)  -> (SLW  x                (ORN y <config.fe.TypeInt64()> (MaskIfNotCarry (ADDconstForCarry [-8] (ZeroExt8to64 y)))))
   223  
   224  // Cleaning up shift ops when input is masked
   225  (MaskIfNotCarry (ADDconstForCarry [c] (ANDconst [d] _))) && c < 0 && d > 0 && c + d < 0 -> (MOVDconst [-1])
   226  (ORN x (MOVDconst [-1])) -> x
   227  
   228  // Potentially useful optimizing rewrites.
   229  // (ADDconstForCarry [k] c), k < 0 && (c < 0 || k+c >= 0) -> CarrySet
   230  // (ADDconstForCarry [k] c), K < 0 && (c >= 0 && k+c < 0) -> CarryClear
   231  // (MaskIfNotCarry CarrySet) -> 0
   232  // (MaskIfNotCarry CarrySet) -> -1
   233  
   234  (Addr {sym} base) -> (MOVDaddr {sym} base)
   235  // (Addr {sym} base) -> (ADDconst {sym} base)
   236  (OffPtr [off] ptr) -> (ADD (MOVDconst <config.Frontend().TypeInt64()> [off]) ptr)
   237  
   238  (And64 x y) -> (AND x y)
   239  (And32 x y) -> (AND x y)
   240  (And16 x y) -> (AND x y)
   241  (And8  x y) -> (AND x y)
   242  
   243  (Or64 x y) -> (OR x y)
   244  (Or32 x y) -> (OR x y)
   245  (Or16 x y) -> (OR x y)
   246  (Or8  x y) -> (OR x y)
   247  
   248  (Xor64 x y) -> (XOR x y)
   249  (Xor32 x y) -> (XOR x y)
   250  (Xor16 x y) -> (XOR x y)
   251  (Xor8  x y) -> (XOR x y)
   252  
   253  (Neg64F x) -> (FNEG x)
   254  (Neg32F x) -> (FNEG x)
   255  (Neg64  x) -> (NEG x)
   256  (Neg32  x) -> (NEG x)
   257  (Neg16  x) -> (NEG x)
   258  (Neg8   x) -> (NEG x)
   259  
   260  (Com64 x) -> (XORconst [-1] x)
   261  (Com32 x) -> (XORconst [-1] x)
   262  (Com16 x) -> (XORconst [-1] x)
   263  (Com8  x) -> (XORconst [-1] x)
   264  
   265  // Lowering boolean ops
   266  (AndB x y) -> (AND x y)
   267  (OrB x y) -> (OR x y)
   268  (Not x) -> (XORconst [1] x)
   269  
   270  // Use ANDN for AND x NOT y
   271  (AND x (XORconst [-1] y)) -> (ANDN x y)
   272  
   273  // Lowering comparisons
   274  (EqB x y)  -> (ANDconst [1] (EQV x y))
   275  // Sign extension dependence on operand sign sets up for sign/zero-extension elision later
   276  (Eq8 x y) && isSigned(x.Type) && isSigned(y.Type) -> (Equal (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   277  (Eq16 x y) && isSigned(x.Type) && isSigned(y.Type) -> (Equal (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   278  (Eq8 x y)  -> (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
   279  (Eq16 x y) -> (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
   280  (Eq32 x y) -> (Equal (CMPW x y))
   281  (Eq64 x y) -> (Equal (CMP x y))
   282  (Eq32F x y) -> (Equal (FCMPU x y))
   283  (Eq64F x y) -> (Equal (FCMPU x y))
   284  (EqPtr x y) -> (Equal (CMP x y))
   285  
   286  (NeqB x y)  -> (XOR x y)
   287  // Like Eq8 and Eq16, prefer sign extension likely to enable later elision.
   288  (Neq8 x y) && isSigned(x.Type) && isSigned(y.Type) -> (NotEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   289  (Neq16 x y) && isSigned(x.Type) && isSigned(y.Type) -> (NotEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   290  (Neq8 x y)  -> (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
   291  (Neq16 x y) -> (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
   292  (Neq32 x y) -> (NotEqual (CMPW x y))
   293  (Neq64 x y) -> (NotEqual (CMP x y))
   294  (Neq32F x y) -> (NotEqual (FCMPU x y))
   295  (Neq64F x y) -> (NotEqual (FCMPU x y))
   296  (NeqPtr x y) -> (NotEqual (CMP x y))
   297  
   298  (Less8 x y)  -> (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   299  (Less16 x y) -> (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   300  (Less32 x y) -> (LessThan (CMPW x y))
   301  (Less64 x y) -> (LessThan (CMP x y))
   302  (Less32F x y) -> (FLessThan (FCMPU x y))
   303  (Less64F x y) -> (FLessThan (FCMPU x y))
   304  
   305  (Less8U x y)  -> (LessThan (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
   306  (Less16U x y) -> (LessThan (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
   307  (Less32U x y) -> (LessThan (CMPWU x y))
   308  (Less64U x y) -> (LessThan (CMPU x y))
   309  
   310  (Leq8 x y)  -> (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   311  (Leq16 x y) -> (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   312  (Leq32 x y) -> (LessEqual (CMPW x y))
   313  (Leq64 x y) -> (LessEqual (CMP x y))
   314  (Leq32F x y) -> (FLessEqual (FCMPU x y))
   315  (Leq64F x y) -> (FLessEqual (FCMPU x y))
   316  
   317  (Leq8U x y)  -> (LessEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
   318  (Leq16U x y) -> (LessEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
   319  (Leq32U x y) -> (LessEqual (CMPWU x y))
   320  (Leq64U x y) -> (LessEqual (CMPU x y))
   321  
   322  (Greater8 x y)  -> (GreaterThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   323  (Greater16 x y) -> (GreaterThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   324  (Greater32 x y) -> (GreaterThan (CMPW x y))
   325  (Greater64 x y) -> (GreaterThan (CMP x y))
   326  (Greater32F x y) -> (FGreaterThan (FCMPU x y))
   327  (Greater64F x y) -> (FGreaterThan (FCMPU x y))
   328  
   329  (Greater8U x y)  -> (GreaterThan (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
   330  (Greater16U x y) -> (GreaterThan (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
   331  (Greater32U x y) -> (GreaterThan (CMPWU x y))
   332  (Greater64U x y) -> (GreaterThan (CMPU x y))
   333  
   334  (Geq8 x y)  -> (GreaterEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
   335  (Geq16 x y) -> (GreaterEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
   336  (Geq32 x y) -> (GreaterEqual (CMPW x y))
   337  (Geq64 x y) -> (GreaterEqual (CMP x y))
   338  (Geq32F x y) -> (FGreaterEqual (FCMPU x y))
   339  (Geq64F x y) -> (FGreaterEqual (FCMPU x y))
   340  
   341  (Geq8U x y)  -> (GreaterEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
   342  (Geq16U x y) -> (GreaterEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
   343  (Geq32U x y) -> (GreaterEqual (CMPWU x y))
   344  (Geq64U x y) -> (GreaterEqual (CMPU x y))
   345  
   346  // Absorb pseudo-ops into blocks.
   347  (If (Equal cc) yes no) -> (EQ cc yes no)
   348  (If (NotEqual cc) yes no) -> (NE cc yes no)
   349  (If (LessThan cc) yes no) -> (LT cc yes no)
   350  (If (LessEqual cc) yes no) -> (LE cc yes no)
   351  (If (GreaterThan cc) yes no) -> (GT cc yes no)
   352  (If (GreaterEqual cc) yes no) -> (GE cc yes no)
   353  (If (FLessThan cc) yes no) -> (FLT cc yes no)
   354  (If (FLessEqual cc) yes no) -> (FLE cc yes no)
   355  (If (FGreaterThan cc) yes no) -> (FGT cc yes no)
   356  (If (FGreaterEqual cc) yes no) -> (FGE cc yes no)
   357  
   358  (If cond yes no) -> (NE (CMPWconst [0] cond) yes no)
   359  
   360  // Absorb boolean tests into block
   361  (NE (CMPWconst [0] (Equal cc)) yes no) -> (EQ cc yes no)
   362  (NE (CMPWconst [0] (NotEqual cc)) yes no) -> (NE cc yes no)
   363  (NE (CMPWconst [0] (LessThan cc)) yes no) -> (LT cc yes no)
   364  (NE (CMPWconst [0] (LessEqual cc)) yes no) -> (LE cc yes no)
   365  (NE (CMPWconst [0] (GreaterThan cc)) yes no) -> (GT cc yes no)
   366  (NE (CMPWconst [0] (GreaterEqual cc)) yes no) -> (GE cc yes no)
   367  (NE (CMPWconst [0] (FLessThan cc)) yes no) -> (FLT cc yes no)
   368  (NE (CMPWconst [0] (FLessEqual cc)) yes no) -> (FLE cc yes no)
   369  (NE (CMPWconst [0] (FGreaterThan cc)) yes no) -> (FGT cc yes no)
   370  (NE (CMPWconst [0] (FGreaterEqual cc)) yes no) -> (FGE cc yes no)
   371  
   372  // Elide compares of bit tests // TODO need to make both CC and result of ANDCC available.
   373  (EQ (CMPconst [0] (ANDconst [c] x)) yes no) -> (EQ (ANDCCconst [c] x) yes no)
   374  (NE (CMPconst [0] (ANDconst [c] x)) yes no) -> (NE (ANDCCconst [c] x) yes no)
   375  (EQ (CMPWconst [0] (ANDconst [c] x)) yes no) -> (EQ (ANDCCconst [c] x) yes no)
   376  (NE (CMPWconst [0] (ANDconst [c] x)) yes no) -> (NE (ANDCCconst [c] x) yes no)
   377  
   378  // absorb flag constants into branches
   379  (EQ (FlagEQ) yes no) -> (First nil yes no)
   380  (EQ (FlagLT) yes no) -> (First nil no yes)
   381  (EQ (FlagGT) yes no) -> (First nil no yes)
   382  
   383  (NE (FlagEQ) yes no) -> (First nil no yes)
   384  (NE (FlagLT) yes no) -> (First nil yes no)
   385  (NE (FlagGT) yes no) -> (First nil yes no)
   386  
   387  (LT (FlagEQ) yes no) -> (First nil no yes)
   388  (LT (FlagLT) yes no) -> (First nil yes no)
   389  (LT (FlagGT) yes no) -> (First nil no yes)
   390  
   391  (LE (FlagEQ) yes no) -> (First nil yes no)
   392  (LE (FlagLT) yes no) -> (First nil yes no)
   393  (LE (FlagGT) yes no) -> (First nil no yes)
   394  
   395  (GT (FlagEQ) yes no) -> (First nil no yes)
   396  (GT (FlagLT) yes no) -> (First nil no yes)
   397  (GT (FlagGT) yes no) -> (First nil yes no)
   398  
   399  (GE (FlagEQ) yes no) -> (First nil yes no)
   400  (GE (FlagLT) yes no) -> (First nil no yes)
   401  (GE (FlagGT) yes no) -> (First nil yes no)
   402  
   403  // absorb InvertFlags into branches
   404  (LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
   405  (GT (InvertFlags cmp) yes no) -> (LT cmp yes no)
   406  (LE (InvertFlags cmp) yes no) -> (GE cmp yes no)
   407  (GE (InvertFlags cmp) yes no) -> (LE cmp yes no)
   408  (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
   409  (NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
   410  
   411  // constant comparisons
   412  (CMPWconst (MOVDconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ)
   413  (CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y)  -> (FlagLT)
   414  (CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y)  -> (FlagGT)
   415  
   416  (CMPconst (MOVDconst [x]) [y]) && int64(x)==int64(y) -> (FlagEQ)
   417  (CMPconst (MOVDconst [x]) [y]) && int64(x)<int64(y)  -> (FlagLT)
   418  (CMPconst (MOVDconst [x]) [y]) && int64(x)>int64(y)  -> (FlagGT)
   419  
   420  (CMPWUconst (MOVDconst [x]) [y]) && int32(x)==int32(y)  -> (FlagEQ)
   421  (CMPWUconst (MOVDconst [x]) [y]) && uint32(x)<uint32(y) -> (FlagLT)
   422  (CMPWUconst (MOVDconst [x]) [y]) && uint32(x)>uint32(y) -> (FlagGT)
   423  
   424  (CMPUconst (MOVDconst [x]) [y]) && int64(x)==int64(y)  -> (FlagEQ)
   425  (CMPUconst (MOVDconst [x]) [y]) && uint64(x)<uint64(y) -> (FlagLT)
   426  (CMPUconst (MOVDconst [x]) [y]) && uint64(x)>uint64(y) -> (FlagGT)
   427  
   428  // other known comparisons
   429  //(CMPconst (MOVBUreg _) [c]) && 0xff < c -> (FlagLT)
   430  //(CMPconst (MOVHUreg _) [c]) && 0xffff < c -> (FlagLT)
   431  //(CMPconst (ANDconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) -> (FlagLT)
   432  //(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n) -> (FlagLT)
   433  
   434  // absorb flag constants into boolean values
   435  (Equal (FlagEQ)) -> (MOVDconst [1])
   436  (Equal (FlagLT)) -> (MOVDconst [0])
   437  (Equal (FlagGT)) -> (MOVDconst [0])
   438  
   439  (NotEqual (FlagEQ)) -> (MOVDconst [0])
   440  (NotEqual (FlagLT)) -> (MOVDconst [1])
   441  (NotEqual (FlagGT)) -> (MOVDconst [1])
   442  
   443  (LessThan (FlagEQ)) -> (MOVDconst [0])
   444  (LessThan (FlagLT)) -> (MOVDconst [1])
   445  (LessThan (FlagGT)) -> (MOVDconst [0])
   446  
   447  (LessEqual (FlagEQ)) -> (MOVDconst [1])
   448  (LessEqual (FlagLT)) -> (MOVDconst [1])
   449  (LessEqual (FlagGT)) -> (MOVDconst [0])
   450  
   451  (GreaterThan (FlagEQ)) -> (MOVDconst [0])
   452  (GreaterThan (FlagLT)) -> (MOVDconst [0])
   453  (GreaterThan (FlagGT)) -> (MOVDconst [1])
   454  
   455  (GreaterEqual (FlagEQ)) -> (MOVDconst [1])
   456  (GreaterEqual (FlagLT)) -> (MOVDconst [0])
   457  (GreaterEqual (FlagGT)) -> (MOVDconst [1])
   458  
   459  // absorb InvertFlags into boolean values
   460  (Equal (InvertFlags x)) -> (Equal x)
   461  (NotEqual (InvertFlags x)) -> (NotEqual x)
   462  (LessThan (InvertFlags x)) -> (GreaterThan x)
   463  (GreaterThan (InvertFlags x)) -> (LessThan x)
   464  (LessEqual (InvertFlags x)) -> (GreaterEqual x)
   465  (GreaterEqual (InvertFlags x)) -> (LessEqual x)
   466  
   467  // Lowering loads
   468  (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
   469  (Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
   470  (Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) -> (MOVWZload ptr mem)
   471  (Load <t> ptr mem) && is16BitInt(t) && isSigned(t) -> (MOVHload ptr mem)
   472  (Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) -> (MOVHZload ptr mem)
   473  (Load <t> ptr mem) && t.IsBoolean() -> (MOVBZload ptr mem)
   474  (Load <t> ptr mem) && is8BitInt(t) && isSigned(t) -> (MOVBreg (MOVBZload ptr mem)) // PPC has no signed-byte load.
   475  (Load <t> ptr mem) && is8BitInt(t) && !isSigned(t) -> (MOVBZload ptr mem)
   476  
   477  (Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem)
   478  (Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
   479  
   480  (Store [8] ptr val mem) && is64BitFloat(val.Type) -> (FMOVDstore ptr val mem)
   481  (Store [8] ptr val mem) && is32BitFloat(val.Type) -> (FMOVDstore ptr val mem) // glitch from (Cvt32Fto64F x) -> x -- type is wrong
   482  (Store [4] ptr val mem) && is32BitFloat(val.Type) -> (FMOVSstore ptr val mem)
   483  (Store [8] ptr val mem) && (is64BitInt(val.Type) || isPtr(val.Type)) -> (MOVDstore ptr val mem)
   484  (Store [4] ptr val mem) && is32BitInt(val.Type) -> (MOVWstore ptr val mem)
   485  (Store [2] ptr val mem) -> (MOVHstore ptr val mem)
   486  (Store [1] ptr val mem) -> (MOVBstore ptr val mem)
   487  
   488  (Zero [s] _ mem) && SizeAndAlign(s).Size() == 0 -> mem
   489  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstorezero destptr mem)
   490  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 2 && SizeAndAlign(s).Align()%2 == 0 ->
   491  	(MOVHstorezero destptr mem)
   492  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 2 ->
   493  	(MOVBstorezero [1] destptr
   494  		(MOVBstorezero [0] destptr mem))
   495  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 4 && SizeAndAlign(s).Align()%4 == 0 ->
   496  	(MOVWstorezero destptr mem)
   497  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 4 && SizeAndAlign(s).Align()%2 == 0 ->
   498  	(MOVHstorezero [2] destptr
   499  		(MOVHstorezero [0] destptr mem))
   500  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 4 ->
   501  	(MOVBstorezero [3] destptr
   502  		(MOVBstorezero [2] destptr
   503  			(MOVBstorezero [1] destptr
   504  				(MOVBstorezero [0] destptr mem))))
   505  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%8 == 0 ->
   506  	(MOVDstorezero [0] destptr mem)
   507  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%4 == 0 ->
   508  	(MOVWstorezero [4] destptr
   509  		(MOVWstorezero [0] destptr mem))
   510  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%2 == 0 ->
   511  	(MOVHstorezero [6] destptr
   512  		(MOVHstorezero [4] destptr
   513  			(MOVHstorezero [2] destptr
   514  				(MOVHstorezero [0] destptr mem))))
   515  
   516  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 3 ->
   517  	(MOVBstorezero [2] destptr
   518  		(MOVBstorezero [1] destptr
   519  			(MOVBstorezero [0] destptr mem)))
   520  
   521  // Zero small numbers of words directly.
   522  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 16 && SizeAndAlign(s).Align()%8 == 0 ->
   523  	(MOVDstorezero [8] destptr
   524                  (MOVDstorezero [0] destptr mem))
   525  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 24 && SizeAndAlign(s).Align()%8 == 0 ->
   526  	(MOVDstorezero [16] destptr
   527  		(MOVDstorezero [8] destptr
   528  			(MOVDstorezero [0] destptr mem)))
   529  (Zero [s] destptr mem) && SizeAndAlign(s).Size() == 32 && SizeAndAlign(s).Align()%8 == 0 ->
   530  	(MOVDstorezero [24] destptr
   531  		(MOVDstorezero [16] destptr
   532  			(MOVDstorezero [8] destptr
   533  				(MOVDstorezero [0] destptr mem))))
   534  
   535  // Large zeroing uses a loop
   536  (Zero [s] ptr mem)
   537  	&& (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%8 != 0 ->
   538  	(LoweredZero [SizeAndAlign(s).Align()]
   539  		ptr
   540  		(ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)])
   541  		mem)
   542  
   543  // moves
   544  (Move [s] _ _ mem) && SizeAndAlign(s).Size() == 0 -> mem
   545  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstore dst (MOVBZload src mem) mem)
   546  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 2 && SizeAndAlign(s).Align()%2 == 0 ->
   547  	(MOVHstore dst (MOVHZload src mem) mem)
   548  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 2 ->
   549  	(MOVBstore [1] dst (MOVBZload [1] src mem)
   550  		(MOVBstore dst (MOVBZload src mem) mem))
   551  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 4 && SizeAndAlign(s).Align()%4 == 0 ->
   552  	(MOVWstore dst (MOVWload src mem) mem)
   553  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 4 && SizeAndAlign(s).Align()%2 == 0 ->
   554  	(MOVHstore [2] dst (MOVHZload [2] src mem)
   555  		(MOVHstore dst (MOVHZload src mem) mem))
   556  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 4 ->
   557  	(MOVBstore [3] dst (MOVBZload [3] src mem)
   558  		(MOVBstore [2] dst (MOVBZload [2] src mem)
   559  			(MOVBstore [1] dst (MOVBZload [1] src mem)
   560  				(MOVBstore dst (MOVBZload src mem) mem))))
   561  
   562  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%8 == 0 ->
   563  	(MOVDstore dst (MOVDload src mem) mem)
   564  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%4 == 0 ->
   565  	(MOVWstore [4] dst (MOVWZload [4] src mem)
   566  		(MOVWstore dst (MOVWZload src mem) mem))
   567  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 8 && SizeAndAlign(s).Align()%2 == 0->
   568  	(MOVHstore [6] dst (MOVHZload [6] src mem)
   569  		(MOVHstore [4] dst (MOVHZload [4] src mem)
   570  			(MOVHstore [2] dst (MOVHZload [2] src mem)
   571  				(MOVHstore dst (MOVHZload src mem) mem))))
   572  
   573  (Move [s] dst src mem) && SizeAndAlign(s).Size() == 3 ->
   574  	(MOVBstore [2] dst (MOVBZload [2] src mem)
   575  		(MOVBstore [1] dst (MOVBZload [1] src mem)
   576  			(MOVBstore dst (MOVBZload src mem) mem)))
   577  
   578  // Large move uses a loop
   579  (Move [s] dst src mem)
   580  	&& (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%8 != 0 ->
   581  	(LoweredMove [SizeAndAlign(s).Align()]
   582  		dst
   583  		src
   584  		(ADDconst <src.Type> src [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)])
   585  		mem)
   586  
   587  // Calls
   588  // Lowering calls
   589  (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
   590  (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
   591  (DeferCall [argwid] mem) -> (CALLdefer [argwid] mem)
   592  (GoCall [argwid] mem) -> (CALLgo [argwid] mem)
   593  (InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
   594  
   595  // Miscellaneous
   596  (Convert <t> x mem) -> (MOVDconvert <t> x mem)
   597  (GetClosurePtr) -> (LoweredGetClosurePtr)
   598  (IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr))
   599  (IsInBounds idx len) -> (LessThan (CMPU idx len))
   600  (IsSliceInBounds idx len) -> (LessEqual (CMPU idx len))
   601  (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
   602  
   603  // Optimizations
   604  // Note that PPC "logical" immediates come in 0:15 and 16:31 unsigned immediate forms,
   605  // so ORconst, XORconst easily expand into a pair.
   606  
   607  // Include very-large constants in the const-const case.
   608  (AND (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c&d])
   609  (OR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c|d])
   610  (XOR (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c^d])
   611  
   612  // Discover consts
   613  (AND x (MOVDconst [c])) && isU16Bit(c) -> (ANDconst [c] x)
   614  (XOR x (MOVDconst [c])) && isU32Bit(c) -> (XORconst [c] x)
   615  (OR x (MOVDconst [c])) && isU32Bit(c) -> (ORconst [c] x)
   616  (AND (MOVDconst [c]) x) && isU16Bit(c) -> (ANDconst [c] x)
   617  (XOR (MOVDconst [c]) x) && isU32Bit(c) -> (XORconst [c] x)
   618  (OR (MOVDconst [c]) x) && isU32Bit(c) -> (ORconst [c] x)
   619  
   620  // Simplify consts
   621  (ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
   622  (ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x)
   623  (XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
   624  (ANDconst [-1] x) -> x
   625  (ANDconst [0] _) -> (MOVDconst [0])
   626  (XORconst [0] x) -> x
   627  (ORconst [-1] _) -> (MOVDconst [-1])
   628  (ORconst [0] x) -> x
   629  
   630  // zero-extend of small and -> small and
   631  (MOVBZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFF -> y
   632  (MOVHZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF -> y
   633  (MOVWZreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFFFFFF -> y
   634  (MOVWZreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0xFFFFFFFF -> y
   635  
   636  // sign extend of small-positive and -> small-positive-and
   637  (MOVBreg y:(ANDconst [c] _)) && uint64(c) <= 0x7F -> y
   638  (MOVHreg y:(ANDconst [c] _)) && uint64(c) <= 0x7FFF -> y
   639  (MOVWreg y:(ANDconst [c] _)) && uint64(c) <= 0xFFFF -> y // 0xFFFF is largest immediate constant, when regarded as 32-bit is > 0
   640  (MOVWreg y:(AND (MOVDconst [c]) _)) && uint64(c) <= 0x7FFFFFFF -> y
   641  
   642  // small and of zero-extend -> either zero-extend or small and
   643    // degenerate-and
   644  (ANDconst [c] y:(MOVBZreg _)) && c&0xFF == 0xFF -> y
   645  (ANDconst [c] y:(MOVHZreg _))  && c&0xFFFF == 0xFFFF -> y
   646  (ANDconst [c] y:(MOVWZreg _))  && c&0xFFFFFFFF == 0xFFFFFFFF -> y
   647    // normal case
   648  (ANDconst [c] (MOVBZreg x)) -> (ANDconst [c&0xFF] x)
   649  (ANDconst [c] (MOVHZreg x)) -> (ANDconst [c&0xFFFF] x)
   650  (ANDconst [c] (MOVWZreg x)) -> (ANDconst [c&0xFFFFFFFF] x)
   651  
   652  // Various redundant zero/sign extension combinations.
   653  (MOVBZreg y:(MOVBZreg _)) -> y  // repeat
   654  (MOVBreg y:(MOVBreg _)) -> y // repeat
   655  (MOVBreg (MOVBZreg x)) -> (MOVBreg x)
   656  (MOVBZreg (MOVBreg x)) -> (MOVBZreg x)
   657  
   658  // H - there are more combinations than these
   659  
   660  (MOVHZreg y:(MOVHZreg _)) -> y // repeat
   661  (MOVHZreg y:(MOVBZreg _)) -> y // wide of narrow
   662  
   663  (MOVHreg y:(MOVHreg _)) -> y // repeat
   664  (MOVHreg y:(MOVBreg _)) -> y // wide of narrow
   665  
   666  (MOVHreg y:(MOVHZreg x)) -> (MOVHreg x)
   667  (MOVHZreg y:(MOVHreg x)) -> (MOVHZreg x)
   668  
   669  // W - there are more combinations than these
   670  
   671  (MOVWZreg y:(MOVWZreg _)) -> y // repeat
   672  (MOVWZreg y:(MOVHZreg _)) -> y // wide of narrow
   673  (MOVWZreg y:(MOVBZreg _)) -> y // wide of narrow
   674  
   675  (MOVWreg y:(MOVWreg _)) -> y // repeat
   676  (MOVWreg y:(MOVHreg _)) -> y // wide of narrow
   677  (MOVWreg y:(MOVBreg _)) -> y // wide of narrow
   678  
   679  (MOVWreg y:(MOVWZreg x)) -> (MOVWreg x)
   680  (MOVWZreg y:(MOVWreg x)) -> (MOVWZreg x)
   681  
   682  // Arithmetic constant ops
   683  
   684  (ADD (MOVDconst [c]) x) && is32Bit(c) -> (ADDconst [c] x)
   685  (ADD x (MOVDconst [c])) && is32Bit(c) -> (ADDconst [c] x)
   686  (ADDconst [c] (ADDconst [d] x)) && is32Bit(c+d) -> (ADDconst [c+d] x)
   687  (ADDconst [0] x) -> x
   688  (SUB x (MOVDconst [c])) && is32Bit(-c) -> (ADDconst [-c] x)
   689  // TODO deal with subtract-from-const
   690  
   691  (ADDconst [c] (MOVDaddr [d] {sym} x)) -> (MOVDaddr [c+d] {sym} x)
   692  
   693  // Fold offsets for stores.
   694  (MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} x val mem)
   695  (MOVWstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} x val mem)
   696  (MOVHstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} x val mem)
   697  (MOVBstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} x val mem)
   698  
   699  (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is16Bit(off1+off2) -> (FMOVSstore [off1+off2] {sym} ptr val mem)
   700  (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is16Bit(off1+off2) -> (FMOVDstore [off1+off2] {sym} ptr val mem)
   701  
   702  (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   703          (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   704  (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   705          (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   706  (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   707          (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   708  (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   709          (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   710  
   711  (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   712          (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   713  (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   714          (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   715  
   716  (MOVBZload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   717          (MOVBZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   718  (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   719          (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   720  (MOVHZload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   721          (MOVHZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   722  (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   723          (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   724  (MOVWZload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   725          (MOVWZload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   726  (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   727          (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   728  (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   729          (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   730  (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   731          (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   732  
   733  // Fold offsets for loads.
   734  (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVSload [off1+off2] {sym} ptr mem)
   735  (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is16Bit(off1+off2) -> (FMOVDload [off1+off2] {sym} ptr mem)
   736  
   737  (MOVDload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVDload [off1+off2] {sym} x mem)
   738  (MOVWload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWload [off1+off2] {sym} x mem)
   739  (MOVWZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVWZload [off1+off2] {sym} x mem)
   740  (MOVHload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHload [off1+off2] {sym} x mem)
   741  (MOVHZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVHZload [off1+off2] {sym} x mem)
   742  (MOVBZload [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) -> (MOVBZload [off1+off2] {sym} x mem)
   743  
   744  // Store of zero -> storezero
   745  (MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVDstorezero [off] {sym} ptr mem)
   746  (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVWstorezero [off] {sym} ptr mem)
   747  (MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVHstorezero [off] {sym} ptr mem)
   748  (MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && c == 0 -> (MOVBstorezero [off] {sym} ptr mem)
   749  
   750  // Fold offsets for storezero
   751  (MOVDstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
   752      (MOVDstorezero [off1+off2] {sym} x mem)
   753  (MOVWstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
   754      (MOVWstorezero [off1+off2] {sym} x mem)
   755  (MOVHstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
   756      (MOVHstorezero [off1+off2] {sym} x mem)
   757  (MOVBstorezero [off1] {sym} (ADDconst [off2] x) mem) && is16Bit(off1+off2) ->
   758      (MOVBstorezero [off1+off2] {sym} x mem)
   759  
   760  // Fold symbols into storezero
   761  (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2) ->
   762      (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
   763  (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2) ->
   764      (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
   765  (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2) ->
   766      (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
   767  (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} x) mem) && canMergeSym(sym1,sym2) ->
   768      (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
   769  
   770  // Lowering extension
   771  // Note: we always extend to 64 bits even though some ops don't need that many result bits.
   772  (SignExt8to16  x) -> (MOVBreg x)
   773  (SignExt8to32  x) -> (MOVBreg x)
   774  (SignExt8to64  x) -> (MOVBreg x)
   775  (SignExt16to32 x) -> (MOVHreg x)
   776  (SignExt16to64 x) -> (MOVHreg x)
   777  (SignExt32to64 x) -> (MOVWreg x)
   778  
   779  (ZeroExt8to16  x) -> (MOVBZreg x)
   780  (ZeroExt8to32  x) -> (MOVBZreg x)
   781  (ZeroExt8to64  x) -> (MOVBZreg x)
   782  (ZeroExt16to32 x) -> (MOVHZreg x)
   783  (ZeroExt16to64 x) -> (MOVHZreg x)
   784  (ZeroExt32to64 x) -> (MOVWZreg x)
   785  
   786  (Trunc16to8  x) -> (MOVBreg x)
   787  (Trunc32to8  x) -> (MOVBreg x)
   788  (Trunc32to16 x) -> (MOVHreg x)
   789  (Trunc64to8  x) -> (MOVBreg x)
   790  (Trunc64to16 x) -> (MOVHreg x)
   791  (Trunc64to32 x) -> (MOVWreg x)
   792  
   793  (Slicemask <t> x) -> (SRADconst (NEG <t> x) [63])
   794  
   795  // Note that MOV??reg returns a 64-bit int, x is not necessarily that wide
   796  // This may interact with other patterns in the future. (Compare with arm64)
   797  (MOVBZreg x:(MOVBZload _ _))  -> x
   798  (MOVHZreg x:(MOVHZload _ _))  -> x
   799  (MOVHreg x:(MOVHload _ _))  -> x
   800  
   801  (MOVBZreg (MOVDconst [c]))  -> (MOVDconst [int64(uint8(c))])
   802  (MOVBreg (MOVDconst [c]))  -> (MOVDconst [int64(int8(c))])
   803  (MOVHZreg (MOVDconst [c]))  -> (MOVDconst [int64(uint16(c))])
   804  (MOVHreg (MOVDconst [c]))  -> (MOVDconst [int64(int16(c))])
   805  
   806  // Lose widening ops fed to to stores
   807  (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   808  (MOVBstore [off] {sym} ptr (MOVBZreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   809  (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   810  (MOVHstore [off] {sym} ptr (MOVHZreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   811  (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
   812  (MOVWstore [off] {sym} ptr (MOVWZreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
   813  
   814  // Lose W-widening ops fed to compare-W
   815  (CMPW x (MOVWreg y)) -> (CMPW x y)
   816  (CMPW (MOVWreg x) y) -> (CMPW x y)
   817  (CMPWU x (MOVWZreg y)) -> (CMPWU x y)
   818  (CMPWU (MOVWZreg x) y) -> (CMPWU x y)
   819  
   820  (CMP x (MOVDconst [c])) && is16Bit(c) -> (CMPconst x [c])
   821  (CMP (MOVDconst [c]) y) && is16Bit(c) -> (InvertFlags (CMPconst y [c]))
   822  (CMPW x (MOVDconst [c])) && is16Bit(c) -> (CMPWconst x [c])
   823  (CMPW (MOVDconst [c]) y) && is16Bit(c) -> (InvertFlags (CMPWconst y [c]))
   824  
   825  (CMPU x (MOVDconst [c])) && isU16Bit(c) -> (CMPUconst x [c])
   826  (CMPU (MOVDconst [c]) y) && isU16Bit(c) -> (InvertFlags (CMPUconst y [c]))
   827  (CMPWU x (MOVDconst [c])) && isU16Bit(c) -> (CMPWUconst x [c])
   828  (CMPWU (MOVDconst [c]) y) && isU16Bit(c) -> (InvertFlags (CMPWUconst y [c]))
   829  
   830  // A particular pattern seen in cgo code:
   831  (AND (MOVDconst [c]) x:(MOVBZload _ _)) -> (ANDconst [c&0xFF] x)
   832  (AND x:(MOVBZload _ _) (MOVDconst [c])) -> (ANDconst [c&0xFF] x)