[CIR] Separate floating-point bin ops from integer bin ops#201462
Conversation
This change creates new FP-specific binary operations and updates the existing binary operations that previously accepted any arithmetic type to only allow integer and vector-of-integer types. This change is being done to prepare for extended floating-point handling such as strict FP semantics and fast-math handling. It also simplifies the handling of integer overflow flags. Assisted-by: Cursor / claude-opus-4.8
|
@llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesThis change creates new FP-specific binary operations and updates the existing binary operations that previously accepted any arithmetic type to only allow integer and vector-of-integer types. This change is being done to prepare for extended floating-point handling such as strict FP semantics and fast-math handling. It also simplifies the handling of integer overflow flags. Assisted-by: Cursor / claude-opus-4.8 Patch is 143.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201462.diff 27 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index a29fb45e95032..a841190c53c0d 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -702,6 +702,41 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::RemOp::create(*this, loc, lhs, rhs);
}
+ mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FAddOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FSubOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FMulOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FDivOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FRemOp::create(*this, loc, lhs, rhs);
+ }
+
mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
return cir::XorOp::create(*this, loc, lhs, rhs);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c4d08d5337031..975be5aac87a7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2430,18 +2430,20 @@ class CIR_BinaryOpWithOverflowFlags<string mnemonic, Type type,
// AddOp
//===----------------------------------------------------------------------===//
-def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
- let summary = "Integer or floating-point addition";
+def CIR_AddOp
+ : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer addition";
let description = [{
- The `cir.add` operation performs addition on integer or floating-point
- operands. Both operands and the result must have the same type.
+ The `cir.add` operation performs addition on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point addition is performed by `cir.fadd`.
+
+ 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.
- 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:
```
@@ -2449,7 +2451,7 @@ def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
%1 = cir.add nsw %a, %b : !s32i
%2 = cir.add nuw %a, %b : !u32i
%3 = cir.add sat %a, %b : !s32i
- %4 = cir.add %a, %b : !cir.float
+ %4 = cir.add %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2458,25 +2460,27 @@ def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
// SubOp
//===----------------------------------------------------------------------===//
-def CIR_SubOp : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyArithType> {
- let summary = "Integer or floating-point subtraction";
+def CIR_SubOp
+ : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.sub` operation performs subtraction on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point subtraction is performed by `cir.fsub`.
+
+ 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.
- 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:
```
%0 = cir.sub %a, %b : !s32i
%1 = cir.sub nsw %a, %b : !s32i
%2 = cir.sub sat %a, %b : !s32i
- %3 = cir.sub %a, %b : !cir.float
+ %3 = cir.sub %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2485,15 +2489,16 @@ def CIR_SubOp : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyArithType> {
// MulOp
//===----------------------------------------------------------------------===//
-def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
- let summary = "Integer or floating-point multiplication";
+def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.mul` operation performs multiplication on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point multiplication is performed by `cir.fmul`.
- 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 `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:
@@ -2501,12 +2506,12 @@ def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
%0 = cir.mul %a, %b : !s32i
%1 = cir.mul nsw %a, %b : !s32i
%2 = cir.mul nuw %a, %b : !u32i
- %3 = cir.mul %a, %b : !cir.float
+ %3 = cir.mul %va, %vb : !cir.vector<4 x !s32i>
```
}];
-
+
let arguments = (ins
- CIR_AnyArithType:$lhs, CIR_AnyArithType:$rhs,
+ CIR_AnyIntOrVecOfIntType:$lhs, CIR_AnyIntOrVecOfIntType:$rhs,
UnitProp:$no_signed_wrap,
UnitProp:$no_unsigned_wrap
);
@@ -2516,26 +2521,25 @@ def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
(`nuw` $no_unsigned_wrap^)?
$lhs `,` $rhs `:` type($lhs) attr-dict
}];
-
- let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// DivOp
//===----------------------------------------------------------------------===//
-def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyArithType> {
- let summary = "Integer or floating-point division";
+def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.div` operation performs division on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type.
Example:
```
%0 = cir.div %a, %b : !s32i
%1 = cir.div %a, %b : !u32i
- %2 = cir.div %a, %b : !cir.float
+ %2 = cir.div %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2544,21 +2548,146 @@ def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyArithType> {
// RemOp
//===----------------------------------------------------------------------===//
-def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyArithType> {
- let summary = "Integer or floating-point remainder";
+def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
-
+ The `cir.rem` operation computes the remainder of division on integer
+ operands. Both operands and the result must have the same integer or
+ vector-of-integer type.
+
Example:
```
%0 = cir.rem %a, %b : !s32i
%1 = cir.rem %a, %b : !u32i
- %2 = cir.rem %a, %b : !cir.float
+ %2 = cir.rem %va, %vb : !cir.vector<4 x !s32i>
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Floating-Point Binary Arithmetic Operations
+//===----------------------------------------------------------------------===//
+
+// Base class for floating-point binary arithmetic operations. The lhs, rhs,
+// and result must all be the same floating-point scalar or vector type.
+class CIR_FPBinaryOp<string mnemonic, list<Trait> traits = []>
+ : CIR_BinaryOp<mnemonic, CIR_AnyFloatOrVecOfFloatType,
+ !listconcat([Pure], traits)>;
+
+//===----------------------------------------------------------------------===//
+// FAddOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FAddOp : CIR_FPBinaryOp<"fadd"> {
+ let summary = "Floating-point addition";
+ let description = [{
+ The `cir.fadd` operation performs floating-point addition on its operands.
+ Both operands and the result must have the same floating-point scalar or
+ vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fadd %a, %b : !cir.float
+ %1 = cir.fadd %a, %b : !cir.double
+ %2 = cir.fadd %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FAddOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FSubOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FSubOp : CIR_FPBinaryOp<"fsub"> {
+ let summary = "Floating-point subtraction";
+ let description = [{
+ The `cir.fsub` operation performs floating-point subtraction on its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fsub %a, %b : !cir.float
+ %1 = cir.fsub %a, %b : !cir.double
+ %2 = cir.fsub %va, %vb : !cir.vector<4 x !cir.float>
```
}];
+
+ let llvmOp = "FSubOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FMulOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FMulOp : CIR_FPBinaryOp<"fmul"> {
+ let summary = "Floating-point multiplication";
+ let description = [{
+ The `cir.fmul` operation performs floating-point multiplication on its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fmul %a, %b : !cir.float
+ %1 = cir.fmul %a, %b : !cir.double
+ %2 = cir.fmul %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FMulOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FDivOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FDivOp : CIR_FPBinaryOp<"fdiv"> {
+ let summary = "Floating-point division";
+ let description = [{
+ The `cir.fdiv` operation performs floating-point division on its operands.
+ Both operands and the result must have the same floating-point scalar or
+ vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fdiv %a, %b : !cir.float
+ %1 = cir.fdiv %a, %b : !cir.double
+ %2 = cir.fdiv %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FDivOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FRemOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FRemOp : CIR_FPBinaryOp<"frem"> {
+ let summary = "Floating-point remainder";
+ let description = [{
+ The `cir.frem` operation computes the floating-point remainder of its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.frem %a, %b : !cir.float
+ %1 = cir.frem %a, %b : !cir.double
+ %2 = cir.frem %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FRemOp";
}
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 3cc79b9796e06..322eec853d821 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -342,13 +342,6 @@ def CIR_AnyFloatOrVecOfFloatType
let cppFunctionName = "isFPOrVectorOfFPType";
}
-// Types valid for arithmetic ops (add/sub/mul/div/rem):
-// scalar or vector of integer or floating-point.
-def CIR_AnyArithType
- : AnyTypeOf<[CIR_AnyIntType, CIR_AnyFloatType,
- CIR_VectorOfIntType, CIR_VectorOfFloatType],
- "integer, 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
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 6e0f4ce00d4f1..9e88e3588d84a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -490,40 +490,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return createMinus(value.getLoc(), value);
}
- //===--------------------------------------------------------------------===//
- // BinaryOp creation helpers
- //===--------------------------------------------------------------------===//
- mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::SubOp::create(*this, loc, lhs, rhs);
- }
-
- mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::AddOp::create(*this, loc, lhs, rhs);
- }
-
- mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::MulOp::create(*this, loc, lhs, rhs);
- }
- mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::DivOp::create(*this, loc, lhs, rhs);
- }
-
//===--------------------------------------------------------------------===//
// CastOp creation helpers
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index c576cb9159f36..5f35b32336e33 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -606,17 +606,23 @@ mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
mlir::isa<cir::ComplexType>(op.rhs.getType()))
return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs);
+ auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFAdd(loc, a, b)
+ : builder.createAdd(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs);
+ mlir::Value newReal = createAdd(op.loc, real, op.rhs);
return builder.createComplexCreate(op.loc, newReal, imag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
- mlir::Value newReal = builder.createAdd(op.loc, op.lhs, real);
+ mlir::Value newReal = createAdd(op.loc, op.lhs, real);
return builder.createComplexCreate(op.loc, newReal, imag);
}
@@ -628,17 +634,23 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
mlir::isa<cir::ComplexType>(op.rhs.getType()))
return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs);
+ auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFSub(loc, a, b)
+ : builder.createSub(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createSub(op.loc, real, op.rhs);
+ mlir::Value newReal = createSub(op.loc, real, op.rhs);
return builder.createComplexCreate(op.loc, newReal, imag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
- mlir::Value newReal = builder.createSub(op.loc, op.lhs, real);
+ mlir::Value newReal = createSub(op.loc, op.lhs, real);
return builder.createComplexCreate(op.loc, newReal, imag);
}
@@ -671,19 +683,25 @@ mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
rangeKind);
}
+ auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFMul(loc, a, b)
+ : builder.createMul(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createMul(op.loc, real, op.rhs);
- mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs);
+ mlir::Value newReal = createMul(op.loc, real, op.rhs);
+ mlir::Value newImag = createMul(op.loc, imag, op.rhs);
return builder.createComplexCreate(op.loc, newReal, newImag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.c...
[truncated]
|
|
@llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesThis change creates new FP-specific binary operations and updates the existing binary operations that previously accepted any arithmetic type to only allow integer and vector-of-integer types. This change is being done to prepare for extended floating-point handling such as strict FP semantics and fast-math handling. It also simplifies the handling of integer overflow flags. Assisted-by: Cursor / claude-opus-4.8 Patch is 143.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201462.diff 27 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index a29fb45e95032..a841190c53c0d 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -702,6 +702,41 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::RemOp::create(*this, loc, lhs, rhs);
}
+ mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FAddOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FSubOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FMulOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FDivOp::create(*this, loc, lhs, rhs);
+ }
+
+ mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+ assert(!cir::MissingFeatures::metaDataNode());
+ assert(!cir::MissingFeatures::fpConstraints());
+ assert(!cir::MissingFeatures::fastMathFlags());
+ return cir::FRemOp::create(*this, loc, lhs, rhs);
+ }
+
mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
return cir::XorOp::create(*this, loc, lhs, rhs);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c4d08d5337031..975be5aac87a7 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2430,18 +2430,20 @@ class CIR_BinaryOpWithOverflowFlags<string mnemonic, Type type,
// AddOp
//===----------------------------------------------------------------------===//
-def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
- let summary = "Integer or floating-point addition";
+def CIR_AddOp
+ : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer addition";
let description = [{
- The `cir.add` operation performs addition on integer or floating-point
- operands. Both operands and the result must have the same type.
+ The `cir.add` operation performs addition on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point addition is performed by `cir.fadd`.
+
+ 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.
- 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:
```
@@ -2449,7 +2451,7 @@ def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
%1 = cir.add nsw %a, %b : !s32i
%2 = cir.add nuw %a, %b : !u32i
%3 = cir.add sat %a, %b : !s32i
- %4 = cir.add %a, %b : !cir.float
+ %4 = cir.add %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2458,25 +2460,27 @@ def CIR_AddOp : CIR_BinaryOpWithOverflowFlags<"add", CIR_AnyArithType> {
// SubOp
//===----------------------------------------------------------------------===//
-def CIR_SubOp : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyArithType> {
- let summary = "Integer or floating-point subtraction";
+def CIR_SubOp
+ : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.sub` operation performs subtraction on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point subtraction is performed by `cir.fsub`.
+
+ 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.
- 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:
```
%0 = cir.sub %a, %b : !s32i
%1 = cir.sub nsw %a, %b : !s32i
%2 = cir.sub sat %a, %b : !s32i
- %3 = cir.sub %a, %b : !cir.float
+ %3 = cir.sub %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2485,15 +2489,16 @@ def CIR_SubOp : CIR_BinaryOpWithOverflowFlags<"sub", CIR_AnyArithType> {
// MulOp
//===----------------------------------------------------------------------===//
-def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
- let summary = "Integer or floating-point multiplication";
+def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.mul` operation performs multiplication on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type. Floating-point multiplication is performed by `cir.fmul`.
- 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 `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:
@@ -2501,12 +2506,12 @@ def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
%0 = cir.mul %a, %b : !s32i
%1 = cir.mul nsw %a, %b : !s32i
%2 = cir.mul nuw %a, %b : !u32i
- %3 = cir.mul %a, %b : !cir.float
+ %3 = cir.mul %va, %vb : !cir.vector<4 x !s32i>
```
}];
-
+
let arguments = (ins
- CIR_AnyArithType:$lhs, CIR_AnyArithType:$rhs,
+ CIR_AnyIntOrVecOfIntType:$lhs, CIR_AnyIntOrVecOfIntType:$rhs,
UnitProp:$no_signed_wrap,
UnitProp:$no_unsigned_wrap
);
@@ -2516,26 +2521,25 @@ def CIR_MulOp : CIR_BinaryOp<"mul", CIR_AnyArithType> {
(`nuw` $no_unsigned_wrap^)?
$lhs `,` $rhs `:` type($lhs) attr-dict
}];
-
- let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
// DivOp
//===----------------------------------------------------------------------===//
-def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyArithType> {
- let summary = "Integer or floating-point division";
+def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
+ The `cir.div` operation performs division on integer operands. Both
+ operands and the result must have the same integer or vector-of-integer
+ type.
Example:
```
%0 = cir.div %a, %b : !s32i
%1 = cir.div %a, %b : !u32i
- %2 = cir.div %a, %b : !cir.float
+ %2 = cir.div %va, %vb : !cir.vector<4 x !s32i>
```
}];
}
@@ -2544,21 +2548,146 @@ def CIR_DivOp : CIR_BinaryOp<"div", CIR_AnyArithType> {
// RemOp
//===----------------------------------------------------------------------===//
-def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyArithType> {
- let summary = "Integer or floating-point remainder";
+def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyIntOrVecOfIntType> {
+ let summary = "Integer 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.
-
+ The `cir.rem` operation computes the remainder of division on integer
+ operands. Both operands and the result must have the same integer or
+ vector-of-integer type.
+
Example:
```
%0 = cir.rem %a, %b : !s32i
%1 = cir.rem %a, %b : !u32i
- %2 = cir.rem %a, %b : !cir.float
+ %2 = cir.rem %va, %vb : !cir.vector<4 x !s32i>
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Floating-Point Binary Arithmetic Operations
+//===----------------------------------------------------------------------===//
+
+// Base class for floating-point binary arithmetic operations. The lhs, rhs,
+// and result must all be the same floating-point scalar or vector type.
+class CIR_FPBinaryOp<string mnemonic, list<Trait> traits = []>
+ : CIR_BinaryOp<mnemonic, CIR_AnyFloatOrVecOfFloatType,
+ !listconcat([Pure], traits)>;
+
+//===----------------------------------------------------------------------===//
+// FAddOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FAddOp : CIR_FPBinaryOp<"fadd"> {
+ let summary = "Floating-point addition";
+ let description = [{
+ The `cir.fadd` operation performs floating-point addition on its operands.
+ Both operands and the result must have the same floating-point scalar or
+ vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fadd %a, %b : !cir.float
+ %1 = cir.fadd %a, %b : !cir.double
+ %2 = cir.fadd %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FAddOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FSubOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FSubOp : CIR_FPBinaryOp<"fsub"> {
+ let summary = "Floating-point subtraction";
+ let description = [{
+ The `cir.fsub` operation performs floating-point subtraction on its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fsub %a, %b : !cir.float
+ %1 = cir.fsub %a, %b : !cir.double
+ %2 = cir.fsub %va, %vb : !cir.vector<4 x !cir.float>
```
}];
+
+ let llvmOp = "FSubOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FMulOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FMulOp : CIR_FPBinaryOp<"fmul"> {
+ let summary = "Floating-point multiplication";
+ let description = [{
+ The `cir.fmul` operation performs floating-point multiplication on its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fmul %a, %b : !cir.float
+ %1 = cir.fmul %a, %b : !cir.double
+ %2 = cir.fmul %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FMulOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FDivOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FDivOp : CIR_FPBinaryOp<"fdiv"> {
+ let summary = "Floating-point division";
+ let description = [{
+ The `cir.fdiv` operation performs floating-point division on its operands.
+ Both operands and the result must have the same floating-point scalar or
+ vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.fdiv %a, %b : !cir.float
+ %1 = cir.fdiv %a, %b : !cir.double
+ %2 = cir.fdiv %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FDivOp";
+}
+
+//===----------------------------------------------------------------------===//
+// FRemOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FRemOp : CIR_FPBinaryOp<"frem"> {
+ let summary = "Floating-point remainder";
+ let description = [{
+ The `cir.frem` operation computes the floating-point remainder of its
+ operands. Both operands and the result must have the same floating-point
+ scalar or vector-of-float type.
+
+ Example:
+
+ ```
+ %0 = cir.frem %a, %b : !cir.float
+ %1 = cir.frem %a, %b : !cir.double
+ %2 = cir.frem %va, %vb : !cir.vector<4 x !cir.float>
+ ```
+ }];
+
+ let llvmOp = "FRemOp";
}
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 3cc79b9796e06..322eec853d821 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -342,13 +342,6 @@ def CIR_AnyFloatOrVecOfFloatType
let cppFunctionName = "isFPOrVectorOfFPType";
}
-// Types valid for arithmetic ops (add/sub/mul/div/rem):
-// scalar or vector of integer or floating-point.
-def CIR_AnyArithType
- : AnyTypeOf<[CIR_AnyIntType, CIR_AnyFloatType,
- CIR_VectorOfIntType, CIR_VectorOfFloatType],
- "integer, 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
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 6e0f4ce00d4f1..9e88e3588d84a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -490,40 +490,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return createMinus(value.getLoc(), value);
}
- //===--------------------------------------------------------------------===//
- // BinaryOp creation helpers
- //===--------------------------------------------------------------------===//
- mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::SubOp::create(*this, loc, lhs, rhs);
- }
-
- mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::AddOp::create(*this, loc, lhs, rhs);
- }
-
- mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::MulOp::create(*this, loc, lhs, rhs);
- }
- mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
- assert(!cir::MissingFeatures::metaDataNode());
- assert(!cir::MissingFeatures::fpConstraints());
- assert(!cir::MissingFeatures::fastMathFlags());
-
- return cir::DivOp::create(*this, loc, lhs, rhs);
- }
-
//===--------------------------------------------------------------------===//
// CastOp creation helpers
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index c576cb9159f36..5f35b32336e33 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -606,17 +606,23 @@ mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {
mlir::isa<cir::ComplexType>(op.rhs.getType()))
return cir::ComplexAddOp::create(builder, op.loc, op.lhs, op.rhs);
+ auto createAdd = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFAdd(loc, a, b)
+ : builder.createAdd(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs);
+ mlir::Value newReal = createAdd(op.loc, real, op.rhs);
return builder.createComplexCreate(op.loc, newReal, imag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
- mlir::Value newReal = builder.createAdd(op.loc, op.lhs, real);
+ mlir::Value newReal = createAdd(op.loc, op.lhs, real);
return builder.createComplexCreate(op.loc, newReal, imag);
}
@@ -628,17 +634,23 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {
mlir::isa<cir::ComplexType>(op.rhs.getType()))
return cir::ComplexSubOp::create(builder, op.loc, op.lhs, op.rhs);
+ auto createSub = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFSub(loc, a, b)
+ : builder.createSub(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createSub(op.loc, real, op.rhs);
+ mlir::Value newReal = createSub(op.loc, real, op.rhs);
return builder.createComplexCreate(op.loc, newReal, imag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.rhs);
- mlir::Value newReal = builder.createSub(op.loc, op.lhs, real);
+ mlir::Value newReal = createSub(op.loc, op.lhs, real);
return builder.createComplexCreate(op.loc, newReal, imag);
}
@@ -671,19 +683,25 @@ mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) {
rangeKind);
}
+ auto createMul = [&](mlir::Location loc, mlir::Value a, mlir::Value b) {
+ return cir::isFPOrVectorOfFPType(a.getType())
+ ? builder.createFMul(loc, a, b)
+ : builder.createMul(loc, a, b);
+ };
+
if (mlir::isa<cir::ComplexType>(op.lhs.getType())) {
mlir::Value real = builder.createComplexReal(op.loc, op.lhs);
mlir::Value imag = builder.createComplexImag(op.loc, op.lhs);
- mlir::Value newReal = builder.createMul(op.loc, real, op.rhs);
- mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs);
+ mlir::Value newReal = createMul(op.loc, real, op.rhs);
+ mlir::Value newImag = createMul(op.loc, imag, op.rhs);
return builder.createComplexCreate(op.loc, newReal, newImag);
}
assert(mlir::isa<cir::ComplexType>(op.rhs.getType()));
mlir::Value real = builder.createComplexReal(op.loc, op.rhs);
mlir::Value imag = builder.c...
[truncated]
|
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
This change creates new FP-specific binary operations and updates the existing binary operations that previously accepted any arithmetic type to only allow integer and vector-of-integer types.
This change is being done to prepare for extended floating-point handling such as strict FP semantics and fast-math handling. It also simplifies the handling of integer overflow flags.
Assisted-by: Cursor / claude-opus-4.8