Index: lib/Transforms/Utils/LoopRotationUtils.cpp =================================================================== --- lib/Transforms/Utils/LoopRotationUtils.cpp +++ lib/Transforms/Utils/LoopRotationUtils.cpp @@ -362,6 +362,20 @@ ValueMap[Inst] = C; } if (C) { + if (auto *IntrInst = dyn_cast(C)) { + // Duplicating lifetimes will create invalid lifetimes. Instead we can + // extend the lifetime of the memory location by hoisting the start to + // the loop entry and sinking ends to the loop exit. + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) { + C->deleteValue(); + Inst->moveBefore(LoopEntryBranch); + continue; + } else if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) { + C->deleteValue(); + Inst->moveBefore(Exit->getFirstNonPHI()); + continue; + } + } // Otherwise, stick the new instruction into the new block! C->setName(Inst->getName()); C->insertBefore(LoopEntryBranch); Index: test/Transforms/LoopRotate/lifetimes.ll =================================================================== --- /dev/null +++ test/Transforms/LoopRotate/lifetimes.ll @@ -0,0 +1,55 @@ +; RUN: opt -S -loop-rotate < %s -verify-loop-info -verify-dom-info | FileCheck %s + +; Make sure we extend lifetimes properly. + +; CHECK-LABEL: @test( +; CHECK-LABEL: entry: +; CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp) + +; CHECK-LABEL: for.body.lr.ph: +; CHECK-NOT: call void @llvm.lifetime.start.p0i8 +; CHECK-NOT: call void @llvm.lifetime.end.p0i8 + +; CHECK-LABEL: return.loopexit: +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp) + +define void @test(i32 %x) nounwind { +entry: + %m = alloca i32, align 4 + br label %for.cond + +for.cond: ; preds = %if.end, %entry + %i.0 = phi i32 [ 0, %entry ], [ %inc, %if.end ] + %cmp = icmp eq i32 %i.0, %x + %tmp = bitcast i32* %m to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp) + store i32 1, i32* %m + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp) + br i1 %cmp, label %return.loopexit, label %for.body + +for.body: ; preds = %for.cond + %call = tail call i32 @foo(i32 %i.0) nounwind + %tobool = icmp eq i32 %call, 0 + br i1 %tobool, label %if.end, label %a + +if.end: ; preds = %for.body + %call1 = tail call i32 @foo(i32 42) nounwind + %inc = add i32 %i.0, 1 + br label %for.cond + +a: ; preds = %for.body + %call2 = tail call i32 @bar(i32 1) nounwind + br label %return + +return.loopexit: ; preds = %for.cond + br label %return + +return: ; preds = %return.loopexit, %a + ret void +} + +declare void @llvm.lifetime.start.p0i8(i64, i8*) +declare void @llvm.lifetime.end.p0i8(i64, i8*) + +declare i32 @bar(i32) +declare i32 @foo(i32)