Skip to content

Commit 8d06a67

Browse files
committed
[SelectionDAG] Avoid aliasing analysis if the object size is unknown.
If the size of memory access is unknown, do not use it to analysis. One example of unknown size memory access is to load/store scalable vector objects on the stack. Differential Revision: https://reviews.llvm.org/D91833
1 parent 77e98ea commit 8d06a67

File tree

3 files changed

+359
-10
lines changed

3 files changed

+359
-10
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
10+
#include "llvm/Analysis/MemoryLocation.h"
1011
#include "llvm/CodeGen/ISDOpcodes.h"
1112
#include "llvm/CodeGen/MachineFrameInfo.h"
1213
#include "llvm/CodeGen/MachineFunction.h"
@@ -96,18 +97,28 @@ bool BaseIndexOffset::computeAliasing(const SDNode *Op0,
9697
int64_t PtrDiff;
9798
if (NumBytes0.hasValue() && NumBytes1.hasValue() &&
9899
BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) {
100+
// If the size of memory access is unknown, do not use it to analysis.
101+
// One example of unknown size memory access is to load/store scalable
102+
// vector objects on the stack.
99103
// BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the
100104
// following situations arise:
101-
IsAlias = !(
102-
// [----BasePtr0----]
103-
// [---BasePtr1--]
104-
// ========PtrDiff========>
105-
(*NumBytes0 <= PtrDiff) ||
106-
// [----BasePtr0----]
107-
// [---BasePtr1--]
108-
// =====(-PtrDiff)====>
109-
(PtrDiff + *NumBytes1 <= 0)); // i.e. *NumBytes1 < -PtrDiff.
110-
return true;
105+
if (PtrDiff >= 0 &&
106+
*NumBytes0 != static_cast<int64_t>(MemoryLocation::UnknownSize)) {
107+
// [----BasePtr0----]
108+
// [---BasePtr1--]
109+
// ========PtrDiff========>
110+
IsAlias = !(*NumBytes0 <= PtrDiff);
111+
return true;
112+
}
113+
if (PtrDiff < 0 &&
114+
*NumBytes1 != static_cast<int64_t>(MemoryLocation::UnknownSize)) {
115+
// [----BasePtr0----]
116+
// [---BasePtr1--]
117+
// =====(-PtrDiff)====>
118+
IsAlias = !((PtrDiff + *NumBytes1) <= 0);
119+
return true;
120+
}
121+
return false;
111122
}
112123
// If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be
113124
// able to calculate their relative offset if at least one arises

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_llvm_unittest(CodeGenTests
2626
MachineOperandTest.cpp
2727
PassManagerTest.cpp
2828
ScalableVectorMVTsTest.cpp
29+
SelectionDAGAddressAnalysisTest.cpp
2930
TypeTraitsTest.cpp
3031
TargetOptionsTest.cpp
3132
TestAsmPrinter.cpp
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
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+
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+
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+
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+
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+
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+
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+
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+
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+
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

0 commit comments

Comments
 (0)