Text file src/cmd/compile/internal/ssa/_gen/divisible.rules

     1  // Copyright 2025 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  // Divisibility checks (x%c == 0 or x%c != 0) convert to multiply, rotate, compare.
     6  // The opt pass rewrote x%c to x-(x/c)*c
     7  // and then also rewrote x-(x/c)*c == 0 to x == (x/c)*c.
     8  // If x/c is being used for a division already (div.Uses != 1)
     9  // then we leave the expression alone.
    10  //
    11  // See ../magic.go for a detailed description of these algorithms.
    12  // See test/codegen/divmod.go for tests.
    13  // See divmod.rules for other division rules that run after these.
    14  
    15  // Divisiblity by unsigned or signed power of two.
    16  (Eq(8|16|32|64)  x (Mul(8|16|32|64) <t> (Div(8|16|32|64)u x (Const(8|16|32|64) [c])) (Const(8|16|32|64) [c])))
    17    && x.Op != OpConst64 && isPowerOfTwo(c) =>
    18    (Eq(8|16|32|64)  (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [c-1])) (Const(8|16|32|64) <t> [0]))
    19  (Eq(8|16|32|64)  x (Mul(8|16|32|64) <t> (Div(8|16|32|64)  x (Const(8|16|32|64) [c])) (Const(8|16|32|64) [c])))
    20    && x.Op != OpConst64 && isPowerOfTwo(c) =>
    21    (Eq(8|16|32|64)  (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [c-1])) (Const(8|16|32|64) <t> [0]))
    22  (Neq(8|16|32|64) x (Mul(8|16|32|64) <t> (Div(8|16|32|64)u x (Const(8|16|32|64) [c])) (Const(8|16|32|64) [c])))
    23    && x.Op != OpConst64 && isPowerOfTwo(c) =>
    24    (Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [c-1])) (Const(8|16|32|64) <t> [0]))
    25  (Neq(8|16|32|64) x (Mul(8|16|32|64) <t> (Div(8|16|32|64)  x (Const(8|16|32|64) [c])) (Const(8|16|32|64) [c])))
    26    && x.Op != OpConst64 && isPowerOfTwo(c) =>
    27    (Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [c-1])) (Const(8|16|32|64) <t> [0]))
    28  
    29  // Divisiblity by unsigned.
    30  (Eq8 x (Mul8 <t> div:(Div8u x (Const8 [c])) (Const8 [c])))
    31    && div.Uses == 1
    32    && x.Op != OpConst8 && udivisibleOK8(c) =>
    33    (Leq8U
    34      (RotateLeft8 <t>
    35        (Mul8 <t> x (Const8 <t> [int8(udivisible8(c).m)]))
    36        (Const8 <t> [int8(8 - udivisible8(c).k)]))
    37      (Const8 <t> [int8(udivisible8(c).max)]))
    38  (Neq8 x (Mul8 <t> div:(Div8u x (Const8 [c])) (Const8 [c])))
    39    && div.Uses == 1
    40    && x.Op != OpConst8 && udivisibleOK8(c) =>
    41    (Less8U
    42      (Const8 <t> [int8(udivisible8(c).max)])
    43      (RotateLeft8 <t>
    44        (Mul8 <t> x (Const8 <t> [int8(udivisible8(c).m)]))
    45        (Const8 <t> [int8(8 - udivisible8(c).k)])))
    46  (Eq16 x (Mul16 <t> div:(Div16u x (Const16 [c])) (Const16 [c])))
    47    && div.Uses == 1
    48    && x.Op != OpConst16 && udivisibleOK16(c) =>
    49    (Leq16U
    50      (RotateLeft16 <t>
    51        (Mul16 <t> x (Const16 <t> [int16(udivisible16(c).m)]))
    52        (Const16 <t> [int16(16 - udivisible16(c).k)]))
    53      (Const16 <t> [int16(udivisible16(c).max)]))
    54  (Neq16 x (Mul16 <t> div:(Div16u x (Const16 [c])) (Const16 [c])))
    55    && div.Uses == 1
    56    && x.Op != OpConst16 && udivisibleOK16(c) =>
    57    (Less16U
    58      (Const16 <t> [int16(udivisible16(c).max)])
    59      (RotateLeft16 <t>
    60        (Mul16 <t> x (Const16 <t> [int16(udivisible16(c).m)]))
    61        (Const16 <t> [int16(16 - udivisible16(c).k)])))
    62  (Eq32 x (Mul32 <t> div:(Div32u x (Const32 [c])) (Const32 [c])))
    63    && div.Uses == 1
    64    && x.Op != OpConst32 && udivisibleOK32(c) =>
    65    (Leq32U
    66      (RotateLeft32 <t>
    67        (Mul32 <t> x (Const32 <t> [int32(udivisible32(c).m)]))
    68        (Const32 <t> [int32(32 - udivisible32(c).k)]))
    69      (Const32 <t> [int32(udivisible32(c).max)]))
    70  (Neq32 x (Mul32 <t> div:(Div32u x (Const32 [c])) (Const32 [c])))
    71    && div.Uses == 1
    72    && x.Op != OpConst32 && udivisibleOK32(c) =>
    73    (Less32U
    74      (Const32 <t> [int32(udivisible32(c).max)])
    75      (RotateLeft32 <t>
    76        (Mul32 <t> x (Const32 <t> [int32(udivisible32(c).m)]))
    77        (Const32 <t> [int32(32 - udivisible32(c).k)])))
    78  (Eq64 x (Mul64 <t> div:(Div64u x (Const64 [c])) (Const64 [c])))
    79    && div.Uses == 1
    80    && x.Op != OpConst64 && udivisibleOK64(c) =>
    81    (Leq64U
    82      (RotateLeft64 <t>
    83        (Mul64 <t> x (Const64 <t> [int64(udivisible64(c).m)]))
    84        (Const64 <t> [int64(64 - udivisible64(c).k)]))
    85      (Const64 <t> [int64(udivisible64(c).max)]))
    86  (Neq64 x (Mul64 <t> div:(Div64u x (Const64 [c])) (Const64 [c])))
    87    && div.Uses == 1
    88    && x.Op != OpConst64 && udivisibleOK64(c) =>
    89    (Less64U
    90      (Const64 <t> [int64(udivisible64(c).max)])
    91      (RotateLeft64 <t>
    92        (Mul64 <t> x (Const64 <t> [int64(udivisible64(c).m)]))
    93        (Const64 <t> [int64(64 - udivisible64(c).k)])))
    94  
    95  // Divisiblity by signed.
    96  (Eq8 x (Mul8 <t> div:(Div8  x (Const8 [c])) (Const8 [c])))
    97    && div.Uses == 1
    98    && x.Op != OpConst8 && sdivisibleOK8(c) =>
    99    (Leq8U
   100      (RotateLeft8 <t>
   101        (Add8 <t> (Mul8 <t> x (Const8 <t> [int8(sdivisible8(c).m)]))
   102          (Const8 <t> [int8(sdivisible8(c).a)]))
   103        (Const8 <t> [int8(8 - sdivisible8(c).k)]))
   104      (Const8 <t> [int8(sdivisible8(c).max)]))
   105  (Neq8 x (Mul8 <t> div:(Div8  x (Const8 [c])) (Const8 [c])))
   106    && div.Uses == 1
   107    && x.Op != OpConst8 && sdivisibleOK8(c) =>
   108    (Less8U
   109      (Const8 <t> [int8(sdivisible8(c).max)])
   110      (RotateLeft8 <t>
   111        (Add8 <t> (Mul8 <t> x (Const8 <t> [int8(sdivisible8(c).m)]))
   112          (Const8 <t> [int8(sdivisible8(c).a)]))
   113        (Const8 <t> [int8(8 - sdivisible8(c).k)])))
   114  (Eq16 x (Mul16 <t> div:(Div16 x (Const16 [c])) (Const16 [c])))
   115    && div.Uses == 1
   116    && x.Op != OpConst16 && sdivisibleOK16(c) =>
   117    (Leq16U
   118      (RotateLeft16 <t>
   119        (Add16 <t> (Mul16 <t> x (Const16 <t> [int16(sdivisible16(c).m)]))
   120          (Const16 <t> [int16(sdivisible16(c).a)]))
   121        (Const16 <t> [int16(16 - sdivisible16(c).k)]))
   122      (Const16 <t> [int16(sdivisible16(c).max)]))
   123  (Neq16 x (Mul16 <t> div:(Div16 x (Const16 [c])) (Const16 [c])))
   124    && div.Uses == 1
   125    && x.Op != OpConst16 && sdivisibleOK16(c) =>
   126    (Less16U
   127      (Const16 <t> [int16(sdivisible16(c).max)])
   128      (RotateLeft16 <t>
   129        (Add16 <t> (Mul16 <t> x (Const16 <t> [int16(sdivisible16(c).m)]))
   130          (Const16 <t> [int16(sdivisible16(c).a)]))
   131        (Const16 <t> [int16(16 - sdivisible16(c).k)])))
   132  (Eq32 x (Mul32 <t> div:(Div32 x (Const32 [c])) (Const32 [c])))
   133    && div.Uses == 1
   134    && x.Op != OpConst32 && sdivisibleOK32(c) =>
   135    (Leq32U
   136      (RotateLeft32 <t>
   137        (Add32 <t> (Mul32 <t> x (Const32 <t> [int32(sdivisible32(c).m)]))
   138          (Const32 <t> [int32(sdivisible32(c).a)]))
   139        (Const32 <t> [int32(32 - sdivisible32(c).k)]))
   140      (Const32 <t> [int32(sdivisible32(c).max)]))
   141  (Neq32 x (Mul32 <t> div:(Div32 x (Const32 [c])) (Const32 [c])))
   142    && div.Uses == 1
   143    && x.Op != OpConst32 && sdivisibleOK32(c) =>
   144    (Less32U
   145      (Const32 <t> [int32(sdivisible32(c).max)])
   146      (RotateLeft32 <t>
   147        (Add32 <t> (Mul32 <t> x (Const32 <t> [int32(sdivisible32(c).m)]))
   148          (Const32 <t> [int32(sdivisible32(c).a)]))
   149        (Const32 <t> [int32(32 - sdivisible32(c).k)])))
   150  (Eq64 x (Mul64 <t> div:(Div64 x (Const64 [c])) (Const64 [c])))
   151    && div.Uses == 1
   152    && x.Op != OpConst64 && sdivisibleOK64(c) =>
   153    (Leq64U
   154      (RotateLeft64 <t>
   155        (Add64 <t> (Mul64 <t> x (Const64 <t> [int64(sdivisible64(c).m)]))
   156          (Const64 <t> [int64(sdivisible64(c).a)]))
   157        (Const64 <t> [int64(64 - sdivisible64(c).k)]))
   158      (Const64 <t> [int64(sdivisible64(c).max)]))
   159  (Neq64 x (Mul64 <t> div:(Div64 x (Const64 [c])) (Const64 [c])))
   160    && div.Uses == 1
   161    && x.Op != OpConst64 && sdivisibleOK64(c) =>
   162    (Less64U
   163      (Const64 <t> [int64(sdivisible64(c).max)])
   164      (RotateLeft64 <t>
   165        (Add64 <t> (Mul64 <t> x (Const64 <t> [int64(sdivisible64(c).m)]))
   166          (Const64 <t> [int64(sdivisible64(c).a)]))
   167        (Const64 <t> [int64(64 - sdivisible64(c).k)])))
   168  

View as plain text