Index: include/llvm/Transforms/Utils/LoopUtils.h =================================================================== --- include/llvm/Transforms/Utils/LoopUtils.h +++ include/llvm/Transforms/Utils/LoopUtils.h @@ -473,16 +473,9 @@ /// getAnalysisUsage. void getLoopAnalysisUsage(AnalysisUsage &AU); -/// Returns true if the hoister and sinker can handle this instruction. -/// If SafetyInfo is null, we are checking for sinking instructions from -/// preheader to loop body (no speculation). -/// If SafetyInfo is not null, we are checking for hoisting/sinking -/// instructions from loop body to preheader/exit. Check if the instruction -/// can execute specultatively. -/// +/// Return true if its safe to hoist or sink the instruction. bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, - Loop *CurLoop, AliasSetTracker *CurAST, - LoopSafetyInfo *SafetyInfo); + Loop *CurLoop, AliasSetTracker *CurAST); } #endif Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -363,7 +363,7 @@ // operands of the instruction are loop invariant. // if (isNotUsedInLoop(I, CurLoop, SafetyInfo) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo)) { + canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST)) { ++II; Changed |= sink(I, LI, DT, CurLoop, CurAST, SafetyInfo); } @@ -416,7 +416,7 @@ // is safe to hoist the instruction. // if (CurLoop->hasLoopInvariantOperands(&I) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo) && + canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST) && isSafeToExecuteUnconditionally( I, DT, CurLoop, SafetyInfo, CurLoop->getLoopPreheader()->getTerminator())) @@ -463,8 +463,7 @@ } bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, - Loop *CurLoop, AliasSetTracker *CurAST, - LoopSafetyInfo *SafetyInfo) { + Loop *CurLoop, AliasSetTracker *CurAST) { // Loads have extra constraints we have to verify before we can hoist them. if (LoadInst *LI = dyn_cast(&I)) { if (!LI->isUnordered()) @@ -530,23 +529,17 @@ return false; } - // Only these instructions are hoistable/sinkable. - if (!isa(I) && !isa(I) && !isa(I) && - !isa(I) && !isa(I) && - !isa(I) && !isa(I) && - !isa(I) && !isa(I) && - !isa(I)) - return false; - - // SafetyInfo is nullptr if we are checking for sinking from preheader to - // loop body. It will be always safe as there is no speculative execution. - if (!SafetyInfo) + // These instructions work on SSA values and have not side effects, and + // known to be moveable. + if (isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I)) return true; - // TODO: Plumb the context instruction through to make hoisting and sinking - // more powerful. Hoisting of loads already works due to the special casing - // above. - return isSafeToExecuteUnconditionally(I, DT, CurLoop, SafetyInfo, nullptr); + // We do not know much about this instruction, return conservatively. + return false; } /// Returns true if a PHINode is a trivially replaceable with an Index: lib/Transforms/Scalar/LoopSink.cpp =================================================================== --- lib/Transforms/Scalar/LoopSink.cpp +++ lib/Transforms/Scalar/LoopSink.cpp @@ -283,7 +283,7 @@ // sinked. for (auto II = Preheader->rbegin(), E = Preheader->rend(); II != E;) { Instruction *I = &*II++; - if (!canSinkOrHoistInst(*I, &AA, &DT, &L, &CurAST, nullptr)) + if (!canSinkOrHoistInst(*I, &AA, &DT, &L, &CurAST)) continue; if (sinkInstruction(L, *I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI)) Changed = true; Index: test/Transforms/LICM/sinking.ll =================================================================== --- test/Transforms/LICM/sinking.ll +++ test/Transforms/LICM/sinking.ll @@ -392,6 +392,38 @@ indirectbr i8* undef, [label %lab21, label %lab19] } +; We can sink the sdiv in the loop here as it has no visible +; side effect. +; CHECK: define i32 @sink_sdiv +define i32 @sink_sdiv(i32, i32, i32) { + %4 = icmp slt i32 0, %0 + br i1 %4, label %preheader, label %ret + +preheader: + br label %header + +header: + %5 = phi i32 [ 0, %preheader ], [ %7, %latch ] + %6 = sdiv i32 %1, %2 + call void @g() + br label %latch + +latch: + %7 = add nsw i32 %5, 1 + %8 = icmp slt i32 %7, %0 + br i1 %8, label %header, label %exit + +exit: +; CHECK: exit: +; CHECK: sdiv + %lcssa = phi i32 [ %6, %latch ] + br label %ret + +ret: + %ret.lcssa = phi i32 [ %lcssa, %exit ], [ 0, %3 ] + ret i32 %ret.lcssa +} + declare void @f(i32*) declare void @g()