Skip to content

Commit 5d9c321

Browse files
Handle scalable store size in MemCpyOptimizer (#118957)
The compiler crashes with an ICE when it tries to create a `memset` with scalable size.
1 parent 516d6ed commit 5d9c321

File tree

2 files changed

+48
-32
lines changed

2 files changed

+48
-32
lines changed

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -787,43 +787,47 @@ bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
787787
// Ensure that the value being stored is something that can be memset'able a
788788
// byte at a time like "0" or "-1" or any width, as well as things like
789789
// 0xA0A0A0A0 and 0.0.
790-
auto *V = SI->getOperand(0);
791-
if (Value *ByteVal = isBytewiseValue(V, DL)) {
792-
if (Instruction *I =
793-
tryMergingIntoMemset(SI, SI->getPointerOperand(), ByteVal)) {
794-
BBI = I->getIterator(); // Don't invalidate iterator.
795-
return true;
796-
}
790+
Value *V = SI->getOperand(0);
791+
Value *ByteVal = isBytewiseValue(V, DL);
792+
if (!ByteVal)
793+
return false;
797794

798-
// If we have an aggregate, we try to promote it to memset regardless
799-
// of opportunity for merging as it can expose optimization opportunities
800-
// in subsequent passes.
801-
auto *T = V->getType();
802-
if (T->isAggregateType()) {
803-
uint64_t Size = DL.getTypeStoreSize(T);
804-
IRBuilder<> Builder(SI);
805-
auto *M = Builder.CreateMemSet(SI->getPointerOperand(), ByteVal, Size,
806-
SI->getAlign());
807-
M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
795+
if (Instruction *I =
796+
tryMergingIntoMemset(SI, SI->getPointerOperand(), ByteVal)) {
797+
BBI = I->getIterator(); // Don't invalidate iterator.
798+
return true;
799+
}
800+
801+
// If we have an aggregate, we try to promote it to memset regardless
802+
// of opportunity for merging as it can expose optimization opportunities
803+
// in subsequent passes.
804+
auto *T = V->getType();
805+
if (!T->isAggregateType())
806+
return false;
808807

809-
LLVM_DEBUG(dbgs() << "Promoting " << *SI << " to " << *M << "\n");
808+
TypeSize Size = DL.getTypeStoreSize(T);
809+
if (Size.isScalable())
810+
return false;
810811

811-
// The newly inserted memset is immediately overwritten by the original
812-
// store, so we do not need to rename uses.
813-
auto *StoreDef = cast<MemoryDef>(MSSA->getMemoryAccess(SI));
814-
auto *NewAccess = MSSAU->createMemoryAccessBefore(M, nullptr, StoreDef);
815-
MSSAU->insertDef(cast<MemoryDef>(NewAccess), /*RenameUses=*/false);
812+
IRBuilder<> Builder(SI);
813+
auto *M = Builder.CreateMemSet(SI->getPointerOperand(), ByteVal, Size,
814+
SI->getAlign());
815+
M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);
816816

817-
eraseInstruction(SI);
818-
NumMemSetInfer++;
817+
LLVM_DEBUG(dbgs() << "Promoting " << *SI << " to " << *M << "\n");
819818

820-
// Make sure we do not invalidate the iterator.
821-
BBI = M->getIterator();
822-
return true;
823-
}
824-
}
819+
// The newly inserted memset is immediately overwritten by the original
820+
// store, so we do not need to rename uses.
821+
auto *StoreDef = cast<MemoryDef>(MSSA->getMemoryAccess(SI));
822+
auto *NewAccess = MSSAU->createMemoryAccessBefore(M, nullptr, StoreDef);
823+
MSSAU->insertDef(cast<MemoryDef>(NewAccess), /*RenameUses=*/false);
825824

826-
return false;
825+
eraseInstruction(SI);
826+
NumMemSetInfer++;
827+
828+
// Make sure we do not invalidate the iterator.
829+
BBI = M->getIterator();
830+
return true;
827831
}
828832

829833
bool MemCpyOptPass::processMemSet(MemSetInst *MSI, BasicBlock::iterator &BBI) {

llvm/test/Transforms/MemCpyOpt/vscale-memset.ll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
define void @foo(ptr %p) {
99
; CHECK-LABEL: @foo(
1010
; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[P:%.*]], align 16
11-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <vscale x 16 x i8>, ptr [[P:%.*]], i64 1
11+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <vscale x 16 x i8>, ptr [[P]], i64 1
1212
; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP1]], align 16
1313
; CHECK-NEXT: ret void
1414
;
@@ -18,6 +18,18 @@ define void @foo(ptr %p) {
1818
ret void
1919
}
2020

21+
; Test the compiler does not crash on a store of a scalable aggregate type.
22+
define void @test_no_crash_scalable_agg(ptr %p) {
23+
; CHECK-LABEL: @test_no_crash_scalable_agg(
24+
; CHECK-NEXT: entry:
25+
; CHECK-NEXT: store { <vscale x 16 x i1>, <vscale x 16 x i1> } zeroinitializer, ptr [[P:%.*]], align 2
26+
; CHECK-NEXT: ret void
27+
;
28+
entry:
29+
store { <vscale x 16 x i1>, <vscale x 16 x i1> } zeroinitializer, ptr %p, align 2
30+
ret void
31+
}
32+
2133
; Positive test
2234

2335
define void @memset_vscale_index_zero(ptr %p, i8 %z) {

0 commit comments

Comments
 (0)