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