1 //===- GISelAliasTest.cpp--------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
20 // Test simple aliasing.
21 TEST_F(AArch64GISelMITest
, SimpleAlias
) {
26 LLT S64
= LLT::scalar(64);
27 LLT P0
= LLT::pointer(0, 64);
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));
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
);
41 // We expect the same address to return alias.
42 EXPECT_TRUE(GISelAddressing::instMayAlias(*Ld1
, *Ld2
, *MRI
, nullptr));
44 // Expect both being volatile to say alias, since we can't reorder them.
45 auto *LoadVolMMO
= MF
->getMachineMemOperand(
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));
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
);
60 GISelAddressing::instMayAlias(*AtomicLd1
, *AtomicLd2
, *MRI
, nullptr));
62 // Invariant memory with stores.
63 auto *LoadInvariantMMO
= MF
->getMachineMemOperand(
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());
69 GISelAddressing::instMayAlias(*InvariantLd
, *Store
, *MRI
, nullptr));
72 // Test aliasing checks for same base + different offsets.
73 TEST_F(AArch64GISelMITest
, OffsetAliasing
) {
78 LLT S64
= LLT::scalar(64);
79 LLT P0
= LLT::pointer(0, 64);
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));
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
);
91 // The offset between the two addresses is >= than the size of access.
93 EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld1
, *Ld2
, *MRI
, nullptr));
94 EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld2
, *Ld1
, *MRI
, nullptr));
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));
102 // Test aliasing checks for frame indexes.
103 TEST_F(AArch64GISelMITest
, FrameIndexAliasing
) {
108 LLT S64
= LLT::scalar(64);
109 LLT P0
= LLT::pointer(0, 64);
111 auto &MFI
= MF
->getFrameInfo();
112 auto FixedFI1
= MFI
.CreateFixedObject(8, 0, true);
113 auto FixedFI2
= MFI
.CreateFixedObject(8, 8, true);
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
);
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
);
126 // The offset between the two addresses is >= than the size of access.
128 EXPECT_FALSE(GISelAddressing::instMayAlias(*Ld1
, *Ld2
, *MRI
, nullptr));
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));
142 GISelAddressing::instMayAlias(*FixedFILd1
, *FixedFILd2
, *MRI
, nullptr));