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