From: George Burgess IV Date: Mon, 23 Oct 2017 20:46:36 +0000 (+0000) Subject: Don't crash when we see unallocatable registers in clobbers X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d7958d5ac0c1e979dec35ea26a981532e094b5b2;p=llvm Don't crash when we see unallocatable registers in clobbers This fixes a bug where we'd crash given code like the test-case from https://bugs.llvm.org/show_bug.cgi?id=30792 . Instead, we let the offending clobber silently slide through. This doesn't fully fix said bug, since the assembler will still complain the moment it sees a crypto/fp/vector op, and we still don't diagnose calls that require vector regs. Differential Revision: https://reviews.llvm.org/D39030 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316374 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index bbee69fb656..ff49134f7b9 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -971,7 +971,9 @@ getStrictFPOpcodeAction(const TargetLowering &TLI, unsigned Opcode, EVT VT) { void SelectionDAGLegalize::LegalizeOp(SDNode *Node) { DEBUG(dbgs() << "\nLegalizing: "; Node->dump(&DAG)); - if (Node->getOpcode() == ISD::TargetConstant) // Allow illegal target nodes. + // Allow illegal target nodes and illegal registers. + if (Node->getOpcode() == ISD::TargetConstant || + Node->getOpcode() == ISD::Register) return; #ifndef NDEBUG @@ -985,7 +987,8 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) { assert((TLI.getTypeAction(*DAG.getContext(), Op.getValueType()) == TargetLowering::TypeLegal || TLI.isTypeLegal(Op.getValueType()) || - Op.getOpcode() == ISD::TargetConstant) && + Op.getOpcode() == ISD::TargetConstant || + Op.getOpcode() == ISD::Register) && "Unexpected illegal type!"); #endif diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index c46d1b04804..094afe2830b 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -89,7 +89,8 @@ private: /// Pretend all of this node's results are legal. bool IgnoreNodeResults(SDNode *N) const { - return N->getOpcode() == ISD::TargetConstant; + return N->getOpcode() == ISD::TargetConstant || + N->getOpcode() == ISD::Register; } /// For integer nodes that are below legal width, this map indicates what @@ -400,18 +401,22 @@ private: /// Given an operand Op of Float type, returns the integer if the Op is not /// supported in target HW and converted to the integer. /// The integer contains exactly the same bits as Op - only the type changed. - /// For example, if Op is an f32 which was softened to an i32, then this method - /// returns an i32, the bits of which coincide with those of Op. + /// For example, if Op is an f32 which was softened to an i32, then this + /// method returns an i32, the bits of which coincide with those of Op. /// If the Op can be efficiently supported in target HW or the operand must /// stay in a register, the Op is not converted to an integer. /// In that case, the given op is returned. SDValue GetSoftenedFloat(SDValue Op) { - SDValue &SoftenedOp = SoftenedFloats[Op]; - if (!SoftenedOp.getNode() && - isSimpleLegalType(Op.getValueType())) + auto Iter = SoftenedFloats.find(Op); + if (Iter == SoftenedFloats.end()) { + assert(isSimpleLegalType(Op.getValueType()) && + "Operand wasn't converted to integer?"); return Op; + } + + SDValue &SoftenedOp = Iter->second; + assert(SoftenedOp.getNode() && "Unconverted op in SoftenedFloats?"); RemapValue(SoftenedOp); - assert(SoftenedOp.getNode() && "Operand wasn't converted to integer?"); return SoftenedOp; } void SetSoftenedFloat(SDValue Op, SDValue Result); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 75641e05648..41d352ded37 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -935,7 +935,23 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, 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])); + assert( + (Regs[I] != SP || + DAG.getMachineFunction().getFrameInfo().hasOpaqueSPAdjustment()) && + "If we clobbered the stack pointer, MFI should know about it."); + } + 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 +959,6 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, 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()); - } } } } diff --git a/test/CodeGen/AArch64/no-fp-asm-clobbers-crash.ll b/test/CodeGen/AArch64/no-fp-asm-clobbers-crash.ll new file mode 100644 index 00000000000..5cd8dc57f9a --- /dev/null +++ b/test/CodeGen/AArch64/no-fp-asm-clobbers-crash.ll @@ -0,0 +1,18 @@ +; RUN: 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: +; CHECK: ret +define void @foo() #0 { +entry: + call void asm sideeffect "", "~{v0}"() + call void asm sideeffect "", "~{s0}"() + ret void +} + +attributes #0 = { nounwind "target-features"="-crypto,-fp-armv8,-neon" }