Index: lib/CodeGen/ScheduleDAGInstrs.cpp =================================================================== --- lib/CodeGen/ScheduleDAGInstrs.cpp +++ lib/CodeGen/ScheduleDAGInstrs.cpp @@ -73,6 +73,10 @@ static cl::opt UseTBAA("use-tbaa-in-sched-mi", cl::Hidden, cl::init(true), cl::desc("Enable use of TBAA during MI DAG construction")); +static cl::opt EnableDbgValueReattach("enable-dbg-value-reattach", + cl::Hidden, cl::init(true), + cl::desc("Enable dbg_value reattachment to the nearest clobbering MI")); + // Note: the two options below might be used in tuning compile time vs // output quality. Setting HugeRegion so large that it will never be // reached means best-effort, but may be slow. @@ -688,6 +692,59 @@ map.reComputeSize(); } +// Some DBG_VALUE-related code here from DbgValueHistoryCalculator +// \brief If @MI is a DBG_VALUE with debug value described by a +// defined register, returns the number of this register. +// In the other case, returns 0. +static unsigned getRegDescriptor(const MachineInstr &MI) { + assert(MI.isDebugValue()); + assert(MI.getNumOperands() == 4); + // If location of variable is described using a register (directly or + // indirectly), this register is always a first operand. + return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; +} + +static bool isClobbered(const TargetRegisterInfo *TRI, const MachineInstr &MI, + const MachineInstr &dbgMI, unsigned SP) { + assert(dbgMI.isDebugValue() && dbgMI.getNumOperands() > 1 && + "Invalid DBG_VALUE instruction!"); + // If DBG_VALUE described by constant + if (!getRegDescriptor(dbgMI)) + return true; + if (MI.isDebugValue()) { + if (dbgMI.getDebugVariable() == MI.getDebugVariable() && + dbgMI.getDebugLoc().getInlinedAt() == MI.getDebugLoc().getInlinedAt()) + return true; + if (unsigned reg1 = getRegDescriptor(MI)) + if (unsigned reg2 = getRegDescriptor(dbgMI)) + return reg1 == reg2; + } else { + if (MI.mayStore()) + return true; + if (unsigned dbgReg = getRegDescriptor(dbgMI)) { + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.isDef() && MO.getReg()) { + if (TRI->isVirtualRegister(MO.getReg())) + return dbgReg == MO.getReg(); + else { + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); + ++AI) { + if (dbgReg == *AI) + return true; + } + } + } else if (MO.isRegMask()) { + // Don't consider SP to be clobbered by register masks. + if (dbgReg != SP && TRI->isPhysicalRegister(dbgReg) && + MO.clobbersPhysReg(dbgReg)) + return true; + } + } + } + } + return false; +} + void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker, PressureDiffs *PDiffs, @@ -750,18 +807,40 @@ // ExitSU. addSchedBarrierDeps(); + bool reattachDbgValueToNearestClobbering = EnableDbgValueReattach; + + const TargetLowering *TLI = ST.getTargetLowering(); + unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); // Walk the list of instructions, from bottom moving up. - MachineInstr *DbgMI = nullptr; + // Track dbg_value instructions and their indices in DbgValues vector + std::list> DbgMIs; + MachineInstr *LastDbgMI = nullptr; for (MachineBasicBlock::iterator MII = RegionEnd, MIE = RegionBegin; MII != MIE; --MII) { MachineInstr &MI = *std::prev(MII); - if (DbgMI) { - DbgValues.push_back(std::make_pair(DbgMI, &MI)); - DbgMI = nullptr; + // maybe re-attach some debug value MIs to their nearest cloberring MI. + if (reattachDbgValueToNearestClobbering && !DbgMIs.empty()) { + for (auto it = DbgMIs.begin(); it != DbgMIs.end();) { + if (isClobbered(TRI, MI, *it->first, SP)) { + LLVM_DEBUG(dbgs() << "Re-attached dbg_value: " << it->first + << "\n >> from: " << *DbgValues[it->second].second + << "\n >> to: " << MI << "\n";); + DbgValues[it->second].second = &MI; + DbgMIs.erase(it++); + } + else ++it; + } + } + if (LastDbgMI) { + DbgValues.emplace_back(LastDbgMI, &MI); + if (reattachDbgValueToNearestClobbering && + !isClobbered(TRI, MI, *LastDbgMI, SP)) + DbgMIs.emplace_back(LastDbgMI, DbgValues.size() - 1); + LastDbgMI = nullptr; } if (MI.isDebugValue()) { - DbgMI = &MI; + LastDbgMI = &MI; continue; } if (MI.isDebugLabel()) @@ -948,8 +1027,8 @@ } } - if (DbgMI) - FirstDbgValue = DbgMI; + if (LastDbgMI) + FirstDbgValue = LastDbgMI; Defs.clear(); Uses.clear(); Index: test/DebugInfo/AArch64/dbg-values-reattach.ll =================================================================== --- test/DebugInfo/AArch64/dbg-values-reattach.ll +++ test/DebugInfo/AArch64/dbg-values-reattach.ll @@ -0,0 +1,145 @@ +; Check that DEBUG_VALUE instructions are not re-scheduled before their correspondent mov instructions (with -enable-dbg-value-reattach fix). + +; RUN: llc -O1 -asm-verbose -march=aarch64 -mtriple=aarch64--linux-gnu -enable-dbg-value-reattach=true < %s | FileCheck -check-prefixes=CHECK-I,CHECK-C,CHECK-S %s +; RUN: llc -O1 -asm-verbose -march=aarch64 -mtriple=aarch64--linux-gnu -enable-dbg-value-reattach=false < %s | not FileCheck -check-prefixes=CHECK-I,CHECK-C,CHECK-S %s + +; CHECK-I: mov w[[IREG:[0-9]+]], w0 +; CHECK-I: DEBUG_VALUE: AddVars:i <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $w[[IREG]] +; CHECK-I: DEBUG_VALUE: AddVars:i <- $w[[IREG]] + +; CHECK-C: mov w[[CREG:[0-9]+]], w1 +; CHECK-C: DEBUG_VALUE: AddVars:c <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $w[[CREG]] +; CHECK-C: DEBUG_VALUE: AddVars:c <- $w[[CREG]] + +; CHECK-S: mov w[[SREG:[0-9]+]], w2 +; CHECK-S: DEBUG_VALUE: AddVars:s <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $w[[SREG]] +; CHECK-S: DEBUG_VALUE: AddVars:s <- $w[[SREG]] + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +$_ZN8OptClass7AddVarsEifdcs = comdat any + +@.str = private unnamed_addr constant [8 x i8] c"i = %d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [8 x i8] c"f = %f\0A\00", align 1 +@.str.2 = private unnamed_addr constant [8 x i8] c"d = %f\0A\00", align 1 +@.str.3 = private unnamed_addr constant [10 x i8] c"c = %hhd\0A\00", align 1 +@.str.4 = private unnamed_addr constant [9 x i8] c"s = %hd\0A\00", align 1 + +; Function Attrs: noimplicitfloat nounwind +define void @_Z1fv() local_unnamed_addr #0 !dbg !8 { + %1 = tail call double @_ZN8OptClass7AddVarsEifdcs(i32 0, float 0.000000e+00, double 1.000000e-01, i8 0, i16 1) #3, !dbg !11 + ret void, !dbg !12 +} + +; Function Attrs: noimplicitfloat nounwind +define linkonce_odr double @_ZN8OptClass7AddVarsEifdcs(i32, float, double, i8, i16) local_unnamed_addr #0 comdat align 2 !dbg !13 { + call void @llvm.dbg.value(metadata i32 %0, metadata !25, metadata !DIExpression()), !dbg !31 + call void @llvm.dbg.value(metadata float %1, metadata !26, metadata !DIExpression()), !dbg !32 + call void @llvm.dbg.value(metadata double %2, metadata !27, metadata !DIExpression()), !dbg !33 + call void @llvm.dbg.value(metadata i8 %3, metadata !28, metadata !DIExpression()), !dbg !34 + call void @llvm.dbg.value(metadata i16 %4, metadata !29, metadata !DIExpression()), !dbg !35 + call void @llvm.dbg.value(metadata double 0.000000e+00, metadata !30, metadata !DIExpression()), !dbg !36 + call void @llvm.dbg.value(metadata i32 %0, metadata !25, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !31 + %6 = fadd float %1, 1.000000e+00, !dbg !37 + call void @llvm.dbg.value(metadata float %6, metadata !26, metadata !DIExpression()), !dbg !32 + %7 = fadd double %2, 1.000000e+00, !dbg !38 + call void @llvm.dbg.value(metadata double %7, metadata !27, metadata !DIExpression()), !dbg !33 + call void @llvm.dbg.value(metadata i8 %3, metadata !28, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !34 + call void @llvm.dbg.value(metadata i16 %4, metadata !29, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !35 + call void @llvm.dbg.value(metadata i32 %0, metadata !25, metadata !DIExpression()), !dbg !31 + %8 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 %0) #3, !dbg !39 + %9 = fadd float %6, -1.000000e+00, !dbg !40 + call void @llvm.dbg.value(metadata float %9, metadata !26, metadata !DIExpression()), !dbg !32 + %10 = fpext float %9 to double, !dbg !40 + %11 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i64 0, i64 0), double %10) #3, !dbg !41 + %12 = fadd double %7, -1.000000e+00, !dbg !42 + call void @llvm.dbg.value(metadata double %12, metadata !27, metadata !DIExpression()), !dbg !33 + %13 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i64 0, i64 0), double %12) #3, !dbg !43 + call void @llvm.dbg.value(metadata i8 %3, metadata !28, metadata !DIExpression()), !dbg !34 + %14 = zext i8 %3 to i32, !dbg !44 + %15 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i64 0, i64 0), i32 %14) #3, !dbg !45 + call void @llvm.dbg.value(metadata i16 %4, metadata !29, metadata !DIExpression()), !dbg !35 + %16 = sext i16 %4 to i32, !dbg !46 + %17 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i32 %16) #3, !dbg !47 + %18 = sitofp i32 %0 to double, !dbg !48 + %19 = fadd double %18, %10, !dbg !49 + %20 = fadd double %12, %19, !dbg !50 + %21 = uitofp i8 %3 to double, !dbg !51 + %22 = fadd double %20, %21, !dbg !52 + %23 = sitofp i16 %4 to double, !dbg !53 + %24 = fadd double %22, %23, !dbg !54 + ret double %24, !dbg !55 +} + +; Function Attrs: noimplicitfloat nounwind +declare i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #2 + +attributes #0 = { noimplicitfloat nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a57" "target-features"="+crc,+crypto,+fp-armv8,+neon" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noimplicitfloat nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a57" "target-features"="+crc,+crypto,+fp-armv8,+neon" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone speculatable } +attributes #3 = { noimplicitfloat } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 7.0.0 (trunk 333100)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "dbg-values-reattach.cpp", directory: "/") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"PIC Level", i32 2} +!7 = !{!"clang version 7.0.0 (trunk 333100)"} +!8 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !1, file: !1, line: 50, type: !9, isLocal: false, isDefinition: true, scopeLine: 51, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !DILocation(line: 52, column: 5, scope: !8) +!12 = !DILocation(line: 53, column: 1, scope: !8) +!13 = distinct !DISubprogram(name: "AddVars", linkageName: "_ZN8OptClass7AddVarsEifdcs", scope: !14, file: !1, line: 6, type: !17, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !0, declaration: !16, retainedNodes: !24) +!14 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "OptClass", file: !1, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !15, identifier: "_ZTS8OptClass") +!15 = !{!16} +!16 = !DISubprogram(name: "AddVars", linkageName: "_ZN8OptClass7AddVarsEifdcs", scope: !14, file: !1, line: 6, type: !17, isLocal: false, isDefinition: false, scopeLine: 6, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, isOptimized: true) +!17 = !DISubroutineType(types: !18) +!18 = !{!19, !20, !21, !19, !22, !23} +!19 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!21 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!22 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!23 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!24 = !{!25, !26, !27, !28, !29, !30} +!25 = !DILocalVariable(name: "i", arg: 1, scope: !13, file: !1, line: 6, type: !20) +!26 = !DILocalVariable(name: "f", arg: 2, scope: !13, file: !1, line: 6, type: !21) +!27 = !DILocalVariable(name: "d", arg: 3, scope: !13, file: !1, line: 6, type: !19) +!28 = !DILocalVariable(name: "c", arg: 4, scope: !13, file: !1, line: 6, type: !22) +!29 = !DILocalVariable(name: "s", arg: 5, scope: !13, file: !1, line: 6, type: !23) +!30 = !DILocalVariable(name: "returnValue", scope: !13, file: !1, line: 8, type: !19) +!31 = !DILocation(line: 6, column: 32, scope: !13) +!32 = !DILocation(line: 6, column: 41, scope: !13) +!33 = !DILocation(line: 6, column: 51, scope: !13) +!34 = !DILocation(line: 6, column: 59, scope: !13) +!35 = !DILocation(line: 6, column: 68, scope: !13) +!36 = !DILocation(line: 8, column: 16, scope: !13) +!37 = !DILocation(line: 21, column: 9, scope: !13) +!38 = !DILocation(line: 22, column: 9, scope: !13) +!39 = !DILocation(line: 26, column: 9, scope: !13) +!40 = !DILocation(line: 27, column: 29, scope: !13) +!41 = !DILocation(line: 27, column: 9, scope: !13) +!42 = !DILocation(line: 28, column: 29, scope: !13) +!43 = !DILocation(line: 28, column: 9, scope: !13) +!44 = !DILocation(line: 29, column: 31, scope: !13) +!45 = !DILocation(line: 29, column: 9, scope: !13) +!46 = !DILocation(line: 30, column: 30, scope: !13) +!47 = !DILocation(line: 30, column: 9, scope: !13) +!48 = !DILocation(line: 46, column: 30, scope: !13) +!49 = !DILocation(line: 46, column: 32, scope: !13) +!50 = !DILocation(line: 46, column: 36, scope: !13) +!51 = !DILocation(line: 46, column: 42, scope: !13) +!52 = !DILocation(line: 46, column: 40, scope: !13) +!53 = !DILocation(line: 46, column: 46, scope: !13) +!54 = !DILocation(line: 46, column: 44, scope: !13) +!55 = !DILocation(line: 46, column: 9, scope: !13) Index: test/DebugInfo/X86/dbg-values-reattach.ll =================================================================== --- test/DebugInfo/X86/dbg-values-reattach.ll +++ test/DebugInfo/X86/dbg-values-reattach.ll @@ -0,0 +1,163 @@ +; Check that DEBUG_VALUE instructions are not re-scheduled before their correspondent mov instructions (with -enable-dbg-value-reattach fix). + +; RUN: llc -O2 -asm-verbose -mtriple=x86_64--linux -mcpu=atom -enable-dbg-value-reattach=true < %s | FileCheck -check-prefixes=CHECK-I,CHECK-C,CHECK-S %s +; RUN: llc -O2 -asm-verbose -mtriple=x86_64--linux -mcpu=atom -enable-dbg-value-reattach=false < %s | not FileCheck -check-prefixes=CHECK-I,CHECK-C,CHECK-S %s + +; CHECK-I: movl %edi, %[[IREG:.*]] +; CHECK-I: DEBUG_VALUE: foo:i <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $[[IREG]] +; CHECK-I: DEBUG_VALUE: foo:i <- $[[IREG]] + +; CHECK-C: movl %esi, %[[CREG:.*]] +; CHECK-C: DEBUG_VALUE: foo:c <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $[[CREG]] +; CHECK-C: DEBUG_VALUE: foo:c <- $[[CREG]] + +; CHECK-S: movl %edx, %[[SREG:.*]] +; CHECK-S: DEBUG_VALUE: foo:s <- [DW_OP_plus_uconst 1, DW_OP_stack_value] $[[SREG]] +; CHECK-S: DEBUG_VALUE: foo:s <- $[[SREG]] + +; ModuleID = './dbg-values-reattach.cpp' +source_filename = "./dbg-values-reattach.cpp" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64--linux" + +@.str = private unnamed_addr constant [8 x i8] c"i = %d\0A\00", align 1 +@.str.1 = private unnamed_addr constant [10 x i8] c"c = %hhd\0A\00", align 1 +@.str.2 = private unnamed_addr constant [9 x i8] c"s = %hd\0A\00", align 1 +@.str.3 = private unnamed_addr constant [13 x i8] c"Vars.i = %d\0A\00", align 1 +@.str.4 = private unnamed_addr constant [15 x i8] c"Vars.c = %hhd\0A\00", align 1 +@.str.5 = private unnamed_addr constant [14 x i8] c"Vars.s = %hd\0A\00", align 1 +@_ZZ3fooicsE4Vars.0 = internal unnamed_addr global i32 0, align 8, !dbg !0 +@_ZZ3fooicsE4Vars.3 = internal unnamed_addr global i8 0, align 8, !dbg !28 +@_ZZ3fooicsE4Vars.4 = internal unnamed_addr global i16 0, align 8, !dbg !29 + +; Function Attrs: nounwind uwtable +define dso_local double @_Z3fooics(i32 %i, i8 signext %c, i16 signext %s) local_unnamed_addr #0 !dbg !2 { +entry: + call void @llvm.dbg.value(metadata i32 %i, metadata !16, metadata !DIExpression()), !dbg !34 + call void @llvm.dbg.value(metadata i8 %c, metadata !17, metadata !DIExpression()), !dbg !35 + call void @llvm.dbg.value(metadata i16 %s, metadata !18, metadata !DIExpression()), !dbg !36 + call void @llvm.dbg.value(metadata double 0.000000e+00, metadata !19, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.value(metadata i32 %i, metadata !16, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !34 + call void @llvm.dbg.value(metadata i8 %c, metadata !17, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !35 + call void @llvm.dbg.value(metadata i16 %s, metadata !18, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !36 + call void @llvm.dbg.value(metadata i32 %i, metadata !16, metadata !DIExpression()), !dbg !34 + %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 %i), !dbg !38 + call void @llvm.dbg.value(metadata i8 %c, metadata !17, metadata !DIExpression()), !dbg !35 + %conv = sext i8 %c to i32, !dbg !39 + %call4 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), i32 %conv), !dbg !40 + call void @llvm.dbg.value(metadata i16 %s, metadata !18, metadata !DIExpression()), !dbg !36 + %conv6 = sext i16 %s to i32, !dbg !41 + %call7 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.2, i64 0, i64 0), i32 %conv6), !dbg !42 + %0 = load i32, i32* @_ZZ3fooicsE4Vars.0, align 8, !dbg !43, !tbaa !44 + %add = add nsw i32 %0, %i, !dbg !43 + %1 = load i8, i8* @_ZZ3fooicsE4Vars.3, align 8, !dbg !52, !tbaa !53 + %add10 = add i8 %1, %c, !dbg !52 + store i8 %add10, i8* @_ZZ3fooicsE4Vars.3, align 8, !dbg !52, !tbaa !53 + %2 = load i16, i16* @_ZZ3fooicsE4Vars.4, align 8, !dbg !54, !tbaa !55 + %add14 = add i16 %2, %s, !dbg !54 + store i16 %add14, i16* @_ZZ3fooicsE4Vars.4, align 8, !dbg !54, !tbaa !55 + %dec16 = add nsw i32 %add, -1, !dbg !56 + store i32 %dec16, i32* @_ZZ3fooicsE4Vars.0, align 8, !dbg !56, !tbaa !44 + %call17 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i64 0, i64 0), i32 %dec16), !dbg !57 + %3 = load i8, i8* @_ZZ3fooicsE4Vars.3, align 8, !dbg !58, !tbaa !53 + %dec18 = add i8 %3, -1, !dbg !58 + store i8 %dec18, i8* @_ZZ3fooicsE4Vars.3, align 8, !dbg !58, !tbaa !53 + %conv19 = sext i8 %dec18 to i32, !dbg !58 + %call20 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.4, i64 0, i64 0), i32 %conv19), !dbg !59 + %4 = load i16, i16* @_ZZ3fooicsE4Vars.4, align 8, !dbg !60, !tbaa !55 + %dec21 = add i16 %4, -1, !dbg !60 + store i16 %dec21, i16* @_ZZ3fooicsE4Vars.4, align 8, !dbg !60, !tbaa !55 + %conv22 = sext i16 %dec21 to i32, !dbg !60 + %call23 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.5, i64 0, i64 0), i32 %conv22), !dbg !61 + %call24 = tail call double @_Z3fooics(i32 %i, i8 signext %c, i16 signext %s), !dbg !62 + %conv25 = sitofp i32 %i to double, !dbg !63 + %conv28 = sitofp i8 %c to double, !dbg !64 + %add29 = fadd double %conv25, %conv28, !dbg !65 + %conv31 = sitofp i16 %s to double, !dbg !66 + %add32 = fadd double %add29, %conv31, !dbg !67 + ret double %add32, !dbg !68 +} + +; Function Attrs: nounwind +declare dso_local i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #2 + +attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="atom" "target-features"="+cx16,+fxsr,+mmx,+movbe,+sahf,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="atom" "target-features"="+cx16,+fxsr,+mmx,+movbe,+sahf,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone speculatable } + +!llvm.dbg.cu = !{!10} +!llvm.module.flags = !{!30, !31, !32} +!llvm.ident = !{!33} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 0, 32)) +!1 = distinct !DIGlobalVariable(name: "Vars", scope: !2, file: !3, line: 14, type: !20, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooics", scope: !3, file: !3, line: 3, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, unit: !10, retainedNodes: !15) +!3 = !DIFile(filename: "./dbg-values-reattach.cpp", directory: "/") +!4 = !DISubroutineType(types: !5) +!5 = !{!6, !7, !8, !9} +!6 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!9 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !11, producer: "clang version 7.0.0 (trunk 333126) (llvm/trunk 333100)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, globals: !13) +!11 = !DIFile(filename: "dbg-values-reattach.cpp", directory: "/") +!12 = !{} +!13 = !{!14} +!14 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!15 = !{!16, !17, !18, !19} +!16 = !DILocalVariable(name: "i", arg: 1, scope: !2, file: !3, line: 3, type: !7) +!17 = !DILocalVariable(name: "c", arg: 2, scope: !2, file: !3, line: 3, type: !8) +!18 = !DILocalVariable(name: "s", arg: 3, scope: !2, file: !3, line: 3, type: !9) +!19 = !DILocalVariable(name: "returnValue", scope: !2, file: !3, line: 5, type: !6) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !2, file: !3, line: 7, size: 192, flags: DIFlagTypePassByValue, elements: !21) +!21 = !{!22, !23, !25, !26, !27} +!22 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !20, file: !3, line: 9, baseType: !7, size: 32) +!23 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !20, file: !3, line: 10, baseType: !24, size: 32, offset: 32) +!24 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!25 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !20, file: !3, line: 11, baseType: !6, size: 64, offset: 64) +!26 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !20, file: !3, line: 12, baseType: !8, size: 8, offset: 128) +!27 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !20, file: !3, line: 13, baseType: !9, size: 16, offset: 144) +!28 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 128, 8)) +!29 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 144, 16)) +!30 = !{i32 2, !"Dwarf Version", i32 4} +!31 = !{i32 2, !"Debug Info Version", i32 3} +!32 = !{i32 1, !"wchar_size", i32 4} +!33 = !{!"clang version 7.0.0 (trunk 333126) (llvm/trunk 333100)"} +!34 = !DILocation(line: 3, column: 16, scope: !2) +!35 = !DILocation(line: 3, column: 24, scope: !2) +!36 = !DILocation(line: 3, column: 33, scope: !2) +!37 = !DILocation(line: 5, column: 12, scope: !2) +!38 = !DILocation(line: 20, column: 5, scope: !2) +!39 = !DILocation(line: 21, column: 27, scope: !2) +!40 = !DILocation(line: 21, column: 5, scope: !2) +!41 = !DILocation(line: 22, column: 26, scope: !2) +!42 = !DILocation(line: 22, column: 5, scope: !2) +!43 = !DILocation(line: 25, column: 12, scope: !2) +!44 = !{!45, !46, i64 0} +!45 = !{!"_ZTSZ3fooicsE3$_0", !46, i64 0, !49, i64 4, !50, i64 8, !47, i64 16, !51, i64 18} +!46 = !{!"int", !47, i64 0} +!47 = !{!"omnipotent char", !48, i64 0} +!48 = !{!"Simple C++ TBAA"} +!49 = !{!"float", !47, i64 0} +!50 = !{!"double", !47, i64 0} +!51 = !{!"short", !47, i64 0} +!52 = !DILocation(line: 26, column: 12, scope: !2) +!53 = !{!45, !47, i64 16} +!54 = !DILocation(line: 27, column: 12, scope: !2) +!55 = !{!45, !51, i64 18} +!56 = !DILocation(line: 29, column: 30, scope: !2) +!57 = !DILocation(line: 29, column: 5, scope: !2) +!58 = !DILocation(line: 30, column: 32, scope: !2) +!59 = !DILocation(line: 30, column: 5, scope: !2) +!60 = !DILocation(line: 31, column: 31, scope: !2) +!61 = !DILocation(line: 31, column: 5, scope: !2) +!62 = !DILocation(line: 33, column: 5, scope: !2) +!63 = !DILocation(line: 35, column: 26, scope: !2) +!64 = !DILocation(line: 35, column: 30, scope: !2) +!65 = !DILocation(line: 35, column: 28, scope: !2) +!66 = !DILocation(line: 35, column: 34, scope: !2) +!67 = !DILocation(line: 35, column: 32, scope: !2) +!68 = !DILocation(line: 35, column: 5, scope: !2)