[AArch64] Add extra add/cast tests for select-optimize.
[llvm-project.git] / llvm / unittests / SandboxIR / UtilsTest.cpp
bloba30fc253a1a7423b23a3d379babc94b58cd4e60c
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-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
27 using namespace llvm;
29 struct UtilsTest : public testing::Test {
30 LLVMContext C;
31 std::unique_ptr<Module> M;
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());
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!");
47 TEST_F(UtilsTest, getMemoryLocation) {
48 parseIR(C, R"IR(
49 define void @foo(ptr %arg0) {
50 %ld = load i8, ptr %arg0
51 ret void
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));
65 TEST_F(UtilsTest, GetPointerDiffInBytes) {
66 parseIR(C, R"IR(
67 define void @foo(ptr %ptr) {
68 %gep0 = getelementptr inbounds float, ptr %ptr, i64 0
69 %gep1 = getelementptr inbounds float, ptr %ptr, i64 1
70 %gep2 = getelementptr inbounds float, ptr %ptr, i64 2
71 %gep3 = getelementptr inbounds float, ptr %ptr, i64 3
73 %ld0 = load float, ptr %gep0
74 %ld1 = load float, ptr %gep1
75 %ld2 = load float, ptr %gep2
76 %ld3 = load float, ptr %gep3
78 %v2ld0 = load <2 x float>, ptr %gep0
79 %v2ld1 = load <2 x float>, ptr %gep1
80 %v2ld2 = load <2 x float>, ptr %gep2
81 %v2ld3 = load <2 x float>, ptr %gep3
83 %v3ld0 = load <3 x float>, ptr %gep0
84 %v3ld1 = load <3 x float>, ptr %gep1
85 %v3ld2 = load <3 x float>, ptr %gep2
86 %v3ld3 = load <3 x float>, ptr %gep3
87 ret void
89 )IR");
90 llvm::Function &LLVMF = *M->getFunction("foo");
91 DominatorTree DT(LLVMF);
92 TargetLibraryInfoImpl TLII;
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);
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++);
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++);
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++);
121 // getPointerDiffInBytes
122 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);
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);
133 // atLowerAddress
134 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));
139 TEST_F(UtilsTest, GetExpected) {
140 parseIR(C, R"IR(
141 define float @foo(float %v, ptr %ptr) {
142 %add = fadd float %v, %v
143 store float %v, ptr %ptr
144 ret float %v
146 define void @bar(float %v, ptr %ptr) {
147 ret void
149 )IR");
150 llvm::Function &Foo = *M->getFunction("foo");
151 sandboxir::Context Ctx(C);
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 // getExpectedValue
160 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 // getExpectedType
166 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());
172 // getExpectedValue for void returns
173 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);
181 TEST_F(UtilsTest, GetNumBits) {
182 parseIR(C, R"IR(
183 define void @foo(float %arg0, double %arg1, i8 %arg2, i64 %arg3, ptr %arg4) {
184 bb0:
185 %ld0 = load float, ptr %arg4
186 %ld1 = load double, ptr %arg4
187 %ld2 = load i8, ptr %arg4
188 %ld3 = load i64, ptr %arg4
189 ret void
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 overload
197 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);
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 overload
211 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);
219 TEST_F(UtilsTest, GetMemBase) {
220 parseIR(C, R"IR(
221 define void @foo(ptr %ptrA, float %val, ptr %ptrB) {
223 %gepA0 = getelementptr float, ptr %ptrA, i32 0
224 %gepA1 = getelementptr float, ptr %ptrA, i32 1
225 %gepB0 = getelementptr float, ptr %ptrB, i32 0
226 %gepB1 = getelementptr float, ptr %ptrB, i32 1
227 store float %val, ptr %gepA0
228 store float %val, ptr %gepA1
229 store float %val, ptr %gepB0
230 store float %val, ptr %gepB1
231 ret void
233 )IR");
234 llvm::Function &Foo = *M->getFunction("foo");
235 sandboxir::Context Ctx(C);
236 sandboxir::Function *F = Ctx.createFunction(&Foo);
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));