207
|
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:
|
|
26 static void SetUpTestCase() {
|
|
27 InitializeAllTargets();
|
|
28 InitializeAllTargetMCs();
|
|
29 }
|
|
30
|
|
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 GTEST_SKIP();
|
|
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 GTEST_SKIP();
|
|
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
|
|
79 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
|
|
80 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
|
|
81 }
|
|
82
|
|
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
|
|
96 TEST_F(SelectionDAGAddressAnalysisTest, sameFrameObject) {
|
|
97 SDLoc Loc;
|
|
98 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
99 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
|
|
100 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
|
|
101 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
102 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
|
|
103 TypeSize Offset = TypeSize::Fixed(0);
|
|
104 SDValue Value = DAG->getConstant(0, Loc, VecVT);
|
|
105 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
|
|
106 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
|
|
107 PtrInfo.getWithOffset(Offset));
|
|
108 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown(
|
|
109 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize());
|
|
110
|
|
111 bool IsAlias;
|
|
112 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
113 Store.getNode(), NumBytes, Store.getNode(), NumBytes, *DAG, IsAlias);
|
|
114
|
|
115 EXPECT_TRUE(IsValid);
|
|
116 EXPECT_TRUE(IsAlias);
|
|
117 }
|
|
118
|
|
119 TEST_F(SelectionDAGAddressAnalysisTest, noAliasingFrameObjects) {
|
|
120 SDLoc Loc;
|
|
121 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
122 // <4 x i8>
|
|
123 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4);
|
|
124 // <2 x i8>
|
|
125 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2);
|
|
126 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
|
|
127 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
128 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
|
|
129 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
|
|
130 TypeSize Offset0 = TypeSize::Fixed(0);
|
|
131 TypeSize Offset1 = SubVecVT.getStoreSize();
|
|
132 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
|
|
133 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
|
|
134 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0,
|
|
135 PtrInfo.getWithOffset(Offset0));
|
|
136 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
|
|
137 PtrInfo.getWithOffset(Offset1));
|
|
138 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
|
|
139 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
|
|
140 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
|
|
141 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
|
|
142
|
|
143 bool IsAlias;
|
|
144 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
145 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
|
|
146
|
|
147 EXPECT_TRUE(IsValid);
|
|
148 EXPECT_FALSE(IsAlias);
|
|
149 }
|
|
150
|
|
151 TEST_F(SelectionDAGAddressAnalysisTest, unknownSizeFrameObjects) {
|
|
152 SDLoc Loc;
|
|
153 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
154 // <vscale x 4 x i8>
|
|
155 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
|
|
156 // <vscale x 2 x i8>
|
|
157 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
|
|
158 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
|
|
159 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
160 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
|
|
161 SDValue Value = DAG->getConstant(0, Loc, SubVecVT);
|
|
162 TypeSize Offset1 = SubVecVT.getStoreSize();
|
|
163 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
|
|
164 SDValue Store0 =
|
|
165 DAG->getStore(DAG->getEntryNode(), Loc, Value, FIPtr, PtrInfo);
|
|
166 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1,
|
|
167 MachinePointerInfo(PtrInfo.getAddrSpace()));
|
|
168 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
|
|
169 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
|
|
170 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
|
|
171 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
|
|
172
|
|
173 bool IsAlias;
|
|
174 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
175 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
|
|
176
|
|
177 EXPECT_FALSE(IsValid);
|
|
178 }
|
|
179
|
|
180 TEST_F(SelectionDAGAddressAnalysisTest, globalWithFrameObject) {
|
|
181 SDLoc Loc;
|
|
182 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
183 // <vscale x 4 x i8>
|
|
184 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, 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, VecVT);
|
|
189 TypeSize Offset = TypeSize::Fixed(0);
|
|
190 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc);
|
|
191 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index,
|
|
192 PtrInfo.getWithOffset(Offset));
|
|
193 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown(
|
|
194 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize());
|
|
195 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(),
|
|
196 G->getType());
|
|
197 SDValue GValue = DAG->getConstant(0, Loc, GTy);
|
|
198 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy);
|
|
199 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr,
|
|
200 MachinePointerInfo(G, 0));
|
|
201 Optional<int64_t> GNumBytes = MemoryLocation::getSizeOrUnknown(
|
|
202 cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize());
|
|
203
|
|
204 bool IsAlias;
|
|
205 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
206 Store.getNode(), NumBytes, GStore.getNode(), GNumBytes, *DAG, IsAlias);
|
|
207
|
|
208 EXPECT_TRUE(IsValid);
|
|
209 EXPECT_FALSE(IsAlias);
|
|
210 }
|
|
211
|
|
212 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsWithinDiff) {
|
|
213 SDLoc Loc;
|
|
214 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
215 // <vscale x 4 x i8>
|
|
216 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
|
|
217 // <vscale x 2 x i8>
|
|
218 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
|
|
219 // <2 x i8>
|
|
220 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2);
|
|
221 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
|
|
222 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
223 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
|
|
224 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT2xi8);
|
|
225 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
|
|
226 TypeSize Offset0 = TypeSize::Fixed(0);
|
|
227 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
|
|
228 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
|
|
229 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
|
|
230 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
|
|
231 PtrInfo.getWithOffset(Offset0));
|
|
232 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
|
|
233 PtrInfo.getWithOffset(Offset1));
|
|
234 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
|
|
235 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
|
|
236 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
|
|
237 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
|
|
238
|
|
239 bool IsAlias;
|
|
240 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
241 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
|
|
242 EXPECT_TRUE(IsValid);
|
|
243 EXPECT_FALSE(IsAlias);
|
|
244
|
|
245 IsValid = BaseIndexOffset::computeAliasing(
|
|
246 Store1.getNode(), NumBytes1, Store0.getNode(), NumBytes0, *DAG, IsAlias);
|
|
247 EXPECT_TRUE(IsValid);
|
|
248 EXPECT_FALSE(IsAlias);
|
|
249 }
|
|
250
|
|
251 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsOutOfDiff) {
|
|
252 SDLoc Loc;
|
|
253 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
254 // <vscale x 4 x i8>
|
|
255 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true);
|
|
256 // <vscale x 2 x i8>
|
|
257 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
|
|
258 // <2 x i8>
|
|
259 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2);
|
|
260 // <4 x i8>
|
|
261 auto SubFixedVecVT4xi8 = EVT::getVectorVT(Context, Int8VT, 4);
|
|
262 SDValue FIPtr = DAG->CreateStackTemporary(VecVT);
|
|
263 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
264 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI);
|
|
265 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT4xi8);
|
|
266 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT);
|
|
267 TypeSize Offset0 = TypeSize::Fixed(0);
|
|
268 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize();
|
|
269 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc);
|
|
270 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc);
|
|
271 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
|
|
272 PtrInfo.getWithOffset(Offset0));
|
|
273 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
|
|
274 PtrInfo.getWithOffset(Offset1));
|
|
275 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
|
|
276 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
|
|
277 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
|
|
278 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
|
|
279
|
|
280 bool IsAlias;
|
|
281 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
282 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
|
|
283 EXPECT_TRUE(IsValid);
|
|
284 EXPECT_TRUE(IsAlias);
|
|
285 }
|
|
286
|
|
287 TEST_F(SelectionDAGAddressAnalysisTest, twoFixedStackObjects) {
|
|
288 SDLoc Loc;
|
|
289 auto Int8VT = EVT::getIntegerVT(Context, 8);
|
|
290 // <vscale x 2 x i8>
|
|
291 auto VecVT = EVT::getVectorVT(Context, Int8VT, 2, true);
|
|
292 // <2 x i8>
|
|
293 auto FixedVecVT = EVT::getVectorVT(Context, Int8VT, 2);
|
|
294 SDValue FIPtr0 = DAG->CreateStackTemporary(FixedVecVT);
|
|
295 SDValue FIPtr1 = DAG->CreateStackTemporary(VecVT);
|
|
296 int FI0 = cast<FrameIndexSDNode>(FIPtr0.getNode())->getIndex();
|
|
297 int FI1 = cast<FrameIndexSDNode>(FIPtr1.getNode())->getIndex();
|
|
298 MachinePointerInfo PtrInfo0 = MachinePointerInfo::getFixedStack(*MF, FI0);
|
|
299 MachinePointerInfo PtrInfo1 = MachinePointerInfo::getFixedStack(*MF, FI1);
|
|
300 SDValue Value0 = DAG->getConstant(0, Loc, FixedVecVT);
|
|
301 SDValue Value1 = DAG->getConstant(0, Loc, VecVT);
|
|
302 TypeSize Offset0 = TypeSize::Fixed(0);
|
|
303 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr0, Offset0, Loc);
|
|
304 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr1, Offset0, Loc);
|
|
305 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0,
|
|
306 PtrInfo0.getWithOffset(Offset0));
|
|
307 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1,
|
|
308 PtrInfo1.getWithOffset(Offset0));
|
|
309 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown(
|
|
310 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize());
|
|
311 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown(
|
|
312 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize());
|
|
313
|
|
314 bool IsAlias;
|
|
315 bool IsValid = BaseIndexOffset::computeAliasing(
|
|
316 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias);
|
|
317 EXPECT_TRUE(IsValid);
|
|
318 EXPECT_FALSE(IsAlias);
|
|
319 }
|
|
320
|
|
321 } // end namespace llvm
|