Skip to content

Commit e818193

Browse files
[DSE] Eliminate zero memset after calloc
Solves PR11896 As noted, this can be improved futher (calloc -> malloc) in some cases. But for know, this is the first step. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D101391
1 parent 39ae5bf commit e818193

File tree

2 files changed

+40
-18
lines changed

2 files changed

+40
-18
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,25 @@ struct DSEState {
17701770
bool storeIsNoop(MemoryDef *Def, const MemoryLocation &DefLoc,
17711771
const Value *DefUO) {
17721772
StoreInst *Store = dyn_cast<StoreInst>(Def->getMemoryInst());
1773+
MemSetInst *MemSet = dyn_cast<MemSetInst>(Def->getMemoryInst());
1774+
Constant *StoredConstant = nullptr;
1775+
if (Store)
1776+
StoredConstant = dyn_cast<Constant>(Store->getOperand(0));
1777+
if (MemSet)
1778+
StoredConstant = dyn_cast<Constant>(MemSet->getValue());
1779+
1780+
if (StoredConstant && StoredConstant->isNullValue()) {
1781+
auto *DefUOInst = dyn_cast<Instruction>(DefUO);
1782+
if (DefUOInst && isCallocLikeFn(DefUOInst, &TLI)) {
1783+
auto *UnderlyingDef = cast<MemoryDef>(MSSA.getMemoryAccess(DefUOInst));
1784+
// If UnderlyingDef is the clobbering access of Def, no instructions
1785+
// between them can modify the memory location.
1786+
auto *ClobberDef =
1787+
MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def);
1788+
return UnderlyingDef == ClobberDef;
1789+
}
1790+
}
1791+
17731792
if (!Store)
17741793
return false;
17751794

@@ -1817,18 +1836,6 @@ struct DSEState {
18171836
}
18181837
}
18191838

1820-
Constant *StoredConstant = dyn_cast<Constant>(Store->getOperand(0));
1821-
if (StoredConstant && StoredConstant->isNullValue()) {
1822-
auto *DefUOInst = dyn_cast<Instruction>(DefUO);
1823-
if (DefUOInst && isCallocLikeFn(DefUOInst, &TLI)) {
1824-
auto *UnderlyingDef = cast<MemoryDef>(MSSA.getMemoryAccess(DefUOInst));
1825-
// If UnderlyingDef is the clobbering access of Def, no instructions
1826-
// between them can modify the memory location.
1827-
auto *ClobberDef =
1828-
MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def);
1829-
return UnderlyingDef == ClobberDef;
1830-
}
1831-
}
18321839
return false;
18331840
}
18341841
};

llvm/test/Transforms/DeadStoreElimination/noop-stores.ll

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,18 +324,27 @@ define i8* @store_zero_after_calloc_inaccessiblememonly() {
324324
define i8* @zero_memset_after_calloc() {
325325
; CHECK-LABEL: @zero_memset_after_calloc(
326326
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
327-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 40000, i1 false)
328327
; CHECK-NEXT: ret i8* [[CALL]]
329328
;
330329
%call = tail call i8* @calloc(i64 10000, i64 4)
331330
call void @llvm.memset.p0i8.i64(i8* %call, i8 0, i64 40000, i1 false)
332331
ret i8* %call
333332
}
334333

334+
define i8* @volatile_zero_memset_after_calloc() {
335+
; CHECK-LABEL: @volatile_zero_memset_after_calloc(
336+
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
337+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 40000, i1 true)
338+
; CHECK-NEXT: ret i8* [[CALL]]
339+
;
340+
%call = tail call i8* @calloc(i64 10000, i64 4)
341+
call void @llvm.memset.p0i8.i64(i8* %call, i8 0, i64 40000, i1 true)
342+
ret i8* %call
343+
}
344+
335345
define i8* @zero_memset_and_store_after_calloc(i8 %v) {
336346
; CHECK-LABEL: @zero_memset_and_store_after_calloc(
337347
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
338-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 40000, i1 false)
339348
; CHECK-NEXT: ret i8* [[CALL]]
340349
;
341350
%call = tail call i8* @calloc(i64 10000, i64 4)
@@ -347,7 +356,6 @@ define i8* @zero_memset_and_store_after_calloc(i8 %v) {
347356
define i8* @partial_zero_memset_after_calloc() {
348357
; CHECK-LABEL: @partial_zero_memset_after_calloc(
349358
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
350-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 20, i1 false)
351359
; CHECK-NEXT: ret i8* [[CALL]]
352360
;
353361
%call = tail call i8* @calloc(i64 10000, i64 4)
@@ -360,7 +368,6 @@ define i8* @partial_zero_memset_and_store_after_calloc(i8 %v) {
360368
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
361369
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 30
362370
; CHECK-NEXT: store i8 [[V:%.*]], i8* [[GEP]], align 1
363-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 20, i1 false)
364371
; CHECK-NEXT: ret i8* [[CALL]]
365372
;
366373
%call = tail call i8* @calloc(i64 10000, i64 4)
@@ -373,7 +380,6 @@ define i8* @partial_zero_memset_and_store_after_calloc(i8 %v) {
373380
define i8* @zero_memset_and_store_with_dyn_index_after_calloc(i8 %v, i64 %idx) {
374381
; CHECK-LABEL: @zero_memset_and_store_with_dyn_index_after_calloc(
375382
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
376-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 0, i64 40000, i1 false)
377383
; CHECK-NEXT: ret i8* [[CALL]]
378384
;
379385
%call = tail call i8* @calloc(i64 10000, i64 4)
@@ -409,6 +415,16 @@ define i8* @zero_memset_after_calloc_inaccessiblememonly() {
409415
ret i8* %call
410416
}
411417

418+
define i8* @cst_nonzero_memset_after_calloc() {
419+
; CHECK-LABEL: @cst_nonzero_memset_after_calloc(
420+
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
421+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL]], i8 1, i64 40000, i1 false)
422+
; CHECK-NEXT: ret i8* [[CALL]]
423+
;
424+
%call = tail call i8* @calloc(i64 10000, i64 4)
425+
call void @llvm.memset.p0i8.i64(i8* %call, i8 1, i64 40000, i1 false)
426+
ret i8* %call
427+
}
412428

413429
define i8* @nonzero_memset_after_calloc(i8 %v) {
414430
; CHECK-LABEL: @nonzero_memset_after_calloc(
@@ -427,7 +443,6 @@ define i8* @nonzero_memset_after_calloc(i8 %v) {
427443
define i8* @memset_pattern16_after_calloc(i8* %pat) {
428444
; CHECK-LABEL: @memset_pattern16_after_calloc(
429445
; CHECK-NEXT: [[CALL:%.*]] = tail call i8* @calloc(i64 10000, i64 4)
430-
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[CALL]], i8 0, i64 40000, i1 false)
431446
; CHECK-NEXT: call void @memset_pattern16(i8* [[CALL]], i8* [[PAT:%.*]], i64 40000)
432447
; CHECK-NEXT: ret i8* [[CALL]]
433448
;

0 commit comments

Comments
 (0)