[llvm-branch-commits] [clang] [CIR] Replace nsw/nuw unit attrs with OverflowFlags BitEnum (PR #195618)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon May 4 02:25:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Henrich Lauko (xlauko)
<details>
<summary>Changes</summary>
Combine the separate `no_signed_wrap` and `no_unsigned_wrap` unit
properties on arithmetic ops into a single `OverflowFlags` BitEnum
(`nsw`, `nuw`). This allows combined flags to be written as
`nsw|nuw` in assembly, replaces the per-flag verification traits
with a single `OverflowFlagsRequireIntType` predicate, and folds
the two `HasAtMostOneOfAttrs` checks into one
`SatExclusiveWithOverflowFlags` predicate.
The bit layout matches `mlir::LLVM::IntegerOverflowFlags`, so
lowering casts the value directly and asserts the layout via
static_assert.
---
Patch is 20.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195618.diff
9 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+18-12)
- (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+14)
- (modified) clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td (+15)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+41-32)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+5-3)
- (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp (+4-4)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+15-7)
- (added) clang/test/CIR/IR/invalid-overflow.cir (+39)
- (added) clang/test/CIR/IR/overflow-flags.cir (+66)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 646fc7eb3c226..d3cc5a551fd27 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -61,6 +61,15 @@ constexpr bool testFlag(OverflowBehavior ob, OverflowBehavior flag) {
return (ob & flag) != OverflowBehavior::None;
}
+inline OverflowFlags toOverflowFlags(OverflowBehavior ob) {
+ auto flags = OverflowFlags::none;
+ if (testFlag(ob, OverflowBehavior::NoSignedWrap))
+ flags = flags | OverflowFlags::nsw;
+ if (testFlag(ob, OverflowBehavior::NoUnsignedWrap))
+ flags = flags | OverflowFlags::nuw;
+ return flags;
+}
+
class CIRBaseBuilderTy : public mlir::OpBuilder {
public:
@@ -279,18 +288,18 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
}
mlir::Value createInc(mlir::Location loc, mlir::Value input,
- bool nsw = false) {
- return cir::IncOp::create(*this, loc, input, nsw);
+ cir::OverflowFlags flags = cir::OverflowFlags::none) {
+ return cir::IncOp::create(*this, loc, input, flags);
}
mlir::Value createDec(mlir::Location loc, mlir::Value input,
- bool nsw = false) {
- return cir::DecOp::create(*this, loc, input, nsw);
+ cir::OverflowFlags flags = cir::OverflowFlags::none) {
+ return cir::DecOp::create(*this, loc, input, flags);
}
mlir::Value createMinus(mlir::Location loc, mlir::Value input,
- bool nsw = false) {
- return cir::MinusOp::create(*this, loc, input, nsw);
+ cir::OverflowFlags flags = cir::OverflowFlags::none) {
+ return cir::MinusOp::create(*this, loc, input, flags);
}
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value) {
@@ -629,8 +638,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::MulOp::create(*this, loc, lhs, rhs);
- op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
+ op.setFlags(toOverflowFlags(ob));
return op;
}
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs,
@@ -645,8 +653,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::SubOp::create(*this, loc, lhs, rhs);
- op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
+ op.setFlags(toOverflowFlags(ob));
op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
return op;
}
@@ -664,8 +671,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::AddOp::create(*this, loc, lhs, rhs);
- op.setNoUnsignedWrap(testFlag(ob, OverflowBehavior::NoUnsignedWrap));
- op.setNoSignedWrap(testFlag(ob, OverflowBehavior::NoSignedWrap));
+ op.setFlags(toOverflowFlags(ob));
op.setSaturated(testFlag(ob, OverflowBehavior::Saturated));
return op;
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 1520999e3f85f..703d75bb2c14c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -110,6 +110,20 @@ def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> {
}];
}
+//===----------------------------------------------------------------------===//
+// OverflowFlagsAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_OFnone : I32BitEnumCaseNone<"none">;
+def CIR_OFnsw : I32BitEnumCaseBit<"nsw", 0>;
+def CIR_OFnuw : I32BitEnumCaseBit<"nuw", 1>;
+
+def CIR_OverflowFlags : CIR_I32BitEnum<
+ "OverflowFlags", "integer arithmetic overflow flags",
+ [CIR_OFnone, CIR_OFnsw, CIR_OFnuw]>;
+
+def CIR_OverflowFlagsProp : CIR_BitEnumProp<CIR_OverflowFlags>;
+
//===----------------------------------------------------------------------===//
// ArgPassingKind + RecordLayoutAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 1de6ffdc08d72..78f74ec8393ae 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -31,6 +31,21 @@ class CIR_EnumAttr<EnumAttrInfo info, string name = "", list<Trait> traits = []>
let assemblyFormat = "`<` $value `>`";
}
+class CIR_I32BitEnum<string name, string summary,
+ list<BitEnumCaseBase> cases>
+ : I32BitEnum<name, summary, cases> {
+ let cppNamespace = "::cir";
+ let separator = "|";
+ let printBitEnumPrimaryGroups = 1;
+}
+
+// CIR property wrapping a BitEnum. Storage is inline (Property, not Attribute);
+// the auto-generated FieldParser parses bare `flag1|flag2` syntax.
+class CIR_BitEnumProp<BitEnum info, string defaultVal = info.cppType # "::none">
+ : EnumProp<info> {
+ let defaultValue = defaultVal;
+}
+
class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
: EnumParameter<info> {
let defaultValue = value;
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 46b23c32b1a98..4ad247a8dba68 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -130,10 +130,22 @@ class FlagRequiresIntType<string flag> : PredOpTrait<
CPred<"::mlir::isa<::cir::IntType>(this->getResult().getType())">]>
>;
-def NSWFlagIntOnly : FlagRequiresIntType<"no_signed_wrap">;
-def NUWFlagIntOnly : FlagRequiresIntType<"no_unsigned_wrap">;
def SatFlagIntOnly : FlagRequiresIntType<"saturated">;
+// Requires that overflow flags imply an integer result type.
+def OverflowFlagsRequireIntType : PredOpTrait<
+ "overflow flags require an integer result type",
+ Or<[CPred<"this->getFlags() == ::cir::OverflowFlags::none">,
+ CPred<"::mlir::isa<::cir::IntType>(this->getResult().getType())">]>
+>;
+
+// Requires that the saturated flag is mutually exclusive with overflow flags.
+def SatExclusiveWithOverflowFlags : PredOpTrait<
+ "sat is mutually exclusive with nsw/nuw overflow flags",
+ CPred<"!this->getSaturated() || "
+ "this->getFlags() == ::cir::OverflowFlags::none">
+>;
+
//===----------------------------------------------------------------------===//
// CastOp
//===----------------------------------------------------------------------===//
@@ -1831,12 +1843,12 @@ class CIR_UnaryOpWithOverflowFlag<string mnemonic, Type type,
list<Trait> traits = []>
: CIR_UnaryOp<mnemonic, type, traits>
{
- let append traits = [NSWFlagIntOnly];
+ let append traits = [OverflowFlagsRequireIntType];
- let append arguments = (ins UnitProp:$no_signed_wrap);
+ let append arguments = (ins CIR_OverflowFlagsProp:$flags);
let prepend assemblyFormat = [{
- (`nsw` $no_signed_wrap^)?
+ ($flags^)?
}];
}
@@ -2383,16 +2395,12 @@ class CIR_BinaryOp<string mnemonic, Type type, list<Trait> traits = []>
class CIR_BinaryOpWithOverflowFlags<string mnemonic, Type type>
: CIR_BinaryOp<mnemonic, type>
{
- let append traits = [Pure, NSWFlagIntOnly, NUWFlagIntOnly];
+ let append traits = [Pure, OverflowFlagsRequireIntType];
- let append arguments = (ins
- UnitProp:$no_signed_wrap,
- UnitProp:$no_unsigned_wrap
- );
+ let append arguments = (ins CIR_OverflowFlagsProp:$flags);
let prepend assemblyFormat = [{
- (`nsw` $no_signed_wrap^)?
- (`nuw` $no_unsigned_wrap^)?
+ ($flags^)?
}];
}
@@ -2400,11 +2408,7 @@ class CIR_BinaryOpWithOverflowFlags<string mnemonic, Type type>
class CIR_SaturatableBinaryOp<string mnemonic, Type type>
: CIR_BinaryOpWithOverflowFlags<mnemonic, type>
{
- let append traits = [
- SatFlagIntOnly,
- HasAtMostOneOfAttrs<["saturated", "no_signed_wrap"]>,
- HasAtMostOneOfAttrs<["saturated", "no_unsigned_wrap"]>
- ];
+ let append traits = [SatFlagIntOnly, SatExclusiveWithOverflowFlags];
let append arguments = (ins UnitProp:$saturated);
@@ -2426,19 +2430,21 @@ def CIR_AddOp : CIR_SaturatableBinaryOp<"add", CIR_AnyArithType> {
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 instead of
- wrapping. The `nsw`/`nuw` flags and `sat` are mutually exclusive.
-
+ unsigned wrap) overflow flags indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively. Combined flags are written as
+ `nsw|nuw`. 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:
```
%0 = cir.add %a, %b : !s32i
%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
+ %3 = cir.add nsw|nuw %a, %b : !s32i
+ %4 = cir.add sat %a, %b : !s32i
+ %5 = cir.add %a, %b : !cir.float
```
}];
}
@@ -2454,11 +2460,12 @@ def CIR_SubOp : CIR_SaturatableBinaryOp<"sub", CIR_AnyArithType> {
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.
-
+ unsigned wrap) overflow flags indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively. Combined flags are written as
+ `nsw|nuw`. The optional `sat` (saturated) attribute clamps the result to
+ the type's representable range. The `nsw`/`nuw` flags and `sat` are
+ mutually exclusive.
+
Example:
```
@@ -2483,8 +2490,9 @@ def CIR_MulOp : CIR_BinaryOpWithOverflowFlags<"mul", CIR_AnyArithType> {
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.
+ unsigned wrap) overflow flags indicate that the result is poison if signed
+ or unsigned overflow occurs, respectively. Combined flags are written as
+ `nsw|nuw`.
Example:
@@ -2492,7 +2500,8 @@ def CIR_MulOp : CIR_BinaryOpWithOverflowFlags<"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 nsw|nuw %a, %b : !s32i
+ %4 = cir.mul %a, %b : !cir.float
```
}];
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 92b7156f3a3a8..07a160b4aa3e0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -796,16 +796,18 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
// NOTE: LLVM codegen will lower this directly to either a FNeg
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
+ auto flags = nsw ? cir::OverflowFlags::nsw : cir::OverflowFlags::none;
return builder.createOrFold<cir::MinusOp>(
- cgf.getLoc(e->getSourceRange().getBegin()), operand, nsw);
+ cgf.getLoc(e->getSourceRange().getBegin()), operand, flags);
}
mlir::Value emitIncOrDec(const UnaryOperator *e, mlir::Value input,
bool nsw = false) {
mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
+ auto flags = nsw ? cir::OverflowFlags::nsw : cir::OverflowFlags::none;
return e->isIncrementOp()
- ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
- : builder.createOrFold<cir::DecOp>(loc, input, nsw);
+ ? builder.createOrFold<cir::IncOp>(loc, input, flags)
+ : builder.createOrFold<cir::DecOp>(loc, input, flags);
}
mlir::Value VisitUnaryNot(const UnaryOperator *e) {
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
index 8769975bdc948..cc2d39116181f 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp
@@ -432,11 +432,11 @@ static mlir::Value lowerDataMemberCast(mlir::Operation *op,
mlir::Value adjustedPtr;
if (isDerivedToBase) {
auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
- subOp.setNoSignedWrap(true);
+ subOp.setFlags(cir::OverflowFlags::nsw);
adjustedPtr = subOp;
} else {
auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
- addOp.setNoSignedWrap(true);
+ addOp.setFlags(cir::OverflowFlags::nsw);
adjustedPtr = addOp;
}
@@ -477,12 +477,12 @@ static mlir::Value lowerMethodCast(mlir::Operation *op, mlir::Value loweredSrc,
if (isDerivedToBase) {
auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
adjField, offsetValue);
- subOp.setNoSignedWrap(true);
+ subOp.setFlags(cir::OverflowFlags::nsw);
adjustedAdjField = subOp;
} else {
auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
adjField, offsetValue);
- addOp.setNoSignedWrap(true);
+ addOp.setFlags(cir::OverflowFlags::nsw);
adjustedAdjField = addOp;
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index e17c7a209db6b..614a534dce232 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2582,7 +2582,8 @@ lowerIncDecOp(CIROp op, typename CIROp::Adaptor adaptor,
mlir::Location loc = op.getLoc();
if (mlir::isa<cir::IntType>(elementType)) {
- auto maybeNSW = nswFlag(op.getNoSignedWrap());
+ auto maybeNSW =
+ nswFlag(bitEnumContainsAll(op.getFlags(), cir::OverflowFlags::nsw));
auto one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
rewriter.replaceOpWithNewOp<LLVMIntOp>(op, adaptor.getInput(), one,
maybeNSW);
@@ -2621,7 +2622,8 @@ mlir::LogicalResult CIRToLLVMMinusOpLowering::matchAndRewrite(
mlir::Location loc = op.getLoc();
if (mlir::isa<cir::IntType>(elementType)) {
- auto maybeNSW = nswFlag(op.getNoSignedWrap());
+ auto maybeNSW =
+ nswFlag(bitEnumContainsAll(op.getFlags(), cir::OverflowFlags::nsw));
mlir::Value zero;
if (isVector)
zero = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmType);
@@ -2683,11 +2685,17 @@ static bool isIntTypeUnsigned(mlir::Type type) {
template <typename BinOp>
static mlir::LLVM::IntegerOverflowFlags intOverflowFlag(BinOp op) {
- if (op.getNoUnsignedWrap())
- return mlir::LLVM::IntegerOverflowFlags::nuw;
- if (op.getNoSignedWrap())
- return mlir::LLVM::IntegerOverflowFlags::nsw;
- return mlir::LLVM::IntegerOverflowFlags::none;
+ // cir::OverflowFlags and mlir::LLVM::IntegerOverflowFlags share the same
+ // bit positions (nsw=0, nuw=1) so the underlying values map directly.
+ static_assert(
+ static_cast<uint32_t>(cir::OverflowFlags::nsw) ==
+ static_cast<uint32_t>(mlir::LLVM::IntegerOverflowFlags::nsw),
+ "nsw bit position mismatch between cir and llvm dialects");
+ static_assert(
+ static_cast<uint32_t>(cir::OverflowFlags::nuw) ==
+ static_cast<uint32_t>(mlir::LLVM::IntegerOverflowFlags::nuw),
+ "nuw bit position mismatch between cir and llvm dialects");
+ return static_cast<mlir::LLVM::IntegerOverflowFlags>(op.getFlags());
}
/// Lower an arithmetic op that supports saturation, overflow flags, and an FP
diff --git a/clang/test/CIR/IR/invalid-overflow.cir b/clang/test/CIR/IR/invalid-overflow.cir
new file mode 100644
index 0000000000000..e92dd8b0f6a43
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-overflow.cir
@@ -0,0 +1,39 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+
+cir.func @nsw_on_float(%a: !cir.float, %b: !cir.float) {
+ // expected-error @below {{overflow flags require an integer result type}}
+ %0 = cir.add nsw %a, %b : !cir.float
+ cir.return
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+cir.func @nuw_on_float(%a: !cir.float, %b: !cir.float) {
+ // expected-error @below {{overflow flags require an integer result type}}
+ %0 = cir.mul nuw %a, %b : !cir.float
+ cir.return
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+cir.func @sat_with_nsw(%a: !s32i, %b: !s32i) {
+ // expected-error @below {{sat is mutually exclusive with nsw/nuw overflow flags}}
+ %0 = cir.add sat nsw %a, %b : !s32i
+ cir.return
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+cir.func @sat_with_nuw(%a: !s32i, %b: !s32i) {
+ // expected-error @below {{sat is mutually exclusive with nsw/nuw overflow flags}}
+ %0 = cir.sub sat nuw %a, %b : !s32i
+ cir.return
+}
diff --git a/clang/test/CIR/IR/overflow-flags.cir b/clang/test/CIR/IR/overflow-flags.cir
new file mode 100644
index 0000000000000..78ef1969e9f59
--- /dev/null
+++ b/clang/test/CIR/IR/overflow-flags.cir
@@ -0,0 +1,66 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+!u32i = !cir.int<u, 32>
+
+module {
+ // Round-trip every BitEnum state on cir.add: none (default, elided),
+ // nsw alone, nuw alone, both flags combined, plus saturated.
+ cir.func @test_add_flags(%a: !s32i, %b: !s32i, %c: !u32i, %d: !u32i) {
+ %0 = cir.add %a, %b : !s32i
+ %1 = cir.add nsw %a, %b : !s32i
+ %2 = cir.add nuw %c, %d : !u32i
+ %3 = cir.add nsw|nuw %a, %b : !s32i
+ %4 = cir.add sat %a, %b : !s32i
+ cir.return
+ }
+ // CHECK-LABEL: cir.func{{.*}} @test_add_flags
+ // CHECK: cir.add %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.add nsw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.add nuw %{{.+}}, %{{.+}} : !u32i
+ // CHECK: cir.add nsw|nuw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.add sat %{{.+}}, %{{.+}} : !s32i
+
+ cir.func @test_sub_flags(%a: !s32i, %b: !s32i) {
+ %0 = cir.sub %a, %b : !s32i
+ %1 = cir.sub nsw %a, %b : !s32i
+ %2 = cir.sub nsw|nuw %a, %b : !s32i
+ %3 = cir.sub sat %a, %b : !s32i
+ cir.return
+ }
+ // CHECK-LABEL: cir.func{{.*}} @test_sub_flags
+ // CHECK: cir.sub %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.sub nsw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.sub nsw|nuw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.sub sat %{{.+}}, %{{.+}} : !s32i
+
+ cir.func @test_mul_flags(%a: !s32i, %b: !s32i) {
+ %0 = cir.mul %a, %b : !s32i
+ %1 = cir.mul nsw %a, %b : !s32i
+ %2 = cir.mul nuw %a, %b : !s32i
+ %3 = cir.mul nsw|nuw %a, %b : !s32i
+ cir.return
+ }
+ // CHECK-LABEL: cir.func{{.*}} @test_mul_flags
+ // CHECK: cir.mul %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.mul nsw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.mul nuw %{{.+}}, %{{.+}} : !s32i
+ // CHECK: cir.mul nsw|nuw %{{.+}}, %{{.+}} : !s32i
+
+ cir.func @test_unary_flags(%a: !s32i) {
+ %0 = cir.minus %a : !s32i
+ %1 = cir.minus nsw %a : !s32i
+ %2 = cir.inc %a : !s...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/195618
More information about the llvm-branch-commits
mailing list