Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -1504,6 +1504,14 @@ NewFn->getBasicBlockList().splice(NewFn->begin(), OldFn->getBasicBlockList()); + // Fixup block addresses to reference new function. + SmallVector BlockAddresses; + for (User *U : OldFn->users()) + if (auto *BA = dyn_cast(U)) + BlockAddresses.push_back(BA); + for (auto *BA : BlockAddresses) + BA->replaceAllUsesWith(BlockAddress::get(NewFn, BA->getBasicBlock())); + // Set of all "call-like" instructions that invoke the old function mapped // to their new replacements. SmallVector, 8> CallSitePairs; Index: llvm/test/Transforms/Attributor/misc_crash.ll =================================================================== --- llvm/test/Transforms/Attributor/misc_crash.ll +++ llvm/test/Transforms/Attributor/misc_crash.ll @@ -75,3 +75,36 @@ %2 = load i32, i32* @var2 ret i32 %2 } + +define void @func4() { +; CHECK-LABEL: define {{[^@]+}}@func4 +; CHECK-NEXT: call void @func5() +; CHECK-NEXT: ret void +; + call void @func5(i32 0) + ret void +} + +define internal void @func5(i32 %0) { +; CHECK-LABEL: define {{[^@]+}}@func5 +; CHECK-NEXT: [[TMP1:%.*]] = alloca i8* +; CHECK-NEXT: br label %block +; CHECK: block: +; CHECK-NEXT: store i8* blockaddress(@func5, %block), i8** [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = load i8*, i8** [[TMP1]] +; CHECK-NEXT: call void @func6(i8* [[TMP2]]) +; CHECK-NEXT: ret void +; + %tmp = alloca i8* + br label %block + +block: + store i8* blockaddress(@func5, %block), i8** %tmp + %addr = load i8*, i8** %tmp + call void @func6(i8* %addr) + ret void +} + +; CHECK-LABEL: declare {{[^@]+}}@func6 +; CHECK-SAME: (i8*) +declare void @func6(i8*)