1 //===- LICMTest.cpp - LICM unit tests -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/ScalarEvolution.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Module.h"
12 #include "llvm/Passes/PassBuilder.h"
13 #include "llvm/Support/SourceMgr.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "llvm/Transforms/Scalar/LICM.h"
16 #include "gtest/gtest.h"
20 TEST(LICMTest
, TestSCEVInvalidationOnHoisting
) {
22 ModulePassManager MPM
;
24 LoopAnalysisManager LAM
;
25 FunctionAnalysisManager FAM
;
26 CGSCCAnalysisManager CGAM
;
27 ModuleAnalysisManager MAM
;
29 PB
.registerModuleAnalyses(MAM
);
30 PB
.registerCGSCCAnalyses(CGAM
);
31 PB
.registerFunctionAnalyses(FAM
);
32 PB
.registerLoopAnalyses(LAM
);
33 PB
.crossRegisterProxies(LAM
, FAM
, CGAM
, MAM
);
35 StringRef PipelineStr
= "require<opt-remark-emit>,loop-mssa(licm)";
36 ASSERT_THAT_ERROR(PB
.parsePassPipeline(MPM
, PipelineStr
), Succeeded());
40 define void @foo(i64* %ptr) {
45 %iv = phi i64 [ 0, %entry ], [ %iv.inc, %loop ]
46 %n = load i64, i64* %ptr, !invariant.load !0
47 %iv.inc = add i64 %iv, 1
48 %cmp = icmp ult i64 %iv.inc, %n
49 br i1 %cmp, label %loop, label %exit
58 std::unique_ptr
<Module
> M
= parseAssemblyString(Text
, Error
, Ctx
);
60 Function
*F
= M
->getFunction("foo");
61 ScalarEvolution
&SE
= FAM
.getResult
<ScalarEvolutionAnalysis
>(*F
);
62 BasicBlock
&EntryBB
= F
->getEntryBlock();
63 BasicBlock
*LoopBB
= EntryBB
.getUniqueSuccessor();
65 // Select `load i64, i64* %ptr`.
66 Instruction
*IBefore
= LoopBB
->getFirstNonPHI();
67 // Make sure the right instruction was selected.
68 ASSERT_TRUE(isa
<LoadInst
>(IBefore
));
69 // Upon this query SCEV caches disposition of <load i64, i64* %ptr> SCEV.
70 ASSERT_EQ(SE
.getBlockDisposition(SE
.getSCEV(IBefore
), LoopBB
),
71 ScalarEvolution::BlockDisposition::DominatesBlock
);
75 // Select `load i64, i64* %ptr` after it was hoisted.
76 Instruction
*IAfter
= EntryBB
.getFirstNonPHI();
77 // Make sure the right instruction was selected.
78 ASSERT_TRUE(isa
<LoadInst
>(IAfter
));
80 ScalarEvolution::BlockDisposition DispositionBeforeInvalidation
=
81 SE
.getBlockDisposition(SE
.getSCEV(IAfter
), LoopBB
);
82 SE
.forgetValue(IAfter
);
83 ScalarEvolution::BlockDisposition DispositionAfterInvalidation
=
84 SE
.getBlockDisposition(SE
.getSCEV(IAfter
), LoopBB
);
86 // If LICM have properly invalidated SCEV,
87 // 1. SCEV of <load i64, i64* %ptr> should properly dominate the "loop" BB,
88 // 2. extra invalidation shouldn't change result of the query.
89 EXPECT_EQ(DispositionBeforeInvalidation
,
90 ScalarEvolution::BlockDisposition::ProperlyDominatesBlock
);
91 EXPECT_EQ(DispositionBeforeInvalidation
, DispositionAfterInvalidation
);