xref: /llvm-project/llvm/unittests/CodeGen/SelectionDAGAddressAnalysisTest.cpp (revision 5bbf1feab5a40337ae8288eb9c9d8d37103c463e)
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
322