mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
9c069372df
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 077bff39d46364035a5dcfa32fc69910ad0975d0 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.
60 lines
2.9 KiB
LLVM
60 lines
2.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
; See https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20210412/904154.html
|
|
; When replacing an allocation that is only modified by a memcpy/memmove from
|
|
; a constant whose alignment is equal to or exceeds that of the allocation,
|
|
; we also need to ensure that we actually can replace all uses of an alloca
|
|
; with said constant. This matters because it could be e.g. a select between
|
|
; two constants, that happens after the first use of an alloca.
|
|
|
|
%t0 = type { i8*, i64 }
|
|
|
|
@g0 = external constant %t0
|
|
@g1 = external constant %t0
|
|
define void @test(i8*%out) {
|
|
; CHECK-LABEL: @test(
|
|
; CHECK-NEXT: [[I0:%.*]] = alloca [[T0:%.*]], align 8
|
|
; CHECK-NEXT: [[I1:%.*]] = bitcast %t0* [[I0]] to i8*
|
|
; CHECK-NEXT: [[I2:%.*]] = call i1 @get_cond()
|
|
; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i8* bitcast (%t0* @g0 to i8*), i8* bitcast (%t0* @g1 to i8*)
|
|
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(16) [[I1]], i8* noundef nonnull align 8 dereferenceable(16) [[I3]], i64 16, i1 false)
|
|
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(16) [[OUT:%.*]], i8* noundef nonnull align 8 dereferenceable(16) [[I1]], i64 16, i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%i0 = alloca %t0
|
|
%i1 = bitcast %t0* %i0 to i8*
|
|
%i2 = call i1 @get_cond()
|
|
%i3 = select i1 %i2, i8* bitcast (%t0* @g0 to i8*), i8* bitcast (%t0* @g1 to i8*)
|
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %i1, i8* %i3, i64 16, i1 false)
|
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %out, i8* %i1, i64 16, i1 false)
|
|
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)
|