Index: llvm/include/llvm/CodeGen/MachineInstr.h =================================================================== --- llvm/include/llvm/CodeGen/MachineInstr.h +++ llvm/include/llvm/CodeGen/MachineInstr.h @@ -1152,8 +1152,14 @@ void print(raw_ostream &OS, bool SkipOpers = false) const; void print(raw_ostream &OS, ModuleSlotTracker &MST, bool SkipOpers = false) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + bool SkipOpers, const TargetInstrInfo * const) const; void dump() const; + // Useful at least to prevent UNKNOWN when outputting + // an MI that is a result of combining MIs. + void dump_with_given_TII(const TargetInstrInfo * const) const; + //===--------------------------------------------------------------------===// // Accessors used to build up machine instructions. Index: llvm/lib/CodeGen/MachineCombiner.cpp =================================================================== --- llvm/lib/CodeGen/MachineCombiner.cpp +++ llvm/lib/CodeGen/MachineCombiner.cpp @@ -134,7 +134,7 @@ // are tracked in the InstrIdxForVirtReg map depth is looked up in InstrDepth for (auto *InstrPtr : InsInstrs) { // for each Use unsigned IDepth = 0; - DEBUG(dbgs() << "NEW INSTR "; InstrPtr->dump(); dbgs() << "\n";); + DEBUG(dbgs() << "NEW INSTR "; InstrPtr->dump_with_given_TII(TII); dbgs() << "\n";); for (const MachineOperand &MO : InstrPtr->operands()) { // Check for virtual register operand. if (!(MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))) Index: llvm/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/lib/CodeGen/MachineInstr.cpp +++ llvm/lib/CodeGen/MachineInstr.cpp @@ -1701,7 +1701,8 @@ } void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, - bool SkipOpers) const { + bool SkipOpers, + const TargetInstrInfo * const TII_in) const { // We can be a bit tidier if we know the MachineFunction. const MachineFunction *MF = nullptr; const TargetRegisterInfo *TRI = nullptr; @@ -1742,6 +1743,9 @@ if (StartOp != 0) OS << " = "; + if (!TII) + TII = TII_in; + // Print the opcode name. if (TII) OS << TII->getName(getOpcode()); @@ -1986,6 +1990,24 @@ OS << '\n'; } +void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, + bool SkipOpers) const { + print(OS, MST, SkipOpers, 0 /* intentional null TargetInstrInfo*/); +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void MachineInstr::dump_with_given_TII(const TargetInstrInfo * const TII_in) const { + dbgs() << " "; + const Module *M = nullptr; + if (const MachineBasicBlock *MBB = getParent()) + if (const MachineFunction *MF = MBB->getParent()) + M = MF->getFunction()->getParent(); + + ModuleSlotTracker MST(M); + print(dbgs(), MST, false /* SkipOpers */, TII_in); +} +#endif + bool MachineInstr::addRegisterKilled(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound) { Index: llvm/test/CodeGen/AArch64/correct_debug_output_when_a_new_MachineInstr_is_generated_in_the_machine_combiner.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/correct_debug_output_when_a_new_MachineInstr_is_generated_in_the_machine_combiner.ll @@ -0,0 +1,58 @@ +; Converted from a machine-reduced C++ test case. + +; The fix is actually generic, but this test is AArch64-specific. + +; RUN: llc -O=3 -mtriple=aarch64-linux-gnu -mcpu=cortex-a57 -debug-only=machine-combiner -debug -o - %s |& FileCheck %s + +; CHECK: NEW INSTR{{.*}}MADDXrrr +; CHECK-NOT: NEW INSTR{{.*}}UNKNOWN + +target triple = "aarch64-sarc-linux-gnu" + +%class.BtlConfig = type { %class.C } +%class.C = type { %class.B } +%class.B = type { %class.D* } +%class.D = type { %class.basic_string.base, [4 x i8] } +%class.basic_string.base = type <{ i64, i64, i32 }> +%class.basic_string = type <{ i64, i64, i32, [4 x i8] }> +@a = global %class.BtlConfig zeroinitializer, align 8 +@.str = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +declare i64 @_ZN1CI1D1AIS0_EE5m_fn1Ev(%class.C*) local_unnamed_addr +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) +define internal void @_GLOBAL__sub_I_main_adv.ii() section ".text.startup" { +entry: + %tmp.i.i = alloca %class.D, align 8 + %agg.tmp.i.i = alloca %class.D, align 8 + %0 = bitcast %class.D* %tmp.i.i to i8* + %1 = bitcast %class.D* %agg.tmp.i.i to i8* + %call8.i.i = tail call i64 @_ZN1CI1D1AIS0_EE5m_fn1Ev(%class.C* getelementptr inbounds (%class.BtlConfig, %class.BtlConfig* @a, i64 0, i32 0)) + %cmp9.i.i = icmp sgt i64 %call8.i.i, 0 + br i1 %cmp9.i.i, label %for.body.lr.ph.i.i, label %__cxx_global_var_init.exit +for.body.lr.ph.i.i: + %2 = bitcast %class.D* %agg.tmp.i.i to %class.basic_string* + br label %for.body.i.i +for.body.i.i: + %conv11.i.i = phi i64 [ 0, %for.body.lr.ph.i.i ], [ %conv.i.i, %for.body.i.i ] + %i.010.i.i = phi i32 [ undef, %for.body.lr.ph.i.i ], [ %inc.i.i, %for.body.i.i ] + %3 = load %class.D*, %class.D** getelementptr inbounds (%class.BtlConfig, %class.BtlConfig* @a, i64 0, i32 0, i32 0, i32 0), align 8, !tbaa !1, !noalias !6 + %arrayidx.i.i.i = getelementptr inbounds %class.D, %class.D* %3, i64 %conv11.i.i + %4 = bitcast %class.D* %arrayidx.i.i.i to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull %0, i8* %4, i64 24, i32 8, i1 false) + %inc.i.i = add i32 %i.010.i.i, 1 + %conv.i.i = zext i32 %inc.i.i to i64 + %call.i.i = call i64 @_ZN1CI1D1AIS0_EE5m_fn1Ev(%class.C* getelementptr inbounds (%class.BtlConfig, %class.BtlConfig* @a, i64 0, i32 0)) + %cmp.i.i = icmp slt i64 %conv.i.i, %call.i.i + br i1 %cmp.i.i, label %for.body.i.i, label %__cxx_global_var_init.exit.loopexit +__cxx_global_var_init.exit.loopexit: + br label %__cxx_global_var_init.exit +__cxx_global_var_init.exit: + ret void +} +!1 = !{!2, !3, i64 0} +!2 = !{!"foo", !3, i64 0} +!3 = !{!"bar", !4, i64 0} +!4 = !{!"baz", !5, i64 0} +!5 = !{!"boo"} +!6 = !{!7} +!7 = distinct !{!7, !8, !"_ZN1CI1D1AIS0_EEixEl: %agg.result"} +!8 = distinct !{!8, !"_ZN1CI1D1AIS0_EEixEl"}