[ADT] Derive FoldingSetNodeIDRef from ArrayRef<unsigned> (NFC) (#220824)
This patch derives FoldingSetNodeIDRef from ArrayRef<unsigned>,
benefiting from:
- Standard ArrayRef accessors like data() and size() instead of custom
getData() and getSize().
- Range-based for loops directly over FoldingSetNodeIDRef.
- Implicit conversions to and from SmallVector<unsigned>, simplifying
FoldingSetNodeID.
Assisted-by: Antigravity
Don't fail a release because a deferred snapshot is still busy
dsl_dataset_user_release_check_one() fails the whole release with
EBUSY when the last hold comes off a snapshot that is marked for
deferred destruction and is still long held. Mark one while it is
idle, with "zfs hold t pool/fs at snap" and then "zfs destroy -d
pool/fs at snap", mount it afterwards by listing .zfs/snapshot, and
"zfs release t pool/fs at snap" reports "dataset is busy" and leaves the
tag where it was. The caller is now sitting on a tag they cannot
drop until the mount goes, and the best-effort unmount the release
path already does cannot take a mount away from an open file.
The check was there because the release is what destroys the
snapshot, and destroying one that something still holds is not on.
Where an owner is what holds it, that is no longer the only way it
gets destroyed: the owner ends at dsl_dataset_disown(), which asks
for the sweep, so the release can drop the tag and leave the mark to
be collected in the ordinary way. Every other long hold keeps
failing the release as before. Nothing would come back for the mark
[20 lines not shown]
Defer destruction of a snapshot that a mount is holding open
On Linux, "zfs destroy -d" on a snapshot automounted under
.zfs/snapshot with a file still open fails with EBUSY, exactly the
way the plain destroy does, and leaves defer_destroy off. The -d
option is documented as marking whatever it cannot destroy right
away, so there is currently no way to say "get rid of it when you
can" about a snapshot someone is reading. Issue #16339.
dsl_destroy_snapshot_check_impl() turns away any long-held snapshot
before it looks at the defer flag, and a snapshot is long held for as
long as it is mounted. Taking the mount away instead is not on the
table: zfsctl_snapshot_unmount() invalidates the snapdir dentry,
which detaches the mount, but the dataset stays owned until the last
open file goes, and the 20ms it then waits is not enough for a file
someone is still reading. FreeBSD never lands here, since its
zfsctl_snapshot_unmount() goes through dounmount() with MS_FORCE.
So let the snapshot be marked, and destroy it once whatever was
[44 lines not shown]
MachinePipeliner: Pass instruction to findLoopIncrementValue (#219966)
The helper recovered the loop block from the operand's parent
instruction. Pass the containing instruction directly so it no longer depends
on MachineOperand::getParent().
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
[flang][cuda] Reject DEVICE derived types with attributed allocatable components (#220411)
CUDA attributed allocatables are allocated from the host in most case
(PINNED, MANAGED, UNIFIED). A DEVICE derived-type object keeps its
component descriptors in device global memory, so allocating such a
component is not valid. It's also invalid for a DEVICE component unless
the allocate statement is in device context.
[VPlan] Allow non-live-in start values for widened inductions (NFC). (#220716)
Prepare VPWidenIntOrFpInductionRecipe for modeling the full epilogue
skeleton and resume values properly, by removing the VPIRValue
requirement for the start value.
The only requirement for the start value is that it dominates the phi,
which the verifier already ensures.
This is NFC today, but prepares for modeling the full epilogue skeleton
in VPlan, which requires adding phi nodes in the preheader before
execute.
[flang][OpenMP] Track reachable metadirective replacement paths
The existing semantic checks can validate loop-associated directives in a
METADIRECTIVE against the following loop, but they do not model how the
METADIRECTIVE chooses among its replacements.
Today each WHEN is considered independently: if its selector can match, its
replacement is checked. Selection instead ranks all applicable candidates as
a set. An unguarded higher-ranked candidate makes lower-ranked candidates
unreachable, while a dynamically guarded candidate leaves them reachable
when its condition is false. Treating both cases alike can diagnose loop
requirements on a replacement that can never be selected.
The selected replacement can also affect later selection. Its directive
contributes to the construct context seen by a nested metadirective. The
checker currently retains only syntactic nesting, so nested construct
selectors cannot observe a directive selected by an enclosing
metadirective.
[44 lines not shown]
[libc++][pstl] Implementation of parallel std::find_end() based on __parallel_find() (#218321)
This PR implements a parallel version of `std::find_end()` based on
`__parallel_find()`.
The algorithm crops the input range to a range where a potential match
can start and runs a chunked parallel find on the cropped range.
Inside each chunk potential matches are looked for using the serial
`std::find_end()` and the last one found is returned.
Since it's based on `__parallel_find()`, the algorithm supports early
termination.
Part of #99938.
[CIR] Use the modern enum case classes
The `I32EnumAttrCase` family carries an `Attr` half, and an `IntegerAttr`
predicate with it, that a CIR enum has no use for now that the enums derive
from `EnumInfo`. Upstream says of those forms that they "are not needed when
using the newer `EnumCase` form".
Rename all 198 of them to `I32EnumCase`, `I32BitEnumCaseNone`,
`I32BitEnumCaseBit` and `BitEnumCaseGroup`. The group class drops its width
prefix because the modern spelling takes the width from its cases.
NFC, mechanical.
[CIR] Record why the CUDA registration attribute parses itself
hasCustomAssemblyFormat with no explanation invites the question of whether a
declarative assemblyFormat would do. It would not. The three flags print as
presence-only keywords and parse in any order, while an optional group
anchored on a `bool` parameter parses and prints a value, so the group would
spell `extern true`. MLIR has no presence-only flag for `bool` in an
attribute format, unlike UnitAttr in an operation format. struct(params)
round-trips but spells the attribute
`<device_side_name = "i", kind = Variable, isExtern = true>` instead of
`<i, Variable, extern>`.
NFC.
[CIR] Drop the redundant suffix from the inline kind mnemonic
inline_kind was the one CIR enum attribute mnemonic still repeating what its
C++ enum class name says. The attribute now spells
`#cir.inline<always_inline>`. The operation argument keeps the name
inline_kind, since that is the accessor name, so the printed form reads
`inline_kind = #cir.inline<always_inline>`.
The enum's summary also becomes "inline kind" rather than the camelCase
"inlineKind", which is what generated docs show now that CIR_InlineKindAttr
no longer overrides it.
25 CHECK lines change across four test files. Nine are in an
aarch64-registered-target test, unsupported in an X86-only build, but the
substitution matches the two CIR tests that do run.
[CIR] Derive lowering attr names from cppClassName, not the def name
CIRLoweringEmitter built its CXX_ABI_ALWAYS_LEGAL_ATTRS entries with
GetOpCppClassName, which splits the TableGen def name at the first
underscore. That works only while every def is named CIR_<CppClassName>Attr.
When one is not, the emitter writes an `isa<>` for a class that does not
exist, and the failure lands as a compile error in generated code.
Attributes carry the authoritative name in cppClassName, which
GenerateAttrToValueVisitor was already reading. Factor that out as
GetAttrCppClassRef and use it for both attribute paths. GetOpCppClassName
stays for operations.
NFC, and checkable. No CIR attribute overrides cppClassName, so the generated
CIRLowering.inc is byte-identical.
[CIR] Drop dead ceremony around the CIR enum attributes
Five things that no longer earn their place in the CIR enum attribute
machinery.
CIR_CleanupKindAttr carried three. Its cppClassName restated the default
AttrDef already derives. Its skipDefaultBuilders plus hand-written
AttrBuilder existed only to default $value to CleanupKind::All, which no
caller relies on, so the generated builders stayed suppressed for nothing.
And its summary and description restated the name, overriding the enum's own
"cleanup kind" that EnumAttr would otherwise inherit. The isNormal, isEH and
isNormalAndEH helpers stay.
CIR_TLSModelAttr's summary restated its name the same way, so only that goes.
CIR_DefaultValuedEnumParameter has never had a user.
NFC.
[CIR] Move the CIR enums off the legacy EnumAttrInfo hierarchy
MLIR has two enum hierarchies. `EnumAttrInfo` doubles as an `IntegerAttr`
constraint, so every CIR enum had to clear `genSpecializedAttr` to say it did
not want one. `EnumInfo` describes a C++ enum and nothing more.
Derive the CIR bases from `I32Enum`, `I64Enum` and `I32BitEnum`, and widen
`CIR_EnumAttr` to the `EnumInfo` that upstream `EnumAttr` already takes. The
flag no longer exists to clear. `FPClassTestEnum` gets unquoted printing from
`BitEnumBase` rather than overriding `printBitEnumQuoted`, and
`CIR_KnownFuncKind` drops a `parameterPrinter` the generated `operator<<`
now covers, still spelling `#cir.func_identity<"std::find">`.
AMDGPU wraps an `I32Enum` in an `EnumAttr` with this same bracketed format.
Parsing moves to the generated `FieldParser`, whose diagnostic names the
accepted spellings, so two `expected-error` lines change. Generated attribute
code drops 16 KB as 28 inlined parsers collapse into it.
[CIR] Migrate the FPClassTest bit enum and unquote its flags
cir.is_fp_class printed its flags inconsistently. Single-bit values came out
bare, as in `fcSNan`, while group values and combinations came out quoted, as
in `"fcInf"` and `"fcSNan|fcNegInf"`. That comes from I32BitEnumAttr setting
printBitEnumQuoted, which EnumAttr.td keeps only for backwards compatibility.
Clearing the bit and using the `enum` directive selects the separator-aware
parser and printer, so every value now spells unquoted:
cir.is_fp_class %x, fcSNan|fcNegInf : (!cir.float) -> !cir.bool
The enum also drops its specialized IntegerAttr for a CIR_EnumAttr wrapper,
giving it the standalone spelling `#cir.fp_class<fcSNan|fcNegInf>`. This
changes operation syntax, so it updates 37 CHECK lines.
[CIR] Migrate GlobalLinkageKind, CallingConv and SideEffect off IntegerAttr
GlobalLinkageKind, CallingConv and SideEffect generated IntegerAttr
subclasses with no dialect spelling of their own. Each now sets
genSpecializedAttr = 0 and gains a CIR_EnumAttr wrapper, and cir.global wraps
$linkage in `enum()`. GlobalLinkageKind spells `#cir.linkage<internal>`,
dropping both the `global_` prefix and the `_kind` suffix.
cir.func and cir.call print all three by hand, but they stream
stringifyGlobalLinkageKind(getLinkage()) and friends, which take the enum
rather than the attribute, so those sites are unchanged.
Operation syntax is unchanged.
[CIR] Migrate AssumeBundleKind, AtomicFetchKind and AsmFlavor off IntegerAttr
AssumeBundleKind, AtomicFetchKind and AsmFlavor generated IntegerAttr
subclasses with no dialect spelling of their own. Each now sets
genSpecializedAttr = 0 and gains a CIR_EnumAttr wrapper.
Unlike the other CIR operation enums, these three are reached through
hand-written parsers and printers, so they needed checking individually.
cir.atomic.fetch references $binop declaratively and gains an `enum()`
wrapper. The other two need no change, since printAssumeBundle is already
typed on cir::AssumeBundleKindAttr and InlineAsmOp::print streams the enum
rather than the attribute.
Operation syntax is unchanged.
[CIR] Migrate MemOrder and SyncScopeKind off IntegerAttr
MemOrder and SyncScopeKind, the enums the atomic operations share, generated
IntegerAttr subclasses with no dialect spelling of their own.
Both now set genSpecializedAttr = 0 and gain CIR_EnumAttr wrappers, spelling
`#cir.mem_order<seq_cst>` and `#cir.sync_scope<system>`, and the atomic
operations wrap their arguments in `enum()` to keep the bare keyword.
`enum()` works as an optional-group anchor, so the `syncscope` and `atomic`
groups on cir.load and cir.store are unaffected. Operation syntax is
unchanged.