[llvm] [SandboxIR][NFC] Move Instruction classes into a separate file (PR #110294)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 27 09:38:46 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: vporpo (vporpo)
<details>
<summary>Changes</summary>
---
Patch is 395.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110294.diff
17 Files Affected:
- (modified) llvm/benchmarks/SandboxIRBench.cpp (+2-1)
- (modified) llvm/include/llvm/SandboxIR/Constant.h (+1)
- (modified) llvm/include/llvm/SandboxIR/Context.h (+1)
- (added) llvm/include/llvm/SandboxIR/Instruction.h (+2741)
- (modified) llvm/include/llvm/SandboxIR/Region.h (+1-1)
- (modified) llvm/include/llvm/SandboxIR/SandboxIR.h (-2718)
- (modified) llvm/include/llvm/SandboxIR/Utils.h (+1-1)
- (modified) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h (+1-1)
- (modified) llvm/lib/SandboxIR/BasicBlock.cpp (+1-1)
- (modified) llvm/lib/SandboxIR/CMakeLists.txt (+1)
- (modified) llvm/lib/SandboxIR/Context.cpp (+4-1)
- (added) llvm/lib/SandboxIR/Instruction.cpp (+1965)
- (modified) llvm/lib/SandboxIR/SandboxIR.cpp (-1952)
- (modified) llvm/lib/SandboxIR/Tracker.cpp (+1-1)
- (modified) llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp (+1)
- (modified) llvm/unittests/SandboxIR/TrackerTest.cpp (+1-1)
- (modified) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp (+1-1)
``````````diff
diff --git a/llvm/benchmarks/SandboxIRBench.cpp b/llvm/benchmarks/SandboxIRBench.cpp
index d4601d5f53d07a..8f7ab1a3768997 100644
--- a/llvm/benchmarks/SandboxIRBench.cpp
+++ b/llvm/benchmarks/SandboxIRBench.cpp
@@ -18,7 +18,8 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/SandboxIR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include <memory>
#include <sstream>
diff --git a/llvm/include/llvm/SandboxIR/Constant.h b/llvm/include/llvm/SandboxIR/Constant.h
index bc0e3d8849237a..a8cc66ba9d6540 100644
--- a/llvm/include/llvm/SandboxIR/Constant.h
+++ b/llvm/include/llvm/SandboxIR/Constant.h
@@ -17,6 +17,7 @@
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/SandboxIR/Argument.h"
#include "llvm/SandboxIR/Context.h"
#include "llvm/SandboxIR/Type.h"
#include "llvm/SandboxIR/User.h"
diff --git a/llvm/include/llvm/SandboxIR/Context.h b/llvm/include/llvm/SandboxIR/Context.h
index 092b791bc2acb9..37f52d74209cb3 100644
--- a/llvm/include/llvm/SandboxIR/Context.h
+++ b/llvm/include/llvm/SandboxIR/Context.h
@@ -159,6 +159,7 @@ class Context {
public:
Context(LLVMContext &LLVMCtx);
+ ~Context();
Tracker &getTracker() { return IRTracker; }
/// Convenience function for `getTracker().save()`
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
new file mode 100644
index 00000000000000..f5f5bb5c4443c2
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -0,0 +1,2741 @@
+//===- Instruction.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_INSTRUCTION_H
+#define LLVM_SANDBOXIR_INSTRUCTION_H
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/SandboxIR/BasicBlock.h"
+#include "llvm/SandboxIR/Constant.h"
+#include "llvm/SandboxIR/User.h"
+
+namespace llvm::sandboxir {
+
+/// A sandboxir::User with operands, opcode and linked with previous/next
+/// instructions in an instruction list.
+class Instruction : public User {
+public:
+ enum class Opcode {
+#define OP(OPC) OPC,
+#define OPCODES(...) __VA_ARGS__
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ };
+
+protected:
+ Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
+ sandboxir::Context &SBCtx)
+ : User(ID, I, SBCtx), Opc(Opc) {}
+
+ Opcode Opc;
+
+ /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
+ /// returns its topmost LLVM IR instruction.
+ llvm::Instruction *getTopmostLLVMInstruction() const;
+ friend class VAArgInst; // For getTopmostLLVMInstruction().
+ friend class FreezeInst; // For getTopmostLLVMInstruction().
+ friend class FenceInst; // For getTopmostLLVMInstruction().
+ friend class SelectInst; // For getTopmostLLVMInstruction().
+ friend class ExtractElementInst; // For getTopmostLLVMInstruction().
+ friend class InsertElementInst; // For getTopmostLLVMInstruction().
+ friend class ShuffleVectorInst; // For getTopmostLLVMInstruction().
+ friend class ExtractValueInst; // For getTopmostLLVMInstruction().
+ friend class InsertValueInst; // For getTopmostLLVMInstruction().
+ friend class BranchInst; // For getTopmostLLVMInstruction().
+ friend class LoadInst; // For getTopmostLLVMInstruction().
+ friend class StoreInst; // For getTopmostLLVMInstruction().
+ friend class ReturnInst; // For getTopmostLLVMInstruction().
+ friend class CallInst; // For getTopmostLLVMInstruction().
+ friend class InvokeInst; // For getTopmostLLVMInstruction().
+ friend class CallBrInst; // For getTopmostLLVMInstruction().
+ friend class LandingPadInst; // For getTopmostLLVMInstruction().
+ friend class CatchPadInst; // For getTopmostLLVMInstruction().
+ friend class CleanupPadInst; // For getTopmostLLVMInstruction().
+ friend class CatchReturnInst; // For getTopmostLLVMInstruction().
+ friend class CleanupReturnInst; // For getTopmostLLVMInstruction().
+ friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
+ friend class ResumeInst; // For getTopmostLLVMInstruction().
+ friend class CatchSwitchInst; // For getTopmostLLVMInstruction().
+ friend class SwitchInst; // For getTopmostLLVMInstruction().
+ friend class UnaryOperator; // For getTopmostLLVMInstruction().
+ friend class BinaryOperator; // For getTopmostLLVMInstruction().
+ friend class AtomicRMWInst; // For getTopmostLLVMInstruction().
+ friend class AtomicCmpXchgInst; // For getTopmostLLVMInstruction().
+ friend class AllocaInst; // For getTopmostLLVMInstruction().
+ friend class CastInst; // For getTopmostLLVMInstruction().
+ friend class PHINode; // For getTopmostLLVMInstruction().
+ friend class UnreachableInst; // For getTopmostLLVMInstruction().
+ friend class CmpInst; // For getTopmostLLVMInstruction().
+
+ /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
+ /// order.
+ virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0;
+ friend class EraseFromParent; // For getLLVMInstrs().
+
+public:
+ static const char *getOpcodeName(Opcode Opc);
+ /// This is used by BasicBlock::iterator.
+ virtual unsigned getNumOfIRInstrs() const = 0;
+ /// \Returns a BasicBlock::iterator for this Instruction.
+ BBIterator getIterator() const;
+ /// \Returns the next sandboxir::Instruction in the block, or nullptr if at
+ /// the end of the block.
+ Instruction *getNextNode() const;
+ /// \Returns the previous sandboxir::Instruction in the block, or nullptr if
+ /// at the beginning of the block.
+ Instruction *getPrevNode() const;
+ /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode
+ /// state to allow for new SandboxIR-specific instructions.
+ Opcode getOpcode() const { return Opc; }
+
+ const char *getOpcodeName() const { return getOpcodeName(Opc); }
+
+ // Note that these functions below are calling into llvm::Instruction.
+ // A sandbox IR instruction could introduce a new opcode that could change the
+ // behavior of one of these functions. It is better that these functions are
+ // only added as needed and new sandbox IR instructions must explicitly check
+ // if any of these functions could have a different behavior.
+
+ bool isTerminator() const {
+ return cast<llvm::Instruction>(Val)->isTerminator();
+ }
+ bool isUnaryOp() const { return cast<llvm::Instruction>(Val)->isUnaryOp(); }
+ bool isBinaryOp() const { return cast<llvm::Instruction>(Val)->isBinaryOp(); }
+ bool isIntDivRem() const {
+ return cast<llvm::Instruction>(Val)->isIntDivRem();
+ }
+ bool isShift() const { return cast<llvm::Instruction>(Val)->isShift(); }
+ bool isCast() const { return cast<llvm::Instruction>(Val)->isCast(); }
+ bool isFuncletPad() const {
+ return cast<llvm::Instruction>(Val)->isFuncletPad();
+ }
+ bool isSpecialTerminator() const {
+ return cast<llvm::Instruction>(Val)->isSpecialTerminator();
+ }
+ bool isOnlyUserOfAnyOperand() const {
+ return cast<llvm::Instruction>(Val)->isOnlyUserOfAnyOperand();
+ }
+ bool isLogicalShift() const {
+ return cast<llvm::Instruction>(Val)->isLogicalShift();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Metadata manipulation.
+ //===--------------------------------------------------------------------===//
+
+ /// Return true if the instruction has any metadata attached to it.
+ bool hasMetadata() const {
+ return cast<llvm::Instruction>(Val)->hasMetadata();
+ }
+
+ /// Return true if this instruction has metadata attached to it other than a
+ /// debug location.
+ bool hasMetadataOtherThanDebugLoc() const {
+ return cast<llvm::Instruction>(Val)->hasMetadataOtherThanDebugLoc();
+ }
+
+ /// Return true if this instruction has the given type of metadata attached.
+ bool hasMetadata(unsigned KindID) const {
+ return cast<llvm::Instruction>(Val)->hasMetadata(KindID);
+ }
+
+ // TODO: Implement getMetadata and getAllMetadata after sandboxir::MDNode is
+ // available.
+
+ // TODO: More missing functions
+
+ /// Detach this from its parent BasicBlock without deleting it.
+ void removeFromParent();
+ /// Detach this Value from its parent and delete it.
+ void eraseFromParent();
+ /// Insert this detached instruction before \p BeforeI.
+ void insertBefore(Instruction *BeforeI);
+ /// Insert this detached instruction after \p AfterI.
+ void insertAfter(Instruction *AfterI);
+ /// Insert this detached instruction into \p BB at \p WhereIt.
+ void insertInto(BasicBlock *BB, const BBIterator &WhereIt);
+ /// Move this instruction to \p WhereIt.
+ void moveBefore(BasicBlock &BB, const BBIterator &WhereIt);
+ /// Move this instruction before \p Before.
+ void moveBefore(Instruction *Before) {
+ moveBefore(*Before->getParent(), Before->getIterator());
+ }
+ /// Move this instruction after \p After.
+ void moveAfter(Instruction *After) {
+ moveBefore(*After->getParent(), std::next(After->getIterator()));
+ }
+ // TODO: This currently relies on LLVM IR Instruction::comesBefore which is
+ // can be linear-time.
+ /// Given an instruction Other in the same basic block as this instruction,
+ /// return true if this instruction comes before Other.
+ bool comesBefore(const Instruction *Other) const {
+ return cast<llvm::Instruction>(Val)->comesBefore(
+ cast<llvm::Instruction>(Other->Val));
+ }
+ /// \Returns the BasicBlock containing this Instruction, or null if it is
+ /// detached.
+ BasicBlock *getParent() const;
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From);
+
+ /// Determine whether the no signed wrap flag is set.
+ bool hasNoUnsignedWrap() const {
+ return cast<llvm::Instruction>(Val)->hasNoUnsignedWrap();
+ }
+ /// Set or clear the nuw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoUnsignedWrap(bool B = true);
+ /// Determine whether the no signed wrap flag is set.
+ bool hasNoSignedWrap() const {
+ return cast<llvm::Instruction>(Val)->hasNoSignedWrap();
+ }
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoSignedWrap(bool B = true);
+ /// Determine whether all fast-math-flags are set.
+ bool isFast() const { return cast<llvm::Instruction>(Val)->isFast(); }
+ /// Set or clear all fast-math-flags on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setFast(bool B);
+ /// Determine whether the allow-reassociation flag is set.
+ bool hasAllowReassoc() const {
+ return cast<llvm::Instruction>(Val)->hasAllowReassoc();
+ }
+ /// Set or clear the reassociation flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowReassoc(bool B);
+ /// Determine whether the exact flag is set.
+ bool isExact() const { return cast<llvm::Instruction>(Val)->isExact(); }
+ /// Set or clear the exact flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setIsExact(bool B = true);
+ /// Determine whether the no-NaNs flag is set.
+ bool hasNoNaNs() const { return cast<llvm::Instruction>(Val)->hasNoNaNs(); }
+ /// Set or clear the no-nans flag on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoNaNs(bool B);
+ /// Determine whether the no-infs flag is set.
+ bool hasNoInfs() const { return cast<llvm::Instruction>(Val)->hasNoInfs(); }
+ /// Set or clear the no-infs flag on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoInfs(bool B);
+ /// Determine whether the no-signed-zeros flag is set.
+ bool hasNoSignedZeros() const {
+ return cast<llvm::Instruction>(Val)->hasNoSignedZeros();
+ }
+ /// Set or clear the no-signed-zeros flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoSignedZeros(bool B);
+ /// Determine whether the allow-reciprocal flag is set.
+ bool hasAllowReciprocal() const {
+ return cast<llvm::Instruction>(Val)->hasAllowReciprocal();
+ }
+ /// Set or clear the allow-reciprocal flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowReciprocal(bool B);
+ /// Determine whether the allow-contract flag is set.
+ bool hasAllowContract() const {
+ return cast<llvm::Instruction>(Val)->hasAllowContract();
+ }
+ /// Set or clear the allow-contract flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowContract(bool B);
+ /// Determine whether the approximate-math-functions flag is set.
+ bool hasApproxFunc() const {
+ return cast<llvm::Instruction>(Val)->hasApproxFunc();
+ }
+ /// Set or clear the approximate-math-functions flag on this instruction,
+ /// which must be an operator which supports this flag. See LangRef.html for
+ /// the meaning of this flag.
+ void setHasApproxFunc(bool B);
+ /// Convenience function for getting all the fast-math flags, which must be an
+ /// operator which supports these flags. See LangRef.html for the meaning of
+ /// these flags.
+ FastMathFlags getFastMathFlags() const {
+ return cast<llvm::Instruction>(Val)->getFastMathFlags();
+ }
+ /// Convenience function for setting multiple fast-math flags on this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void setFastMathFlags(FastMathFlags FMF);
+ /// Convenience function for transferring all fast-math flag values to this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void copyFastMathFlags(FastMathFlags FMF);
+
+ bool isAssociative() const {
+ return cast<llvm::Instruction>(Val)->isAssociative();
+ }
+
+ bool isCommutative() const {
+ return cast<llvm::Instruction>(Val)->isCommutative();
+ }
+
+ bool isIdempotent() const {
+ return cast<llvm::Instruction>(Val)->isIdempotent();
+ }
+
+ bool isNilpotent() const {
+ return cast<llvm::Instruction>(Val)->isNilpotent();
+ }
+
+ bool mayWriteToMemory() const {
+ return cast<llvm::Instruction>(Val)->mayWriteToMemory();
+ }
+
+ bool mayReadFromMemory() const {
+ return cast<llvm::Instruction>(Val)->mayReadFromMemory();
+ }
+ bool mayReadOrWriteMemory() const {
+ return cast<llvm::Instruction>(Val)->mayReadOrWriteMemory();
+ }
+
+ bool isAtomic() const { return cast<llvm::Instruction>(Val)->isAtomic(); }
+
+ bool hasAtomicLoad() const {
+ return cast<llvm::Instruction>(Val)->hasAtomicLoad();
+ }
+
+ bool hasAtomicStore() const {
+ return cast<llvm::Instruction>(Val)->hasAtomicStore();
+ }
+
+ bool isVolatile() const { return cast<llvm::Instruction>(Val)->isVolatile(); }
+
+ Type *getAccessType() const;
+
+ bool mayThrow(bool IncludePhaseOneUnwind = false) const {
+ return cast<llvm::Instruction>(Val)->mayThrow(IncludePhaseOneUnwind);
+ }
+
+ bool isFenceLike() const {
+ return cast<llvm::Instruction>(Val)->isFenceLike();
+ }
+
+ bool mayHaveSideEffects() const {
+ return cast<llvm::Instruction>(Val)->mayHaveSideEffects();
+ }
+
+ // TODO: Missing functions.
+
+ bool isStackSaveOrRestoreIntrinsic() const {
+ auto *I = cast<llvm::Instruction>(Val);
+ return match(I,
+ PatternMatch::m_Intrinsic<llvm::Intrinsic::stackrestore>()) ||
+ match(I, PatternMatch::m_Intrinsic<llvm::Intrinsic::stacksave>());
+ }
+
+ /// We consider \p I as a Memory Dependency Candidate instruction if it
+ /// reads/write memory or if it has side-effects. This is used by the
+ /// dependency graph.
+ bool isMemDepCandidate() const {
+ auto *I = cast<llvm::Instruction>(Val);
+ return I->mayReadOrWriteMemory() &&
+ (!isa<llvm::IntrinsicInst>(I) ||
+ (cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
+ Intrinsic::sideeffect &&
+ cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
+ Intrinsic::pseudoprobe));
+ }
+
+#ifndef NDEBUG
+ void dumpOS(raw_ostream &OS) const override;
+#endif
+};
+
+/// Instructions that contain a single LLVM Instruction can inherit from this.
+template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
+ SingleLLVMInstructionImpl(ClassID ID, Opcode Opc, llvm::Instruction *I,
+ sandboxir::Context &SBCtx)
+ : Instruction(ID, Opc, I, SBCtx) {}
+
+ // All instructions are friends with this so they can call the constructor.
+#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ friend class UnaryInstruction;
+ friend class CallBase;
+ friend class FuncletPadInst;
+ friend class CmpInst;
+
+ Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+ return getOperandUseDefault(OpIdx, Verify);
+ }
+ SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
+ return {cast<llvm::Instruction>(Val)};
+ }
+
+public:
+ unsigned getUseOperandNo(const Use &Use) const final {
+ return getUseOperandNoDefault(Use);
+ }
+ unsigned getNumOfIRInstrs() const final { return 1u; }
+#ifndef NDEBUG
+ void verify() const final { assert(isa<LLVMT>(Val) && "Expected LLVMT!"); }
+ void dumpOS(raw_ostream &OS) const override {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+ }
+#endif
+};
+
+class FenceInst : public SingleLLVMInstructionImpl<llvm::FenceInst> {
+ FenceInst(llvm::FenceInst *FI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Fence, Opcode::Fence, FI, Ctx) {}
+ friend Context; // For constructor;
+
+public:
+ static FenceInst *create(AtomicOrdering Ordering, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System);
+ /// Returns the ordering constraint of this fence instruction.
+ AtomicOrdering getOrdering() const {
+ return cast<llvm::FenceInst>(Val)->getOrdering();
+ }
+ /// Sets the ordering constraint of this fence instruction. May only be
+ /// Acquire, Release, AcquireRelease, or SequentiallyConsistent.
+ void setOrdering(AtomicOrdering Ordering);
+ /// Returns the synchronization scope ID of this fence instruction.
+ SyncScope::ID getSyncScopeID() const {
+ return cast<llvm::FenceInst>(Val)->getSyncScopeID();
+ }
+ /// Sets the synchronization scope ID of this fence instruction.
+ void setSyncScopeID(SyncScope::ID SSID);
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Fence;
+ }
+};
+
+class SelectInst : public SingleLLVMInstructionImpl<llvm::SelectInst> {
+ /// Use Context::createSelectInst(). Don't call the
+ /// constructor directly.
+ SelectInst(llvm::SelectInst *CI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Select, Opcode::Select, CI, Ctx) {}
+ friend Context; // for SelectInst()
+ static Value *createCommon(Value *Cond, Value *True, Value *False,
+ const Twine &Name, IRBuilder<> &Builder,
+ Context &Ctx);
+
+public:
+ static Value *create(Value *C...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/110294
More information about the llvm-commits
mailing list