Index: llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -550,6 +550,10 @@ // The MachineFunction currently being translated. MachineFunction *MF; + using CallSiteInfo = MachineFunction::CallSiteInfo; + using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; + DenseMap GlobalCallSiteInfo; + /// MachineRegisterInfo used to create virtual registers. MachineRegisterInfo *MRI = nullptr; @@ -595,6 +599,17 @@ std::unique_ptr SL; + void addCallSiteInfo(const MachineInstr *MI, CallSiteInfoImpl &&CallInfo) { + GlobalCallSiteInfo[MI] = std::move(CallInfo); + } + + CallSiteInfo getGlobalCallSiteInfo(const MachineInstr *MI) { + auto I = GlobalCallSiteInfo.find(MI); + if (I != GlobalCallSiteInfo.end()) + return std::move(I->second); + return CallSiteInfo(); + } + // * Insert all the code needed to materialize the constants // at the proper place. E.g., Entry block or dominator block // of each constant depending on how fancy we want to be. Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2167,6 +2167,7 @@ SmallVector, 8> Args; Register SwiftInVReg = 0; Register SwiftErrorVReg = 0; + CallSiteInfo CSInfo; for (auto &Arg : CB.args()) { if (CLI->supportSwiftError() && isSwiftError(Arg)) { assert(SwiftInVReg == 0 && "Expected only one swift error argument"); @@ -2182,6 +2183,8 @@ Args.push_back(getOrCreateVRegs(*Arg)); } + unsigned MBBLengthBefore = MIRBuilder.getMBB().size(); + // We don't set HasCalls on MFI here yet because call lowering may decide to // optimize into tail calls. Instead, we defer that to selection where a final // scan is done to check if any instructions are calls. @@ -2194,6 +2197,24 @@ assert(!HasTailCall && "Can't tail call return twice from block?"); const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); HasTailCall = TII->isTailCall(*std::prev(MIRBuilder.getInsertPt())); + + // Add registers used from COPY instructions to the CallSiteInfo. + unsigned MINo = 0, ArgNo = 0; + for (const MachineInstr &MI : MIRBuilder.getMBB()) { + // The only relevant instructions are the ones that were added to + // MIRBuilder in lowerCall. Use a counter to know when the old size + // to see when the old size is surpassed. + if (MINo++ >= MBBLengthBefore) { + if (MI.isCopy()) + CSInfo.emplace_back(MI.getOperand(0).getReg(), ArgNo++); + if (MI.isCandidateForCallSiteEntry()) { + addCallSiteInfo(&MI, std::move(CSInfo)); + if (MF->getTarget().Options.EmitCallSiteInfo) + MF->addCallArgsForwardingRegs(&MI, getGlobalCallSiteInfo(&MI)); + break; + } + } + } } return Success; Index: llvm/test/CodeGen/X86/call-site-info-output2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/call-site-info-output2.ll @@ -0,0 +1,71 @@ +;; Test call site info when using GlobalISel. MIR printer and parser. +;; Parser assertions and machine verifier will check the rest +; RUN: llc -emit-call-site-info -global-isel %s -stop-before=finalize-isel -o %t.mir +; RUN: cat %t.mir | FileCheck %s +; CHECK: name: fn3 +; CHECK: callSites: +; CHECK-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; CHECK-NEXT: arg: 0, reg: '$edi' +; CHECK: name: fn2 +; CHECK: callSites: +;; There is no need to verify call instruction location since it will be +;; checked by the MIR parser in the next RUN. +; CHECK-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; CHECK-NEXT: arg: 0, reg: '$edi' +; CHECK-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; CHECK-NEXT: arg: 0, reg: '$edi' +; CHECK-NEXT: arg: 1, reg: '$esi' +; CHECK-NEXT: arg: 2, reg: '$edx' +; RUN: llc -emit-call-site-info %t.mir -run-pass=finalize-isel -o -| FileCheck %s --check-prefix=PARSER +;; Verify that we are able to parse output mir and that we are getting the same result. +; PARSER: name: fn3 +; PARSER: callSites: +; PARSER-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; PARSER-NEXT: arg: 0, reg: '$edi' +; PARSER: name: fn2 +; PARSER: callSites: +; PARSER-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; PARSER-NEXT: arg: 0, reg: '$edi' +; PARSER-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; PARSER-NEXT: arg: 0, reg: '$edi' +; PARSER-NEXT: arg: 1, reg: '$esi' +; PARSER-NEXT: arg: 2, reg: '$edx' + +; ModuleID = 'test/CodeGen/X86/call-site-info-output2.c' +source_filename = "test/CodeGen/X86/call-site-info-output2.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind uwtable +define dso_local i32 @fn1(i32 %a) local_unnamed_addr { +entry: + %c = add i32 %a, 2 + ret i32 %c +} + +; Function Attrs: noinline nounwind uwtable +define dso_local i32 @fn3(i32 %a, i32 %b, i32 %c) local_unnamed_addr { +entry: + %d = add i32 %a, %b + %e = mul i32 %d, %c + %f = call i32 @fn1(i32 %e) + ret i32 %f +} + +; Function Attrs: noinline nounwind uwtable +define dso_local i64 @fn2(i32 %a, i32 %b, i32 %c) local_unnamed_addr { +entry: + %call = call i32 @fn1(i32 5) + %add = mul i32 %a, 3 + %sub = sub i32 %add, %b + %add2 = add i32 %sub, %c + %conv4 = sext i32 %add2 to i64 + %call2 = call i32 @fn3(i32 5, i32 %add2, i32 %add2) + ret i64 %conv4 +} + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 9.0.0"}