diff llvm/unittests/Analysis/MemorySSATest.cpp @ 236:c4bab56944e8 llvm-original

LLVM 16
author kono
date Wed, 09 Nov 2022 17:45:10 +0900
parents 79ff65ed7e25
children 1f2b6ac9f198
line wrap: on
line diff
--- a/llvm/unittests/Analysis/MemorySSATest.cpp	Wed Jul 21 10:27:27 2021 +0900
+++ b/llvm/unittests/Analysis/MemorySSATest.cpp	Wed Nov 09 17:45:10 2022 +0900
@@ -1003,50 +1003,6 @@
       << "(DefX1 = " << DefX1 << ")";
 }
 
-// Test Must alias for optimized uses
-TEST_F(MemorySSATest, TestLoadMustAlias) {
-  F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
-                       GlobalValue::ExternalLinkage, "F", &M);
-  B.SetInsertPoint(BasicBlock::Create(C, "", F));
-  Type *Int8 = Type::getInt8Ty(C);
-  Value *AllocaA = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
-  Value *AllocaB = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "B");
-
-  B.CreateStore(ConstantInt::get(Int8, 1), AllocaB);
-  // Check load from LOE
-  LoadInst *LA1 = B.CreateLoad(Int8, AllocaA, "");
-  // Check load alias cached for second load
-  LoadInst *LA2 = B.CreateLoad(Int8, AllocaA, "");
-
-  B.CreateStore(ConstantInt::get(Int8, 1), AllocaA);
-  // Check load from store/def
-  LoadInst *LA3 = B.CreateLoad(Int8, AllocaA, "");
-  // Check load alias cached for second load
-  LoadInst *LA4 = B.CreateLoad(Int8, AllocaA, "");
-
-  setupAnalyses();
-  MemorySSA &MSSA = *Analyses->MSSA;
-
-  unsigned I = 0;
-  for (LoadInst *V : {LA1, LA2}) {
-    MemoryUse *MemUse = dyn_cast_or_null<MemoryUse>(MSSA.getMemoryAccess(V));
-    EXPECT_EQ(MemUse->getOptimizedAccessType(), None)
-        << "Load " << I << " doesn't have the correct alias information";
-    // EXPECT_EQ expands such that if we increment I above, it won't get
-    // incremented except when we try to print the error message.
-    ++I;
-  }
-  for (LoadInst *V : {LA3, LA4}) {
-    MemoryUse *MemUse = dyn_cast_or_null<MemoryUse>(MSSA.getMemoryAccess(V));
-    EXPECT_EQ(MemUse->getOptimizedAccessType().getValue(),
-              AliasResult::MustAlias)
-        << "Load " << I << " doesn't have the correct alias information";
-    // EXPECT_EQ expands such that if we increment I above, it won't get
-    // incremented except when we try to print the error message.
-    ++I;
-  }
-}
-
 // Test Must alias for optimized defs.
 TEST_F(MemorySSATest, TestStoreMustAlias) {
   F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
@@ -1071,9 +1027,6 @@
     MemoryDef *MemDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(V));
     EXPECT_EQ(MemDef->isOptimized(), false)
         << "Store " << I << " is optimized from the start?";
-    EXPECT_EQ(MemDef->getOptimizedAccessType(), None)
-        << "Store " << I
-        << " has correct alias information before being optimized?";
     if (V == SA1)
       Walker->getClobberingMemoryAccess(V);
     else {
@@ -1084,57 +1037,6 @@
     }
     EXPECT_EQ(MemDef->isOptimized(), true)
         << "Store " << I << " was not optimized";
