[llvm] [llvm][sroa] Disable support for `invariant.group` (PR #151743)
Tommy Má¶œMichen via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 1 11:06:28 PDT 2025
https://github.com/tommymcm created https://github.com/llvm/llvm-project/pull/151743
Resolves #151574
> SROA pass does not perform aggregate load/store rewriting on a pointer whose source is a `launder.invariant.group`.
>
> This causes failed assertion in `AllocaSlices`.
>
> ```
> void (anonymous namespace)::AllocaSlices::SliceBuilder::visitStoreInst(StoreInst &):
> Assertion `(!SI.isSimple() || ValOp->getType()->isSingleValueType()) &&
> "All simple FCA stores should have been pre-split"' failed.
> ```
Disables support for `{launder,strip}.invariant.group` intrinsics in SROA.
Updates SROA test for `invariant.group` support.
>From 1f665752398b51cbc375df459d87104586a21526 Mon Sep 17 00:00:00 2001
From: Tommy McMichen <tommymcmichen at fb.com>
Date: Fri, 1 Aug 2025 10:58:24 -0700
Subject: [PATCH] [llvm][sroa] Disabled support for `invariant.group`
---
llvm/lib/Transforms/Scalar/SROA.cpp | 15 ++-------
llvm/test/Transforms/SROA/invariant-group.ll | 34 ++++++++++++++++----
2 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 23256cf2acbd2..03d9f32aa3f03 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -1247,8 +1247,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
"Map index doesn't point back to a slice with this user.");
}
- // Disable SRoA for any intrinsics except for lifetime invariants and
- // invariant group.
+ // Disable SRoA for any intrinsics except for lifetime invariants.
// FIXME: What about debug intrinsics? This matches old behavior, but
// doesn't make sense.
void visitIntrinsicInst(IntrinsicInst &II) {
@@ -1268,12 +1267,6 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
return;
}
- if (II.isLaunderOrStripInvariantGroup()) {
- insertUse(II, Offset, AllocSize, true);
- enqueueUsers(II);
- return;
- }
-
Base::visitIntrinsicInst(II);
}
@@ -3607,8 +3600,7 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {
}
bool visitIntrinsicInst(IntrinsicInst &II) {
- assert((II.isLifetimeStartOrEnd() || II.isLaunderOrStripInvariantGroup() ||
- II.isDroppable()) &&
+ assert((II.isLifetimeStartOrEnd() || II.isDroppable()) &&
"Unexpected intrinsic!");
LLVM_DEBUG(dbgs() << " original: " << II << "\n");
@@ -3622,9 +3614,6 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {
return true;
}
- if (II.isLaunderOrStripInvariantGroup())
- return true;
-
assert(II.getArgOperand(1) == OldPtr);
// Lifetime intrinsics are only promotable if they cover the whole alloca.
// Therefore, we drop lifetime intrinsics which don't cover the whole
diff --git a/llvm/test/Transforms/SROA/invariant-group.ll b/llvm/test/Transforms/SROA/invariant-group.ll
index 1be6f6e2fc32b..147ea3704f6b9 100644
--- a/llvm/test/Transforms/SROA/invariant-group.ll
+++ b/llvm/test/Transforms/SROA/invariant-group.ll
@@ -11,10 +11,17 @@ declare i32 @somevalue()
define void @f() {
; CHECK-LABEL: @f(
+; CHECK-NEXT: [[A:%.*]] = alloca [[T:%.*]], align 8
+; CHECK-NEXT: [[A1_I8_INV:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[A]])
+; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue()
; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue()
-; CHECK-NEXT: call void @h(i32 [[SV1]])
-; CHECK-NEXT: call void @h(i32 [[SV2]])
+; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]]
+; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4
+; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
+; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4
+; CHECK-NEXT: call void @h(i32 [[V1]])
+; CHECK-NEXT: call void @h(i32 [[V2]])
; CHECK-NEXT: ret void
;
%a = alloca %t
@@ -44,7 +51,7 @@ define void @g() {
; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1
; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue()
; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue()
-; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]]
+; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4
; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]]
; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4
@@ -81,6 +88,9 @@ define void @g() {
define void @store_and_launder() {
; CHECK-LABEL: @store_and_launder(
+; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
+; CHECK-NEXT: store i32 0, ptr [[VALPTR]], align 4
+; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
; CHECK-NEXT: ret void
;
%valptr = alloca i32, align 4
@@ -91,7 +101,10 @@ define void @store_and_launder() {
define i32 @launder_and_load() {
; CHECK-LABEL: @launder_and_load(
-; CHECK-NEXT: ret i32 undef
+; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
+; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[VALPTR]], align 4
+; CHECK-NEXT: ret i32 [[V2]]
;
%valptr = alloca i32, align 4
%barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr)
@@ -101,6 +114,9 @@ define i32 @launder_and_load() {
define void @launder_and_ptr_arith() {
; CHECK-LABEL: @launder_and_ptr_arith(
+; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]])
+; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i32, ptr [[VALPTR]], i32 0
; CHECK-NEXT: ret void
;
%valptr = alloca i32, align 4
@@ -140,9 +156,13 @@ end:
define void @partial_promotion_of_alloca() {
; CHECK-LABEL: @partial_promotion_of_alloca(
-; CHECK-NEXT: [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4
-; CHECK-NEXT: [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4
+; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], align 4
+; CHECK-NEXT: [[FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 0
+; CHECK-NEXT: store i32 0, ptr [[FIELD_PTR]], align 4
+; CHECK-NEXT: [[VOLATILE_FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 1
+; CHECK-NEXT: store volatile i32 0, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]]
+; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]])
+; CHECK-NEXT: [[LOAD_VAL:%.*]] = load volatile i32, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]]
; CHECK-NEXT: ret void
;
%struct_ptr = alloca %t, align 4
More information about the llvm-commits
mailing list