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 //===----------------------------------------------------------------------===//
8
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/Support/SourceMgr.h"
17 #include "llvm/Support/TargetRegistry.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "gtest/gtest.h"
21
22 namespace llvm {
23
24 class SelectionDAGAddressAnalysisTest : public testing::Test {
25 protected:
SetUpTestCase()26 static void SetUpTestCase() {
27 InitializeAllTargets();
28 InitializeAllTargetMCs();
29 }
30
SetUp()31 void SetUp() override {
32 StringRef Assembly = "@g = global i32 0\n"
33 "define i32 @f() {\n"
34 " %1 = load i32, i32* @g\n"
35 " ret i32 %1\n"
36 "}";
37
38 Triple TargetTriple("aarch64--");
39 std::string Error;
40 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
41 // FIXME: These tests do not depend on AArch64 specifically, but we have to
42 // initialize a target. A skeleton Target for unittests would allow us to
43 // always run these tests.
44 if (!T)
45 return;
46
47 TargetOptions Options;
48 TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
49 T->createTargetMachine("AArch64", "", "+sve", Options, None, None,
50 CodeGenOpt::Aggressive)));
51 if (!TM)
52 return;
53
54 SMDiagnostic SMError;
55 M = parseAssemblyString(Assembly, SMError, Context);
56 if (!M)
57 report_fatal_error(SMError.getMessage());
58 M->setDataLayout(TM->createDataLayout());
59
60 F = M->getFunction("f");
61 if (!F)
62 report_fatal_error("F?");
63 G = M->getGlobalVariable("g");
64 if (!G)
65 report_fatal_error("G?");
66
67 MachineModuleInfo MMI(TM.get());
68
69 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F),
70 0, MMI);
71
72 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOpt::None);
73 if (!DAG)
74 report_fatal_error("DAG?");
75 OptimizationRemarkEmitter ORE(F);
76 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr);
77 }
78
getTypeAction(EVT VT)79 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
80 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
81 }
82
getTypeToTransformTo(EVT VT)83 EVT getTypeToTransformTo(EVT VT) {
84 return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT);
85 }
86
87 LLVMContext Context;
88 std::unique_ptr<LLVMTargetMachine> TM;
89 std::unique_ptr<Module> M;
90 Function *F;
91 GlobalVariable *G;
92 std::unique_ptr<MachineFunction> MF;
93 std::unique_ptr<SelectionDAG> DAG;
94 };
95
TEST_F(SelectionDAGAddressAnalysisTest,sameFrameObject)96 TEST_F(SelectionDAGAddressAnalysisTest, sameFrameObject) {
97 if (!TM)
98 return;
99 SDLoc Loc;
100 auto Int8VT = EVT::getIntegerVT(Context, 8);
101 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
102 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
103 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
104 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
105 TypeSize Offset = TypeSize::Fixed(0);
106 SDValue Value = DAG->getConstant(0, Loc, VecVT);
107 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
108 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
109 PtrInfo.getWithOffset(Offset));
110 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown(
111 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize());
112
113 bool IsAlias;
114 bool IsValid = BaseIndexOffset::computeAliasing(
115 Store.getNode(), NumBytes, Store.getNode(), NumBytes, *DAG, IsAlias);
116
117 EXPECT_TRUE(IsValid);
118 EXPECT_TRUE(IsAlias);
119 }
120
TEST_F(SelectionDAGAddressAnalysisTest,noAliasingFrameObjects)121 TEST_F(SelectionDAGAddressAnalysisTest, noAliasingFrameObjects) {
122 if (!TM)
123 return;
124 SDLoc Loc;
125 auto Int8VT = EVT::getIntegerVT(Context, 8);
126 // <4 x i8>
127 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
128 // <2 x i8>
129 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2);
130 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
131 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
132 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
133 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
134 TypeSize Offset0 = TypeSize::Fixed(0);
135 TypeSize Offset1 = SubVecVT.getStoreSize();
136 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
137 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
138 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0,
139 PtrInfo.getWithOffset(Offset0));
140 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
141 PtrInfo.getWithOffset(Offset1));
142 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
143 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
144 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
145 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
146
147 bool IsAlias;
148 bool IsValid = BaseIndexOffset::computeAliasing(
149 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
150
151 EXPECT_TRUE(IsValid);
152 EXPECT_FALSE(IsAlias);
153 }
154
TEST_F(SelectionDAGAddressAnalysisTest,unknownSizeFrameObjects)155 TEST_F(SelectionDAGAddressAnalysisTest, unknownSizeFrameObjects) {
156 if (!TM)
157 return;
158 SDLoc Loc;
159 auto Int8VT = EVT::getIntegerVT(Context, 8);
160 // <vscale x 4 x i8>
161 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
162 // <vscale x 2 x i8>
163 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
164 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
165 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
166 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
167 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
168 TypeSize Offset0 = TypeSize::Fixed(0);
169 TypeSize Offset1 = SubVecVT.getStoreSize();
170 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
171 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
172 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0,
173 PtrInfo.getWithOffset(Offset0));
174 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
175 PtrInfo.getWithOffset(Offset1));
176 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
177 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
178 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
179 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
180
181 bool IsAlias;
182 bool IsValid = BaseIndexOffset::computeAliasing(
183 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
184
185 EXPECT_FALSE(IsValid);
186 }
187
TEST_F(SelectionDAGAddressAnalysisTest,globalWithFrameObject)188 TEST_F(SelectionDAGAddressAnalysisTest, globalWithFrameObject) {
189 if (!TM)
190 return;
191 SDLoc Loc;
192 auto Int8VT = EVT::getIntegerVT(Context, 8);
193 // <vscale x 4 x i8>
194 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
195 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
196 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
197 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
198 SDValue Value = DAG->getConstant(0, Loc, VecVT);
199 TypeSize Offset = TypeSize::Fixed(0);
200 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
201 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
202 PtrInfo.getWithOffset(Offset));
203 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown(
204 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize());
205 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(),
206 G->getType());
207 SDValue GValue = DAG->getConstant(0, Loc, GTy);
208 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy);
209 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr,
210 MachinePointerInfo(G, 0));
211 Optional<int64_t> GNumBytes = MemoryLocation::getSizeOrUnknown(
212 cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize());
213
214 bool IsAlias;
215 bool IsValid = BaseIndexOffset::computeAliasing(
216 Store.getNode(), NumBytes, GStore.getNode(), GNumBytes, *DAG, IsAlias);
217
218 EXPECT_TRUE(IsValid);
219 EXPECT_FALSE(IsAlias);
220 }
221
TEST_F(SelectionDAGAddressAnalysisTest,fixedSizeFrameObjectsWithinDiff)222 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsWithinDiff) {
223 if (!TM)
224 return;
225 SDLoc Loc;
226 auto Int8VT = EVT::getIntegerVT(Context, 8);
227 // <vscale x 4 x i8>
228 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
229 // <vscale x 2 x i8>
230 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
231 // <2 x i8>
232 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2);
233 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
234 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
235 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
236 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT2xi8);
237 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
238 TypeSize Offset0 = TypeSize::Fixed(0);
239 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
240 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
241 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
242 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
243 PtrInfo.getWithOffset(Offset0));
244 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
245 PtrInfo.getWithOffset(Offset1));
246 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
247 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
248 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
249 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
250
251 bool IsAlias;
252 bool IsValid = BaseIndexOffset::computeAliasing(
253 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
254 EXPECT_TRUE(IsValid);
255 EXPECT_FALSE(IsAlias);
256
257 IsValid = BaseIndexOffset::computeAliasing(
258 Store1.getNode(), NumBytes1, Store0.getNode(), NumBytes0, *DAG, IsAlias);
259 EXPECT_TRUE(IsValid);
260 EXPECT_FALSE(IsAlias);
261 }
262
TEST_F(SelectionDAGAddressAnalysisTest,fixedSizeFrameObjectsOutOfDiff)263 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsOutOfDiff) {
264 if (!TM)
265 return;
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 // <4 x i8>
275 auto SubFixedVecVT4xi8 = EVT::getVectorVT(Context, Int8VT, 4);
276 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
277 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
278 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
279 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT4xi8);
280 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
281 TypeSize Offset0 = TypeSize::Fixed(0);
282 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
283 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
284 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
285 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
286 PtrInfo.getWithOffset(Offset0));
287 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
288 PtrInfo.getWithOffset(Offset1));
289 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
290 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
291 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
292 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
293
294 bool IsAlias;
295 bool IsValid = BaseIndexOffset::computeAliasing(
296 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
297 EXPECT_TRUE(IsValid);
298 EXPECT_TRUE(IsAlias);
299 }
300
TEST_F(SelectionDAGAddressAnalysisTest,twoFixedStackObjects)301 TEST_F(SelectionDAGAddressAnalysisTest, twoFixedStackObjects) {
302 if (!TM)
303 return;
304 SDLoc Loc;
305 auto Int8VT = EVT::getIntegerVT(Context, 8);
306 // <vscale x 2 x i8>
307 auto VecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
308 // <2 x i8>
309 auto FixedVecVT = EVT::getVectorVT(Context, Int8VT, 2);
310 SDValue FIPtr0 = DAG->CreateStackTemporary(FixedVecVT);
311 SDValue FIPtr1 = DAG->CreateStackTemporary(VecVT);
312 int FI0 = cast<FrameIndexSDNode>(FIPtr0.getNode())->getIndex();
313 int FI1 = cast<FrameIndexSDNode>(FIPtr1.getNode())->getIndex();
314 MachinePointerInfo PtrInfo0 = MachinePointerInfo::getFixedStack(*MF, FI0);
315 MachinePointerInfo PtrInfo1 = MachinePointerInfo::getFixedStack(*MF, FI1);
316 SDValue Value0 = DAG->getConstant(0, Loc, FixedVecVT);
317 SDValue Value1 = DAG->getConstant(0, Loc, VecVT);
318 TypeSize Offset0 = TypeSize::Fixed(0);
319 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr0, Offset0, Loc);
320 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr1, Offset0, Loc);
321 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
322 PtrInfo0.getWithOffset(Offset0));
323 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
324 PtrInfo1.getWithOffset(Offset0));
325 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
326 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
327 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
328 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
329
330 bool IsAlias;
331 bool IsValid = BaseIndexOffset::computeAliasing(
332 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
333 EXPECT_TRUE(IsValid);
334 EXPECT_FALSE(IsAlias);
335 }
336
337 } // end namespace llvm
338