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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
