[clang] [CIR] Split cir.binop into separate per-operation binary ops (PR #184227)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 2 12:58:15 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Henrich Lauko (xlauko)
<details>
<summary>Changes</summary>
LLVM lowering uses per-op patterns generated by the CIRLowering.inc TableGen
infrastructure instead of a monolithic TypeSwitch dispatch.
---
Patch is 817.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/184227.diff
108 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+49-28)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+236-51)
- (modified) clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td (+18)
- (modified) clang/include/clang/CIR/Interfaces/CIROpInterfaces.td (+26)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+4-4)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+10-16)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp (+14-14)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+11-23)
- (modified) clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.cpp (+2-2)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+30-22)
- (modified) clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp (+2-3)
- (modified) clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp (+40-59)
- (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp (+28-14)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+126-103)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+1)
- (modified) clang/test/CIR/CodeGen/assign-operator.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/atomic.c (+49-49)
- (modified) clang/test/CIR/CodeGen/basic.c (+3-3)
- (modified) clang/test/CIR/CodeGen/basic.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/binop.cpp (+12-12)
- (modified) clang/test/CIR/CodeGen/bitfields.c (+1-1)
- (modified) clang/test/CIR/CodeGen/complex-compound-assignment.cpp (+29-29)
- (modified) clang/test/CIR/CodeGen/complex-mul-div.cpp (+124-124)
- (modified) clang/test/CIR/CodeGen/complex.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/compound_assign.cpp (+8-8)
- (modified) clang/test/CIR/CodeGen/if.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/integer-overflow.c (+6-6)
- (modified) clang/test/CIR/CodeGen/lambda.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/namespace.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/new.cpp (+5-5)
- (modified) clang/test/CIR/CodeGen/no-odr-use.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/non-type-template-param.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/opaque.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/pointer-to-member-func-cast.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/pointer-to-member-func-cmp.cpp (+4-4)
- (modified) clang/test/CIR/CodeGen/pointer-to-member-func.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/requires-expr.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/size-of-vla.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/struct-init.cpp (+3-3)
- (modified) clang/test/CIR/CodeGen/switch_flat_op.cpp (+4-4)
- (modified) clang/test/CIR/CodeGen/ternary.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/throws.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/try-catch.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/variable-decomposition.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/vector-ext-element.cpp (+4-4)
- (modified) clang/test/CIR/CodeGen/vector-ext.cpp (+15-15)
- (modified) clang/test/CIR/CodeGen/vector.cpp (+17-17)
- (modified) clang/test/CIR/CodeGen/vla.c (+3-3)
- (modified) clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c (+12-12)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx10_2_512bf16-builtins.c (+1-1)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx10_2bf16-builtins.c (+2-2)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx2-builtins.c (+4-4)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512bw-builtins.c (+14-14)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512dq-builtins.c (+491-491)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512f-builtins.c (+11-11)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512fp16-builtins.c (+1-1)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx512vldq-builtins.c (+4-4)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/cmp-builtins.c (+23-23)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/sse2-builtins.c (+3-3)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c (+92-92)
- (modified) clang/test/CIR/CodeGenOpenACC/atomic-capture.cpp (+18-18)
- (modified) clang/test/CIR/CodeGenOpenACC/atomic-update.cpp (+5-5)
- (modified) clang/test/CIR/CodeGenOpenACC/atomic-write.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-firstprivate-clause.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-default-ops.cpp (+57-57)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-float.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-inline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-int.cpp (+15-15)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-reduction-clause-outline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/combined.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-private-clause.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-default-ops.c (+57-57)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-default-ops.cpp (+57-57)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-float.c (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-float.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-inline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-int.c (+15-15)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-int.cpp (+15-15)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-outline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-reduction-clause-unsigned-int.c (+15-15)
- (modified) clang/test/CIR/CodeGenOpenACC/firstprivate-clause-recipes.cpp (+23-23)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-private-clause.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-default-ops.cpp (+57-57)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-float.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-inline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-int.cpp (+15-15)
- (modified) clang/test/CIR/CodeGenOpenACC/loop-reduction-clause-outline-ops.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenOpenACC/loop.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-array-recipes-CtorDtor.cpp (+8-8)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-array-recipes-CtorDtor.cpp (+73-73)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-array-recipes-NoOps.cpp (+52-52)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-array-recipes-int.cpp (+52-52)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-recipes-CtorDtor.cpp (+30-30)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-recipes-NoOps.cpp (+24-24)
- (modified) clang/test/CIR/CodeGenOpenACC/private-clause-pointer-recipes-int.cpp (+24-24)
- (modified) clang/test/CIR/CodeGenOpenACC/reduction-clause-recipes.cpp (+25-25)
- (modified) clang/test/CIR/CodeGenOpenMP/omp-llvmir.c (+1-1)
- (modified) clang/test/CIR/CodeGenOpenMP/parallel.c (+2-2)
- (modified) clang/test/CIR/IR/throw.cir (+2-2)
- (modified) clang/test/CIR/IR/vector.cir (+2-2)
- (modified) clang/test/CIR/Lowering/binop-bool.cir (+3-3)
- (modified) clang/test/CIR/Lowering/binop-fp.cir (+8-8)
- (modified) clang/test/CIR/Lowering/binop-signed-int.cir (+11-11)
- (modified) clang/test/CIR/Lowering/binop-unsigned-int.cir (+11-11)
- (modified) clang/test/CIR/Transforms/switch.cir (+2-2)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 32d0921d15363..117ee06a16714 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -544,11 +544,36 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
// Binary Operators
//===--------------------------------------------------------------------===//
- mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
- cir::BinOpKind kind, mlir::Value rhs) {
- return cir::BinOp::create(*this, loc, lhs.getType(), kind, lhs, rhs);
+private:
+ // Builds a simple binary op whose result type equals the operand type.
+ template <typename Op>
+ mlir::Value createBinaryOp(mlir::Location loc, mlir::Value lhs,
+ mlir::Value rhs) {
+ return Op::create(*this, loc, lhs, rhs);
+ }
+
+ // Builds a binary op with nsw/nuw overflow flags (no sat, e.g. Mul).
+ template <typename Op>
+ mlir::Value createOverflowOp(mlir::Location loc, mlir::Value lhs,
+ mlir::Value rhs, OverflowBehavior ob) {
+ auto op = Op::create(*this, loc, lhs, rhs);
+ op.setNoUnsignedWrap(ob & OverflowBehavior::NoUnsignedWrap);
+ op.setNoSignedWrap(ob & OverflowBehavior::NoSignedWrap);
+ return op;
+ }
+
+ // Builds a binary op with nsw/nuw overflow flags and saturation (Add, Sub).
+ template <typename Op>
+ mlir::Value createOverflowSatOp(mlir::Location loc, mlir::Value lhs,
+ mlir::Value rhs, OverflowBehavior ob) {
+ auto op = Op::create(*this, loc, lhs, rhs);
+ op.setNoUnsignedWrap(ob & OverflowBehavior::NoUnsignedWrap);
+ op.setNoSignedWrap(ob & OverflowBehavior::NoSignedWrap);
+ op.setSaturated(ob & OverflowBehavior::Saturated);
+ return op;
}
+public:
mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
unsigned bits) {
llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
@@ -557,11 +582,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
}
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+ return createBinaryOp<cir::AndOp>(loc, lhs, rhs);
}
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- return createBinop(loc, lhs, cir::BinOpKind::Or, rhs);
+ return createBinaryOp<cir::OrOp>(loc, lhs, rhs);
}
mlir::Value createSelect(mlir::Location loc, mlir::Value condition,
@@ -584,13 +609,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
OverflowBehavior ob = OverflowBehavior::None) {
- auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Mul,
- lhs, rhs);
- op.setNoUnsignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
- return op;
+ return createOverflowOp<cir::MulOp>(loc, lhs, rhs, ob);
}
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
mlir::Value rhs) {
@@ -603,14 +622,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
OverflowBehavior ob = OverflowBehavior::None) {
- auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Sub,
- lhs, rhs);
- op.setNoUnsignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
- op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
- return op;
+ return createOverflowSatOp<cir::SubOp>(loc, lhs, rhs, ob);
}
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs,
@@ -625,14 +637,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
OverflowBehavior ob = OverflowBehavior::None) {
- auto op = cir::BinOp::create(*this, loc, lhs.getType(), cir::BinOpKind::Add,
- lhs, rhs);
- op.setNoUnsignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(
- llvm::to_underlying(ob & OverflowBehavior::NoSignedWrap));
- op.setSaturated(llvm::to_underlying(ob & OverflowBehavior::Saturated));
- return op;
+ return createOverflowSatOp<cir::AddOp>(loc, lhs, rhs, ob);
}
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs,
@@ -645,6 +650,22 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
}
+ mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ return createBinaryOp<cir::DivOp>(loc, lhs, rhs);
+ }
+
+ mlir::Value createRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ return createBinaryOp<cir::RemOp>(loc, lhs, rhs);
+ }
+
+ mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ return createBinaryOp<cir::XorOp>(loc, lhs, rhs);
+ }
+
+ mlir::Value createMax(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ return createBinaryOp<cir::MaxOp>(loc, lhs, rhs);
+ }
+
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
mlir::Value lhs, mlir::Value rhs) {
return cir::CmpOp::create(*this, loc, kind, lhs, rhs);
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a5a5197cd3ea6..1315cde17f946 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2119,76 +2119,261 @@ def CIR_BinOpOverflowOp : CIR_Op<"binop.overflow", [Pure, SameTypeOperands]> {
//===----------------------------------------------------------------------===//
-// BinOp
-//===----------------------------------------------------------------------===//
-
-// FIXME: represent Commutative, Idempotent traits for appropriate binops
-def CIR_BinOpKind : CIR_I32EnumAttr<
- "BinOpKind", "binary operation (arith and logic) kind", [
- I32EnumAttrCase<"Mul", 0, "mul">,
- I32EnumAttrCase<"Div", 1, "div">,
- I32EnumAttrCase<"Rem", 2, "rem">,
- I32EnumAttrCase<"Add", 3, "add">,
- I32EnumAttrCase<"Sub", 4, "sub">,
- I32EnumAttrCase<"And", 5, "and">,
- I32EnumAttrCase<"Xor", 6, "xor">,
- I32EnumAttrCase<"Or", 7, "or">,
- I32EnumAttrCase<"Max", 8, "max">
-]>;
+// Binary Arithmetic and Logic Operations
+//===----------------------------------------------------------------------===//
-def CIR_BinOp : CIR_Op<"binop", [
- Pure, SameTypeOperands, SameOperandsAndResultType
-]> {
- let summary = "Binary operations (arith and logic)";
+// Base class for all CIR binary arithmetic/logic operations.
+// `type` constrains the lhs/rhs/result type.
+class CIR_BinaryOp<string mnemonic, Type type, list<Trait> traits = []>
+ : CIR_Op<mnemonic, !listconcat([
+ NoMemoryEffect, SameOperandsAndResultType,
+ DeclareOpInterfaceMethods<CIR_BinaryOpInterface>
+ ], traits)>
+{
+ let arguments = (ins
+ type:$lhs,
+ type:$rhs
+ );
+
+ let results = (outs type:$result);
+
+ let assemblyFormat = [{
+ $lhs `,` $rhs `:` type($lhs) attr-dict
+ }];
+}
+
+// Base class for binary ops that support integer overflow flags (nsw/nuw)
+// and saturated arithmetic.
+class CIR_BinaryOverflowOp<string mnemonic, Type type, list<Trait> traits = []>
+ : CIR_BinaryOp<mnemonic, type, !listconcat([Pure], traits)>
+{
+ let arguments = (ins
+ type:$lhs, type:$rhs,
+ UnitProp:$no_signed_wrap,
+ UnitProp:$no_unsigned_wrap,
+ UnitProp:$saturated
+ );
+
+ let assemblyFormat = [{
+ (`nsw` $no_signed_wrap^)?
+ (`nuw` $no_unsigned_wrap^)?
+ (`sat` $saturated^)?
+ $lhs `,` $rhs `:` type($lhs) attr-dict
+ }];
+
+ let hasVerifier = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// AddOp
+//===----------------------------------------------------------------------===//
+
+def CIR_AddOp : CIR_BinaryOverflowOp<"add", CIR_AnyArithType> {
+ let summary = "Integer or floating-point addition";
let description = [{
- cir.binop performs the binary operation according to
- the specified opcode kind: [mul, div, rem, add, sub,
- and, xor, or, max].
+ The `cir.add` operation performs addition on integer or floating-point
+ operands. Both operands and the result must have the same type.
- It requires two input operands and has one result, all types
- should be the same.
+ For integer types, the optional `nsw` (no signed wrap) and `nuw` (no
+ unsigned wrap) unit attributes indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively. The optional `sat` (saturated)
+ attribute clamps the result to the type's representable range instead of
+ wrapping. The `nsw`/`nuw` flags and `sat` are mutually exclusive.
+
+ Example:
+
+ ```mlir
+ %0 = cir.add %a, %b : !s32i
+ %1 = cir.add %a, %b nsw : !s32i
+ %2 = cir.add %a, %b nuw : !u32i
+ %3 = cir.add %a, %b sat : !s32i
+ %4 = cir.add %a, %b : !cir.float
+ ```
+ }];
+}
- If the `nsw` (no signed wrap) or `nuw` (no unsigned wrap) attributes are
- present, the result is poison if signed or unsigned overflow occurs
- (respectively).
+//===----------------------------------------------------------------------===//
+// SubOp
+//===----------------------------------------------------------------------===//
- If the `sat` (saturated) attribute is present, the result is clamped to
- the maximum value representatable by the type if it would otherwise
- exceed that value and is clamped to the minimum representable value if
- it would otherwise be below that value.
+def CIR_SubOp : CIR_BinaryOverflowOp<"sub", CIR_AnyArithType> {
+ let summary = "Integer or floating-point subtraction";
+ let description = [{
+ The `cir.sub` operation performs subtraction on integer or floating-point
+ operands. Both operands and the result must have the same type.
+
+ For integer types, the optional `nsw` (no signed wrap) and `nuw` (no
+ unsigned wrap) unit attributes indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively. The optional `sat` (saturated)
+ attribute clamps the result to the type's representable range. The
+ `nsw`/`nuw` flags and `sat` are mutually exclusive.
+
+ Example:
```mlir
- %5 = cir.binop(add, %1, %2) : !s32i
- %6 = cir.binop(mul, %1, %2) : !u8i
- %7 = cir.binop(add, %1, %2) nsw : !s32i
- %8 = cir.binop(add, %3, %4) nuw : !u32i
- %9 = cir.binop(add, %1, %2) sat : !s32i
+ %0 = cir.sub %a, %b : !s32i
+ %1 = cir.sub %a, %b nsw : !s32i
+ %2 = cir.sub %a, %b sat : !s32i
+ %3 = cir.sub %a, %b : !cir.float
```
}];
+}
+
+//===----------------------------------------------------------------------===//
+// MulOp
+//===----------------------------------------------------------------------===//
+def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
+ let summary = "Integer or floating-point multiplication";
+ let description = [{
+ The `cir.mul` operation performs multiplication on integer or floating-point
+ operands. Both operands and the result must have the same type.
+
+ For integer types, the optional `nsw` (no signed wrap) and `nuw` (no
+ unsigned wrap) unit attributes indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively.
+
+ Example:
+
+ ```mlir
+ %0 = cir.mul %a, %b : !s32i
+ %1 = cir.mul %a, %b nsw : !s32i
+ %2 = cir.mul %a, %b nuw : !u32i
+ %3 = cir.mul %a, %b : !cir.float
+ ```
+ }];
+
let arguments = (ins
- CIR_BinOpKind:$kind,
- CIR_AnyType:$lhs, CIR_AnyType:$rhs,
- UnitAttr:$no_unsigned_wrap,
- UnitAttr:$no_signed_wrap,
- UnitAttr:$saturated
+ CIR_AnyArithType:$lhs, CIR_AnyArithType:$rhs,
+ UnitProp:$no_signed_wrap,
+ UnitProp:$no_unsigned_wrap
);
- // TODO: get more accurate than CIR_AnyType
- let results = (outs CIR_AnyType:$result);
-
let assemblyFormat = [{
- `(` $kind `,` $lhs `,` $rhs `)`
(`nsw` $no_signed_wrap^)?
(`nuw` $no_unsigned_wrap^)?
- (`sat` $saturated^)?
- `:` type($lhs) attr-dict
+ $lhs `,` $rhs `:` type($lhs) attr-dict
}];
let hasVerifier = 1;
+}
- let extraLLVMLoweringPatternDecl = [{
- mlir::LLVM::IntegerOverflowFlags getIntOverflowFlag(cir::BinOp op) const;
+//===----------------------------------------------------------------------===//
+// DivOp
+//===----------------------------------------------------------------------===//
+
+def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyArithType> {
+ let summary = "Integer or floating-point division";
+ let description = [{
+ The `cir.div` operation performs division on integer or floating-point
+ operands. Both operands and the result must have the same type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.div %a, %b : !s32i
+ %1 = cir.div %a, %b : !u32i
+ %2 = cir.div %a, %b : !cir.float
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// RemOp
+//===----------------------------------------------------------------------===//
+
+def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyArithType> {
+ let summary = "Integer or floating-point remainder";
+ let description = [{
+ The `cir.rem` operation computes the remainder of division on integer or
+ floating-point operands. Both operands and the result must have the same
+ type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.rem %a, %b : !s32i
+ %1 = cir.rem %a, %b : !u32i
+ %2 = cir.rem %a, %b : !cir.float
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// AndOp
+//===----------------------------------------------------------------------===//
+
+// FIXME: Commutative, Idempotent traits
+def CIR_AndOp : CIR_BinaryOp<"and", CIR_AnyBitwiseType> {
+ let summary = "Bitwise AND";
+ let description = [{
+ The `cir.and` operation performs a bitwise AND on integer operands.
+ Both operands and the result must have the same integer type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.and %a, %b : !s32i
+ %1 = cir.and %a, %b : !cir.bool
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// OrOp
+//===----------------------------------------------------------------------===//
+
+// FIXME: Commutative, Idempotent traits
+def CIR_OrOp : CIR_BinaryOp<"or", CIR_AnyBitwiseType> {
+ let summary = "Bitwise OR";
+ let description = [{
+ The `cir.or` operation performs a bitwise OR on integer operands.
+ Both operands and the result must have the same integer type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.or %a, %b : !s32i
+ %1 = cir.or %a, %b : !cir.bool
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// XorOp
+//===----------------------------------------------------------------------===//
+
+def CIR_XorOp : CIR_BinaryOp<"xor", CIR_AnyBitwiseType> {
+ let summary = "Bitwise XOR";
+ let description = [{
+ The `cir.xor` operation performs a bitwise XOR on integer operands.
+ Both operands and the result must have the same integer type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.xor %a, %b : !s32i
+ %1 = cir.xor %a, %b : !cir.bool
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// MaxOp
+//===----------------------------------------------------------------------===//
+
+def CIR_MaxOp : CIR_BinaryOp<"max", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer maximum";
+ let description = [{
+ The `cir.max` operation computes the maximum of two integer operands.
+ Both operands and the result must have the same integer type.
+
+ Example:
+
+ ```mlir
+ %0 = cir.max %a, %b : !s32i
+ %1 = cir.max %a, %b : !u32i
+ ```
}];
}
@@ -2206,7 +2391,7 @@ def CIR_ShiftOp : CIR_Op<"shift", [Pure]> {
integer type, or all integer type. If they are vectors, each vector element of
the shift target is shifted by the corresponding shift amount in
the shift amount vector.
-
+
```mlir
%res = cir.shift(left, %lhs : !u64i, %amount : !s32i) -> !u64i
%new_vec = cir.shift(left, %lhs : !cir.vector<2 x !s32i>, %rhs :
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 1a5bae13c96df..f48b13ff9718b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -167,6 +167,11 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType],
let cppFunctionName = "isAnyIntegerOrFloatingPointType";
}
+def CIR_AnyIntOrBoolType
+ : AnyTypeOf<[CIR_AnyIntType, CIR_AnyBoolType], "integer or boolean type"> {
+ let cppFunctionName = "isIntOrBoolType";
+}
+
def CIR_AnyIntOrBoolOrFloatType
: AnyTypeOf<[CIR_AnyBoolType, CIR_AnyFloatType, CIR_AnyIntType],
"integer, boolean or floating point type"> {
@@ -331,6 +336,19 @@ def CIR_AnyFloatOrVecOfFloatType
let cppFunctionName = "isFPOrVectorOfFPType";
}
+// Types valid for arithmetic ops (add/sub/mul/div/rem):
+// scalar or vector of integer, boolean, or floating-point.
+def CIR_AnyArithType
+ : AnyTypeOf<[CIR_AnyIntType, CIR_AnyBoolType, CIR_AnyFloatType,
+ CIR_VectorOfIntType, CIR_VectorOfFloatType],
+ "integer, boolean, floating-point, or vector of integer/float">;
+
+// Types valid for bitwise ops (and/or/xor):
+// integer, boolean, or vector of integer (no floating-point).
+def CIR_AnyBitwiseType
+ : AnyTypeOf<[CIR_AnyIntType, CIR_AnyBoolType, CIR_VectorOfIntType],
+ "integer, boolean, or vector of integer">;
+
//===----------------------------------------------------------------------===//
// Data member type predicates
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index c73eadaff6f3e..c715e2e03a7b9 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -163,6 +163,32 @@ let cppNamespace = "::cir" in {
}];
}
+ def CIR_BinaryOpInterface : OpInterface<"BinaryOpInterface"> {
+ let description = [{
+ Common interface for CIR binary arithmetic and logic operations.
+ Provides uniform access to the left-hand side operand, right-hand side
+ operand, and result of any binary operation in the CIR dialect.
+ }];
+
+ let methods = [
+ InterfaceMethod<"Return the left-hand side operand.",
+ "mlir::Value", "getLhs", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return $_op.getLhs();
+ }]>,
+ InterfaceMethod<"Return the right-hand side operand.",
+ "mlir::Value", "getRhs", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return $_op.getRhs();
+ }]>,
+ InterfaceMethod<"Return the result value.",
+ "mlir::Value", "getResult", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return $_op.getResult();
+ }]>,
+ ];
+ }
+
} // namespace cir
#endif // CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index cd13c9578adf7..cbb6a78d5212b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -449,7 +449,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
assert(!cir::MissingFeatures::fpConstraints());
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::BinOp::create(*this, loc...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/184227
More information about the cfe-commits
mailing list