Skip to content

Commit 05284a0

Browse files
[SROA] Rewrite invariant group intrinsics after splitting alloca
A miscompilation issue has been addressed with improved handling. Fixes: #105537.
1 parent d4a38c8 commit 05284a0

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3531,8 +3531,19 @@ class AllocaSliceRewriter : public InstVisitor<AllocaSliceRewriter, bool> {
35313531
return true;
35323532
}
35333533

3534-
if (II.isLaunderOrStripInvariantGroup())
3534+
if (II.isLaunderOrStripInvariantGroup()) {
3535+
Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->getType());
3536+
Value *New = nullptr;
3537+
if (II.getIntrinsicID() == Intrinsic::launder_invariant_group)
3538+
New = IRB.CreateLaunderInvariantGroup(AdjustedPtr);
3539+
else if (II.getIntrinsicID() == Intrinsic::strip_invariant_group)
3540+
New = IRB.CreateStripInvariantGroup(AdjustedPtr);
3541+
3542+
New->takeName(&II);
3543+
II.replaceAllUsesWith(New);
3544+
LLVM_DEBUG(dbgs() << " to: " << *New << "\n");
35353545
return true;
3546+
}
35363547

35373548
assert(II.getArgOperand(1) == OldPtr);
35383549
// Lifetime intrinsics are only promotable if they cover the whole alloca.

llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
8181
return false;
8282
} else if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
8383
if (!II->isLifetimeStartOrEnd() && !II->isDroppable() &&
84-
II->getIntrinsicID() != Intrinsic::fake_use)
84+
II->getIntrinsicID() != Intrinsic::fake_use &&
85+
!II->isLaunderOrStripInvariantGroup())
8586
return false;
8687
} else if (const BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
8788
if (!onlyUsedByLifetimeMarkersOrDroppableInsts(BCI))

llvm/test/Transforms/SROA/invariant-group.ll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ define void @partial_promotion_of_alloca() {
142142
; CHECK-LABEL: @partial_promotion_of_alloca(
143143
; CHECK-NEXT: [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4
144144
; CHECK-NEXT: store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4
145+
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR_SROA_2]])
145146
; CHECK-NEXT: [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4
146147
; CHECK-NEXT: ret void
147148
;
@@ -155,6 +156,19 @@ define void @partial_promotion_of_alloca() {
155156
ret void
156157
}
157158

159+
define void @memcpy_after_laundering_alloca(ptr %ptr) {
160+
; CHECK-LABEL: @memcpy_after_laundering_alloca(
161+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca { i64, i64 }, align 8
162+
; CHECK-NEXT: [[LAUNDER:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[ALLOCA]])
163+
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[LAUNDER]], ptr [[PTR:%.*]], i64 16, i1 false)
164+
; CHECK-NEXT: ret void
165+
;
166+
%alloca = alloca { i64, i64 }, align 8
167+
%launder = call ptr @llvm.launder.invariant.group.p0(ptr %alloca)
168+
call void @llvm.memcpy.p0.p0.i64(ptr %launder, ptr %ptr, i64 16, i1 false)
169+
ret void
170+
}
171+
158172
declare void @use(ptr)
159173

160174
!0 = !{}

0 commit comments

Comments
 (0)