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