diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -993,7 +993,7 @@ isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || - isa(I)); + isa(I) || isa(I)); } /// Return true if all of the alias sets within this AST are known not to /// contain a Mod, or if MSSA knows thare are no MemoryDefs in the loop. @@ -1231,6 +1231,10 @@ return MSSA->isLiveOnEntryDef(Source) || !CurLoop->contains(Source->getBlock()); } + } else if (isa(&I)) { + // Freeze instruction cannot be sunk into a loop because it may yield a + // different value for each iteration after sinking. + return !Flags->IsSink; } assert(!I.mayReadOrWriteMemory() && "unhandled aliasing"); @@ -1945,7 +1949,7 @@ // Note that proving a load safe to speculate requires proving // sufficient alignment at the target location. Proving it guaranteed // to execute does as well. Thus we can increase our guaranteed - // alignment as well. + // alignment as well. if (!DereferenceableInPH || (InstAlignment > Alignment)) if (isSafeToExecuteUnconditionally(*Load, DT, CurLoop, SafetyInfo, ORE, Preheader->getTerminator())) { diff --git a/llvm/test/Transforms/LICM/freeze.ll b/llvm/test/Transforms/LICM/freeze.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LICM/freeze.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -licm -S < %s | FileCheck %s + +define void @licm(i1 %a) { +; CHECK-LABEL: @licm( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = freeze i1 [[A:%.*]] +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: call void @use(i1 [[B]]) +; CHECK-NEXT: br label [[LOOP]] +; +entry: + br label %loop +loop: + %b = freeze i1 %a + call void @use(i1 %b) + br label %loop +} + +declare void @use(i1)