diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 1083e397c2a..9043256e8a9 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -618,6 +618,14 @@ public: BasicBlocks.sort(comp); } + /// Return the number of \p MachineInstrs in this \p MachineFunction. + unsigned getInstructionCount() const { + unsigned InstrCount = 0; + for (const MachineBasicBlock &MBB : BasicBlocks) + InstrCount += MBB.size(); + return InstrCount; + } + //===--------------------------------------------------------------------===// // Internal functions used to automatically number MachineBasicBlocks diff --git a/lib/CodeGen/MachineFunctionPass.cpp b/lib/CodeGen/MachineFunctionPass.cpp index 67ac95740e3..5db4e299fa7 100644 --- a/lib/CodeGen/MachineFunctionPass.cpp +++ b/lib/CodeGen/MachineFunctionPass.cpp @@ -23,11 +23,13 @@ #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" using namespace llvm; +using namespace ore; Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, const std::string &Banner) const { @@ -57,9 +59,43 @@ bool MachineFunctionPass::runOnFunction(Function &F) { llvm_unreachable("MachineFunctionProperties check failed"); } #endif + // Collect the MI count of the function before the pass. + unsigned CountBefore, CountAfter; + + // Check if the user asked for size remarks. + bool ShouldEmitSizeRemarks = + F.getParent()->shouldEmitInstrCountChangedRemark(); + + // If we want size remarks, collect the number of MachineInstrs in our + // MachineFunction before the pass runs. + if (ShouldEmitSizeRemarks) + CountBefore = MF.getInstructionCount(); bool RV = runOnMachineFunction(MF); + if (ShouldEmitSizeRemarks) { + // We wanted size remarks. Check if there was a change to the number of + // MachineInstrs in the module. Emit a remark if there was a change. + CountAfter = MF.getInstructionCount(); + if (CountBefore != CountAfter) { + MachineOptimizationRemarkEmitter MORE(MF, nullptr); + MORE.emit([&]() { + int64_t Delta = static_cast(CountAfter) - + static_cast(CountBefore); + MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange", + MF.getFunction().getSubprogram(), + &MF.front()); + R << NV("Pass", getPassName()) + << ": Function: " << NV("Function", F.getName()) << ": " + << "MI Instruction count changed from " + << NV("MIInstrsBefore", CountBefore) << " to " + << NV("MIInstrsAfter", CountAfter) + << "; Delta: " << NV("Delta", Delta); + return R; + }); + } + } + MFProps.set(SetProperties); MFProps.reset(ClearedProperties); return RV; diff --git a/test/Other/machine-size-remarks.ll b/test/Other/machine-size-remarks.ll new file mode 100644 index 00000000000..188676db8b3 --- /dev/null +++ b/test/Other/machine-size-remarks.ll @@ -0,0 +1,58 @@ +; RUN: llc -mtriple x86_64---- %s -pass-remarks-analysis='size-info'\ +; RUN: -pass-remarks-output=%t.yaml -o /dev/null < %s 2> %t; \ +; RUN: cat %t %t.yaml | FileCheck %s + +; Make sure that machine-level size remarks work. +; Test the following: +; - When we create a MachineFunction (e.g, during instruction selection), it +; has a size of 0. +; - The initial size of the function after filling it is positive. +; - After that, we can increase or decrease the size of the function. +; - ... The final size must be positive. +; - ... The delta can be negative or positive. + +; CHECK: remark: :0:0: X86 DAG->DAG Instruction Selection: Function: +; CHECK-SAME: main: MI Instruction count changed from 0 +; CHECK-SAME: to [[INIT:[1-9][0-9]*]]; Delta: [[INIT]] +; CHECK-NEXT: remark: :0:0: Simple Register Coalescing: Function: main: +; CHECK-SAME: MI Instruction count changed from [[INIT]] to +; CHECK-SAME: [[FINAL:[1-9][0-9]*]]; +; CHECK-SAME: Delta: [[DELTA:-?[1-9][0-9]*]] +; CHECK-NEXT: --- !Analysis +; CHECK-NEXT: Pass: size-info +; CHECK-NEXT: Name: FunctionMISizeChange +; CHECK-NEXT: Function: main +; CHECK-NEXT: Args: +; CHECK-NEXT: - Pass: 'X86 DAG->DAG Instruction Selection' +; CHECK-NEXT: - String: ': Function: ' +; CHECK-NEXT: - Function: main +; CHECK-NEXT: - String: ': ' +; CHECK-NEXT: - String: 'MI Instruction count changed from ' +; CHECK-NEXT: - MIInstrsBefore: '0' +; CHECK-NEXT: - String: ' to ' +; CHECK-NEXT: - MIInstrsAfter: '[[INIT]]' +; CHECK-NEXT: - String: '; Delta: ' +; CHECK-NEXT: - Delta: '[[INIT]]' +; CHECK-DAG: --- !Analysis +; CHECK-NEXT: Pass: size-info +; CHECK-NEXT: Name: FunctionMISizeChange +; CHECK-NEXT: Function: main +; CHECK-NEXT: Args: +; CHECK-NEXT: - Pass: Simple Register Coalescing +; CHECK-NEXT: - String: ': Function: ' +; CHECK-NEXT: - Function: main +; CHECK-NEXT: - String: ': ' +; CHECK-NEXT: - String: 'MI Instruction count changed from ' +; CHECK-NEXT: - MIInstrsBefore: '[[INIT]]' +; CHECK-NEXT: - String: ' to ' +; CHECK-NEXT: - MIInstrsAfter: '[[FINAL]]' +; CHECK-NEXT: - String: '; Delta: ' +; CHECK-NEXT: - Delta: '[[DELTA]]' +define i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone ssp uwtable }