-    if (I == 0 || I == 1)
-      EXPECT_EQ(MemDef->getOptimizedAccessType(), None)
-          << "Store " << I << " doesn't have the correct alias information";
-    else
-      EXPECT_EQ(MemDef->getOptimizedAccessType().getValue(),
-                AliasResult::MustAlias)
-          << "Store " << I << " doesn't have the correct alias information";
-    // EXPECT_EQ expands such that if we increment I above, it won't get
-    // incremented except when we try to print the error message.
-    ++I;
-  }
-}
-
-// Test May alias for optimized uses.
-TEST_F(MemorySSATest, TestLoadMayAlias) {
-  F = Function::Create(FunctionType::get(B.getVoidTy(),
-                                         {B.getInt8PtrTy(), B.getInt8PtrTy()},
-                                         false),
-                       GlobalValue::ExternalLinkage, "F", &M);
-  B.SetInsertPoint(BasicBlock::Create(C, "", F));
-  Type *Int8 = Type::getInt8Ty(C);
-  auto *ArgIt = F->arg_begin();
-  Argument *PointerA = &*ArgIt;
-  Argument *PointerB = &*(++ArgIt);
-  B.CreateStore(ConstantInt::get(Int8, 1), PointerB);
-  LoadInst *LA1 = B.CreateLoad(Int8, PointerA, "");
-  B.CreateStore(ConstantInt::get(Int8, 0), PointerA);
-  LoadInst *LB1 = B.CreateLoad(Int8, PointerB, "");
-  B.CreateStore(ConstantInt::get(Int8, 0), PointerA);
-  LoadInst *LA2 = B.CreateLoad(Int8, PointerA, "");
-  B.CreateStore(ConstantInt::get(Int8, 0), PointerB);
-  LoadInst *LB2 = B.CreateLoad(Int8, PointerB, "");
-
-  setupAnalyses();
-  MemorySSA &MSSA = *Analyses->MSSA;
-
-  unsigned I = 0;
-  for (LoadInst *V : {LA1, LB1}) {
-    MemoryUse *MemUse = dyn_cast_or_null<MemoryUse>(MSSA.getMemoryAccess(V));
-    EXPECT_EQ(MemUse->getOptimizedAccessType().getValue(),
-              AliasResult::MayAlias)
-        << "Load " << I << " doesn't have the correct alias information";
-    // EXPECT_EQ expands such that if we increment I above, it won't get
-    // incremented except when we try to print the error message.
-    ++I;
-  }
-  for (LoadInst *V : {LA2, LB2}) {
-    MemoryUse *MemUse = dyn_cast_or_null<MemoryUse>(MSSA.getMemoryAccess(V));
-    EXPECT_EQ(MemUse->getOptimizedAccessType().getValue(),
-              AliasResult::MustAlias)
-        << "Load " << I << " doesn't have the correct alias information";
     // EXPECT_EQ expands such that if we increment I above, it won't get
     // incremented except when we try to print the error message.
     ++I;
@@ -1178,9 +1080,6 @@
     MemoryDef *MemDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(V));
     EXPECT_EQ(MemDef->isOptimized(), false)
         << "Store " << I << " is optimized from the start?";
-    EXPECT_EQ(MemDef->getOptimizedAccessType(), None)
-        << "Store " << I
-        << " has correct alias information before being optimized?";
     ++I;
   }
 
@@ -1192,17 +1091,6 @@
     MemoryDef *MemDef = dyn_cast_or_null<MemoryDef>(MSSA.getMemoryAccess(V));
     EXPECT_EQ(MemDef->isOptimized(), true)
         << "Store " << I << " was not optimized";
-    if (I == 1 || I == 3 || I == 4)
-      EXPECT_EQ(MemDef->getOptimizedAccessType().getValue(),
-                AliasResult::MayAlias)
-          << "Store " << I << " doesn't have the correct alias information";
-    else if (I == 0 || I == 2)
-      EXPECT_EQ(MemDef->getOptimizedAccessType(), None)
-          << "Store " << I << " doesn't have the correct alias information";
-    else
-      EXPECT_EQ(MemDef->getOptimizedAccessType().getValue(),
-                AliasResult::MustAlias)
-          << "Store " << I << " doesn't have the correct alias information";
     // EXPECT_EQ expands such that if we increment I above, it won't get
     // incremented except when we try to print the error message.
     ++I;
@@ -1725,4 +1613,186 @@
       EXPECT_TRUE(ItB->second.Size.getValue() == 8);
     }
   }
