llvm.org GIT mirror llvm / 6602cf7
[MemorySSA] Fix def optimization handling In order for more complex updates of MSSA to happen (e.g. those in D45299), MemoryDefs need to be actual `Use`s of what they're optimized to. This patch makes that happen. In addition, this patch changes our optimization behavior for Defs slightly: we'll now consider a Def optimization invalid if the MemoryAccess it's optimized to changes. That we weren't doing this before was a bug, but given that we were tracking these with a WeakVH before, it was sort of difficult for that to matter. We're already have both of these behaviors for MemoryUses. The difference is that a MemoryUse's defining access is always its optimized access, and defining accesses are always `Use`s (in the LLVM sense). Nothing exploded when testing a stage3 clang+llvm locally, so... This also includes the test-case promised in r340461. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@340577 91177308-0d34-0410-b5e6-96231b3b80d8 George Burgess IV 1 year, 27 days ago
2 changed file(s) with 167 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
279279 friend class MemorySSAUpdater;
280280
281281 MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
282 DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
283 : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInstruction(MI),
284 OptimizedAccessAlias(MayAlias) {
282 DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB,
283 unsigned NumOperands)
284 : MemoryAccess(C, Vty, DeleteValue, BB, NumOperands),
285 MemoryInstruction(MI), OptimizedAccessAlias(MayAlias) {
285286 setDefiningAccess(DMA);
286287 }
287288
307308 Optional OptimizedAccessAlias;
308309 };
309310
310 template <>
311 struct OperandTraits
312 : public FixedNumOperandTraits {};
313 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
314
315311 /// Represents read-only accesses to memory
316312 ///
317313 /// In particular, the set of Instructions that will be represented by
322318 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
323319
324320 MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
325 : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB) {}
321 : MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB,
322 /*NumOperands=*/1) {}
326323
327324 // allocate space for exactly one operand
328325 void *operator new(size_t s) { return User::operator new(s, 1); }
380377
381378 MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
382379 unsigned Ver)
383 : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB), ID(Ver) {}
384
385 // allocate space for exactly one operand
386 void *operator new(size_t s) { return User::operator new(s, 1); }
380 : MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB,
381 /*NumOperands=*/2),
382 ID(Ver) {}
383
384 // allocate space for exactly two operands
385 void *operator new(size_t s) { return User::operator new(s, 2); }
387386
388387 static bool classof(const Value *MA) {
389388 return MA->getValueID() == MemoryDefVal;
390389 }
391390
392391 void setOptimized(MemoryAccess *MA) {
393 Optimized = MA;
394 OptimizedID = getDefiningAccess()->getID();
392 setOperand(1, MA);
393 OptimizedID = MA->getID();
395394 }
396395
397396 MemoryAccess *getOptimized() const {
398 return cast_or_null(Optimized);
397 return cast_or_null(getOperand(1));
399398 }
400399
401400 bool isOptimized() const {
402 return getOptimized() && getDefiningAccess() &&
403 OptimizedID == getDefiningAccess()->getID();
401 return getOptimized() && OptimizedID == getOptimized()->getID();
404402 }
405403
406404 void resetOptimized() {
416414
417415 const unsigned ID;
418416 unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
419 WeakVH Optimized;
420417 };
421418
422419 template <>
423 struct OperandTraits : public FixedNumOperandTraits1> {};
420 struct OperandTraits : public FixedNumOperandTraits2> {};
424421 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
422
423 template <>
424 struct OperandTraits {
425 static Use *op_begin(MemoryUseOrDef *MUD) {
426 if (auto *MU = dyn_cast(MUD))
427 return OperandTraits::op_begin(MU);
428 return OperandTraits::op_begin(cast(MUD));
429 }
430
431 static Use *op_end(MemoryUseOrDef *MUD) {
432 if (auto *MU = dyn_cast(MUD))
433 return OperandTraits::op_end(MU);
434 return OperandTraits::op_end(cast(MUD));
435 }
436
437 static unsigned operands(const MemoryUseOrDef *MUD) {
438 if (const auto *MU = dyn_cast(MUD))
439 return OperandTraits::operands(MU);
440 return OperandTraits::operands(cast(MUD));
441 }
442 };
443 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
425444
426445 /// Represents phi nodes for memory accesses.
427446 ///
12641264 MSSA.getWalker()->getClobberingMemoryAccess(BarAccess);
12651265 EXPECT_EQ(BarClobber, LifetimeStartAccess);
12661266 }
1267
1268 TEST_F(MemorySSATest, DefOptimizationsAreInvalidatedOnMoving) {
1269 IRBuilder<> B(C);
1270 F = Function::Create(FunctionType::get(B.getVoidTy(), {B.getInt1Ty()}, false),
1271 GlobalValue::ExternalLinkage, "F", &M);
1272
1273 // Make a CFG like
1274 // entry
1275 // / \
1276 // a b
1277 // \ /
1278 // c
1279 //
1280 // Put a def in A and a def in B, move the def from A -> B, observe as the
1281 // optimization is invalidated.
1282 BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
1283 BasicBlock *BlockA = BasicBlock::Create(C, "a", F);
1284 BasicBlock *BlockB = BasicBlock::Create(C, "b", F);
1285 BasicBlock *BlockC = BasicBlock::Create(C, "c", F);
1286
1287 B.SetInsertPoint(Entry);
1288 Type *Int8 = Type::getInt8Ty(C);
1289 Value *Alloca = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "alloc");
1290 StoreInst *StoreEntry = B.CreateStore(B.getInt8(0), Alloca);
1291 B.CreateCondBr(B.getTrue(), BlockA, BlockB);
1292
1293 B.SetInsertPoint(BlockA);
1294 StoreInst *StoreA = B.CreateStore(B.getInt8(1), Alloca);
1295 B.CreateBr(BlockC);
1296
1297 B.SetInsertPoint(BlockB);
1298 StoreInst *StoreB = B.CreateStore(B.getInt8(2), Alloca);
1299 B.CreateBr(BlockC);
1300
1301 B.SetInsertPoint(BlockC);
1302 B.CreateUnreachable();
1303
1304 setupAnalyses();
1305 MemorySSA &MSSA = *Analyses->MSSA;
1306
1307 auto *AccessEntry = cast(MSSA.getMemoryAccess(StoreEntry));
1308 auto *StoreAEntry = cast(MSSA.getMemoryAccess(StoreA));
1309 auto *StoreBEntry = cast(MSSA.getMemoryAccess(StoreB));
1310
1311 ASSERT_EQ(MSSA.getWalker()->getClobberingMemoryAccess(StoreAEntry),
1312 AccessEntry);
1313 ASSERT_TRUE(StoreAEntry->isOptimized());
1314
1315 ASSERT_EQ(MSSA.getWalker()->getClobberingMemoryAccess(StoreBEntry),
1316 AccessEntry);
1317 ASSERT_TRUE(StoreBEntry->isOptimized());
1318
1319 // Note that if we did InsertionPlace::Beginning, we don't go out of our way
1320 // to invalidate the cache for StoreBEntry. If the user wants to actually do
1321 // moves like these, it's up to them to ensure that nearby cache entries are
1322 // correctly invalidated (which, in general, requires walking all instructions
1323 // that the moved instruction dominates. So we probably shouldn't be doing
1324 // moves like this in general. Still, works as a test-case. ;) )
1325 MemorySSAUpdater(&MSSA).moveToPlace(StoreAEntry, BlockB,
1326 MemorySSA::InsertionPlace::End);
1327 ASSERT_FALSE(StoreAEntry->isOptimized());
1328 ASSERT_EQ(MSSA.getWalker()->getClobberingMemoryAccess(StoreAEntry),
1329 StoreBEntry);
1330 }
1331
1332 TEST_F(MemorySSATest, TestOptimizedDefsAreProperUses) {
1333 F = Function::Create(FunctionType::get(B.getVoidTy(),
1334 {B.getInt8PtrTy(), B.getInt8PtrTy()},
1335 false),
1336 GlobalValue::ExternalLinkage, "F", &M);
1337 B.SetInsertPoint(BasicBlock::Create(C, "", F));
1338 Type *Int8 = Type::getInt8Ty(C);
1339 Value *AllocA = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
1340 Value *AllocB = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "B");
1341
1342 StoreInst *StoreA = B.CreateStore(ConstantInt::get(Int8, 0), AllocA);
1343 StoreInst *StoreB = B.CreateStore(ConstantInt::get(Int8, 1), AllocB);
1344 StoreInst *StoreA2 = B.CreateStore(ConstantInt::get(Int8, 2), AllocA);
1345
1346 setupAnalyses();
1347 MemorySSA &MSSA = *Analyses->MSSA;
1348 MemorySSAWalker *Walker = Analyses->Walker;
1349
1350 // If these don't hold, there's no chance of the test result being useful.
1351 ASSERT_EQ(Walker->getClobberingMemoryAccess(StoreA),
1352 MSSA.getLiveOnEntryDef());
1353 ASSERT_EQ(Walker->getClobberingMemoryAccess(StoreB),
1354 MSSA.getLiveOnEntryDef());
1355 auto *StoreAAccess = cast(MSSA.getMemoryAccess(StoreA));
1356 auto *StoreA2Access = cast(MSSA.getMemoryAccess(StoreA2));
1357 ASSERT_EQ(Walker->getClobberingMemoryAccess(StoreA2), StoreAAccess);
1358 ASSERT_EQ(StoreA2Access->getOptimized(), StoreAAccess);
1359
1360 auto *StoreBAccess = cast(MSSA.getMemoryAccess(StoreB));
1361 ASSERT_LT(StoreAAccess->getID(), StoreBAccess->getID());
1362 ASSERT_LT(StoreBAccess->getID(), StoreA2Access->getID());
1363
1364 auto SortVecByID = [](std::vector &Defs) {
1365 llvm::sort(Defs.begin(), Defs.end(),
1366 [](const MemoryDef *LHS, const MemoryDef *RHS) {
1367 return LHS->getID() < RHS->getID();
1368 });
1369 };
1370
1371 auto SortedUserList = [&](const MemoryDef *MD) {
1372 std::vector Result;
1373 transform(MD->users(), std::back_inserter(Result),
1374 [](const User *U) { return cast(U); });
1375 SortVecByID(Result);
1376 return Result;
1377 };
1378
1379 // Use std::vectors, since they have nice pretty-printing if the test fails.
1380 // Parens are necessary because EXPECT_EQ is a macro, and we have commas in
1381 // our init lists...
1382 EXPECT_EQ(SortedUserList(StoreAAccess),
1383 (std::vector{StoreBAccess, StoreA2Access}));
1384
1385 EXPECT_EQ(SortedUserList(StoreBAccess),
1386 std::vector{StoreA2Access});
1387
1388 // StoreAAccess should be present twice, since it uses liveOnEntry for both
1389 // its defining and optimized accesses. This is a bit awkward, and is not
1390 // relied upon anywhere at the moment. If this is painful, we can fix it.
1391 EXPECT_EQ(SortedUserList(cast(MSSA.getLiveOnEntryDef())),
1392 (std::vector{StoreAAccess, StoreAAccess,
1393 StoreBAccess}));
1394 }