[llvm] 973f760 - [HWASan] [MTE] support double lifetime.end in same BB

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 2 10:59:02 PST 2026


Author: Florian Mayer
Date: 2026-03-02T10:58:58-08:00
New Revision: 973f7606fba48afc3427c8c8dbbc186139c982e7

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

LOG: [HWASan] [MTE] support double lifetime.end in same BB

We can just ignore the second one, because it will always be a no-op.

Reviewers: pcc, usama54321, vitalybuka

Reviewed By: vitalybuka

Pull Request: https://github.com/llvm/llvm-project/pull/183809

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
    llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
    llvm/test/CodeGen/AArch64/stack-tagging.ll
    llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
index 69a4f6548317e..90270ef483636 100644
--- a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
+++ b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
@@ -33,10 +33,6 @@ struct AllocaInfo {
   struct BBInfo {
     Intrinsic::ID First = Intrinsic::not_intrinsic;
     Intrinsic::ID Last = Intrinsic::not_intrinsic;
-    // This BB calls lifetime.end twice without a start inbetween.
-    // TODO: handle this case smarter than just throwing out lifetime
-    // annotations completely.
-    bool DoubleEnd = false;
   };
   AllocaInst *AI;
   SmallVector<IntrinsicInst *, 2> LifetimeStart;

diff  --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
index b13e7353674bf..06523f3b0b5f3 100644
--- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
+++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
@@ -76,17 +76,15 @@ bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT,
   SmallVector<BasicBlock *, 2> LastEndBlocks;
   SmallPtrSet<const BasicBlock *, 2> FirstEndBlocks;
   SmallPtrSet<BasicBlock *, 2> StartBlocks;
-  if (any_of(AInfo.BBInfos, [&](const auto &It) {
-        const auto &[BB, BBI] = It;
-        if (BBI.Last == Intrinsic::lifetime_end)
-          LastEndBlocks.append(succ_begin(BB), succ_end(BB));
-        else
-          StartBlocks.insert(BB);
-        if (BBI.First == Intrinsic::lifetime_end)
-          FirstEndBlocks.insert(BB);
-        return BBI.DoubleEnd;
-      }))
-    return false;
+  for_each(AInfo.BBInfos, [&](const auto &It) {
+    const auto &[BB, BBI] = It;
+    if (BBI.Last == Intrinsic::lifetime_end)
+      LastEndBlocks.append(succ_begin(BB), succ_end(BB));
+    else
+      StartBlocks.insert(BB);
+    if (BBI.First == Intrinsic::lifetime_end)
+      FirstEndBlocks.insert(BB);
+  });
   if (LastEndBlocks.empty() || FirstEndBlocks.empty())
     return true;
   return !isManyPotentiallyReachableFromMany(LastEndBlocks, FirstEndBlocks,
@@ -156,13 +154,10 @@ void StackInfoBuilder::visit(OptimizationRemarkEmitter &ORE,
     auto &AInfo = Info.AllocasToInstrument[AI];
     auto &BBInfo = AInfo.BBInfos[II->getParent()];
 
-    if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
+    if (II->getIntrinsicID() == Intrinsic::lifetime_start)
       AInfo.LifetimeStart.push_back(II);
-    } else {
+    else if (BBInfo.Last != Intrinsic::lifetime_end)
       AInfo.LifetimeEnd.push_back(II);
-      if (BBInfo.Last == Intrinsic::lifetime_end)
-        BBInfo.DoubleEnd = true;
-    }
 
     BBInfo.Last = II->getIntrinsicID();
     if (BBInfo.First == Intrinsic::not_intrinsic)

diff  --git a/llvm/test/CodeGen/AArch64/stack-tagging.ll b/llvm/test/CodeGen/AArch64/stack-tagging.ll
index f75a656f16fbf..c2ff7530451eb 100644
--- a/llvm/test/CodeGen/AArch64/stack-tagging.ll
+++ b/llvm/test/CodeGen/AArch64/stack-tagging.ll
@@ -162,12 +162,13 @@ if.end:
 
 
 ; CHECK-LABEL: define void @DoubleEnd(
-; CHECK:  call void @llvm.aarch64.settag(
 ; CHECK:  br i1
-; CHECK-NOT: @llvm.lifetime.start
+; CHECK:  call void @llvm.lifetime.start.p0(
+; CHECK:  call void @llvm.aarch64.settag(
 ; CHECK:  call void @use8(
 ; CHECK:  call void @llvm.aarch64.settag(
-; CHECK-NOT: @llvm.lifetime.end
+; CHECK:  call void @llvm.lifetime.end.p0(
+; CHECK:  br label
 ; CHECK:  ret void
 
 

diff  --git a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll
index a783e11da4622..a95d81bf3d2c1 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope.ll
@@ -3458,23 +3458,20 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; X86-SCOPE-NEXT:    [[TMP9:%.*]] = shl i64 [[TMP6]], 57
 ; X86-SCOPE-NEXT:    [[TMP10:%.*]] = or i64 [[TMP8]], [[TMP9]]
 ; X86-SCOPE-NEXT:    [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP10]] to ptr
-; X86-SCOPE-NEXT:    [[TMP11:%.*]] = trunc i64 [[TMP6]] to i8
-; X86-SCOPE-NEXT:    call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP11]], i64 16)
 ; X86-SCOPE-NEXT:    br label [[TMP12:%.*]]
-; X86-SCOPE:       12:
+; X86-SCOPE:       11:
+; X86-SCOPE-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[TMP4]])
 ; X86-SCOPE-NEXT:    [[TMP13:%.*]] = trunc i64 [[TMP6]] to i8
 ; X86-SCOPE-NEXT:    call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP13]], i64 16)
 ; X86-SCOPE-NEXT:    [[TMP14:%.*]] = tail call i1 (...) @cond()
 ; X86-SCOPE-NEXT:    [[TMP15:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
 ; X86-SCOPE-NEXT:    call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP15]], i64 16)
