Index: lib/Transforms/Utils/LoopRotationUtils.cpp =================================================================== --- lib/Transforms/Utils/LoopRotationUtils.cpp +++ lib/Transforms/Utils/LoopRotationUtils.cpp @@ -332,6 +332,19 @@ continue; } + // 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 (auto *IntrInst = dyn_cast(Inst)) { + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) { + Inst->moveBefore(LoopEntryBranch); + continue; + } else if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) { + Inst->moveBefore(Exit->getFirstNonPHI()); + continue; + } + } + // Otherwise, create a duplicate of the instruction. Instruction *C = Inst->clone(); Index: test/Transforms/LoopRotate/lifetimes.ll =================================================================== --- /dev/null +++ test/Transforms/LoopRotate/lifetimes.ll @@ -0,0 +1,52 @@ +; 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) + %tobool = icmp eq i32 %call, 0 + br i1 %tobool, label %if.end, label %a + +if.end: ; preds = %for.body + %inc = add i32 %i.0, 1 + br label %for.cond + +a: ; preds = %for.body + 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 @foo(i32)