Index: include/llvm/MC/MCParser/MCAsmParser.h =================================================================== --- include/llvm/MC/MCParser/MCAsmParser.h +++ include/llvm/MC/MCParser/MCAsmParser.h @@ -128,6 +128,8 @@ MCAsmParser(); bool HadError = false; + /// Enable print [latency:throughput] in output file + bool EnablePrintSchedInfo = false; SmallVector PendingErrors; /// Flag tracking whether any errors have been encountered. @@ -163,6 +165,9 @@ bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } + void setEnablePrintSchedInfo(bool Value) { EnablePrintSchedInfo = Value; } + bool enablePrintSchedInfo() { return EnablePrintSchedInfo; } + /// \brief Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -144,6 +144,7 @@ " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); + Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo); if (Dialect == InlineAsm::AD_Intel) // We need this flag to be able to parse numbers like "0bH" Parser->setParsingInlineAsm(true); Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.h =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.h +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.h @@ -42,7 +42,8 @@ virtual void InstrumentAndEmitInstruction( const MCInst &Inst, SmallVectorImpl> &Operands, - MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); + MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out, + bool EnableSchedInfo); protected: friend X86AsmInstrumentation * @@ -54,7 +55,8 @@ unsigned GetFrameRegGeneric(const MCContext &Ctx, MCStreamer &Out); - void EmitInstruction(MCStreamer &Out, const MCInst &Inst); + void EmitInstruction(MCStreamer &Out, const MCInst &Inst, + bool EnableSchedInfo = false); const MCSubtargetInfo *&STI; Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -193,11 +193,9 @@ ~X86AddressSanitizer() override = default; // X86AsmInstrumentation implementation: - void InstrumentAndEmitInstruction(const MCInst &Inst, - OperandVector &Operands, - MCContext &Ctx, - const MCInstrInfo &MII, - MCStreamer &Out) override { + void InstrumentAndEmitInstruction(const MCInst &Inst, OperandVector &Operands, + MCContext &Ctx, const MCInstrInfo &MII, + MCStreamer &Out, bool) override { InstrumentMOVS(Inst, Operands, Ctx, MII, Out); if (RepPrefix) EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX)); @@ -1045,13 +1043,13 @@ void X86AsmInstrumentation::InstrumentAndEmitInstruction( const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, MCStreamer &Out) { - EmitInstruction(Out, Inst); + const MCInstrInfo &MII, MCStreamer &Out, bool EnableSchedInfo) { + EmitInstruction(Out, Inst, EnableSchedInfo); } -void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, - const MCInst &Inst) { - Out.EmitInstruction(Inst, *STI); +void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, const MCInst &Inst, + bool EnableSchedInfo) { + Out.EmitInstruction(Inst, *STI, EnableSchedInfo); } unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx, Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -2699,8 +2699,9 @@ void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out) { - Instrumentation->InstrumentAndEmitInstruction(Inst, Operands, getContext(), - MII, Out); + Instrumentation->InstrumentAndEmitInstruction( + Inst, Operands, getContext(), MII, Out, + getParser().enablePrintSchedInfo()); } bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Index: test/CodeGen/X86/inline-schedule.ll =================================================================== --- test/CodeGen/X86/inline-schedule.ll +++ test/CodeGen/X86/inline-schedule.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -print-schedule -mcpu=btver2 | FileCheck %s --check-prefix=BTVER2 + +define i64 @test_bsr64(i64 %a0, i64 *%a1) nounwind { +; BTVER2-LABEL: test_bsr64: +; BTVER2: # BB#0: +; BTVER2-NEXT: #APP +; BTVER2-NEXT: bsrq (%rsi), %rax # sched: [4:1.00] +; BTVER2-NEXT: #NO_APP +; BTVER2-NEXT: #APP +; BTVER2-NEXT: bsrq %rdi, %rcx # sched: [1:0.50] +; BTVER2-NEXT: #NO_APP +; BTVER2-NEXT: orq %rcx, %rax # sched: [1:0.50] +; BTVER2-NEXT: retq # sched: [4:1.00] + %1 = tail call i64 asm "bsr $1, $0", "=r,r"(i64 %a0) nounwind + %2 = tail call i64 asm "bsr $1, $0", "=r,*m"(i64 *%a1) nounwind + %3 = or i64 %1, %2 + ret i64 %3 +} + +define i64 @test_bswap64(i64 %a0) nounwind { +; BTVER2-LABEL: test_bswap64: +; BTVER2: # BB#0: +; BTVER2-NEXT: bswapq %rdi # sched: [1:0.50] +; BTVER2-NEXT: movq %rdi, %rax # sched: [1:0.17] +; BTVER2-NEXT: retq # sched: [4:1.00] + %1 = tail call i64 asm "bswap $0", "=r,0"(i64 %a0) nounwind + ret i64 %1 +} +