@@ -1640,6 +1640,82 @@ def CIR_CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
16401640 let isLLVMLoweringRecursive = true;
16411641}
16421642
1643+ //===----------------------------------------------------------------------===//
1644+ // BinOpOverflowOp
1645+ //===----------------------------------------------------------------------===//
1646+
1647+ def CIR_BinOpOverflowKind : CIR_I32EnumAttr<
1648+ "BinOpOverflowKind", "checked binary arithmetic operation kind", [
1649+ I32EnumAttrCase<"Add", 0, "add">,
1650+ I32EnumAttrCase<"Sub", 1, "sub">,
1651+ I32EnumAttrCase<"Mul", 2, "mul">
1652+ ]>;
1653+
1654+ def CIR_BinOpOverflowOp : CIR_Op<"binop.overflow", [Pure, SameTypeOperands]> {
1655+ let summary = "Perform binary integral arithmetic with overflow checking";
1656+ let description = [{
1657+ `cir.binop.overflow` performs binary arithmetic operations with overflow
1658+ checking on integral operands.
1659+
1660+ The `kind` argument specifies the kind of arithmetic operation to perform.
1661+ It can be either `add`, `sub`, or `mul`. The `lhs` and `rhs` arguments
1662+ specify the input operands of the arithmetic operation. The types of `lhs`
1663+ and `rhs` must be the same.
1664+
1665+ `cir.binop.overflow` produces two SSA values. `result` is the result of the
1666+ arithmetic operation truncated to its specified type. `overflow` is a
1667+ boolean value indicating whether overflow happens during the operation.
1668+
1669+ The exact semantic of this operation is as follows:
1670+
1671+ - `lhs` and `rhs` are promoted to an imaginary integral type that has
1672+ infinite precision.
1673+ - The arithmetic operation is performed on the promoted operands.
1674+ - The infinite-precision result is truncated to the type of `result`. The
1675+ truncated result is assigned to `result`.
1676+ - If the truncated result is equal to the un-truncated result, `overflow`
1677+ is assigned to false. Otherwise, `overflow` is assigned to true.
1678+ }];
1679+
1680+ let arguments = (ins
1681+ CIR_BinOpOverflowKind:$kind,
1682+ CIR_IntType:$lhs,
1683+ CIR_IntType:$rhs
1684+ );
1685+
1686+ let results = (outs CIR_IntType:$result, CIR_BoolType:$overflow);
1687+
1688+ let assemblyFormat = [{
1689+ `(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
1690+ `(` qualified(type($result)) `,` qualified(type($overflow)) `)`
1691+ attr-dict
1692+ }];
1693+
1694+ let builders = [
1695+ OpBuilder<(ins "cir::IntType":$resultTy,
1696+ "cir::BinOpOverflowKind":$kind,
1697+ "mlir::Value":$lhs,
1698+ "mlir::Value":$rhs), [{
1699+ auto overflowTy = cir::BoolType::get($_builder.getContext());
1700+ build($_builder, $_state, resultTy, overflowTy, kind, lhs, rhs);
1701+ }]>
1702+ ];
1703+
1704+ let extraLLVMLoweringPatternDecl = [{
1705+ static std::string getLLVMIntrinName(cir::BinOpOverflowKind opKind,
1706+ bool isSigned, unsigned width);
1707+
1708+ struct EncompassedTypeInfo {
1709+ bool sign;
1710+ unsigned width;
1711+ };
1712+
1713+ static EncompassedTypeInfo computeEncompassedTypeWidth(cir::IntType operandTy,
1714+ cir::IntType resultTy);
1715+ }];
1716+ }
1717+
1718+
16431719//===----------------------------------------------------------------------===//
16441720// BinOp
16451721//===----------------------------------------------------------------------===//
0 commit comments