Index: llvm/trunk/lib/Transforms/Scalar/LICM.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp @@ -77,7 +77,8 @@ static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI); static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop, const LICMSafetyInfo *SafetyInfo); -static bool hoist(Instruction &I, BasicBlock *Preheader); +static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, + const LICMSafetyInfo *SafetyInfo); static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT, const Loop *CurLoop, AliasSetTracker *CurAST, const LICMSafetyInfo *SafetyInfo); @@ -397,7 +398,7 @@ canSinkOrHoistInst(I, AA, DT, TLI, CurLoop, CurAST, SafetyInfo) && isSafeToExecuteUnconditionally(I, DT, TLI, CurLoop, SafetyInfo, CurLoop->getLoopPreheader()->getTerminator())) - Changed |= hoist(I, CurLoop->getLoopPreheader()); + Changed |= hoist(I, DT, CurLoop, SafetyInfo); } const std::vector &Children = N->getChildren(); @@ -716,16 +717,26 @@ /// When an instruction is found to only use loop invariant operands that /// is safe to hoist, this instruction is called to do the dirty work. /// -static bool hoist(Instruction &I, BasicBlock *Preheader) { +static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, + const LICMSafetyInfo *SafetyInfo) { + auto *Preheader = CurLoop->getLoopPreheader(); DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I << "\n"); + + // Metadata can be dependent on conditions we are hoisting above. + // Conservatively strip all metadata on the instruction unless we were + // guaranteed to execute I if we entered the loop, in which case the metadata + // is valid in the loop preheader. + if (I.hasMetadataOtherThanDebugLoc() && + // The check on hasMetadataOtherThanDebugLoc is to prevent us from burning + // time in isGuaranteedToExecute if we don't actually have anything to + // drop. It is a compile time optimization, not required for correctness. + !isGuaranteedToExecute(I, DT, CurLoop, SafetyInfo)) + I.dropUnknownNonDebugMetadata(); + // Move the new node to the Preheader, before its terminator. I.moveBefore(Preheader->getTerminator()); - // Metadata can be dependent on the condition we are hoisting above. - // Conservatively strip all metadata on the instruction. - I.dropUnknownNonDebugMetadata(); - if (isa(I)) ++NumMovedLoads; else if (isa(I)) ++NumMovedCalls; ++NumHoisted; Index: llvm/trunk/test/Transforms/LICM/hoist-deref-load.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/hoist-deref-load.ll +++ llvm/trunk/test/Transforms/LICM/hoist-deref-load.ll @@ -432,5 +432,42 @@ ret void } +define void @test11(i32* noalias %a, i32* %b, i32** dereferenceable(8) %cptr, i32 %n) #0 { +; CHECK-LABEL: @test11( +entry: + %cmp11 = icmp sgt i32 %n, 0 + br i1 %cmp11, label %for.body, label %for.end + +; CHECK: for.body.preheader: +; CHECK: %c = load i32*, i32** %cptr, !dereferenceable !0 +; CHECK: %d = load i32, i32* %c, align 4 + + +for.body: ; preds = %entry, %for.inc + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv + %0 = load i32, i32* %arrayidx, align 4 + %cmp1 = icmp sgt i32 %0, 0 + %c = load i32*, i32** %cptr, !dereferenceable !0 + br i1 %cmp1, label %if.then, label %for.inc + +if.then: ; preds = %for.body + %d = load i32, i32* %c, align 4 + %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv + %e = load i32, i32* %arrayidx3, align 4 + %mul = mul nsw i32 %e, %d + store i32 %mul, i32* %arrayidx, align 4 + br label %for.inc + +for.inc: ; preds = %for.body, %if.then + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, %n + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.inc, %entry + ret void +} + attributes #0 = { nounwind uwtable } !0 = !{i64 4}