blob: cba45a96e68b487113327b48ffede60548d69864 [file] [log] [blame]
Kit Barton37b79222019-05-14 13:26:36 +00001//===- IVDescriptorsTest.cpp - IVDescriptors unit tests -------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Analysis/IVDescriptors.h"
10#include "llvm/Analysis/AssumptionCache.h"
11#include "llvm/Analysis/LoopInfo.h"
12#include "llvm/Analysis/ScalarEvolution.h"
13#include "llvm/Analysis/TargetLibraryInfo.h"
14#include "llvm/AsmParser/Parser.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/Support/SourceMgr.h"
17#include "gtest/gtest.h"
18
19using namespace llvm;
20
21/// Build the loop info and scalar evolution for the function and run the Test.
22static void runWithLoopInfoAndSE(
23 Module &M, StringRef FuncName,
24 function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE)> Test) {
25 auto *F = M.getFunction(FuncName);
26 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
27
28 TargetLibraryInfoImpl TLII;
29 TargetLibraryInfo TLI(TLII);
30 AssumptionCache AC(*F);
31 DominatorTree DT(*F);
32 LoopInfo LI(DT);
33 ScalarEvolution SE(*F, TLI, AC, DT, LI);
34
35 Test(*F, LI, SE);
36}
37
38static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
39 SMDiagnostic Err;
40 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
41 if (!Mod)
42 Err.print("IVDescriptorsTests", errs());
43 return Mod;
44}
45
46// This tests that IVDescriptors can obtain the induction binary operator for
47// integer induction variables. And hasUnsafeAlgebra() and
48// getUnsafeAlgebraInst() correctly return the expected behavior, i.e. no unsafe
49// algebra.
50TEST(IVDescriptorsTest, LoopWithSingleLatch) {
51 // Parse the module.
52 LLVMContext Context;
53
54 std::unique_ptr<Module> M = parseIR(
55 Context,
56 R"(define void @foo(i32* %A, i32 %ub) {
57entry:
58 br label %for.body
59for.body:
60 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
61 %idxprom = sext i32 %i to i64
62 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
63 store i32 %i, i32* %arrayidx, align 4
64 %inc = add nsw i32 %i, 1
65 %cmp = icmp slt i32 %inc, %ub
66 br i1 %cmp, label %for.body, label %for.exit
67for.exit:
68 br label %for.end
69for.end:
70 ret void
71})"
72 );
73
74 runWithLoopInfoAndSE(
75 *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
76 Function::iterator FI = F.begin();
77 // First basic block is entry - skip it.
78 BasicBlock *Header = &*(++FI);
79 assert(Header->getName() == "for.body");
80 Loop *L = LI.getLoopFor(Header);
81 EXPECT_NE(L, nullptr);
82 PHINode *Inst_i = dyn_cast<PHINode>(&Header->front());
83 assert(Inst_i->getName() == "i");
84 InductionDescriptor IndDesc;
85 bool IsInductionPHI =
86 InductionDescriptor::isInductionPHI(Inst_i, L, &SE, IndDesc);
87 EXPECT_TRUE(IsInductionPHI);
88 Instruction *Inst_inc = nullptr;
89 BasicBlock::iterator BBI = Header->begin();
90 do {
91 if ((&*BBI)->getName() == "inc")
92 Inst_inc = &*BBI;
93 ++BBI;
94 } while (!Inst_inc);
95 assert(Inst_inc->getName() == "inc");
96 EXPECT_EQ(IndDesc.getInductionBinOp(), Inst_inc);
97 EXPECT_FALSE(IndDesc.hasUnsafeAlgebra());
98 EXPECT_EQ(IndDesc.getUnsafeAlgebraInst(), nullptr);
99 });
100}