[IR] Remove terminatepad

It turns out that terminatepad gives little benefit over a cleanuppad
which calls the termination function.  This is not sufficient to
implement fully generic filters but MSVC doesn't support them which
makes terminatepad a little over-designed.

Depends on D15478.

Differential Revision: http://reviews.llvm.org/D15479

llvm-svn: 255522
This commit is contained in:
David Majnemer 2015-12-14 18:34:23 +00:00
parent feeefb214d
commit bbfc7219ef
41 changed files with 109 additions and 770 deletions

View File

@ -615,15 +615,11 @@ purposes.
The following new instructions are considered "exception handling pads", in that
they must be the first non-phi instruction of a basic block that may be the
unwind destination of an EH flow edge:
``catchswitch``, ``catchpad``, ``cleanuppad``, and ``terminatepad``.
``catchswitch``, ``catchpad``, and ``cleanuppad``.
As with landingpads, when entering a try scope, if the
frontend encounters a call site that may throw an exception, it should emit an
invoke that unwinds to a ``catchswitch`` block. Similarly, inside the scope of a
C++ object with a destructor, invokes should unwind to a ``cleanuppad``. The
``terminatepad`` instruction exists to represent ``noexcept`` and throw
specifications with one combined instruction. All potentially throwing calls in
a ``noexcept`` function should transitively unwind to a terminateblock. Throw
specifications are not implemented by MSVC, and are not yet supported.
C++ object with a destructor, invokes should unwind to a ``cleanuppad``.
New instructions are also used to mark the points where control is transferred
out of a catch/cleanup handler (which will correspond to exits from the
@ -634,9 +630,9 @@ by normal execution executes a ``cleanupret`` instruction, which is a terminator
indicating where the active exception will unwind to next.
Each of these new EH pad instructions has a way to identify which action should
be considered after this action. The ``catchswitch`` and ``terminatepad``
instructions are terminators, and have a unwind destination operand analogous
to the unwind destination of an invoke. The ``cleanuppad`` instruction is not
be considered after this action. The ``catchswitch`` instruction is a terminator
and has an unwind destination operand analogous to the unwind destination of an
invoke. The ``cleanuppad`` instruction is not
a terminator, so the unwind destination is stored on the ``cleanupret``
instruction instead. Successfully executing a catch handler should resume
normal control flow, so neither ``catchpad`` nor ``catchret`` instructions can
@ -707,7 +703,9 @@ all of the new IR instructions:
catchret from %catch to label %return
lpad.terminate: ; preds = %catch.body, %lpad.catch
terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
cleanuppad within none []
call void @"\01?terminate@@YAXXZ"
unreachable
}
Funclet parent tokens
@ -725,8 +723,7 @@ The ``catchswitch`` instruction does not create a funclet, but it produces a
token that is always consumed by its immediate successor ``catchpad``
instructions. This ensures that every catch handler modelled by a ``catchpad``
belongs to exactly one ``catchswitch``, which models the dispatch point after a
C++ try. The ``terminatepad`` instruction cannot contain lexically nested
funclets inside the termination action, so it does not produce a token.
C++ try.
Here is an example of what this nesting looks like using some hypothetical
C++ code:

View File

