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. 21 TEST_F(AArch64GISelMITest, SimpleAlias) { 22 setUp(); 23 if (!TM) 24 return; 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. 73 TEST_F(AArch64GISelMITest, OffsetAliasing) { 74 setUp(); 75 if (!TM) 76 return; 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. 103 TEST_F(AArch64GISelMITest, FrameIndexAliasing) { 104 setUp(); 105 if (!TM) 106 return; 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