xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/GISelAliasTest.cpp (revision 7fc871591f1399cd88ff301ed84fa67dc3bf7a6b)
1dc84770dSAmara Emerson //===- GISelAliasTest.cpp--------------------------------------------------===//
2dc84770dSAmara Emerson //
3dc84770dSAmara Emerson // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dc84770dSAmara Emerson // See https://llvm.org/LICENSE.txt for license information.
5dc84770dSAmara Emerson // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dc84770dSAmara Emerson //
7dc84770dSAmara Emerson //===----------------------------------------------------------------------===//
8dc84770dSAmara Emerson 
9dc84770dSAmara Emerson #include "GISelMITest.h"
10dc84770dSAmara Emerson #include "llvm/CodeGen/GlobalISel/LoadStoreOpt.h"
11989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFrameInfo.h"
12dc84770dSAmara Emerson #include "llvm/CodeGen/MachineMemOperand.h"
13dc84770dSAmara Emerson #include "llvm/IR/LLVMContext.h"
14dc84770dSAmara Emerson #include "llvm/IR/Metadata.h"
15dc84770dSAmara Emerson #include "llvm/Support/AtomicOrdering.h"
16dc84770dSAmara Emerson #include "gtest/gtest.h"
17dc84770dSAmara Emerson 
18dc84770dSAmara Emerson namespace {
19dc84770dSAmara Emerson 
20dc84770dSAmara Emerson // Test simple aliasing.
TEST_F(AArch64GISelMITest,SimpleAlias)21dc84770dSAmara Emerson TEST_F(AArch64GISelMITest, SimpleAlias) {
22dc84770dSAmara Emerson   setUp();
23dc84770dSAmara Emerson   if (!TM)
24*7fc87159SPaul Robinson     GTEST_SKIP();
25dc84770dSAmara Emerson 
26dc84770dSAmara Emerson   LLT S64 = LLT::scalar(64);
27dc84770dSAmara Emerson   LLT P0 = LLT::pointer(0, 64);
28dc84770dSAmara Emerson 
29dc84770dSAmara Emerson   auto Base = B.buildIntToPtr(P0, Copies[0]);
30dc84770dSAmara Emerson   auto Base2 = B.buildIntToPtr(P0, Copies[1]);
31dc84770dSAmara Emerson   // These two addresses are identical.
32dc84770dSAmara Emerson   auto Addr = B.buildPtrAdd(P0, Base, B.buildConstant(S64, 8));
33dc84770dSAmara Emerson   auto Addr2 = B.buildPtrAdd(P0, Base, B.buildConstant(S64, 8));
34dc84770dSAmara Emerson 
35dc84770dSAmara Emerson   MachinePointerInfo PtrInfo;
36dc84770dSAmara Emerson   auto *LoadMMO = MF->getMachineMemOperand(
37dc84770dSAmara Emerson       PtrInfo, MachineMemOperand::Flags::MOLoad, S64, Align());
38dc84770dSAmara Emerson   auto Ld1 = B.buildLoad(S64, Addr, *LoadMMO);
39dc84770dSAmara Emerson   auto Ld2 = B.buildLoad(S64, Addr2, *LoadMMO);
40dc84770dSAmara Emerson 
41dc84770dSAmara Emerson   // We expect the same address to return alias.
42dc84770dSAmara Emerson   EXPECT_TRUE(GISelAddressing::instMayAlias(*Ld1, *Ld2, *MRI, nullptr));
43dc84770dSAmara Emerson 
44dc84770dSAmara Emerson   // Expect both being volatile to say alias, since we can't reorder them.
45dc84770dSAmara Emerson   auto *LoadVolMMO = MF->getMachineMemOperand(
46dc84770dSAmara Emerson       LoadMMO,
47dc84770dSAmara Emerson       MachineMemOperand::Flags::MOLoad | MachineMemOperand::Flags::MOVolatile);
48dc84770dSAmara Emerson   // Pick a different address so we don't trivially match the alias case above.
49dc84770dSAmara Emerson   auto VolLd1 = B.buildLoad(S64, Addr, *LoadVolMMO);
50dc84770dSAmara Emerson   auto VolLd2 = B.buildLoad(S64, Base2, *LoadVolMMO);
51dc84770dSAmara Emerson   EXPECT_TRUE(GISelAddressing::instMayAlias(*VolLd1, *VolLd2, *MRI, nullptr));
52dc84770dSAmara Emerson 
53dc84770dSAmara Emerson   // Same for atomics.
54dc84770dSAmara Emerson   auto *LoadAtomicMMO = MF->getMachineMemOperand(
55dc84770dSAmara Emerson       PtrInfo, MachineMemOperand::Flags::MOLoad, S64, Align(8), AAMDNodes(),
56dc84770dSAmara Emerson       nullptr, SyncScope::System, AtomicOrdering::Acquire);
57dc84770dSAmara Emerson   auto AtomicLd1 = B.buildLoad(S64, Addr, *LoadAtomicMMO);
58dc84770dSAmara Emerson   auto AtomicLd2 = B.buildLoad(S64, Base2, *LoadAtomicMMO);
59dc84770dSAmara Emerson   EXPECT_TRUE(
60dc84770dSAmara Emerson       GISelAddressing::instMayAlias(*AtomicLd1, *AtomicLd2, *MRI, nullptr));
61dc84770dSAmara Emerson 
62dc84770dSAmara Emerson   // Invariant memory with stores.
63dc84770dSAmara Emerson   auto *LoadInvariantMMO = MF->getMachineMemOperand(
64dc84770dSAmara Emerson       LoadMMO,
65dc84770dSAmara Emerson       MachineMemOperand::Flags::MOLoad | MachineMemOperand::Flags::MOInvariant);
66dc84770dSAmara Emerson   auto InvariantLd = B.buildLoad(S64, Addr, *LoadInvariantMMO);
67dc84770dSAmara Emerson   auto Store = B.buildStore(B.buildConstant(S64, 0), Base2, PtrInfo, Align());
68dc84770dSAmara Emerson   EXPECT_FALSE(
69dc84770dSAmara Emerson       GISelAddressing::instMayAlias(*InvariantLd, *Store, *MRI, nullptr));
70dc84770dSAmara Emerson }
71dc84770dSAmara Emerson 
72dc84770dSAmara Emerson // Test aliasing checks for same base + different offsets.
TEST_F(AArch64GISelMITest,OffsetAliasing)73dc84770dSAmara Emerson TEST_F(AArch64GISelMITest, OffsetAliasing) {
74dc84770dSAmara Emerson   setUp();
75dc84770dSAmara Emerson   if (!TM)
76*7fc87159SPaul Robinson     GTEST_SKIP();
77dc84770dSAmara Emerson 
78dc84770dSAmara Emerson   LLT S64 = LLT::scalar(64);
79dc84770dSAmara Emerson   LLT P0 = LLT::pointer(0, 64);
80dc84770dSAmara Emerson 
81dc84770dSAmara Emerson   auto Base = B.buildIntToPtr(P0, Copies[0]);
82dc84770dSAmara Emerson   auto Addr = B.buildPtrAdd(P0, Base, B.buildConstant(S64, 8));
83dc84770dSAmara Emerson   auto Addr2 = B.buildPtrAdd(P0, Base, B.buildConstant(S64, 16));
84dc84770dSAmara Emerson 
85dc84770dSAmara Emerson   MachinePointerInfo PtrInfo;
86dc84770dSAmara Emerson   auto *LoadMMO = MF->getMachineMemOperand(
87dc84770dSAmara Emerson       PtrInfo, MachineMemOperand::Flags::MOLoad, S64, Align());
88dc84770dSAmara Emerson   auto Ld1 = B.buildLoad(S64, Addr, *LoadMMO);
89dc84770dSAmara Emerson   auto Ld2 = B.buildLoad(S64, Addr2, *LoadMMO);
90dc84770dSAmara Emerson 
91dc84770dSAmara Emerson   // The offset between the two addresses is >= than the size of access.
92dc84770dSAmara Emerson   // Can't alias.
93dc84770dSAmara Emerson   EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld1, *Ld2, *MRI, nullptr));
94dc84770dSAmara Emerson   EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld2, *Ld1, *MRI, nullptr));
95dc84770dSAmara Emerson 
96dc84770dSAmara Emerson   auto Addr3 = B.buildPtrAdd(P0, Base, B.buildConstant(S64, 4));
97dc84770dSAmara Emerson   auto Ld3 = B.buildLoad(S64, Addr3, *LoadMMO);
98dc84770dSAmara Emerson   // Offset of 4 is < the size of access, 8 bytes.
99dc84770dSAmara Emerson   EXPECT_TRUE(GISelAddressing::instMayAlias(*Ld1, *Ld3, *MRI, nullptr));
100dc84770dSAmara Emerson }
101dc84770dSAmara Emerson 
102dc84770dSAmara Emerson // Test aliasing checks for frame indexes.
TEST_F(AArch64GISelMITest,FrameIndexAliasing)103dc84770dSAmara Emerson TEST_F(AArch64GISelMITest, FrameIndexAliasing) {
104dc84770dSAmara Emerson   setUp();
105dc84770dSAmara Emerson   if (!TM)
106*7fc87159SPaul Robinson     GTEST_SKIP();
107dc84770dSAmara Emerson 
108dc84770dSAmara Emerson   LLT S64 = LLT::scalar(64);
109dc84770dSAmara Emerson   LLT P0 = LLT::pointer(0, 64);
110dc84770dSAmara Emerson 
111dc84770dSAmara Emerson   auto &MFI = MF->getFrameInfo();
112dc84770dSAmara Emerson   auto FixedFI1 = MFI.CreateFixedObject(8, 0, true);
113dc84770dSAmara Emerson   auto FixedFI2 = MFI.CreateFixedObject(8, 8, true);
114dc84770dSAmara Emerson 
115dc84770dSAmara Emerson   auto FI1 = MFI.CreateStackObject(8, Align(8), false);
116dc84770dSAmara Emerson   auto GFI1 = B.buildFrameIndex(P0, FI1);
117dc84770dSAmara Emerson   // This G_FRAME_INDEX is separate but refers to the same index.
118dc84770dSAmara Emerson   auto GFI2 = B.buildFrameIndex(P0, FI1);
119dc84770dSAmara Emerson 
120dc84770dSAmara Emerson   MachinePointerInfo PtrInfo;
121dc84770dSAmara Emerson   auto *LoadMMO = MF->getMachineMemOperand(
122dc84770dSAmara Emerson       PtrInfo, MachineMemOperand::Flags::MOLoad, S64, Align());
123dc84770dSAmara Emerson   auto Ld1 = B.buildLoad(S64, GFI1, *LoadMMO);
124dc84770dSAmara Emerson   auto Ld2 = B.buildLoad(S64, GFI2, *LoadMMO);
125dc84770dSAmara Emerson 
126dc84770dSAmara Emerson   // The offset between the two addresses is >= than the size of access.
127dc84770dSAmara Emerson   // Can't alias.
128dc84770dSAmara Emerson   EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld1, *Ld2, *MRI, nullptr));
129dc84770dSAmara Emerson 
130dc84770dSAmara Emerson 
131dc84770dSAmara Emerson   auto GFixedFI1 = B.buildFrameIndex(P0, FixedFI1);
132dc84770dSAmara Emerson   auto GFixedFI2 = B.buildFrameIndex(P0, FixedFI2);
133dc84770dSAmara Emerson   auto FixedFILd1 = B.buildLoad(S64, GFixedFI1, *LoadMMO);
134dc84770dSAmara Emerson   auto FixedFILd2 = B.buildLoad(S64, GFixedFI2, *LoadMMO);
135dc84770dSAmara Emerson   // If we have two different FrameIndex bases, but at least one is not a fixed
136dc84770dSAmara Emerson   // object, then we can say they don't alias. If both were fixed, then we could
137dc84770dSAmara Emerson   // have multiple frameindex slots being accessed at once since their relative
138dc84770dSAmara Emerson   // positions are known. However, if one is not fixed, then they can't alias
139dc84770dSAmara Emerson   // because non-fixed FIs are only given offsets during PEI.
140dc84770dSAmara Emerson   EXPECT_FALSE(GISelAddressing::instMayAlias(*FixedFILd1, *Ld1, *MRI, nullptr));
141dc84770dSAmara Emerson   EXPECT_TRUE(
142dc84770dSAmara Emerson       GISelAddressing::instMayAlias(*FixedFILd1, *FixedFILd2, *MRI, nullptr));
143dc84770dSAmara Emerson }
144dc84770dSAmara Emerson 
145dc84770dSAmara Emerson } // namespace
146