diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/ProfDataUtils.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" @@ -425,6 +426,21 @@ // Delete the unconditional branch that was just created by the split. StartBlock->getTerminator()->eraseFromParent(); + // Move any lifetime-end intrinsic calls found in the StartBlock to the + // newly-created end block to ensure sound lifetime info after sinking (in + // case any use is sinked). + SmallVector EndLifetimeCalls; + for (Instruction &I : *StartBlock) { + if (IntrinsicInst *II = dyn_cast(&I)) { + if (II->getIntrinsicID() == Intrinsic::lifetime_end) { + EndLifetimeCalls.push_back(&I); + } + } + } + for (auto *LC : EndLifetimeCalls) { + LC->moveBefore(&*EndBlock->getFirstInsertionPt()); + } + // Move any debug/pseudo instructions that were in-between the select // group to the newly-created end block. SmallVector DebugPseudoINS; diff --git a/llvm/test/CodeGen/X86/select-optimize.ll b/llvm/test/CodeGen/X86/select-optimize.ll --- a/llvm/test/CodeGen/X86/select-optimize.ll +++ b/llvm/test/CodeGen/X86/select-optimize.ll @@ -187,6 +187,7 @@ ; Cold value operand with load in its one-use dependence slice shoud result ; into a branch with sinked dependence slice. +; The lifetime-end intrinsics should be soundly preserved. define i32 @expensive_val_operand3(ptr nocapture %a, i32 %b, i32 %y, i1 %cmp) { ; CHECK-LABEL: @expensive_val_operand3( ; CHECK-NEXT: [[SEL_FROZEN:%.*]] = freeze i1 [[CMP:%.*]] @@ -197,9 +198,11 @@ ; CHECK-NEXT: br label [[SELECT_END]] ; CHECK: select.end: ; CHECK-NEXT: [[SEL:%.*]] = phi i32 [ [[X]], [[SELECT_TRUE_SINK]] ], [ [[Y:%.*]], [[TMP0:%.*]] ] +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 2, ptr nonnull [[A]]) ; CHECK-NEXT: ret i32 [[SEL]] ; %load = load i32, ptr %a, align 8 + call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %a) %x = add i32 %load, %b %sel = select i1 %cmp, i32 %x, i32 %y, !prof !17 ret i32 %sel @@ -447,6 +450,9 @@ ; Function Attrs: nounwind readnone speculatable willreturn declare void @llvm.dbg.value(metadata, metadata, metadata) +; Function Attrs: argmemonly mustprogress nocallback nofree nosync nounwind willreturn +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) + !llvm.module.flags = !{!0, !26, !27} !0 = !{i32 1, !"ProfileSummary", !1} !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}