Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -210,6 +210,10 @@ EmitStartPt = EmitStartPt->getPrevNode(); LLVM_DEBUG(dbgs() << "removing dead local value materialization" << LocalMI); + auto CalleesMap = MF->getCallSitesInfo(); + if (LocalMI.isCandidateForCallSiteEntry() && + CalleesMap.find(&LocalMI) != CalleesMap.end()) + MF->eraseCallSiteInfo(&LocalMI); LocalMI.eraseFromParent(); } } @@ -470,6 +474,10 @@ MachineInstr *Dead = &*I; ++I; + auto CalleesMap = MF->getCallSitesInfo(); + if (Dead->isCandidateForCallSiteEntry() && + CalleesMap.find(Dead) != CalleesMap.end()) + MF->eraseCallSiteInfo(Dead); Dead->eraseFromParent(); ++NumFastIselDead; } @@ -941,6 +949,10 @@ MIB->setPhysRegsDeadExcept(CLI.InRegs, TRI); + auto CalleesMap = FuncInfo.MF->getCallSitesInfo(); + if (CLI.Call->isCandidateForCallSiteEntry() && + CalleesMap.find(CLI.Call) != CalleesMap.end()) + FuncInfo.MF->eraseCallSiteInfo(CLI.Call); // Delete the original call instruction. CLI.Call->eraseFromParent(); Index: llvm/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/lib/Target/X86/X86FastISel.cpp +++ llvm/lib/Target/X86/X86FastISel.cpp @@ -3218,6 +3218,8 @@ bool Is64Bit = Subtarget->is64Bit(); bool IsWin64 = Subtarget->isCallingConvWin64(CC); + MachineFunction::CallSiteInfo CSInfo; + // Call / invoke instructions with NoCfCheck attribute require special // handling. if (CB && CB->doesNoCfCheck()) @@ -3433,6 +3435,8 @@ if (VA.isRegLoc()) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); + + CSInfo.emplace_back(VA.getLocReg(), i); OutRegs.push_back(VA.getLocReg()); } else { assert(VA.isMemLoc() && "Unknown value location!"); @@ -3546,6 +3550,9 @@ MIB.addReg(0); } + if (MIB->isCandidateForCallSiteEntry() && TM.Options.EmitCallSiteInfo) + MF->addCallArgsForwardingRegs(&*MIB, std::move(CSInfo)); + // Add a register mask operand representing the call-preserved registers. // Proper defs for return values will be added by setPhysRegsDeadExcept(). MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC)); Index: llvm/test/CodeGen/X86/call-site-info-output.ll =================================================================== --- llvm/test/CodeGen/X86/call-site-info-output.ll +++ llvm/test/CodeGen/X86/call-site-info-output.ll @@ -18,6 +18,14 @@ ; PARSER-NEXT: arg: 0, reg: '$edi' ; PARSER-NEXT: arg: 1, reg: '$esi' ; PARSER-NEXT: arg: 2, reg: '$edx' +; RUN: llc -emit-call-site-info %s -stop-before=finalize-isel -fast-isel=true -o - | FileCheck %s --check-prefix=FASTISEL +; Verify that callSites entry are generated for fastIsel. +; FASTISEL: name: fn2 +; FASTISEL: callSites: +; FASTISEL-NEXT: bb: {{.*}}, offset: {{.*}}, fwdArgRegs: +; FASTISEL-NEXT: arg: 0, reg: '$edi' +; FASTISEL-NEXT: arg: 1, reg: '$esi' +; FASTISEL-NEXT: arg: 2, reg: '$edx' ; ModuleID = 'test/CodeGen/X86/call-site-info-output.c' source_filename = "test/CodeGen/X86/call-site-info-output.c" Index: llvm/test/DebugInfo/X86/callsitepar-fastisel.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/callsitepar-fastisel.ll @@ -0,0 +1,200 @@ +;; This test checks if DW_TAG_GNU_call_site_parameter is generated for fastIsel. +; REQUIRES: x86_64-linux +;RUN: llc -mtriple=x86_64-pc-linux-gnu -emit-call-site-info -fast-isel=true -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s +;CHECK: DW_TAG_GNU_call_site +;CHECK: DW_AT_abstract_origin +;CHECK-SAME: "foo" +;CHECK: DW_AT_low_pc +;CHECK: DW_TAG_GNU_call_site_parameter +;CHECK: DW_AT_location (DW_OP_reg4 RSI) +;CHECK: DW_AT_GNU_call_site_value + +;;The IR is generated from below source program +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;subroutine foo (array) +;; integer :: array(:,:) +;; array(:,:) = 5 +;; array(1,1) = 30 +;;end subroutine +;; +;;program vla_sub +;; interface +;; subroutine foo (array) +;; integer :: array (:,:) +;; end subroutine +;; end interface +;; +;; integer :: sub_arr(42,42) +;; sub_arr(:,:) = 1 +;; call foo(sub_arr) +;;end program vla_sub +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; ModuleID = 'fast.ll' +source_filename = "/tmp/fast.ll" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.BSS2 = type <{ [7056 x i8] }> + +@.BSS2 = internal global %struct.BSS2 zeroinitializer, align 32, !dbg !0 +@.C359_MAIN_ = internal constant i64 42 +@.C333_MAIN_ = internal constant i64 1 +@.C368_MAIN_ = internal constant i64 4 +@.C367_MAIN_ = internal constant i64 25 +@.C331_MAIN_ = internal constant i64 0 +@.C330_MAIN_ = internal constant i32 0 + +; Function Attrs: nofree norecurse nounwind +define void @foo_(i64* noalias nocapture %array, i64* noalias nocapture readonly %"array$sd") local_unnamed_addr !dbg !15 { +L.entry: + call void @llvm.dbg.value(metadata i64* %array, metadata !28, metadata !DIExpression()), !dbg !29 + call void @llvm.dbg.declare(metadata i64* %"array$sd", metadata !30, metadata !DIExpression()), !dbg !29 + %0 = getelementptr i64, i64* %"array$sd", i64 11 + %1 = load i64, i64* %0, align 8 + call void @llvm.dbg.value(metadata i64 %1, metadata !21, metadata !DIExpression()), !dbg !29 + %2 = getelementptr i64, i64* %"array$sd", i64 20 + %3 = load i64, i64* %2, align 8 + %4 = getelementptr i64, i64* %"array$sd", i64 17 + %5 = load i64, i64* %4, align 8 + call void @llvm.dbg.value(metadata i64 %5, metadata !24, metadata !DIExpression()), !dbg !29 + %6 = getelementptr i64, i64* %"array$sd", i64 7 + %7 = load i64, i64* %6, align 8 + %8 = getelementptr i64, i64* %"array$sd", i64 16 + %9 = load i64, i64* %8, align 8 + %10 = add nsw i64 %9, -1 + %11 = mul nsw i64 %10, %3 + %12 = getelementptr i64, i64* %"array$sd", i64 10 + %13 = load i64, i64* %12, align 8 + %14 = add i64 %7, -1 + %15 = add i64 %14, %13 + %16 = add i64 %15, %11 + %17 = icmp slt i64 %1, 1, !dbg !35 + %18 = icmp slt i64 %5, 1, !dbg !35 + %19 = or i1 %17, %18, !dbg !35 + br i1 %19, label %L.LB1_372, label %L.LB1_371.preheader, !dbg !35 + +L.LB1_371.preheader: ; preds = %L.entry + %20 = bitcast i64* %array to i8* + %21 = getelementptr i8, i8* %20, i64 -4 + %22 = bitcast i8* %21 to i32* + br label %L.LB1_371 + +L.LB1_371: ; preds = %L.LB1_371.preheader, %L.LB1_426 + %"i$a_368.0" = phi i64 [ %28, %L.LB1_426 ], [ 1, %L.LB1_371.preheader ], !dbg !35 + %23 = mul nsw i64 %"i$a_368.0", %3 + %24 = add i64 %23, %16 + br label %L.LB1_374 + +L.LB1_374: ; preds = %L.LB1_374, %L.LB1_371 + %"i$b_369.0" = phi i64 [ 1, %L.LB1_371 ], [ %27, %L.LB1_374 ], !dbg !35 + %25 = add i64 %24, %"i$b_369.0", !dbg !35 + %26 = getelementptr i32, i32* %22, i64 %25, !dbg !35 + store i32 5, i32* %26, align 4, !dbg !35 + %27 = add nuw i64 %"i$b_369.0", 1, !dbg !35 + %exitcond.not = icmp eq i64 %"i$b_369.0", %1, !dbg !35 + br i1 %exitcond.not, label %L.LB1_426, label %L.LB1_374, !dbg !35 + +L.LB1_426: ; preds = %L.LB1_374 + %28 = add nuw i64 %"i$a_368.0", 1, !dbg !35 + %exitcond9.not = icmp eq i64 %"i$a_368.0", %5, !dbg !35 + br i1 %exitcond9.not, label %L.LB1_372, label %L.LB1_371, !dbg !35 + +L.LB1_372: ; preds = %L.LB1_426, %L.entry + %29 = add nsw i64 %16, %3, !dbg !36 + %30 = bitcast i64* %array to i32*, !dbg !36 + %31 = getelementptr i32, i32* %30, i64 %29, !dbg !36 + store i32 30, i32* %31, align 4, !dbg !36 + ret void, !dbg !37 +} + +define void @MAIN_() local_unnamed_addr !dbg !2 { +L.entry: + %"sub_arr$sd1_366" = alloca [22 x i64], align 8 + call void (i8*, ...) bitcast (void (...)* @fort_init to void (i8*, ...)*)(i8* bitcast (i32* @.C330_MAIN_ to i8*)) + %0 = bitcast [22 x i64]* %"sub_arr$sd1_366" to i8* + call void (i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, ...) bitcast (void (...)* @f90_template2_i8 to void (i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, ...)*)(i8* nonnull %0, i8* bitcast (i64* @.C331_MAIN_ to i8*), i8* bitcast (i64* @.C367_MAIN_ to i8*), i8* bitcast (i64* @.C368_MAIN_ to i8*), i8* bitcast (i64* @.C333_MAIN_ to i8*), i8* bitcast (i64* @.C359_MAIN_ to i8*), i8* bitcast (i64* @.C333_MAIN_ to i8*), i8* bitcast (i64* @.C359_MAIN_ to i8*)) + call void (i8*, i32, ...) bitcast (void (...)* @f90_set_intrin_type_i8 to void (i8*, i32, ...)*)(i8* nonnull %0, i32 25) + br label %L.LB2_374 + +L.LB2_374: ; preds = %L.LB2_402, %L.entry + %"i$a_363.0" = phi i64 [ 1, %L.entry ], [ %5, %L.LB2_402 ], !dbg !38 + %1 = mul nuw nsw i64 %"i$a_363.0", 42 + br label %L.LB2_377 + +L.LB2_377: ; preds = %L.LB2_377, %L.LB2_374 + %"i$b_364.0" = phi i64 [ 1, %L.LB2_374 ], [ %4, %L.LB2_377 ], !dbg !38 + %2 = add nuw nsw i64 %"i$b_364.0", %1, !dbg !38 + %3 = getelementptr i32, i32* bitcast (i8* getelementptr (i8, i8* getelementptr inbounds (%struct.BSS2, %struct.BSS2* @.BSS2, i64 0, i32 0, i64 0), i64 -172) to i32*), i64 %2, !dbg !38 + store i32 1, i32* %3, align 4, !dbg !38 + %4 = add nuw nsw i64 %"i$b_364.0", 1, !dbg !38 + %exitcond.not = icmp eq i64 %4, 43, !dbg !38 + br i1 %exitcond.not, label %L.LB2_402, label %L.LB2_377, !dbg !38 + +L.LB2_402: ; preds = %L.LB2_377 + %5 = add nuw nsw i64 %"i$a_363.0", 1, !dbg !38 + %exitcond5.not = icmp eq i64 %5, 43, !dbg !38 + br i1 %exitcond5.not, label %L.LB2_403, label %L.LB2_374, !dbg !38 + +L.LB2_403: ; preds = %L.LB2_402 + %6 = getelementptr inbounds [22 x i64], [22 x i64]* %"sub_arr$sd1_366", i64 0, i64 0, !dbg !39 + call void @foo_(i64* bitcast (%struct.BSS2* @.BSS2 to i64*), i64* nonnull %6), !dbg !39 + ret void, !dbg !40 +} + +declare void @f90_set_intrin_type_i8(...) local_unnamed_addr + +declare void @f90_template2_i8(...) local_unnamed_addr + +declare void @fort_init(...) local_unnamed_addr + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.module.flags = !{!13, !14} +!llvm.dbg.cu = !{!4} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "sub_arr", linkageName: ".BSS2", scope: !2, file: !3, line: 14, type: !9, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "vla_sub", scope: !4, file: !3, line: 7, type: !7, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4) +!3 = !DIFile(filename: "fast.f90", directory: "/dir") +!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None) +!5 = !{} +!6 = !{!0} +!7 = !DISubroutineType(cc: DW_CC_program, types: !8) +!8 = !{null} +!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 56448, align: 32, elements: !11) +!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed) +!11 = !{!12, !12} +!12 = !DISubrange(lowerBound: 1, upperBound: 42) +!13 = !{i32 2, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = distinct !DISubprogram(name: "foo", scope: !4, file: !3, line: 1, type: !16, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4) +!16 = !DISubroutineType(types: !17) +!17 = !{null, !18, !25} +!18 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !19) +!19 = !{!20, !23} +!20 = !DISubrange(lowerBound: 1, upperBound: !21) +!21 = distinct !DILocalVariable(scope: !15, file: !3, line: 2, type: !22, flags: DIFlagArtificial) +!22 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed) +!23 = !DISubrange(lowerBound: 1, upperBound: !24) +!24 = distinct !DILocalVariable(scope: !15, file: !3, line: 2, type: !22, flags: DIFlagArtificial) +!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !22, size: 1408, align: 64, elements: !26) +!26 = !{!27} +!27 = !DISubrange(lowerBound: 1, upperBound: 22) +!28 = !DILocalVariable(arg: 1, scope: !15, file: !3, line: 1, type: !22) +!29 = !DILocation(line: 0, scope: !15) +!30 = !DILocalVariable(name: "array", arg: 2, scope: !15, file: !3, line: 1, type: !31) +!31 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !32, dataLocation: !28) +!32 = !{!33, !34} +!33 = !DISubrange(lowerBound: 1, upperBound: !21, stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 112, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 24, DW_OP_deref, DW_OP_mul)) +!34 = !DISubrange(lowerBound: 1, upperBound: !24, stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_push_object_address, DW_OP_plus_uconst, 24, DW_OP_deref, DW_OP_mul)) +!35 = !DILocation(line: 3, column: 1, scope: !15) +!36 = !DILocation(line: 4, column: 1, scope: !15) +!37 = !DILocation(line: 5, column: 1, scope: !15) +!38 = !DILocation(line: 15, column: 1, scope: !2) +!39 = !DILocation(line: 16, column: 1, scope: !2) +!40 = !DILocation(line: 17, column: 1, scope: !2)