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