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