[llvm] f7a6c34 - [mte] support more complicated lifetimes (e.g. for exceptions).

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 2 14:39:33 PST 2022


Author: Florian Mayer
Date: 2022-02-02T14:39:22-08:00
New Revision: f7a6c341cb936991eb3ccac3be25b02fecf7a4b8

URL: https://github.com/llvm/llvm-project/commit/f7a6c341cb936991eb3ccac3be25b02fecf7a4b8
DIFF: https://github.com/llvm/llvm-project/commit/f7a6c341cb936991eb3ccac3be25b02fecf7a4b8.diff

LOG: [mte] support more complicated lifetimes (e.g. for exceptions).

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D118848

Added: 
    llvm/test/CodeGen/AArch64/stack-tagging-split-lifetime.ll

Modified: 
    llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
    llvm/lib/Target/AArch64/AArch64StackTagging.cpp
    llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
    llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
index 8168b515099fa..e50fb6dc6fa89 100644
--- a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
+++ b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
@@ -67,7 +67,7 @@ bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT,
 
 bool isStandardLifetime(const SmallVectorImpl<IntrinsicInst *> &LifetimeStart,
                         const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd,
-                        const DominatorTree &DT, size_t MaxLifetimes);
+                        const DominatorTree *DT, size_t MaxLifetimes);
 } // namespace llvm
 
 #endif

diff  --git a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
index 31a00a41ab4ce..256a28826c661 100644
--- a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
+++ b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
@@ -78,6 +78,12 @@ static cl::opt<unsigned>
     ClMergeInitSizeLimit("stack-tagging-merge-init-size-limit", cl::init(272),
                          cl::Hidden);
 
+static cl::opt<size_t> ClMaxLifetimes(
+    "stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3),
+    cl::ReallyHidden,
+    cl::desc("How many lifetime ends to handle for a single alloca."),
+    cl::Optional);
+
 static const Align kTagGranuleSize = Align(16);
 
 namespace {
@@ -645,14 +651,17 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
     Info.AI->replaceAllUsesWith(TagPCall);
     TagPCall->setOperand(0, Info.AI);
 
+    bool StandardLifetime =
+        UnrecognizedLifetimes.empty() &&
+        isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, DT,
+                           ClMaxLifetimes);
     // Calls to functions that may return twice (e.g. setjmp) confuse the
     // postdominator analysis, and will leave us to keep memory tagged after
     // function return. Work around this by always untagging at every return
     // statement if return_twice functions are called.
-    if (UnrecognizedLifetimes.empty() && Info.LifetimeStart.size() == 1 &&
-        Info.LifetimeEnd.size() == 1 && !CallsReturnTwice) {
+    if (UnrecognizedLifetimes.empty() && StandardLifetime &&
+        !CallsReturnTwice) {
       IntrinsicInst *Start = Info.LifetimeStart[0];
-      IntrinsicInst *End = Info.LifetimeEnd[0];
       uint64_t Size =
           cast<ConstantInt>(Start->getArgOperand(0))->getZExtValue();
       Size = alignTo(Size, kTagGranuleSize);
@@ -661,8 +670,10 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
       auto TagEnd = [&](Instruction *Node) { untagAlloca(AI, Node, Size); };
       if (!DT || !PDT ||
           !forAllReachableExits(*DT, *PDT, Start, Info.LifetimeEnd, RetVec,
-                                TagEnd))
-        End->eraseFromParent();
+                                TagEnd)) {
+        for (auto *End : Info.LifetimeEnd)
+          End->eraseFromParent();
+      }
     } else {
       uint64_t Size = Info.AI->getAllocationSizeInBits(*DL).getValue() / 8;
       Value *Ptr = IRB.CreatePointerCast(TagPCall, IRB.getInt8PtrTy());

diff  --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 6f10862d18555..32e87a207ffdd 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -1382,7 +1382,7 @@ bool HWAddressSanitizer::instrumentStack(
     };
     bool StandardLifetime =
         UnrecognizedLifetimes.empty() &&
-        isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, GetDT(),
+        isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, &GetDT(),
                            ClMaxLifetimes);
     if (ShouldDetectUseAfterScope && StandardLifetime) {
       IntrinsicInst *Start = Info.LifetimeStart[0];

diff  --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
index a2ba28aff9a6b..845adbafef83a 100644
--- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
+++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
@@ -15,7 +15,7 @@
 namespace llvm {
 namespace {
 bool maybeReachableFromEachOther(const SmallVectorImpl<IntrinsicInst *> &Insts,
-                                 const DominatorTree &DT, size_t MaxLifetimes) {
+                                 const DominatorTree *DT, size_t MaxLifetimes) {
   // If we have too many lifetime ends, give up, as the algorithm below is N^2.
   if (Insts.size() > MaxLifetimes)
     return true;
@@ -23,7 +23,7 @@ bool maybeReachableFromEachOther(const SmallVectorImpl<IntrinsicInst *> &Insts,
     for (size_t J = 0; J < Insts.size(); ++J) {
       if (I == J)
         continue;
-      if (isPotentiallyReachable(Insts[I], Insts[J], nullptr, &DT))
+      if (isPotentiallyReachable(Insts[I], Insts[J], nullptr, DT))
         return true;
     }
   }
@@ -33,7 +33,7 @@ bool maybeReachableFromEachOther(const SmallVectorImpl<IntrinsicInst *> &Insts,
 
 bool isStandardLifetime(const SmallVectorImpl<IntrinsicInst *> &LifetimeStart,
                         const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd,
-                        const DominatorTree &DT, size_t MaxLifetimes) {
+                        const DominatorTree *DT, size_t MaxLifetimes) {
   // An alloca that has exactly one start and end in every possible execution.
   // If it has multiple ends, they have to be unreachable from each other, so
   // at most one of them is actually used for each execution of the function.

diff  --git a/llvm/test/CodeGen/AArch64/stack-tagging-split-lifetime.ll b/llvm/test/CodeGen/AArch64/stack-tagging-split-lifetime.ll
new file mode 100644
index 0000000000000..395602220b5d3
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stack-tagging-split-lifetime.ll
@@ -0,0 +1,38 @@
+; RUN: opt -S -aarch64-stack-tagging -stack-tagging-use-stack-safety=0 %s -o - | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-arm-unknown-eabi"
+
+define  void @f(i1 %cond) local_unnamed_addr sanitize_memtag {
+start:
+; CHECK-LABEL: start:
+  %a = alloca i8, i32 48, align 8
+  call void @llvm.lifetime.start.p0i8(i64 48, i8* nonnull %a)
+; CHECK: call void @llvm.aarch64.settag(i8* %a.tag, i64 48)
+  br i1 %cond, label %next0, label %next1
+
+next0:
+; CHECK-LABEL: next0:
+; CHECK: call void @llvm.aarch64.settag
+  call void @llvm.lifetime.end.p0i8(i64 40, i8* nonnull %a)
+  br label %exit0
+
+exit0:
+; CHECK-LABEL: exit0:
+; CHECK-NOT: call void @llvm.aarch64.settag
+  ret void
+
+next1:
+; CHECK-LABEL: next1:
+; CHECK: call void @llvm.aarch64.settag
+  call void @llvm.lifetime.end.p0i8(i64 40, i8* nonnull %a)
+  br label %exit1
+
+exit1:
+; CHECK-LABEL: exit1:
+; CHECK-NOT: call void @llvm.aarch64.settag
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)


        


More information about the llvm-commits mailing list