1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00
llvm-mirror/unittests/Transforms/Scalar/LICMTest.cpp
Serguei Katkov fbe4879842 [LICM] Invalidate SCEV upon instruction hoisting
Since SCEV can cache information about location of an instruction, it should be invalidated when the instruction is moved.
There should be similar bug in code sinking part of LICM, it will be fixed in a follow-up change.

Patch Author: Daniil Suchkov
Reviewers: asbirlea, mkazantsev, reames
Reviewed By: asbirlea
Subscribers: hiraditya, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D69370
2019-10-31 17:37:53 +07:00

94 lines
3.1 KiB
C++

//===- LICMTest.cpp - LICM unit tests -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Module.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Testing/Support/Error.h"
#include "llvm/Transforms/Scalar/LICM.h"
#include "gtest/gtest.h"
namespace llvm {
TEST(LICMTest, TestSCEVInvalidationOnHoisting) {
LLVMContext Ctx;
ModulePassManager MPM;
PassBuilder PB;
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
StringRef PipelineStr = "require<opt-remark-emit>,loop(licm)";
ASSERT_THAT_ERROR(PB.parsePassPipeline(MPM, PipelineStr), Succeeded());
SMDiagnostic Error;
StringRef Text = R"(
define void @foo(i64* %ptr) {
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.inc, %loop ]
%n = load i64, i64* %ptr, !invariant.load !0
%iv.inc = add i64 %iv, 1
%cmp = icmp ult i64 %iv.inc, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
!0 = !{}
)";
std::unique_ptr<Module> M = parseAssemblyString(Text, Error, Ctx);
ASSERT_TRUE(M);
Function *F = M->getFunction("foo");
ScalarEvolution &SE = FAM.getResult<ScalarEvolutionAnalysis>(*F);
BasicBlock &EntryBB = F->getEntryBlock();
BasicBlock *LoopBB = EntryBB.getUniqueSuccessor();
// Select `load i64, i64* %ptr`.
Instruction *IBefore = LoopBB->getFirstNonPHI();
// Make sure the right instruction was selected.
ASSERT_TRUE(isa<LoadInst>(IBefore));
// Upon this query SCEV caches disposition of <load i64, i64* %ptr> SCEV.
ASSERT_EQ(SE.getBlockDisposition(SE.getSCEV(IBefore), LoopBB),
ScalarEvolution::BlockDisposition::DominatesBlock);
MPM.run(*M, MAM);
// Select `load i64, i64* %ptr` after it was hoisted.
Instruction *IAfter = EntryBB.getFirstNonPHI();
// Make sure the right instruction was selected.
ASSERT_TRUE(isa<LoadInst>(IAfter));
ScalarEvolution::BlockDisposition DispositionBeforeInvalidation =
SE.getBlockDisposition(SE.getSCEV(IAfter), LoopBB);
SE.forgetValue(IAfter);
ScalarEvolution::BlockDisposition DispositionAfterInvalidation =
SE.getBlockDisposition(SE.getSCEV(IAfter), LoopBB);
// If LICM have properly invalidated SCEV,
// 1. SCEV of <load i64, i64* %ptr> should properly dominate the "loop" BB,
// 2. extra invalidation shouldn't change result of the query.
EXPECT_EQ(DispositionBeforeInvalidation,
ScalarEvolution::BlockDisposition::ProperlyDominatesBlock);
EXPECT_EQ(DispositionBeforeInvalidation, DispositionAfterInvalidation);
}
}