[gcov] Bump default version to 11.1
[llvm-project.git] / llvm / unittests / CodeGen / SelectionDAGAddressAnalysisTest.cpp
blob1958104720644ac28c023948c480c5d81eca3ff0
1 //===- llvm/unittest/CodeGen/SelectionDAGAddressAnalysisTest.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/CodeGen/SelectionDAGAddressAnalysis.h"
10 #include "llvm/Analysis/MemoryLocation.h"
11 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/CodeGen/MachineModuleInfo.h"
14 #include "llvm/CodeGen/SelectionDAG.h"
15 #include "llvm/CodeGen/TargetLowering.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/MC/TargetRegistry.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Target/TargetMachine.h"
21 #include "gtest/gtest.h"
23 namespace llvm {
25 class SelectionDAGAddressAnalysisTest : public testing::Test {
26 protected:
27 static void SetUpTestCase() {
28 InitializeAllTargets();
29 InitializeAllTargetMCs();
32 void SetUp() override {
33 StringRef Assembly = "@g = global i32 0\n"
34 "@g_alias = alias i32, i32* @g\n"
35 "define i32 @f() {\n"
36 " %1 = load i32, i32* @g\n"
37 " ret i32 %1\n"
38 "}";
40 Triple TargetTriple("aarch64--");
41 std::string Error;
42 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
43 // FIXME: These tests do not depend on AArch64 specifically, but we have to
44 // initialize a target. A skeleton Target for unittests would allow us to
45 // always run these tests.
46 if (!T)
47 GTEST_SKIP();
49 TargetOptions Options;
50 TM = std::unique_ptr<TargetMachine>(
51 T->createTargetMachine("AArch64", "", "+sve", Options, std::nullopt,
52 std::nullopt, CodeGenOptLevel::Aggressive));
53 if (!TM)
54 GTEST_SKIP();
56 SMDiagnostic SMError;
57 M = parseAssemblyString(Assembly, SMError, Context);
58 if (!M)
59 report_fatal_error(SMError.getMessage());
60 M->setDataLayout(TM->createDataLayout());
62 F = M->getFunction("f");
63 if (!F)
64 report_fatal_error("F?");
65 G = M->getGlobalVariable("g");
66 if (!G)
67 report_fatal_error("G?");
68 AliasedG = M->getNamedAlias("g_alias");
69 if (!AliasedG)
70 report_fatal_error("AliasedG?");
72 MachineModuleInfo MMI(TM.get());
74 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F),
75 MMI.getContext(), 0);
77 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None);
78 if (!DAG)
79 report_fatal_error("DAG?");
80 OptimizationRemarkEmitter ORE(F);
81 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr, MMI,
82 nullptr);
85 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
86 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
89 EVT getTypeToTransformTo(EVT VT) {
90 return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT);
93 LLVMContext Context;
94 std::unique_ptr<TargetMachine> TM;
95 std::unique_ptr<Module> M;
96 Function *F;
97 GlobalVariable *G;
98 GlobalAlias *AliasedG;
99 std::unique_ptr<MachineFunction> MF;
100 std::unique_ptr<SelectionDAG> DAG;
103 TEST_F(SelectionDAGAddressAnalysisTest, sameFrameObject) {
104 SDLoc Loc;
105 auto Int8VT = EVT::getIntegerVT(Context, 8);
106 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
107 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
108 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
109 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
110 TypeSize Offset = TypeSize::getFixed(0);
111 SDValue Value = DAG->getConstant(0, Loc, VecVT);
112 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
113 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
114 PtrInfo.getWithOffset(Offset));
115 TypeSize NumBytes = cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize();
117 bool IsAlias;
118 bool IsValid = BaseIndexOffset::computeAliasing(
119 Store.getNode(), LocationSize::precise(NumBytes), Store.getNode(),
120 LocationSize::precise(NumBytes), *DAG, IsAlias);
122 EXPECT_TRUE(IsValid);
123 EXPECT_TRUE(IsAlias);
126 TEST_F(SelectionDAGAddressAnalysisTest, sameFrameObjectUnknownSize) {
127 SDLoc Loc;
128 auto Int8VT = EVT::getIntegerVT(Context, 8);
129 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
130 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
131 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
132 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
133 TypeSize Offset = TypeSize::getFixed(0);
134 SDValue Value = DAG->getConstant(0, Loc, VecVT);
135 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
136 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
137 PtrInfo.getWithOffset(Offset));
139 bool IsAlias;
140 bool IsValid = BaseIndexOffset::computeAliasing(
141 Store.getNode(), LocationSize::beforeOrAfterPointer(), Store.getNode(),
142 LocationSize::beforeOrAfterPointer(), *DAG, IsAlias);
144 EXPECT_FALSE(IsValid);
147 TEST_F(SelectionDAGAddressAnalysisTest, noAliasingFrameObjects) {
148 SDLoc Loc;
149 auto Int8VT = EVT::getIntegerVT(Context, 8);
150 // <4 x i8>
151 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
152 // <2 x i8>
153 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2);
154 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
155 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
156 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
157 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
158 TypeSize Offset0 = TypeSize::getFixed(0);
159 TypeSize Offset1 = SubVecVT.getStoreSize();
160 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
161 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
162 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0,
163 PtrInfo.getWithOffset(Offset0));
164 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
165 PtrInfo.getWithOffset(Offset1));
166 TypeSize NumBytes0 = cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize();
167 TypeSize NumBytes1 = cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize();
169 bool IsAlias;
170 bool IsValid = BaseIndexOffset::computeAliasing(
171 Store0.getNode(), LocationSize::precise(NumBytes0), Store1.getNode(),
172 LocationSize::precise(NumBytes1), *DAG, IsAlias);
174 EXPECT_TRUE(IsValid);
175 EXPECT_FALSE(IsAlias);
178 TEST_F(SelectionDAGAddressAnalysisTest, unknownSizeFrameObjects) {
179 SDLoc Loc;
180 auto Int8VT = EVT::getIntegerVT(Context, 8);
181 // <vscale x 4 x i8>
182 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
183 // <vscale x 2 x i8>
184 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
185 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
186 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
187 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
188 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
189 TypeSize Offset1 = SubVecVT.getStoreSize();
190 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
191 SDValue Store0 =
192 DAG->getStore(DAG->getEntryNode(), Loc, Value, FIPtr, PtrInfo);
193 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
194 MachinePointerInfo(PtrInfo.getAddrSpace()));
195 TypeSize NumBytes0 = cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize();
196 TypeSize NumBytes1 = cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize();
198 bool IsAlias;
199 bool IsValid = BaseIndexOffset::computeAliasing(
200 Store0.getNode(), LocationSize::precise(NumBytes0), Store1.getNode(),
201 LocationSize::precise(NumBytes1), *DAG, IsAlias);
203 EXPECT_FALSE(IsValid);
206 TEST_F(SelectionDAGAddressAnalysisTest, globalWithFrameObject) {
207 SDLoc Loc;
208 auto Int8VT = EVT::getIntegerVT(Context, 8);
209 // <vscale x 4 x i8>
210 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
211 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
212 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
213 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
214 SDValue Value = DAG->getConstant(0, Loc, VecVT);
215 TypeSize Offset = TypeSize::getFixed(0);
216 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
217 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
218 PtrInfo.getWithOffset(Offset));
219 TypeSize NumBytes = cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize();
220 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(),
221 G->getType());
222 SDValue GValue = DAG->getConstant(0, Loc, GTy);
223 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy);
224 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr,
225 MachinePointerInfo(G, 0));
226 TypeSize GNumBytes = cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize();
228 bool IsAlias;
229 bool IsValid = BaseIndexOffset::computeAliasing(
230 Store.getNode(), LocationSize::precise(NumBytes), GStore.getNode(),
231 LocationSize::precise(GNumBytes), *DAG, IsAlias);
233 EXPECT_TRUE(IsValid);
234 EXPECT_FALSE(IsAlias);
237 TEST_F(SelectionDAGAddressAnalysisTest, globalWithAliasedGlobal) {
238 SDLoc Loc;
240 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(),
241 G->getType());
242 SDValue GValue = DAG->getConstant(0, Loc, GTy);
243 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy);
244 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr,
245 MachinePointerInfo(G, 0));
246 TypeSize GNumBytes = cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize();
248 SDValue AliasedGValue = DAG->getConstant(1, Loc, GTy);
249 SDValue AliasedGAddr = DAG->getGlobalAddress(AliasedG, Loc, GTy);
250 SDValue AliasedGStore =
251 DAG->getStore(DAG->getEntryNode(), Loc, AliasedGValue, AliasedGAddr,
252 MachinePointerInfo(AliasedG, 0));
254 bool IsAlias;
255 bool IsValid = BaseIndexOffset::computeAliasing(
256 GStore.getNode(), LocationSize::precise(GNumBytes),
257 AliasedGStore.getNode(), LocationSize::precise(GNumBytes), *DAG, IsAlias);
259 // With some deeper analysis we could detect if G and AliasedG is aliasing or
260 // not. But computeAliasing is currently defensive and assumes that a
261 // GlobalAlias might alias with any global variable.
262 EXPECT_FALSE(IsValid);
265 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsWithinDiff) {
266 SDLoc Loc;
267 auto Int8VT = EVT::getIntegerVT(Context, 8);
268 // <vscale x 4 x i8>
269 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
270 // <vscale x 2 x i8>
271 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
272 // <2 x i8>
273 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2);
274 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
275 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
276 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
277 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT2xi8);
278 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
279 TypeSize Offset0 = TypeSize::getFixed(0);
280 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
281 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
282 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
283 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
284 PtrInfo.getWithOffset(Offset0));
285 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
286 PtrInfo.getWithOffset(Offset1));
287 TypeSize NumBytes0 = cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize();
288 TypeSize NumBytes1 = cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize();
290 bool IsAlias;
291 bool IsValid = BaseIndexOffset::computeAliasing(
292 Store0.getNode(), LocationSize::precise(NumBytes0), Store1.getNode(),
293 LocationSize::precise(NumBytes1), *DAG, IsAlias);
294 EXPECT_TRUE(IsValid);
295 EXPECT_FALSE(IsAlias);
297 IsValid = BaseIndexOffset::computeAliasing(
298 Store1.getNode(), LocationSize::precise(NumBytes1), Store0.getNode(),
299 LocationSize::precise(NumBytes0), *DAG, IsAlias);
300 EXPECT_TRUE(IsValid);
301 EXPECT_FALSE(IsAlias);
304 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsOutOfDiff) {
305 SDLoc Loc;
306 auto Int8VT = EVT::getIntegerVT(Context, 8);
307 // <vscale x 4 x i8>
308 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
309 // <vscale x 2 x i8>
310 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
311 // <2 x i8>
312 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2);
313 // <4 x i8>
314 auto SubFixedVecVT4xi8 = EVT::getVectorVT(Context, Int8VT, 4);
315 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
316 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
317 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
318 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT4xi8);
319 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
320 TypeSize Offset0 = TypeSize::getFixed(0);
321 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
322 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
323 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
324 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
325 PtrInfo.getWithOffset(Offset0));
326 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
327 PtrInfo.getWithOffset(Offset1));
328 TypeSize NumBytes0 = cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize();
329 TypeSize NumBytes1 = cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize();
331 bool IsAlias;
332 bool IsValid = BaseIndexOffset::computeAliasing(
333 Store0.getNode(), LocationSize::precise(NumBytes0), Store1.getNode(),
334 LocationSize::precise(NumBytes1), *DAG, IsAlias);
335 EXPECT_TRUE(IsValid);
336 EXPECT_TRUE(IsAlias);
339 TEST_F(SelectionDAGAddressAnalysisTest, twoFixedStackObjects) {
340 SDLoc Loc;
341 auto Int8VT = EVT::getIntegerVT(Context, 8);
342 // <vscale x 2 x i8>
343 auto VecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
344 // <2 x i8>
345 auto FixedVecVT = EVT::getVectorVT(Context, Int8VT, 2);
346 SDValue FIPtr0 = DAG->CreateStackTemporary(FixedVecVT);
347 SDValue FIPtr1 = DAG->CreateStackTemporary(VecVT);
348 int FI0 = cast<FrameIndexSDNode>(FIPtr0.getNode())->getIndex();
349 int FI1 = cast<FrameIndexSDNode>(FIPtr1.getNode())->getIndex();
350 MachinePointerInfo PtrInfo0 = MachinePointerInfo::getFixedStack(*MF, FI0);
351 MachinePointerInfo PtrInfo1 = MachinePointerInfo::getFixedStack(*MF, FI1);
352 SDValue Value0 = DAG->getConstant(0, Loc, FixedVecVT);
353 SDValue Value1 = DAG->getConstant(0, Loc, VecVT);
354 TypeSize Offset0 = TypeSize::getFixed(0);
355 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr0, Offset0, Loc);
356 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr1, Offset0, Loc);
357 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
358 PtrInfo0.getWithOffset(Offset0));
359 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
360 PtrInfo1.getWithOffset(Offset0));
361 TypeSize NumBytes0 = cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize();
362 TypeSize NumBytes1 = cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize();
364 bool IsAlias;
365 bool IsValid = BaseIndexOffset::computeAliasing(
366 Store0.getNode(), LocationSize::precise(NumBytes0), Store1.getNode(),
367 LocationSize::precise(NumBytes1), *DAG, IsAlias);
368 EXPECT_TRUE(IsValid);
369 EXPECT_FALSE(IsAlias);
372 } // end namespace llvm