Documentation

SSA.Projects.InstCombine.LLVM.Semantics

def LLVM.IntW (w : ) :
Equations
Instances For
    def LLVM.and? {w : } (x : BitVec w) (y : BitVec w) :

    The ‘and’ instruction returns the bitwise logical and of its two operands.

    Equations
    Instances For
      theorem LLVM.and?_eq :
      ∀ {w : } {a b : BitVec w}, LLVM.and? a b = some (a.and b)
      def LLVM.and {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) :
      Equations
      Instances For
        def LLVM.or? {w : } (x : BitVec w) (y : BitVec w) :

        The ‘or’ instruction returns the bitwise logical inclusive or of its two operands.

        Equations
        Instances For
          theorem LLVM.or?_eq :
          ∀ {w : } {a b : BitVec w}, LLVM.or? a b = some (a.or b)
          Instances For
            def LLVM.or {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flag : optParam LLVM.DisjointFlag { disjoint := false }) :
            Equations
            Instances For
              def LLVM.xor? {w : } (x : BitVec w) (y : BitVec w) :

              The ‘xor’ instruction returns the bitwise logical exclusive or of its two operands. The xor is used to implement the “one’s complement” operation, which is the “~” operator in C.

              Equations
              Instances For
                theorem LLVM.xor?_eq :
                ∀ {w : } {a b : BitVec w}, LLVM.xor? a b = some (a.xor b)
                def LLVM.xor {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) :
                Equations
                Instances For
                  def LLVM.add? {w : } (x : BitVec w) (y : BitVec w) :

                  The value produced is the integer sum of the two operands. If the sum has unsigned overflow, the result returned is the mathematical result modulo 2n, where n is the bit width of the result. Because LLVM integers use a two’s complement representation, this instruction is appropriate for both signed and unsigned integers.

                  Equations
                  Instances For
                    theorem LLVM.add?_eq :
                    ∀ {w : } {a b : BitVec w}, LLVM.add? a b = some (a.add b)
                    Instances For
                      def LLVM.add {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flags : optParam LLVM.NoWrapFlags { nsw := false, nuw := false }) :
                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For
                        def LLVM.sub? {w : } (x : BitVec w) (y : BitVec w) :

                        The value produced is the integer difference of the two operands. If the difference has unsigned overflow, the result returned is the mathematical result modulo 2n, where n is the bit width of the result. Because LLVM integers use a two’s complement representation, this instruction is appropriate for both signed and unsigned integers.

                        Equations
                        Instances For
                          theorem LLVM.sub?_eq :
                          ∀ {w : } {a b : BitVec w}, LLVM.sub? a b = some (a.sub b)
                          def LLVM.sub {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flags : optParam LLVM.NoWrapFlags { nsw := false, nuw := false }) :
                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            def LLVM.mul? {w : } (x : BitVec w) (y : BitVec w) :

                            The value produced is the integer product of the two operands. If the result of the multiplication has unsigned overflow, the result returned is the mathematical result modulo 2n, where n is the bit width of the result. Because LLVM integers use a two’s complement representation, and the result is the same width as the operands, this instruction returns the correct result for both signed and unsigned integers.

                            If a full product (e.g. i32 * i32 -> i64) is needed, the operands should be sign-extended or zero-extended as appropriate to the width of the full product.

                            Equations
                            Instances For
                              theorem LLVM.mul?_eq :
                              ∀ {w : } {a b : BitVec w}, LLVM.mul? a b = some (a.mul b)
                              def LLVM.mul {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flags : optParam LLVM.NoWrapFlags { nsw := false, nuw := false }) :
                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                def LLVM.udiv? {w : } (x : BitVec w) (y : BitVec w) :

                                The value produced is the unsigned integer quotient of the two operands. Note that unsigned integer division and signed integer division are distinct operations; for signed integer division, use ‘sdiv’. Division by zero is undefined behavior.

                                Equations
                                Instances For
                                  structure LLVM.ExactFlag :
                                  Instances For
                                    def LLVM.udiv {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flag : optParam LLVM.ExactFlag { exact := false }) :
                                    Equations
                                    Instances For
                                      def LLVM.sdiv? {w : } (x : BitVec w) (y : BitVec w) :

                                      The value produced is the signed integer quotient of the two operands rounded towards zero. Note that signed integer division and unsigned integer division are distinct operations; for unsigned integer division, use ‘udiv’. Division by zero is undefined behavior. Overflow also leads to undefined behavior; this is a rare case, but can occur, for example, by doing a 32-bit division of -2147483648 by -1.

                                      Notes #

                                      The rounding is round to zero, not round to -infty. at width 1, -1 / -1 is considered -1 at width 2, -4 / -1 is considered overflow!

                                      Equations
                                      Instances For
                                        theorem LLVM.sdiv?_eq_pure_of_neq_allOnes {w : } {x : BitVec w} {y : BitVec w} (hy : y 0) (hx : BitVec.intMin w x) :
                                        LLVM.sdiv? x y = pure (x.sdiv y)
                                        def LLVM.sdiv {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flag : optParam LLVM.ExactFlag { exact := false }) :
                                        Equations
                                        Instances For
                                          theorem LLVM.sdiv?_eq_div_if {w : } {x : BitVec w} {y : BitVec w} :
                                          LLVM.sdiv? x y = if y = 0 w 1 x = BitVec.intMin w y = -1 then none else pure (x.sdiv y)
                                          def LLVM.urem? {w : } (x : BitVec w) (y : BitVec w) :

                                          This instruction returns the unsigned integer remainder of a division. This instruction always performs an unsigned division to get the remainder. Note that unsigned integer remainder and signed integer remainder are distinct operations; for signed integer remainder, use ‘srem’. Taking the remainder of a division by zero is undefined behavior.

                                          Equations
                                          Instances For
                                            def LLVM.urem {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) :
                                            Equations
                                            Instances For
                                              def Int.rem (x : ) (y : ) :
                                              Equations
                                              • x.rem y = if x 0 then x % y else x % y - y.natAbs
                                              Instances For
                                                theorem Int.rem_sign_dividend (x : ) (y : ) :
                                                x.rem y < 0 x < 0
                                                def LLVM.srem? {w : } (x : BitVec w) (y : BitVec w) :

                                                This instruction returns the remainder of a division (where the result is either zero or has the same sign as the dividend, op1), not the modulo operator (where the result is either zero or has the same sign as the divisor, op2) of a value. For more information about the difference, see The Math Forum. For a table of how this is implemented in various languages, please see Wikipedia: modulo operation. Note that signed integer remainder and unsigned integer remainder are distinct operations; for unsigned integer remainder, use ‘urem’. Taking the remainder of a division by zero is undefined behavior. For vectors, if any element of the divisor is zero, the operation has undefined behavior. Overflow also leads to undefined behavior; this is a rare case, but can occur, for example, by taking the remainder of a 32-bit division of -2147483648 by -1. (The remainder doesn’t actually overflow, but this rule lets srem be implemented using instructions that return both the result of the division and the remainder.)

                                                The fundamental equation of div/rem is: x = (x/y) * y + x%y => x%y = x - (x/y) We use this equation to define srem.

                                                Equations
                                                Instances For
                                                  def LLVM.srem {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) :
                                                  Equations
                                                  Instances For
                                                    def LLVM.sshr {n : } (a : BitVec n) (s : ) :
                                                    Equations
                                                    Instances For
                                                      def LLVM.shl? {n : } (op1 : BitVec n) (op2 : BitVec n) :

                                                      Shift left instruction. The value produced is op1 * 2^op2 mod 2n, where n is the width of the result. If op2 is (statically or dynamically) equal to or larger than the number of bits in op1, this instruction returns a poison value.

                                                      Equations
                                                      Instances For
                                                        def LLVM.shl {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flags : optParam LLVM.NoWrapFlags { nsw := false, nuw := false }) :
                                                        Equations
                                                        • One or more equations did not get rendered due to their size.
                                                        Instances For
                                                          def LLVM.lshr? {n : } (op1 : BitVec n) (op2 : BitVec n) :

                                                          This instruction always performs a logical shift right operation. The most significant bits of the result will be filled with zero bits after the shift.

                                                          If op2 is (statically or dynamically) equal to or larger than the number of bits in op1, this instruction returns a poison value.

                                                          Corresponds to Std.BitVec.ushiftRight in the pure case.

                                                          Equations
                                                          Instances For
                                                            def LLVM.lshr {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flag : optParam LLVM.ExactFlag { exact := false }) :
                                                            Equations
                                                            Instances For
                                                              def LLVM.ashr? {n : } (op1 : BitVec n) (op2 : BitVec n) :

                                                              This instruction always performs an arithmetic shift right operation, The most significant bits of the result will be filled with the sign bit of op1.

                                                              If op2 is (statically or dynamically) equal to or larger than the number of bits in op1, this instruction returns a poison value.

                                                              Corresponds to Std.BitVec.sshiftRight in the pure case.

                                                              Equations
                                                              Instances For
                                                                def LLVM.ashr {w : } (x : LLVM.IntW w) (y : LLVM.IntW w) (flag : optParam LLVM.ExactFlag { exact := false }) :
                                                                Equations
                                                                Instances For
                                                                  def LLVM.select {w : } (c? : LLVM.IntW 1) (x? : LLVM.IntW w) (y? : LLVM.IntW w) :

                                                                  If the condition is an i1 and it evaluates to 1, the instruction returns the first value argument; otherwise, it returns the second value argument.

                                                                  If the condition is an i1 and it evaluates to 1, the instruction returns the first value argument; otherwise, it returns the second value argument.

                                                                  Equations
                                                                  Instances For
                                                                    Equations
                                                                    Equations
                                                                    • One or more equations did not get rendered due to their size.
                                                                    def LLVM.icmp' {w : } (c : LLVM.IntPredicate) (x : BitVec w) (y : BitVec w) :

                                                                    The ‘icmp’ instruction takes three operands. The first operand is the condition code indicating the kind of comparison to perform. It is not a value, just a keyword. The possible condition codes are:

                                                                    • eq: equal
                                                                    • ne: not equal
                                                                    • ugt: unsigned greater than
                                                                    • uge: unsigned greater or equal
                                                                    • ult: unsigned less than
                                                                    • ule: unsigned less or equal
                                                                    • sgt: signed greater than
                                                                    • sge: signed greater or equal
                                                                    • slt: signed less than
                                                                    • sle: signed less or equal

                                                                    The remaining two arguments must be integer. They must also be identical types.

                                                                    Equations
                                                                    Instances For
                                                                      def LLVM.icmp? {w : } (c : LLVM.IntPredicate) (x : BitVec w) (y : BitVec w) :

                                                                      Wrapper around icmp (this cannot become none on its own).

                                                                      The ‘icmp’ instruction takes three operands. The first operand is the condition code indicating the kind of comparison to perform. It is not a value, just a keyword. The possible condition codes are:

                                                                      • eq: equal
                                                                      • ne: not equal
                                                                      • ugt: unsigned greater than
                                                                      • uge: unsigned greater or equal
                                                                      • ult: unsigned less than
                                                                      • ule: unsigned less or equal
                                                                      • sgt: signed greater than
                                                                      • sge: signed greater or equal
                                                                      • slt: signed less than
                                                                      • sle: signed less or equal

                                                                      The remaining two arguments must be integer. They must also be identical types.

                                                                      Equations
                                                                      Instances For
                                                                        def LLVM.icmp {w : } (c : LLVM.IntPredicate) (x : LLVM.IntW w) (y : LLVM.IntW w) :
                                                                        Equations
                                                                        Instances For
                                                                          def LLVM.const? {w : } (i : ) :

                                                                          Unlike LLVM IR, MLIR does not have first-class constant values. Therefore, all constants must be created as SSA values before being used in other operations. llvm.mlir.constant creates such values for scalars and vectors. It has a mandatory value attribute, which must be an integer (currently the only supported type in these semantics).

                                                                          The type of the attribute is one of the corresponding MLIR builtin types. The operation produces a new SSA value of the specified LLVM IR dialect type. The type of that value must correspond to the attribute type converted to LLVM IR.

                                                                          This interprets the value as a signed bitvector. If the bitwidth is not enough it will be reduced, returning the value (2^w + (i mod 2^w)) mod 2^w.

                                                                          TODO: double-check that truncating works the same as MLIR (signedness, overflow, etc)

                                                                          Equations
                                                                          Instances For
                                                                            def LLVM.not? {w : } (x : BitVec w) :
                                                                            Equations
                                                                            Instances For
                                                                              theorem LLVM.not?_eq :
                                                                              ∀ {w : } {a : BitVec w}, LLVM.not? a = some a.not
                                                                              def LLVM.not {w : } (x : LLVM.IntW w) :
                                                                              Equations
                                                                              Instances For
                                                                                def LLVM.neg? {w : } (x : BitVec w) :
                                                                                Equations
                                                                                Instances For
                                                                                  theorem LLVM.neg?_eq :
                                                                                  ∀ {w : } {a : BitVec w}, LLVM.neg? a = some a.neg
                                                                                  def LLVM.neg {w : } (x : LLVM.IntW w) :
                                                                                  Equations
                                                                                  Instances For