Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp =================================================================== --- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -967,16 +967,19 @@ for (unsigned Ri = 0; Ri != RetCount; ++Ri) if (NewRetIdxs[Ri] != -1) { Value *V; - if (RetTypes.size() > 1) + if (RetTypes.size() > 1) { // We are still returning a struct, so extract the value from our // return value V = ExtractValueInst::Create(NewCB, NewRetIdxs[Ri], "newret", InsertPt); - else + cast(V)->setDebugLoc(InsertPt->getDebugLoc()); + } else { // We are now returning a single element, so just insert that V = NewCB; + } // Insert the value at the old position RetVal = InsertValueInst::Create(RetVal, V, Ri, "oldret", InsertPt); + cast(RetVal)->setDebugLoc(InsertPt->getDebugLoc()); } // Now, replace all uses of the old call instruction with the return // struct we built @@ -1035,12 +1038,14 @@ if (NewRetIdxs[RetI] != -1) { ExtractValueInst *EV = ExtractValueInst::Create(OldRet, RetI, "oldret", RI); + EV->setDebugLoc(RI->getDebugLoc()); if (RetTypes.size() > 1) { // We're still returning a struct, so reinsert the value into // our new return value at the new index RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[RetI], "newret", RI); + cast(RetVal)->setDebugLoc(RI->getDebugLoc()); } else { // We are now only returning a simple value, so just return the // extracted value. Index: llvm/test/Transforms/DeadArgElim/multdeadretval.ll =================================================================== --- llvm/test/Transforms/DeadArgElim/multdeadretval.ll +++ llvm/test/Transforms/DeadArgElim/multdeadretval.ll @@ -4,6 +4,25 @@ ; any remaining dead stuff. ; RUN: opt < %s -deadargelim -instcombine -dce -S | not grep i16 +; RUN: opt < %s -enable-debugify=synthetic -deadargelim -S 2>&1 \ +; RUN: | FileCheck %s -check-prefix=DEBUG + +; Check that every instruction inserted by -deadargelim has a debug location. +; DEBUG: %oldret = extractvalue { i16, i32 } %B, 1, !dbg ![[RET1:.*]] +; DEBUG: %oldret = extractvalue { i32, i16 } %B, 0, !dbg ![[RET2:.*]] +; DEBUG: %oldret = insertvalue { i16, i32 } undef, i32 %ret, 1, !dbg ![[RET3:.*]] +; DEBUG: %oldret = extractvalue { i32, i32, i16 } %C, 0, !dbg ![[RET4:.*]] +; DEBUG: %newret = insertvalue { i32, i32 } undef, i32 %oldret, 0, !dbg ![[RET4:.*]] +; DEBUG: %oldret1 = extractvalue { i32, i32, i16 } %C, 1, !dbg ![[RET4:.*]] +; DEBUG: %newret2 = insertvalue { i32, i32 } %newret, i32 %oldret1, 1, !dbg ![[RET4:.*]] +; DEBUG: %oldret = extractvalue { { i32 }, { i16, i16 } } %C, 0, !dbg ![[RET5:.*]] +; DEBUG: %oldret = insertvalue { i32, i16 } undef, i32 %ret, 0, !dbg ![[RET6:.*]] +; DEBUG: %newret = extractvalue { i32, i32 } %ret1, 0, !dbg ![[RET7:.*]] +; DEBUG: %oldret1 = insertvalue { i32, i32, i16 } undef, i32 %newret, 0, !dbg ![[RET7:.*]] +; DEBUG: %newret2 = extractvalue { i32, i32 } %ret1, 1, !dbg ![[RET7:.*]] +; DEBUG: %oldret3 = insertvalue { i32, i32, i16 } %oldret1, i32 %newret2, 1, !dbg ![[RET7:.*]] +; DEBUG: %oldret4 = insertvalue { { i32 }, { i16, i16 } } undef, { i32 } %ret2, 0, !dbg ![[RET8:.*]] + define internal {i16, i32} @test(i16 %DEADARG) { %A = insertvalue {i16,i32} undef, i16 1, 0 %B = insertvalue {i16,i32} %A, i32 1001, 1 @@ -66,3 +85,13 @@ %Q = add i32 %W, %LIVE5 ret i32 %Q } + +; --- synthetic DILocations: +; DEBUG-DAG: ![[RET1]] = !DILocation(line: 3, column: 1 +; DEBUG-DAG: ![[RET2]] = !DILocation(line: 7, column: 1 +; DEBUG-DAG: ![[RET3]] = !DILocation(line: 8, column: 1 +; DEBUG-DAG: ![[RET4]] = !DILocation(line: 16, column: 1 +; DEBUG-DAG: ![[RET5]] = !DILocation(line: 20, column: 1 +; DEBUG-DAG: ![[RET6]] = !DILocation(line: 21, column: 1 +; DEBUG-DAG: ![[RET7]] = !DILocation(line: 27, column: 1 +; DEBUG-DAG: ![[RET8]] = !DILocation(line: 33, column: 1