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 return; 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 return; 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 if (!TM) 98 return; 99 SDLoc Loc; 100 auto Int8VT = EVT::getIntegerVT(Context, 8); 101 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4); 102 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 103 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 104 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 105 TypeSize Offset = TypeSize::Fixed(0); 106 SDValue Value = DAG->getConstant(0, Loc, VecVT); 107 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc); 108 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index, 109 PtrInfo.getWithOffset(Offset)); 110 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown( 111 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize()); 112 113 bool IsAlias; 114 bool IsValid = BaseIndexOffset::computeAliasing( 115 Store.getNode(), NumBytes, Store.getNode(), NumBytes, *DAG, IsAlias); 116 117 EXPECT_TRUE(IsValid); 118 EXPECT_TRUE(IsAlias); 119 } 120 121 TEST_F(SelectionDAGAddressAnalysisTest, noAliasingFrameObjects) { 122 if (!TM) 123 return; 124 SDLoc Loc; 125 auto Int8VT = EVT::getIntegerVT(Context, 8); 126 // <4 x i8> 127 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4); 128 // <2 x i8> 129 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2); 130 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 131 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 132 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 133 SDValue Value = DAG->getConstant(0, Loc, SubVecVT); 134 TypeSize Offset0 = TypeSize::Fixed(0); 135 TypeSize Offset1 = SubVecVT.getStoreSize(); 136 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 137 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 138 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0, 139 PtrInfo.getWithOffset(Offset0)); 140 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1, 141 PtrInfo.getWithOffset(Offset1)); 142 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 143 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 144 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 145 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 146 147 bool IsAlias; 148 bool IsValid = BaseIndexOffset::computeAliasing( 149 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 150 151 EXPECT_TRUE(IsValid); 152 EXPECT_FALSE(IsAlias); 153 } 154 155 TEST_F(SelectionDAGAddressAnalysisTest, unknownSizeFrameObjects) { 156 if (!TM) 157 return; 158 SDLoc Loc; 159 auto Int8VT = EVT::getIntegerVT(Context, 8); 160 // <vscale x 4 x i8> 161 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 162 // <vscale x 2 x i8> 163 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 164 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 165 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 166 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 167 SDValue Value = DAG->getConstant(0, Loc, SubVecVT); 168 TypeSize Offset0 = TypeSize::Fixed(0); 169 TypeSize Offset1 = SubVecVT.getStoreSize(); 170 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 171 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 172 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index0, 173 PtrInfo.getWithOffset(Offset0)); 174 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index1, 175 PtrInfo.getWithOffset(Offset1)); 176 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 177 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 178 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 179 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 180 181 bool IsAlias; 182 bool IsValid = BaseIndexOffset::computeAliasing( 183 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 184 185 EXPECT_FALSE(IsValid); 186 } 187 188 TEST_F(SelectionDAGAddressAnalysisTest, globalWithFrameObject) { 189 if (!TM) 190 return; 191 SDLoc Loc; 192 auto Int8VT = EVT::getIntegerVT(Context, 8); 193 // <vscale x 4 x i8> 194 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 195 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 196 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 197 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 198 SDValue Value = DAG->getConstant(0, Loc, VecVT); 199 TypeSize Offset = TypeSize::Fixed(0); 200 SDValue Index = DAG->getMemBasePlusOffset(FIPtr, Offset, Loc); 201 SDValue Store = DAG->getStore(DAG->getEntryNode(), Loc, Value, Index, 202 PtrInfo.getWithOffset(Offset)); 203 Optional<int64_t> NumBytes = MemoryLocation::getSizeOrUnknown( 204 cast<StoreSDNode>(Store)->getMemoryVT().getStoreSize()); 205 EVT GTy = DAG->getTargetLoweringInfo().getValueType(DAG->getDataLayout(), 206 G->getType()); 207 SDValue GValue = DAG->getConstant(0, Loc, GTy); 208 SDValue GAddr = DAG->getGlobalAddress(G, Loc, GTy); 209 SDValue GStore = DAG->getStore(DAG->getEntryNode(), Loc, GValue, GAddr, 210 MachinePointerInfo(G, 0)); 211 Optional<int64_t> GNumBytes = MemoryLocation::getSizeOrUnknown( 212 cast<StoreSDNode>(GStore)->getMemoryVT().getStoreSize()); 213 214 bool IsAlias; 215 bool IsValid = BaseIndexOffset::computeAliasing( 216 Store.getNode(), NumBytes, GStore.getNode(), GNumBytes, *DAG, IsAlias); 217 218 EXPECT_TRUE(IsValid); 219 EXPECT_FALSE(IsAlias); 220 } 221 222 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsWithinDiff) { 223 if (!TM) 224 return; 225 SDLoc Loc; 226 auto Int8VT = EVT::getIntegerVT(Context, 8); 227 // <vscale x 4 x i8> 228 auto VecVT = EVT::getVectorVT(Context, Int8VT, 4, true); 229 // <vscale x 2 x i8> 230 auto SubVecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 231 // <2 x i8> 232 auto SubFixedVecVT2xi8 = EVT::getVectorVT(Context, Int8VT, 2); 233 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 234 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 235 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 236 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT2xi8); 237 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT); 238 TypeSize Offset0 = TypeSize::Fixed(0); 239 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize(); 240 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 241 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 242 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 243 PtrInfo.getWithOffset(Offset0)); 244 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 245 PtrInfo.getWithOffset(Offset1)); 246 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 247 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 248 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 249 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 250 251 bool IsAlias; 252 bool IsValid = BaseIndexOffset::computeAliasing( 253 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 254 EXPECT_TRUE(IsValid); 255 EXPECT_FALSE(IsAlias); 256 257 IsValid = BaseIndexOffset::computeAliasing( 258 Store1.getNode(), NumBytes1, Store0.getNode(), NumBytes0, *DAG, IsAlias); 259 EXPECT_TRUE(IsValid); 260 EXPECT_FALSE(IsAlias); 261 } 262 263 TEST_F(SelectionDAGAddressAnalysisTest, fixedSizeFrameObjectsOutOfDiff) { 264 if (!TM) 265 return; 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 // <4 x i8> 275 auto SubFixedVecVT4xi8 = EVT::getVectorVT(Context, Int8VT, 4); 276 SDValue FIPtr = DAG->CreateStackTemporary(VecVT); 277 int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex(); 278 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(*MF, FI); 279 SDValue Value0 = DAG->getConstant(0, Loc, SubFixedVecVT4xi8); 280 SDValue Value1 = DAG->getConstant(0, Loc, SubVecVT); 281 TypeSize Offset0 = TypeSize::Fixed(0); 282 TypeSize Offset1 = SubFixedVecVT2xi8.getStoreSize(); 283 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr, Offset0, Loc); 284 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr, Offset1, Loc); 285 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 286 PtrInfo.getWithOffset(Offset0)); 287 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 288 PtrInfo.getWithOffset(Offset1)); 289 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 290 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 291 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 292 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 293 294 bool IsAlias; 295 bool IsValid = BaseIndexOffset::computeAliasing( 296 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 297 EXPECT_TRUE(IsValid); 298 EXPECT_TRUE(IsAlias); 299 } 300 301 TEST_F(SelectionDAGAddressAnalysisTest, twoFixedStackObjects) { 302 if (!TM) 303 return; 304 SDLoc Loc; 305 auto Int8VT = EVT::getIntegerVT(Context, 8); 306 // <vscale x 2 x i8> 307 auto VecVT = EVT::getVectorVT(Context, Int8VT, 2, true); 308 // <2 x i8> 309 auto FixedVecVT = EVT::getVectorVT(Context, Int8VT, 2); 310 SDValue FIPtr0 = DAG->CreateStackTemporary(FixedVecVT); 311 SDValue FIPtr1 = DAG->CreateStackTemporary(VecVT); 312 int FI0 = cast<FrameIndexSDNode>(FIPtr0.getNode())->getIndex(); 313 int FI1 = cast<FrameIndexSDNode>(FIPtr1.getNode())->getIndex(); 314 MachinePointerInfo PtrInfo0 = MachinePointerInfo::getFixedStack(*MF, FI0); 315 MachinePointerInfo PtrInfo1 = MachinePointerInfo::getFixedStack(*MF, FI1); 316 SDValue Value0 = DAG->getConstant(0, Loc, FixedVecVT); 317 SDValue Value1 = DAG->getConstant(0, Loc, VecVT); 318 TypeSize Offset0 = TypeSize::Fixed(0); 319 SDValue Index0 = DAG->getMemBasePlusOffset(FIPtr0, Offset0, Loc); 320 SDValue Index1 = DAG->getMemBasePlusOffset(FIPtr1, Offset0, Loc); 321 SDValue Store0 = DAG->getStore(DAG->getEntryNode(), Loc, Value0, Index0, 322 PtrInfo0.getWithOffset(Offset0)); 323 SDValue Store1 = DAG->getStore(DAG->getEntryNode(), Loc, Value1, Index1, 324 PtrInfo1.getWithOffset(Offset0)); 325 Optional<int64_t> NumBytes0 = MemoryLocation::getSizeOrUnknown( 326 cast<StoreSDNode>(Store0)->getMemoryVT().getStoreSize()); 327 Optional<int64_t> NumBytes1 = MemoryLocation::getSizeOrUnknown( 328 cast<StoreSDNode>(Store1)->getMemoryVT().getStoreSize()); 329 330 bool IsAlias; 331 bool IsValid = BaseIndexOffset::computeAliasing( 332 Store0.getNode(), NumBytes0, Store1.getNode(), NumBytes1, *DAG, IsAlias); 333 EXPECT_TRUE(IsValid); 334 EXPECT_FALSE(IsAlias); 335 } 336 337 } // end namespace llvm 338