[GlobalISel] Introduce G_TRAP, G_DEBUGTRAP, G_UBSANTRAP (#84941)
Here we introduce three new GMIR instructions to cover a set of trap intrinsics. The idea behind it is that generic intrinsics shouldn't be used with G_INTRINSIC opcode. These new instructions can match perfectly with existing trap ISD nodes. It allows X86, AArch64, RISCV and Mips to reuse SelectionDAG patterns for selection and avoid manual selection. However AMDGPU is an exception. It selects traps during legalization regardless SelectionDAG or GlobalISel. Since there are not many places where traps are used, this change attempts to clean up all the usages of G_INTRINSIC with trap intrinsics. So, there is no stage when both G_TRAP and G_INTRINSIC_W_SIDE_EFFECTS(@llvm.trap) are allowed.
This commit is contained in:
parent
d7c672834e
commit
d365a45cb3
@ -939,6 +939,25 @@ The _CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`.
|
||||
Unlike SelectionDAG, there is no _VOID variant. Both of these are permitted
|
||||
to have zero, one, or multiple results.
|
||||
|
||||
G_TRAP, G_DEBUGTRAP, G_UBSANTRAP
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Represents :ref:`llvm.trap <llvm.trap>`, :ref:`llvm.debugtrap <llvm.debugtrap>`
|
||||
and :ref:`llvm.ubsantrap <llvm.ubsantrap>` that generate a target dependent
|
||||
trap instructions.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
G_TRAP
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
G_DEBUGTRAP
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
G_UBSANTRAP 12
|
||||
|
||||
Variadic Arguments
|
||||
------------------
|
||||
|
||||
|
@ -26926,6 +26926,8 @@ Arguments:
|
||||
|
||||
The argument should be an MDTuple containing any number of MDStrings.
|
||||
|
||||
.. _llvm.trap:
|
||||
|
||||
'``llvm.trap``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -26953,6 +26955,8 @@ This intrinsic is lowered to the target dependent trap instruction. If
|
||||
the target does not have a trap instruction, this intrinsic will be
|
||||
lowered to a call of the ``abort()`` function.
|
||||
|
||||
.. _llvm.debugtrap:
|
||||
|
||||
'``llvm.debugtrap``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -26980,6 +26984,8 @@ This intrinsic is lowered to code which is intended to cause an
|
||||
execution trap with the intention of requesting the attention of a
|
||||
debugger.
|
||||
|
||||
.. _llvm.ubsantrap:
|
||||
|
||||
'``llvm.ubsantrap``' Intrinsic
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -243,6 +243,10 @@ private:
|
||||
bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
|
||||
unsigned Opcode);
|
||||
|
||||
/// Translate an LLVM trap intrinsic (trap, debugtrap, ubsantrap).
|
||||
bool translateTrap(const CallInst &U, MachineIRBuilder &MIRBuilder,
|
||||
unsigned Opcode);
|
||||
|
||||
// Translate @llvm.experimental.vector.interleave2 and
|
||||
// @llvm.experimental.vector.deinterleave2 intrinsics for fixed-width vector
|
||||
// types into vector shuffles.
|
||||
|
@ -2113,6 +2113,11 @@ public:
|
||||
DstMMO, SrcMMO);
|
||||
}
|
||||
|
||||
/// Build and insert G_TRAP or G_DEBUGTRAP
|
||||
MachineInstrBuilder buildTrap(bool Debug = false) {
|
||||
return buildInstr(Debug ? TargetOpcode::G_DEBUGTRAP : TargetOpcode::G_TRAP);
|
||||
}
|
||||
|
||||
/// Build and insert \p Dst = G_SBFX \p Src, \p LSB, \p Width.
|
||||
MachineInstrBuilder buildSbfx(const DstOp &Dst, const SrcOp &Src,
|
||||
const SrcOp &LSB, const SrcOp &Width) {
|
||||
|
@ -837,6 +837,11 @@ HANDLE_TARGET_OPCODE(G_MEMMOVE)
|
||||
HANDLE_TARGET_OPCODE(G_MEMSET)
|
||||
HANDLE_TARGET_OPCODE(G_BZERO)
|
||||
|
||||
/// llvm.trap, llvm.debugtrap and llvm.ubsantrap intrinsics
|
||||
HANDLE_TARGET_OPCODE(G_TRAP)
|
||||
HANDLE_TARGET_OPCODE(G_DEBUGTRAP)
|
||||
HANDLE_TARGET_OPCODE(G_UBSANTRAP)
|
||||
|
||||
/// Vector reductions
|
||||
HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FADD)
|
||||
HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FMUL)
|
||||
|
@ -1575,6 +1575,28 @@ def G_BZERO : GenericInstruction {
|
||||
let mayStore = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Trap intrinsics
|
||||
//------------------------------------------------------------------------------
|
||||
def G_TRAP : GenericInstruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins);
|
||||
let hasSideEffects = true;
|
||||
let mayStore = true;
|
||||
}
|
||||
|
||||
def G_DEBUGTRAP : GenericInstruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins);
|
||||
let hasSideEffects = true;
|
||||
}
|
||||
|
||||
def G_UBSANTRAP : GenericInstruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins i8imm:$kind);
|
||||
let hasSideEffects = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bitfield extraction.
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -250,6 +250,9 @@ def : GINodeEquiv<G_ATOMICRMW_UINC_WRAP, atomic_load_uinc_wrap>;
|
||||
def : GINodeEquiv<G_ATOMICRMW_UDEC_WRAP, atomic_load_udec_wrap>;
|
||||
def : GINodeEquiv<G_FENCE, atomic_fence>;
|
||||
def : GINodeEquiv<G_PREFETCH, prefetch>;
|
||||
def : GINodeEquiv<G_TRAP, trap>;
|
||||
def : GINodeEquiv<G_DEBUGTRAP, debugtrap>;
|
||||
def : GINodeEquiv<G_UBSANTRAP, ubsantrap>;
|
||||
|
||||
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
|
||||
// Should be used on defs that subclass GIComplexOperandMatcher<>.
|
||||
|
@ -1771,6 +1771,32 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IRTranslator::translateTrap(const CallInst &CI,
|
||||
MachineIRBuilder &MIRBuilder,
|
||||
unsigned Opcode) {
|
||||
StringRef TrapFuncName =
|
||||
CI.getAttributes().getFnAttr("trap-func-name").getValueAsString();
|
||||
if (TrapFuncName.empty()) {
|
||||
if (Opcode == TargetOpcode::G_UBSANTRAP) {
|
||||
uint64_t Code = cast<ConstantInt>(CI.getOperand(0))->getZExtValue();
|
||||
MIRBuilder.buildInstr(Opcode, {}, ArrayRef<llvm::SrcOp>{Code});
|
||||
} else {
|
||||
MIRBuilder.buildInstr(Opcode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CallLowering::CallLoweringInfo Info;
|
||||
if (Opcode == TargetOpcode::G_UBSANTRAP)
|
||||
Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)),
|
||||
CI.getArgOperand(0)->getType(), 0});
|
||||
|
||||
Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
|
||||
Info.CB = &CI;
|
||||
Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
|
||||
return CLI->lowerCall(MIRBuilder, Info);
|
||||
}
|
||||
|
||||
bool IRTranslator::translateVectorInterleave2Intrinsic(
|
||||
const CallInst &CI, MachineIRBuilder &MIRBuilder) {
|
||||
assert(CI.getIntrinsicID() == Intrinsic::experimental_vector_interleave2 &&
|
||||
@ -2459,22 +2485,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::trap:
|
||||
return translateTrap(CI, MIRBuilder, TargetOpcode::G_TRAP);
|
||||
case Intrinsic::debugtrap:
|
||||
case Intrinsic::ubsantrap: {
|
||||
StringRef TrapFuncName =
|
||||
CI.getAttributes().getFnAttr("trap-func-name").getValueAsString();
|
||||
if (TrapFuncName.empty())
|
||||
break; // Use the default handling.
|
||||
CallLowering::CallLoweringInfo Info;
|
||||
if (ID == Intrinsic::ubsantrap) {
|
||||
Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)),
|
||||
CI.getArgOperand(0)->getType(), 0});
|
||||
}
|
||||
Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
|
||||
Info.CB = &CI;
|
||||
Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
|
||||
return CLI->lowerCall(MIRBuilder, Info);
|
||||
}
|
||||
return translateTrap(CI, MIRBuilder, TargetOpcode::G_DEBUGTRAP);
|
||||
case Intrinsic::ubsantrap:
|
||||
return translateTrap(CI, MIRBuilder, TargetOpcode::G_UBSANTRAP);
|
||||
case Intrinsic::amdgcn_cs_chain:
|
||||
return translateCallBase(CI, MIRBuilder);
|
||||
case Intrinsic::fptrunc_round: {
|
||||
@ -3047,7 +3062,7 @@ bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuil
|
||||
}
|
||||
}
|
||||
|
||||
MIRBuilder.buildIntrinsic(Intrinsic::trap, ArrayRef<Register>());
|
||||
MIRBuilder.buildTrap();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1867,6 +1867,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
|
||||
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_UBSANTRAP: {
|
||||
const MachineOperand &KindOp = MI->getOperand(0);
|
||||
if (!MI->getOperand(0).isImm()) {
|
||||
report("Crash kind must be an immediate", &KindOp, 0);
|
||||
break;
|
||||
}
|
||||
int64_t Kind = MI->getOperand(0).getImm();
|
||||
if (!isInt<8>(Kind))
|
||||
report("Crash kind must be 8 bit wide", &KindOp, 0);
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_VECREDUCE_SEQ_FADD:
|
||||
case TargetOpcode::G_VECREDUCE_SEQ_FMUL: {
|
||||
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
|
||||
|
@ -8436,6 +8436,9 @@ def ubsan_trap_xform : SDNodeXForm<timm, [{
|
||||
return CurDAG->getTargetConstant(N->getZExtValue() | ('U' << 8), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def gi_ubsan_trap_xform : GICustomOperandRenderer<"renderUbsanTrap">,
|
||||
GISDNodeXFormEquiv<ubsan_trap_xform>;
|
||||
|
||||
def ubsan_trap_imm : TImmLeaf<i32, [{
|
||||
return isUInt<8>(Imm);
|
||||
}], ubsan_trap_xform>;
|
||||
|
@ -479,6 +479,8 @@ private:
|
||||
int OpIdx = -1) const;
|
||||
void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I,
|
||||
int OpIdx = -1) const;
|
||||
void renderUbsanTrap(MachineInstrBuilder &MIB, const MachineInstr &MI,
|
||||
int OpIdx) const;
|
||||
void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI,
|
||||
int OpIdx = -1) const;
|
||||
void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI,
|
||||
@ -6159,16 +6161,6 @@ bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
|
||||
constrainSelectedInstRegOperands(*NewI, TII, TRI, RBI);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::trap:
|
||||
MIB.buildInstr(AArch64::BRK, {}, {}).addImm(1);
|
||||
break;
|
||||
case Intrinsic::debugtrap:
|
||||
MIB.buildInstr(AArch64::BRK, {}, {}).addImm(0xF000);
|
||||
break;
|
||||
case Intrinsic::ubsantrap:
|
||||
MIB.buildInstr(AArch64::BRK, {}, {})
|
||||
.addImm(I.getOperand(1).getImm() | ('U' << 8));
|
||||
break;
|
||||
case Intrinsic::aarch64_neon_ld1x2: {
|
||||
LLT Ty = MRI.getType(I.getOperand(0).getReg());
|
||||
unsigned Opc = 0;
|
||||
@ -7663,6 +7655,14 @@ void AArch64InstructionSelector::renderLogicalImm64(
|
||||
MIB.addImm(Enc);
|
||||
}
|
||||
|
||||
void AArch64InstructionSelector::renderUbsanTrap(MachineInstrBuilder &MIB,
|
||||
const MachineInstr &MI,
|
||||
int OpIdx) const {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_UBSANTRAP && OpIdx == 0 &&
|
||||
"Expected G_UBSANTRAP");
|
||||
MIB.addImm(MI.getOperand(0).getImm() | ('U' << 8));
|
||||
}
|
||||
|
||||
void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB,
|
||||
const MachineInstr &MI,
|
||||
int OpIdx) const {
|
||||
|
@ -2030,6 +2030,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
|
||||
getActionDefinitionsBuilder({G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET})
|
||||
.lower();
|
||||
|
||||
getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
|
||||
|
||||
getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE,
|
||||
G_INDEXED_LOAD, G_INDEXED_SEXTLOAD,
|
||||
G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
|
||||
@ -2134,6 +2136,10 @@ bool AMDGPULegalizerInfo::legalizeCustom(
|
||||
return legalizeGetFPEnv(MI, MRI, B);
|
||||
case TargetOpcode::G_SET_FPENV:
|
||||
return legalizeSetFPEnv(MI, MRI, B);
|
||||
case TargetOpcode::G_TRAP:
|
||||
return legalizeTrap(MI, MRI, B);
|
||||
case TargetOpcode::G_DEBUGTRAP:
|
||||
return legalizeDebugTrap(MI, MRI, B);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -2925,7 +2931,7 @@ bool AMDGPULegalizerInfo::legalizeGlobalValue(
|
||||
// functions that use local objects. However, if these dead functions are
|
||||
// not eliminated, we don't want a compile time error. Just emit a warning
|
||||
// and a trap, since there should be no callable path here.
|
||||
B.buildIntrinsic(Intrinsic::trap, ArrayRef<Register>());
|
||||
B.buildTrap();
|
||||
B.buildUndef(DstReg);
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
@ -6618,9 +6624,9 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper,
|
||||
}
|
||||
|
||||
// TODO: Move to selection
|
||||
bool AMDGPULegalizerInfo::legalizeTrapIntrinsic(MachineInstr &MI,
|
||||
MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const {
|
||||
bool AMDGPULegalizerInfo::legalizeTrap(MachineInstr &MI,
|
||||
MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const {
|
||||
if (!ST.isTrapHandlerEnabled() ||
|
||||
ST.getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA)
|
||||
return legalizeTrapEndpgm(MI, MRI, B);
|
||||
@ -6726,8 +6732,9 @@ bool AMDGPULegalizerInfo::legalizeTrapHsa(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AMDGPULegalizerInfo::legalizeDebugTrapIntrinsic(
|
||||
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const {
|
||||
bool AMDGPULegalizerInfo::legalizeDebugTrap(MachineInstr &MI,
|
||||
MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const {
|
||||
// Is non-HSA path or trap-handler disabled? Then, report a warning
|
||||
// accordingly
|
||||
if (!ST.isTrapHandlerEnabled() ||
|
||||
@ -7270,10 +7277,6 @@ bool AMDGPULegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
|
||||
case Intrinsic::amdgcn_struct_buffer_atomic_fadd_v2bf16:
|
||||
case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd_v2bf16:
|
||||
return legalizeBufferAtomic(MI, B, IntrID);
|
||||
case Intrinsic::trap:
|
||||
return legalizeTrapIntrinsic(MI, MRI, B);
|
||||
case Intrinsic::debugtrap:
|
||||
return legalizeDebugTrapIntrinsic(MI, MRI, B);
|
||||
case Intrinsic::amdgcn_rsq_clamp:
|
||||
return legalizeRsqClampIntrinsic(MI, MRI, B);
|
||||
case Intrinsic::amdgcn_ds_fadd:
|
||||
|
@ -226,16 +226,16 @@ public:
|
||||
|
||||
bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const;
|
||||
|
||||
bool legalizeTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeDebugTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &B) const;
|
||||
|
||||
bool legalizeIntrinsic(LegalizerHelper &Helper,
|
||||
MachineInstr &MI) const override;
|
||||
|
@ -508,16 +508,8 @@ bool MipsLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
|
||||
MachineInstr &MI) const {
|
||||
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
|
||||
const MipsSubtarget &ST = MI.getMF()->getSubtarget<MipsSubtarget>();
|
||||
const MipsInstrInfo &TII = *ST.getInstrInfo();
|
||||
const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
|
||||
const RegisterBankInfo &RBI = *ST.getRegBankInfo();
|
||||
|
||||
switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
|
||||
case Intrinsic::trap: {
|
||||
MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
|
||||
MI.eraseFromParent();
|
||||
return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
|
||||
}
|
||||
case Intrinsic::vacopy: {
|
||||
MachinePointerInfo MPO;
|
||||
LLT PtrTy = LLT::pointer(0, 32);
|
||||
|
@ -77,8 +77,6 @@ private:
|
||||
MachineRegisterInfo &MRI) const;
|
||||
bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB,
|
||||
MachineRegisterInfo &MRI) const;
|
||||
bool selectIntrinsicWithSideEffects(MachineInstr &MI, MachineIRBuilder &MIB,
|
||||
MachineRegisterInfo &MRI) const;
|
||||
void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
|
||||
MachineIRBuilder &MIB) const;
|
||||
bool selectMergeValues(MachineInstr &MI, MachineIRBuilder &MIB,
|
||||
@ -686,8 +684,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
|
||||
return selectSelect(MI, MIB, MRI);
|
||||
case TargetOpcode::G_FCMP:
|
||||
return selectFPCompare(MI, MIB, MRI);
|
||||
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
|
||||
return selectIntrinsicWithSideEffects(MI, MIB, MRI);
|
||||
case TargetOpcode::G_FENCE: {
|
||||
AtomicOrdering FenceOrdering =
|
||||
static_cast<AtomicOrdering>(MI.getOperand(0).getImm());
|
||||
@ -1255,29 +1251,6 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
|
||||
MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
|
||||
"Unexpected opcode");
|
||||
// Find the intrinsic ID.
|
||||
unsigned IntrinID = cast<GIntrinsic>(MI).getIntrinsicID();
|
||||
|
||||
// Select the instruction.
|
||||
switch (IntrinID) {
|
||||
default:
|
||||
return false;
|
||||
case Intrinsic::trap:
|
||||
MIB.buildInstr(RISCV::UNIMP, {}, {});
|
||||
break;
|
||||
case Intrinsic::debugtrap:
|
||||
MIB.buildInstr(RISCV::EBREAK, {}, {});
|
||||
break;
|
||||
}
|
||||
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering,
|
||||
SyncScope::ID FenceSSID,
|
||||
MachineIRBuilder &MIB) const {
|
||||
|
@ -119,8 +119,6 @@ private:
|
||||
MachineFunction &MF) const;
|
||||
bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
bool selectIntrinsicWSideEffects(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
|
||||
// emit insert subreg instruction and insert it before MachineInstr &I
|
||||
bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
|
||||
@ -434,8 +432,6 @@ bool X86InstructionSelector::select(MachineInstr &I) {
|
||||
return selectMulDivRem(I, MRI, MF);
|
||||
case TargetOpcode::G_SELECT:
|
||||
return selectSelect(I, MRI, MF);
|
||||
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
|
||||
return selectIntrinsicWSideEffects(I, MRI, MF);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1834,21 +1830,6 @@ bool X86InstructionSelector::selectSelect(MachineInstr &I,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool X86InstructionSelector::selectIntrinsicWSideEffects(
|
||||
MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const {
|
||||
|
||||
assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
|
||||
"unexpected instruction");
|
||||
|
||||
if (I.getOperand(0).getIntrinsicID() != Intrinsic::trap)
|
||||
return false;
|
||||
|
||||
BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TRAP));
|
||||
|
||||
I.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
InstructionSelector *
|
||||
llvm::createX86InstructionSelector(const X86TargetMachine &TM,
|
||||
X86Subtarget &Subtarget,
|
||||
|
@ -6,7 +6,7 @@ declare void @llvm.trap()
|
||||
define void @unreachable() {
|
||||
; CHECK-LABEL: name: unreachable
|
||||
; CHECK: bb.1 (%ir-block.0):
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
unreachable
|
||||
ret void
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ define void @bar() personality ptr @__gxx_personality_v0 {
|
||||
; CHECK-NEXT: $x0 = COPY [[LOAD]](p0)
|
||||
; CHECK-NEXT: BL @_Unwind_Resume, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
|
||||
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
%exn.slot = alloca ptr
|
||||
%ehselector.slot = alloca i32
|
||||
%1 = invoke i32 @foo(i32 42) to label %continue unwind label %cleanup
|
||||
|
@ -752,6 +752,15 @@
|
||||
# DEBUG-NEXT: G_BZERO (opcode {{[0-9]+}}): 2 type indices, 1 imm index
|
||||
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
|
||||
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
|
||||
# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
|
||||
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: G_DEBUGTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
|
||||
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: G_UBSANTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
|
||||
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
|
||||
# DEBUG-NEXT: G_VECREDUCE_SEQ_FADD (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
|
||||
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
|
||||
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
|
||||
|
@ -26,7 +26,7 @@ body: |
|
||||
; CHECK-LABEL: name: foo
|
||||
; CHECK: BRK 1
|
||||
; CHECK: RET_ReallyLR
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
RET_ReallyLR
|
||||
|
||||
...
|
||||
|
@ -26,7 +26,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
|
||||
@ -48,7 +48,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%8:_(s32) = G_ZEXT %6(s8)
|
||||
@ -80,7 +80,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
|
||||
@ -102,7 +102,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%8:_(s32) = G_ZEXT %6(s16)
|
||||
@ -134,7 +134,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: liveins: $x2
|
||||
@ -165,7 +165,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
liveins: $x2
|
||||
@ -206,7 +206,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
|
||||
@ -228,7 +228,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%8:_(s32) = G_ANYEXT %6(s16)
|
||||
@ -261,7 +261,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
|
||||
@ -284,7 +284,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%8:_(s32) = G_ZEXT %6(s16)
|
||||
@ -317,7 +317,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
|
||||
@ -340,7 +340,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%8:_(s32) = G_ZEXT %6(s16)
|
||||
@ -377,7 +377,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: liveins: $x2
|
||||
@ -410,7 +410,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
liveins: $x2
|
||||
@ -512,7 +512,7 @@ body: |
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.3:
|
||||
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s16)
|
||||
@ -544,7 +544,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%9:_(s32) = G_ZEXT %6(s16)
|
||||
@ -577,7 +577,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
|
||||
@ -601,7 +601,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%9:_(s32) = G_ZEXT %7(s8)
|
||||
@ -634,7 +634,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
|
||||
@ -658,7 +658,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%9:_(s32) = G_ZEXT %7(s8)
|
||||
@ -692,7 +692,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8)
|
||||
@ -717,7 +717,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%10:_(s32) = G_ZEXT %8(s8)
|
||||
@ -783,7 +783,7 @@ body: |
|
||||
; CHECK-NEXT: bb.1:
|
||||
; CHECK-NEXT: successors:
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDO]](s16)
|
||||
@ -804,7 +804,7 @@ body: |
|
||||
bb.2:
|
||||
successors:
|
||||
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.3:
|
||||
%6:_(s32) = G_ANYEXT %4(s16)
|
||||
@ -839,7 +839,7 @@ body: |
|
||||
; CHECK-NEXT: RET_ReallyLR implicit $w0
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: bb.2:
|
||||
; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; CHECK-NEXT: G_TRAP
|
||||
bb.1:
|
||||
successors: %bb.2(0x7ffff800), %bb.3(0x00000800)
|
||||
liveins: $w0, $w1
|
||||
@ -860,6 +860,6 @@ body: |
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
bb.3:
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
...
|
||||
|
@ -24,7 +24,7 @@ body: |
|
||||
bb.0:
|
||||
%0:_(s8) = G_CONSTANT i8 0
|
||||
%1:_(p1) = G_CONSTANT i64 0
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
bb.1:
|
||||
G_STORE %0, %1 :: (store 1, addrspace 1)
|
||||
@ -55,7 +55,7 @@ body: |
|
||||
; GCN-NEXT: S_ENDPGM 0
|
||||
bb.0:
|
||||
%0:_(s8) = G_CONSTANT i8 0
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
%1:_(p1) = G_CONSTANT i64 0
|
||||
|
||||
bb.1:
|
||||
|
@ -1,5 +1,5 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
declare void @llvm.trap()
|
||||
@ -9,12 +9,15 @@
|
||||
---
|
||||
name: f
|
||||
alignment: 4
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
; MIPS32-LABEL: name: f
|
||||
; MIPS32: TRAP
|
||||
; MIPS32: RetRA
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
; MIPS32-NEXT: RetRA
|
||||
G_TRAP
|
||||
RetRA
|
||||
|
||||
...
|
@ -14,7 +14,7 @@ body: |
|
||||
; CHECK-LABEL: name: test_trap
|
||||
; CHECK: UNIMP
|
||||
; CHECK-NEXT: PseudoRET
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
PseudoRET
|
||||
|
||||
...
|
||||
@ -28,7 +28,7 @@ body: |
|
||||
; CHECK-LABEL: name: test_debugtrap
|
||||
; CHECK: EBREAK
|
||||
; CHECK-NEXT: PseudoRET
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.debugtrap)
|
||||
G_DEBUGTRAP
|
||||
PseudoRET
|
||||
|
||||
...
|
||||
|
@ -23,6 +23,6 @@ body: |
|
||||
bb.1 (%ir-block.0):
|
||||
; CHECK-LABEL: name: trap
|
||||
; CHECK: TRAP
|
||||
G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap)
|
||||
G_TRAP
|
||||
|
||||
...
|
||||
|
73
llvm/test/CodeGen/X86/isel-traps.ll
Normal file
73
llvm/test/CodeGen/X86/isel-traps.ll
Normal file
@ -0,0 +1,73 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64
|
||||
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64
|
||||
; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X64
|
||||
; RUN: llc < %s -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86
|
||||
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86
|
||||
; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X86
|
||||
|
||||
declare void @llvm.trap()
|
||||
|
||||
define void @test_trap() {
|
||||
; ALL-LABEL: test_trap:
|
||||
; ALL: # %bb.0:
|
||||
; ALL-NEXT: ud2
|
||||
; ALL-NEXT: ret{{[l|q]}}
|
||||
tail call void @llvm.trap()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_debugtrap() {
|
||||
; ALL-LABEL: test_debugtrap:
|
||||
; ALL: # %bb.0:
|
||||
; ALL-NEXT: int3
|
||||
; ALL-NEXT: ret{{[l|q]}}
|
||||
tail call void @llvm.debugtrap()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_ubsantrap() {
|
||||
; ALL-LABEL: test_ubsantrap:
|
||||
; ALL: # %bb.0:
|
||||
; ALL-NEXT: ud1l 12(%eax), %eax
|
||||
; ALL-NEXT: ret{{[l|q]}}
|
||||
call void @llvm.ubsantrap(i8 12)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_ubsantrap_custom() nounwind {
|
||||
; X64-LABEL: test_ubsantrap_custom:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: pushq %rax
|
||||
; X64-NEXT: movl $42, %edi
|
||||
; X64-NEXT: callq guide@PLT
|
||||
; X64-NEXT: popq %rax
|
||||
; X64-NEXT: retq
|
||||
;
|
||||
; GISEL-X64-LABEL: test_ubsantrap_custom:
|
||||
; GISEL-X64: # %bb.0:
|
||||
; GISEL-X64-NEXT: pushq %rax
|
||||
; GISEL-X64-NEXT: movl $42, %edi
|
||||
; GISEL-X64-NEXT: callq guide
|
||||
; GISEL-X64-NEXT: popq %rax
|
||||
; GISEL-X64-NEXT: retq
|
||||
;
|
||||
; X86-LABEL: test_ubsantrap_custom:
|
||||
; X86: # %bb.0:
|
||||
; X86-NEXT: subl $12, %esp
|
||||
; X86-NEXT: movl $42, (%esp)
|
||||
; X86-NEXT: calll guide
|
||||
; X86-NEXT: addl $12, %esp
|
||||
; X86-NEXT: retl
|
||||
;
|
||||
; GISEL-X86-LABEL: test_ubsantrap_custom:
|
||||
; GISEL-X86: # %bb.0:
|
||||
; GISEL-X86-NEXT: subl $12, %esp
|
||||
; GISEL-X86-NEXT: movl $42, %eax
|
||||
; GISEL-X86-NEXT: movl %eax, (%esp)
|
||||
; GISEL-X86-NEXT: calll guide
|
||||
; GISEL-X86-NEXT: addl $12, %esp
|
||||
; GISEL-X86-NEXT: retl
|
||||
call void @llvm.ubsantrap(i8 42) "trap-func-name"="guide"
|
||||
ret void
|
||||
}
|
18
llvm/test/MachineVerifier/test_g_ubsantrap.mir
Normal file
18
llvm/test/MachineVerifier/test_g_ubsantrap.mir
Normal file
@ -0,0 +1,18 @@
|
||||
# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
|
||||
# REQUIRES: aarch64-registered-target
|
||||
|
||||
---
|
||||
name: test_ubsantrap
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
body: |
|
||||
bb.0:
|
||||
|
||||
; CHECK: Crash kind must be 8 bit wide
|
||||
G_UBSANTRAP 4096
|
||||
|
||||
; CHECK: Crash kind must be an immediate
|
||||
%5:_(s32) = IMPLICIT_DEF
|
||||
G_UBSANTRAP %5
|
||||
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user