+; X86-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]])
 ; X86-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; X86-SCOPE-NEXT:    [[TMP16:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; X86-SCOPE-NEXT:    call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP16]], i64 16)
+; X86-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]])
 ; X86-SCOPE-NEXT:    br i1 [[TMP14]], label [[TMP17:%.*]], label [[TMP12]]
-; X86-SCOPE:       17:
+; X86-SCOPE:       15:
 ; X86-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; X86-SCOPE-NEXT:    [[TMP18:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; X86-SCOPE-NEXT:    call void @__hwasan_tag_memory(ptr [[TMP4]], i8 [[TMP18]], i64 16)
 ; X86-SCOPE-NEXT:    ret i32 0
 ;
 ; X86-NOSCOPE-LABEL: @double_end(
@@ -3497,6 +3494,7 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; X86-NOSCOPE:       12:
 ; X86-NOSCOPE-NEXT:    [[TMP13:%.*]] = tail call i1 (...) @cond()
 ; X86-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
+; X86-NOSCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP4]])
 ; X86-NOSCOPE-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP12]]
 ; X86-NOSCOPE:       14:
 ; X86-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
@@ -3534,14 +3532,9 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-SCOPE-NEXT:    [[TMP23:%.*]] = shl i64 [[TMP20]], 56
 ; AARCH64-SCOPE-NEXT:    [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]]
 ; AARCH64-SCOPE-NEXT:    [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr
-; AARCH64-SCOPE-NEXT:    [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8
-; AARCH64-SCOPE-NEXT:    [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SCOPE-NEXT:    [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935
-; AARCH64-SCOPE-NEXT:    [[TMP28:%.*]] = lshr i64 [[TMP27]], 4
-; AARCH64-SCOPE-NEXT:    [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]]
-; AARCH64-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP29]], i8 [[TMP25]], i64 1, i1 false)
 ; AARCH64-SCOPE-NEXT:    br label [[TMP30:%.*]]
-; AARCH64-SCOPE:       30:
+; AARCH64-SCOPE:       25:
+; AARCH64-SCOPE-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SCOPE-NEXT:    [[TMP31:%.*]] = trunc i64 [[TMP20]] to i8
 ; AARCH64-SCOPE-NEXT:    [[TMP32:%.*]] = ptrtoint ptr [[TMP18]] to i64
 ; AARCH64-SCOPE-NEXT:    [[TMP33:%.*]] = and i64 [[TMP32]], 72057594037927935
@@ -3555,22 +3548,12 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-SCOPE-NEXT:    [[TMP40:%.*]] = lshr i64 [[TMP39]], 4
 ; AARCH64-SCOPE-NEXT:    [[TMP41:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP40]]
 ; AARCH64-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP41]], i8 [[TMP37]], i64 1, i1 false)