@ -5004,7 +5004,6 @@ The terminator instructions are: ':ref:`ret <i_ret>`',
':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`',
':ref:`catchret <i_catchret>`',
':ref:`cleanupret <i_cleanupret>`',
':ref:`terminatepad <i_terminatepad>`',
and ':ref:`unreachable <i_unreachable>`'.
.. _i_ret:
@ -5388,8 +5387,7 @@ The ``parent`` argument is the token of the funclet that contains the
this operand may be the token ``none``.
The ``default`` argument is the label of another basic block beginning with a
"pad" instruction, one of ``cleanuppad``, ``terminatepad``, or
``catchswitch``.
"pad" instruction, one of ``cleanuppad`` or ``catchswitch``.
The ``handlers`` are a list of successor blocks that each begin with a
:ref:`catchpad <i_catchpad>` instruction.
@ -5473,7 +5471,7 @@ The pad may then be "exited" in one of three ways:
is undefined behavior if any descendant pads have been entered but not yet
exited.
2) implicitly via a call (which unwinds all the way to the current function's caller),
or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller.
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
the ``catchpad``. When the ``catchpad`` is exited in this manner, it is
undefined behavior if the destination EH pad has a parent which is not an
@ -5589,62 +5587,6 @@ Example:
cleanupret from %cleanup unwind to caller
cleanupret from %cleanup unwind label %continue
.. _i_terminatepad:
'``terminatepad``' Instruction
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
::
terminatepad within <token> [<args>*] unwind label <exception label>
terminatepad within <token> [<args>*] unwind to caller
Overview:
"""""""""
The '``terminatepad``' instruction is used by `LLVM's exception handling
system <ExceptionHandling.html#overview>`_ to specify that a basic block
is a terminate block --- one where a personality routine may decide to
terminate the program.
The ``args`` correspond to whatever information the personality
routine requires to know if this is an appropriate place to terminate the
program. Control is transferred to the ``exception`` label if the
personality routine decides not to terminate the program for the
in-flight exception.
Arguments:
""""""""""
The instruction takes a list of arbitrary values which are interpreted
by the :ref:`personality function <personalityfn>`.
The ``terminatepad`` may be given an ``exception`` label to
transfer control to if the in-flight exception matches the ``args``.
Semantics:
""""""""""
When the call stack is being unwound due to an exception being thrown,
the exception is compared against the ``args``. If it matches,
then control is transfered to the ``exception`` basic block. Otherwise,
the program is terminated via personality-specific means. Typically,
the first argument to ``terminatepad`` specifies what function the
personality should defer to in order to terminate the program.
The ``terminatepad`` instruction is both a terminator and a "pad" instruction,
meaning that is always the only non-phi instruction in the basic block.
Example:
""""""""
.. code-block:: llvm
;; A terminate block which only permits integers.
terminatepad within none [i8** @_ZTIi] unwind label %continue
.. _i_unreachable:
'``unreachable``' Instruction
@ -8686,7 +8628,7 @@ The pad may then be "exited" in one of three ways:
is undefined behavior if any descendant pads have been entered but not yet
exited.
2) implicitly via a call (which unwinds all the way to the current function's caller),
or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller.
3) implicitly via an unwind edge whose destination EH pad isn't a descendant of
the ``cleanuppad``. When the ``cleanuppad`` is exited in this manner, it is
undefined behavior if the destination EH pad has a parent which is not an

View File

@ -252,9 +252,8 @@ typedef enum {
LLVMCleanupRet = 61,
LLVMCatchRet = 62,
LLVMCatchPad = 63,
LLVMTerminatePad = 64,
LLVMCleanupPad = 65,
LLVMCatchSwitch = 66
LLVMCleanupPad = 64,
LLVMCatchSwitch = 65
} LLVMOpcode;
typedef enum {
@ -1224,7 +1223,6 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(TerminatePadInst) \
macro(FuncletPadInst) \
macro(CatchPadInst) \
macro(CleanupPadInst) \

View File

@ -421,9 +421,9 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [val] or [val,bb#]
FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [val,bb#]
FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [bb#,bb#,num,args...]
FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
FUNC_CODE_INST_CATCHSWITCH = 53, // CATCHSWITCH: [num,args...] or [num,args...,bb]
FUNC_CODE_INST_CLEANUPPAD = 51, // CLEANUPPAD: [num,args...]
FUNC_CODE_INST_CATCHSWITCH = 52, // CATCHSWITCH: [num,args...] or [num,args...,bb]
// 53 is unused.
// 54 is unused.
FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
};

View File

@ -720,13 +720,6 @@ public:
return Insert(CatchPadInst::Create(ParentPad, Args), Name);
}
TerminatePadInst *CreateTerminatePad(Value *ParentPad,
BasicBlock *UnwindBB = nullptr,
ArrayRef<Value *> Args = None,
const Twine &Name = "") {
return Insert(TerminatePadInst::Create(ParentPad, UnwindBB, Args), Name);
}
CleanupPadInst *CreateCleanupPad(Value *ParentPad,
ArrayRef<Value *> Args = None,
const Twine &Name = "") {

View File

@ -172,7 +172,6 @@ public:
RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst); }
RetTy visitCatchSwitchInst(CatchSwitchInst &I) { DELEGATE(TerminatorInst);}
RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);}
RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);}
RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);}
RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);}

View File

@ -87,7 +87,6 @@ public:
case Instruction::CleanupRet:
case Instruction::Invoke:
case Instruction::Resume:
case Instruction::TerminatePad:
return true;
default:
return false;

View File

@ -117,85 +117,84 @@ HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
HANDLE_TERM_INST (11, TerminatePad , TerminatePadInst)
LAST_TERM_INST (11)
LAST_TERM_INST (10)
// Standard binary operators...
FIRST_BINARY_INST(12)
HANDLE_BINARY_INST(12, Add , BinaryOperator)
HANDLE_BINARY_INST(13, FAdd , BinaryOperator)
HANDLE_BINARY_INST(14, Sub , BinaryOperator)
HANDLE_BINARY_INST(15, FSub , BinaryOperator)
HANDLE_BINARY_INST(16, Mul , BinaryOperator)
HANDLE_BINARY_INST(17, FMul , BinaryOperator)
HANDLE_BINARY_INST(18, UDiv , BinaryOperator)
HANDLE_BINARY_INST(19, SDiv , BinaryOperator)
HANDLE_BINARY_INST(20, FDiv , BinaryOperator)
HANDLE_BINARY_INST(21, URem , BinaryOperator)
HANDLE_BINARY_INST(22, SRem , BinaryOperator)
HANDLE_BINARY_INST(23, FRem , BinaryOperator)
FIRST_BINARY_INST(11)
HANDLE_BINARY_INST(11, Add , BinaryOperator)
HANDLE_BINARY_INST(12, FAdd , BinaryOperator)
HANDLE_BINARY_INST(13, Sub , BinaryOperator)
HANDLE_BINARY_INST(14, FSub , BinaryOperator)
HANDLE_BINARY_INST(15, Mul , BinaryOperator)
HANDLE_BINARY_INST(16, FMul , BinaryOperator)
HANDLE_BINARY_INST(17, UDiv , BinaryOperator)
HANDLE_BINARY_INST(18, SDiv , BinaryOperator)
HANDLE_BINARY_INST(19, FDiv , BinaryOperator)
HANDLE_BINARY_INST(20, URem , BinaryOperator)
HANDLE_BINARY_INST(21, SRem , BinaryOperator)
HANDLE_BINARY_INST(22, FRem , BinaryOperator)
// Logical operators (integer operands)
HANDLE_BINARY_INST(24, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(27, And , BinaryOperator)
HANDLE_BINARY_INST(28, Or , BinaryOperator)
HANDLE_BINARY_INST(29, Xor , BinaryOperator)
LAST_BINARY_INST(29)
HANDLE_BINARY_INST(23, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(26, And , BinaryOperator)
HANDLE_BINARY_INST(27, Or , BinaryOperator)
HANDLE_BINARY_INST(28, Xor , BinaryOperator)
LAST_BINARY_INST(28)
// Memory operators...
FIRST_MEMORY_INST(30)
HANDLE_MEMORY_INST(30, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(31, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(32, Store , StoreInst )
HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(34, Fence , FenceInst )
HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(36)
FIRST_MEMORY_INST(29)
HANDLE_MEMORY_INST(29, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(30, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(31, Store , StoreInst )
HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(33, Fence , FenceInst )
HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(35)
// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
FIRST_CAST_INST(37)
HANDLE_CAST_INST(37, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(38, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(39, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(40, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(41, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(42, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(43, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(44, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(45, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(48, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(49)
FIRST_CAST_INST(36)
HANDLE_CAST_INST(36, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(37, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(38, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(39, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(40, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(41, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(42, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(43, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(44, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(47, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(48)
FIRST_FUNCLETPAD_INST(50)
HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(51, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(51)
FIRST_FUNCLETPAD_INST(49)
HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(50, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(50)
// Other operators...
FIRST_OTHER_INST(52)
HANDLE_OTHER_INST(52, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(53, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(54, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(55, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(56, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(57, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(58, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(59, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(60, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(61, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(62, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(64, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(65, LandingPad, LandingPadInst) // Landing pad instruction.
LAST_OTHER_INST(65)
FIRST_OTHER_INST(51)
HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction
HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass
HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction.
LAST_OTHER_INST(64)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST

View File

@ -396,7 +396,6 @@ public:
case Instruction::CatchPad:
case Instruction::CleanupPad:
case Instruction::LandingPad:
case Instruction::TerminatePad:
return true;
default:
return false;

View File

@ -3991,143 +3991,6 @@ struct OperandTraits<CatchSwitchInst> : public HungoffOperandTraits<2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value)
//===----------------------------------------------------------------------===//
// TerminatePadInst Class
//===----------------------------------------------------------------------===//
class TerminatePadInst : public TerminatorInst {
private:
void init(Value *ParentPad, BasicBlock *BB, ArrayRef<Value *> Args);
TerminatePadInst(const TerminatePadInst &TPI);
explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
Instruction *InsertBefore);
explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
TerminatePadInst *cloneImpl() const;
public:
static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB = nullptr,
ArrayRef<Value *> Args = None,
Instruction *InsertBefore = nullptr) {
unsigned Values = unsigned(Args.size()) + 1;
if (BB)
++Values;
return new (Values)
TerminatePadInst(ParentPad, BB, Args, Values, InsertBefore);
}
static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args,
BasicBlock *InsertAtEnd) {
unsigned Values = unsigned(Args.size()) + 1;
if (BB)
++Values;
return new (Values)
TerminatePadInst(ParentPad, BB, Args, Values, InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
bool unwindsToCaller() const { return !hasUnwindDest(); }
/// getNumArgOperands - Return the number of terminatepad arguments.
///
unsigned getNumArgOperands() const {
unsigned NumOperands = getNumOperands();
if (hasUnwindDest())
return NumOperands - 2;
return NumOperands - 1;
}
/// Convenience accessors
Value *getParentPad() const { return Op<-1>(); }
void setParentPad(Value *ParentPad) {
assert(ParentPad);
Op<-1>() = ParentPad;
}
/// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument.
///
Value *getArgOperand(unsigned i) const { return getOperand(i); }
void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
const_op_iterator arg_begin() const { return op_begin(); }
op_iterator arg_begin() { return op_begin(); }
const_op_iterator arg_end() const {
if (hasUnwindDest())
return op_end() - 2;
return op_end() - 1;
}
op_iterator arg_end() {
if (hasUnwindDest())
return op_end() - 2;
return op_end() - 1;
}
/// arg_operands - iteration adapter for range-for loops.
iterator_range<op_iterator> arg_operands() {
return make_range(arg_begin(), arg_end());
}
/// arg_operands - iteration adapter for range-for loops.
iterator_range<const_op_iterator> arg_operands() const {
return make_range(arg_begin(), arg_end());
}
/// \brief Wrappers for getting the \c Use of a terminatepad argument.
const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
// get*Dest - Return the destination basic blocks...
BasicBlock *getUnwindDest() const {
if (!hasUnwindDest())
return nullptr;
return cast<BasicBlock>(Op<-2>());
}
void setUnwindDest(BasicBlock *B) {
assert(B && hasUnwindDest());
Op<-2>() = B;
}
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::TerminatePad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
BasicBlock *getSuccessorV(unsigned idx) const override;
unsigned getNumSuccessorsV() const override;
void setSuccessorV(unsigned idx, BasicBlock *B) override;
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
};
template <>
struct OperandTraits<TerminatePadInst>
: public VariadicOperandTraits<TerminatePadInst, /*MINARITY=*/1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value)
//===----------------------------------------------------------------------===//
// CleanupPadInst Class
//===----------------------------------------------------------------------===//

View File

@ -289,8 +289,8 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, bool Deref, int Offset = 0);
/// Replace 'BB's terminator with one that does not have an unwind successor
/// block. Rewrites `invoke` to `call`, `terminatepad unwind label %foo` to
/// `terminatepad unwind to caller`, etc. Updates any PHIs in unwind successor.
/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
/// successor.
///
/// \param BB Block whose terminator will be replaced. Its terminator must
/// have an unwind successor.

View File

@ -57,9 +57,8 @@ DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
// contain" is used to distinguish from being "transitively contained" in
// a nested funclet).
//
// Note: Despite not being funclets in the truest sense, terminatepad and
// catchswitch are considered to belong to their own funclet for the purposes
// of coloring.
// Note: Despite not being a funclet in the truest sense, a catchswitch is
// considered to belong to its own funclet for the purposes of coloring.
DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
<< F.getName() << "\n");

View File

@ -98,8 +98,6 @@ static BasicBlock::iterator findInsertPointAfter(Instruction *I,
while (IP->isEHPad()) {
if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
++IP;
} else if (auto *TPI = dyn_cast<TerminatePadInst>(IP)) {
IP = TPI->getUnwindDest()->getFirstNonPHI()->getIterator();
} else if (isa<CatchSwitchInst>(IP)) {
IP = MustDominate->getFirstInsertionPt();
} else {

View File

@ -3436,7 +3436,6 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
case Instruction::CatchRet:
case Instruction::CleanupPad:
case Instruction::CleanupRet:
case Instruction::TerminatePad:
return false; // Misc instructions which have effects
}
}

View File

@ -763,7 +763,6 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(catchret, CatchRet);
INSTKEYWORD(catchswitch, CatchSwitch);
INSTKEYWORD(catchpad, CatchPad);
INSTKEYWORD(terminatepad, TerminatePad);
INSTKEYWORD(cleanuppad, CleanupPad);
#undef INSTKEYWORD

View File

@ -4723,7 +4723,6 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_catchret: return ParseCatchRet(Inst, PFS);
case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS);
case lltok::kw_terminatepad:return ParseTerminatePad(Inst, PFS);
case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
@ -5285,43 +5284,6 @@ bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
return false;
}
/// ParseTerminatePad
/// ::= 'terminatepad' within Parent ParamList 'to' TypeAndValue
bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
Value *ParentPad = nullptr;
if (ParseToken(lltok::kw_within, "expected 'within' after terminatepad"))
return true;
if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
Lex.getKind() != lltok::LocalVarID)
return TokError("expected scope value for terminatepad");
if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
return true;
SmallVector<Value *, 8> Args;
if (ParseExceptionArgs(Args, PFS))
return true;
if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
return true;
BasicBlock *UnwindBB = nullptr;
if (Lex.getKind() == lltok::kw_to) {
Lex.Lex();
if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
return true;
} else {
if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
return true;
}
}
Inst = TerminatePadInst::Create(ParentPad, UnwindBB, Args);
return false;
}
/// ParseCleanupPad
/// ::= 'cleanuppad' within Parent ParamList
bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {

View File

@ -465,7 +465,6 @@ namespace llvm {
bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,

View File

@ -185,7 +185,7 @@ namespace lltok {
kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
kw_unreachable, kw_cleanupret, kw_catchswitch, kw_catchret, kw_catchpad,
kw_terminatepad, kw_cleanuppad,
kw_cleanuppad,
kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
kw_getelementptr,

View File

@ -4484,40 +4484,6 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [tok,bb#,num,(ty,val)*]
// We must have, at minimum, the outer scope and the number of arguments.
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
Value *ParentPad =
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
BasicBlock *UnwindDest = nullptr;
if (Idx + 1 == Record.size()) {
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
if (Record.size() != Idx)
return error("Invalid record");
I = TerminatePadInst::Create(ParentPad, UnwindDest, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHPAD:
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // [tok,num,(ty,val)*]
// We must have, at minimum, the outer scope and the number of arguments.

View File

@ -2025,21 +2025,6 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Vals.push_back(VE.getValueID(CatchSwitch.getUnwindDest()));
break;
}
case Instruction::TerminatePad: {
Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
const auto &TPI = cast<TerminatePadInst>(I);
pushValue(TPI.getParentPad(), InstID, Vals, VE);
unsigned NumArgOperands = TPI.getNumArgOperands();
Vals.push_back(NumArgOperands);
for (unsigned Op = 0; Op != NumArgOperands; ++Op)
PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
if (TPI.hasUnwindDest())
Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
break;
}
case Instruction::Unreachable:
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;

View File

@ -1230,8 +1230,8 @@ void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
/// When an invoke or a cleanupret unwinds to the next EH pad, there are
/// many places it could ultimately go. In the IR, we have a single unwind
/// destination, but in the machine CFG, we enumerate all the possible blocks.
/// This function skips over imaginary basic blocks that hold catchswitch or
/// terminatepad instructions, and finds all the "real" machine
/// This function skips over imaginary basic blocks that hold catchswitch
/// instructions, and finds all the "real" machine
/// basic block destinations. As those destinations may not be successors of
/// EHPadBB, here we also calculate the edge probability to those destinations.
/// The passed-in Prob is the edge probability to EHPadBB.
@ -1300,10 +1300,6 @@ void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) {
DAG.setRoot(Ret);
}
void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
report_fatal_error("visitTerminatePad not yet implemented!");
}
void SelectionDAGBuilder::visitCatchSwitch(const CatchSwitchInst &CSI) {
report_fatal_error("visitCatchSwitch not yet implemented!");
}

View File

@ -740,7 +740,6 @@ private:
void visitCatchSwitch(const CatchSwitchInst &I);
void visitCatchRet(const CatchReturnInst &I);
void visitCatchPad(const CatchPadInst &I);
void visitTerminatePad(const TerminatePadInst &TPI);
void visitCleanupPad(const CleanupPadInst &CPI);
BranchProbability getEdgeProbability(const MachineBasicBlock *Src,

View File

@ -1574,7 +1574,6 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
case CatchRet: return 0;
case CatchPad: return 0;
case CatchSwitch: return 0;
case TerminatePad: return 0;
case CleanupPad: return 0;
case Add: return ISD::ADD;
case FAdd: return ISD::FADD;

View File

@ -70,7 +70,6 @@ private:
void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
DenseMap<BasicBlock *, Value *> &Loads, Function &F);
bool prepareExplicitEH(Function &F);
void replaceTerminatePadWithCleanup(Function &F);
void colorFunclets(Function &F);
void demotePHIsOnFunclets(Function &F);
@ -523,45 +522,6 @@ void llvm::calculateClrEHStateNumbers(const Function *Fn,
calculateStateNumbersForInvokes(Fn, FuncInfo);
}
void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) {
if (Personality != EHPersonality::MSVC_CXX)
return;
for (BasicBlock &BB : F) {
Instruction *First = BB.getFirstNonPHI();
auto *TPI = dyn_cast<TerminatePadInst>(First);
if (!TPI)
continue;
if (TPI->getNumArgOperands() != 1)
report_fatal_error(
"Expected a unary terminatepad for MSVC C++ personalities!");
auto *TerminateFn = dyn_cast<Function>(TPI->getArgOperand(0));
if (!TerminateFn)
report_fatal_error("Function operand expected in terminatepad for MSVC "
"C++ personalities!");
// Insert the cleanuppad instruction.
auto *CPI =
CleanupPadInst::Create(TPI->getParentPad(), {},
Twine("terminatepad.for.", BB.getName()), &BB);
// Insert the call to the terminate instruction.
auto *CallTerminate = CallInst::Create(TerminateFn, {}, &BB);
CallTerminate->setDoesNotThrow();
CallTerminate->setDoesNotReturn();
CallTerminate->setCallingConv(TerminateFn->getCallingConv());
// Insert a new terminator for the cleanuppad using the same successor as
// the terminatepad.
CleanupReturnInst::Create(CPI, TPI->getUnwindDest(), &BB);
// Let's remove the terminatepad now that we've inserted the new
// instructions.
TPI->eraseFromParent();
}
}
void WinEHPrepare::colorFunclets(Function &F) {
BlockColors = colorEHFunclets(F);
@ -885,8 +845,6 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
// not.
removeUnreachableBlocks(F);
replaceTerminatePadWithCleanup(F);
// Determine which blocks are reachable from which funclet entries.
colorFunclets(F);

View File

@ -2917,21 +2917,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
}
Out << ']';
} else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
Out << " within ";
writeOperand(TPI->getParentPad(), /*PrintType=*/false);
Out << " [";
for (unsigned Op = 0, NumOps = TPI->getNumArgOperands(); Op < NumOps;
++Op) {
if (Op > 0)
Out << ", ";
writeOperand(TPI->getArgOperand(Op), /*PrintType=*/true);
}
Out << "] unwind ";
if (TPI->hasUnwindDest())
writeOperand(TPI->getUnwindDest(), /*PrintType=*/true);
else
Out << "to caller";
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {

View File

@ -206,7 +206,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case CatchRet: return "catchret";
case CatchPad: return "catchpad";
case CatchSwitch: return "catchswitch";
case TerminatePad: return "terminatepad";
// Standard binary operators...
case Add: return "add";
@ -421,7 +420,6 @@ bool Instruction::mayReadFromMemory() const {
case Instruction::AtomicRMW:
case Instruction::CatchPad:
case Instruction::CatchRet:
case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->doesNotAccessMemory();
@ -444,7 +442,6 @@ bool Instruction::mayWriteToMemory() const {
case Instruction::AtomicRMW:
case Instruction::CatchPad:
case Instruction::CatchRet:
case Instruction::TerminatePad:
return true;
case Instruction::Call:
return !cast<CallInst>(this)->onlyReadsMemory();
@ -477,8 +474,6 @@ bool Instruction::mayThrow() const {
return CRI->unwindsToCaller();
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(this))
return CatchSwitch->unwindsToCaller();
if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
return TPI->unwindsToCaller();
return isa<ResumeInst>(this);
}

View File

@ -980,60 +980,6 @@ FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
init(ParentPad, Args, NameStr);
}
//===----------------------------------------------------------------------===//
// TerminatePadInst Implementation
//===----------------------------------------------------------------------===//
void TerminatePadInst::init(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args) {
if (BB) {
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
setUnwindDest(BB);
}
std::copy(Args.begin(), Args.end(), arg_begin());
setParentPad(ParentPad);
}
TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
: TerminatorInst(TPI.getType(), Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) -
TPI.getNumOperands(),
TPI.getNumOperands()) {
setInstructionSubclassData(TPI.getSubclassDataFromInstruction());
std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
}
TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) - Values,
Values, InsertBefore) {
init(ParentPad, BB, Args);
}
TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
ArrayRef<Value *> Args, unsigned Values,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
Instruction::TerminatePad,
OperandTraits<TerminatePadInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(ParentPad, BB, Args);
}
BasicBlock *TerminatePadInst::getSuccessorV(unsigned Idx) const {
assert(Idx == 0);
return getUnwindDest();
}
unsigned TerminatePadInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
void TerminatePadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
assert(Idx == 0);
return setUnwindDest(B);
}
//===----------------------------------------------------------------------===//
// UnreachableInst Implementation
//===----------------------------------------------------------------------===//
@ -4025,10 +3971,6 @@ FuncletPadInst *FuncletPadInst::cloneImpl() const {
return new (getNumOperands()) FuncletPadInst(*this);
}
TerminatePadInst *TerminatePadInst::cloneImpl() const {
return new (getNumOperands()) TerminatePadInst(*this);
}
UnreachableInst *UnreachableInst::cloneImpl() const {
LLVMContext &Context = getContext();
return new UnreachableInst(Context);

View File

@ -403,7 +403,6 @@ private:
void visitCleanupPadInst(CleanupPadInst &CPI);
void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
void visitCleanupReturnInst(CleanupReturnInst &CRI);
void visitTerminatePadInst(TerminatePadInst &TPI);
void VerifyCallSite(CallSite CS);
void verifyMustTailCall(CallInst &CI);
@ -2899,8 +2898,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) {
if (auto *II = dyn_cast<InvokeInst>(TI)) {
Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,
"EH pad must be jumped to via an unwind edge", &I, II);
} else if (!isa<CleanupReturnInst>(TI) && !isa<TerminatePadInst>(TI) &&
!isa<CatchSwitchInst>(TI)) {
} else if (!isa<CleanupReturnInst>(TI) && !isa<CatchSwitchInst>(TI)) {
Assert(false, "EH pad must be jumped to via an unwind edge", &I, TI);
}
}
@ -3002,8 +3000,7 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
BasicBlock *UnwindDest;
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
UnwindDest = CRI->getUnwindDest();
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U) ||
isa<TerminatePadInst>(U)) {
} else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
continue;
} else {
Assert(false, "bogus cleanuppad use", &CPI);
@ -3072,37 +3069,6 @@ void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
visitTerminatorInst(CRI);
}
void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) {
visitEHPadPredecessors(TPI);
BasicBlock *BB = TPI.getParent();
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"TerminatePadInst needs to be in a function with a personality.",
&TPI);
// The terminatepad instruction must be the first non-PHI instruction in the
// block.
Assert(BB->getFirstNonPHI() == &TPI,
"TerminatePadInst not the first non-PHI instruction in the block.",
&TPI);
if (BasicBlock *UnwindDest = TPI.getUnwindDest()) {
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(I->isEHPad() && !isa<LandingPadInst>(I),
"TerminatePadInst must unwind to an EH block which is not a "
"landingpad.",
&TPI);
}
auto *ParentPad = TPI.getParentPad();
Assert(isa<CatchSwitchInst>(ParentPad) || isa<ConstantTokenNone>(ParentPad) ||
isa<CleanupPadInst>(ParentPad) || isa<CatchPadInst>(ParentPad),
"TerminatePadInst has an invalid parent.", ParentPad);
visitTerminatorInst(TPI);
}
void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
Instruction *Op = cast<Instruction>(I.getOperand(i));
// If the we have an invalid invoke, don't try to compute the dominance.

View File

@ -2695,11 +2695,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOrigin(&I, getCleanOrigin());
}
void visitTerminatePad(TerminatePadInst &I) {
DEBUG(dbgs() << "TerminatePad: " << I << "\n");
// Nothing to do here.
}
void visitGetElementPtrInst(GetElementPtrInst &I) {
handleShadowOr(I);
}

View File

@ -343,15 +343,7 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
continue;
Instruction *Replacement = nullptr;
if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
if (TPI->unwindsToCaller()) {
SmallVector<Value *, 3> TerminatePadArgs;
for (Value *ArgOperand : TPI->arg_operands())
TerminatePadArgs.push_back(ArgOperand);
Replacement = TerminatePadInst::Create(TPI->getParentPad(), UnwindDest,
TerminatePadArgs, TPI);
}
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
if (CatchSwitch->unwindsToCaller()) {
auto *NewCatchSwitch = CatchSwitchInst::Create(
CatchSwitch->getParentPad(), UnwindDest,
@ -1441,10 +1433,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
if (!I->isEHPad())
continue;
if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
if (isa<ConstantTokenNone>(TPI->getParentPad()))
TPI->setParentPad(CallSiteEHPad);
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
CatchSwitch->setParentPad(CallSiteEHPad);
} else {

View File

@ -1338,13 +1338,6 @@ void llvm::removeUnwindEdge(BasicBlock *BB) {
if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI);
UnwindDest = CRI->getUnwindDest();
} else if (auto *TPI = dyn_cast<TerminatePadInst>(TI)) {
SmallVector<Value *, 3> TerminatePadArgs;
for (Value *Operand : TPI->arg_operands())
TerminatePadArgs.push_back(Operand);
NewTI = TerminatePadInst::Create(TPI->getParentPad(), nullptr,
TerminatePadArgs, TPI);
UnwindDest = TPI->getUnwindDest();
} else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
auto *NewCatchSwitch = CatchSwitchInst::Create(
CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(),

View File

@ -3498,7 +3498,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
}
} else if ((isa<InvokeInst>(TI) &&
cast<InvokeInst>(TI)->getUnwindDest() == BB) ||
isa<TerminatePadInst>(TI) || isa<CatchSwitchInst>(TI)) {
isa<CatchSwitchInst>(TI)) {
removeUnwindEdge(TI->getParent());
Changed = true;
} else if (isa<CleanupReturnInst>(TI)) {

View File

@ -774,7 +774,7 @@ entry:
invoke void @f.ccc() to label %normal unwind label %catchswitch3
catchswitch1:
%cs1 = catchswitch within none [label %catchpad1] unwind label %terminate.1
%cs1 = catchswitch within none [label %catchpad1] unwind to caller
catchpad1:
catchpad within %cs1 []
@ -802,20 +802,9 @@ catchpad3:
cleanuppad1:
%clean.1 = cleanuppad within none []
unreachable
; CHECK: %clean.1 = cleanuppad within none []
invoke void @f.ccc() to label %normal unwind label %terminate.2
terminate.1:
terminatepad within none [] unwind to caller
; CHECK: terminatepad within none [] unwind to caller
terminate.2:
terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
; CHECK: terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
normal.pre:
terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
; CHECK: terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
; CHECK-NEXT: unreachable
normal:
ret i32 0
@ -852,8 +841,10 @@ return:
ret i32 0
terminate:
terminatepad within %cs [] unwind to caller
; CHECK: terminatepad within %cs [] unwind to caller
cleanuppad within %cs []
unreachable
; CHECK: cleanuppad within %cs []
; CHECK-NEXT: unreachable
continue:
ret i32 0

View File

@ -93,22 +93,6 @@ exit:
unreachable
}
; CHECK-LABEL: @test3(
define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @f()
to label %invoke.cont unwind label %terminate
invoke.cont:
ret void
terminate:
; CHECK: cleanuppad within none []
; CHECK: call void @__std_terminate()
; CHECK: unreachable
terminatepad within none [void ()* @__std_terminate] unwind to caller
}
; CHECK-LABEL: @test4(
define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
entry:

View File

@ -123,28 +123,6 @@ exit:
ret i8 0
}
define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %try.cont
try.cont:
invoke void @_Z3quxv() optsize
to label %try.cont unwind label %bb
bb:
terminatepad within none [i7 4] unwind label %bb
}
define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %try.cont
try.cont:
invoke void @_Z3quxv() optsize
to label %try.cont unwind label %bb
bb:
terminatepad within none [i7 4] unwind to caller
}
define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
entry:
br label %try.cont

View File

@ -1,53 +0,0 @@
; RUN: opt < %s -inline -S | FileCheck %s
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc18.0.0"
define void @f() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @g()
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
%cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
%0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
invoke void @dtor()
to label %invoke.cont.1 unwind label %ehcleanup
invoke.cont.1: ; preds = %catch
catchret from %0 to label %try.cont
try.cont: ; preds = %entry, %invoke.cont.1
ret void
ehcleanup:
%cp2 = cleanuppad within none []
call void @g()
cleanupret from %cp2 unwind to caller
}
; CHECK-LABEL: define void @f(
; CHECK: invoke void @g()
; CHECK: to label %dtor.exit unwind label %terminate.i
; CHECK: terminate.i:
; CHECK-NEXT: terminatepad within %0 [void ()* @terminate] unwind label %ehcleanup
declare i32 @__CxxFrameHandler3(...)
define internal void @dtor() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @g()
to label %invoke.cont unwind label %terminate
invoke.cont: ; preds = %entry
ret void
terminate: ; preds = %entry
terminatepad within none [void ()* @terminate] unwind to caller
}
declare void @g()
declare void @terminate()

View File

@ -20,9 +20,6 @@ throw: ; preds = %throw, %entry
pad: ; preds = %throw
%phi2 = phi i8* [ %tmp96, %throw ]
terminatepad within none [] unwind label %blah
blah:
%cs = catchswitch within none [label %unreachable] unwind label %blah2
unreachable:

View File

@ -63,14 +63,6 @@ lpad:
resume { i8*, i32 } zeroinitializer
}
define i8 @call_with_same_range() {
; CHECK-LABEL: @call_with_same_range
; CHECK: tail call i8 @call_with_range
bitcast i8 0 to i8
%out = call i8 @dummy(), !range !0
ret i8 %out
}
define i8 @invoke_with_same_range() personality i8* undef {
; CHECK-LABEL: @invoke_with_same_range()
; CHECK: tail call i8 @invoke_with_range()
@ -84,6 +76,14 @@ lpad:
resume { i8*, i32 } zeroinitializer
}
define i8 @call_with_same_range() {
; CHECK-LABEL: @call_with_same_range
; CHECK: tail call i8 @call_with_range
bitcast i8 0 to i8
%out = call i8 @dummy(), !range !0
ret i8 %out
}
declare i8 @dummy();

View File

@ -219,61 +219,6 @@ ehcleanup:
cleanupret from %cp2 unwind to caller
}
; This tests the case where a terminatepad unwinds to a cleanuppad.
; I'm not sure how this case would arise, but it seems to be syntactically
; legal so I'm testing it.
;
; CHECK-LABEL: define void @f5()
; CHECK: entry:
; CHECK: invoke void @g()
; CHECK: to label %try.cont unwind label %terminate
; CHECK: terminate:
; CHECK: terminatepad within none [i7 4] unwind to caller
; CHECK-NOT: cleanuppad
; CHECK: try.cont:
; CHECK: invoke void @g()
; CHECK: to label %try.cont.1 unwind label %terminate.1
; CHECK: terminate.1:
; CHECK: terminatepad within none [i7 4] unwind label %ehcleanup.2
; CHECK-NOT: ehcleanup.1:
; CHECK: ehcleanup.2:
; CHECK: [[TMP:\%.+]] = cleanuppad
; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
; CHECK: cleanupret from [[TMP]] unwind to caller
; CHECK: }
define void @f5() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
%a = alloca %struct.S2, align 1
invoke void @g()
to label %try.cont unwind label %terminate
terminate: ; preds = %entry
terminatepad within none [i7 4] unwind label %ehcleanup
ehcleanup: ; preds = %terminate
%0 = cleanuppad within none []
cleanupret from %0 unwind to caller
try.cont: ; preds = %entry
invoke void @g()
to label %try.cont.1 unwind label %terminate.1
terminate.1: ; preds = %try.cont
terminatepad within none [i7 4] unwind label %ehcleanup.1
ehcleanup.1: ; preds = %terminate.1
%1 = cleanuppad within none []
cleanupret from %1 unwind label %ehcleanup.2
ehcleanup.2: ; preds = %ehcleanup.1
%2 = cleanuppad within none []
call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a)
cleanupret from %2 unwind to caller
try.cont.1: ; preds = %try.cont
ret void
}
; This case tests simplification of an otherwise empty cleanup pad that contains
; a PHI node.
;

View File

@ -65,21 +65,6 @@ unreachable.unwind:
unreachable
}
; CHECK-LABEL: define void @test4()
define void @test4() personality i8* bitcast (void ()* @Personality to i8*) {
entry:
invoke void @f()
to label %exit unwind label %terminate.pad
terminate.pad:
; CHECK: terminatepad within none [] unwind to caller
terminatepad within none [] unwind label %unreachable.unwind
exit:
ret void
unreachable.unwind:
cleanuppad within none []
unreachable
}
; CHECK-LABEL: define void @test5()
define void @test5() personality i8* bitcast (void ()* @Personality to i8*) {
entry:

View File

@ -259,7 +259,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
STRINGIFY_CODE(FUNC_CODE, INST_TERMINATEPAD)
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)