146 lines · cpp
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-exception6//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 18namespace {19 20// Test simple aliasing.21TEST_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.73TEST_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.103TEST_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 fixed136 // object, then we can say they don't alias. If both were fixed, then we could137 // have multiple frameindex slots being accessed at once since their relative138 // positions are known. However, if one is not fixed, then they can't alias139 // 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} // namespace146