250 lines · cpp
1//===- UtilsTest.cpp ------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/SandboxIR/Utils.h"10#include "llvm/Analysis/AssumptionCache.h"11#include "llvm/Analysis/BasicAliasAnalysis.h"12#include "llvm/Analysis/LoopInfo.h"13#include "llvm/Analysis/TargetLibraryInfo.h"14#include "llvm/AsmParser/Parser.h"15#include "llvm/IR/BasicBlock.h"16#include "llvm/IR/DataLayout.h"17#include "llvm/IR/Dominators.h"18#include "llvm/IR/Function.h"19#include "llvm/IR/Instruction.h"20#include "llvm/IR/Module.h"21#include "llvm/SandboxIR/Constant.h"22#include "llvm/SandboxIR/Context.h"23#include "llvm/SandboxIR/Function.h"24#include "llvm/Support/SourceMgr.h"25#include "gtest/gtest.h"26 27using namespace llvm;28 29struct UtilsTest : public testing::Test {30 LLVMContext C;31 std::unique_ptr<Module> M;32 33 void parseIR(LLVMContext &C, const char *IR) {34 SMDiagnostic Err;35 M = parseAssemblyString(IR, Err, C);36 if (!M)37 Err.print("UtilsTest", errs());38 }39 BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {40 for (BasicBlock &BB : F)41 if (BB.getName() == Name)42 return &BB;43 llvm_unreachable("Expected to find basic block!");44 }45};46 47TEST_F(UtilsTest, getMemoryLocation) {48 parseIR(C, R"IR(49define void @foo(ptr %arg0) {50 %ld = load i8, ptr %arg051 ret void52}53)IR");54 llvm::Function *LLVMF = &*M->getFunction("foo");55 auto *LLVMBB = &*LLVMF->begin();56 auto *LLVMLd = cast<llvm::LoadInst>(&*LLVMBB->begin());57 sandboxir::Context Ctx(C);58 sandboxir::Function *F = Ctx.createFunction(LLVMF);59 auto *BB = &*F->begin();60 auto *Ld = cast<sandboxir::LoadInst>(&*BB->begin());61 EXPECT_EQ(sandboxir::Utils::memoryLocationGetOrNone(Ld),62 MemoryLocation::getOrNone(LLVMLd));63}64 65TEST_F(UtilsTest, GetPointerDiffInBytes) {66 parseIR(C, R"IR(67define void @foo(ptr %ptr) {68 %gep0 = getelementptr inbounds float, ptr %ptr, i64 069 %gep1 = getelementptr inbounds float, ptr %ptr, i64 170 %gep2 = getelementptr inbounds float, ptr %ptr, i64 271 %gep3 = getelementptr inbounds float, ptr %ptr, i64 372 73 %ld0 = load float, ptr %gep074 %ld1 = load float, ptr %gep175 %ld2 = load float, ptr %gep276 %ld3 = load float, ptr %gep377 78 %v2ld0 = load <2 x float>, ptr %gep079 %v2ld1 = load <2 x float>, ptr %gep180 %v2ld2 = load <2 x float>, ptr %gep281 %v2ld3 = load <2 x float>, ptr %gep382 83 %v3ld0 = load <3 x float>, ptr %gep084 %v3ld1 = load <3 x float>, ptr %gep185 %v3ld2 = load <3 x float>, ptr %gep286 %v3ld3 = load <3 x float>, ptr %gep387 ret void88}89)IR");90 llvm::Function &LLVMF = *M->getFunction("foo");91 DominatorTree DT(LLVMF);92 TargetLibraryInfoImpl TLII(M->getTargetTriple());93 TargetLibraryInfo TLI(TLII);94 DataLayout DL(M->getDataLayout());95 AssumptionCache AC(LLVMF);96 BasicAAResult BAA(DL, LLVMF, TLI, AC, &DT);97 AAResults AA(TLI);98 AA.addAAResult(BAA);99 LoopInfo LI(DT);100 ScalarEvolution SE(LLVMF, TLI, AC, DT, LI);101 sandboxir::Context Ctx(C);102 103 auto &F = *Ctx.createFunction(&LLVMF);104 auto &BB = *F.begin();105 auto It = std::next(BB.begin(), 4);106 auto *L0 = cast<sandboxir::LoadInst>(&*It++);107 auto *L1 = cast<sandboxir::LoadInst>(&*It++);108 auto *L2 = cast<sandboxir::LoadInst>(&*It++);109 [[maybe_unused]] auto *L3 = cast<sandboxir::LoadInst>(&*It++);110 111 auto *V2L0 = cast<sandboxir::LoadInst>(&*It++);112 auto *V2L1 = cast<sandboxir::LoadInst>(&*It++);113 auto *V2L2 = cast<sandboxir::LoadInst>(&*It++);114 auto *V2L3 = cast<sandboxir::LoadInst>(&*It++);115 116 [[maybe_unused]] auto *V3L0 = cast<sandboxir::LoadInst>(&*It++);117 auto *V3L1 = cast<sandboxir::LoadInst>(&*It++);118 [[maybe_unused]] auto *V3L2 = cast<sandboxir::LoadInst>(&*It++);119 [[maybe_unused]] auto *V3L3 = cast<sandboxir::LoadInst>(&*It++);120 121 // getPointerDiffInBytes122 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L1, SE), 4);123 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, L2, SE), 8);124 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L1, L0, SE), -4);125 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L0, SE), 0);126 127 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V2L1, SE), 4);128 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(L0, V3L1, SE), 4);129 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L2, SE), 8);130 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L0, V2L3, SE), 12);131 EXPECT_EQ(*sandboxir::Utils::getPointerDiffInBytes(V2L3, V2L0, SE), -12);132 133 // atLowerAddress134 EXPECT_TRUE(sandboxir::Utils::atLowerAddress(L0, L1, SE));135 EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L1, L0, SE));136 EXPECT_FALSE(sandboxir::Utils::atLowerAddress(L3, V3L3, SE));137}138 139TEST_F(UtilsTest, GetExpected) {140 parseIR(C, R"IR(141define float @foo(float %v, ptr %ptr) {142 %add = fadd float %v, %v143 store float %v, ptr %ptr144 ret float %v145}146define void @bar(float %v, ptr %ptr) {147 ret void148}149)IR");150 llvm::Function &Foo = *M->getFunction("foo");151 sandboxir::Context Ctx(C);152 153 Ctx.createFunction(&Foo);154 auto *FooBB = cast<sandboxir::BasicBlock>(Ctx.getValue(&*Foo.begin()));155 auto FooIt = FooBB->begin();156 auto Add = cast<sandboxir::Instruction>(&*FooIt++);157 auto *S0 = cast<sandboxir::Instruction>(&*FooIt++);158 auto *RetF = cast<sandboxir::Instruction>(&*FooIt++);159 // getExpectedValue160 EXPECT_EQ(sandboxir::Utils::getExpectedValue(Add), Add);161 EXPECT_EQ(sandboxir::Utils::getExpectedValue(S0),162 cast<sandboxir::StoreInst>(S0)->getValueOperand());163 EXPECT_EQ(sandboxir::Utils::getExpectedValue(RetF),164 cast<sandboxir::ReturnInst>(RetF)->getReturnValue());165 // getExpectedType166 EXPECT_EQ(sandboxir::Utils::getExpectedType(Add), Add->getType());167 EXPECT_EQ(sandboxir::Utils::getExpectedType(S0),168 cast<sandboxir::StoreInst>(S0)->getValueOperand()->getType());169 EXPECT_EQ(sandboxir::Utils::getExpectedType(RetF),170 cast<sandboxir::ReturnInst>(RetF)->getReturnValue()->getType());171 172 // getExpectedValue for void returns173 llvm::Function &Bar = *M->getFunction("bar");174 Ctx.createFunction(&Bar);175 auto *BarBB = cast<sandboxir::BasicBlock>(Ctx.getValue(&*Bar.begin()));176 auto BarIt = BarBB->begin();177 auto *RetV = cast<sandboxir::Instruction>(&*BarIt++);178 EXPECT_EQ(sandboxir::Utils::getExpectedValue(RetV), nullptr);179}180 181TEST_F(UtilsTest, GetNumBits) {182 parseIR(C, R"IR(183define void @foo(float %arg0, double %arg1, i8 %arg2, i64 %arg3, ptr %arg4) {184bb0:185 %ld0 = load float, ptr %arg4186 %ld1 = load double, ptr %arg4187 %ld2 = load i8, ptr %arg4188 %ld3 = load i64, ptr %arg4189 ret void190}191)IR");192 llvm::Function &Foo = *M->getFunction("foo");193 sandboxir::Context Ctx(C);194 sandboxir::Function *F = Ctx.createFunction(&Foo);195 const DataLayout &DL = M->getDataLayout();196 // getNumBits for scalars via the Value overload197 EXPECT_EQ(sandboxir::Utils::getNumBits(F->getArg(0), DL),198 DL.getTypeSizeInBits(Type::getFloatTy(C)));199 EXPECT_EQ(sandboxir::Utils::getNumBits(F->getArg(1), DL),200 DL.getTypeSizeInBits(Type::getDoubleTy(C)));201 EXPECT_EQ(sandboxir::Utils::getNumBits(F->getArg(2), DL), 8u);202 EXPECT_EQ(sandboxir::Utils::getNumBits(F->getArg(3), DL), 64u);203 204 auto &BB = *F->begin();205 auto It = BB.begin();206 auto *L0 = cast<sandboxir::LoadInst>(&*It++);207 auto *L1 = cast<sandboxir::LoadInst>(&*It++);208 auto *L2 = cast<sandboxir::LoadInst>(&*It++);209 auto *L3 = cast<sandboxir::LoadInst>(&*It++);210 // getNumBits for scalars via the Instruction overload211 EXPECT_EQ(sandboxir::Utils::getNumBits(L0),212 DL.getTypeSizeInBits(Type::getFloatTy(C)));213 EXPECT_EQ(sandboxir::Utils::getNumBits(L1),214 DL.getTypeSizeInBits(Type::getDoubleTy(C)));215 EXPECT_EQ(sandboxir::Utils::getNumBits(L2), 8u);216 EXPECT_EQ(sandboxir::Utils::getNumBits(L3), 64u);217}218 219TEST_F(UtilsTest, GetMemBase) {220 parseIR(C, R"IR(221define void @foo(ptr %ptrA, float %val, ptr %ptrB) {222bb:223 %gepA0 = getelementptr float, ptr %ptrA, i32 0224 %gepA1 = getelementptr float, ptr %ptrA, i32 1225 %gepB0 = getelementptr float, ptr %ptrB, i32 0226 %gepB1 = getelementptr float, ptr %ptrB, i32 1227 store float %val, ptr %gepA0228 store float %val, ptr %gepA1229 store float %val, ptr %gepB0230 store float %val, ptr %gepB1231 ret void232}233)IR");234 llvm::Function &Foo = *M->getFunction("foo");235 sandboxir::Context Ctx(C);236 sandboxir::Function *F = Ctx.createFunction(&Foo);237 238 auto It = std::next(F->begin()->begin(), 4);239 auto *St0 = cast<sandboxir::StoreInst>(&*It++);240 auto *St1 = cast<sandboxir::StoreInst>(&*It++);241 auto *St2 = cast<sandboxir::StoreInst>(&*It++);242 auto *St3 = cast<sandboxir::StoreInst>(&*It++);243 EXPECT_EQ(sandboxir::Utils::getMemInstructionBase(St0),244 sandboxir::Utils::getMemInstructionBase(St1));245 EXPECT_EQ(sandboxir::Utils::getMemInstructionBase(St2),246 sandboxir::Utils::getMemInstructionBase(St3));247 EXPECT_NE(sandboxir::Utils::getMemInstructionBase(St0),248 sandboxir::Utils::getMemInstructionBase(St3));249}250