Skip to content

Commit

Permalink
[InstCombine] remove uses before deleting instructions (PR43723)
Browse files Browse the repository at this point in the history
This is a less ambitious alternative to previous attempts to fix
this bug with:
rG56b2aee1875a
rGef02831f0a4e
rG56b2aee1875a
...because those all failed bot testing with use-after-free or
other problems.

The original crashing/assert problem is still showing up on
various fuzzers, so I've added a new minimal test based on
another one of those failures.

Instead of trying to manage and coordinate the logic in
isAllocSiteRemovable() with the deletion loops, just loosen
the existing code that handles casts and GEP by replacing
with undef to allow other opcodes. That means that no
instructions with uses should assert on deletion, and there
are hopefully no non-obvious sanitizer bugs induced.
  • Loading branch information
rotateright committed Jan 2, 2020
1 parent 324fd59 commit 88fc5fd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
7 changes: 4 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Expand Up @@ -2450,12 +2450,13 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
replaceInstUsesWith(*C,
ConstantInt::get(Type::getInt1Ty(C->getContext()),
C->isFalseWhenEqual()));
} else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I) ||
isa<AddrSpaceCastInst>(I)) {
replaceInstUsesWith(*I, UndefValue::get(I->getType()));
} else if (auto *SI = dyn_cast<StoreInst>(I)) {
for (auto *DII : DIIs)
ConvertDebugDeclareToDebugValue(DII, SI, *DIB);
} else {
// Casts, GEP, or anything else: we're about to delete this instruction,
// so it can not have any valid uses.
replaceInstUsesWith(*I, UndefValue::get(I->getType()));
}
eraseInstFromFunction(*I);
}
Expand Down
42 changes: 42 additions & 0 deletions llvm/test/Transforms/InstCombine/builtin-object-size-ptr.ll
Expand Up @@ -28,6 +28,48 @@ define i32 @foo() #0 {
ret i32 %conv
}

; This used to crash while erasing instructions:
; https://bugs.llvm.org/show_bug.cgi?id=43723

define void @PR43723() {
; CHECK-LABEL: @PR43723(
; CHECK-NEXT: ret void
;
%tab = alloca [10 x i8], align 16
%t0 = bitcast [10 x i8]* %tab to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %t0, i8 9, i64 10, i1 false)
%t1 = call {}* @llvm.invariant.start.p0i8(i64 10, i8* align 16 %t0)
call void @llvm.invariant.end.p0i8({}* %t1, i64 10, i8* align 16 %t0)
ret void

uselistorder i8* %t0, { 1, 0, 2 }
}

define void @unknown_use_of_invariant_start({}** %p) {
; CHECK-LABEL: @unknown_use_of_invariant_start(
; CHECK-NEXT: ret void
;
%tab = alloca [10 x i8], align 16
%t0 = bitcast [10 x i8]* %tab to i8*
call void @llvm.memset.p0i8.i64(i8* align 16 %t0, i8 9, i64 10, i1 false)
%t1 = call {}* @llvm.invariant.start.p0i8(i64 10, i8* align 16 %t0)
call void @llvm.invariant.end.p0i8({}* %t1, i64 10, i8* align 16 %t0)
store {}* %t1, {}** %p
ret void
}

define {}* @minimal_invariant_start_use(i8 %x) {
; CHECK-LABEL: @minimal_invariant_start_use(
; CHECK-NEXT: ret {}* undef
;
%a = alloca i8
%i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
ret {}* %i
}

declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) #2
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #0
declare {}* @llvm.invariant.start.p0i8(i64 immarg, i8* nocapture) #0
declare void @llvm.invariant.end.p0i8({}*, i64 immarg, i8* nocapture) #0

0 comments on commit 88fc5fd

Please sign in to comment.