+; AARCH64-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; AARCH64-SCOPE-NEXT:    [[TMP42:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; AARCH64-SCOPE-NEXT:    [[TMP43:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SCOPE-NEXT:    [[TMP44:%.*]] = and i64 [[TMP43]], 72057594037927935
-; AARCH64-SCOPE-NEXT:    [[TMP45:%.*]] = lshr i64 [[TMP44]], 4
-; AARCH64-SCOPE-NEXT:    [[TMP46:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP45]]
-; AARCH64-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP46]], i8 [[TMP42]], i64 1, i1 false)
+; AARCH64-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SCOPE-NEXT:    br i1 [[TMP36]], label [[TMP47:%.*]], label [[TMP30]]
-; AARCH64-SCOPE:       47:
+; AARCH64-SCOPE:       37:
 ; AARCH64-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; AARCH64-SCOPE-NEXT:    [[TMP48:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; AARCH64-SCOPE-NEXT:    [[TMP49:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SCOPE-NEXT:    [[TMP50:%.*]] = and i64 [[TMP49]], 72057594037927935
-; AARCH64-SCOPE-NEXT:    [[TMP51:%.*]] = lshr i64 [[TMP50]], 4
-; AARCH64-SCOPE-NEXT:    [[TMP52:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP51]]
-; AARCH64-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP52]], i8 [[TMP48]], i64 1, i1 false)
 ; AARCH64-SCOPE-NEXT:    ret i32 0
 ;
 ; AARCH64-NOSCOPE-LABEL: @double_end(
@@ -3613,6 +3596,7 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-NOSCOPE:       30:
 ; AARCH64-NOSCOPE-NEXT:    [[TMP31:%.*]] = tail call i1 (...) @cond()
 ; AARCH64-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
+; AARCH64-NOSCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-NOSCOPE-NEXT:    br i1 [[TMP31]], label [[TMP32:%.*]], label [[TMP30]]
 ; AARCH64-NOSCOPE:       32:
 ; AARCH64-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
@@ -3654,17 +3638,9 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP23:%.*]] = shl i64 [[TMP20]], 56
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP24:%.*]] = or i64 [[TMP22]], [[TMP23]]
 ; AARCH64-SHORT-SCOPE-NEXT:    [[ALLOCA_0_HWASAN:%.*]] = inttoptr i64 [[TMP24]] to ptr
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP25:%.*]] = trunc i64 [[TMP20]] to i8
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP26:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP27:%.*]] = and i64 [[TMP26]], 72057594037927935
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP28:%.*]] = lshr i64 [[TMP27]], 4
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP29:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP28]]
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP30:%.*]] = getelementptr i8, ptr [[TMP29]], i32 0
-; AARCH64-SHORT-SCOPE-NEXT:    store i8 1, ptr [[TMP30]], align 1
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP31:%.*]] = getelementptr i8, ptr [[TMP18]], i32 15
-; AARCH64-SHORT-SCOPE-NEXT:    store i8 [[TMP25]], ptr [[TMP31]], align 1
 ; AARCH64-SHORT-SCOPE-NEXT:    br label [[TMP32:%.*]]
-; AARCH64-SHORT-SCOPE:       32:
+; AARCH64-SHORT-SCOPE:       25:
+; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP33:%.*]] = trunc i64 [[TMP20]] to i8
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP34:%.*]] = ptrtoint ptr [[TMP18]] to i64
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP35:%.*]] = and i64 [[TMP34]], 72057594037927935
@@ -3681,22 +3657,12 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP44:%.*]] = lshr i64 [[TMP43]], 4
 ; AARCH64-SHORT-SCOPE-NEXT:    [[TMP45:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP44]]
 ; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP45]], i8 [[TMP41]], i64 1, i1 false)
+; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SHORT-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP46:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP47:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP48:%.*]] = and i64 [[TMP47]], 72057594037927935
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP49:%.*]] = lshr i64 [[TMP48]], 4
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP50:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP49]]
-; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP50]], i8 [[TMP46]], i64 1, i1 false)
+; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SHORT-SCOPE-NEXT:    br i1 [[TMP40]], label [[TMP51:%.*]], label [[TMP32]]
-; AARCH64-SHORT-SCOPE:       51:
+; AARCH64-SHORT-SCOPE:       39:
 ; AARCH64-SHORT-SCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP52:%.*]] = trunc i64 [[HWASAN_UAR_TAG]] to i8
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP53:%.*]] = ptrtoint ptr [[TMP18]] to i64
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP54:%.*]] = and i64 [[TMP53]], 72057594037927935
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP55:%.*]] = lshr i64 [[TMP54]], 4
-; AARCH64-SHORT-SCOPE-NEXT:    [[TMP56:%.*]] = getelementptr i8, ptr [[TMP17]], i64 [[TMP55]]
-; AARCH64-SHORT-SCOPE-NEXT:    call void @llvm.memset.p0.i64(ptr align 1 [[TMP56]], i8 [[TMP52]], i64 1, i1 false)
 ; AARCH64-SHORT-SCOPE-NEXT:    ret i32 0
 ;
 ; AARCH64-SHORT-NOSCOPE-LABEL: @double_end(
@@ -3742,6 +3708,7 @@ define dso_local i32 @double_end() local_unnamed_addr sanitize_hwaddress {
 ; AARCH64-SHORT-NOSCOPE:       32:
 ; AARCH64-SHORT-NOSCOPE-NEXT:    [[TMP33:%.*]] = tail call i1 (...) @cond()
 ; AARCH64-SHORT-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])
+; AARCH64-SHORT-NOSCOPE-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[TMP18]])
 ; AARCH64-SHORT-NOSCOPE-NEXT:    br i1 [[TMP33]], label [[TMP34:%.*]], label [[TMP32]]
 ; AARCH64-SHORT-NOSCOPE:       34:
 ; AARCH64-SHORT-NOSCOPE-NEXT:    call void @use(ptr nonnull [[ALLOCA_0_HWASAN]])


        


More information about the llvm-commits mailing list