Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
AAResults *AA);
static bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
Loop *CurLoop, Instruction &I,
SinkAndHoistLICMFlags &Flags);
SinkAndHoistLICMFlags &Flags,
bool InvariantGroup);
static bool pointerInvalidatedByBlockWithMSSA(BasicBlock &BB, MemorySSA &MSSA,
MemoryUse &MU);
static Instruction *cloneInstructionInExitBlock(
Expand Down Expand Up @@ -1165,13 +1166,14 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
if (isLoadInvariantInLoop(LI, DT, CurLoop))
return true;

bool Invalidated;
bool InvariantGroup = LI->hasMetadata(LLVMContext::MD_invariant_group);

bool Invalidated = pointerInvalidatedByLoopWithMSSA(
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(LI)), CurLoop, I, *Flags,
InvariantGroup);
if (CurAST)
Invalidated = pointerInvalidatedByLoop(MemoryLocation::get(LI), CurAST,
Invalidated &= pointerInvalidatedByLoop(MemoryLocation::get(LI), CurAST,
CurLoop, AA);
else
Invalidated = pointerInvalidatedByLoopWithMSSA(
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(LI)), CurLoop, I, *Flags);
// Check loop-invariant address because this may also be a sinkable load
// whose address is not necessarily loop-invariant.
if (ORE && Invalidated && CurLoop->isLoopInvariant(LI->getPointerOperand()))
Expand Down Expand Up @@ -1227,7 +1229,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
else
Invalidated = pointerInvalidatedByLoopWithMSSA(
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop, I,
*Flags);
*Flags, false);
if (Invalidated)
return false;
}
Expand Down Expand Up @@ -2301,7 +2303,8 @@ static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,

bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
Loop *CurLoop, Instruction &I,
SinkAndHoistLICMFlags &Flags) {
SinkAndHoistLICMFlags &Flags,
bool InvariantGroup) {
// For hoisting, use the walker to determine safety
if (!Flags.getIsSink()) {
MemoryAccess *Source;
Expand All @@ -2312,8 +2315,10 @@ bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
Source = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(MU);
Flags.incrementClobberingCalls();
}

return !MSSA->isLiveOnEntryDef(Source) &&
CurLoop->contains(Source->getBlock());
CurLoop->contains(Source->getBlock()) &&
!(InvariantGroup && Source->getBlock() == CurLoop->getHeader() && isa<MemoryPhi>(Source));
}

// For sinking, we'd need to check all Defs below this use. The getClobbering
Expand Down
69 changes: 69 additions & 0 deletions llvm/test/Transforms/LICM/invariant.group.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=licm < %s -S | FileCheck %s

define void @test(i32* %arg, i32* %arg1) {
; CHECK-LABEL: @test(
; CHECK-NEXT: bb2:
; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[ARG1:%.*]], align 4, !invariant.group !0
; CHECK-NEXT: br label [[BB5:%.*]]
; CHECK: bb5:
; CHECK-NEXT: [[TMP6:%.*]] = phi i64 [ 0, [[BB2:%.*]] ], [ [[TMP10:%.*]], [[BB5]] ]
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[ARG:%.*]], i64 [[TMP6]]
; CHECK-NEXT: store i32 [[TMP3]], i32* [[TMP7]], align 8
; CHECK-NEXT: [[TMP10]] = add nuw nsw i64 [[TMP6]], 1
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 200
; CHECK-NEXT: br i1 [[TMP11]], label [[BB12:%.*]], label [[BB5]]
; CHECK: bb12:
; CHECK-NEXT: ret void
;
bb2: ; preds = %bb
br label %bb5

bb5: ; preds = %bb5, %bb2
%tmp6 = phi i64 [ 0, %bb2 ], [ %tmp10, %bb5 ]
%tmp3 = load i32, i32* %arg1, align 4, !invariant.group !0
%tmp7 = getelementptr inbounds i32, i32* %arg, i64 %tmp6
store i32 %tmp3, i32* %tmp7, align 8
%tmp10 = add nuw nsw i64 %tmp6, 1
%tmp11 = icmp eq i64 %tmp10, 200
br i1 %tmp11, label %bb12, label %bb5

bb12: ; preds = %bb5, %bb
ret void
}


define void @test_fail(i32* %arg, i32* %arg1) {
; CHECK-LABEL: @test_fail(
; CHECK-NEXT: bb2:
; CHECK-NEXT: br label [[BB5:%.*]]
; CHECK: bb5:
; CHECK-NEXT: [[TMP6:%.*]] = phi i64 [ 0, [[BB2:%.*]] ], [ [[TMP10:%.*]], [[BB5]] ]
; CHECK-NEXT: store i32 3, i32* [[ARG1:%.*]], align 4
; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[ARG1]], align 4, !invariant.group !0
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[ARG:%.*]], i64 [[TMP6]]
; CHECK-NEXT: store i32 [[TMP3]], i32* [[TMP7]], align 8
; CHECK-NEXT: [[TMP10]] = add nuw nsw i64 [[TMP6]], 1
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 200
; CHECK-NEXT: br i1 [[TMP11]], label [[BB12:%.*]], label [[BB5]]
; CHECK: bb12:
; CHECK-NEXT: ret void
;
bb2: ; preds = %bb
br label %bb5

bb5: ; preds = %bb5, %bb2
%tmp6 = phi i64 [ 0, %bb2 ], [ %tmp10, %bb5 ]
store i32 3, i32* %arg1
%tmp3 = load i32, i32* %arg1, align 4, !invariant.group !0
%tmp7 = getelementptr inbounds i32, i32* %arg, i64 %tmp6
store i32 %tmp3, i32* %tmp7, align 8
%tmp10 = add nuw nsw i64 %tmp6, 1
%tmp11 = icmp eq i64 %tmp10, 200
br i1 %tmp11, label %bb12, label %bb5

bb12: ; preds = %bb5, %bb
ret void
}

!0 = !{}