diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index a226865262ed..ae0c84786e19 100644 --- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -216,6 +216,14 @@ bool LoopIdiomRecognize::runOnCountableLoop() { << CurLoop->getHeader()->getName() << "\n"); bool MadeChange = false; + + // The following transforms hoist stores/memsets into the loop pre-header. + // Give up if the loop has instructions may throw. + LoopSafetyInfo SafetyInfo; + computeLoopSafetyInfo(&SafetyInfo, CurLoop); + if (SafetyInfo.MayThrow) + return MadeChange; + // Scan all the blocks in the loop that are not in subloops. for (auto *BB : CurLoop->getBlocks()) { // Ignore blocks in subloops. diff --git a/llvm/test/Transforms/LoopIdiom/unwind.ll b/llvm/test/Transforms/LoopIdiom/unwind.ll new file mode 100644 index 000000000000..a132cba164bd --- /dev/null +++ b/llvm/test/Transforms/LoopIdiom/unwind.ll @@ -0,0 +1,33 @@ +; RUN: opt -loop-idiom < %s -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @ff() + +define void @test(i8* noalias nocapture %base, i64 %size) #1 { +entry: + %cmp3 = icmp eq i64 %size, 0 + br i1 %cmp3, label %for.end, label %for.body.preheader + +for.body.preheader: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body +; CHECK-LABEL: @test( +; CHECK-NOT: llvm.memset + %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ] + tail call void @ff() + %arrayidx = getelementptr inbounds i8, i8* %base, i64 %indvars.iv + store i8 0, i8* %arrayidx, align 1 + %indvars.iv.next = add i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, %size + br i1 %exitcond, label %for.body, label %for.end.loopexit + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + ret void +} + +attributes #1 = { uwtable }