forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- IVDescriptorsTest.cpp - IVDescriptors 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/IVDescriptors.h"
 | |
| #include "llvm/Analysis/AssumptionCache.h"
 | |
| #include "llvm/Analysis/LoopInfo.h"
 | |
| #include "llvm/Analysis/ScalarEvolution.h"
 | |
| #include "llvm/Analysis/TargetLibraryInfo.h"
 | |
| #include "llvm/AsmParser/Parser.h"
 | |
| #include "llvm/IR/Dominators.h"
 | |
| #include "llvm/Support/SourceMgr.h"
 | |
| #include "gtest/gtest.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| /// Build the loop info and scalar evolution for the function and run the Test.
 | |
| static void runWithLoopInfoAndSE(
 | |
|     Module &M, StringRef FuncName,
 | |
|     function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE)> Test) {
 | |
|   auto *F = M.getFunction(FuncName);
 | |
|   ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
 | |
| 
 | |
|   TargetLibraryInfoImpl TLII;
 | |
|   TargetLibraryInfo TLI(TLII);
 | |
|   AssumptionCache AC(*F);
 | |
|   DominatorTree DT(*F);
 | |
|   LoopInfo LI(DT);
 | |
|   ScalarEvolution SE(*F, TLI, AC, DT, LI);
 | |
| 
 | |
|   Test(*F, LI, SE);
 | |
| }
 | |
| 
 | |
| static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
 | |
|   SMDiagnostic Err;
 | |
|   std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
 | |
|   if (!Mod)
 | |
|     Err.print("IVDescriptorsTests", errs());
 | |
|   return Mod;
 | |
| }
 | |
| 
 | |
| // This tests that IVDescriptors can obtain the induction binary operator for
 | |
| // integer induction variables. And hasUnsafeAlgebra() and
 | |
| // getUnsafeAlgebraInst() correctly return the expected behavior, i.e. no unsafe
 | |
| // algebra.
 | |
| TEST(IVDescriptorsTest, LoopWithSingleLatch) {
 | |
|   // Parse the module.
 | |
|   LLVMContext Context;
 | |
| 
 | |
|   std::unique_ptr<Module> M = parseIR(
 | |
|     Context,
 | |
|     R"(define void @foo(i32* %A, i32 %ub) {
 | |
| entry:
 | |
|   br label %for.body
 | |
| for.body:
 | |
|   %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
 | |
|   %idxprom = sext i32 %i to i64
 | |
|   %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
 | |
|   store i32 %i, i32* %arrayidx, align 4
 | |
|   %inc = add nsw i32 %i, 1
 | |
|   %cmp = icmp slt i32 %inc, %ub
 | |
|   br i1 %cmp, label %for.body, label %for.exit
 | |
| for.exit:
 | |
|   br label %for.end
 | |
| for.end:
 | |
|   ret void
 | |
| })"
 | |
|     );
 | |
| 
 | |
|   runWithLoopInfoAndSE(
 | |
|       *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
 | |
|         Function::iterator FI = F.begin();
 | |
|         // First basic block is entry - skip it.
 | |
|         BasicBlock *Header = &*(++FI);
 | |
|         assert(Header->getName() == "for.body");
 | |
|         Loop *L = LI.getLoopFor(Header);
 | |
|         EXPECT_NE(L, nullptr);
 | |
|         PHINode *Inst_i = dyn_cast<PHINode>(&Header->front());
 | |
|         assert(Inst_i->getName() == "i");
 | |
|         InductionDescriptor IndDesc;
 | |
|         bool IsInductionPHI =
 | |
|             InductionDescriptor::isInductionPHI(Inst_i, L, &SE, IndDesc);
 | |
|         EXPECT_TRUE(IsInductionPHI);
 | |
|         Instruction *Inst_inc = nullptr;
 | |
|         BasicBlock::iterator BBI = Header->begin();
 | |
|         do {
 | |
|           if ((&*BBI)->getName() == "inc")
 | |
|             Inst_inc = &*BBI;
 | |
|           ++BBI;
 | |
|         } while (!Inst_inc);
 | |
|         assert(Inst_inc->getName() == "inc");
 | |
|         EXPECT_EQ(IndDesc.getInductionBinOp(), Inst_inc);
 | |
|         EXPECT_FALSE(IndDesc.hasUnsafeAlgebra());
 | |
|         EXPECT_EQ(IndDesc.getUnsafeAlgebraInst(), nullptr);
 | |
|       });
 | |
| }
 |