Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1596,6 +1596,35 @@ DII->setOperand(2, MetadataAsValue::get(I.getContext(), DIExpr)); DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); } + } else if (auto *EVI = dyn_cast(&I)) { + // Rewrite the extractvalue by shifting away the unrelated bits of the + // aggregate operand. + Value *Agg = EVI->getAggregateOperand(); + ArrayRef FieldIndices = EVI->getIndices(); + unsigned FieldOffset = 0; + for (unsigned I = 0, E = FieldIndices.size(); I < E; ++I) { + Type *IndexedTy = ExtractValueInst::getIndexedType( + Agg->getType(), FieldIndices.take_front(I)); + if (IndexedTy->isStructTy()) { + auto *Layout = DL.getStructLayout(cast(IndexedTy)); + FieldOffset += Layout->getElementOffsetInBits(FieldIndices[I]); + } else if (IndexedTy->isArrayTy()) { + Type *ElementTy = IndexedTy->getSequentialElementType(); + FieldOffset += DL.getTypeAllocSizeInBits(ElementTy) * FieldIndices[I]; + } else { + llvm_unreachable("Not a valid type to index into with extractvalue"); + } + } + + MetadataAsValue *AggMD = wrapMD(Agg); + for (auto *DII : DbgUsers) { + if (FieldOffset) { + applyOps(DII, {dwarf::DW_OP_constu, FieldOffset, dwarf::DW_OP_shr}); + } else { + DII->setOperand(0, AggMD); + DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); + } + } } } Index: test/Transforms/InstCombine/debuginfo-variables.ll =================================================================== --- test/Transforms/InstCombine/debuginfo-variables.ll +++ test/Transforms/InstCombine/debuginfo-variables.ll @@ -94,6 +94,69 @@ ret void } +define void @test_extractvalue_1([1 x i64] %Arr) { +; CHECK-LABEL: @test_extractvalue_1( +; CHECK-NEXT: call void @llvm.dbg.value(metadata [1 x i64] %Arr, metadata !77, metadata !DIExpression()), !dbg !78 + %1 = extractvalue [1 x i64] %Arr, 0 + ret void +} + +define void @test_extractvalue_2([2 x i64] %Arr) { +; CHECK-LABEL: @test_extractvalue_2( +; CHECK-NEXT: call void @llvm.dbg.value(metadata [2 x i64] %Arr, metadata !82, metadata !DIExpression(DW_OP_constu, 64, DW_OP_shr, DW_OP_stack_value)), !dbg !83 + %1 = extractvalue [2 x i64] %Arr, 1 + ret void +} + +%ty1 = type { i32 } + +define void @test_extractvalue_3(%ty1 %S) { +; CHECK-LABEL: @test_extractvalue_3( +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty1 %S, metadata !87, metadata !DIExpression()), !dbg !88 + %1 = extractvalue %ty1 %S, 0 + ret void +} + +; Note: this is an unpacked struct. +%ty2 = type { [2 x i8], [2 x i32], %ty1, [2 x %ty1], <2 x i8>, [1 x [2 x i8]] } + +define void @test_extractvalue_4(%ty2 %S) { +; CHECK-LABEL: @test_extractvalue_4( +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !92, metadata !DIExpression(DW_OP_constu, 8, DW_OP_shr, DW_OP_stack_value)), !dbg !100 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !94, metadata !DIExpression(DW_OP_constu, 64, DW_OP_shr, DW_OP_stack_value)), !dbg !101 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !95, metadata !DIExpression(DW_OP_constu, 96, DW_OP_shr, DW_OP_stack_value)), !dbg !102 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !96, metadata !DIExpression(DW_OP_constu, 160, DW_OP_shr, DW_OP_stack_value)), !dbg !103 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !97, metadata !DIExpression(DW_OP_constu, 192, DW_OP_shr, DW_OP_stack_value)), !dbg !104 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty2 %S, metadata !99, metadata !DIExpression(DW_OP_constu, 216, DW_OP_shr, DW_OP_stack_value)), !dbg !105 + %1 = extractvalue %ty2 %S, 0, 1 + %2 = extractvalue %ty2 %S, 1, 1 + %3 = extractvalue %ty2 %S, 2, 0 + %4 = extractvalue %ty2 %S, 3, 1, 0 + %5 = extractvalue %ty2 %S, 4 + %6 = extractvalue %ty2 %S, 5, 0, 1 + ret void +} + +; Note: this is a packed struct. +%ty3 = type <{ [2 x i8], [2 x i32], %ty1, [2 x %ty1], <2 x i8>, [1 x [2 x i8]] }> + +define void @test_extractvalue_5(%ty3 %S) { +; CHECK-LABEL: @test_extractvalue_5( +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !109, metadata !DIExpression(DW_OP_constu, 8, DW_OP_shr, DW_OP_stack_value)), !dbg !115 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !110, metadata !DIExpression(DW_OP_constu, 48, DW_OP_shr, DW_OP_stack_value)), !dbg !116 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !111, metadata !DIExpression(DW_OP_constu, 80, DW_OP_shr, DW_OP_stack_value)), !dbg !117 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !112, metadata !DIExpression(DW_OP_constu, 144, DW_OP_shr, DW_OP_stack_value)), !dbg !118 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !113, metadata !DIExpression(DW_OP_constu, 176, DW_OP_shr, DW_OP_stack_value)), !dbg !119 +; CHECK-NEXT: call void @llvm.dbg.value(metadata %ty3 %S, metadata !114, metadata !DIExpression(DW_OP_constu, 200, DW_OP_shr, DW_OP_stack_value)), !dbg !120 + %1 = extractvalue %ty3 %S, 0, 1 + %2 = extractvalue %ty3 %S, 1, 1 + %3 = extractvalue %ty3 %S, 2, 0 + %4 = extractvalue %ty3 %S, 3, 1, 0 + %5 = extractvalue %ty3 %S, 4 + %6 = extractvalue %ty3 %S, 5, 0, 1 + ret void +} + ; CHECK: !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9) ; CHECK: !10 = !DILocalVariable(name: "2", scope: !5, file: !1, line: 2, type: !11) ; CHECK: !12 = !DILocation(line: 2, column: 1, scope: !5) @@ -134,3 +197,17 @@ ; CHECK: !72 = !DILocalVariable(name: "14", scope: !70, file: !1, line: 26, type: !11) ; CHECK: !73 = !DILocation(line: 26, column: 1, scope: !70) + +; CHECK: !92 = !DILocalVariable(name: "18", scope: !90, file: !1, line: 34, type: !93) +; CHECK: !94 = !DILocalVariable(name: "19", scope: !90, file: !1, line: 35, type: !9) +; CHECK: !95 = !DILocalVariable(name: "20", scope: !90, file: !1, line: 36, type: !9) +; CHECK: !96 = !DILocalVariable(name: "21", scope: !90, file: !1, line: 37, type: !9) +; CHECK: !97 = !DILocalVariable(name: "22", scope: !90, file: !1, line: 38, type: !98) +; CHECK: !99 = !DILocalVariable(name: "23", scope: !90, file: !1, line: 39, type: !93) + +; CHECK: !109 = !DILocalVariable(name: "24", scope: !107, file: !1, line: 41, type: !93) +; CHECK: !110 = !DILocalVariable(name: "25", scope: !107, file: !1, line: 42, type: !9) +; CHECK: !111 = !DILocalVariable(name: "26", scope: !107, file: !1, line: 43, type: !9) +; CHECK: !112 = !DILocalVariable(name: "27", scope: !107, file: !1, line: 44, type: !9) +; CHECK: !113 = !DILocalVariable(name: "28", scope: !107, file: !1, line: 45, type: !98) +; CHECK: !114 = !DILocalVariable(name: "29", scope: !107, file: !1, line: 46, type: !93)