1 //===- llvm/unittest/CodeGen/SelectionDAGAddressAnalysisTest.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 "llvm/CodeGen/SelectionDAGAddressAnalysis.h" 10 #include "llvm/Analysis/MemoryLocation.h" 11 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 12 #include "llvm/AsmParser/Parser.h" 13 #include "llvm/CodeGen/MachineModuleInfo.h" 14 #include "llvm/CodeGen/SelectionDAG.h" 15 #include "llvm/CodeGen/TargetLowering.h" 16 #include "llvm/Support/SourceMgr.h" 17 #include "llvm/Support/TargetRegistry.h" 18 #include "llvm/Support/TargetSelect.h" 19 #include "llvm/Target/TargetMachine.h" 20 #include "gtest/gtest.h" 21 22 namespace llvm { 23 24 class SelectionDAGAddressAnalysisTest : public testing::Test { 25 protected: 26 static void SetUpTestCase() { 27 InitializeAllTargets(); 28 InitializeAllTargetMCs(); 29 } 30 31 void SetUp() override { 32 StringRef Assembly = "@g = global i32 0\n" 33 "define i32 @f() {\n" 34 " %1 = load i32, i32* @g\n" 35 " ret i32 %1\n" 36 "}"; 37 38 Triple TargetTriple("aarch64--"); 39 std::string Error; 40 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); 41 // FIXME: These tests do not depend on AArch64 specifically, but we have to 42 // initialize a target. A skeleton Target for unittests would allow us to 43 // always run these tests. 44 if (!T) 45 GTEST_SKIP(); 46 47 TargetOptions Options; 48 TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>( 49 T->createTargetMachine("AArch64", "", "+sve", Options, None, None, 50 CodeGenOpt::Aggressive))); 51 if (!TM) 52 GTEST_SKIP(); 53 54 SMDiagnostic SMError; 55 M = parseAssemblyString(Assembly, SMError, Context); 56 if (!M) 57 report_fatal_error(SMError.getMessage()); 58 M->setDataLayout(TM->createDataLayout()); 59 60 F = M->getFunction("f"); 61 if (!F) 62 report_fatal_error("F?"); 63 G = M->getGlobalVariable("g"); 64 if (!G) 65 report_fatal_error("G?"); 66 67 MachineModuleInfo MMI(TM.get()); 68 69 MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F), 70 0, MMI); 71 72 DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOpt::None); 73 if (!DAG) 74 report_fatal_error("DAG?"); 75 OptimizationRemarkEmitter ORE(F); 76 DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr); 77 } 78 79 TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) { 80 return DAG->getTargetLoweringInfo().getTypeAction(Context, VT); 81 } 82 83 EVT getTypeToTransformTo(EVT VT) { 84 return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT); 85 } 86 87 LLVMContext Context; 88 std::unique_ptr<LLVMTargetMachine> TM; 89 std::unique_ptr<Module> M; 90 Function *F; 91 GlobalVariable *G; 92 std::unique_ptr<MachineFunction> MF; 93 std::unique_ptr<SelectionDAG> DAG; 94 }; 95 96 TEST_F(SelectionDAGAddressAnalysisTest, sameFrameObject) { 97 SDLoc Loc; 98 auto Int8VT = EVT::getIntegerVT(Context, 8); 99 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4); 100 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 101 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 102 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 103 TypeSize Offset = TypeSize::Fixed(0); 104 SDValue Value = DAG->getConstant(0, Loc, VecVT); 105 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc); 106 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index, 107 PtrInfo.getWithOffset(Offset)); 108 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown( 109 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize()); 110 111 bool IsAlias; 112 bool IsValid = BaseIndexOffset::computeAliasing( 113 Store.getNode(), NumBytes, Store.getNode(), NumBytes, *DAG, IsAlias); 114 115 EXPECT_TRUE(IsValid); 116 EXPECT_TRUE(IsAlias); 117 } 118 119 TEST_F(SelectionDAGAddressAnalysisTest, noAliasingFrameObjects) { 120 SDLoc Loc; 121 auto Int8VT = EVT::getIntegerVT(Context, 8); 122 // <4 x i8> 123 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4); 124 // <2 x i8> 125 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2); 126 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 127 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 128 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 129 SDValue Value = DAG->getConstant(0, Loc, SubVecVT); 130 TypeSize Offset0 = TypeSize::Fixed(0); 131 TypeSize Offset1 = SubVecVT.getStoreSize(); 132 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 133 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 134 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0, 135 PtrInfo.getWithOffset(Offset0)); 136 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1, 137 PtrInfo.getWithOffset(Offset1)); 138 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 139 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 140 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 141 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 142 143 bool IsAlias; 144 bool IsValid = BaseIndexOffset::computeAliasing( 145 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 146 147 EXPECT_TRUE(IsValid); 148 EXPECT_FALSE(IsAlias); 149 } 150 151 TEST_F(SelectionDAGAddressAnalysisTest, unknownSizeFrameObjects) { 152 SDLoc Loc; 153 auto Int8VT = EVT::getIntegerVT(Context, 8); 154 // <vscale x 4 x i8> 155 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 156 // <vscale x 2 x i8> 157 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 158 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 159 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 160 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 161 SDValue Value = DAG->getConstant(0, Loc, SubVecVT); 162 TypeSize Offset1 = SubVecVT.getStoreSize(); 163 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 164 SDValue Store0 = 165 DAG->getStore(DAG->getEntryNode(), Loc, Value, FIPtr, PtrInfo); 166 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1, 167 MachinePointerInfo(PtrInfo.getAddrSpace())); 168 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 169 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 170 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 171 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 172 173 bool IsAlias; 174 bool IsValid = BaseIndexOffset::computeAliasing( 175 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 176 177 EXPECT_FALSE(IsValid); 178 } 179 180 TEST_F(SelectionDAGAddressAnalysisTest, globalWithFrameObject) { 181 SDLoc Loc; 182 auto Int8VT = EVT::getIntegerVT(Context, 8); 183 // <vscale x 4 x i8> 184 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 185 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 186 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 187 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 188 SDValue Value = DAG->getConstant(0, Loc, VecVT); 189 TypeSize Offset = TypeSize::Fixed(0); 190 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc); 191 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index, 192 PtrInfo.getWithOffset(Offset)); 193 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown( 194 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize()); 195 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(), 196 G->getType()); 197 SDValue GValue = DAG->getConstant(0, Loc, GTy); 198 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy); 199 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr, 200 MachinePointerInfo(G, 0)); 201 Optional<int64_t> GNumBytes = MemoryLocation::getSizeOrUnknown( 202 cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize()); 203 204 bool IsAlias; 205 bool IsValid = BaseIndexOffset::computeAliasing( 206 Store.getNode(), NumBytes, GStore.getNode(), GNumBytes, *DAG, IsAlias); 207 208 EXPECT_TRUE(IsValid); 209 EXPECT_FALSE(IsAlias); 210 } 211 212 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsWithinDiff) { 213 SDLoc Loc; 214 auto Int8VT = EVT::getIntegerVT(Context, 8); 215 // <vscale x 4 x i8> 216 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 217 // <vscale x 2 x i8> 218 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 219 // <2 x i8> 220 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2); 221 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 222 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 223 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 224 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT2xi8); 225 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT); 226 TypeSize Offset0 = TypeSize::Fixed(0); 227 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize(); 228 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 229 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 230 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 231 PtrInfo.getWithOffset(Offset0)); 232 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 233 PtrInfo.getWithOffset(Offset1)); 234 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 235 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 236 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 237 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 238 239 bool IsAlias; 240 bool IsValid = BaseIndexOffset::computeAliasing( 241 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 242 EXPECT_TRUE(IsValid); 243 EXPECT_FALSE(IsAlias); 244 245 IsValid = BaseIndexOffset::computeAliasing( 246 Store1.getNode(), NumBytes1, Store0.getNode(), NumBytes0, *DAG, IsAlias); 247 EXPECT_TRUE(IsValid); 248 EXPECT_FALSE(IsAlias); 249 } 250 251 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsOutOfDiff) { 252 SDLoc Loc; 253 auto Int8VT = EVT::getIntegerVT(Context, 8); 254 // <vscale x 4 x i8> 255 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 256 // <vscale x 2 x i8> 257 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 258 // <2 x i8> 259 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2); 260 // <4 x i8> 261 auto SubFixedVecVT4xi8 = EVT::getVectorVT(Context, Int8VT, 4); 262 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 263 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 264 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 265 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT4xi8); 266 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT); 267 TypeSize Offset0 = TypeSize::Fixed(0); 268 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize(); 269 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 270 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 271 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 272 PtrInfo.getWithOffset(Offset0)); 273 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 274 PtrInfo.getWithOffset(Offset1)); 275 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 276 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 277 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 278 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 279 280 bool IsAlias; 281 bool IsValid = BaseIndexOffset::computeAliasing( 282 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 283 EXPECT_TRUE(IsValid); 284 EXPECT_TRUE(IsAlias); 285 } 286 287 TEST_F(SelectionDAGAddressAnalysisTest, twoFixedStackObjects) { 288 SDLoc Loc; 289 auto Int8VT = EVT::getIntegerVT(Context, 8); 290 // <vscale x 2 x i8> 291 auto VecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 292 // <2 x i8> 293 auto FixedVecVT = EVT::getVectorVT(Context, Int8VT, 2); 294 SDValue FIPtr0 = DAG->CreateStackTemporary(FixedVecVT); 295 SDValue FIPtr1 = DAG->CreateStackTemporary(VecVT); 296 int FI0 = cast<FrameIndexSDNode>(FIPtr0.getNode())->getIndex(); 297 int FI1 = cast<FrameIndexSDNode>(FIPtr1.getNode())->getIndex(); 298 MachinePointerInfo PtrInfo0 = MachinePointerInfo::getFixedStack(*MF, FI0); 299 MachinePointerInfo PtrInfo1 = MachinePointerInfo::getFixedStack(*MF, FI1); 300 SDValue Value0 = DAG->getConstant(0, Loc, FixedVecVT); 301 SDValue Value1 = DAG->getConstant(0, Loc, VecVT); 302 TypeSize Offset0 = TypeSize::Fixed(0); 303 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr0, Offset0, Loc); 304 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr1, Offset0, Loc); 305 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 306 PtrInfo0.getWithOffset(Offset0)); 307 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 308 PtrInfo1.getWithOffset(Offset0)); 309 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 310 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 311 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 312 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 313 314 bool IsAlias; 315 bool IsValid = BaseIndexOffset::computeAliasing( 316 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 317 EXPECT_TRUE(IsValid); 318 EXPECT_FALSE(IsAlias); 319 } 320 321 } // end namespace llvm 322