1 //===- llvm/unittest/CodeGen/SelectionDAGAddressAnalysisTest.cpp ---------===//
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
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"
25 class SelectionDAGAddressAnalysisTest
: public testing::Test
{
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"
36 " %1 = load i32, i32* @g\n"
40 Triple
TargetTriple("aarch64--");
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.
49 TargetOptions Options
;
50 TM
= std::unique_ptr
<TargetMachine
>(
51 T
->createTargetMachine("AArch64", "", "+sve", Options
, std::nullopt
,
52 std::nullopt
, CodeGenOptLevel::Aggressive
));
57 M
= parseAssemblyString(Assembly
, SMError
, Context
);
59 report_fatal_error(SMError
.getMessage());
60 M
->setDataLayout(TM
->createDataLayout());
62 F
= M
->getFunction("f");
64 report_fatal_error("F?");
65 G
= M
->getGlobalVariable("g");
67 report_fatal_error("G?");
68 AliasedG
= M
->getNamedAlias("g_alias");
70 report_fatal_error("AliasedG?");
72 MachineModuleInfo
MMI(TM
.get());
74 MF
= std::make_unique
<MachineFunction
>(*F
, *TM
, *TM
->getSubtargetImpl(*F
),
77 DAG
= std::make_unique
<SelectionDAG
>(*TM
, CodeGenOptLevel::None
);
79 report_fatal_error("DAG?");
80 OptimizationRemarkEmitter
ORE(F
);
81 DAG
->init(*MF
, ORE
, nullptr, nullptr, nullptr, nullptr, nullptr, MMI
,
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
);
94 std::unique_ptr
<TargetMachine
> TM
;
95 std::unique_ptr
<Module
> M
;
98 GlobalAlias
*AliasedG
;
99 std::unique_ptr
<MachineFunction
> MF
;
100 std::unique_ptr
<SelectionDAG
> DAG
;
103 TEST_F(SelectionDAGAddressAnalysisTest
, sameFrameObject
) {
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();
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
) {
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
));
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
) {
149 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
151 auto VecVT
= EVT::getVectorVT(Context
, Int8VT
, 4);
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();
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
) {
180 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
182 auto VecVT
= EVT::getVectorVT(Context
, Int8VT
, 4, true);
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
);
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();
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
) {
208 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
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(),
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();
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
) {
240 EVT GTy
= DAG
->getTargetLoweringInfo().getValueType(DAG
->getDataLayout(),
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));
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
) {
267 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
269 auto VecVT
= EVT::getVectorVT(Context
, Int8VT
, 4, true);
271 auto SubVecVT
= EVT::getVectorVT(Context
, Int8VT
, 2, true);
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();
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
) {
306 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
308 auto VecVT
= EVT::getVectorVT(Context
, Int8VT
, 4, true);
310 auto SubVecVT
= EVT::getVectorVT(Context
, Int8VT
, 2, true);
312 auto SubFixedVecVT2xi8
= EVT::getVectorVT(Context
, Int8VT
, 2);
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();
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
) {
341 auto Int8VT
= EVT::getIntegerVT(Context
, 8);
343 auto VecVT
= EVT::getVectorVT(Context
, Int8VT
, 2, true);
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();
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