Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -962,11 +962,22 @@ return Action; } +static bool illegalNodeIsAcceptable(const SDNode *Node) { + // Allow illegal target nodes and illegal registers only referenced by + // inline asm. + if (Node->getOpcode() == ISD::Register) { + return all_of(Node->uses(), [](const SDNode *O) { + return O->getOpcode() == ISD::INLINEASM; + }); + } + return Node->getOpcode() == ISD::TargetConstant; +} + /// Return a legal replacement for the given operation, with all legal operands. void SelectionDAGLegalize::LegalizeOp(SDNode *Node) { DEBUG(dbgs() << "\nLegalizing: "; Node->dump(&DAG)); - if (Node->getOpcode() == ISD::TargetConstant) // Allow illegal target nodes. + if (illegalNodeIsAcceptable(Node)) return; #ifndef NDEBUG @@ -980,7 +991,7 @@ assert((TLI.getTypeAction(*DAG.getContext(), Op.getValueType()) == TargetLowering::TypeLegal || TLI.isTypeLegal(Op.getValueType()) || - Op.getOpcode() == ISD::TargetConstant) && + illegalNodeIsAcceptable(Op.getNode())) && "Unexpected illegal type!"); #endif Index: lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -89,6 +89,13 @@ /// Pretend all of this node's results are legal. bool IgnoreNodeResults(SDNode *N) const { + if (N->getOpcode() == ISD::Register) { + // Assume that registers only used by inline asm were vetted properly + // when they were parsed. + return all_of(N->uses(), [](const SDNode *O) { + return O->getOpcode() == ISD::INLINEASM; + }); + } return N->getOpcode() == ISD::TargetConstant; } Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -935,7 +935,22 @@ SDValue Res = DAG.getTargetConstant(Flag, dl, MVT::i32); Ops.push_back(Res); - unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); + if (Code == InlineAsm::Kind_Clobber) { + // Clobbers should always have a 1:1 mapping with registers, and may + // reference registers that have illegal (e.g. vector) types. Hence, we + // shouldn't try to apply any sort of splitting logic to them. + assert(Regs.size() == RegVTs.size() && Regs.size() == ValueVTs.size() && + "No 1:1 mapping from clobbers to regs?"); + unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); + for (unsigned I = 0, E = ValueVTs.size(); I != E; ++I) { + Ops.push_back(DAG.getRegister(Regs[I], RegVTs[I])); + if (Regs[I] == SP) { + assert(DAG.getMachineFunction().getFrameInfo().hasOpaqueSPAdjustment()); + } + } + return; + } + for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), ValueVTs[Value]); MVT RegisterVT = RegVTs[Value]; @@ -943,11 +958,6 @@ assert(Reg < Regs.size() && "Mismatch in # registers expected"); unsigned TheReg = Regs[Reg++]; Ops.push_back(DAG.getRegister(TheReg, RegisterVT)); - - if (TheReg == SP && Code == InlineAsm::Kind_Clobber) { - // If we clobbered the stack pointer, MFI should know about it. - assert(DAG.getMachineFunction().getFrameInfo().hasOpaqueSPAdjustment()); - } } } } Index: test/CodeGen/AArch64/no-fp-asm-clobbers-crash.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/no-fp-asm-clobbers-crash.ll @@ -0,0 +1,29 @@ +; RUN: not llc < %s | FileCheck %s +; +; Be sure that we ignore clobbers of unallocatable registers, rather than +; crashing. + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64" + +; CHECK-LABEL: foo: +; Should make the asm parser unhappy. +; CHECK-NOT: add v0, v1 +; CHECK: ret +define void @foo() #0 { +entry: + call void asm sideeffect "add v0.2d, v1.2d, v2.2d", "~{v0},~{v1},~{v2}"() + ret void +} + +; CHECK-LABEL: bar: +; Should make the asm parser unhappy. +; CHECK-NOT: fmov s1, s0 +; CHECK: ret +define void @bar() #0 { +entry: + call void asm sideeffect "fmov s1, s0", "~{s0},~{s1}"() + ret void +} + +attributes #0 = { nounwind "target-features"="-crypto,-fp-armv8,-neon" }