blob: b7fb3cc97d66aa413de4e64af6658c7868c97c7f [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes='sroa<aggregate-to-vector>,gvn,instcombine,simplifycfg' -S %s | FileCheck %s
%struct.myint4 = type { i32, i32, i32, i32 }
define dso_local void @foo_flat(ptr noundef %x, i64 %y.coerce0, i64 %y.coerce1, i32 noundef %cond) {
; CHECK-LABEL: define dso_local void @foo_flat(
; CHECK-SAME: ptr noundef [[X:%.*]], i64 [[Y_COERCE0:%.*]], i64 [[Y_COERCE1:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[DOTY_COERCE1:%.*]] = select i1 [[TOBOOL_NOT]], i64 0, i64 [[Y_COERCE1]]
; CHECK-NEXT: [[DOTY_COERCE0:%.*]] = select i1 [[TOBOOL_NOT]], i64 0, i64 [[Y_COERCE0]]
; CHECK-NEXT: store i64 [[DOTY_COERCE0]], ptr [[X]], align 16
; CHECK-NEXT: [[X_REPACK7:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 8
; CHECK-NEXT: store i64 [[DOTY_COERCE1]], ptr [[X_REPACK7]], align 8
; CHECK-NEXT: ret void
;
entry:
%y = alloca %struct.myint4, align 16
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.myint4, align 16
%zero = alloca %struct.myint4, align 16
%data = alloca %struct.myint4, align 16
%0 = getelementptr inbounds nuw { i64, i64 }, ptr %y, i32 0, i32 0
store i64 %y.coerce0, ptr %0, align 16
%1 = getelementptr inbounds nuw { i64, i64 }, ptr %y, i32 0, i32 1
store i64 %y.coerce1, ptr %1, align 8
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 16 %temp, ptr align 16 %y, i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 16 %zero, i8 0, i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%2 = load i32, ptr %cond.addr, align 4
%tobool = icmp ne i32 %2, 0
br i1 %tobool, label %cond.true, label %cond.false
cond.true:
br label %cond.end
cond.false:
br label %cond.end
cond.end:
%cond1 = phi ptr [ %temp, %cond.true ], [ %zero, %cond.false ]
%whole = load { i64, i64 }, ptr %cond1, align 16
store { i64, i64 } %whole, ptr %data, align 16
%3 = load ptr, ptr %x.addr, align 8
%whole2 = load { i64, i64 }, ptr %data, align 16
store { i64, i64 } %whole2, ptr %3, align 16
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.myint4_base_n = type { i32, i32, i32, i32 }
%struct.myint4_nested = type { %struct.myint4_base_n }
define dso_local void @foo_nested(ptr noundef %x, i64 %y.coerce0, i64 %y.coerce1, i32 noundef %cond) {
; CHECK-LABEL: define dso_local void @foo_nested(
; CHECK-SAME: ptr noundef [[X:%.*]], i64 [[Y_COERCE0:%.*]], i64 [[Y_COERCE1:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[DOTY_COERCE1:%.*]] = select i1 [[TOBOOL_NOT]], i64 0, i64 [[Y_COERCE1]]
; CHECK-NEXT: [[DOTY_COERCE0:%.*]] = select i1 [[TOBOOL_NOT]], i64 0, i64 [[Y_COERCE0]]
; CHECK-NEXT: store i64 [[DOTY_COERCE0]], ptr [[X]], align 16
; CHECK-NEXT: [[X_REPACK7:%.*]] = getelementptr inbounds nuw i8, ptr [[X]], i64 8
; CHECK-NEXT: store i64 [[DOTY_COERCE1]], ptr [[X_REPACK7]], align 8
; CHECK-NEXT: ret void
;
entry:
%y = alloca %struct.myint4_nested, align 16
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.myint4_nested, align 16
%zero = alloca %struct.myint4_nested, align 16
%data = alloca %struct.myint4_nested, align 16
%0 = getelementptr inbounds nuw { i64, i64 }, ptr %y, i32 0, i32 0
store i64 %y.coerce0, ptr %0, align 16
%1 = getelementptr inbounds nuw { i64, i64 }, ptr %y, i32 0, i32 1
store i64 %y.coerce1, ptr %1, align 8
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 16 %temp, ptr align 16 %y, i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 16 %zero, i8 0, i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%2 = load i32, ptr %cond.addr, align 4
%tobool = icmp ne i32 %2, 0
br i1 %tobool, label %cond.true, label %cond.false
cond.true:
br label %cond.end
cond.false:
br label %cond.end
cond.end:
%cond1 = phi ptr [ %temp, %cond.true ], [ %zero, %cond.false ]
%whole = load { i64, i64 }, ptr %cond1, align 16
store { i64, i64 } %whole, ptr %data, align 16
%3 = load ptr, ptr %x.addr, align 8
%whole2 = load { i64, i64 }, ptr %data, align 16
store { i64, i64 } %whole2, ptr %3, align 16
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.padded = type { i32, i8, i32, i8 }
define dso_local void @foo_padded(ptr noundef %x, i32 %a0, i8 %a1,
; CHECK-LABEL: define dso_local void @foo_padded(
; CHECK-SAME: ptr noundef [[X:%.*]], i32 [[A0:%.*]], i8 [[A1:%.*]], i32 [[A2:%.*]], i8 [[A3:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TEMP:%.*]] = alloca [[STRUCT_PADDED:%.*]], align 4
; CHECK-NEXT: [[ZERO:%.*]] = alloca [[STRUCT_PADDED]], align 4
; CHECK-NEXT: [[DATA:%.*]] = alloca [[STRUCT_PADDED]], align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: store i32 [[A0]], ptr [[TEMP]], align 4
; CHECK-NEXT: [[Y_SROA_2_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 4
; CHECK-NEXT: store i8 [[A1]], ptr [[Y_SROA_2_0_TEMP_SROA_IDX]], align 4
; CHECK-NEXT: [[Y_SROA_31_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 8
; CHECK-NEXT: store i32 [[A2]], ptr [[Y_SROA_31_0_TEMP_SROA_IDX]], align 4
; CHECK-NEXT: [[Y_SROA_4_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 12
; CHECK-NEXT: store i8 [[A3]], ptr [[Y_SROA_4_0_TEMP_SROA_IDX]], align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) [[ZERO]], i8 0, i64 16, i1 false)
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[DATA]])
; CHECK-NEXT: [[TOBOOL_PAD_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[ZERO_TEMP:%.*]] = select i1 [[TOBOOL_PAD_NOT]], ptr [[ZERO]], ptr [[TEMP]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) [[DATA]], ptr noundef nonnull align 4 dereferenceable(16) [[ZERO_TEMP]], i64 16, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) [[X]], ptr noundef nonnull align 4 dereferenceable(16) [[DATA]], i64 16, i1 false)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[DATA]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: ret void
;
i32 %a2, i8 %a3,
i32 noundef %cond) {
entry:
%y = alloca %struct.padded, align 4
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.padded, align 4
%zero = alloca %struct.padded, align 4
%data = alloca %struct.padded, align 4
%y_i32_0 = getelementptr inbounds %struct.padded, ptr %y, i32 0, i32 0
store i32 %a0, ptr %y_i32_0, align 4
%y_i8_1 = getelementptr inbounds %struct.padded, ptr %y, i32 0, i32 1
store i8 %a1, ptr %y_i8_1, align 1
%y_i32_2 = getelementptr inbounds %struct.padded, ptr %y, i32 0, i32 2
store i32 %a2, ptr %y_i32_2, align 4
%y_i8_3 = getelementptr inbounds %struct.padded, ptr %y, i32 0, i32 3
store i8 %a3, ptr %y_i8_3, align 1
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %temp, ptr align 4 %y,
i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 4 %zero, i8 0, i64 16, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%c.pad = load i32, ptr %cond.addr, align 4
%tobool.pad = icmp ne i32 %c.pad, 0
br i1 %tobool.pad, label %cond.true.pad, label %cond.false.pad
cond.true.pad:
br label %cond.end.pad
cond.false.pad:
br label %cond.end.pad
cond.end.pad:
%cond1.pad = phi ptr [ %temp, %cond.true.pad ], [ %zero, %cond.false.pad ]
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %data, ptr align 4 %cond1.pad,
i64 16, i1 false)
%xv.pad = load ptr, ptr %x.addr, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %xv.pad, ptr align 4 %data,
i64 16, i1 false)
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.nonhomo = type { i32, i64, i32, i64 }
define dso_local void @foo_nonhomo(ptr noundef %x, i32 %a0, i64 %a1,
; CHECK-LABEL: define dso_local void @foo_nonhomo(
; CHECK-SAME: ptr noundef [[X:%.*]], i32 [[A0:%.*]], i64 [[A1:%.*]], i32 [[A2:%.*]], i64 [[A3:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TEMP:%.*]] = alloca [[STRUCT_NONHOMO:%.*]], align 8
; CHECK-NEXT: [[ZERO:%.*]] = alloca [[STRUCT_NONHOMO]], align 8
; CHECK-NEXT: [[DATA:%.*]] = alloca [[STRUCT_NONHOMO]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: store i32 [[A0]], ptr [[TEMP]], align 8
; CHECK-NEXT: [[Y_SROA_2_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 4
; CHECK-NEXT: store i64 [[A1]], ptr [[Y_SROA_2_0_TEMP_SROA_IDX]], align 4
; CHECK-NEXT: [[Y_SROA_3_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 12
; CHECK-NEXT: store i32 [[A2]], ptr [[Y_SROA_3_0_TEMP_SROA_IDX]], align 4
; CHECK-NEXT: [[Y_SROA_4_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 16
; CHECK-NEXT: store i64 [[A3]], ptr [[Y_SROA_4_0_TEMP_SROA_IDX]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) [[ZERO]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[DATA]])
; CHECK-NEXT: [[TOBOOL_NH_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[ZERO_TEMP:%.*]] = select i1 [[TOBOOL_NH_NOT]], ptr [[ZERO]], ptr [[TEMP]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) [[DATA]], ptr noundef nonnull align 8 dereferenceable(32) [[ZERO_TEMP]], i64 32, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) [[X]], ptr noundef nonnull align 8 dereferenceable(32) [[DATA]], i64 32, i1 false)
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[DATA]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: ret void
;
i32 %a2, i64 %a3,
i32 noundef %cond) {
entry:
%y = alloca %struct.nonhomo, align 8
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.nonhomo, align 8
%zero = alloca %struct.nonhomo, align 8
%data = alloca %struct.nonhomo, align 8
%y_i32_0n = getelementptr inbounds %struct.nonhomo, ptr %y, i32 0, i32 0
store i32 %a0, ptr %y_i32_0n, align 4
%y_i64_1n = getelementptr inbounds %struct.nonhomo, ptr %y, i32 0, i32 1
store i64 %a1, ptr %y_i64_1n, align 8
%y_i32_2n = getelementptr inbounds %struct.nonhomo, ptr %y, i32 0, i32 2
store i32 %a2, ptr %y_i32_2n, align 4
%y_i64_3n = getelementptr inbounds %struct.nonhomo, ptr %y, i32 0, i32 3
store i64 %a3, ptr %y_i64_3n, align 8
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %temp, ptr align 8 %y,
i64 32, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 8 %zero, i8 0, i64 32, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%c.nh = load i32, ptr %cond.addr, align 4
%tobool.nh = icmp ne i32 %c.nh, 0
br i1 %tobool.nh, label %cond.true.nh, label %cond.false.nh
cond.true.nh:
br label %cond.end.nh
cond.false.nh:
br label %cond.end.nh
cond.end.nh:
%cond1.nh = phi ptr [ %temp, %cond.true.nh ], [ %zero, %cond.false.nh ]
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %data, ptr align 8 %cond1.nh,
i64 32, i1 false)
%xv.nh = load ptr, ptr %x.addr, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %xv.nh, ptr align 8 %data,
i64 32, i1 false)
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.i1x4 = type { i1, i1, i1, i1 }
define dso_local void @foo_i1(ptr noundef %x, i64 %dummy0, i64 %dummy1,
; CHECK-LABEL: define dso_local void @foo_i1(
; CHECK-SAME: ptr noundef [[X:%.*]], i64 [[DUMMY0:%.*]], i64 [[DUMMY1:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TEMP:%.*]] = alloca [[STRUCT_I1X4:%.*]], align 1
; CHECK-NEXT: [[ZERO:%.*]] = alloca [[STRUCT_I1X4]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: store i32 0, ptr [[ZERO]], align 1
; CHECK-NEXT: [[TOBOOL_I1_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[ZERO_TEMP:%.*]] = select i1 [[TOBOOL_I1_NOT]], ptr [[ZERO]], ptr [[TEMP]]
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ZERO_TEMP]], align 1
; CHECK-NEXT: store i32 [[TMP0]], ptr [[X]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[ZERO]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: ret void
;
i32 noundef %cond) {
entry:
%y = alloca %struct.i1x4, align 1
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.i1x4, align 1
%zero = alloca %struct.i1x4, align 1
%data = alloca %struct.i1x4, align 1
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 1 %temp, ptr align 1 %y,
i64 4, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 1 %zero, i8 0, i64 4, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%c.i1 = load i32, ptr %cond.addr, align 4
%tobool.i1 = icmp ne i32 %c.i1, 0
br i1 %tobool.i1, label %cond.true.i1, label %cond.false.i1
cond.true.i1:
br label %cond.end.i1
cond.false.i1:
br label %cond.end.i1
cond.end.i1:
%cond1.i1 = phi ptr [ %temp, %cond.true.i1 ], [ %zero, %cond.false.i1 ]
call void @llvm.memcpy.p0.p0.i64(ptr align 1 %data, ptr align 1 %cond1.i1,
i64 4, i1 false)
%xv.i1 = load ptr, ptr %x.addr, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 1 %xv.i1, ptr align 1 %data,
i64 4, i1 false)
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.ptr4 = type { ptr, ptr, ptr, ptr }
define dso_local void @foo_ptr(ptr noundef %x, ptr %p0, ptr %p1,
; CHECK-LABEL: define dso_local void @foo_ptr(
; CHECK-SAME: ptr noundef [[X:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]], i32 noundef [[COND:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TEMP:%.*]] = alloca [[STRUCT_PTR4:%.*]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: store ptr [[P0]], ptr [[TEMP]], align 8
; CHECK-NEXT: [[Y_SROA_2_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 8
; CHECK-NEXT: store ptr [[P1]], ptr [[Y_SROA_2_0_TEMP_SROA_IDX]], align 8
; CHECK-NEXT: [[Y_SROA_3_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 16
; CHECK-NEXT: store ptr [[P2]], ptr [[Y_SROA_3_0_TEMP_SROA_IDX]], align 8
; CHECK-NEXT: [[Y_SROA_4_0_TEMP_SROA_IDX:%.*]] = getelementptr inbounds nuw i8, ptr [[TEMP]], i64 24
; CHECK-NEXT: store ptr [[P3]], ptr [[Y_SROA_4_0_TEMP_SROA_IDX]], align 8
; CHECK-NEXT: [[TOBOOL_PTR_NOT:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: [[DATA_SROA_0_0_COPYLOAD_PRE:%.*]] = load <4 x ptr>, ptr [[TEMP]], align 8
; CHECK-NEXT: [[DATA_SROA_0_0_COPYLOAD:%.*]] = select i1 [[TOBOOL_PTR_NOT]], <4 x ptr> splat (ptr null), <4 x ptr> [[DATA_SROA_0_0_COPYLOAD_PRE]]
; CHECK-NEXT: store <4 x ptr> [[DATA_SROA_0_0_COPYLOAD]], ptr [[X]], align 8
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[TEMP]])
; CHECK-NEXT: ret void
;
ptr %p2, ptr %p3,
i32 noundef %cond) {
entry:
%y = alloca %struct.ptr4, align 8
%x.addr = alloca ptr, align 8
%cond.addr = alloca i32, align 4
%temp = alloca %struct.ptr4, align 8
%zero = alloca %struct.ptr4, align 8
%data = alloca %struct.ptr4, align 8
%y_p0 = getelementptr inbounds %struct.ptr4, ptr %y, i32 0, i32 0
store ptr %p0, ptr %y_p0, align 8
%y_p1 = getelementptr inbounds %struct.ptr4, ptr %y, i32 0, i32 1
store ptr %p1, ptr %y_p1, align 8
%y_p2 = getelementptr inbounds %struct.ptr4, ptr %y, i32 0, i32 2
store ptr %p2, ptr %y_p2, align 8
%y_p3 = getelementptr inbounds %struct.ptr4, ptr %y, i32 0, i32 3
store ptr %p3, ptr %y_p3, align 8
store ptr %x, ptr %x.addr, align 8
store i32 %cond, ptr %cond.addr, align 4
call void @llvm.lifetime.start.p0(ptr %temp)
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %temp, ptr align 8 %y,
i64 32, i1 false)
call void @llvm.lifetime.start.p0(ptr %zero)
call void @llvm.memset.p0.i64(ptr align 8 %zero, i8 0, i64 32, i1 false)
call void @llvm.lifetime.start.p0(ptr %data)
%c.ptr = load i32, ptr %cond.addr, align 4
%tobool.ptr = icmp ne i32 %c.ptr, 0
br i1 %tobool.ptr, label %cond.true.ptr, label %cond.false.ptr
cond.true.ptr:
br label %cond.end.ptr
cond.false.ptr:
br label %cond.end.ptr
cond.end.ptr:
%cond1.ptr = phi ptr [ %temp, %cond.true.ptr ], [ %zero, %cond.false.ptr ]
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %data, ptr align 8 %cond1.ptr,
i64 32, i1 false)
%xv.ptr = load ptr, ptr %x.addr, align 8
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %xv.ptr, ptr align 8 %data,
i64 32, i1 false)
call void @llvm.lifetime.end.p0(ptr %data)
call void @llvm.lifetime.end.p0(ptr %zero)
call void @llvm.lifetime.end.p0(ptr %temp)
ret void
}
%struct.i5x2 = type { i5, i5 }
define void @struct_i5x2_memcpy_into_alloca(ptr %c) {
; CHECK-LABEL: define void @struct_i5x2_memcpy_into_alloca(
; CHECK-SAME: ptr [[C:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[E:%.*]] = alloca [[STRUCT_I5X2:%.*]], align 1
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[E]], ptr align 1 [[C]], i32 2, i1 true)
; CHECK-NEXT: ret void
;
entry:
%e = alloca %struct.i5x2, align 1
call void @llvm.memcpy.p0.p0.i32(ptr align 1 %e, ptr align 1 %c, i32 2, i1 true)
ret void
}
%struct.i32x3 = type { i32, i32, i32 }
define void @struct_i32x3_memcpy_into_alloca(ptr %c) {
; CHECK-LABEL: define void @struct_i32x3_memcpy_into_alloca(
; CHECK-SAME: ptr [[C:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[E_SROA_0:%.*]] = alloca <3 x i32>, align 16
; CHECK-NEXT: [[E_SROA_0_0_COPYLOAD:%.*]] = load volatile <3 x i32>, ptr [[C]], align 4
; CHECK-NEXT: store volatile <3 x i32> [[E_SROA_0_0_COPYLOAD]], ptr [[E_SROA_0]], align 16
; CHECK-NEXT: ret void
;
entry:
%e = alloca %struct.i32x3, align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %e, ptr align 4 %c, i32 12, i1 true)
ret void
}