-}
\ No newline at end of file
+}
+
+TEST_F(MemorySSATest, TestInvariantGroup) {
+  SMDiagnostic E;
+  auto M = parseAssemblyString("declare void @f(i8*)\n"
+                               "define i8 @test(i8* %p) {\n"
+                               "entry:\n"
+                               "  store i8 42, i8* %p, !invariant.group !0\n"
+                               "  call void @f(i8* %p)\n"
+                               "  %v = load i8, i8* %p, !invariant.group !0\n"
+                               "  ret i8 %v\n"
+                               "}\n"
+                               "!0 = !{}",
+                               E, C);
+  ASSERT_TRUE(M);
+  F = M->getFunction("test");
+  ASSERT_TRUE(F);
+  setupAnalyses();
+  MemorySSA &MSSA = *Analyses->MSSA;
+  MemorySSAWalker *Walker = Analyses->Walker;
+
+  auto &BB = F->getEntryBlock();
+  auto &SI = cast<StoreInst>(*BB.begin());
+  auto &Call = cast<CallBase>(*std::next(BB.begin()));
+  auto &LI = cast<LoadInst>(*std::next(std::next(BB.begin())));
+
+  {
+    MemoryAccess *SAccess = MSSA.getMemoryAccess(&SI);
+    MemoryAccess *LAccess = MSSA.getMemoryAccess(&LI);
+    MemoryAccess *SClobber = Walker->getClobberingMemoryAccess(SAccess);
+    EXPECT_TRUE(MSSA.isLiveOnEntryDef(SClobber));
+    MemoryAccess *LClobber = Walker->getClobberingMemoryAccess(LAccess);
+    EXPECT_EQ(SAccess, LClobber);
+  }
+
+  // remove store and verify that the memory accesses still make sense
+  MemorySSAUpdater Updater(&MSSA);
+  Updater.removeMemoryAccess(&SI);
+  SI.eraseFromParent();
+
+  {
+    MemoryAccess *CallAccess = MSSA.getMemoryAccess(&Call);
+    MemoryAccess *LAccess = MSSA.getMemoryAccess(&LI);
+    MemoryAccess *LClobber = Walker->getClobberingMemoryAccess(LAccess);
+    EXPECT_EQ(CallAccess, LClobber);
+  }
+}
+
+static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
+  for (BasicBlock &BB : F)
+    if (BB.getName() == Name)
+      return &BB;
+  llvm_unreachable("Expected to find basic block!");
+}
+
+static Instruction *getInstructionByName(Function &F, StringRef Name) {
+  for (BasicBlock &BB : F)
+    for (Instruction &I : BB)
+      if (I.getName() == Name)
+        return &I;
+  llvm_unreachable("Expected to find instruction!");
+}
+
+TEST_F(MemorySSATest, TestVisitedBlocks) {
+  SMDiagnostic E;
+  auto M = parseAssemblyString(
+      "define void @test(i64* noalias %P, i64 %N) {\n"
+      "preheader.n:\n"
+      "  br label %header.n\n"
+      "header.n:\n"
+      "  %n = phi i64 [ 0, %preheader.n ], [ %inc.n, %latch.n ]\n"
+      "  %guard.cond.i = icmp slt i64 0, %N\n"
+      "  br i1 %guard.cond.i, label %header.i.check, label %other.i\n"
+      "header.i.check:\n"
+      "  br label %preheader.i\n"
+      "preheader.i:\n"
+      "  br label %header.i\n"
+      "header.i:\n"
+      "  %i = phi i64 [ 0, %preheader.i ], [ %inc.i, %header.i ]\n"
+      "  %v1 = load i64, i64* %P, align 8\n"
+      "  %v2 = load i64, i64* %P, align 8\n"
+      "  %inc.i = add nsw i64 %i, 1\n"
+      "  %cmp.i = icmp slt i64 %inc.i, %N\n"
+      "  br i1 %cmp.i, label %header.i, label %exit.i\n"
+      "exit.i:\n"
+      "  br label %commonexit\n"
+      "other.i:\n"
+      "  br label %commonexit\n"
+      "commonexit:\n"
+      "  br label %latch.n\n"
+      "latch.n:\n"
+      "  %inc.n = add nsw i64 %n, 1\n"
+      "  %cmp.n = icmp slt i64 %inc.n, %N\n"
+      "  br i1 %cmp.n, label %header.n, label %exit.n\n"
+      "exit.n:\n"
+      "  ret void\n"
+      "}\n",
+      E, C);
+  ASSERT_TRUE(M);
+  F = M->getFunction("test");
+  ASSERT_TRUE(F);
+  setupAnalyses();
+  MemorySSA &MSSA = *Analyses->MSSA;
+  MemorySSAUpdater Updater(&MSSA);
+
+  {
+    // Move %v1 before the terminator of %header.i.check
+    BasicBlock *BB = getBasicBlockByName(*F, "header.i.check");
+    Instruction *LI = getInstructionByName(*F, "v1");
+    LI->moveBefore(BB->getTerminator());
+    if (MemoryUseOrDef *MUD = MSSA.getMemoryAccess(LI))
+      Updater.moveToPlace(MUD, BB, MemorySSA::BeforeTerminator);
+
+    // Change the termiantor of %header.i.check to `br label true, label
+    // %preheader.i, label %other.i`
+    BB->getTerminator()->eraseFromParent();
+    ConstantInt *BoolTrue = ConstantInt::getTrue(F->getContext());
+    BranchInst::Create(getBasicBlockByName(*F, "preheader.i"),
+                       getBasicBlockByName(*F, "other.i"), BoolTrue, BB);
+    SmallVector<DominatorTree::UpdateType, 4> DTUpdates;
+    DTUpdates.push_back(DominatorTree::UpdateType(
+        DominatorTree::Insert, BB, getBasicBlockByName(*F, "other.i")));
+    Updater.applyUpdates(DTUpdates, Analyses->DT, true);
+  }
+
+  // After the first moveToPlace(), %other.i is in VisitedBlocks, even after
+  // there is a new edge to %other.i, which makes the second moveToPlace()
+  // traverse incorrectly.
+  {
+    // Move %v2 before the terminator of %preheader.i
+    BasicBlock *BB = getBasicBlockByName(*F, "preheader.i");
+    Instruction *LI = getInstructionByName(*F, "v2");
+    LI->moveBefore(BB->getTerminator());
+    // Check that there is no assertion of "Incomplete phi during partial
+    // rename"
+    if (MemoryUseOrDef *MUD = MSSA.getMemoryAccess(LI))
+      Updater.moveToPlace(MUD, BB, MemorySSA::BeforeTerminator);
+  }
+}
+
+TEST_F(MemorySSATest, TestNoDbgInsts) {
+  SMDiagnostic E;
+  auto M = parseAssemblyString(R"(
+      define void @test() presplitcoroutine {
+      entry:
+        %i = alloca i32
+        call void @llvm.dbg.declare(metadata ptr %i, metadata !6, metadata !DIExpression()), !dbg !10
+        call void @llvm.dbg.value(metadata ptr %i, metadata !6, metadata !DIExpression()), !dbg !10
+        ret void
+      }
+
+      declare void @llvm.dbg.declare(metadata, metadata, metadata) nocallback nofree nosync nounwind readnone speculatable willreturn
+      declare void @llvm.dbg.value(metadata, metadata, metadata) nocallback nofree nosync nounwind readnone speculatable willreturn
+
+      !llvm.dbg.cu = !{!0}
+
+      !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
+      !1 = !DIFile(filename: "repro.cpp", directory: ".")
+      !2 = !{}
+      !3 = !{i32 7, !"Dwarf Version", i32 4}
+      !4 = !{i32 2, !"Debug Info Version", i32 3}
+      !5 = !{!"clang version 15.0.0"}
+      !6 = !DILocalVariable(name: "i", scope: !7, file: !1, line: 24, type: !10)
+      !7 = distinct !DILexicalBlock(scope: !8, file: !1, line: 23, column: 12)
+      !8 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 23, type: !9, scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+      !9 = !DISubroutineType(types: !2)
+      !10 = !DILocation(line: 24, column: 7, scope: !7)
+    )",
+    E, C);
+  ASSERT_TRUE(M);
+  F = M->getFunction("test");
+  ASSERT_TRUE(F);
+  setupAnalyses();
+  MemorySSA &MSSA = *Analyses->MSSA;
+  MemorySSAUpdater Updater(&MSSA);
+
+  BasicBlock &Entry = F->front();
+  auto I = Entry.begin();
+  Instruction *DbgDeclare = cast<Instruction>(I++);
+  Instruction *DbgValue = cast<Instruction>(I++);
+  ASSERT_EQ(MSSA.getMemoryAccess(DbgDeclare), nullptr);
+  ASSERT_EQ(MSSA.getMemoryAccess(DbgValue), nullptr);
+}