[Instcombine] Disable memcpy of alloca bypass for instruction sources

This transformation is fundamentally broken when it comes to dominance,
it just happened to work when the source of the memcpy can be moved into
the place of the alloca. The bug shows up a lot more often since
077bff39d4 allows the source to be a
switch.

It would be possible to check dominance of the source and all its
operands, but that seems very heavy for instcombine.
This commit is contained in:
Benjamin Kramer 2021-04-14 16:37:38 +02:00
parent e3070db0f7
commit cf4161673c
2 changed files with 27 additions and 4 deletions

View File

@ -407,10 +407,9 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
TheSrc, AllocaAlign, DL, &AI, &AC, &DT);
if (AllocaAlign <= SourceAlign &&
isDereferenceableForAllocaSize(TheSrc, &AI, DL) &&
(!isa<Instruction>(TheSrc) || all_of(AI.users(), [&](const User *U) {
return DT.dominates(cast<Instruction>(TheSrc), cast<Instruction>(U));
}))) {
// FIXME: can the dominance restriction be relaxed by sinking instrns?
!isa<Instruction>(TheSrc)) {
// FIXME: Can we sink instructions without violating dominance when TheSrc
// is an instruction instead of a constant or argument?
LLVM_DEBUG(dbgs() << "Found alloca equal to global: " << AI << '\n');
LLVM_DEBUG(dbgs() << " memcpy = " << *Copy << '\n');
unsigned SrcAddrSpace = TheSrc->getType()->getPointerAddressSpace();

View File

@ -31,5 +31,29 @@ define void @test(i8*%out) {
ret void
}
define void @test2() {
; CHECK-LABEL: @test2(
; CHECK-NEXT: bb:
; CHECK-NEXT: [[I:%.*]] = alloca [[T0:%.*]], align 8
; CHECK-NEXT: [[I1:%.*]] = call i32 @func(%t0* undef)
; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[I1]], 2503
; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i8* bitcast (%t0* @g0 to i8*), i8* bitcast (%t0* @g1 to i8*)
; CHECK-NEXT: [[I4:%.*]] = bitcast %t0* [[I]] to i8*
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(16) [[I4]], i8* noundef nonnull align 8 dereferenceable(16) [[I3]], i64 16, i1 false)
; CHECK-NEXT: [[I5:%.*]] = call i32 @func(%t0* nonnull byval([[T0]]) [[I]])
; CHECK-NEXT: unreachable
;
bb:
%i = alloca %t0, align 8
%i1 = call i32 @func(%t0* undef)
%i2 = icmp eq i32 %i1, 2503
%i3 = select i1 %i2, i8* bitcast (%t0* @g0 to i8*), i8* bitcast (%t0* @g1 to i8*)
%i4 = bitcast %t0* %i to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(16) %i4, i8* noundef nonnull align 8 dereferenceable(16) %i3, i64 16, i1 false)
%i5 = call i32 @func(%t0* nonnull byval(%t0) %i)
unreachable
}
declare i32 @func(%t0*)
declare i1 @get_cond()
declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)