StephenFan updated this revision to Diff 444701.
StephenFan added a comment.

1. Record bypassed lifetime start markers in codegenfunction class instead of 
lexicalscope. Since bypassed variables may be defined when lexicalscope is 
nullptr. This can also fix test fail of use-after-scope-goto.cpp.
2. Check more lifetime.start or end intrinsics in lifetime2.c test file.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129448/new/

https://reviews.llvm.org/D129448

Files:
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/test/CodeGen/lifetime2.c

Index: clang/test/CodeGen/lifetime2.c
===================================================================
--- clang/test/CodeGen/lifetime2.c
+++ clang/test/CodeGen/lifetime2.c
@@ -35,11 +35,12 @@
 // CHECK-LABEL: @goto_bypass
 void goto_bypass(void) {
   {
-    // O2-NOT: @llvm.lifetime.start.p0i8(i64 1
-    // O2-NOT: @llvm.lifetime.end.p0i8(i64 1
+    // O2: @llvm.lifetime.start.p0i8(i64 1
     char x;
   l1:
+    // O2: @llvm.lifetime.start.p0i8(i64 1
     bar(&x, 1);
+    // O2: @llvm.lifetime.end.p0i8(i64 1
   }
   goto l1;
 }
@@ -69,24 +70,26 @@
   switch (n) {
   case 1:
     n = n;
-    // O2-NOT: @llvm.lifetime.start.p0i8(i64 1
-    // O2-NOT: @llvm.lifetime.end.p0i8(i64 1
+    // O2: @llvm.lifetime.start.p0i8(i64 1
     char x;
     bar(&x, 1);
     break;
   case 2:
+    // O2: @llvm.lifetime.start.p0i8(i64 1
     bar(&x, 1);
     break;
+    // O2: @llvm.lifetime.end.p0i8(i64 1
   }
 }
 
 // CHECK-LABEL: @indirect_jump
 void indirect_jump(int n) {
   char x;
-  // O2-NOT: @llvm.lifetime
+  // O2: @llvm.lifetime.start
   void *T[] = {&&L};
   goto *T[n];
 L:
+  // O2: @llvm.lifetime.start
   bar(&x, 1);
 }
 
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -38,6 +38,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
@@ -1926,6 +1927,14 @@
   /// The current lexical scope.
   LexicalScope *CurLexicalScope = nullptr;
 
+  /// Map from lexical socpe to vector of bypassed lifetime start markers.
+  /// NOTE: If a lifetime start marker isn't defined in any lexical scope(
+  /// defining while CurLexicalScope is nullptr), its key is nullptr;
+  std::map<const LexicalScope *, llvm::SmallVector<llvm::CallInst *, 8>>
+      BypassedLifetimeStartMarkers;
+
+  void restartBypassedVariable();
+
   /// The current source location that should be used for exception
   /// handling code.
   SourceLocation CurEHLocation;
@@ -2922,7 +2931,8 @@
   void EmitSehTryScopeBegin();
   void EmitSehTryScopeEnd();
 
-  llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
+  llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr,
+                                 bool isBypassed = false);
   void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
 
   llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1233,6 +1233,8 @@
     EmitBranch(SkipCountBB);
   }
   EmitBlock(BB);
+  restartBypassedVariable();
+
   uint64_t CurrentCount = getCurrentProfileCount();
   incrementProfileCounter(S);
   setCurrentProfileCount(getCurrentProfileCount() + CurrentCount);
@@ -1299,6 +1301,14 @@
   return ResTy;
 }
 
+void CodeGenFunction::restartBypassedVariable() {
+  if (BypassedLifetimeStartMarkers.count(CurLexicalScope))
+    llvm::for_each(BypassedLifetimeStartMarkers[CurLexicalScope],
+                   [this](const llvm::CallInst *LifetimeStartMarker) {
+                     Builder.Insert(LifetimeStartMarker->clone());
+                   });
+}
+
 void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
                                    const CGFunctionInfo &FnInfo) {
   assert(Fn && "generating code for null Function");
@@ -1454,6 +1464,8 @@
   // a quick pass now to see if we can.
   if (!CurFn->doesNotThrow())
     TryMarkNoThrow(CurFn);
+
+  BypassedLifetimeStartMarkers.clear();
 }
 
 /// ContainsLabel - Return true if the statement contains a label in it.  If
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -646,6 +646,7 @@
   }
 
   EmitBlock(Dest.getBlock());
+  restartBypassedVariable();
 
   // Emit debug info for labels.
   if (CGDebugInfo *DI = getDebugInfo()) {
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -1330,7 +1330,8 @@
 /// \return a pointer to the temporary size Value if a marker was emitted, null
 /// otherwise
 llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
-                                                llvm::Value *Addr) {
+                                                llvm::Value *Addr,
+                                                bool isBypassed) {
   if (!ShouldEmitLifetimeMarkers)
     return nullptr;
 
@@ -1342,6 +1343,8 @@
   Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
   llvm::CallInst *C =
       Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+  if (isBypassed)
+    BypassedLifetimeStartMarkers[CurLexicalScope].push_back(C);
   C->setDoesNotThrow();
   return SizeV;
 }
@@ -1551,24 +1554,10 @@
       // Emit a lifetime intrinsic if meaningful. There's no point in doing this
       // if we don't have a valid insertion point (?).
       if (HaveInsertPoint() && !IsMSCatchParam) {
-        // If there's a jump into the lifetime of this variable, its lifetime
-        // gets broken up into several regions in IR, which requires more work
-        // to handle correctly. For now, just omit the intrinsics; this is a
-        // rare case, and it's better to just be conservatively correct.
-        // PR28267.
-        //
-        // We have to do this in all language modes if there's a jump past the
-        // declaration. We also have to do it in C if there's a jump to an
-        // earlier point in the current block because non-VLA lifetimes begin as
-        // soon as the containing block is entered, not when its variables
-        // actually come into scope; suppressing the lifetime annotations
-        // completely in this case is unnecessarily pessimistic, but again, this
-        // is rare.
-        if (!Bypasses.IsBypassed(&D) &&
-            !(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
+        if (!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
           llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
-          emission.SizeForLifetimeMarkers =
-              EmitLifetimeStart(Size, AllocaAddr.getPointer());
+          emission.SizeForLifetimeMarkers = EmitLifetimeStart(
+              Size, AllocaAddr.getPointer(), Bypasses.IsBypassed(&D));
         }
       } else {
         assert(!emission.useLifetimeMarkers());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to