• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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