From 768ebcdf631baa1b18dc65a5983a237b307a99c2 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 10 May 2013 14:09:52 +0000 Subject: DAGCombiner: Generate a correct constant for vector types when folding (xor (and)) into (and (not)). PR15948. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181597 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 3 +-- test/CodeGen/X86/xor.ll | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 700ee12072..c54dffbb13 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3464,8 +3464,7 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { if (N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() && N0->getOperand(1) == N1) { SDValue X = N0->getOperand(0); - SDValue NotX = DAG.getNode(ISD::XOR, X.getDebugLoc(), VT, X, - DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT)); + SDValue NotX = DAG.getNOT(X.getDebugLoc(), X, VT); AddToWorkList(NotX.getNode()); return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, NotX, N1); } diff --git a/test/CodeGen/X86/xor.ll b/test/CodeGen/X86/xor.ll index 2408bfe72c..574bb7817e 100644 --- a/test/CodeGen/X86/xor.ll +++ b/test/CodeGen/X86/xor.ll @@ -154,3 +154,14 @@ define i32 @test9(i32 %a) nounwind { ; X32: notl [[REG:%[a-z]+]] ; X32: andl {{.*}}[[REG:%[a-z]+]] } + +; PR15948 +define <4 x i32> @test10(<4 x i32> %a) nounwind { + %1 = and <4 x i32> %a, + %2 = xor <4 x i32> %1, + ret <4 x i32> %2 +; X64: test10: +; X64: andnps +; X32: test10: +; X32: andnps +} -- cgit v1.2.3 From 2e2c12b9961647987692389bc3cc25eae9220d26 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 10 May 2013 14:42:16 +0000 Subject: XFAILing this test on Win32 to unbreak the build bots. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181600 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/ExecutionEngine/MCJIT/eh.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ExecutionEngine/MCJIT/eh.ll b/test/ExecutionEngine/MCJIT/eh.ll index 0c19b1bf2e..cd67dd70c5 100644 --- a/test/ExecutionEngine/MCJIT/eh.ll +++ b/test/ExecutionEngine/MCJIT/eh.ll @@ -1,5 +1,5 @@ ; RUN: %lli_mcjit %s -; XFAIL: arm, cygwin +; XFAIL: arm, cygwin, win32 declare i8* @__cxa_allocate_exception(i64) declare void @__cxa_throw(i8*, i8*, i8*) declare i32 @__gxx_personality_v0(...) -- cgit v1.2.3 From c24a374331fc97dd215937c8f0a9bf5271f39657 Mon Sep 17 00:00:00 2001 From: Logan Chien Date: Fri, 10 May 2013 16:17:24 +0000 Subject: Implement AsmParser for ARM unwind directives. This commit implements the AsmParser for fnstart, fnend, cantunwind, personality, handlerdata, pad, setfp, save, and vsave directives. This commit fixes some minor issue in the ARMELFStreamer: * The switch back to corresponding section after the .fnend directive. * Emit the unwind opcode while processing .fnend directive if there is no .handlerdata directive. * Emit the unwind opcode to .ARM.extab while processing .handlerdata even if .personality directive does not exist. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181603 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 255 +++++++++++++++++- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 56 ++-- test/MC/ARM/eh-compact-pr0.s | 104 +++++++ test/MC/ARM/eh-compact-pr1.s | 74 +++++ test/MC/ARM/eh-directive-cantunwind-diagnostics.s | 106 ++++++++ test/MC/ARM/eh-directive-cantunwind.s | 51 ++++ test/MC/ARM/eh-directive-fnend-diagnostics.s | 17 ++ test/MC/ARM/eh-directive-fnstart-diagnostics.s | 31 +++ test/MC/ARM/eh-directive-handlerdata.s | 108 ++++++++ test/MC/ARM/eh-directive-pad-diagnostics.s | 39 +++ test/MC/ARM/eh-directive-pad.s | 226 ++++++++++++++++ test/MC/ARM/eh-directive-personality-diagnostics.s | 39 +++ test/MC/ARM/eh-directive-personality.s | 90 +++++++ test/MC/ARM/eh-directive-save-diagnoatics.s | 41 +++ test/MC/ARM/eh-directive-save.s | 298 +++++++++++++++++++++ test/MC/ARM/eh-directive-section-comdat.s | 126 +++++++++ test/MC/ARM/eh-directive-section-multiple-func.s | 129 +++++++++ test/MC/ARM/eh-directive-section.s | 164 ++++++++++++ test/MC/ARM/eh-directive-setfp-diagnostics.s | 87 ++++++ test/MC/ARM/eh-directive-setfp.s | 239 +++++++++++++++++ .../ARM/eh-directive-text-section-multiple-func.s | 81 ++++++ test/MC/ARM/eh-directive-text-section.s | 82 ++++++ test/MC/ARM/eh-directive-vsave-diagnostics.s | 41 +++ test/MC/ARM/eh-directive-vsave.s | 130 +++++++++ 24 files changed, 2587 insertions(+), 27 deletions(-) create mode 100644 test/MC/ARM/eh-compact-pr0.s create mode 100644 test/MC/ARM/eh-compact-pr1.s create mode 100644 test/MC/ARM/eh-directive-cantunwind-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-cantunwind.s create mode 100644 test/MC/ARM/eh-directive-fnend-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-fnstart-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-handlerdata.s create mode 100644 test/MC/ARM/eh-directive-pad-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-pad.s create mode 100644 test/MC/ARM/eh-directive-personality-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-personality.s create mode 100644 test/MC/ARM/eh-directive-save-diagnoatics.s create mode 100644 test/MC/ARM/eh-directive-save.s create mode 100644 test/MC/ARM/eh-directive-section-comdat.s create mode 100644 test/MC/ARM/eh-directive-section-multiple-func.s create mode 100644 test/MC/ARM/eh-directive-section.s create mode 100644 test/MC/ARM/eh-directive-setfp-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-setfp.s create mode 100644 test/MC/ARM/eh-directive-text-section-multiple-func.s create mode 100644 test/MC/ARM/eh-directive-text-section.s create mode 100644 test/MC/ARM/eh-directive-vsave-diagnostics.s create mode 100644 test/MC/ARM/eh-directive-vsave.s diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 1dd2953b29..4d3bf34d48 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -49,6 +49,20 @@ class ARMAsmParser : public MCTargetAsmParser { MCAsmParser &Parser; const MCRegisterInfo *MRI; + // Unwind directives state + SMLoc FnStartLoc; + SMLoc CantUnwindLoc; + SMLoc PersonalityLoc; + SMLoc HandlerDataLoc; + int FPReg; + void resetUnwindDirectiveParserState() { + FnStartLoc = SMLoc(); + CantUnwindLoc = SMLoc(); + PersonalityLoc = SMLoc(); + HandlerDataLoc = SMLoc(); + FPReg = -1; + } + // Map of register aliases registers via the .req directive. StringMap RegisterReqs; @@ -113,6 +127,14 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveUnreq(SMLoc L); bool parseDirectiveArch(SMLoc L); bool parseDirectiveEabiAttr(SMLoc L); + bool parseDirectiveFnStart(SMLoc L); + bool parseDirectiveFnEnd(SMLoc L); + bool parseDirectiveCantUnwind(SMLoc L); + bool parseDirectivePersonality(SMLoc L); + bool parseDirectiveHandlerData(SMLoc L); + bool parseDirectiveSetFP(SMLoc L); + bool parseDirectivePad(SMLoc L); + bool parseDirectiveRegSave(SMLoc L, bool IsVector); StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode, bool &CarrySetting, unsigned &ProcessorIMod, @@ -242,7 +264,7 @@ public: }; ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) - : MCTargetAsmParser(), STI(_STI), Parser(_Parser) { + : MCTargetAsmParser(), STI(_STI), Parser(_Parser), FPReg(-1) { MCAsmParserExtension::Initialize(_Parser); // Cache the MCRegisterInfo. @@ -7658,6 +7680,24 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { return parseDirectiveArch(DirectiveID.getLoc()); else if (IDVal == ".eabi_attribute") return parseDirectiveEabiAttr(DirectiveID.getLoc()); + else if (IDVal == ".fnstart") + return parseDirectiveFnStart(DirectiveID.getLoc()); + else if (IDVal == ".fnend") + return parseDirectiveFnEnd(DirectiveID.getLoc()); + else if (IDVal == ".cantunwind") + return parseDirectiveCantUnwind(DirectiveID.getLoc()); + else if (IDVal == ".personality") + return parseDirectivePersonality(DirectiveID.getLoc()); + else if (IDVal == ".handlerdata") + return parseDirectiveHandlerData(DirectiveID.getLoc()); + else if (IDVal == ".setfp") + return parseDirectiveSetFP(DirectiveID.getLoc()); + else if (IDVal == ".pad") + return parseDirectivePad(DirectiveID.getLoc()); + else if (IDVal == ".save") + return parseDirectiveRegSave(DirectiveID.getLoc(), false); + else if (IDVal == ".vsave") + return parseDirectiveRegSave(DirectiveID.getLoc(), true); return true; } @@ -7858,6 +7898,219 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { return true; } +/// parseDirectiveFnStart +/// ::= .fnstart +bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { + if (FnStartLoc.isValid()) { + Error(L, ".fnstart starts before the end of previous one"); + Error(FnStartLoc, "previous .fnstart starts here"); + return true; + } + + FnStartLoc = L; + getParser().getStreamer().EmitFnStart(); + return false; +} + +/// parseDirectiveFnEnd +/// ::= .fnend +bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .fnend directive"); + + // Reset the unwind directives parser state + resetUnwindDirectiveParserState(); + + getParser().getStreamer().EmitFnEnd(); + return false; +} + +/// parseDirectiveCantUnwind +/// ::= .cantunwind +bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { + // Check the ordering of unwind directives + CantUnwindLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .cantunwind directive"); + if (HandlerDataLoc.isValid()) { + Error(L, ".cantunwind can't be used with .handlerdata directive"); + Error(HandlerDataLoc, ".handlerdata was specified here"); + return true; + } + if (PersonalityLoc.isValid()) { + Error(L, ".cantunwind can't be used with .personality directive"); + Error(PersonalityLoc, ".personality was specified here"); + return true; + } + + getParser().getStreamer().EmitCantUnwind(); + return false; +} + +/// parseDirectivePersonality +/// ::= .personality name +bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { + // Check the ordering of unwind directives + PersonalityLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .personality directive"); + if (CantUnwindLoc.isValid()) { + Error(L, ".personality can't be used with .cantunwind directive"); + Error(CantUnwindLoc, ".cantunwind was specified here"); + return true; + } + if (HandlerDataLoc.isValid()) { + Error(L, ".personality must precede .handlerdata directive"); + Error(HandlerDataLoc, ".handlerdata was specified here"); + return true; + } + + // Parse the name of the personality routine + if (Parser.getTok().isNot(AsmToken::Identifier)) { + Parser.eatToEndOfStatement(); + return Error(L, "unexpected input in .personality directive."); + } + StringRef Name(Parser.getTok().getIdentifier()); + Parser.Lex(); + + MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name); + getParser().getStreamer().EmitPersonality(PR); + return false; +} + +/// parseDirectiveHandlerData +/// ::= .handlerdata +bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { + // Check the ordering of unwind directives + HandlerDataLoc = L; + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .personality directive"); + if (CantUnwindLoc.isValid()) { + Error(L, ".handlerdata can't be used with .cantunwind directive"); + Error(CantUnwindLoc, ".cantunwind was specified here"); + return true; + } + + getParser().getStreamer().EmitHandlerData(); + return false; +} + +/// parseDirectiveSetFP +/// ::= .setfp fpreg, spreg [, offset] +bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .setfp directive"); + if (HandlerDataLoc.isValid()) + return Error(L, ".setfp must precede .handlerdata directive"); + + // Parse fpreg + SMLoc NewFPRegLoc = Parser.getTok().getLoc(); + int NewFPReg = tryParseRegister(); + if (NewFPReg == -1) + return Error(NewFPRegLoc, "frame pointer register expected"); + + // Consume comma + if (!Parser.getTok().is(AsmToken::Comma)) + return Error(Parser.getTok().getLoc(), "comma expected"); + Parser.Lex(); // skip comma + + // Parse spreg + SMLoc NewSPRegLoc = Parser.getTok().getLoc(); + int NewSPReg = tryParseRegister(); + if (NewSPReg == -1) + return Error(NewSPRegLoc, "stack pointer register expected"); + + if (NewSPReg != ARM::SP && NewSPReg != FPReg) + return Error(NewSPRegLoc, + "register should be either $sp or the latest fp register"); + + // Update the frame pointer register + FPReg = NewFPReg; + + // Parse offset + int64_t Offset = 0; + if (Parser.getTok().is(AsmToken::Comma)) { + Parser.Lex(); // skip comma + + if (Parser.getTok().isNot(AsmToken::Hash) && + Parser.getTok().isNot(AsmToken::Dollar)) { + return Error(Parser.getTok().getLoc(), "'#' expected"); + } + Parser.Lex(); // skip hash token. + + const MCExpr *OffsetExpr; + SMLoc ExLoc = Parser.getTok().getLoc(); + SMLoc EndLoc; + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed setfp offset"); + const MCConstantExpr *CE = dyn_cast(OffsetExpr); + if (!CE) + return Error(ExLoc, "setfp offset must be an immediate"); + + Offset = CE->getValue(); + } + + getParser().getStreamer().EmitSetFP(static_cast(NewFPReg), + static_cast(NewSPReg), + Offset); + return false; +} + +/// parseDirective +/// ::= .pad offset +bool ARMAsmParser::parseDirectivePad(SMLoc L) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .pad directive"); + if (HandlerDataLoc.isValid()) + return Error(L, ".pad must precede .handlerdata directive"); + + // Parse the offset + if (Parser.getTok().isNot(AsmToken::Hash) && + Parser.getTok().isNot(AsmToken::Dollar)) { + return Error(Parser.getTok().getLoc(), "'#' expected"); + } + Parser.Lex(); // skip hash token. + + const MCExpr *OffsetExpr; + SMLoc ExLoc = Parser.getTok().getLoc(); + SMLoc EndLoc; + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed pad offset"); + const MCConstantExpr *CE = dyn_cast(OffsetExpr); + if (!CE) + return Error(ExLoc, "pad offset must be an immediate"); + + getParser().getStreamer().EmitPad(CE->getValue()); + return false; +} + +/// parseDirectiveRegSave +/// ::= .save { registers } +/// ::= .vsave { registers } +bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { + // Check the ordering of unwind directives + if (!FnStartLoc.isValid()) + return Error(L, ".fnstart must precede .save or .vsave directives"); + if (HandlerDataLoc.isValid()) + return Error(L, ".save or .vsave must precede .handlerdata directive"); + + // Parse the register list + SmallVector Operands; + if (parseRegisterList(Operands)) + return true; + ARMOperand *Op = (ARMOperand*)Operands[0]; + if (!IsVector && !Op->isRegList()) + return Error(L, ".save expects GPR registers"); + if (IsVector && !Op->isDPRRegList()) + return Error(L, ".vsave expects DPR registers"); + + getParser().getStreamer().EmitRegSave(Op->getRegList(), IsVector); + return false; +} + /// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterMCAsmParser X(TheARMTarget); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 6c3d247668..82d296ffd7 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -204,6 +204,7 @@ private: void EmitPersonalityFixup(StringRef Name); void CollectUnwindOpcodes(); + void FlushUnwindOpcodes(bool AllowCompactModel0); void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags, SectionKind Kind, const MCSymbol &Fn); @@ -333,22 +334,8 @@ void ARMELFStreamer::EmitFnEnd() { assert(FnStart && ".fnstart must preceeds .fnend"); // Emit unwind opcodes if there is no .handlerdata directive - if (!ExTab && !CantUnwind) { - CollectUnwindOpcodes(); - - unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex(); - if (PersonalityIndex == AEABI_UNWIND_CPP_PR1 || - PersonalityIndex == AEABI_UNWIND_CPP_PR2) { - // For the __aeabi_unwind_cpp_pr1 and __aeabi_unwind_cpp_pr2, we have to - // emit the unwind opcodes in the corresponding ".ARM.extab" section, and - // then emit a reference to these unwind opcodes in the second word of - // the exception index table entry. - SwitchToExTabSection(*FnStart); - ExTab = getContext().CreateTempSymbol(); - EmitLabel(ExTab); - EmitBytes(UnwindOpAsm.data(), 0); - } - } + if (!ExTab && !CantUnwind) + FlushUnwindOpcodes(true); // Emit the exception index table entry SwitchToExIdxSection(*FnStart); @@ -384,6 +371,9 @@ void ARMELFStreamer::EmitFnEnd() { EmitBytes(UnwindOpAsm.data(), 0); } + // Switch to the section containing FnStart + SwitchSection(&FnStart->getSection()); + // Clean exception handling frame information Reset(); } @@ -392,7 +382,18 @@ void ARMELFStreamer::EmitCantUnwind() { CantUnwind = true; } -void ARMELFStreamer::EmitHandlerData() { +void ARMELFStreamer::FlushUnwindOpcodes(bool AllowCompactModel0) { + // Collect and finalize the unwind opcodes + CollectUnwindOpcodes(); + + // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx + // section. Thus, we don't have to create an entry in the .ARM.extab + // section. + if (AllowCompactModel0 && + UnwindOpAsm.getPersonalityIndex() == AEABI_UNWIND_CPP_PR0) + return; + + // Switch to .ARM.extab section. SwitchToExTabSection(*FnStart); // Create .ARM.extab label for offset in .ARM.exidx @@ -400,21 +401,24 @@ void ARMELFStreamer::EmitHandlerData() { ExTab = getContext().CreateTempSymbol(); EmitLabel(ExTab); - // Emit Personality - assert(Personality && ".personality directive must preceed .handlerdata"); - - const MCSymbolRefExpr *PersonalityRef = - MCSymbolRefExpr::Create(Personality, - MCSymbolRefExpr::VK_ARM_PREL31, - getContext()); + // Emit personality + if (Personality) { + const MCSymbolRefExpr *PersonalityRef = + MCSymbolRefExpr::Create(Personality, + MCSymbolRefExpr::VK_ARM_PREL31, + getContext()); - EmitValue(PersonalityRef, 4, 0); + EmitValue(PersonalityRef, 4, 0); + } // Emit unwind opcodes - CollectUnwindOpcodes(); EmitBytes(UnwindOpAsm.data(), 0); } +void ARMELFStreamer::EmitHandlerData() { + FlushUnwindOpcodes(false); +} + void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) { Personality = Per; UnwindOpAsm.setPersonality(Per); diff --git a/test/MC/ARM/eh-compact-pr0.s b/test/MC/ARM/eh-compact-pr0.s new file mode 100644 index 0000000000..6b866d5538 --- /dev/null +++ b/test/MC/ARM/eh-compact-pr0.s @@ -0,0 +1,104 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the compact pr0 model + + .syntax unified + + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function +func1: + .fnstart + .save {r11, lr} + push {r11, lr} + .setfp r11, sp + mov r11, sp + pop {r11, lr} + mov pc, lr + .fnend + + .section .TEST2 + .globl func2 + .align 2 + .type func2,%function +func2: + .fnstart + .save {r11, lr} + push {r11, lr} + pop {r11, pc} + .fnend + + + +@------------------------------------------------------------------------------- +@ Check .TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 00482DE9 0DB0A0E1 0048BDE8 0EF0A0E1 |.H-......H......| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check .ARM.exidx.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST1 +@------------------------------------------------------------------------------- +@ The first word should be relocated to .TEST1 section. Besides, there is +@ another relocation entry for __aeabi_unwind_cpp_pr0, so that the linker +@ will keep __aeabi_unwind_cpp_pr0. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr0 0x0 +@ CHECK: ] +@------------------------------------------------------------------------------- +@ 0x80 = Compact model 0, personality routine: __aeabi_unwind_cpp_pr0 +@ 0x9B = $sp can be found in $r11 +@ 0x8480 = pop {r11, r14} +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 80849B80 |........| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check .TEST2 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 00482DE9 0088BDE8 |.H-.....| +@ CHECK: ) +@ CHECK: } +@------------------------------------------------------------------------------- +@ Check .ARM.exidx.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST2 +@------------------------------------------------------------------------------- +@ The first word should be relocated to .TEST2 section. Besides, there is +@ another relocation entry for __aeabi_unwind_cpp_pr0, so that the linker +@ will keep __aeabi_unwind_cpp_pr0. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST2 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr0 0x0 +@ CHECK: ] +@------------------------------------------------------------------------------- +@ 0x80 = Compact model 0, personality routine: __aeabi_unwind_cpp_pr0 +@ 0x8480 = pop {r11, r14} +@ 0xB0 = finish +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0808480 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-compact-pr1.s b/test/MC/ARM/eh-compact-pr1.s new file mode 100644 index 0000000000..0fac3e2100 --- /dev/null +++ b/test/MC/ARM/eh-compact-pr1.s @@ -0,0 +1,74 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the compact pr1 model + + .syntax unified + + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function +func1: + .fnstart + .save {r4, r5, r11, lr} + push {r4, r5, r11, lr} + add r0, r1, r0 + .setfp r11, sp, #8 + add r11, sp, #8 + pop {r4, r5, r11, pc} + .fnend + + + +@------------------------------------------------------------------------------- +@ Check .TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 30482DE9 000081E0 08B08DE2 3088BDE8 |0H-.........0...| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check .ARM.extab.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@------------------------------------------------------------------------------- +@ 0x81 = Compact model 1, personality routine: __aeabi_unwind_cpp_pr1 +@ 0x9B = $sp can be found in $r11 +@ 0x41 = $sp = $sp - 8 +@ 0x8483 = pop {r4, r5, r11, r14} +@ 0xB0 = finish +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 419B0181 B0B08384 |A.......| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check .ARM.exidx.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST1 +@------------------------------------------------------------------------------- +@ The first word should be relocated to .TEST1 section, and the second word +@ should be relocated to .ARM.extab.TEST1 section. Besides, there is +@ another relocation entry for __aeabi_unwind_cpp_pr1, so that the linker +@ will keep __aeabi_unwind_cpp_pr1. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr1 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-cantunwind-diagnostics.s b/test/MC/ARM/eh-directive-cantunwind-diagnostics.s new file mode 100644 index 0000000000..5a6a46c69a --- /dev/null +++ b/test/MC/ARM/eh-directive-cantunwind-diagnostics.s @@ -0,0 +1,106 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck < %t %s + +@ Check the diagnostics for .cantunwind, .handlerdata, and .personality + +@ .cantunwind directive can't be used with .handlerdata directive nor +@ .personality directive. This test case check for the diagnostics for +@ the conflicts. + + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: cantunwind + personality +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + .cantunwind + .personality __gxx_personality_v0 +@ CHECK: error: .personality can't be used with .cantunwind directive +@ CEHCK: .personality __gxx_personality_v0 +@ CHECK: ^ +@ CHECK: error: .cantunwind was specified here +@ CHECK: .cantunwind +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: cantunwind + handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .cantunwind + .handlerdata +@ CHECK: error: .handlerdata can't be used with .cantunwind directive +@ CEHCK: .handlerdata +@ CHECK: ^ +@ CHECK: error: .cantunwind was specified here +@ CHECK: .cantunwind +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST3: personality + cantunwind +@------------------------------------------------------------------------------- + .globl func3 + .align 2 + .type func3,%function + .fnstart +func3: + .personality __gxx_personality_v0 + .cantunwind +@ CHECK: error: .cantunwind can't be used with .personality directive +@ CEHCK: .cantunwind +@ CHECK: ^ +@ CHECK: error: .personality was specified here +@ CHECK: .personality __gxx_personality_v0 +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST4: handlerdata + cantunwind +@------------------------------------------------------------------------------- + .globl func4 + .align 2 + .type func4,%function + .fnstart +func4: + .handlerdata + .cantunwind +@ CHECK: error: .cantunwind can't be used with .handlerdata directive +@ CEHCK: .cantunwind +@ CHECK: ^ +@ CHECK: error: .handlerdata was specified here +@ CHECK: .handlerdata +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST5: cantunwind + fnstart +@------------------------------------------------------------------------------- + .globl func5 + .align 2 + .type func5,%function + .cantunwind +@ CHECK: error: .fnstart must precede .cantunwind directive +@ CHECK: .cantunwind +@ CHECK: ^ + .fnstart +func5: + .fnend diff --git a/test/MC/ARM/eh-directive-cantunwind.s b/test/MC/ARM/eh-directive-cantunwind.s new file mode 100644 index 0000000000..0545f6d3c8 --- /dev/null +++ b/test/MC/ARM/eh-directive-cantunwind.s @@ -0,0 +1,51 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the .cantunwind directive + +@ When a function contains a .cantunwind directive, we should create an entry +@ in corresponding .ARM.exidx, and its second word should be EXIDX_CANTUNWIND. + + .syntax unified + + .text + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .cantunwind + .fnend + + + +@------------------------------------------------------------------------------- +@ Check .text section +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Name: .text +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check .ARM.exidx section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .text 0x0 +@ CHECK: ] +@------------------------------------------------------------------------------- +@ The first word should be the offset to .text. +@ The second word should be EXIDX_CANTUNWIND (01000000). +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 01000000 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-fnend-diagnostics.s b/test/MC/ARM/eh-directive-fnend-diagnostics.s new file mode 100644 index 0000000000..a5e4d3bf5b --- /dev/null +++ b/test/MC/ARM/eh-directive-fnend-diagnostics.s @@ -0,0 +1,17 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi \ +@ RUN: -filetype=obj -o /dev/null 2>&1 | FileCheck %s + +@ Check the diagnostics for mismatched .fnend directive + + + .syntax unified + .text + + .globl func1 + .align 2 + .type func1,%function +func1: + .fnend +@ CHECK: error: .fnstart must precede .fnend directive +@ CHECK: .fnend +@ CHECK: ^ diff --git a/test/MC/ARM/eh-directive-fnstart-diagnostics.s b/test/MC/ARM/eh-directive-fnstart-diagnostics.s new file mode 100644 index 0000000000..29bcb0dd9c --- /dev/null +++ b/test/MC/ARM/eh-directive-fnstart-diagnostics.s @@ -0,0 +1,31 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi \ +@ RUN: -filetype=obj -o /dev/null 2>&1 | FileCheck %s + +@ Check the diagnostics for the mismatched .fnstart directives. + +@ There should be some diagnostics when the previous .fnstart is not closed +@ by the .fnend directive. + + + .syntax unified + .text + + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + @ Intentionally miss the .fnend directive + + .globl func2 + .align 2 + .type func2,%function + .fnstart +@ CHECK: error: .fnstart starts before the end of previous one +@ CHECK: .fnstart +@ CHECK: ^ +@ CHECK: error: previous .fnstart starts here +@ CHECK: .fnstart +@ CHECK: ^ +func2: + .fnend diff --git a/test/MC/ARM/eh-directive-handlerdata.s b/test/MC/ARM/eh-directive-handlerdata.s new file mode 100644 index 0000000000..45f22ddb63 --- /dev/null +++ b/test/MC/ARM/eh-directive-handlerdata.s @@ -0,0 +1,108 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the .handlerdata directive (without .personality directive) + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .handlerdata + .fnend + + +@ CHECK:Section { +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK:} + +@ CHECK:Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: B0B0B080 |....| +@ CHECK: ) +@ CHECK:} + +@ CHECK:Section { +@ CHECK: Name: .ARM.exidx.TEST1 +@------------------------------------------------------------------------------- +@ We should see a relocation entry to __aeabi_unwind_cpp_pr0, so that the +@ linker can keep __aeabi_unwind_cpp_pr0. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr0 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK:} + + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: +@------------------------------------------------------------------------------- +@ Use a lot of unwind opcdes to get __aeabi_unwind_cpp_pr1. +@------------------------------------------------------------------------------- + .save {r4, r5, r6, r7, r8, r9, r10, r11, r12} + push {r4, r5, r6, r7, r8, r9, r10, r11, r12} + pop {r4, r5, r6, r7, r8, r9, r10, r11, r12} + .pad #0x240 + sub sp, sp, #0x240 + add sp, sp, #0x240 + bx lr + .handlerdata + .fnend + + + +@ CHECK:Section { +@ CHECK: Name: .TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: F01F2DE9 F01FBDE8 09DD4DE2 09DD8DE2 |..-.......M.....| +@ CHECK: 0010: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK:} + +@ CHECK:Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 0FB20181 B0B0FF81 |........| +@ CHECK: ) +@ CHECK:} + +@ CHECK:Section { +@ CHECK: Name: .ARM.exidx.TEST2 +@------------------------------------------------------------------------------- +@ We should see a relocation entry to __aeabi_unwind_cpp_pr0, so that the +@ linker can keep __aeabi_unwind_cpp_pr0. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST2 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr1 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST2 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK:} diff --git a/test/MC/ARM/eh-directive-pad-diagnostics.s b/test/MC/ARM/eh-directive-pad-diagnostics.s new file mode 100644 index 0000000000..7072159621 --- /dev/null +++ b/test/MC/ARM/eh-directive-pad-diagnostics.s @@ -0,0 +1,39 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK < %t %s + +@ Check the diagnostics for .pad directive. + + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: .pad before .fnstart +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .pad #0 +@ CHECK: error: .fnstart must precede .pad directive +@ CHECK: .pad #0 +@ CHECK: ^ + .fnstart +func1: + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: .pad after .handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .handlerdata + .pad #0 +@ CHECK: error: .pad must precede .handlerdata directive +@ CHECK: .pad #0 +@ CHECK: ^ + .fnend diff --git a/test/MC/ARM/eh-directive-pad.s b/test/MC/ARM/eh-directive-pad.s new file mode 100644 index 0000000000..ba850ffe77 --- /dev/null +++ b/test/MC/ARM/eh-directive-pad.s @@ -0,0 +1,226 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd | FileCheck %s + +@ Check for different stack pointer offsets. + +@ The .pad directive will track the stack pointer offsets. There are several +@ ways to encode the stack offsets. We have to test: +@ +@ offset < 0x00 +@ offset == 0x00 +@ 0x04 <= offset <= 0x100 +@ 0x104 <= offset <= 0x200 +@ 0x204 <= offset + + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + .pad #0 + sub sp, sp, #0 + add sp, sp, #0 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit nothing (will be filled up with finish opcode). +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2a + .align 2 + .type func2a,%function + .fnstart +func2a: + .pad #0x4 + sub sp, sp, #0x4 + add sp, sp, #0x4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2b + .align 2 + .type func2b,%function + .fnstart +func2b: + .pad #0x100 + sub sp, sp, #0x100 + add sp, sp, #0x100 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit ((offset - 4) >> 2). +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B00000 00000000 B0B03F00 |..............?.| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ TEST3 +@------------------------------------------------------------------------------- + .section .TEST3 + .globl func3a + .align 2 + .type func3a,%function + .fnstart +func3a: + .pad #0x104 + sub sp, sp, #0x104 + add sp, sp, #0x104 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func3b + .align 2 + .type func3b,%function + .fnstart +func3b: + .pad #0x200 + sub sp, sp, #0x200 + add sp, sp, #0x200 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x3F and ((offset - 0x104) >> 2). +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST3 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0003F00 00000000 B03F3F00 |......?......??.| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST4 +@------------------------------------------------------------------------------- + .section .TEST4 + .globl func4a + .align 2 + .type func4a,%function + .fnstart +func4a: + .pad #0x204 + sub sp, sp, #0x204 + add sp, sp, #0x204 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4b + .align 2 + .type func4b,%function + .fnstart +func4b: + .pad #0x580 + sub sp, sp, #0x580 + add sp, sp, #0x580 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0xB2 and the ULEB128 encoding of +@ ((offset - 0x204) >> 2). +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST4 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B000B200 00000000 01DFB200 |................| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST5 +@------------------------------------------------------------------------------- + .section .TEST5 + .globl func4a + .align 2 + .type func4a,%function + .fnstart +func5a: + .pad #-0x4 + add sp, sp, #0x4 + sub sp, sp, #0x4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func5b + .align 2 + .type func5b,%function + .fnstart +func5b: + .pad #-0x104 + add sp, sp, #0x104 + sub sp, sp, #0x4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func5c + .align 2 + .type func5c,%function + .fnstart +func5c: + .pad #-0x204 + add sp, sp, #0x204 + sub sp, sp, #0x4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit (0x40 | (-offset - 4)) >> 2. When (-offset - 4) +@ is greater than 0x3f, then multiple 0x7f should be emitted. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST5 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B04000 00000000 B0407F00 |......@......@..| +@ CHECK: 0010: 00000000 407F7F00 |....@...| +@ CHECK: ) +@ CHECK: } diff --git a/test/MC/ARM/eh-directive-personality-diagnostics.s b/test/MC/ARM/eh-directive-personality-diagnostics.s new file mode 100644 index 0000000000..83e9c25f0b --- /dev/null +++ b/test/MC/ARM/eh-directive-personality-diagnostics.s @@ -0,0 +1,39 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK < %t %s + +@ Check the diagnostics for .personality directive. + + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: .personality before .fnstart +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .personality __gxx_personality_v0 +@ CHECK: error: .fnstart must precede .personality directive +@ CHECK: .personality __gxx_personality_v0 +@ CHECK: ^ + .fnstart +func1: + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: .personality after .handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .handlerdata + .personality __gxx_personality_v0 +@ CHECK: error: .personality must precede .handlerdata directive +@ CHECK: .personality __gxx_personality_v0 +@ CHECK: ^ + .fnend diff --git a/test/MC/ARM/eh-directive-personality.s b/test/MC/ARM/eh-directive-personality.s new file mode 100644 index 0000000000..2267108b28 --- /dev/null +++ b/test/MC/ARM/eh-directive-personality.s @@ -0,0 +1,90 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the .personality directive. + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + +@ CHECK: Section { +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST1 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + bx lr + .personality __gxx_personality_v0 + @ The .handlerdata directive is intentionally ignored. The .fnend @ directive should create the EXTAB entry and flush the unwind opcodes. + .fnend + + +@ CHECK: Section { +@ CHECK: Name: .TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST2 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST2 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST2 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK: } diff --git a/test/MC/ARM/eh-directive-save-diagnoatics.s b/test/MC/ARM/eh-directive-save-diagnoatics.s new file mode 100644 index 0000000000..0e6d7404a3 --- /dev/null +++ b/test/MC/ARM/eh-directive-save-diagnoatics.s @@ -0,0 +1,41 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK < %t %s + +@ Check the diagnostics for .save directive + +@ .save directive should always come after .fnstart directive and +@ before .handlerdata directive. + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: .save before .fnstart +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .save {r4, r5, r6, r7} +@ CHECK: error: .fnstart must precede .save or .vsave directives +@ CHECK: .save {r4, r5, r6, r7} +@ CHECK: ^ + .fnstart +func1: + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: .save after .handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .handlerdata + .save {r4, r5, r6, r7} +@ CHECK: error: .save or .vsave must precede .handlerdata directive +@ CHECK: .save {r4, r5, r6, r7} +@ CHECK: ^ + .fnend diff --git a/test/MC/ARM/eh-directive-save.s b/test/MC/ARM/eh-directive-save.s new file mode 100644 index 0000000000..f9c8c5f03f --- /dev/null +++ b/test/MC/ARM/eh-directive-save.s @@ -0,0 +1,298 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd | FileCheck %s + +@ Check the .save directive + +@ The .save directive records the GPR registers which are pushed to the +@ stack. There are 4 different unwind opcodes: +@ +@ 0xB100: pop r[3:0] +@ 0xA0: pop r[(4+x):4] @ r[4+x]-r[4] must be consecutive. +@ 0xA8: pop r14, r[(4+x):4] @ r[4+x]-r[4] must be consecutive. +@ 0x8000: pop r[15:4] +@ +@ If register list specifed by .save directive is possible to be encoded +@ by 0xA0 or 0xA8, then the assembler should prefer them over 0x8000. + + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1a + .align 2 + .type func1a,%function + .fnstart +func1a: + .save {r0} + push {r0} + pop {r0} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1b + .align 2 + .type func1b,%function + .fnstart +func1b: + .save {r0, r1} + push {r0, r1} + pop {r0, r1} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1c + .align 2 + .type func1c,%function + .fnstart +func1c: + .save {r0, r2} + push {r0, r2} + pop {r0, r2} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1d + .align 2 + .type func1d,%function + .fnstart +func1d: + .save {r1, r2} + push {r1, r2} + pop {r1, r2} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1e + .align 2 + .type func1e,%function + .fnstart +func1e: + .save {r0, r1, r2, r3} + push {r0, r1, r2, r3} + pop {r0, r1, r2, r3} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0xB000 unwind opcode. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B001B100 00000000 B003B100 |................| +@ CHECK: 0010: 00000000 B005B100 00000000 B006B100 |................| +@ CHECK: 0020: 00000000 B00FB100 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2a + .align 2 + .type func2a,%function + .fnstart +func2a: + .save {r4} + push {r4} + pop {r4} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2b + .align 2 + .type func2b,%function + .fnstart +func2b: + .save {r4, r5} + push {r4, r5} + pop {r4, r5} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2c + .align 2 + .type func2c,%function + .fnstart +func2c: + .save {r4, r5, r6, r7, r8, r9, r10, r11} + push {r4, r5, r6, r7, r8, r9, r10, r11} + pop {r4, r5, r6, r7, r8, r9, r10, r11} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0xA0 unwind opcode. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0A000 00000000 B0B0A100 |................| +@ CHECK: 0010: 00000000 B0B0A700 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST3 +@------------------------------------------------------------------------------- + .section .TEST3 + .globl func3a + .align 2 + .type func3a,%function + .fnstart +func3a: + .save {r4, r14} + push {r4, r14} + pop {r4, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func3b + .align 2 + .type func3b,%function + .fnstart +func3b: + .save {r4, r5, r14} + push {r4, r5, r14} + pop {r4, r5, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func3c + .align 2 + .type func3c,%function + .fnstart +func3c: + .save {r4, r5, r6, r7, r8, r9, r10, r11, r14} + push {r4, r5, r6, r7, r8, r9, r10, r11, r14} + pop {r4, r5, r6, r7, r8, r9, r10, r11, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0xA8 unwind opcode. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST3 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0A800 00000000 B0B0A900 |................| +@ CHECK: 0010: 00000000 B0B0AF00 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST4 +@------------------------------------------------------------------------------- + .section .TEST4 + .globl func4a + .align 2 + .type func4a,%function + .fnstart +func4a: + .save {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} + push {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} + pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4b + .align 2 + .type func4b,%function + .fnstart +func4b: + @ Note: r7 is missing intentionally. + .save {r4, r5, r6, r8, r9, r10, r11} + push {r4, r5, r6, r8, r9, r10, r11} + pop {r4, r5, r6, r8, r9, r10, r11} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4c + .align 2 + .type func4c,%function + .fnstart +func4c: + @ Note: r7 is missing intentionally. + .save {r4, r5, r6, r8, r9, r10, r11, r14} + push {r4, r5, r6, r8, r9, r10, r11, r14} + pop {r4, r5, r6, r8, r9, r10, r11, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4d + .align 2 + .type func4d,%function + .fnstart +func4d: + @ Note: The register list is not start with r4. + .save {r5, r6, r7} + push {r5, r6, r7} + pop {r5, r6, r7} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4e + .align 2 + .type func4e,%function + .fnstart +func4e: + @ Note: The register list is not start with r4. + .save {r5, r6, r7, r14} + push {r5, r6, r7, r14} + pop {r5, r6, r7, r14} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x8000 unwind opcode. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST4 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0FF8500 00000000 B0F78000 |................| +@ CHECK: 0010: 00000000 B0F78400 00000000 B00E8000 |................| +@ CHECK: 0020: 00000000 B00E8400 |........| +@ CHECK: ) +@ CHECK: } diff --git a/test/MC/ARM/eh-directive-section-comdat.s b/test/MC/ARM/eh-directive-section-comdat.s new file mode 100644 index 0000000000..296718f096 --- /dev/null +++ b/test/MC/ARM/eh-directive-section-comdat.s @@ -0,0 +1,126 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr -t | FileCheck %s + +@ Check the .group section for the function in comdat section. + +@ In C++, the instantiation of the template will come with linkonce (or +@ linkonce_odr) linkage, so that the linker can remove the duplicated +@ instantiation. When the exception handling is enabled on those function, +@ we have to group the corresponding .ARM.extab and .ARM.exidx with the +@ text section together. +@ +@ This test case will check the content of .group section. The section index +@ of the grouped sections should be recorded in .group section. + + .syntax unified + .section .TEST1,"axG",%progbits,func1,comdat + .weak func1 + .align 2 + .type func1,%function +func1: + .fnstart + .save {r4, lr} + push {r4, lr} + .vsave {d8, d9, d10, d11, d12} + vpush {d8, d9, d10, d11, d12} + .pad #24 + sub sp, sp, #24 + + add sp, sp, #24 + vpop {d8, d9, d10, d11, d12} + pop {r4, pc} + + .globl __gxx_personality_v0 + .personality __gxx_personality_v0 + .handlerdata + .fnend + + + +@------------------------------------------------------------------------------- +@ Check the .group section +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Index: 1 +@ CHECK: Name: .group +@ CHECK: Type: SHT_GROUP (0x11) +@ CHECK: Flags [ (0x0) +@ CHECK: ] +@ CHECK: SectionData ( +@------------------------------------------------------------------------------- +@ The second, third, and fourth word should correspond to the section index +@ of .TEST1, .ARM.extab.TEST1, and .ARM.exidx.TEST1. +@------------------------------------------------------------------------------- +@ CHECK: 0000: 01000000 05000000 06000000 08000000 |................| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Index: 5 +@ CHECK: Name: .TEST1 +@ CHECK: Type: SHT_PROGBITS (0x1) +@------------------------------------------------------------------------------- +@ The flags should contain SHF_GROUP. +@------------------------------------------------------------------------------- +@ CHECK: Flags [ (0x206) +@ CHECK: SHF_ALLOC (0x2) +@ CHECK: SHF_EXECINSTR (0x4) +@ CHECK: SHF_GROUP (0x200) +@ CHECK: ] +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .ARM.extab.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Index: 6 +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: Type: SHT_PROGBITS (0x1) +@------------------------------------------------------------------------------- +@ The flags should contain SHF_GROUP. +@------------------------------------------------------------------------------- +@ CHECK: Flags [ (0x202) +@ CHECK: SHF_ALLOC (0x2) +@ CHECK: SHF_GROUP (0x200) +@ CHECK: ] +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .ARM.exidx.TEST1 section +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Index: 8 +@ CHECK: Name: .ARM.exidx.TEST1 +@ CHECK: Type: SHT_ARM_EXIDX (0x70000001) +@------------------------------------------------------------------------------- +@ The flags should contain SHF_GROUP. +@------------------------------------------------------------------------------- +@ CHECK: Flags [ (0x282) +@ CHECK: SHF_ALLOC (0x2) +@ CHECK: SHF_GROUP (0x200) +@ CHECK: SHF_LINK_ORDER (0x80) +@ CHECK: ] +@ CHECK: Link: 5 +@ CHECK: } +@ CHECK: ] + + + +@------------------------------------------------------------------------------- +@ Check symbol func1. It should be weak binding, and belong to .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Symbols [ +@ CHECK: Symbol { +@ CHECK: Name: func1 +@ CHECK: Binding: Weak (0x2) +@ CHECK: Type: Function (0x2) +@ CHECK: Section: .TEST1 (0x5) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-section-multiple-func.s b/test/MC/ARM/eh-directive-section-multiple-func.s new file mode 100644 index 0000000000..444099f8f6 --- /dev/null +++ b/test/MC/ARM/eh-directive-section-multiple-func.s @@ -0,0 +1,129 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr -t | FileCheck %s + +@ Check whether the section is switched back properly. + +@ The assembler should switch the section back to the corresponding section +@ after it have emitted the exception handling indices and tables. In this +@ test case, we are checking whether the section is correct when .section +@ directives is used. + +@ In this example, func1 and func2 should be defined in .TEST1 section. +@ It is incorrect if the func2 is in .text, .ARM.extab.TEST1, or +@ .ARM.exidx.TEST1 sections. + + .syntax unified + + .section .TEST1 + + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + +@------------------------------------------------------------------------------- +@ Check the .text section. This should be empty. +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Name: .text +@ CHECK: SectionData ( +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .TEST1 section. There should be two "bx lr" instructions. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 1EFF2FE1 |../.../.| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ Check the .ARM.extab.TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: 0x8 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 00000000 B0B0B000 |................| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .ARM.exidx.TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST1 +@ CHECK: Link: 4 +@------------------------------------------------------------------------------- +@ The first word of each entry should be relocated to .TEST1 section. +@ The second word of each entry should be relocated to +@ .ARM.extab.TESET1 section. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: 0x8 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0xC R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: ] +@------------------------------------------------------------------------------- +@ The first word should be the offset to .TEST1. +@ The second word should be the offset to .ARM.extab.TEST1 +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 04000000 08000000 |................| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] + + + +@------------------------------------------------------------------------------- +@ Check the symbols "func1" and "func2". They should belong to .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Symbols [ +@ CHECK: Symbol { +@ CHECK: Name: func1 +@ CHECK: Value: 0x0 +@ CHECK: Size: 0 +@ CHECK: Binding: Global (0x1) +@ CHECK: Type: Function (0x2) +@ CHECK: Other: 0 +@ CHECK: Section: .TEST1 (0x4) +@ CHECK: } +@ CHECK: Symbol { +@ CHECK: Name: func2 +@ CHECK: Value: 0x4 +@ CHECK: Size: 0 +@ CHECK: Binding: Global (0x1) +@ CHECK: Type: Function (0x2) +@ CHECK: Other: 0 +@ CHECK: Section: .TEST1 (0x4) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-section.s b/test/MC/ARM/eh-directive-section.s new file mode 100644 index 0000000000..5f5d1252f8 --- /dev/null +++ b/test/MC/ARM/eh-directive-section.s @@ -0,0 +1,164 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr -t | FileCheck %s + +@ Check the combination of .section, .fnstart, and .fnend directives. + +@ For the functions in .text section, the exception handling index (EXIDX) +@ should be generated in .ARM.exidx, and the exception handling table (EXTAB) +@ should be generated in .ARM.extab. + +@ For the functions in custom section specified by .section directives, +@ the EXIDX should be generated in ".ARM.exidx[[SECTION_NAME]]", and the EXTAB +@ should be generated in ".ARM.extab[[SECTION_NAME]]". + + .syntax unified + +@------------------------------------------------------------------------------- +@ .TEST1 section +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + +@------------------------------------------------------------------------------- +@ TEST2 section (without the dot in the beginning) +@------------------------------------------------------------------------------- + .section TEST2 + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + +@------------------------------------------------------------------------------- +@ Check the .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Index: 4 +@ CHECK: Name: .TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } + +@------------------------------------------------------------------------------- +@ Check the .ARM.extab.TEST1 section, the EXTAB of .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 |........| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the.ARM.exidx.TEST1 section, the EXIDX of .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx.TEST1 + +@------------------------------------------------------------------------------- +@ This section should linked with .TEST1 section. +@------------------------------------------------------------------------------- +@ CHECK: Link: 4 + +@------------------------------------------------------------------------------- +@ The first word should be relocated to the code address in .TEST1 section. +@ The second word should be relocated to the EHTAB entry in .ARM.extab.TEST1 +@ section. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .TEST1 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extab.TEST1 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ Check the TEST2 section (without the dot in the beginning) +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Index: 9 +@ CHECK: Name: TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } + +@------------------------------------------------------------------------------- +@ Check the .ARM.extabTEST2 section, the EXTAB of TEST2 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extabTEST2 +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 __gxx_personality_v0 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B000 |........| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .ARM.exidxTEST2 section, the EXIDX of TEST2 section. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidxTEST2 + +@------------------------------------------------------------------------------- +@ This section should linked with TEST2 section. +@------------------------------------------------------------------------------- +@ CHECK: Link: 9 + +@------------------------------------------------------------------------------- +@ The first word should be relocated to the code address in TEST2 section. +@ The second word should be relocated to the EHTAB entry in .ARM.extabTEST2 +@ section. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 TEST2 0x0 +@ CHECK: 0x4 R_ARM_PREL31 .ARM.extabTEST2 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00000000 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] + + + +@------------------------------------------------------------------------------- +@ Check the symbols and the sections they belong to +@------------------------------------------------------------------------------- +@ CHECK: Symbols [ +@ CHECK: Symbol { +@ CHECK: Name: func1 +@ CHECK: Section: .TEST1 (0x4) +@ CHECK: } +@ CHECK: Symbol { +@ CHECK: Name: func2 +@ CHECK: Section: TEST2 (0x9) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-setfp-diagnostics.s b/test/MC/ARM/eh-directive-setfp-diagnostics.s new file mode 100644 index 0000000000..a5b8aa2386 --- /dev/null +++ b/test/MC/ARM/eh-directive-setfp-diagnostics.s @@ -0,0 +1,87 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK < %t %s + +@ Check the diagnostics for .setfp directive. + + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: .setfp before .fnstart +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .setfp fp, sp, #0 +@ CHECK: error: .fnstart must precede .setfp directive +@ CHECK: .setfp fp, sp, #0 +@ CHECK: ^ + .fnstart +func1: + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: .setfp after .handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .handlerdata + .setfp fp, sp, #0 +@ CHECK: error: .setfp must precede .handlerdata directive +@ CHECK: .setfp fp, sp, #0 +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST3: .setfp with bad fp register +@------------------------------------------------------------------------------- + .globl func3 + .align 2 + .type func3,%function + .fnstart +func3: + .setfp 0, r0, #0 +@ CHECK: error: frame pointer register expected +@ CHECK: .setfp 0, r0, #0 +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST4: .setfp with bad sp register +@------------------------------------------------------------------------------- + .globl func4 + .align 2 + .type func4,%function + .fnstart +func4: + .setfp fp, 0, #0 +@ CHECK: error: stack pointer register expected +@ CHECK: .setfp fp, 0, #0 +@ CHECK: ^ + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST5: .setfp with non-sp register as second operand +@------------------------------------------------------------------------------- + .globl func5 + .align 2 + .type func5,%function + .fnstart +func5: + .setfp fp, r0, #0 +@ CHECK: error: register should be either $sp or the latest fp register +@ CHECK: .setfp fp, r0, #0 +@ CHECK: ^ + .fnend diff --git a/test/MC/ARM/eh-directive-setfp.s b/test/MC/ARM/eh-directive-setfp.s new file mode 100644 index 0000000000..3fbab5a3e7 --- /dev/null +++ b/test/MC/ARM/eh-directive-setfp.s @@ -0,0 +1,239 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd | FileCheck %s + +@ Check for .setfp directive. + +@ The .setfp directive will track the offset between the frame pointer and +@ the stack pointer. This is required for the function that will change +@ the stack pointer out of the function prologue. If the exception is thrown, +@ then libunwind will reconstruct the stack pointer from the frame pointer. +@ The reconstruction code is implemented by two different unwind opcode: +@ (i) the unwind opcode to copy stack offset from the other register, and +@ (ii) the unwind opcode to add or substract the stack offset. +@ +@ This file includes several cases separated by different range of -offset +@ +@ (-offset) < 0x00 +@ (-offset) == 0x00 +@ 0x04 <= (-offset) <= 0x100 +@ 0x104 <= (-offset) <= 0x200 +@ 0x204 <= (-offset) + + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + .setfp fp, sp, #0 + add fp, sp, #0 + sub sp, fp, #0 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x9B to copy stack pointer from r11. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B09B00 |........| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2a + .align 2 + .type func2a,%function + .fnstart +func2a: + .setfp fp, sp, #-4 + add fp, sp, #4 + sub sp, fp, #4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2b + .align 2 + .type func2b,%function + .fnstart +func2b: + .setfp fp, sp, #-0x100 + add fp, sp, #0x100 + sub sp, fp, #0x100 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x9B to copy stack pointer from r11. +@ The assembler should emit ((-offset - 4) >> 2) for offset. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0009B00 00000000 B03F9B00 |.............?..| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST3 +@------------------------------------------------------------------------------- + .section .TEST3 + .globl func3a + .align 2 + .type func3a,%function + .fnstart +func3a: + .setfp fp, sp, #-0x104 + sub fp, sp, #0x104 + add sp, fp, #0x104 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func3b + .align 2 + .type func3b,%function + .fnstart +func3b: + .setfp fp, sp, #-0x200 + sub fp, sp, #0x200 + add sp, fp, #0x200 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x9B to copy stack pointer from r11. +@ The assembler should emit 0x3F and ((-offset - 0x104) >> 2) for offset. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST3 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 003F9B00 00000000 3F3F9B00 |.....?......??..| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST4 +@------------------------------------------------------------------------------- + .section .TEST4 + .globl func4a + .align 2 + .type func4a,%function + .fnstart +func4a: + .setfp fp, sp, #-0x204 + sub fp, sp, #0x204 + add sp, fp, #0x204 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func4b + .align 2 + .type func4b,%function + .fnstart +func4b: + .setfp fp, sp, #-0x580 + sub fp, sp, #0x580 + add sp, fp, #0x580 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x9B to copy stack pointer from r11. +@ The assembler should emit 0xB2 and the ULEB128 encoding of +@ ((-offset - 0x204) >> 2) for offset. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST4 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 00B29B00 00000000 DFB29B01 |................| +@ CHECK: 0010: B0B0B001 |....| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST5 +@------------------------------------------------------------------------------- + .section .TEST5 + .globl func5a + .align 2 + .type func5a,%function + .fnstart +func5a: + .setfp fp, sp, #0x4 + add fp, sp, #0x4 + sub sp, fp, #0x4 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func5b + .align 2 + .type func5b,%function + .fnstart +func5b: + .setfp fp, sp, #0x104 + add fp, sp, #0x104 + sub sp, fp, #0x104 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func5c + .align 2 + .type func5c,%function + .fnstart +func5c: + .setfp fp, sp, #0x204 + add fp, sp, #0x204 + sub sp, fp, #0x204 + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@------------------------------------------------------------------------------- +@ The assembler should emit 0x9B to copy stack pointer from r11. +@ The assembler should emit (0x40 | (offset - 4)) >> 2 for offset. +@ If (offset - 4) is greater than 0x3f, then multiple 0x7f should be emitted. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST5 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0409B00 00000000 407F9B00 |.....@......@...| +@ CHECK: 0010: 00000000 7F7F9B01 B0B0B040 |...........@| +@ CHECK: ) +@ CHECK: } diff --git a/test/MC/ARM/eh-directive-text-section-multiple-func.s b/test/MC/ARM/eh-directive-text-section-multiple-func.s new file mode 100644 index 0000000000..c9412763a8 --- /dev/null +++ b/test/MC/ARM/eh-directive-text-section-multiple-func.s @@ -0,0 +1,81 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr -r -t | FileCheck %s + +@ Check whether the section is switched back or not. + +@ The assembler should emit the machine code of "func2" in .text section. +@ It is incorrect if the machine code is emitted in .ARM.exidx or .ARM.extab. +@ Besides, there should be two entries in .ARM.exidx section. + + .syntax unified + + .text + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .fnend + + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + bx lr + .fnend + + +@------------------------------------------------------------------------------- +@ Check the .text section. There should be two "bx lr" instructions. +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { +@ CHECK: Name: .text +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 1EFF2FE1 |../.../.| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the .ARM.exidx section. +@ There should be two entries (two words per entry.) +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx +@------------------------------------------------------------------------------- +@ The first word of each entry should be relocated to .text section. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .text 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr0 0x0 +@ CHECK: 0x8 R_ARM_PREL31 .text 0x0 +@ CHECK: ] +@ CHECK: SectionData ( +@------------------------------------------------------------------------------- +@ The first word should be the offset to .text. The second word should be +@ 0xB0B0B080, which means compact model 0 is used (0x80) and the rest of the +@ word is filled with FINISH opcode (0xB0). +@------------------------------------------------------------------------------- +@ CHECK: 0000: 00000000 B0B0B080 04000000 B0B0B080 |................| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] + + + +@------------------------------------------------------------------------------- +@ Check the symbols "func1" and "func2". They should belong to .text section. +@------------------------------------------------------------------------------- +@ CHECK: Symbols [ +@ CHECK: Symbol { +@ CHECK: Name: func1 +@ CHECK: Section: .text (0x1) +@ CHECK: } +@ CHECK: Symbol { +@ CHECK: Name: func2 +@ CHECK: Section: .text (0x1) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-text-section.s b/test/MC/ARM/eh-directive-text-section.s new file mode 100644 index 0000000000..5ab1baa592 --- /dev/null +++ b/test/MC/ARM/eh-directive-text-section.s @@ -0,0 +1,82 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the .fnstart directive and the .fnend directive. + +@ The .fnstart directive and .fnend directive should create an entry in +@ exception handling table. For example, if the function is defined in .text +@ section, then there should be an entry in .ARM.exidx section. + + .syntax unified + + .text + .globl func1 + .align 2 + .type func1,%function + .fnstart +func1: + bx lr + .fnend + + + +@------------------------------------------------------------------------------- +@ Check the .text section. +@------------------------------------------------------------------------------- +@ CHECK: Sections [ +@ CHECK: Section { + +@------------------------------------------------------------------------------- +@ Check the index of .text section. This will be used in .ARM.exidx. +@------------------------------------------------------------------------------- +@ CHECK: Index: 1 +@ CHECK: Name: .text +@ CHECK: Type: SHT_PROGBITS (0x1) +@ CHECK: Flags [ (0x6) +@ CHECK: SHF_ALLOC (0x2) +@ CHECK: SHF_EXECINSTR (0x4) +@ CHECK: ] +@ CHECK: SectionData ( +@ CHECK: 0000: 1EFF2FE1 |../.| +@ CHECK: ) +@ CHECK: } + + +@------------------------------------------------------------------------------- +@ Check the name of the EXIDX section. For the function in the .text section, +@ this should be .ARM.exidx. It is incorrect to see .ARM.exidx.text here. +@------------------------------------------------------------------------------- +@ CHECK: Section { +@ CHECK: Name: .ARM.exidx +@ CHECK: Type: SHT_ARM_EXIDX (0x70000001) +@ CHECK: Flags [ (0x82) +@ CHECK: SHF_ALLOC (0x2) +@ CHECK: SHF_LINK_ORDER (0x80) +@ CHECK: ] + +@------------------------------------------------------------------------------- +@ Check the linked section of the EXIDX section. This should be the index +@ of the .text section. +@------------------------------------------------------------------------------- +@ CHECK: Link: 1 + +@------------------------------------------------------------------------------- +@ The first word should be relocated to the code address in .text section. +@ Besides, since this function is using compact model 0, thus we have to +@ add an relocation to __aeabi_unwind_cpp_pr0. +@------------------------------------------------------------------------------- +@ CHECK: Relocations [ +@ CHECK: 0x0 R_ARM_PREL31 .text 0x0 +@ CHECK: 0x0 R_ARM_NONE __aeabi_unwind_cpp_pr0 0x0 +@ CHECK: ] + +@------------------------------------------------------------------------------- +@ The first word should be the offset to .text. The second word should be +@ 0xB0B0B080, which means compact model 0 is used (0x80) and the rest of the +@ word is filled with FINISH opcode (0xB0). +@------------------------------------------------------------------------------- +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B0B0B080 |........| +@ CHECK: ) +@ CHECK: } +@ CHECK: ] diff --git a/test/MC/ARM/eh-directive-vsave-diagnostics.s b/test/MC/ARM/eh-directive-vsave-diagnostics.s new file mode 100644 index 0000000000..62787f37c2 --- /dev/null +++ b/test/MC/ARM/eh-directive-vsave-diagnostics.s @@ -0,0 +1,41 @@ +@ RUN: not llvm-mc -triple=armv7-unknown-linux-gnueabi < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK < %t %s + +@ Check the diagnostics for .vsave directive + +@ .vsave directive should always come after .fnstart directive +@ and before .handlerdata directive. + + .syntax unified + .text + +@------------------------------------------------------------------------------- +@ TEST1: .vsave before .fnstart +@------------------------------------------------------------------------------- + .globl func1 + .align 2 + .type func1,%function + .vsave {d0, d1, d2, d3} +@ CHECK: error: .fnstart must precede .save or .vsave directives +@ CHECK: .vsave {d0, d1, d2, d3} +@ CHECK: ^ + .fnstart +func1: + .fnend + + + +@------------------------------------------------------------------------------- +@ TEST2: .vsave after .handlerdata +@------------------------------------------------------------------------------- + .globl func2 + .align 2 + .type func2,%function + .fnstart +func2: + .handlerdata + .vsave {d0, d1, d2, d3} +@ CHECK: error: .save or .vsave must precede .handlerdata directive +@ CHECK: .vsave {d0, d1, d2, d3} +@ CHECK: ^ + .fnend diff --git a/test/MC/ARM/eh-directive-vsave.s b/test/MC/ARM/eh-directive-vsave.s new file mode 100644 index 0000000000..c9b78d7e27 --- /dev/null +++ b/test/MC/ARM/eh-directive-vsave.s @@ -0,0 +1,130 @@ +@ RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -s -sd -sr | FileCheck %s + +@ Check the .vsave directive + +@ The .vsave directive records the VFP registers which are pushed to the +@ stack. There are two different opcodes: +@ +@ 0xC800: pop d[(16+x+y):(16+x)] @ d[16+x+y]-d[16+x] must be consecutive +@ 0xC900: pop d[(x+y):x] @ d[x+y]-d[x] must be consecutive + + + .syntax unified + +@------------------------------------------------------------------------------- +@ TEST1 +@------------------------------------------------------------------------------- + .section .TEST1 + .globl func1a + .align 2 + .type func1a,%function + .fnstart +func1a: + .vsave {d0} + vpush {d0} + vpop {d0} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1b + .align 2 + .type func1b,%function + .fnstart +func1b: + .vsave {d0, d1, d2, d3} + vpush {d0, d1, d2, d3} + vpop {d0, d1, d2, d3} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1c + .align 2 + .type func1c,%function + .fnstart +func1c: + .vsave {d0, d1, d2, d3, d4, d5, d6, d7} + vpush {d0, d1, d2, d3, d4, d5, d6, d7} + vpop {d0, d1, d2, d3, d4, d5, d6, d7} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func1d + .align 2 + .type func1d,%function + .fnstart +func1d: + .vsave {d2, d3, d4, d5, d6, d7} + vpush {d2, d3, d4, d5, d6, d7} + vpop {d2, d3, d4, d5, d6, d7} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST1 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B000C900 00000000 B003C900 |................| +@ CHECK: 0010: 00000000 B007C900 00000000 B025C900 |.............%..| +@ CHECK: ) +@ CHECK: } + + + +@------------------------------------------------------------------------------- +@ TEST2 +@------------------------------------------------------------------------------- + .section .TEST2 + .globl func2a + .align 2 + .type func2a,%function + .fnstart +func2a: + .vsave {d16} + vpush {d16} + vpop {d16} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2b + .align 2 + .type func2b,%function + .fnstart +func2b: + .vsave {d16, d17, d18, d19} + vpush {d16, d17, d18, d19} + vpop {d16, d17, d18, d19} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + + .globl func2c + .align 2 + .type func2c,%function + .fnstart +func2c: + .vsave {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} + vpush {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} + vpop {d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31} + bx lr + .personality __gxx_personality_v0 + .handlerdata + .fnend + +@ CHECK: Section { +@ CHECK: Name: .ARM.extab.TEST2 +@ CHECK: SectionData ( +@ CHECK: 0000: 00000000 B000C800 00000000 B003C800 |................| +@ CHECK: 0010: 00000000 B00FC800 |........| +@ CHECK: ) +@ CHECK: } -- cgit v1.2.3 From 7159a307b9a0a53f9a33e416d24b9308ef547d97 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 10 May 2013 16:26:37 +0000 Subject: InstCombine: Don't claim to be able to evaluate any shl in a zexted type. The shift amount may be larger than the type leading to undefined behavior. Limit the transform to constant shift amounts. While there update the bits to clear in the result which may enable additional optimizations. PR15959. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181604 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineCasts.cpp | 12 ++++++++++- test/Transforms/InstCombine/cast.ll | 28 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 2ee1278d23..361acdde81 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -677,7 +677,6 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) { case Instruction::Add: case Instruction::Sub: case Instruction::Mul: - case Instruction::Shl: if (!CanEvaluateZExtd(I->getOperand(0), Ty, BitsToClear) || !CanEvaluateZExtd(I->getOperand(1), Ty, Tmp)) return false; @@ -701,6 +700,17 @@ static bool CanEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear) { // Otherwise, we don't know how to analyze this BitsToClear case yet. return false; + case Instruction::Shl: + // We can promote shl(x, cst) if we can promote x. Since shl overwrites the + // upper bits we can reduce BitsToClear by the shift amount. + if (ConstantInt *Amt = dyn_cast(I->getOperand(1))) { + if (!CanEvaluateZExtd(I->getOperand(0), Ty, BitsToClear)) + return false; + uint64_t ShiftAmt = Amt->getZExtValue(); + BitsToClear = ShiftAmt < BitsToClear ? BitsToClear - ShiftAmt : 0; + return true; + } + return false; case Instruction::LShr: // We can promote lshr(x, cst) if we can promote x. This requires the // ultimate 'and' to clear out the high zero bits we're clearing out though. diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index de738bb7c0..ff2c0a9289 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -898,3 +898,31 @@ define double @test81(double *%p, float %f) { %l = load double* %r ret double %l } + +define i64 @test82(i64 %A) nounwind { + %B = trunc i64 %A to i32 + %C = lshr i32 %B, 8 + %D = shl i32 %C, 9 + %E = zext i32 %D to i64 + ret i64 %E + +; CHECK: @test82 +; CHECK-NEXT: [[REG:%[0-9]*]] = shl i64 %A, 1 +; CHECK-NEXT: %E = and i64 [[REG]], 4294966784 +; CHECK-NEXT: ret i64 %E +} + +; PR15959 +define i64 @test83(i16 %a, i64 %k) { + %conv = sext i16 %a to i32 + %sub = add nsw i64 %k, -1 + %sh_prom = trunc i64 %sub to i32 + %shl = shl i32 %conv, %sh_prom + %sh_prom1 = zext i32 %shl to i64 + ret i64 %sh_prom1 + +; CHECK: @test83 +; CHECK: %sub = add nsw i64 %k, 4294967295 +; CHECK: %sh_prom = trunc i64 %sub to i32 +; CHECK: %shl = shl i32 %conv, %sh_prom +} -- cgit v1.2.3 From 3a0d00eef992daafecc4d96fa716f851d8c9059a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 10 May 2013 16:53:12 +0000 Subject: Remove unused function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181606 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonRegisterInfo.cpp | 10 ---------- lib/Target/Hexagon/HexagonRegisterInfo.h | 1 - 2 files changed, 11 deletions(-) diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/lib/Target/Hexagon/HexagonRegisterInfo.cpp index d8b4e2fcb3..d59d7d3382 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.cpp +++ b/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -295,16 +295,6 @@ unsigned HexagonRegisterInfo::getStackRegister() const { return Hexagon::R29; } -void HexagonRegisterInfo::getInitialFrameState(std::vector - &Moves) const -{ - // VirtualFP = (R30 + #0). - unsigned FPReg = getFrameRegister(); - MachineLocation Dst(MachineLocation::VirtualFP); - MachineLocation Src(FPReg, 0); - Moves.push_back(MachineMove(0, Dst, Src)); -} - unsigned HexagonRegisterInfo::getEHExceptionRegister() const { llvm_unreachable("What is the exception register"); } diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.h b/lib/Target/Hexagon/HexagonRegisterInfo.h index 8a3f94a3fd..c74155ac3b 100644 --- a/lib/Target/Hexagon/HexagonRegisterInfo.h +++ b/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -78,7 +78,6 @@ struct HexagonRegisterInfo : public HexagonGenRegisterInfo { unsigned getRARegister() const; unsigned getFrameRegister(const MachineFunction &MF) const; unsigned getFrameRegister() const; - void getInitialFrameState(std::vector &Moves) const; unsigned getStackRegister() const; // Exception handling queries. -- cgit v1.2.3 From 2e24e19cacacd4eea346b914124ffc3acadbd72e Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Fri, 10 May 2013 17:15:51 +0000 Subject: Better output for long help strings for command-line options. Summary: This patch allows using \n inside long help strings for command-line options, so that all lines are equally indented. This is not a perfect solution, as we don't (and probably don't want to) know about terminal width, but it allows to format long help strings somehow readable without manually padding them with spaces. A motivating example is -help output from clang-format (source code in tools/clang-format/ClangFormat.cpp, see cl options offset, length, style, and dump-config). Reviewers: atrick, alexfh Reviewed By: alexfh CC: llvm-commits, rafael Differential Revision: http://llvm-reviews.chandlerc.com/D779 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181608 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandLine.rst | 3 ++- lib/Support/CommandLine.cpp | 24 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst index 9b77a98908..6535551844 100644 --- a/docs/CommandLine.rst +++ b/docs/CommandLine.rst @@ -930,7 +930,8 @@ This section describes the basic attributes that you can specify on options. .. _cl::desc(...): * The **cl::desc** attribute specifies a description for the option to be - shown in the ``-help`` output for the program. + shown in the ``-help`` output for the program. This attribute supports + multi-line descriptions with lines separated by '\n'. .. _cl::value_desc: diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 18d3db527b..f09705e69a 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -913,11 +913,20 @@ size_t alias::getOptionWidth() const { return std::strlen(ArgStr)+6; } +static void printHelpStr(StringRef HelpStr, size_t Indent, + size_t FirstLineIndentedBy) { + std::pair Split = HelpStr.split('\n'); + outs().indent(Indent - FirstLineIndentedBy) << " - " << Split.first << "\n"; + while (!Split.second.empty()) { + Split = Split.second.split('\n'); + outs().indent(Indent) << Split.first << "\n"; + } +} + // Print out the option for the alias. void alias::printOptionInfo(size_t GlobalWidth) const { - size_t L = std::strlen(ArgStr); outs() << " -" << ArgStr; - outs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; + printHelpStr(HelpStr, GlobalWidth, std::strlen(ArgStr) + 6); } //===----------------------------------------------------------------------===// @@ -946,7 +955,7 @@ void basic_parser_impl::printOptionInfo(const Option &O, if (const char *ValName = getValueName()) outs() << "=<" << getValueStr(O, ValName) << '>'; - outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n'; + printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O)); } void basic_parser_impl::printOptionName(const Option &O, @@ -1087,9 +1096,8 @@ size_t generic_parser_base::getOptionWidth(const Option &O) const { void generic_parser_base::printOptionInfo(const Option &O, size_t GlobalWidth) const { if (O.hasArgStr()) { - size_t L = std::strlen(O.ArgStr); outs() << " -" << O.ArgStr; - outs().indent(GlobalWidth-L-6) << " - " << O.HelpStr << '\n'; + printHelpStr(O.HelpStr, GlobalWidth, std::strlen(O.ArgStr) + 6); for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { size_t NumSpaces = GlobalWidth-strlen(getOption(i))-8; @@ -1100,9 +1108,9 @@ void generic_parser_base::printOptionInfo(const Option &O, if (O.HelpStr[0]) outs() << " " << O.HelpStr << '\n'; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - size_t L = std::strlen(getOption(i)); - outs() << " -" << getOption(i); - outs().indent(GlobalWidth-L-8) << " - " << getDescription(i) << '\n'; + const char *Option = getOption(i); + outs() << " -" << Option; + printHelpStr(getDescription(i), GlobalWidth, std::strlen(Option) + 8); } } } -- cgit v1.2.3 From 50be71d18262ac9f27daef14b429d8132923f1df Mon Sep 17 00:00:00 2001 From: Andrew Kaylor Date: Fri, 10 May 2013 17:58:41 +0000 Subject: Fix MCJITCAPITest.cpp unit test on Windows. MCJIT on Windows requires an explicit target triple with "-elf" appended to generate objects in ELF format. The common test framework was setting up this triple, but it wasn't passed to the C API in the test. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181614 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index d8cf6c592d..07ea1afe1a 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -48,6 +48,8 @@ TEST_F(MCJITCAPITest, simple_function) { // Creates a function that returns 42, compiles it, and runs it. LLVMModuleRef module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(module, HostTriple.c_str()); LLVMValueRef function = LLVMAddFunction( module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); -- cgit v1.2.3 From 6e53180db120b30f600ac31611a9dd47ef7f4921 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 10 May 2013 18:16:59 +0000 Subject: Remove unused argument. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181618 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/TargetRegistry.h | 9 ++++----- lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp | 2 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 2 +- lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp | 2 +- lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h | 4 +--- lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp | 4 ++-- lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp | 2 +- lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp | 2 +- lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h | 3 +-- lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 2 +- lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h | 3 +-- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 4 ++-- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 2 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h | 2 +- lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 2 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 2 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h | 3 +-- lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 2 +- lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h | 3 +-- lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp | 4 ++-- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 2 +- lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp | 2 +- lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h | 2 +- lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 4 ++-- 24 files changed, 31 insertions(+), 38 deletions(-) diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index b06676d4d2..5bfb8ad41d 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -70,8 +70,7 @@ namespace llvm { typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); - typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const Target &T, - StringRef TT); + typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(StringRef TT); typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, CodeModel::Model CM, @@ -269,7 +268,7 @@ namespace llvm { MCAsmInfo *createMCAsmInfo(StringRef Triple) const { if (!MCAsmInfoCtorFn) return 0; - return MCAsmInfoCtorFn(*this, Triple); + return MCAsmInfoCtorFn(Triple); } /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. @@ -804,8 +803,8 @@ namespace llvm { TargetRegistry::RegisterMCAsmInfo(T, &Allocator); } private: - static MCAsmInfo *Allocator(const Target &T, StringRef TT) { - return new MCAsmInfoImpl(T, TT); + static MCAsmInfo *Allocator(StringRef TT) { + return new MCAsmInfoImpl(TT); } }; diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp index 819eeadb44..3435217bb2 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -57,7 +57,7 @@ static MCRegisterInfo *createAArch64MCRegisterInfo(StringRef Triple) { return X; } -static MCAsmInfo *createAArch64MCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createAArch64MCAsmInfo(StringRef TT) { Triple TheTriple(TT); MCAsmInfo *MAI = new AArch64ELFMCAsmInfo(); diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index f09fb5a94f..57239f8011 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -159,7 +159,7 @@ static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) { return X; } -static MCAsmInfo *createARMMCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createARMMCAsmInfo(StringRef TT) { Triple TheTriple(TT); if (TheTriple.isOSDarwin()) diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index 3deb8d1deb..495dbb97b0 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp @@ -15,7 +15,7 @@ using namespace llvm; -HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) { +HexagonMCAsmInfo::HexagonMCAsmInfo(StringRef TT) { Data16bitsDirective = "\t.half\t"; Data32bitsDirective = "\t.word\t"; Data64bitsDirective = 0; // .xword is only supported by V9. diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h index d336cd5be9..0b94d2141c 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h @@ -18,11 +18,9 @@ #include "llvm/MC/MCAsmInfo.h" namespace llvm { - class Target; - class HexagonMCAsmInfo : public MCAsmInfo { public: - explicit HexagonMCAsmInfo(const Target &T, StringRef TT); + explicit HexagonMCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 6b1d2d1619..273bc22b8e 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -54,8 +54,8 @@ static MCSubtargetInfo *createHexagonMCSubtargetInfo(StringRef TT, return X; } -static MCAsmInfo *createHexagonMCAsmInfo(const Target &T, StringRef TT) { - MCAsmInfo *MAI = new HexagonMCAsmInfo(T, TT); +static MCAsmInfo *createHexagonMCAsmInfo(StringRef TT) { + MCAsmInfo *MAI = new HexagonMCAsmInfo(TT); // VirtualFP = (R30 + #0). MachineLocation Dst(MachineLocation::VirtualFP); diff --git a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp index 380750d50f..ec76dba491 100644 --- a/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp +++ b/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp @@ -53,7 +53,7 @@ static MCSubtargetInfo *createMBlazeMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createMCAsmInfo(StringRef TT) { Triple TheTriple(TT); switch (TheTriple.getOS()) { default: diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp index 3c95760569..d213a45bb9 100644 --- a/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp @@ -17,7 +17,7 @@ using namespace llvm; void MSP430MCAsmInfo::anchor() { } -MSP430MCAsmInfo::MSP430MCAsmInfo(const Target &T, StringRef TT) { +MSP430MCAsmInfo::MSP430MCAsmInfo(StringRef TT) { PointerSize = CalleeSaveStackSlotSize = 2; PrivateGlobalPrefix = ".L"; diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h index e5c2fc283b..feb040d13b 100644 --- a/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h +++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h @@ -18,12 +18,11 @@ namespace llvm { class StringRef; - class Target; class MSP430MCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit MSP430MCAsmInfo(const Target &T, StringRef TT); + explicit MSP430MCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 5d4b32d305..33f6f9620e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -18,7 +18,7 @@ using namespace llvm; void MipsMCAsmInfo::anchor() { } -MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { +MipsMCAsmInfo::MipsMCAsmInfo(StringRef TT) { Triple TheTriple(TT); if ((TheTriple.getArch() == Triple::mips) || (TheTriple.getArch() == Triple::mips64)) diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index e1d878936f..772234eb71 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -18,12 +18,11 @@ namespace llvm { class StringRef; - class Target; class MipsMCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit MipsMCAsmInfo(const Target &T, StringRef TT); + explicit MipsMCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index be83b54b61..26694ffdac 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -93,8 +93,8 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) { - MCAsmInfo *MAI = new MipsMCAsmInfo(T, TT); +static MCAsmInfo *createMipsMCAsmInfo(StringRef TT) { + MCAsmInfo *MAI = new MipsMCAsmInfo(TT); MachineLocation Dst(MachineLocation::VirtualFP); MachineLocation Src(Mips::SP, 0); diff --git a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp index 459cd96cb0..fa33a75c61 100644 --- a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp +++ b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp @@ -27,7 +27,7 @@ Debug("debug-compile", cl::desc("Compile for debugging"), cl::Hidden, void NVPTXMCAsmInfo::anchor() {} -NVPTXMCAsmInfo::NVPTXMCAsmInfo(const Target &T, const StringRef &TT) { +NVPTXMCAsmInfo::NVPTXMCAsmInfo(const StringRef &TT) { Triple TheTriple(TT); if (TheTriple.getArch() == Triple::nvptx64) { PointerSize = CalleeSaveStackSlotSize = 8; diff --git a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h index 82097daa4a..7d1633f60d 100644 --- a/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h +++ b/lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h @@ -23,7 +23,7 @@ class StringRef; class NVPTXMCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit NVPTXMCAsmInfo(const Target &T, const StringRef &TT); + explicit NVPTXMCAsmInfo(const StringRef &TT); }; } // namespace llvm diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 2209f936ec..a01fa44a9a 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -58,7 +58,7 @@ static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createPPCMCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createPPCMCAsmInfo(StringRef TT) { Triple TheTriple(TT); bool isPPC64 = TheTriple.getArch() == Triple::ppc64; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp index 3d4bfdcd5e..5a52abee03 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -18,7 +18,7 @@ using namespace llvm; void SparcELFMCAsmInfo::anchor() { } -SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, StringRef TT) { +SparcELFMCAsmInfo::SparcELFMCAsmInfo(StringRef TT) { IsLittleEndian = false; Triple TheTriple(TT); if (TheTriple.getArch() == Triple::sparcv9) { diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h index f0e1354c21..621e8ffadf 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h @@ -18,12 +18,11 @@ namespace llvm { class StringRef; - class Target; class SparcELFMCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit SparcELFMCAsmInfo(const Target &T, StringRef TT); + explicit SparcELFMCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp index c96a0d4c67..9e27aa004a 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp @@ -13,7 +13,7 @@ using namespace llvm; -SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, StringRef TT) { +SystemZMCAsmInfo::SystemZMCAsmInfo(StringRef TT) { PointerSize = 8; CalleeSaveStackSlotSize = 8; IsLittleEndian = false; diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h index bac1bca381..d440787de5 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h @@ -14,12 +14,11 @@ #include "llvm/Support/Compiler.h" namespace llvm { -class Target; class StringRef; class SystemZMCAsmInfo : public MCAsmInfo { public: - explicit SystemZMCAsmInfo(const Target &T, StringRef TT); + explicit SystemZMCAsmInfo(StringRef TT); // Override MCAsmInfo; virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp index 49a7f47e7d..6844f92ec9 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -27,8 +27,8 @@ using namespace llvm; -static MCAsmInfo *createSystemZMCAsmInfo(const Target &T, StringRef TT) { - MCAsmInfo *MAI = new SystemZMCAsmInfo(T, TT); +static MCAsmInfo *createSystemZMCAsmInfo(StringRef TT) { + MCAsmInfo *MAI = new SystemZMCAsmInfo(TT); MachineLocation FPDst(MachineLocation::VirtualFP); MachineLocation FPSrc(SystemZ::R15D, -SystemZMC::CFAOffsetFromInitialSP); MAI->addInitialFrameState(0, FPDst, FPSrc); diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp index 5e84530cd7..226ebca8cb 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -263,7 +263,7 @@ static MCRegisterInfo *createX86MCRegisterInfo(StringRef TT) { return X; } -static MCAsmInfo *createX86MCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createX86MCAsmInfo(StringRef TT) { Triple TheTriple(TT); bool is64Bit = TheTriple.getArch() == Triple::x86_64; diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp index 1cfdbda003..6f4455117a 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp @@ -13,7 +13,7 @@ using namespace llvm; void XCoreMCAsmInfo::anchor() { } -XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, StringRef TT) { +XCoreMCAsmInfo::XCoreMCAsmInfo(StringRef TT) { SupportsDebugInformation = true; Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h index 076777541e..b5a9660d5f 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h @@ -23,7 +23,7 @@ namespace llvm { class XCoreMCAsmInfo : public MCAsmInfo { virtual void anchor(); public: - explicit XCoreMCAsmInfo(const Target &T, StringRef TT); + explicit XCoreMCAsmInfo(StringRef TT); }; } // namespace llvm diff --git a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp index c1773653f5..e38da34a81 100644 --- a/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp +++ b/lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.cpp @@ -51,8 +51,8 @@ static MCSubtargetInfo *createXCoreMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createXCoreMCAsmInfo(const Target &T, StringRef TT) { - MCAsmInfo *MAI = new XCoreMCAsmInfo(T, TT); +static MCAsmInfo *createXCoreMCAsmInfo(StringRef TT) { + MCAsmInfo *MAI = new XCoreMCAsmInfo(TT); // Initial state of the frame pointer is SP. MachineLocation Dst(MachineLocation::VirtualFP); -- cgit v1.2.3 From ffc49cbea41c08132587a3e622bb65191fa576a2 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 10 May 2013 18:24:17 +0000 Subject: [ms-inline asm] Fix a crasher when we fail on a direct match. The issue was that the MatchingInlineAsm and VariantID args to the MatchInstructionImpl function weren't being set properly. Specifically, when parsing intel syntax, the parser thought it was parsing inline assembly in the at&t dialect; that will never be the case. The crash was caused when the emitter tried to emit the instruction, but the operands weren't set. When parsing inline assembly we only set the opcode, not the operands, which is used to lookup the instruction descriptor. rdar://13854391 and PR15945 Also, this commit reverts r176036. Now that we're correctly parsing the intel syntax the pushad/popad don't match properly. I've reimplemented that fix using a MnemonicAlias. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181620 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 8 ++++---- lib/Target/X86/X86InstrInfo.td | 7 +++++-- test/MC/X86/x86_errors.s | 3 +++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 520c4c0048..019a670083 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -2308,25 +2308,25 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, unsigned Match1, Match2, Match3, Match4; Match1 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, - isParsingIntelSyntax()); + MatchingInlineAsm, isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match1 == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; Tmp[Base.size()] = Suffixes[1]; Match2 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, - isParsingIntelSyntax()); + MatchingInlineAsm, isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match2 == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; Tmp[Base.size()] = Suffixes[2]; Match3 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, - isParsingIntelSyntax()); + MatchingInlineAsm, isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match3 == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; Tmp[Base.size()] = Suffixes[3]; Match4 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, - isParsingIntelSyntax()); + MatchingInlineAsm, isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match4 == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 3380d8c64e..ad26bce01b 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -884,12 +884,12 @@ def PUSHF64 : I<0x9C, RawFrm, (outs), (ins), "pushfq", [], IIC_PUSH_F>, let Defs = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], Uses = [ESP], mayLoad = 1, neverHasSideEffects = 1, SchedRW = [WriteLoad] in { -def POPA32 : I<0x61, RawFrm, (outs), (ins), "popa{l|d}", [], IIC_POP_A>, +def POPA32 : I<0x61, RawFrm, (outs), (ins), "popa{l}", [], IIC_POP_A>, Requires<[In32BitMode]>; } let Defs = [ESP], Uses = [EDI, ESI, EBP, EBX, EDX, ECX, EAX, ESP], mayStore = 1, neverHasSideEffects = 1, SchedRW = [WriteStore] in { -def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pusha{l|d}", [], IIC_PUSH_A>, +def PUSHA32 : I<0x60, RawFrm, (outs), (ins), "pusha{l}", [], IIC_PUSH_A>, Requires<[In32BitMode]>; } @@ -1867,6 +1867,9 @@ def : MnemonicAlias<"pushf", "pushfl", "att">, Requires<[In32BitMode]>; def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; def : MnemonicAlias<"pushfd", "pushfl", "att">; +def : MnemonicAlias<"popad", "popa", "intel">, Requires<[In32BitMode]>; +def : MnemonicAlias<"pushad", "pusha", "intel">, Requires<[In32BitMode]>; + def : MnemonicAlias<"repe", "rep", "att">; def : MnemonicAlias<"repz", "rep", "att">; def : MnemonicAlias<"repnz", "repne", "att">; diff --git a/test/MC/X86/x86_errors.s b/test/MC/X86/x86_errors.s index 6e14d62fda..a974233d2f 100644 --- a/test/MC/X86/x86_errors.s +++ b/test/MC/X86/x86_errors.s @@ -28,3 +28,6 @@ lea (%rsp, %rbp, $4), %rax // rdar://10423777 // 64: error: index register is 32-bit, but base register is 64-bit movq (%rsi,%ecx),%xmm0 + +// 32: error: invalid operand for instruction +outb al, 4 -- cgit v1.2.3 From ed9fc9b8eef60e6305d1ba0fedd57e5b2bce3476 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 10 May 2013 18:31:42 +0000 Subject: Fix the R600 build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181621 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 2 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp b/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp index 2aae26aa12..f1c44df975 100644 --- a/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp +++ b/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp @@ -11,7 +11,7 @@ #include "AMDGPUMCAsmInfo.h" using namespace llvm; -AMDGPUMCAsmInfo::AMDGPUMCAsmInfo(const Target &T, StringRef &TT) : MCAsmInfo() { +AMDGPUMCAsmInfo::AMDGPUMCAsmInfo(StringRef &TT) : MCAsmInfo() { HasSingleParameterDotFile = false; WeakDefDirective = 0; //===------------------------------------------------------------------===// diff --git a/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h b/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h index 3ad0fa6824..485167b3da 100644 --- a/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h +++ b/lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h @@ -17,12 +17,11 @@ #include "llvm/MC/MCAsmInfo.h" namespace llvm { -class Target; class StringRef; class AMDGPUMCAsmInfo : public MCAsmInfo { public: - explicit AMDGPUMCAsmInfo(const Target &T, StringRef &TT); + explicit AMDGPUMCAsmInfo(StringRef &TT); const char* getDataASDirective(unsigned int Size, unsigned int AS) const; const MCSection* getNonexecutableStackSection(MCContext &CTX) const; }; -- cgit v1.2.3 From 1a35b8e2eb165624013d5a2eaf8b673f026999fc Mon Sep 17 00:00:00 2001 From: Jyotsna Verma Date: Fri, 10 May 2013 20:27:34 +0000 Subject: Hexagon: Fix switch cases in HexagonVLIWPacketizer.cpp. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181624 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/Hexagon.td | 6 +- lib/Target/Hexagon/HexagonFrameLowering.cpp | 54 ++- lib/Target/Hexagon/HexagonInstrFormats.td | 2 + lib/Target/Hexagon/HexagonInstrInfo.cpp | 147 ++----- lib/Target/Hexagon/HexagonInstrInfo.h | 2 + lib/Target/Hexagon/HexagonInstrInfoV4.td | 87 +++-- lib/Target/Hexagon/HexagonInstrInfoV5.td | 23 +- lib/Target/Hexagon/HexagonVLIWPacketizer.cpp | 552 +-------------------------- test/CodeGen/Hexagon/pred-gp.ll | 28 ++ 9 files changed, 198 insertions(+), 703 deletions(-) create mode 100644 test/CodeGen/Hexagon/pred-gp.ll diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td index 9b3a64316a..6c7f963b53 100644 --- a/lib/Target/Hexagon/Hexagon.td +++ b/lib/Target/Hexagon/Hexagon.td @@ -126,9 +126,9 @@ def getPredNewOpcode : InstrMapping { def getNewValueOpcode : InstrMapping { let FilterClass = "NewValueRel"; let RowFields = ["BaseOpcode", "PredSense", "PNewValue"]; - let ColFields = ["isNVStore"]; - let KeyCol = ["0"]; - let ValueCols = [["1"]]; + let ColFields = ["NValueST"]; + let KeyCol = ["false"]; + let ValueCols = [["true"]]; } def getBasedWithImmOffset : InstrMapping { diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index de993ee875..77ad70dd6c 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -174,30 +174,56 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = prior(MBB.end()); DebugLoc dl = MBBI->getDebugLoc(); // - // Only insert deallocframe if we need to. + // Only insert deallocframe if we need to. Also at -O0. See comment + // in emitPrologue above. // - if (hasFP(MF)) { + if (hasFP(MF) || MF.getTarget().getOptLevel() == CodeGenOpt::None) { MachineBasicBlock::iterator MBBI = prior(MBB.end()); MachineBasicBlock::iterator MBBI_end = MBB.end(); - // - // For Hexagon, we don't need the frame size. - // - MachineFrameInfo *MFI = MF.getFrameInfo(); - int NumBytes = (int) MFI->getStackSize(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); - + // Handle EH_RETURN. + if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) { + MachineOperand &OffsetReg = MBBI->getOperand(0); + assert(OffsetReg.isReg() && "Offset should be in register!"); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr), + Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28); + return; + } // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher // versions. if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPret && !DisableDeallocRet) { - // Remove jumpr node. - MBB.erase(MBBI); + // Check for RESTORE_DEALLOC_RET_JMP_V4 call. Don't emit an extra DEALLOC + // instruction if we encounter it. + MachineBasicBlock::iterator BeforeJMPR = + MBB.begin() == MBBI ? MBBI : prior(MBBI); + if (BeforeJMPR != MBBI && + BeforeJMPR->getOpcode() == Hexagon::RESTORE_DEALLOC_RET_JMP_V4) { + // Remove the JMPR node. + MBB.erase(MBBI); + return; + } + // Add dealloc_return. - BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) - .addImm(NumBytes); - } else { // Add deallocframe for V2 and V3. - BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)); + // Transfer the function live-out registers. + MIB->copyImplicitOps(*MBB.getParent(), &*MBBI); + // Remove the JUMPR node. + MBB.erase(MBBI); + } else { // Add deallocframe for V2 and V3, and V4 tail calls. + // Check for RESTORE_DEALLOC_BEFORE_TAILCALL_V4. We don't need an extra + // DEALLOCFRAME instruction after it. + MachineBasicBlock::iterator Term = MBB.getFirstTerminator(); + MachineBasicBlock::iterator I = + Term == MBB.begin() ? MBB.end() : prior(Term); + if (I != MBB.end() && + I->getOpcode() == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4) + return; + + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); } } } diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td index f97143ff01..e71386ada2 100644 --- a/lib/Target/Hexagon/HexagonInstrFormats.td +++ b/lib/Target/Hexagon/HexagonInstrFormats.td @@ -158,6 +158,7 @@ class InstHexagon pattern, string CextOpcode = ""; string PredSense = ""; string PNewValue = ""; + string NValueST = ""; // Set to "true" for new-value stores. string InputType = ""; // Input is "imm" or "reg" type. string isMEMri = "false"; // Set to "true" for load/store with MEMri operand. string isFloat = "false"; // Set to "true" for the floating-point load/store. @@ -166,6 +167,7 @@ class InstHexagon pattern, let PredSense = !if(isPredicated, !if(isPredicatedFalse, "false", "true"), ""); let PNewValue = !if(isPredicatedNew, "new", ""); + let NValueST = !if(isNVStore, "true", "false"); // *** Must match MCTargetDesc/HexagonBaseInfo.h *** } diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp index 469e8021fa..7dec127453 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -630,111 +630,6 @@ bool HexagonInstrInfo::isBranch (const MachineInstr *MI) const { return MI->getDesc().isBranch(); } -bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { - switch (MI->getOpcode()) { - default: return false; - // Store Byte - case Hexagon::STrib_nv_V4: - case Hexagon::STrib_indexed_nv_V4: - case Hexagon::STrib_indexed_shl_nv_V4: - case Hexagon::STrib_shl_nv_V4: - case Hexagon::STb_GP_nv_V4: - case Hexagon::POST_STbri_nv_V4: - case Hexagon::STrib_cPt_nv_V4: - case Hexagon::STrib_cdnPt_nv_V4: - case Hexagon::STrib_cNotPt_nv_V4: - case Hexagon::STrib_cdnNotPt_nv_V4: - case Hexagon::STrib_indexed_cPt_nv_V4: - case Hexagon::STrib_indexed_cdnPt_nv_V4: - case Hexagon::STrib_indexed_cNotPt_nv_V4: - case Hexagon::STrib_indexed_cdnNotPt_nv_V4: - case Hexagon::STrib_indexed_shl_cPt_nv_V4: - case Hexagon::STrib_indexed_shl_cdnPt_nv_V4: - case Hexagon::STrib_indexed_shl_cNotPt_nv_V4: - case Hexagon::STrib_indexed_shl_cdnNotPt_nv_V4: - case Hexagon::POST_STbri_cPt_nv_V4: - case Hexagon::POST_STbri_cdnPt_nv_V4: - case Hexagon::POST_STbri_cNotPt_nv_V4: - case Hexagon::POST_STbri_cdnNotPt_nv_V4: - case Hexagon::STb_GP_cPt_nv_V4: - case Hexagon::STb_GP_cNotPt_nv_V4: - case Hexagon::STb_GP_cdnPt_nv_V4: - case Hexagon::STb_GP_cdnNotPt_nv_V4: - case Hexagon::STrib_abs_nv_V4: - case Hexagon::STrib_abs_cPt_nv_V4: - case Hexagon::STrib_abs_cdnPt_nv_V4: - case Hexagon::STrib_abs_cNotPt_nv_V4: - case Hexagon::STrib_abs_cdnNotPt_nv_V4: - - // Store Halfword - case Hexagon::STrih_nv_V4: - case Hexagon::STrih_indexed_nv_V4: - case Hexagon::STrih_indexed_shl_nv_V4: - case Hexagon::STrih_shl_nv_V4: - case Hexagon::STh_GP_nv_V4: - case Hexagon::POST_SThri_nv_V4: - case Hexagon::STrih_cPt_nv_V4: - case Hexagon::STrih_cdnPt_nv_V4: - case Hexagon::STrih_cNotPt_nv_V4: - case Hexagon::STrih_cdnNotPt_nv_V4: - case Hexagon::STrih_indexed_cPt_nv_V4: - case Hexagon::STrih_indexed_cdnPt_nv_V4: - case Hexagon::STrih_indexed_cNotPt_nv_V4: - case Hexagon::STrih_indexed_cdnNotPt_nv_V4: - case Hexagon::STrih_indexed_shl_cPt_nv_V4: - case Hexagon::STrih_indexed_shl_cdnPt_nv_V4: - case Hexagon::STrih_indexed_shl_cNotPt_nv_V4: - case Hexagon::STrih_indexed_shl_cdnNotPt_nv_V4: - case Hexagon::POST_SThri_cPt_nv_V4: - case Hexagon::POST_SThri_cdnPt_nv_V4: - case Hexagon::POST_SThri_cNotPt_nv_V4: - case Hexagon::POST_SThri_cdnNotPt_nv_V4: - case Hexagon::STh_GP_cPt_nv_V4: - case Hexagon::STh_GP_cNotPt_nv_V4: - case Hexagon::STh_GP_cdnPt_nv_V4: - case Hexagon::STh_GP_cdnNotPt_nv_V4: - case Hexagon::STrih_abs_nv_V4: - case Hexagon::STrih_abs_cPt_nv_V4: - case Hexagon::STrih_abs_cdnPt_nv_V4: - case Hexagon::STrih_abs_cNotPt_nv_V4: - case Hexagon::STrih_abs_cdnNotPt_nv_V4: - - // Store Word - case Hexagon::STriw_nv_V4: - case Hexagon::STriw_indexed_nv_V4: - case Hexagon::STriw_indexed_shl_nv_V4: - case Hexagon::STriw_shl_nv_V4: - case Hexagon::STw_GP_nv_V4: - case Hexagon::POST_STwri_nv_V4: - case Hexagon::STriw_cPt_nv_V4: - case Hexagon::STriw_cdnPt_nv_V4: - case Hexagon::STriw_cNotPt_nv_V4: - case Hexagon::STriw_cdnNotPt_nv_V4: - case Hexagon::STriw_indexed_cPt_nv_V4: - case Hexagon::STriw_indexed_cdnPt_nv_V4: - case Hexagon::STriw_indexed_cNotPt_nv_V4: - case Hexagon::STriw_indexed_cdnNotPt_nv_V4: - case Hexagon::STriw_indexed_shl_cPt_nv_V4: - case Hexagon::STriw_indexed_shl_cdnPt_nv_V4: - case Hexagon::STriw_indexed_shl_cNotPt_nv_V4: - case Hexagon::STriw_indexed_shl_cdnNotPt_nv_V4: - case Hexagon::POST_STwri_cPt_nv_V4: - case Hexagon::POST_STwri_cdnPt_nv_V4: - case Hexagon::POST_STwri_cNotPt_nv_V4: - case Hexagon::POST_STwri_cdnNotPt_nv_V4: - case Hexagon::STw_GP_cPt_nv_V4: - case Hexagon::STw_GP_cNotPt_nv_V4: - case Hexagon::STw_GP_cdnPt_nv_V4: - case Hexagon::STw_GP_cdnNotPt_nv_V4: - case Hexagon::STriw_abs_nv_V4: - case Hexagon::STriw_abs_cPt_nv_V4: - case Hexagon::STriw_abs_cdnPt_nv_V4: - case Hexagon::STriw_abs_cNotPt_nv_V4: - case Hexagon::STriw_abs_cdnNotPt_nv_V4: - return true; - } -} - bool HexagonInstrInfo::isNewValueInst(const MachineInstr *MI) const { if (isNewValueJump(MI)) return true; @@ -862,6 +757,18 @@ unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { } } +// New Value Store instructions. +bool HexagonInstrInfo::isNewValueStore(const MachineInstr *MI) const { + const uint64_t F = MI->getDesc().TSFlags; + + return ((F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask); +} + +bool HexagonInstrInfo::isNewValueStore(unsigned Opcode) const { + const uint64_t F = get(Opcode).TSFlags; + + return ((F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask); +} int HexagonInstrInfo:: getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { @@ -1304,6 +1211,8 @@ isValidAutoIncImm(const EVT VT, const int Offset) const { bool HexagonInstrInfo:: isMemOp(const MachineInstr *MI) const { +// return MI->getDesc().mayLoad() && MI->getDesc().mayStore(); + switch (MI->getOpcode()) { default: return false; @@ -1611,6 +1520,34 @@ bool HexagonInstrInfo::isDotNewInst (const MachineInstr* MI) const { (isPredicated(MI) && isPredicatedNew(MI))); } +// Return the new value instruction for a given store. +int HexagonInstrInfo::GetDotNewOp(const MachineInstr* MI) const { + int NVOpcode = Hexagon::getNewValueOpcode(MI->getOpcode()); + if (NVOpcode >= 0) // Valid new-value store instruction. + return NVOpcode; + + switch (MI->getOpcode()) { + default: llvm_unreachable("Unknown .new type"); + // store new value byte + case Hexagon::STrib_shl_V4: + return Hexagon::STrib_shl_nv_V4; + + case Hexagon::STrih_shl_V4: + return Hexagon::STrih_shl_nv_V4; + + case Hexagon::STriw_f: + return Hexagon::STriw_nv_V4; + + case Hexagon::STriw_indexed_f: + return Hexagon::STriw_indexed_nv_V4; + + case Hexagon::STriw_shl_V4: + return Hexagon::STriw_shl_nv_V4; + + } + return 0; +} + // Return .new predicate version for an instruction. int HexagonInstrInfo::GetDotNewPredOp(MachineInstr *MI, const MachineBranchProbabilityInfo diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h index 2becc02570..f3297fbd33 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/lib/Target/Hexagon/HexagonInstrInfo.h @@ -185,6 +185,7 @@ public: bool isNewValueInst(const MachineInstr* MI) const; bool isNewValue(const MachineInstr* MI) const; bool isDotNewInst(const MachineInstr* MI) const; + int GetDotNewOp(const MachineInstr* MI) const; int GetDotNewPredOp(MachineInstr *MI, const MachineBranchProbabilityInfo *MBPI) const; @@ -194,6 +195,7 @@ public: bool isExtended(const MachineInstr* MI) const; bool isPostIncrement(const MachineInstr* MI) const; bool isNewValueStore(const MachineInstr* MI) const; + bool isNewValueStore(unsigned Opcode) const; bool isNewValueJump(const MachineInstr* MI) const; bool isNewValueJumpCandidate(const MachineInstr *MI) const; diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td index c7f4edfe67..022a7f6136 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV4.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -2564,8 +2564,9 @@ def NTSTBIT_ri : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), //Deallocate frame and return. // dealloc_return let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicable = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { - def DEALLOC_RET_V4 : NVInst_V4<(outs), (ins i32imm:$amt1), + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1 in { +let validSubTargets = HasV4SubT in + def DEALLOC_RET_V4 : LD0Inst<(outs), (ins), "dealloc_return", []>, Requires<[HasV4T]>; @@ -2574,9 +2575,10 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicable = 1, // Restore registers and dealloc return function call. let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, Defs = [R29, R30, R31, PC] in { +let validSubTargets = HasV4SubT in def RESTORE_DEALLOC_RET_JMP_V4 : JInst<(outs), (ins calltarget:$dst), - "jump $dst // Restore_and_dealloc_return", + "jump $dst", []>, Requires<[HasV4T]>; } @@ -2584,9 +2586,10 @@ let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, // Restore registers and dealloc frame before a tail call. let isCall = 1, isBarrier = 1, Defs = [R29, R30, R31, PC] in { +let validSubTargets = HasV4SubT in def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : JInst<(outs), (ins calltarget:$dst), - "call $dst // Restore_and_dealloc_before_tailcall", + "call $dst", []>, Requires<[HasV4T]>; } @@ -2603,10 +2606,11 @@ let isCall = 1, isBarrier = 1, // if (Ps) dealloc_return let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, isPredicated = 1 in { - def DEALLOC_RET_cPt_V4 : NVInst_V4<(outs), - (ins PredRegs:$src1, i32imm:$amt1), +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cPt_V4 : LD0Inst<(outs), + (ins PredRegs:$src1), "if ($src1) dealloc_return", []>, Requires<[HasV4T]>; @@ -2614,10 +2618,10 @@ let isReturn = 1, isTerminator = 1, // if (!Ps) dealloc_return let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, - isPredicated = 1 in { - def DEALLOC_RET_cNotPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, - i32imm:$amt1), + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, + isPredicated = 1, isPredicatedFalse = 1 in { +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cNotPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), "if (!$src1) dealloc_return", []>, Requires<[HasV4T]>; @@ -2625,10 +2629,10 @@ let isReturn = 1, isTerminator = 1, // if (Ps.new) dealloc_return:nt let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, isPredicated = 1 in { - def DEALLOC_RET_cdnPnt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, - i32imm:$amt1), +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), "if ($src1.new) dealloc_return:nt", []>, Requires<[HasV4T]>; @@ -2636,10 +2640,10 @@ let isReturn = 1, isTerminator = 1, // if (!Ps.new) dealloc_return:nt let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, - isPredicated = 1 in { - def DEALLOC_RET_cNotdnPnt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, - i32imm:$amt1), + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, + isPredicated = 1, isPredicatedFalse = 1 in { +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cNotdnPnt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), "if (!$src1.new) dealloc_return:nt", []>, Requires<[HasV4T]>; @@ -2647,21 +2651,21 @@ let isReturn = 1, isTerminator = 1, // if (Ps.new) dealloc_return:t let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, isPredicated = 1 in { - def DEALLOC_RET_cdnPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, - i32imm:$amt1), +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), "if ($src1.new) dealloc_return:t", []>, Requires<[HasV4T]>; } -// if (!Ps.new) dealloc_return:nt +// if (!Ps.new) dealloc_return:nt let isReturn = 1, isTerminator = 1, - Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1, - isPredicated = 1 in { - def DEALLOC_RET_cNotdnPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, - i32imm:$amt1), + Defs = [R29, R30, R31, PC], Uses = [R30], neverHasSideEffects = 1, + isPredicated = 1, isPredicatedFalse = 1 in { +let validSubTargets = HasV4SubT in + def DEALLOC_RET_cNotdnPt_V4 : LD0Inst<(outs), (ins PredRegs:$src1), "if (!$src1.new) dealloc_return:t", []>, Requires<[HasV4T]>; @@ -3063,37 +3067,42 @@ def : Pat<(HexagonCONST32_GP tblockaddress:$src1), (TFRI_V4 tblockaddress:$src1)>, Requires<[HasV4T]>; -let AddedComplexity=50, neverHasSideEffects = 1, isPredicated = 1 in +let isExtended = 1, opExtendable = 2, AddedComplexity=50, +neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cPt_V4 : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$src2), - "if($src1) $dst = ##$src2", + (ins PredRegs:$src1, s16Ext:$src2), + "if($src1) $dst = #$src2", []>, Requires<[HasV4T]>; -let AddedComplexity=50, neverHasSideEffects = 1, isPredicated = 1 in +let isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1, +neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cNotPt_V4 : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$src2), - "if(!$src1) $dst = ##$src2", + (ins PredRegs:$src1, s16Ext:$src2), + "if(!$src1) $dst = #$src2", []>, Requires<[HasV4T]>; -let AddedComplexity=50, neverHasSideEffects = 1, isPredicated = 1 in +let isExtended = 1, opExtendable = 2, AddedComplexity=50, +neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cdnPt_V4 : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$src2), - "if($src1.new) $dst = ##$src2", + (ins PredRegs:$src1, s16Ext:$src2), + "if($src1.new) $dst = #$src2", []>, Requires<[HasV4T]>; -let AddedComplexity=50, neverHasSideEffects = 1, isPredicated = 1 in +let isExtended = 1, opExtendable = 2, AddedComplexity=50, isPredicatedFalse = 1, +neverHasSideEffects = 1, isPredicated = 1, validSubTargets = HasV4SubT in def TFRI_cdnNotPt_V4 : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, globaladdress:$src2), - "if(!$src1.new) $dst = ##$src2", + (ins PredRegs:$src1, s16Ext:$src2), + "if(!$src1.new) $dst = #$src2", []>, Requires<[HasV4T]>; let AddedComplexity = 50, Predicates = [HasV4T] in def : Pat<(HexagonCONST32_GP tglobaladdr:$src1), - (TFRI_V4 tglobaladdr:$src1)>; + (TFRI_V4 tglobaladdr:$src1)>, + Requires<[HasV4T]>; // Load - Indirect with long offset: These instructions take global address diff --git a/lib/Target/Hexagon/HexagonInstrInfoV5.td b/lib/Target/Hexagon/HexagonInstrInfoV5.td index 92d098cc04..9da6074558 100644 --- a/lib/Target/Hexagon/HexagonInstrInfoV5.td +++ b/lib/Target/Hexagon/HexagonInstrInfoV5.td @@ -26,22 +26,29 @@ def CONST32_Float_Real : LDInst<(outs IntRegs:$dst), (ins f32imm:$src1), // Only works with single precision fp value. // For double precision, use CONST64_float_real, as 64bit transfer // can only hold 40-bit values - 32 from const ext + 8 bit immediate. -let isMoveImm = 1, isReMaterializable = 1, isPredicable = 1 in -def TFRI_f : ALU32_ri<(outs IntRegs:$dst), (ins f32imm:$src1), - "$dst = ##$src1", +// Make sure that complexity is more than the CONST32 pattern in +// HexagonInstrInfo.td patterns. +let isExtended = 1, opExtendable = 1, isMoveImm = 1, isReMaterializable = 1, +isPredicable = 1, AddedComplexity = 30, validSubTargets = HasV5SubT, +isCodeGenOnly = 1 in +def TFRI_f : ALU32_ri<(outs IntRegs:$dst), (ins f32Ext:$src1), + "$dst = #$src1", [(set IntRegs:$dst, fpimm:$src1)]>, Requires<[HasV5T]>; +let isExtended = 1, opExtendable = 2, isPredicated = 1, +neverHasSideEffects = 1, validSubTargets = HasV5SubT in def TFRI_cPt_f : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, f32imm:$src2), - "if ($src1) $dst = ##$src2", + (ins PredRegs:$src1, f32Ext:$src2), + "if ($src1) $dst = #$src2", []>, Requires<[HasV5T]>; -let isPredicated = 1 in +let isExtended = 1, opExtendable = 2, isPredicated = 1, isPredicatedFalse = 1, +neverHasSideEffects = 1, validSubTargets = HasV5SubT in def TFRI_cNotPt_f : ALU32_ri<(outs IntRegs:$dst), - (ins PredRegs:$src1, f32imm:$src2), - "if (!$src1) $dst = ##$src2", + (ins PredRegs:$src1, f32Ext:$src2), + "if (!$src1) $dst =#$src2", []>, Requires<[HasV5T]>; diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index fbe67e3882..6ed9d55135 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -498,250 +498,6 @@ static bool DoesModifyCalleeSavedReg(MachineInstr *MI, return false; } -// Return the new value instruction for a given store. -static int GetDotNewOp(const int opc) { - switch (opc) { - default: llvm_unreachable("Unknown .new type"); - // store new value byte - case Hexagon::STrib: - return Hexagon::STrib_nv_V4; - - case Hexagon::STrib_indexed: - return Hexagon::STrib_indexed_nv_V4; - - case Hexagon::STrib_indexed_shl_V4: - return Hexagon::STrib_indexed_shl_nv_V4; - - case Hexagon::STrib_shl_V4: - return Hexagon::STrib_shl_nv_V4; - - case Hexagon::STb_GP_V4: - return Hexagon::STb_GP_nv_V4; - - case Hexagon::POST_STbri: - return Hexagon::POST_STbri_nv_V4; - - case Hexagon::STrib_cPt: - return Hexagon::STrib_cPt_nv_V4; - - case Hexagon::STrib_cdnPt_V4: - return Hexagon::STrib_cdnPt_nv_V4; - - case Hexagon::STrib_cNotPt: - return Hexagon::STrib_cNotPt_nv_V4; - - case Hexagon::STrib_cdnNotPt_V4: - return Hexagon::STrib_cdnNotPt_nv_V4; - - case Hexagon::STrib_indexed_cPt: - return Hexagon::STrib_indexed_cPt_nv_V4; - - case Hexagon::STrib_indexed_cdnPt_V4: - return Hexagon::STrib_indexed_cdnPt_nv_V4; - - case Hexagon::STrib_indexed_cNotPt: - return Hexagon::STrib_indexed_cNotPt_nv_V4; - - case Hexagon::STrib_indexed_cdnNotPt_V4: - return Hexagon::STrib_indexed_cdnNotPt_nv_V4; - - case Hexagon::STrib_indexed_shl_cPt_V4: - return Hexagon::STrib_indexed_shl_cPt_nv_V4; - - case Hexagon::STrib_indexed_shl_cdnPt_V4: - return Hexagon::STrib_indexed_shl_cdnPt_nv_V4; - - case Hexagon::STrib_indexed_shl_cNotPt_V4: - return Hexagon::STrib_indexed_shl_cNotPt_nv_V4; - - case Hexagon::STrib_indexed_shl_cdnNotPt_V4: - return Hexagon::STrib_indexed_shl_cdnNotPt_nv_V4; - - case Hexagon::POST_STbri_cPt: - return Hexagon::POST_STbri_cPt_nv_V4; - - case Hexagon::POST_STbri_cdnPt_V4: - return Hexagon::POST_STbri_cdnPt_nv_V4; - - case Hexagon::POST_STbri_cNotPt: - return Hexagon::POST_STbri_cNotPt_nv_V4; - - case Hexagon::POST_STbri_cdnNotPt_V4: - return Hexagon::POST_STbri_cdnNotPt_nv_V4; - - case Hexagon::STb_GP_cPt_V4: - return Hexagon::STb_GP_cPt_nv_V4; - - case Hexagon::STb_GP_cNotPt_V4: - return Hexagon::STb_GP_cNotPt_nv_V4; - - case Hexagon::STb_GP_cdnPt_V4: - return Hexagon::STb_GP_cdnPt_nv_V4; - - case Hexagon::STb_GP_cdnNotPt_V4: - return Hexagon::STb_GP_cdnNotPt_nv_V4; - - // store new value halfword - case Hexagon::STrih: - return Hexagon::STrih_nv_V4; - - case Hexagon::STrih_indexed: - return Hexagon::STrih_indexed_nv_V4; - - case Hexagon::STrih_indexed_shl_V4: - return Hexagon::STrih_indexed_shl_nv_V4; - - case Hexagon::STrih_shl_V4: - return Hexagon::STrih_shl_nv_V4; - - case Hexagon::STh_GP_V4: - return Hexagon::STh_GP_nv_V4; - - case Hexagon::POST_SThri: - return Hexagon::POST_SThri_nv_V4; - - case Hexagon::STrih_cPt: - return Hexagon::STrih_cPt_nv_V4; - - case Hexagon::STrih_cdnPt_V4: - return Hexagon::STrih_cdnPt_nv_V4; - - case Hexagon::STrih_cNotPt: - return Hexagon::STrih_cNotPt_nv_V4; - - case Hexagon::STrih_cdnNotPt_V4: - return Hexagon::STrih_cdnNotPt_nv_V4; - - case Hexagon::STrih_indexed_cPt: - return Hexagon::STrih_indexed_cPt_nv_V4; - - case Hexagon::STrih_indexed_cdnPt_V4: - return Hexagon::STrih_indexed_cdnPt_nv_V4; - - case Hexagon::STrih_indexed_cNotPt: - return Hexagon::STrih_indexed_cNotPt_nv_V4; - - case Hexagon::STrih_indexed_cdnNotPt_V4: - return Hexagon::STrih_indexed_cdnNotPt_nv_V4; - - case Hexagon::STrih_indexed_shl_cPt_V4: - return Hexagon::STrih_indexed_shl_cPt_nv_V4; - - case Hexagon::STrih_indexed_shl_cdnPt_V4: - return Hexagon::STrih_indexed_shl_cdnPt_nv_V4; - - case Hexagon::STrih_indexed_shl_cNotPt_V4: - return Hexagon::STrih_indexed_shl_cNotPt_nv_V4; - - case Hexagon::STrih_indexed_shl_cdnNotPt_V4: - return Hexagon::STrih_indexed_shl_cdnNotPt_nv_V4; - - case Hexagon::POST_SThri_cPt: - return Hexagon::POST_SThri_cPt_nv_V4; - - case Hexagon::POST_SThri_cdnPt_V4: - return Hexagon::POST_SThri_cdnPt_nv_V4; - - case Hexagon::POST_SThri_cNotPt: - return Hexagon::POST_SThri_cNotPt_nv_V4; - - case Hexagon::POST_SThri_cdnNotPt_V4: - return Hexagon::POST_SThri_cdnNotPt_nv_V4; - - case Hexagon::STh_GP_cPt_V4: - return Hexagon::STh_GP_cPt_nv_V4; - - case Hexagon::STh_GP_cNotPt_V4: - return Hexagon::STh_GP_cNotPt_nv_V4; - - case Hexagon::STh_GP_cdnPt_V4: - return Hexagon::STh_GP_cdnPt_nv_V4; - - case Hexagon::STh_GP_cdnNotPt_V4: - return Hexagon::STh_GP_cdnNotPt_nv_V4; - - // store new value word - case Hexagon::STriw: - return Hexagon::STriw_nv_V4; - - case Hexagon::STriw_indexed: - return Hexagon::STriw_indexed_nv_V4; - - case Hexagon::STriw_indexed_shl_V4: - return Hexagon::STriw_indexed_shl_nv_V4; - - case Hexagon::STriw_shl_V4: - return Hexagon::STriw_shl_nv_V4; - - case Hexagon::STw_GP_V4: - return Hexagon::STw_GP_nv_V4; - - case Hexagon::POST_STwri: - return Hexagon::POST_STwri_nv_V4; - - case Hexagon::STriw_cPt: - return Hexagon::STriw_cPt_nv_V4; - - case Hexagon::STriw_cdnPt_V4: - return Hexagon::STriw_cdnPt_nv_V4; - - case Hexagon::STriw_cNotPt: - return Hexagon::STriw_cNotPt_nv_V4; - - case Hexagon::STriw_cdnNotPt_V4: - return Hexagon::STriw_cdnNotPt_nv_V4; - - case Hexagon::STriw_indexed_cPt: - return Hexagon::STriw_indexed_cPt_nv_V4; - - case Hexagon::STriw_indexed_cdnPt_V4: - return Hexagon::STriw_indexed_cdnPt_nv_V4; - - case Hexagon::STriw_indexed_cNotPt: - return Hexagon::STriw_indexed_cNotPt_nv_V4; - - case Hexagon::STriw_indexed_cdnNotPt_V4: - return Hexagon::STriw_indexed_cdnNotPt_nv_V4; - - case Hexagon::STriw_indexed_shl_cPt_V4: - return Hexagon::STriw_indexed_shl_cPt_nv_V4; - - case Hexagon::STriw_indexed_shl_cdnPt_V4: - return Hexagon::STriw_indexed_shl_cdnPt_nv_V4; - - case Hexagon::STriw_indexed_shl_cNotPt_V4: - return Hexagon::STriw_indexed_shl_cNotPt_nv_V4; - - case Hexagon::STriw_indexed_shl_cdnNotPt_V4: - return Hexagon::STriw_indexed_shl_cdnNotPt_nv_V4; - - case Hexagon::POST_STwri_cPt: - return Hexagon::POST_STwri_cPt_nv_V4; - - case Hexagon::POST_STwri_cdnPt_V4: - return Hexagon::POST_STwri_cdnPt_nv_V4; - - case Hexagon::POST_STwri_cNotPt: - return Hexagon::POST_STwri_cNotPt_nv_V4; - - case Hexagon::POST_STwri_cdnNotPt_V4: - return Hexagon::POST_STwri_cdnNotPt_nv_V4; - - case Hexagon::STw_GP_cPt_V4: - return Hexagon::STw_GP_cPt_nv_V4; - - case Hexagon::STw_GP_cNotPt_V4: - return Hexagon::STw_GP_cNotPt_nv_V4; - - case Hexagon::STw_GP_cdnPt_V4: - return Hexagon::STw_GP_cdnPt_nv_V4; - - case Hexagon::STw_GP_cdnNotPt_V4: - return Hexagon::STw_GP_cdnNotPt_nv_V4; - - } -} - // Returns true if an instruction can be promoted to .new predicate // or new-value store. bool HexagonPacketizerList::isNewifiable(MachineInstr* MI) { @@ -781,7 +537,7 @@ bool HexagonPacketizerList::PromoteToDotNew(MachineInstr* MI, if (RC == &Hexagon::PredRegsRegClass) NewOpcode = QII->GetDotNewPredOp(MI, MBPI); else - NewOpcode = GetDotNewOp(MI->getOpcode()); + NewOpcode = QII->GetDotNewOp(MI); MI->setDesc(QII->get(NewOpcode)); return true; @@ -1380,295 +1136,23 @@ bool HexagonPacketizerList::DemoteToDotOld(MachineInstr* MI) { return true; } -// Returns true if an instruction is predicated on p0 and false if it's -// predicated on !p0. - -static bool GetPredicateSense(MachineInstr* MI, - const HexagonInstrInfo *QII) { +enum PredicateKind { + PK_False, + PK_True, + PK_Unknown +}; - switch (MI->getOpcode()) { - default: llvm_unreachable("Unknown predicate sense of the instruction"); - case Hexagon::TFR_cPt: - case Hexagon::TFR_cdnPt: - case Hexagon::TFRI_cPt: - case Hexagon::TFRI_cdnPt: - case Hexagon::STrib_cPt : - case Hexagon::STrib_cdnPt_V4 : - case Hexagon::STrib_indexed_cPt : - case Hexagon::STrib_indexed_cdnPt_V4 : - case Hexagon::STrib_indexed_shl_cPt_V4 : - case Hexagon::STrib_indexed_shl_cdnPt_V4 : - case Hexagon::POST_STbri_cPt : - case Hexagon::POST_STbri_cdnPt_V4 : - case Hexagon::STrih_cPt : - case Hexagon::STrih_cdnPt_V4 : - case Hexagon::STrih_indexed_cPt : - case Hexagon::STrih_indexed_cdnPt_V4 : - case Hexagon::STrih_indexed_shl_cPt_V4 : - case Hexagon::STrih_indexed_shl_cdnPt_V4 : - case Hexagon::POST_SThri_cPt : - case Hexagon::POST_SThri_cdnPt_V4 : - case Hexagon::STriw_cPt : - case Hexagon::STriw_cdnPt_V4 : - case Hexagon::STriw_indexed_cPt : - case Hexagon::STriw_indexed_cdnPt_V4 : - case Hexagon::STriw_indexed_shl_cPt_V4 : - case Hexagon::STriw_indexed_shl_cdnPt_V4 : - case Hexagon::POST_STwri_cPt : - case Hexagon::POST_STwri_cdnPt_V4 : - case Hexagon::STrib_imm_cPt_V4 : - case Hexagon::STrib_imm_cdnPt_V4 : - case Hexagon::STrid_cPt : - case Hexagon::STrid_cdnPt_V4 : - case Hexagon::STrid_indexed_cPt : - case Hexagon::STrid_indexed_cdnPt_V4 : - case Hexagon::STrid_indexed_shl_cPt_V4 : - case Hexagon::STrid_indexed_shl_cdnPt_V4 : - case Hexagon::POST_STdri_cPt : - case Hexagon::POST_STdri_cdnPt_V4 : - case Hexagon::STrih_imm_cPt_V4 : - case Hexagon::STrih_imm_cdnPt_V4 : - case Hexagon::STriw_imm_cPt_V4 : - case Hexagon::STriw_imm_cdnPt_V4 : - case Hexagon::JMP_tnew_t : - case Hexagon::LDrid_cPt : - case Hexagon::LDrid_cdnPt : - case Hexagon::LDrid_indexed_cPt : - case Hexagon::LDrid_indexed_cdnPt : - case Hexagon::POST_LDrid_cPt : - case Hexagon::POST_LDrid_cdnPt_V4 : - case Hexagon::LDriw_cPt : - case Hexagon::LDriw_cdnPt : - case Hexagon::LDriw_indexed_cPt : - case Hexagon::LDriw_indexed_cdnPt : - case Hexagon::POST_LDriw_cPt : - case Hexagon::POST_LDriw_cdnPt_V4 : - case Hexagon::LDrih_cPt : - case Hexagon::LDrih_cdnPt : - case Hexagon::LDrih_indexed_cPt : - case Hexagon::LDrih_indexed_cdnPt : - case Hexagon::POST_LDrih_cPt : - case Hexagon::POST_LDrih_cdnPt_V4 : - case Hexagon::LDrib_cPt : - case Hexagon::LDrib_cdnPt : - case Hexagon::LDrib_indexed_cPt : - case Hexagon::LDrib_indexed_cdnPt : - case Hexagon::POST_LDrib_cPt : - case Hexagon::POST_LDrib_cdnPt_V4 : - case Hexagon::LDriuh_cPt : - case Hexagon::LDriuh_cdnPt : - case Hexagon::LDriuh_indexed_cPt : - case Hexagon::LDriuh_indexed_cdnPt : - case Hexagon::POST_LDriuh_cPt : - case Hexagon::POST_LDriuh_cdnPt_V4 : - case Hexagon::LDriub_cPt : - case Hexagon::LDriub_cdnPt : - case Hexagon::LDriub_indexed_cPt : - case Hexagon::LDriub_indexed_cdnPt : - case Hexagon::POST_LDriub_cPt : - case Hexagon::POST_LDriub_cdnPt_V4 : - case Hexagon::LDrid_indexed_shl_cPt_V4 : - case Hexagon::LDrid_indexed_shl_cdnPt_V4 : - case Hexagon::LDrib_indexed_shl_cPt_V4 : - case Hexagon::LDrib_indexed_shl_cdnPt_V4 : - case Hexagon::LDriub_indexed_shl_cPt_V4 : - case Hexagon::LDriub_indexed_shl_cdnPt_V4 : - case Hexagon::LDrih_indexed_shl_cPt_V4 : - case Hexagon::LDrih_indexed_shl_cdnPt_V4 : - case Hexagon::LDriuh_indexed_shl_cPt_V4 : - case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : - case Hexagon::LDriw_indexed_shl_cPt_V4 : - case Hexagon::LDriw_indexed_shl_cdnPt_V4 : - case Hexagon::ADD_ri_cPt : - case Hexagon::ADD_ri_cdnPt : - case Hexagon::ADD_rr_cPt : - case Hexagon::ADD_rr_cdnPt : - case Hexagon::XOR_rr_cPt : - case Hexagon::XOR_rr_cdnPt : - case Hexagon::AND_rr_cPt : - case Hexagon::AND_rr_cdnPt : - case Hexagon::OR_rr_cPt : - case Hexagon::OR_rr_cdnPt : - case Hexagon::SUB_rr_cPt : - case Hexagon::SUB_rr_cdnPt : - case Hexagon::COMBINE_rr_cPt : - case Hexagon::COMBINE_rr_cdnPt : - case Hexagon::ASLH_cPt_V4 : - case Hexagon::ASLH_cdnPt_V4 : - case Hexagon::ASRH_cPt_V4 : - case Hexagon::ASRH_cdnPt_V4 : - case Hexagon::SXTB_cPt_V4 : - case Hexagon::SXTB_cdnPt_V4 : - case Hexagon::SXTH_cPt_V4 : - case Hexagon::SXTH_cdnPt_V4 : - case Hexagon::ZXTB_cPt_V4 : - case Hexagon::ZXTB_cdnPt_V4 : - case Hexagon::ZXTH_cPt_V4 : - case Hexagon::ZXTH_cdnPt_V4 : - case Hexagon::LDd_GP_cPt_V4 : - case Hexagon::LDb_GP_cPt_V4 : - case Hexagon::LDub_GP_cPt_V4 : - case Hexagon::LDh_GP_cPt_V4 : - case Hexagon::LDuh_GP_cPt_V4 : - case Hexagon::LDw_GP_cPt_V4 : - case Hexagon::STd_GP_cPt_V4 : - case Hexagon::STb_GP_cPt_V4 : - case Hexagon::STh_GP_cPt_V4 : - case Hexagon::STw_GP_cPt_V4 : - case Hexagon::LDd_GP_cdnPt_V4 : - case Hexagon::LDb_GP_cdnPt_V4 : - case Hexagon::LDub_GP_cdnPt_V4 : - case Hexagon::LDh_GP_cdnPt_V4 : - case Hexagon::LDuh_GP_cdnPt_V4 : - case Hexagon::LDw_GP_cdnPt_V4 : - case Hexagon::STd_GP_cdnPt_V4 : - case Hexagon::STb_GP_cdnPt_V4 : - case Hexagon::STh_GP_cdnPt_V4 : - case Hexagon::STw_GP_cdnPt_V4 : - return true; +/// Returns true if an instruction is predicated on p0 and false if it's +/// predicated on !p0. +static PredicateKind getPredicateSense(MachineInstr* MI, + const HexagonInstrInfo *QII) { + if (!QII->isPredicated(MI)) + return PK_Unknown; - case Hexagon::TFR_cNotPt: - case Hexagon::TFR_cdnNotPt: - case Hexagon::TFRI_cNotPt: - case Hexagon::TFRI_cdnNotPt: - case Hexagon::STrib_cNotPt : - case Hexagon::STrib_cdnNotPt_V4 : - case Hexagon::STrib_indexed_cNotPt : - case Hexagon::STrib_indexed_cdnNotPt_V4 : - case Hexagon::STrib_indexed_shl_cNotPt_V4 : - case Hexagon::STrib_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_STbri_cNotPt : - case Hexagon::POST_STbri_cdnNotPt_V4 : - case Hexagon::STrih_cNotPt : - case Hexagon::STrih_cdnNotPt_V4 : - case Hexagon::STrih_indexed_cNotPt : - case Hexagon::STrih_indexed_cdnNotPt_V4 : - case Hexagon::STrih_indexed_shl_cNotPt_V4 : - case Hexagon::STrih_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_SThri_cNotPt : - case Hexagon::POST_SThri_cdnNotPt_V4 : - case Hexagon::STriw_cNotPt : - case Hexagon::STriw_cdnNotPt_V4 : - case Hexagon::STriw_indexed_cNotPt : - case Hexagon::STriw_indexed_cdnNotPt_V4 : - case Hexagon::STriw_indexed_shl_cNotPt_V4 : - case Hexagon::STriw_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_STwri_cNotPt : - case Hexagon::POST_STwri_cdnNotPt_V4 : - case Hexagon::STrib_imm_cNotPt_V4 : - case Hexagon::STrib_imm_cdnNotPt_V4 : - case Hexagon::STrid_cNotPt : - case Hexagon::STrid_cdnNotPt_V4 : - case Hexagon::STrid_indexed_cdnNotPt_V4 : - case Hexagon::STrid_indexed_cNotPt : - case Hexagon::STrid_indexed_shl_cNotPt_V4 : - case Hexagon::STrid_indexed_shl_cdnNotPt_V4 : - case Hexagon::POST_STdri_cNotPt : - case Hexagon::POST_STdri_cdnNotPt_V4 : - case Hexagon::STrih_imm_cNotPt_V4 : - case Hexagon::STrih_imm_cdnNotPt_V4 : - case Hexagon::STriw_imm_cNotPt_V4 : - case Hexagon::STriw_imm_cdnNotPt_V4 : - case Hexagon::JMP_fnew_t : - case Hexagon::LDrid_cNotPt : - case Hexagon::LDrid_cdnNotPt : - case Hexagon::LDrid_indexed_cNotPt : - case Hexagon::LDrid_indexed_cdnNotPt : - case Hexagon::POST_LDrid_cNotPt : - case Hexagon::POST_LDrid_cdnNotPt_V4 : - case Hexagon::LDriw_cNotPt : - case Hexagon::LDriw_cdnNotPt : - case Hexagon::LDriw_indexed_cNotPt : - case Hexagon::LDriw_indexed_cdnNotPt : - case Hexagon::POST_LDriw_cNotPt : - case Hexagon::POST_LDriw_cdnNotPt_V4 : - case Hexagon::LDrih_cNotPt : - case Hexagon::LDrih_cdnNotPt : - case Hexagon::LDrih_indexed_cNotPt : - case Hexagon::LDrih_indexed_cdnNotPt : - case Hexagon::POST_LDrih_cNotPt : - case Hexagon::POST_LDrih_cdnNotPt_V4 : - case Hexagon::LDrib_cNotPt : - case Hexagon::LDrib_cdnNotPt : - case Hexagon::LDrib_indexed_cNotPt : - case Hexagon::LDrib_indexed_cdnNotPt : - case Hexagon::POST_LDrib_cNotPt : - case Hexagon::POST_LDrib_cdnNotPt_V4 : - case Hexagon::LDriuh_cNotPt : - case Hexagon::LDriuh_cdnNotPt : - case Hexagon::LDriuh_indexed_cNotPt : - case Hexagon::LDriuh_indexed_cdnNotPt : - case Hexagon::POST_LDriuh_cNotPt : - case Hexagon::POST_LDriuh_cdnNotPt_V4 : - case Hexagon::LDriub_cNotPt : - case Hexagon::LDriub_cdnNotPt : - case Hexagon::LDriub_indexed_cNotPt : - case Hexagon::LDriub_indexed_cdnNotPt : - case Hexagon::POST_LDriub_cNotPt : - case Hexagon::POST_LDriub_cdnNotPt_V4 : - case Hexagon::LDrid_indexed_shl_cNotPt_V4 : - case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrib_indexed_shl_cNotPt_V4 : - case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriub_indexed_shl_cNotPt_V4 : - case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDrih_indexed_shl_cNotPt_V4 : - case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : - case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : - case Hexagon::LDriw_indexed_shl_cNotPt_V4 : - case Hexagon::LDriw_indexed_shl_cdnNotPt_V4 : - case Hexagon::ADD_ri_cNotPt : - case Hexagon::ADD_ri_cdnNotPt : - case Hexagon::ADD_rr_cNotPt : - case Hexagon::ADD_rr_cdnNotPt : - case Hexagon::XOR_rr_cNotPt : - case Hexagon::XOR_rr_cdnNotPt : - case Hexagon::AND_rr_cNotPt : - case Hexagon::AND_rr_cdnNotPt : - case Hexagon::OR_rr_cNotPt : - case Hexagon::OR_rr_cdnNotPt : - case Hexagon::SUB_rr_cNotPt : - case Hexagon::SUB_rr_cdnNotPt : - case Hexagon::COMBINE_rr_cNotPt : - case Hexagon::COMBINE_rr_cdnNotPt : - case Hexagon::ASLH_cNotPt_V4 : - case Hexagon::ASLH_cdnNotPt_V4 : - case Hexagon::ASRH_cNotPt_V4 : - case Hexagon::ASRH_cdnNotPt_V4 : - case Hexagon::SXTB_cNotPt_V4 : - case Hexagon::SXTB_cdnNotPt_V4 : - case Hexagon::SXTH_cNotPt_V4 : - case Hexagon::SXTH_cdnNotPt_V4 : - case Hexagon::ZXTB_cNotPt_V4 : - case Hexagon::ZXTB_cdnNotPt_V4 : - case Hexagon::ZXTH_cNotPt_V4 : - case Hexagon::ZXTH_cdnNotPt_V4 : + if (QII->isPredicatedTrue(MI)) + return PK_True; - case Hexagon::LDd_GP_cNotPt_V4 : - case Hexagon::LDb_GP_cNotPt_V4 : - case Hexagon::LDub_GP_cNotPt_V4 : - case Hexagon::LDh_GP_cNotPt_V4 : - case Hexagon::LDuh_GP_cNotPt_V4 : - case Hexagon::LDw_GP_cNotPt_V4 : - case Hexagon::STd_GP_cNotPt_V4 : - case Hexagon::STb_GP_cNotPt_V4 : - case Hexagon::STh_GP_cNotPt_V4 : - case Hexagon::STw_GP_cNotPt_V4 : - case Hexagon::LDd_GP_cdnNotPt_V4 : - case Hexagon::LDb_GP_cdnNotPt_V4 : - case Hexagon::LDub_GP_cdnNotPt_V4 : - case Hexagon::LDh_GP_cdnNotPt_V4 : - case Hexagon::LDuh_GP_cdnNotPt_V4 : - case Hexagon::LDw_GP_cdnNotPt_V4 : - case Hexagon::STd_GP_cdnNotPt_V4 : - case Hexagon::STb_GP_cdnNotPt_V4 : - case Hexagon::STh_GP_cdnNotPt_V4 : - case Hexagon::STw_GP_cdnNotPt_V4 : - return false; - } - // return *some value* to avoid compiler warning - return false; + return PK_False; } static MachineOperand& GetPostIncrementOperand(MachineInstr *MI, @@ -1842,7 +1326,7 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, if (( predRegNumDst != predRegNumSrc) || QII->isDotNewInst(PacketMI) != QII->isDotNewInst(MI) || - GetPredicateSense(MI, QII) != GetPredicateSense(PacketMI, QII)) { + getPredicateSense(MI, QII) != getPredicateSense(PacketMI, QII)) { return false; } } @@ -1968,7 +1452,7 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, else { // Create a dot new machine instruction to see if resources can be // allocated. If not, bail out now. - int NewOpcode = GetDotNewOp(MI->getOpcode()); + int NewOpcode = QII->GetDotNewOp(MI); const MCInstrDesc &desc = QII->get(NewOpcode); DebugLoc dl; MachineInstr *NewMI = @@ -2109,7 +1593,7 @@ bool HexagonPacketizerList::ArePredicatesComplements (MachineInstr* MI1, // We also need to differentiate .old vs. .new: // !p0 is not complimentary to p0.new return ((MI1->getOperand(1).getReg() == MI2->getOperand(1).getReg()) && - (GetPredicateSense(MI1, QII) != GetPredicateSense(MI2, QII)) && + (getPredicateSense(MI1, QII) != getPredicateSense(MI2, QII)) && (QII->isDotNewInst(MI1) == QII->isDotNewInst(MI2))); } diff --git a/test/CodeGen/Hexagon/pred-gp.ll b/test/CodeGen/Hexagon/pred-gp.ll new file mode 100644 index 0000000000..299bd8679d --- /dev/null +++ b/test/CodeGen/Hexagon/pred-gp.ll @@ -0,0 +1,28 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; Check that we are able to predicate instructions with gp-relative +; addressing mode. + +@d = external global i32 +@c = common global i32 0, align 4 + +; Function Attrs: nounwind +define i32 @test2(i8 zeroext %a, i8 zeroext %b) #0 { +; CHECK: if{{ *}}({{!*}}p{{[0-3]+}}{{[.new]*}}){{ *}}r{{[0-9]+}}{{ *}}={{ *}}memw(##{{[cd]}}) +; CHECK: if{{ *}}({{!*}}p{{[0-3]+}}){{ *}}r{{[0-9]+}}{{ *}}={{ *}}memw(##{{[cd]}}) +entry: + %cmp = icmp eq i8 %a, %b + br i1 %cmp, label %if.then, label %entry.if.end_crit_edge + +entry.if.end_crit_edge: + %.pre = load i32* @c, align 4 + br label %if.end + +if.then: + %0 = load i32* @d, align 4 + store i32 %0, i32* @c, align 4 + br label %if.end + +if.end: + %1 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %0, %if.then ] + ret i32 %1 +} -- cgit v1.2.3 From cdfb55d15bbcdf1533ca26ffcb9c94fa5d225bd0 Mon Sep 17 00:00:00 2001 From: Jyotsna Verma Date: Fri, 10 May 2013 20:58:11 +0000 Subject: Hexagon: Fix switch statements in GetDotOldOp and IsNewifyStore. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181628 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/Hexagon.td | 24 + lib/Target/Hexagon/HexagonInstrInfo.cpp | 35 ++ lib/Target/Hexagon/HexagonInstrInfo.h | 2 + lib/Target/Hexagon/HexagonVLIWPacketizer.cpp | 727 +-------------------------- 4 files changed, 81 insertions(+), 707 deletions(-) diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td index 6c7f963b53..568798c3a4 100644 --- a/lib/Target/Hexagon/Hexagon.td +++ b/lib/Target/Hexagon/Hexagon.td @@ -119,6 +119,18 @@ def getPredNewOpcode : InstrMapping { let ValueCols = [["new"]]; } +//===----------------------------------------------------------------------===// +// Generate mapping table to relate .new predicated instructions with their old +// format. +// +def getPredOldOpcode : InstrMapping { + let FilterClass = "PredNewRel"; + let RowFields = ["BaseOpcode", "PredSense", "isNVStore"]; + let ColFields = ["PNewValue"]; + let KeyCol = ["new"]; + let ValueCols = [[""]]; +} + //===----------------------------------------------------------------------===// // Generate mapping table to relate store instructions with their new-value // format. @@ -131,6 +143,18 @@ def getNewValueOpcode : InstrMapping { let ValueCols = [["true"]]; } +//===----------------------------------------------------------------------===// +// Generate mapping table to relate new-value store instructions with their old +// format. +// +def getNonNVStore : InstrMapping { + let FilterClass = "NewValueRel"; + let RowFields = ["BaseOpcode", "PredSense", "PNewValue"]; + let ColFields = ["NValueST"]; + let KeyCol = ["true"]; + let ValueCols = [["false"]]; +} + def getBasedWithImmOffset : InstrMapping { let FilterClass = "AddrModeRel"; let RowFields = ["CextOpcode", "PredSense", "PNewValue", "isNVStore", diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp index 7dec127453..33a937308d 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -1027,6 +1027,16 @@ bool HexagonInstrInfo::isPredicatedNew(unsigned Opcode) const { return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); } +// Returns true, if a ST insn can be promoted to a new-value store. +bool HexagonInstrInfo::mayBeNewStore(const MachineInstr *MI) const { + const HexagonRegisterInfo& QRI = getRegisterInfo(); + const uint64_t F = MI->getDesc().TSFlags; + + return ((F >> HexagonII::mayNVStorePos) & + HexagonII::mayNVStoreMask & + QRI.Subtarget.hasV4TOps()); +} + bool HexagonInstrInfo::DefinesPredicate(MachineInstr *MI, std::vector &Pred) const { @@ -1520,6 +1530,31 @@ bool HexagonInstrInfo::isDotNewInst (const MachineInstr* MI) const { (isPredicated(MI) && isPredicatedNew(MI))); } +// Returns the most basic instruction for the .new predicated instructions and +// new-value stores. +// For example, all of the following instructions will be converted back to the +// same instruction: +// 1) if (p0.new) memw(R0+#0) = R1.new ---> +// 2) if (p0) memw(R0+#0)= R1.new -------> if (p0) memw(R0+#0) = R1 +// 3) if (p0.new) memw(R0+#0) = R1 ---> +// + +int HexagonInstrInfo::GetDotOldOp(const int opc) const { + int NewOp = opc; + if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form + NewOp = Hexagon::getPredOldOpcode(NewOp); + if (NewOp < 0) + assert(0 && "Couldn't change predicate new instruction to its old form."); + } + + if (isNewValueStore(NewOp)) { // Convert into non new-value format + NewOp = Hexagon::getNonNVStore(NewOp); + if (NewOp < 0) + assert(0 && "Couldn't change new-value store to its old form."); + } + return NewOp; +} + // Return the new value instruction for a given store. int HexagonInstrInfo::GetDotNewOp(const MachineInstr* MI) const { int NVOpcode = Hexagon::getNewValueOpcode(MI->getOpcode()); diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h index f3297fbd33..d1209dec3b 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/lib/Target/Hexagon/HexagonInstrInfo.h @@ -185,10 +185,12 @@ public: bool isNewValueInst(const MachineInstr* MI) const; bool isNewValue(const MachineInstr* MI) const; bool isDotNewInst(const MachineInstr* MI) const; + int GetDotOldOp(const int opc) const; int GetDotNewOp(const MachineInstr* MI) const; int GetDotNewPredOp(MachineInstr *MI, const MachineBranchProbabilityInfo *MBPI) const; + bool mayBeNewStore(const MachineInstr* MI) const; bool isDeallocRet(const MachineInstr *MI) const; unsigned getInvertedPredicatedOpcode(const int Opc) const; bool isExtendable(const MachineInstr* MI) const; diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index 6ed9d55135..c508d124b3 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -164,7 +164,6 @@ namespace { unsigned, std::map ); bool isNewifiable(MachineInstr* MI); bool isCondInst(MachineInstr* MI); - bool IsNewifyStore (MachineInstr* MI); bool tryAllocateResourcesForConstExt(MachineInstr* MI); bool canReserveResourcesForConstExt(MachineInstr *MI); void reserveResourcesForConstExt(MachineInstr* MI); @@ -383,104 +382,6 @@ static bool IsControlFlow(MachineInstr* MI) { return (MI->getDesc().isTerminator() || MI->getDesc().isCall()); } -// Function returns true if an instruction can be promoted to the new-value -// store. It will always return false for v2 and v3. -// It lists all the conditional and unconditional stores that can be promoted -// to the new-value stores. - -bool HexagonPacketizerList::IsNewifyStore (MachineInstr* MI) { - const HexagonRegisterInfo* QRI = - (const HexagonRegisterInfo *) TM.getRegisterInfo(); - switch (MI->getOpcode()) - { - // store byte - case Hexagon::STrib: - case Hexagon::STrib_indexed: - case Hexagon::STrib_indexed_shl_V4: - case Hexagon::STrib_shl_V4: - case Hexagon::STb_GP_V4: - case Hexagon::POST_STbri: - case Hexagon::STrib_cPt: - case Hexagon::STrib_cdnPt_V4: - case Hexagon::STrib_cNotPt: - case Hexagon::STrib_cdnNotPt_V4: - case Hexagon::STrib_indexed_cPt: - case Hexagon::STrib_indexed_cdnPt_V4: - case Hexagon::STrib_indexed_cNotPt: - case Hexagon::STrib_indexed_cdnNotPt_V4: - case Hexagon::STrib_indexed_shl_cPt_V4: - case Hexagon::STrib_indexed_shl_cdnPt_V4: - case Hexagon::STrib_indexed_shl_cNotPt_V4: - case Hexagon::STrib_indexed_shl_cdnNotPt_V4: - case Hexagon::POST_STbri_cPt: - case Hexagon::POST_STbri_cdnPt_V4: - case Hexagon::POST_STbri_cNotPt: - case Hexagon::POST_STbri_cdnNotPt_V4: - case Hexagon::STb_GP_cPt_V4: - case Hexagon::STb_GP_cNotPt_V4: - case Hexagon::STb_GP_cdnPt_V4: - case Hexagon::STb_GP_cdnNotPt_V4: - - // store halfword - case Hexagon::STrih: - case Hexagon::STrih_indexed: - case Hexagon::STrih_indexed_shl_V4: - case Hexagon::STrih_shl_V4: - case Hexagon::STh_GP_V4: - case Hexagon::POST_SThri: - case Hexagon::STrih_cPt: - case Hexagon::STrih_cdnPt_V4: - case Hexagon::STrih_cNotPt: - case Hexagon::STrih_cdnNotPt_V4: - case Hexagon::STrih_indexed_cPt: - case Hexagon::STrih_indexed_cdnPt_V4: - case Hexagon::STrih_indexed_cNotPt: - case Hexagon::STrih_indexed_cdnNotPt_V4: - case Hexagon::STrih_indexed_shl_cPt_V4: - case Hexagon::STrih_indexed_shl_cdnPt_V4: - case Hexagon::STrih_indexed_shl_cNotPt_V4: - case Hexagon::STrih_indexed_shl_cdnNotPt_V4: - case Hexagon::POST_SThri_cPt: - case Hexagon::POST_SThri_cdnPt_V4: - case Hexagon::POST_SThri_cNotPt: - case Hexagon::POST_SThri_cdnNotPt_V4: - case Hexagon::STh_GP_cPt_V4: - case Hexagon::STh_GP_cNotPt_V4: - case Hexagon::STh_GP_cdnPt_V4: - case Hexagon::STh_GP_cdnNotPt_V4: - - // store word - case Hexagon::STriw: - case Hexagon::STriw_indexed: - case Hexagon::STriw_indexed_shl_V4: - case Hexagon::STriw_shl_V4: - case Hexagon::STw_GP_V4: - case Hexagon::POST_STwri: - case Hexagon::STriw_cPt: - case Hexagon::STriw_cdnPt_V4: - case Hexagon::STriw_cNotPt: - case Hexagon::STriw_cdnNotPt_V4: - case Hexagon::STriw_indexed_cPt: - case Hexagon::STriw_indexed_cdnPt_V4: - case Hexagon::STriw_indexed_cNotPt: - case Hexagon::STriw_indexed_cdnNotPt_V4: - case Hexagon::STriw_indexed_shl_cPt_V4: - case Hexagon::STriw_indexed_shl_cdnPt_V4: - case Hexagon::STriw_indexed_shl_cNotPt_V4: - case Hexagon::STriw_indexed_shl_cdnNotPt_V4: - case Hexagon::POST_STwri_cPt: - case Hexagon::POST_STwri_cdnPt_V4: - case Hexagon::POST_STwri_cNotPt: - case Hexagon::POST_STwri_cdnNotPt_V4: - case Hexagon::STw_GP_cPt_V4: - case Hexagon::STw_GP_cNotPt_V4: - case Hexagon::STw_GP_cdnPt_V4: - case Hexagon::STw_GP_cdnNotPt_V4: - return QRI->Subtarget.hasV4TOps(); - } - return false; -} - static bool IsLoopN(MachineInstr *MI) { return (MI->getOpcode() == Hexagon::LOOP0_i || MI->getOpcode() == Hexagon::LOOP0_r); @@ -501,7 +402,8 @@ static bool DoesModifyCalleeSavedReg(MachineInstr *MI, // Returns true if an instruction can be promoted to .new predicate // or new-value store. bool HexagonPacketizerList::isNewifiable(MachineInstr* MI) { - if ( isCondInst(MI) || IsNewifyStore(MI)) + const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; + if ( isCondInst(MI) || QII->mayBeNewStore(MI)) return true; else return false; @@ -543,595 +445,9 @@ bool HexagonPacketizerList::PromoteToDotNew(MachineInstr* MI, return true; } -// Returns the most basic instruction for the .new predicated instructions and -// new-value stores. -// For example, all of the following instructions will be converted back to the -// same instruction: -// 1) if (p0.new) memw(R0+#0) = R1.new ---> -// 2) if (p0) memw(R0+#0)= R1.new -------> if (p0) memw(R0+#0) = R1 -// 3) if (p0.new) memw(R0+#0) = R1 ---> -// -// To understand the translation of instruction 1 to its original form, consider -// a packet with 3 instructions. -// { p0 = cmp.eq(R0,R1) -// if (p0.new) R2 = add(R3, R4) -// R5 = add (R3, R1) -// } -// if (p0) memw(R5+#0) = R2 <--- trying to include it in the previous packet -// -// This instruction can be part of the previous packet only if both p0 and R2 -// are promoted to .new values. This promotion happens in steps, first -// predicate register is promoted to .new and in the next iteration R2 is -// promoted. Therefore, in case of dependence check failure (due to R5) during -// next iteration, it should be converted back to its most basic form. - -static int GetDotOldOp(const int opc) { - switch (opc) { - default: llvm_unreachable("Unknown .old type"); - case Hexagon::TFR_cdnPt: - return Hexagon::TFR_cPt; - - case Hexagon::TFR_cdnNotPt: - return Hexagon::TFR_cNotPt; - - case Hexagon::TFRI_cdnPt: - return Hexagon::TFRI_cPt; - - case Hexagon::TFRI_cdnNotPt: - return Hexagon::TFRI_cNotPt; - - case Hexagon::JMP_tnew_t: - return Hexagon::JMP_t; - - case Hexagon::JMP_fnew_t: - return Hexagon::JMP_f; - - case Hexagon::JMPR_tnew_tV3: - return Hexagon::JMPR_t; - - case Hexagon::JMPR_fnew_tV3: - return Hexagon::JMPR_f; - - // Load double word - - case Hexagon::LDrid_cdnPt : - return Hexagon::LDrid_cPt; - - case Hexagon::LDrid_cdnNotPt : - return Hexagon::LDrid_cNotPt; - - case Hexagon::LDrid_indexed_cdnPt : - return Hexagon::LDrid_indexed_cPt; - - case Hexagon::LDrid_indexed_cdnNotPt : - return Hexagon::LDrid_indexed_cNotPt; - - case Hexagon::POST_LDrid_cdnPt_V4 : - return Hexagon::POST_LDrid_cPt; - - case Hexagon::POST_LDrid_cdnNotPt_V4 : - return Hexagon::POST_LDrid_cNotPt; - - // Load word - - case Hexagon::LDriw_cdnPt : - return Hexagon::LDriw_cPt; - - case Hexagon::LDriw_cdnNotPt : - return Hexagon::LDriw_cNotPt; - - case Hexagon::LDriw_indexed_cdnPt : - return Hexagon::LDriw_indexed_cPt; - - case Hexagon::LDriw_indexed_cdnNotPt : - return Hexagon::LDriw_indexed_cNotPt; - - case Hexagon::POST_LDriw_cdnPt_V4 : - return Hexagon::POST_LDriw_cPt; - - case Hexagon::POST_LDriw_cdnNotPt_V4 : - return Hexagon::POST_LDriw_cNotPt; - - // Load half - - case Hexagon::LDrih_cdnPt : - return Hexagon::LDrih_cPt; - - case Hexagon::LDrih_cdnNotPt : - return Hexagon::LDrih_cNotPt; - - case Hexagon::LDrih_indexed_cdnPt : - return Hexagon::LDrih_indexed_cPt; - - case Hexagon::LDrih_indexed_cdnNotPt : - return Hexagon::LDrih_indexed_cNotPt; - - case Hexagon::POST_LDrih_cdnPt_V4 : - return Hexagon::POST_LDrih_cPt; - - case Hexagon::POST_LDrih_cdnNotPt_V4 : - return Hexagon::POST_LDrih_cNotPt; - - // Load byte - - case Hexagon::LDrib_cdnPt : - return Hexagon::LDrib_cPt; - - case Hexagon::LDrib_cdnNotPt : - return Hexagon::LDrib_cNotPt; - - case Hexagon::LDrib_indexed_cdnPt : - return Hexagon::LDrib_indexed_cPt; - - case Hexagon::LDrib_indexed_cdnNotPt : - return Hexagon::LDrib_indexed_cNotPt; - - case Hexagon::POST_LDrib_cdnPt_V4 : - return Hexagon::POST_LDrib_cPt; - - case Hexagon::POST_LDrib_cdnNotPt_V4 : - return Hexagon::POST_LDrib_cNotPt; - - // Load unsigned half - - case Hexagon::LDriuh_cdnPt : - return Hexagon::LDriuh_cPt; - - case Hexagon::LDriuh_cdnNotPt : - return Hexagon::LDriuh_cNotPt; - - case Hexagon::LDriuh_indexed_cdnPt : - return Hexagon::LDriuh_indexed_cPt; - - case Hexagon::LDriuh_indexed_cdnNotPt : - return Hexagon::LDriuh_indexed_cNotPt; - - case Hexagon::POST_LDriuh_cdnPt_V4 : - return Hexagon::POST_LDriuh_cPt; - - case Hexagon::POST_LDriuh_cdnNotPt_V4 : - return Hexagon::POST_LDriuh_cNotPt; - - // Load unsigned byte - case Hexagon::LDriub_cdnPt : - return Hexagon::LDriub_cPt; - - case Hexagon::LDriub_cdnNotPt : - return Hexagon::LDriub_cNotPt; - - case Hexagon::LDriub_indexed_cdnPt : - return Hexagon::LDriub_indexed_cPt; - - case Hexagon::LDriub_indexed_cdnNotPt : - return Hexagon::LDriub_indexed_cNotPt; - - case Hexagon::POST_LDriub_cdnPt_V4 : - return Hexagon::POST_LDriub_cPt; - - case Hexagon::POST_LDriub_cdnNotPt_V4 : - return Hexagon::POST_LDriub_cNotPt; - - // V4 indexed+scaled Load - - case Hexagon::LDrid_indexed_shl_cdnPt_V4 : - return Hexagon::LDrid_indexed_shl_cPt_V4; - - case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDrid_indexed_shl_cNotPt_V4; - - case Hexagon::LDrib_indexed_shl_cdnPt_V4 : - return Hexagon::LDrib_indexed_shl_cPt_V4; - - case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDrib_indexed_shl_cNotPt_V4; - - case Hexagon::LDriub_indexed_shl_cdnPt_V4 : - return Hexagon::LDriub_indexed_shl_cPt_V4; - - case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDriub_indexed_shl_cNotPt_V4; - - case Hexagon::LDrih_indexed_shl_cdnPt_V4 : - return Hexagon::LDrih_indexed_shl_cPt_V4; - - case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDrih_indexed_shl_cNotPt_V4; - - case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : - return Hexagon::LDriuh_indexed_shl_cPt_V4; - - case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDriuh_indexed_shl_cNotPt_V4; - - case Hexagon::LDriw_indexed_shl_cdnPt_V4 : - return Hexagon::LDriw_indexed_shl_cPt_V4; - - case Hexagon::LDriw_indexed_shl_cdnNotPt_V4 : - return Hexagon::LDriw_indexed_shl_cNotPt_V4; - - // V4 global address load - - case Hexagon::LDd_GP_cdnPt_V4: - return Hexagon::LDd_GP_cPt_V4; - - case Hexagon::LDd_GP_cdnNotPt_V4: - return Hexagon::LDd_GP_cNotPt_V4; - - case Hexagon::LDb_GP_cdnPt_V4: - return Hexagon::LDb_GP_cPt_V4; - - case Hexagon::LDb_GP_cdnNotPt_V4: - return Hexagon::LDb_GP_cNotPt_V4; - - case Hexagon::LDub_GP_cdnPt_V4: - return Hexagon::LDub_GP_cPt_V4; - - case Hexagon::LDub_GP_cdnNotPt_V4: - return Hexagon::LDub_GP_cNotPt_V4; - - case Hexagon::LDh_GP_cdnPt_V4: - return Hexagon::LDh_GP_cPt_V4; - - case Hexagon::LDh_GP_cdnNotPt_V4: - return Hexagon::LDh_GP_cNotPt_V4; - - case Hexagon::LDuh_GP_cdnPt_V4: - return Hexagon::LDuh_GP_cPt_V4; - - case Hexagon::LDuh_GP_cdnNotPt_V4: - return Hexagon::LDuh_GP_cNotPt_V4; - - case Hexagon::LDw_GP_cdnPt_V4: - return Hexagon::LDw_GP_cPt_V4; - - case Hexagon::LDw_GP_cdnNotPt_V4: - return Hexagon::LDw_GP_cNotPt_V4; - - // Conditional add - - case Hexagon::ADD_ri_cdnPt : - return Hexagon::ADD_ri_cPt; - case Hexagon::ADD_ri_cdnNotPt : - return Hexagon::ADD_ri_cNotPt; - - case Hexagon::ADD_rr_cdnPt : - return Hexagon::ADD_rr_cPt; - case Hexagon::ADD_rr_cdnNotPt: - return Hexagon::ADD_rr_cNotPt; - - // Conditional logical Operations - - case Hexagon::XOR_rr_cdnPt : - return Hexagon::XOR_rr_cPt; - case Hexagon::XOR_rr_cdnNotPt : - return Hexagon::XOR_rr_cNotPt; - - case Hexagon::AND_rr_cdnPt : - return Hexagon::AND_rr_cPt; - case Hexagon::AND_rr_cdnNotPt : - return Hexagon::AND_rr_cNotPt; - - case Hexagon::OR_rr_cdnPt : - return Hexagon::OR_rr_cPt; - case Hexagon::OR_rr_cdnNotPt : - return Hexagon::OR_rr_cNotPt; - - // Conditional Subtract - - case Hexagon::SUB_rr_cdnPt : - return Hexagon::SUB_rr_cPt; - case Hexagon::SUB_rr_cdnNotPt : - return Hexagon::SUB_rr_cNotPt; - - // Conditional combine - - case Hexagon::COMBINE_rr_cdnPt : - return Hexagon::COMBINE_rr_cPt; - case Hexagon::COMBINE_rr_cdnNotPt : - return Hexagon::COMBINE_rr_cNotPt; - -// Conditional shift operations - - case Hexagon::ASLH_cdnPt_V4 : - return Hexagon::ASLH_cPt_V4; - case Hexagon::ASLH_cdnNotPt_V4 : - return Hexagon::ASLH_cNotPt_V4; - - case Hexagon::ASRH_cdnPt_V4 : - return Hexagon::ASRH_cPt_V4; - case Hexagon::ASRH_cdnNotPt_V4 : - return Hexagon::ASRH_cNotPt_V4; - - case Hexagon::SXTB_cdnPt_V4 : - return Hexagon::SXTB_cPt_V4; - case Hexagon::SXTB_cdnNotPt_V4 : - return Hexagon::SXTB_cNotPt_V4; - - case Hexagon::SXTH_cdnPt_V4 : - return Hexagon::SXTH_cPt_V4; - case Hexagon::SXTH_cdnNotPt_V4 : - return Hexagon::SXTH_cNotPt_V4; - - case Hexagon::ZXTB_cdnPt_V4 : - return Hexagon::ZXTB_cPt_V4; - case Hexagon::ZXTB_cdnNotPt_V4 : - return Hexagon::ZXTB_cNotPt_V4; - - case Hexagon::ZXTH_cdnPt_V4 : - return Hexagon::ZXTH_cPt_V4; - case Hexagon::ZXTH_cdnNotPt_V4 : - return Hexagon::ZXTH_cNotPt_V4; - - // Store byte - - case Hexagon::STrib_imm_cdnPt_V4 : - return Hexagon::STrib_imm_cPt_V4; - - case Hexagon::STrib_imm_cdnNotPt_V4 : - return Hexagon::STrib_imm_cNotPt_V4; - - case Hexagon::STrib_cdnPt_nv_V4 : - case Hexagon::STrib_cPt_nv_V4 : - case Hexagon::STrib_cdnPt_V4 : - return Hexagon::STrib_cPt; - - case Hexagon::STrib_cdnNotPt_nv_V4 : - case Hexagon::STrib_cNotPt_nv_V4 : - case Hexagon::STrib_cdnNotPt_V4 : - return Hexagon::STrib_cNotPt; - - case Hexagon::STrib_indexed_cdnPt_V4 : - case Hexagon::STrib_indexed_cPt_nv_V4 : - case Hexagon::STrib_indexed_cdnPt_nv_V4 : - return Hexagon::STrib_indexed_cPt; - - case Hexagon::STrib_indexed_cdnNotPt_V4 : - case Hexagon::STrib_indexed_cNotPt_nv_V4 : - case Hexagon::STrib_indexed_cdnNotPt_nv_V4 : - return Hexagon::STrib_indexed_cNotPt; - - case Hexagon::STrib_indexed_shl_cdnPt_nv_V4: - case Hexagon::STrib_indexed_shl_cPt_nv_V4 : - case Hexagon::STrib_indexed_shl_cdnPt_V4 : - return Hexagon::STrib_indexed_shl_cPt_V4; - - case Hexagon::STrib_indexed_shl_cdnNotPt_nv_V4: - case Hexagon::STrib_indexed_shl_cNotPt_nv_V4 : - case Hexagon::STrib_indexed_shl_cdnNotPt_V4 : - return Hexagon::STrib_indexed_shl_cNotPt_V4; - - case Hexagon::POST_STbri_cdnPt_nv_V4 : - case Hexagon::POST_STbri_cPt_nv_V4 : - case Hexagon::POST_STbri_cdnPt_V4 : - return Hexagon::POST_STbri_cPt; - - case Hexagon::POST_STbri_cdnNotPt_nv_V4 : - case Hexagon::POST_STbri_cNotPt_nv_V4: - case Hexagon::POST_STbri_cdnNotPt_V4 : - return Hexagon::POST_STbri_cNotPt; - - case Hexagon::STb_GP_cdnPt_nv_V4: - case Hexagon::STb_GP_cdnPt_V4: - case Hexagon::STb_GP_cPt_nv_V4: - return Hexagon::STb_GP_cPt_V4; - - case Hexagon::STb_GP_cdnNotPt_nv_V4: - case Hexagon::STb_GP_cdnNotPt_V4: - case Hexagon::STb_GP_cNotPt_nv_V4: - return Hexagon::STb_GP_cNotPt_V4; - - // Store new-value byte - unconditional - case Hexagon::STrib_nv_V4: - return Hexagon::STrib; - - case Hexagon::STrib_indexed_nv_V4: - return Hexagon::STrib_indexed; - - case Hexagon::STrib_indexed_shl_nv_V4: - return Hexagon::STrib_indexed_shl_V4; - - case Hexagon::STrib_shl_nv_V4: - return Hexagon::STrib_shl_V4; - - case Hexagon::STb_GP_nv_V4: - return Hexagon::STb_GP_V4; - - case Hexagon::POST_STbri_nv_V4: - return Hexagon::POST_STbri; - - // Store halfword - case Hexagon::STrih_imm_cdnPt_V4 : - return Hexagon::STrih_imm_cPt_V4; - - case Hexagon::STrih_imm_cdnNotPt_V4 : - return Hexagon::STrih_imm_cNotPt_V4; - - case Hexagon::STrih_cdnPt_nv_V4 : - case Hexagon::STrih_cPt_nv_V4 : - case Hexagon::STrih_cdnPt_V4 : - return Hexagon::STrih_cPt; - - case Hexagon::STrih_cdnNotPt_nv_V4 : - case Hexagon::STrih_cNotPt_nv_V4 : - case Hexagon::STrih_cdnNotPt_V4 : - return Hexagon::STrih_cNotPt; - - case Hexagon::STrih_indexed_cdnPt_nv_V4: - case Hexagon::STrih_indexed_cPt_nv_V4 : - case Hexagon::STrih_indexed_cdnPt_V4 : - return Hexagon::STrih_indexed_cPt; - - case Hexagon::STrih_indexed_cdnNotPt_nv_V4: - case Hexagon::STrih_indexed_cNotPt_nv_V4 : - case Hexagon::STrih_indexed_cdnNotPt_V4 : - return Hexagon::STrih_indexed_cNotPt; - - case Hexagon::STrih_indexed_shl_cdnPt_nv_V4 : - case Hexagon::STrih_indexed_shl_cPt_nv_V4 : - case Hexagon::STrih_indexed_shl_cdnPt_V4 : - return Hexagon::STrih_indexed_shl_cPt_V4; - - case Hexagon::STrih_indexed_shl_cdnNotPt_nv_V4 : - case Hexagon::STrih_indexed_shl_cNotPt_nv_V4 : - case Hexagon::STrih_indexed_shl_cdnNotPt_V4 : - return Hexagon::STrih_indexed_shl_cNotPt_V4; - - case Hexagon::POST_SThri_cdnPt_nv_V4 : - case Hexagon::POST_SThri_cPt_nv_V4 : - case Hexagon::POST_SThri_cdnPt_V4 : - return Hexagon::POST_SThri_cPt; - - case Hexagon::POST_SThri_cdnNotPt_nv_V4 : - case Hexagon::POST_SThri_cNotPt_nv_V4 : - case Hexagon::POST_SThri_cdnNotPt_V4 : - return Hexagon::POST_SThri_cNotPt; - - case Hexagon::STh_GP_cdnPt_nv_V4: - case Hexagon::STh_GP_cdnPt_V4: - case Hexagon::STh_GP_cPt_nv_V4: - return Hexagon::STh_GP_cPt_V4; - - case Hexagon::STh_GP_cdnNotPt_nv_V4: - case Hexagon::STh_GP_cdnNotPt_V4: - case Hexagon::STh_GP_cNotPt_nv_V4: - return Hexagon::STh_GP_cNotPt_V4; - - // Store new-value halfword - unconditional - - case Hexagon::STrih_nv_V4: - return Hexagon::STrih; - - case Hexagon::STrih_indexed_nv_V4: - return Hexagon::STrih_indexed; - - case Hexagon::STrih_indexed_shl_nv_V4: - return Hexagon::STrih_indexed_shl_V4; - - case Hexagon::STrih_shl_nv_V4: - return Hexagon::STrih_shl_V4; - - case Hexagon::STh_GP_nv_V4: - return Hexagon::STh_GP_V4; - - case Hexagon::POST_SThri_nv_V4: - return Hexagon::POST_SThri; - - // Store word - - case Hexagon::STriw_imm_cdnPt_V4 : - return Hexagon::STriw_imm_cPt_V4; - - case Hexagon::STriw_imm_cdnNotPt_V4 : - return Hexagon::STriw_imm_cNotPt_V4; - - case Hexagon::STriw_cdnPt_nv_V4 : - case Hexagon::STriw_cPt_nv_V4 : - case Hexagon::STriw_cdnPt_V4 : - return Hexagon::STriw_cPt; - - case Hexagon::STriw_cdnNotPt_nv_V4 : - case Hexagon::STriw_cNotPt_nv_V4 : - case Hexagon::STriw_cdnNotPt_V4 : - return Hexagon::STriw_cNotPt; - - case Hexagon::STriw_indexed_cdnPt_nv_V4 : - case Hexagon::STriw_indexed_cPt_nv_V4 : - case Hexagon::STriw_indexed_cdnPt_V4 : - return Hexagon::STriw_indexed_cPt; - - case Hexagon::STriw_indexed_cdnNotPt_nv_V4 : - case Hexagon::STriw_indexed_cNotPt_nv_V4 : - case Hexagon::STriw_indexed_cdnNotPt_V4 : - return Hexagon::STriw_indexed_cNotPt; - - case Hexagon::STriw_indexed_shl_cdnPt_nv_V4 : - case Hexagon::STriw_indexed_shl_cPt_nv_V4 : - case Hexagon::STriw_indexed_shl_cdnPt_V4 : - return Hexagon::STriw_indexed_shl_cPt_V4; - - case Hexagon::STriw_indexed_shl_cdnNotPt_nv_V4 : - case Hexagon::STriw_indexed_shl_cNotPt_nv_V4 : - case Hexagon::STriw_indexed_shl_cdnNotPt_V4 : - return Hexagon::STriw_indexed_shl_cNotPt_V4; - - case Hexagon::POST_STwri_cdnPt_nv_V4 : - case Hexagon::POST_STwri_cPt_nv_V4 : - case Hexagon::POST_STwri_cdnPt_V4 : - return Hexagon::POST_STwri_cPt; - - case Hexagon::POST_STwri_cdnNotPt_nv_V4 : - case Hexagon::POST_STwri_cNotPt_nv_V4 : - case Hexagon::POST_STwri_cdnNotPt_V4 : - return Hexagon::POST_STwri_cNotPt; - - case Hexagon::STw_GP_cdnPt_nv_V4: - case Hexagon::STw_GP_cdnPt_V4: - case Hexagon::STw_GP_cPt_nv_V4: - return Hexagon::STw_GP_cPt_V4; - - case Hexagon::STw_GP_cdnNotPt_nv_V4: - case Hexagon::STw_GP_cdnNotPt_V4: - case Hexagon::STw_GP_cNotPt_nv_V4: - return Hexagon::STw_GP_cNotPt_V4; - - // Store new-value word - unconditional - - case Hexagon::STriw_nv_V4: - return Hexagon::STriw; - - case Hexagon::STriw_indexed_nv_V4: - return Hexagon::STriw_indexed; - - case Hexagon::STriw_indexed_shl_nv_V4: - return Hexagon::STriw_indexed_shl_V4; - - case Hexagon::STriw_shl_nv_V4: - return Hexagon::STriw_shl_V4; - - case Hexagon::STw_GP_nv_V4: - return Hexagon::STw_GP_V4; - - case Hexagon::POST_STwri_nv_V4: - return Hexagon::POST_STwri; - - // Store doubleword - - case Hexagon::STrid_cdnPt_V4 : - return Hexagon::STrid_cPt; - - case Hexagon::STrid_cdnNotPt_V4 : - return Hexagon::STrid_cNotPt; - - case Hexagon::STrid_indexed_cdnPt_V4 : - return Hexagon::STrid_indexed_cPt; - - case Hexagon::STrid_indexed_cdnNotPt_V4 : - return Hexagon::STrid_indexed_cNotPt; - - case Hexagon::STrid_indexed_shl_cdnPt_V4 : - return Hexagon::STrid_indexed_shl_cPt_V4; - - case Hexagon::STrid_indexed_shl_cdnNotPt_V4 : - return Hexagon::STrid_indexed_shl_cNotPt_V4; - - case Hexagon::POST_STdri_cdnPt_V4 : - return Hexagon::POST_STdri_cPt; - - case Hexagon::POST_STdri_cdnNotPt_V4 : - return Hexagon::POST_STdri_cNotPt; - - case Hexagon::STd_GP_cdnPt_V4 : - return Hexagon::STd_GP_cPt_V4; - - case Hexagon::STd_GP_cdnNotPt_V4 : - return Hexagon::STd_GP_cNotPt_V4; - - } -} - bool HexagonPacketizerList::DemoteToDotOld(MachineInstr* MI) { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; - int NewOpcode = GetDotOldOp(MI->getOpcode()); + int NewOpcode = QII->GetDotOldOp(MI->getOpcode()); MI->setDesc(QII->get(NewOpcode)); return true; } @@ -1221,10 +537,10 @@ static MachineOperand& GetStoreValueOperand(MachineInstr *MI) { // Arch Spec: 3.4.4.2 bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, MachineInstr *PacketMI, unsigned DepReg, - std::map MIToSUnit) -{ - // Make sure we are looking at the store - if (!IsNewifyStore(MI)) + std::map MIToSUnit) { + const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; + // Make sure we are looking at the store, that can be promoted. + if (!QII->mayBeNewStore(MI)) return false; // Make sure there is dependency and can be new value'ed @@ -1232,12 +548,11 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, GetStoreValueOperand(MI).getReg() != DepReg) return false; - const HexagonRegisterInfo* QRI = + const HexagonRegisterInfo* QRI = (const HexagonRegisterInfo *) TM.getRegisterInfo(); const MCInstrDesc& MCID = PacketMI->getDesc(); // first operand is always the result - const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; const TargetRegisterClass* PacketRC = QII->getRegClass(MCID, 0, QRI, MF); // if there is already an store in the packet, no can do new value store @@ -1280,7 +595,7 @@ bool HexagonPacketizerList::CanPromoteToNewValueStore( MachineInstr *MI, } // If the source that feeds the store is predicated, new value store must - // also be also predicated. + // also be predicated. if (QII->isPredicated(PacketMI)) { if (!QII->isPredicated(MI)) return false; @@ -1407,10 +722,11 @@ bool HexagonPacketizerList::CanPromoteToNewValue( MachineInstr *MI, MachineBasicBlock::iterator &MII) { + const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; const HexagonRegisterInfo* QRI = (const HexagonRegisterInfo *) TM.getRegisterInfo(); if (!QRI->Subtarget.hasV4TOps() || - !IsNewifyStore(MI)) + !QII->mayBeNewStore(MI)) return false; MachineInstr *PacketMI = PacketSU->getInstr(); @@ -1437,7 +753,7 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, { const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII; // Already a dot new instruction. - if (QII->isDotNewInst(MI) && !IsNewifyStore(MI)) + if (QII->isDotNewInst(MI) && !QII->mayBeNewStore(MI)) return false; if (!isNewifiable(MI)) @@ -1447,7 +763,7 @@ bool HexagonPacketizerList::CanPromoteToDotNew( MachineInstr *MI, if (RC == &Hexagon::PredRegsRegClass && isCondInst(MI)) return true; else if (RC != &Hexagon::PredRegsRegClass && - !IsNewifyStore(MI)) // MI is not a new-value store + !QII->mayBeNewStore(MI)) // MI is not a new-value store return false; else { // Create a dot new machine instruction to see if resources can be @@ -1691,24 +1007,21 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { } // A LoopN instruction cannot appear in the same packet as a jump or call. - if (IsLoopN(I) && ( IsDirectJump(J) - || MCIDJ.isCall() - || QII->isDeallocRet(J))) { + if (IsLoopN(I) && + (IsDirectJump(J) || MCIDJ.isCall() || QII->isDeallocRet(J))) { Dependence = true; return false; } - if (IsLoopN(J) && ( IsDirectJump(I) - || MCIDI.isCall() - || QII->isDeallocRet(I))) { + if (IsLoopN(J) && + (IsDirectJump(I) || MCIDI.isCall() || QII->isDeallocRet(I))) { Dependence = true; return false; } // dealloc_return cannot appear in the same packet as a conditional or // unconditional jump. - if (QII->isDeallocRet(I) && ( MCIDJ.isBranch() - || MCIDJ.isCall() - || MCIDJ.isBarrier())) { + if (QII->isDeallocRet(I) && + (MCIDJ.isBranch() || MCIDJ.isCall() || MCIDJ.isBarrier())) { Dependence = true; return false; } @@ -1733,7 +1046,7 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { } //if dealloc_return - if (MCIDJ.mayStore() && QII->isDeallocRet(I)){ + if (MCIDJ.mayStore() && QII->isDeallocRet(I)) { Dependence = true; return false; } -- cgit v1.2.3 From fd4ccda4a56d1664b43ca7ed9909254f6de592bb Mon Sep 17 00:00:00 2001 From: Jyotsna Verma Date: Fri, 10 May 2013 21:44:02 +0000 Subject: Fix unused variable error. Earlier, this variable was used in an assert and was causing failure on darwin. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181630 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonFrameLowering.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp index 77ad70dd6c..0fda4edf86 100644 --- a/lib/Target/Hexagon/HexagonFrameLowering.cpp +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -184,8 +184,7 @@ void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); // Handle EH_RETURN. if (MBBI->getOpcode() == Hexagon::EH_RETURN_JMPR) { - MachineOperand &OffsetReg = MBBI->getOperand(0); - assert(OffsetReg.isReg() && "Offset should be in register!"); + assert(MBBI->getOperand(0).isReg() && "Offset should be in register!"); BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)); BuildMI(MBB, MBBI, dl, TII.get(Hexagon::ADD_rr), Hexagon::R29).addReg(Hexagon::R29).addReg(Hexagon::R28); -- cgit v1.2.3 From 4de9d72883eebe4e86bffdaad89483dfe822e2a5 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 10 May 2013 21:52:07 +0000 Subject: PR14492: Debug Info: Support for values of non-integer non-type template parameters. This is only tested for global variables at the moment (& includes tests for the unnamed parameter case, since apparently this entire function was completely untested previously) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181632 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DIBuilder.h | 7 ++- include/llvm/DebugInfo.h | 2 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 20 ++++++- lib/IR/DIBuilder.cpp | 4 +- lib/IR/DebugInfo.cpp | 4 ++ test/DebugInfo/template.ll | 84 +++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 test/DebugInfo/template.ll diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index 4ce884b736..bb1bdd7017 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -332,10 +332,9 @@ namespace llvm { /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - uint64_t Value, - MDNode *File = 0, unsigned LineNo = 0, - unsigned ColumnNo = 0); + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, + DIType Ty, Value *Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index 5f92ca22ec..91c3066338 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -401,7 +401,7 @@ namespace llvm { DIScope getContext() const { return getFieldAs(1); } StringRef getName() const { return getStringField(2); } DIType getType() const { return getFieldAs(3); } - uint64_t getValue() const { return getUInt64Field(4); } + Value *getValue() const; StringRef getFilename() const { return getFieldAs(5).getFilename(); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index c38ada6b66..7f0c33bb05 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -588,6 +588,9 @@ static bool isTypeSigned(DIType Ty, int *SizeInBits) { /// addConstantValue - Add constant value entry in variable DIE. bool CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty) { + // FIXME: This is a bit conservative/simple - it emits negative values at + // their maximum bit width which is a bit unfortunate (& doesn't prefer + // udata/sdata over dataN as suggested by the DWARF spec) assert(MO.isImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); int SizeInBits = -1; @@ -1095,8 +1098,21 @@ CompileUnit::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV){ addType(ParamDIE, TPV.getType()); if (!TPV.getName().empty()) addString(ParamDIE, dwarf::DW_AT_name, TPV.getName()); - addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - TPV.getValue()); + if (Value *Val = TPV.getValue()) { + if (ConstantInt *CI = dyn_cast(Val)) + addConstantValue(ParamDIE, CI, TPV.getType().isUnsignedDIType()); + else if (GlobalValue *GV = dyn_cast(Val)) { + // For declaration non-type template parameters (such as global values and + // functions) + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + addOpAddress(Block, Asm->Mang->getSymbol(GV)); + // Emit DW_OP_stack_value to use the address as the immediate value of the + // parameter, rather than a pointer to it. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); + addBlock(ParamDIE, dwarf::DW_AT_location, 0, Block); + } + } + return ParamDIE; } diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index eb220b2349..4bb87c9afb 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -502,7 +502,7 @@ DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, /// value parameter. DITemplateValueParameter DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, - DIType Ty, uint64_t Val, + DIType Ty, Value *Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { @@ -510,7 +510,7 @@ DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, getNonCompileUnitScope(Context), MDString::get(VMContext, Name), Ty, - ConstantInt::get(Type::getInt64Ty(VMContext), Val), + Val, File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 38fc90f865..8a0fb8d5b1 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -695,6 +695,10 @@ DIArray DISubprogram::getVariables() const { return DIArray(); } +Value *DITemplateValueParameter::getValue() const { + return getField(DbgNode, 4); +} + void DIScope::setFilename(StringRef Name, LLVMContext &Context) { if (!DbgNode) return; diff --git a/test/DebugInfo/template.ll b/test/DebugInfo/template.ll new file mode 100644 index 0000000000..47173550c6 --- /dev/null +++ b/test/DebugInfo/template.ll @@ -0,0 +1,84 @@ +; REQUIRES: object-emission + +; RUN: llc -O0 -filetype=obj < %s > %t +; RUN: llvm-dwarfdump %t | FileCheck %s + +; IR generated with `clang++ -g -emit-llvm -S` from the following code: +; template func() { } +; int glbl = func<3, &glbl>(); + +; CHECK: [[INT:0x[0-9a-f]*]]:{{ *}}DW_TAG_base_type +; CHECK-NEXT: DW_AT_name{{.*}} = "int" + +; CHECK: DW_AT_name{{.*}}"func<3, &glbl>" +; CHECK-NOT: NULL +; CHECK: DW_TAG_template_value_parameter +; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INT]]} +; CHECK-NEXT: DW_AT_name{{.*}}= "x" + +; This could be made shorter by encoding it as _sdata rather than data4, or +; even as data1. DWARF strongly urges implementations to prefer +; _sdata/_udata rather than dataN + +; CHECK-NEXT: DW_AT_const_value [DW_FORM_data4]{{.*}}(0x00000003) + +; CHECK: DW_TAG_template_value_parameter +; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INTPTR:0x[0-9a-f]*]]} + +; The address of the global 'glbl', followed by DW_OP_stack_value (9f), to use +; the value immediately, rather than indirecting through the address. + +; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{ *}}(<0x0a> 03 00 00 00 00 00 00 00 00 9f ) + +; CHECK: [[INTPTR]]:{{ *}}DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type{{.*}} => {[[INT]]} + +@glbl = global i32 0, align 4 +@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] + +define internal void @__cxx_global_var_init() section ".text.startup" { +entry: + %call = call i32 @_Z4funcILi3EXadL_Z4glblEEEiv(), !dbg !20 + store i32 %call, i32* @glbl, align 4, !dbg !20 + ret void, !dbg !20 +} + +; Function Attrs: nounwind uwtable +define linkonce_odr i32 @_Z4funcILi3EXadL_Z4glblEEEiv() #0 { +entry: + ret i32 3, !dbg !21 +} + +define internal void @_GLOBAL__I_a() section ".text.startup" { +entry: + call void @__cxx_global_var_init(), !dbg !22 + ret void, !dbg !22 +} + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} + +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !18, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] [DW_LANG_C_plus_plus] +!1 = metadata !{metadata !"templ.cpp", metadata !"/usr/local/google/home/blaikie/dev/scratch"} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4, metadata !8, metadata !16} +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"__cxx_global_var_init", metadata !"__cxx_global_var_init", metadata !"", i32 2, metadata !6, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @__cxx_global_var_init, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 2] [local] [def] [__cxx_global_var_init] +!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] +!6 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = metadata !{null} +!8 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"func<3, &glbl>", metadata !"func<3, &glbl>", metadata !"_Z4funcILi3EXadL_Z4glblEEEiv", i32 1, metadata !9, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z4funcILi3EXadL_Z4glblEEEiv, metadata !12, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [func<3, &glbl>] +!9 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !10, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!10 = metadata !{metadata !11} +!11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!12 = metadata !{metadata !13, metadata !14} +!13 = metadata !{i32 786480, null, metadata !"x", metadata !11, i32 3, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] +!14 = metadata !{i32 786480, null, metadata !"", metadata !15, i32* @glbl, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] +!15 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] +!16 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"_GLOBAL__I_a", metadata !"_GLOBAL__I_a", metadata !"", i32 1, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i32 64, i1 false, void ()* @_GLOBAL__I_a, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [local] [def] [_GLOBAL__I_a] +!17 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!18 = metadata !{metadata !19} +!19 = metadata !{i32 786484, i32 0, null, metadata !"glbl", metadata !"glbl", metadata !"", metadata !5, i32 2, metadata !11, i32 0, i32 1, i32* @glbl, null} ; [ DW_TAG_variable ] [glbl] [line 2] [def] +!20 = metadata !{i32 2, i32 0, metadata !4, null} +!21 = metadata !{i32 1, i32 0, metadata !8, null} +!22 = metadata !{i32 1, i32 0, metadata !16, null} -- cgit v1.2.3 From acd1d031b84e76f6fbb35601b337359cab436022 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 10 May 2013 22:14:39 +0000 Subject: Give the test from r181632 a target triple. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181637 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/DebugInfo/X86/template.ll | 84 ++++++++++++++++++++++++++++++++++++++++++ test/DebugInfo/template.ll | 84 ------------------------------------------ 2 files changed, 84 insertions(+), 84 deletions(-) create mode 100644 test/DebugInfo/X86/template.ll delete mode 100644 test/DebugInfo/template.ll diff --git a/test/DebugInfo/X86/template.ll b/test/DebugInfo/X86/template.ll new file mode 100644 index 0000000000..817bdc9cf7 --- /dev/null +++ b/test/DebugInfo/X86/template.ll @@ -0,0 +1,84 @@ +; REQUIRES: object-emission + +; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %s > %t +; RUN: llvm-dwarfdump %t | FileCheck %s + +; IR generated with `clang++ -g -emit-llvm -S` from the following code: +; template func() { } +; int glbl = func<3, &glbl>(); + +; CHECK: [[INT:0x[0-9a-f]*]]:{{ *}}DW_TAG_base_type +; CHECK-NEXT: DW_AT_name{{.*}} = "int" + +; CHECK: DW_AT_name{{.*}}"func<3, &glbl>" +; CHECK-NOT: NULL +; CHECK: DW_TAG_template_value_parameter +; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INT]]} +; CHECK-NEXT: DW_AT_name{{.*}}= "x" + +; This could be made shorter by encoding it as _sdata rather than data4, or +; even as data1. DWARF strongly urges implementations to prefer +; _sdata/_udata rather than dataN + +; CHECK-NEXT: DW_AT_const_value [DW_FORM_data4]{{.*}}(0x00000003) + +; CHECK: DW_TAG_template_value_parameter +; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INTPTR:0x[0-9a-f]*]]} + +; The address of the global 'glbl', followed by DW_OP_stack_value (9f), to use +; the value immediately, rather than indirecting through the address. + +; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{ *}}(<0x0a> 03 00 00 00 00 00 00 00 00 9f ) + +; CHECK: [[INTPTR]]:{{ *}}DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type{{.*}} => {[[INT]]} + +@glbl = global i32 0, align 4 +@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] + +define internal void @__cxx_global_var_init() section ".text.startup" { +entry: + %call = call i32 @_Z4funcILi3EXadL_Z4glblEEEiv(), !dbg !20 + store i32 %call, i32* @glbl, align 4, !dbg !20 + ret void, !dbg !20 +} + +; Function Attrs: nounwind uwtable +define linkonce_odr i32 @_Z4funcILi3EXadL_Z4glblEEEiv() #0 { +entry: + ret i32 3, !dbg !21 +} + +define internal void @_GLOBAL__I_a() section ".text.startup" { +entry: + call void @__cxx_global_var_init(), !dbg !22 + ret void, !dbg !22 +} + +attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} + +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !18, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] [DW_LANG_C_plus_plus] +!1 = metadata !{metadata !"templ.cpp", metadata !"/usr/local/google/home/blaikie/dev/scratch"} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4, metadata !8, metadata !16} +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"__cxx_global_var_init", metadata !"__cxx_global_var_init", metadata !"", i32 2, metadata !6, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @__cxx_global_var_init, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 2] [local] [def] [__cxx_global_var_init] +!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] +!6 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = metadata !{null} +!8 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"func<3, &glbl>", metadata !"func<3, &glbl>", metadata !"_Z4funcILi3EXadL_Z4glblEEEiv", i32 1, metadata !9, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z4funcILi3EXadL_Z4glblEEEiv, metadata !12, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [func<3, &glbl>] +!9 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !10, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!10 = metadata !{metadata !11} +!11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!12 = metadata !{metadata !13, metadata !14} +!13 = metadata !{i32 786480, null, metadata !"x", metadata !11, i32 3, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] +!14 = metadata !{i32 786480, null, metadata !"", metadata !15, i32* @glbl, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] +!15 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] +!16 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"_GLOBAL__I_a", metadata !"_GLOBAL__I_a", metadata !"", i32 1, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i32 64, i1 false, void ()* @_GLOBAL__I_a, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [local] [def] [_GLOBAL__I_a] +!17 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!18 = metadata !{metadata !19} +!19 = metadata !{i32 786484, i32 0, null, metadata !"glbl", metadata !"glbl", metadata !"", metadata !5, i32 2, metadata !11, i32 0, i32 1, i32* @glbl, null} ; [ DW_TAG_variable ] [glbl] [line 2] [def] +!20 = metadata !{i32 2, i32 0, metadata !4, null} +!21 = metadata !{i32 1, i32 0, metadata !8, null} +!22 = metadata !{i32 1, i32 0, metadata !16, null} diff --git a/test/DebugInfo/template.ll b/test/DebugInfo/template.ll deleted file mode 100644 index 47173550c6..0000000000 --- a/test/DebugInfo/template.ll +++ /dev/null @@ -1,84 +0,0 @@ -; REQUIRES: object-emission - -; RUN: llc -O0 -filetype=obj < %s > %t -; RUN: llvm-dwarfdump %t | FileCheck %s - -; IR generated with `clang++ -g -emit-llvm -S` from the following code: -; template func() { } -; int glbl = func<3, &glbl>(); - -; CHECK: [[INT:0x[0-9a-f]*]]:{{ *}}DW_TAG_base_type -; CHECK-NEXT: DW_AT_name{{.*}} = "int" - -; CHECK: DW_AT_name{{.*}}"func<3, &glbl>" -; CHECK-NOT: NULL -; CHECK: DW_TAG_template_value_parameter -; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INT]]} -; CHECK-NEXT: DW_AT_name{{.*}}= "x" - -; This could be made shorter by encoding it as _sdata rather than data4, or -; even as data1. DWARF strongly urges implementations to prefer -; _sdata/_udata rather than dataN - -; CHECK-NEXT: DW_AT_const_value [DW_FORM_data4]{{.*}}(0x00000003) - -; CHECK: DW_TAG_template_value_parameter -; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INTPTR:0x[0-9a-f]*]]} - -; The address of the global 'glbl', followed by DW_OP_stack_value (9f), to use -; the value immediately, rather than indirecting through the address. - -; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{ *}}(<0x0a> 03 00 00 00 00 00 00 00 00 9f ) - -; CHECK: [[INTPTR]]:{{ *}}DW_TAG_pointer_type -; CHECK-NEXT: DW_AT_type{{.*}} => {[[INT]]} - -@glbl = global i32 0, align 4 -@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] - -define internal void @__cxx_global_var_init() section ".text.startup" { -entry: - %call = call i32 @_Z4funcILi3EXadL_Z4glblEEEiv(), !dbg !20 - store i32 %call, i32* @glbl, align 4, !dbg !20 - ret void, !dbg !20 -} - -; Function Attrs: nounwind uwtable -define linkonce_odr i32 @_Z4funcILi3EXadL_Z4glblEEEiv() #0 { -entry: - ret i32 3, !dbg !21 -} - -define internal void @_GLOBAL__I_a() section ".text.startup" { -entry: - call void @__cxx_global_var_init(), !dbg !22 - ret void, !dbg !22 -} - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -!llvm.dbg.cu = !{!0} - -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !18, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] [DW_LANG_C_plus_plus] -!1 = metadata !{metadata !"templ.cpp", metadata !"/usr/local/google/home/blaikie/dev/scratch"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4, metadata !8, metadata !16} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"__cxx_global_var_init", metadata !"__cxx_global_var_init", metadata !"", i32 2, metadata !6, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @__cxx_global_var_init, null, null, metadata !2, i32 2} ; [ DW_TAG_subprogram ] [line 2] [local] [def] [__cxx_global_var_init] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/usr/local/google/home/blaikie/dev/scratch/templ.cpp] -!6 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{null} -!8 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"func<3, &glbl>", metadata !"func<3, &glbl>", metadata !"_Z4funcILi3EXadL_Z4glblEEEiv", i32 1, metadata !9, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @_Z4funcILi3EXadL_Z4glblEEEiv, metadata !12, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [func<3, &glbl>] -!9 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !10, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!10 = metadata !{metadata !11} -!11 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!12 = metadata !{metadata !13, metadata !14} -!13 = metadata !{i32 786480, null, metadata !"x", metadata !11, i32 3, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] -!14 = metadata !{i32 786480, null, metadata !"", metadata !15, i32* @glbl, null, i32 0, i32 0} ; [ DW_TAG_template_value_parameter ] -!15 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int] -!16 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"_GLOBAL__I_a", metadata !"_GLOBAL__I_a", metadata !"", i32 1, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i32 64, i1 false, void ()* @_GLOBAL__I_a, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [local] [def] [_GLOBAL__I_a] -!17 = metadata !{i32 786453, i32 0, i32 0, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!18 = metadata !{metadata !19} -!19 = metadata !{i32 786484, i32 0, null, metadata !"glbl", metadata !"glbl", metadata !"", metadata !5, i32 2, metadata !11, i32 0, i32 1, i32* @glbl, null} ; [ DW_TAG_variable ] [glbl] [line 2] [def] -!20 = metadata !{i32 2, i32 0, metadata !4, null} -!21 = metadata !{i32 1, i32 0, metadata !8, null} -!22 = metadata !{i32 1, i32 0, metadata !16, null} -- cgit v1.2.3 From 1197e38f3338b8db76f0fa38c2687c65b2bcea5c Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 10 May 2013 22:17:10 +0000 Subject: Micro-optimization: don't shift an entire bitcode record over to get the code. Previously, BitstreamCursor read an abbreviated record by splatting the whole thing into a data vector, then extracting and removing the /first/ element. Now, it reads the first element--the record code--separately from the actual field values. No (intended) functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181639 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitstreamReader.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index 9dafe2a036..1fd9abd8b1 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -204,7 +204,16 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); - for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + // Read the record code first. + assert(Abbv->getNumOperandInfos() != 0 && "no record code in abbreviation?"); + const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0); + if (CodeOp.isLiteral()) + readAbbreviatedLiteral(CodeOp, Vals); + else + readAbbreviatedField(CodeOp, Vals); + unsigned Code = (unsigned)Vals.pop_back_val(); + + for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); if (Op.isLiteral()) { readAbbreviatedLiteral(Op, Vals); @@ -264,8 +273,6 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, JumpToBit(NewEnd); } - unsigned Code = (unsigned)Vals[0]; - Vals.erase(Vals.begin()); return Code; } -- cgit v1.2.3 From 46090914b783b632618268f2a5c99aab83732688 Mon Sep 17 00:00:00 2001 From: Reed Kotler Date: Fri, 10 May 2013 22:25:39 +0000 Subject: Checkin in of first of several patches to finish implementation of mips16/mips32 floating point interoperability. This patch fixes returns from mips16 functions so that if the function was in fact called by a mips32 hard float routine, then values that would have been returned in floating point registers are so returned. Mips16 mode has no floating point instructions so there is no way to load values into floating point registers. This is needed when returning float, double, single complex, double complex in the Mips ABI. Helper functions in libc for mips16 are available to do this. For efficiency purposes, these helper functions have a different calling convention from normal Mips calls. Registers v0,v1,a0,a1 are used to pass parameters instead of a0,a1,a2,a3. This is because v0,v1,a0,a1 are the natural registers used to return floating point values in soft float. These values can then be moved to the appropriate floating point registers with no extra cost. The only register that is modified is ra in this call. The helper functions make sure that the return values are in the floating point registers that they would be in if soft float was not in effect (which it is for mips16, though the soft float is implemented using a mips32 library that uses hard float). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181641 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/CMakeLists.txt | 1 + lib/Target/Mips/Mips16HardFloat.cpp | 141 +++++++++++++++++++++++++++++++++ lib/Target/Mips/Mips16HardFloat.h | 54 +++++++++++++ lib/Target/Mips/Mips16ISelLowering.cpp | 11 +-- lib/Target/Mips/MipsCallingConv.td | 10 +++ lib/Target/Mips/MipsISelLowering.cpp | 40 +++++++++- lib/Target/Mips/MipsISelLowering.h | 14 +++- lib/Target/Mips/MipsRegisterInfo.cpp | 4 + lib/Target/Mips/MipsRegisterInfo.h | 1 + lib/Target/Mips/MipsSubtarget.cpp | 8 +- lib/Target/Mips/MipsSubtarget.h | 11 ++- lib/Target/Mips/MipsTargetMachine.cpp | 3 + test/CodeGen/Mips/mips16_fpret.ll | 77 ++++++++++++++++++ 13 files changed, 359 insertions(+), 16 deletions(-) create mode 100644 lib/Target/Mips/Mips16HardFloat.cpp create mode 100644 lib/Target/Mips/Mips16HardFloat.h create mode 100644 test/CodeGen/Mips/mips16_fpret.ll diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 78a9f70c66..8be68c5b4f 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -15,6 +15,7 @@ add_public_tablegen_target(MipsCommonTableGen) add_llvm_target(MipsCodeGen Mips16FrameLowering.cpp + Mips16HardFloat.cpp Mips16InstrInfo.cpp Mips16ISelDAGToDAG.cpp Mips16ISelLowering.cpp diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp new file mode 100644 index 0000000000..4d1e61bb99 --- /dev/null +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -0,0 +1,141 @@ +//===---- Mips16HardFloat.cpp for Mips16 Hard Float --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pass needed for Mips16 Hard Float +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips16-hard-float" +#include "Mips16HardFloat.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include + +// +// Return types that matter for hard float are: +// float, double, complex float, and complex double +// +enum FPReturnVariant { + FRet, DRet, CFRet, CDRet, NoFPRet +}; + +// +// Determine which FP return type this function has +// +static FPReturnVariant whichFPReturnVariant(Type *T) { + switch (T->getTypeID()) { + case Type::FloatTyID: + return FRet; + case Type::DoubleTyID: + return DRet; + case Type::StructTyID: + if (T->getStructNumElements() != 2) + break; + if ((T->getContainedType(0)->isFloatTy()) && + (T->getContainedType(1)->isFloatTy())) + return CFRet; + if ((T->getContainedType(0)->isDoubleTy()) && + (T->getContainedType(1)->isDoubleTy())) + return CDRet; + break; + default: + break; + } + return NoFPRet; +} + +// +// Returns of float, double and complex need to be handled with a helper +// function. The "AndCal" part is coming in a later patch. +// +static bool fixupFPReturnAndCall + (Function &F, Module *M, const MipsSubtarget &Subtarget) { + bool Modified = false; + LLVMContext &C = M->getContext(); + Type *MyVoid = Type::getVoidTy(C); + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + Instruction &Inst = *I; + if (const ReturnInst *RI = dyn_cast(I)) { + Value *RVal = RI->getReturnValue(); + if (!RVal) continue; + // + // If there is a return value and it needs a helper function, + // figure out which one and add a call before the actual + // return to this helper. The purpose of the helper is to move + // floating point values from their soft float return mapping to + // where they would have been mapped to in floating point registers. + // + Type *T = RVal->getType(); + FPReturnVariant RV = whichFPReturnVariant(T); + if (RV == NoFPRet) continue; + static const char* Helper[NoFPRet] = + {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc", + "__mips16_ret_dc"}; + const char *Name = Helper[RV]; + AttributeSet A; + Value *Params[] = {RVal}; + Modified = true; + // + // These helper functions have a different calling ABI so + // this __Mips16RetHelper indicates that so that later + // during call setup, the proper call lowering to the helper + // functions will take place. + // + A = A.addAttribute(C, AttributeSet::FunctionIndex, + "__Mips16RetHelper"); + A = A.addAttribute(C, AttributeSet::FunctionIndex, + Attribute::ReadNone); + Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL)); + CallInst::Create(F, Params, "", &Inst ); + } + } + return Modified; +} + +namespace llvm { + +// +// This pass only makes sense when the underlying chip has floating point but +// we are compiling as mips16. +// For all mips16 functions (that are not stubs we have already generated), or +// declared via attributes as nomips16, we must: +// 1) fixup all returns of float, double, single and double complex +// by calling a helper function before the actual return. +// 2) generate helper functions (stubs) that can be called by mips32 functions +// that will move parameters passed normally passed in floating point +// registers the soft float equivalents. (Coming in a later patch). +// 3) in the case of static relocation, generate helper functions so that +// mips16 functions can call extern functions of unknown type (mips16 or +// mips32). (Coming in a later patch). +// 4) TBD. For pic, calls to extern functions of unknown type are handled by +// predefined helper functions in libc but this work is currently done +// during call lowering but it should be moved here in the future. +// +bool Mips16HardFloat::runOnModule(Module &M) { + DEBUG(errs() << "Run on Module Mips16HardFloat\n"); + bool Modified = false; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") || + F->hasFnAttribute("nomips16")) continue; + Modified |= fixupFPReturnAndCall(*F, &M, Subtarget); + } + return Modified; +} + +char Mips16HardFloat::ID = 0; + +} + +ModulePass *llvm::createMips16HardFloat(MipsTargetMachine &TM) { + return new Mips16HardFloat(TM); +} + diff --git a/lib/Target/Mips/Mips16HardFloat.h b/lib/Target/Mips/Mips16HardFloat.h new file mode 100644 index 0000000000..b7f712af5b --- /dev/null +++ b/lib/Target/Mips/Mips16HardFloat.h @@ -0,0 +1,54 @@ +//===---- Mips16HardFloat.h for Mips16 Hard Float --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a phase which implements part of the floating point +// interoperability between Mips16 and Mips32 code. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MipsTargetMachine.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + + +#ifndef MIPS16HARDFLOAT_H +#define MIPS16HARDFLOAT_H + +using namespace llvm; + +namespace llvm { + +class Mips16HardFloat : public ModulePass { + +public: + static char ID; + + Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), + TM(TM_), Subtarget(TM.getSubtarget()) { + } + + virtual const char *getPassName() const { + return "MIPS16 Hard Float Pass"; + } + + virtual bool runOnModule(Module &M); + +protected: + /// Keep a pointer to the MipsSubtarget around so that we can make the right + /// decision when generating code for different targets. + const TargetMachine &TM; + const MipsSubtarget &Subtarget; + +}; + +ModulePass *createMips16HardFloat(MipsTargetMachine &TM); + +} +#endif diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index f63318f1e6..c633d312bb 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "mips-lower" #include "Mips16ISelLowering.h" #include "MipsRegisterInfo.h" +#include "MipsTargetMachine.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Support/CommandLine.h" @@ -21,11 +22,6 @@ using namespace llvm; -static cl::opt -Mips16HardFloat("mips16-hard-float", cl::NotHidden, - cl::desc("MIPS: mips16 hard float enable."), - cl::init(false)); - static cl::opt DontExpandCondPseudos16( "mips16-dont-expand-cond-pseudo", cl::init(false), @@ -50,7 +46,7 @@ Mips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM) // Set up the register classes addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass); - if (Mips16HardFloat) + if (Subtarget->inMips16HardFloat()) setMips16HardFloatLibCalls(); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); @@ -374,7 +370,8 @@ getOpndList(SmallVectorImpl &Ops, const char* Mips16HelperFunction = 0; bool NeedMips16Helper = false; - if (getTargetMachine().Options.UseSoftFloat && Mips16HardFloat) { + if (getTargetMachine().Options.UseSoftFloat && + Subtarget->inMips16HardFloat()) { // // currently we don't have symbols tagged with the mips16 or mips32 // qualifier so we will assume that we don't know what kind it is. diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 462def76cc..6e8c5d24a8 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -196,6 +196,13 @@ def CC_Mips_FastCC : CallingConv<[ CCDelegateTo ]>; +//== + +def CC_Mips16RetHelper : CallingConv<[ + // Integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> +]>; + //===----------------------------------------------------------------------===// // Mips Calling Convention Dispatch //===----------------------------------------------------------------------===// @@ -223,3 +230,6 @@ def CSR_N32 : CalleeSavedRegs<(add D31_64, D29_64, D27_64, D25_64, D24_64, def CSR_N64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64, GP_64, (sequence "S%u_64", 7, 0))>; + +def CSR_Mips16RetHelper : + CalleeSavedRegs<(add V0, V1, (sequence "A%u", 3, 0), S0, S1)>; diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 4d76181f92..ab105b3655 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -2229,6 +2229,15 @@ getOpndList(SmallVectorImpl &Ops, const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); assert(Mask && "Missing call preserved mask for calling convention"); + if (Subtarget->inMips16HardFloat()) { + if (GlobalAddressSDNode *G = dyn_cast(CLI.Callee)) { + llvm::StringRef Sym = G->getGlobal()->getName(); + Function *F = G->getGlobal()->getParent()->getFunction(Sym); + if (F->hasFnAttribute("__Mips16RetHelper")) { + Mask = MipsRegisterInfo::getMips16RetHelperMask(); + } + } + } Ops.push_back(CLI.DAG.getRegisterMask(Mask)); if (InFlag.getNode()) @@ -2260,7 +2269,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVector ArgLocs; CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); - MipsCC MipsCCInfo(CallConv, IsO32, CCInfo); + MipsCC::SpecialCallingConvType SpecialCallingConv = + getSpecialCallingConv(Callee); + MipsCC MipsCCInfo(CallConv, IsO32, CCInfo, SpecialCallingConv); MipsCCInfo.analyzeCallOperands(Outs, IsVarArg, getTargetMachine().Options.UseSoftFloat, @@ -3029,13 +3040,32 @@ static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) { return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol())); } -MipsTargetLowering::MipsCC::MipsCC(CallingConv::ID CC, bool IsO32_, - CCState &Info) - : CCInfo(Info), CallConv(CC), IsO32(IsO32_) { +MipsTargetLowering::MipsCC::SpecialCallingConvType + MipsTargetLowering::getSpecialCallingConv(SDValue Callee) const { + MipsCC::SpecialCallingConvType SpecialCallingConv = + MipsCC::NoSpecialCallingConv;; + if (Subtarget->inMips16HardFloat()) { + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + llvm::StringRef Sym = G->getGlobal()->getName(); + Function *F = G->getGlobal()->getParent()->getFunction(Sym); + if (F->hasFnAttribute("__Mips16RetHelper")) { + SpecialCallingConv = MipsCC::Mips16RetHelperConv; + } + } + } + return SpecialCallingConv; +} + +MipsTargetLowering::MipsCC::MipsCC( + CallingConv::ID CC, bool IsO32_, CCState &Info, + MipsCC::SpecialCallingConvType SpecialCallingConv_) + : CCInfo(Info), CallConv(CC), IsO32(IsO32_), + SpecialCallingConv(SpecialCallingConv_){ // Pre-allocate reserved argument area. CCInfo.AllocateStack(reservedArgArea(), 1); } + void MipsTargetLowering::MipsCC:: analyzeCallOperands(const SmallVectorImpl &Args, bool IsVarArg, bool IsSoftFloat, const SDNode *CallNode, @@ -3183,6 +3213,8 @@ llvm::CCAssignFn *MipsTargetLowering::MipsCC::fixedArgFn() const { if (CallConv == CallingConv::Fast) return CC_Mips_FastCC; + if (SpecialCallingConv == Mips16RetHelperConv) + return CC_Mips16RetHelper; return IsO32 ? CC_MipsO32 : CC_MipsN; } diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 5587e8f581..233c11f789 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -240,7 +240,14 @@ namespace llvm { /// arguments and inquire about calling convention information. class MipsCC { public: - MipsCC(CallingConv::ID CallConv, bool IsO32, CCState &Info); + enum SpecialCallingConvType { + Mips16RetHelperConv, NoSpecialCallingConv + }; + + MipsCC( + CallingConv::ID CallConv, bool IsO32, CCState &Info, + SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv); + void analyzeCallOperands(const SmallVectorImpl &Outs, bool IsVarArg, bool IsSoftFloat, @@ -313,15 +320,18 @@ namespace llvm { CCState &CCInfo; CallingConv::ID CallConv; bool IsO32; + SpecialCallingConvType SpecialCallingConv; SmallVector ByValArgs; }; - + protected: // Subtarget Info const MipsSubtarget *Subtarget; bool HasMips64, IsN64, IsO32; private: + + MipsCC::SpecialCallingConvType getSpecialCallingConv(SDValue Callee) const; // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index dead07bacd..ae25e456d5 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -100,6 +100,10 @@ MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const { return CSR_N64_RegMask; } +const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() { + return CSR_Mips16RetHelper_RegMask; +} + BitVector MipsRegisterInfo:: getReservedRegs(const MachineFunction &MF) const { static const uint16_t ReservedCPURegs[] = { diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 5ed5124139..20ba41d7fd 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -46,6 +46,7 @@ public: MachineFunction &MF) const; const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; const uint32_t *getCallPreservedMask(CallingConv::ID) const; + static const uint32_t *getMips16RetHelperMask(); BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 14a2b27795..259e68df32 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -48,6 +48,11 @@ static cl::opt Mips_Os16( "floating point as Mips 16"), cl::Hidden); +static cl::opt +Mips16HardFloat("mips16-hard-float", cl::NotHidden, + cl::desc("MIPS: mips16 hard float enable."), + cl::init(false)); + void MipsSubtarget::anchor() { } MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, @@ -58,7 +63,8 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false), HasBitCount(false), HasFPIdx(false), - InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), + InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), + InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), RM(_RM), OverrideMode(NoOverride), TM(_TM) { diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index f2f0e15887..ef7568a813 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -93,6 +93,9 @@ protected: // InMips16 -- can process Mips16 instructions bool InMips16Mode; + // Mips16 hard float + bool InMips16HardFloat; + // PreviousInMips16 -- the function we just processed was in Mips 16 Mode bool PreviousInMips16Mode; @@ -170,9 +173,12 @@ public: } llvm_unreachable("Unexpected mode"); } - bool inMips16ModeDefault() { + bool inMips16ModeDefault() const { return InMips16Mode; } + bool inMips16HardFloat() const { + return inMips16Mode() && InMips16HardFloat; + } bool inMicroMipsMode() const { return InMicroMipsMode; } bool hasDSP() const { return HasDSP; } bool hasDSPR2() const { return HasDSPR2; } @@ -188,7 +194,8 @@ public: bool hasBitCount() const { return HasBitCount; } bool hasFPIdx() const { return HasFPIdx; } - bool allowMixed16_32() const { return AllowMixed16_32;}; + bool allowMixed16_32() const { return inMips16ModeDefault() | + AllowMixed16_32;} bool os16() const { return Os16;}; diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index ee28e2a122..a876f1c7f0 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -22,6 +22,7 @@ #include "MipsSEISelLowering.h" #include "MipsSEISelDAGToDAG.h" #include "Mips16FrameLowering.h" +#include "Mips16HardFloat.h" #include "Mips16InstrInfo.h" #include "Mips16ISelDAGToDAG.h" #include "Mips16ISelLowering.h" @@ -156,6 +157,8 @@ void MipsPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); if (getMipsSubtarget().os16()) addPass(createMipsOs16(getMipsTargetMachine())); + if (getMipsSubtarget().inMips16HardFloat()) + addPass(createMips16HardFloat(getMipsTargetMachine())); } // Install an instruction selector pass using // the ISelDag to gen Mips code. diff --git a/test/CodeGen/Mips/mips16_fpret.ll b/test/CodeGen/Mips/mips16_fpret.ll new file mode 100644 index 0000000000..ae0d1b44ae --- /dev/null +++ b/test/CodeGen/Mips/mips16_fpret.ll @@ -0,0 +1,77 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static < %s | FileCheck %s -check-prefix=1 +; RUN: llc -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static < %s | FileCheck %s -check-prefix=2 +; RUN: llc -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static < %s | FileCheck %s -check-prefix=3 +; RUN: llc -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=static < %s | FileCheck %s -check-prefix=4 + + +@x = global float 0x41F487E980000000, align 4 +@dx = global double 0x41CDCC8BC4800000, align 8 +@cx = global { float, float } { float 1.000000e+00, float 9.900000e+01 }, align 4 +@dcx = global { double, double } { double 0x42CE5E14A412B480, double 0x423AA4C580DB0000 }, align 8 + +define float @foox() { +entry: + %0 = load float* @x, align 4 + ret float %0 +; 1: .ent foox +; 1: lw $2, %lo(x)(${{[0-9]+}}) +; 1: jal __mips16_ret_sf +} + +define double @foodx() { +entry: + %0 = load double* @dx, align 8 + ret double %0 +; 1: .ent foodx +; 1: lw $2, %lo(dx)(${{[0-9]+}}) +; 1: jal __mips16_ret_df +; 2: .ent foodx +; 2: lw $3, 4(${{[0-9]+}}) +; 2: jal __mips16_ret_df + +} + +define { float, float } @foocx() { +entry: + %retval = alloca { float, float }, align 4 + %cx.real = load float* getelementptr inbounds ({ float, float }* @cx, i32 0, i32 0) + %cx.imag = load float* getelementptr inbounds ({ float, float }* @cx, i32 0, i32 1) + %real = getelementptr inbounds { float, float }* %retval, i32 0, i32 0 + %imag = getelementptr inbounds { float, float }* %retval, i32 0, i32 1 + store float %cx.real, float* %real + store float %cx.imag, float* %imag + %0 = load { float, float }* %retval + ret { float, float } %0 +; 1: .ent foocx +; 1: lw $2, %lo(cx)(${{[0-9]+}}) +; 1: jal __mips16_ret_sc +; 2: .ent foocx +; 2: lw $3, 4(${{[0-9]+}}) +; 2: jal __mips16_ret_sc +} + +define { double, double } @foodcx() { +entry: + %retval = alloca { double, double }, align 8 + %dcx.real = load double* getelementptr inbounds ({ double, double }* @dcx, i32 0, i32 0) + %dcx.imag = load double* getelementptr inbounds ({ double, double }* @dcx, i32 0, i32 1) + %real = getelementptr inbounds { double, double }* %retval, i32 0, i32 0 + %imag = getelementptr inbounds { double, double }* %retval, i32 0, i32 1 + store double %dcx.real, double* %real + store double %dcx.imag, double* %imag + %0 = load { double, double }* %retval + ret { double, double } %0 +; 1: .ent foodcx +; 1: lw $2, %lo(dcx)(${{[0-9]+}}) +; 1: jal __mips16_ret_dc +; 2: .ent foodcx +; 2: lw $3, 4(${{[0-9]+}}) +; 2: jal __mips16_ret_dc +; 3: .ent foodcx +; 3: lw $4, 8(${{[0-9]+}}) +; 3: jal __mips16_ret_dc +; 4: .ent foodcx +; 4: lw $5, 12(${{[0-9]+}}) +; 4: jal __mips16_ret_dc +} + -- cgit v1.2.3 From ef3e423e2313ee05ba136aafc1e34c45a2702577 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Fri, 10 May 2013 22:55:44 +0000 Subject: Add an additional testcase for PR15882. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181646 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Transforms/LoopVectorize/reverse_iter.ll | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/Transforms/LoopVectorize/reverse_iter.ll diff --git a/test/Transforms/LoopVectorize/reverse_iter.ll b/test/Transforms/LoopVectorize/reverse_iter.ll new file mode 100644 index 0000000000..6ff4f1f8d1 --- /dev/null +++ b/test/Transforms/LoopVectorize/reverse_iter.ll @@ -0,0 +1,45 @@ +; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.8.0" + +; Make sure that the reverse iterators are calculated using 64bit arithmetic, not 32. +; +; int foo(int n, int *A) { +; int sum; +; for (int i=n; i > 0; i--) +; sum += A[i*2]; +; return sum; +; } +; + +;CHECK: @foo +;CHECK: +;CHECK: ret +define i32 @foo(i32 %n, i32* nocapture %A) { + %1 = icmp sgt i32 %n, 0 + br i1 %1, label %.lr.ph, label %._crit_edge + +.lr.ph: ; preds = %0 + %2 = sext i32 %n to i64 + br label %3 + +;