+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64-p1:32:32:32-p2:16:16:16-n8:16:32:64"
define i32* @combine_redundant_addrspacecast(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_redundant_addrspacecast(
-; CHECK: addrspacecast i32 addrspace(1)* %x to i32*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast i32 addrspace(1)* [[X:%.*]] to i32*
+; CHECK-NEXT: ret i32* [[Z]]
+;
%y = addrspacecast i32 addrspace(1)* %x to i32 addrspace(3)*
%z = addrspacecast i32 addrspace(3)* %y to i32*
ret i32* %z
define <4 x i32*> @combine_redundant_addrspacecast_vector(<4 x i32 addrspace(1)*> %x) nounwind {
; CHECK-LABEL: @combine_redundant_addrspacecast_vector(
-; CHECK: addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32*>
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast <4 x i32 addrspace(1)*> [[X:%.*]] to <4 x i32*>
+; CHECK-NEXT: ret <4 x i32*> [[Z]]
+;
%y = addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32 addrspace(3)*>
%z = addrspacecast <4 x i32 addrspace(3)*> %y to <4 x i32*>
ret <4 x i32*> %z
define float* @combine_redundant_addrspacecast_types(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_redundant_addrspacecast_types(
-; CHECK-NEXT: bitcast i32 addrspace(1)* %x to float addrspace(1)*
-; CHECK-NEXT: addrspacecast float addrspace(1)* %1 to float*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 addrspace(1)* [[X:%.*]] to float addrspace(1)*
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float*
+; CHECK-NEXT: ret float* [[Z]]
+;
%y = addrspacecast i32 addrspace(1)* %x to i32 addrspace(3)*
%z = addrspacecast i32 addrspace(3)* %y to float*
ret float* %z
define <4 x float*> @combine_redundant_addrspacecast_types_vector(<4 x i32 addrspace(1)*> %x) nounwind {
; CHECK-LABEL: @combine_redundant_addrspacecast_types_vector(
-; CHECK-NEXT: bitcast <4 x i32 addrspace(1)*> %x to <4 x float addrspace(1)*>
-; CHECK-NEXT: addrspacecast <4 x float addrspace(1)*> %1 to <4 x float*>
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32 addrspace(1)*> [[X:%.*]] to <4 x float addrspace(1)*>
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast <4 x float addrspace(1)*> [[TMP1]] to <4 x float*>
+; CHECK-NEXT: ret <4 x float*> [[Z]]
+;
%y = addrspacecast <4 x i32 addrspace(1)*> %x to <4 x i32 addrspace(3)*>
%z = addrspacecast <4 x i32 addrspace(3)*> %y to <4 x float*>
ret <4 x float*> %z
define float addrspace(2)* @combine_addrspacecast_bitcast_1(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_addrspacecast_bitcast_1(
-; CHECK-NEXT: bitcast i32 addrspace(1)* %x to float addrspace(1)*
-; CHECK-NEXT: addrspacecast float addrspace(1)* %1 to float addrspace(2)*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 addrspace(1)* [[X:%.*]] to float addrspace(1)*
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float addrspace(2)*
+; CHECK-NEXT: ret float addrspace(2)* [[Z]]
+;
%y = addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)*
%z = bitcast i32 addrspace(2)* %y to float addrspace(2)*
ret float addrspace(2)* %z
define i32 addrspace(2)* @combine_addrspacecast_bitcast_2(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_addrspacecast_bitcast_2(
-; CHECK: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast i32 addrspace(1)* [[X:%.*]] to i32 addrspace(2)*
+; CHECK-NEXT: ret i32 addrspace(2)* [[Z]]
+;
%y = addrspacecast i32 addrspace(1)* %x to float addrspace(2)*
%z = bitcast float addrspace(2)* %y to i32 addrspace(2)*
ret i32 addrspace(2)* %z
define i32 addrspace(2)* @combine_bitcast_addrspacecast_1(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_bitcast_addrspacecast_1(
-; CHECK: addrspacecast i32 addrspace(1)* %x to i32 addrspace(2)*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast i32 addrspace(1)* [[X:%.*]] to i32 addrspace(2)*
+; CHECK-NEXT: ret i32 addrspace(2)* [[Z]]
+;
%y = bitcast i32 addrspace(1)* %x to i8 addrspace(1)*
%z = addrspacecast i8 addrspace(1)* %y to i32 addrspace(2)*
ret i32 addrspace(2)* %z
define float addrspace(2)* @combine_bitcast_addrspacecast_2(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_bitcast_addrspacecast_2(
-; CHECK: bitcast i32 addrspace(1)* %x to float addrspace(1)*
-; CHECK: addrspacecast float addrspace(1)* %1 to float addrspace(2)*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 addrspace(1)* [[X:%.*]] to float addrspace(1)*
+; CHECK-NEXT: [[Z:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float addrspace(2)*
+; CHECK-NEXT: ret float addrspace(2)* [[Z]]
+;
%y = bitcast i32 addrspace(1)* %x to i8 addrspace(1)*
%z = addrspacecast i8 addrspace(1)* %y to float addrspace(2)*
ret float addrspace(2)* %z
define float addrspace(2)* @combine_addrspacecast_types(i32 addrspace(1)* %x) nounwind {
; CHECK-LABEL: @combine_addrspacecast_types(
-; CHECK-NEXT: bitcast i32 addrspace(1)* %x to float addrspace(1)*
-; CHECK-NEXT: addrspacecast float addrspace(1)* %1 to float addrspace(2)*
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 addrspace(1)* [[X:%.*]] to float addrspace(1)*
+; CHECK-NEXT: [[Y:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float addrspace(2)*
+; CHECK-NEXT: ret float addrspace(2)* [[Y]]
+;
%y = addrspacecast i32 addrspace(1)* %x to float addrspace(2)*
ret float addrspace(2)* %y
}
define <4 x float addrspace(2)*> @combine_addrspacecast_types_vector(<4 x i32 addrspace(1)*> %x) nounwind {
; CHECK-LABEL: @combine_addrspacecast_types_vector(
-; CHECK-NEXT: bitcast <4 x i32 addrspace(1)*> %x to <4 x float addrspace(1)*>
-; CHECK-NEXT: addrspacecast <4 x float addrspace(1)*> %1 to <4 x float addrspace(2)*>
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32 addrspace(1)*> [[X:%.*]] to <4 x float addrspace(1)*>
+; CHECK-NEXT: [[Y:%.*]] = addrspacecast <4 x float addrspace(1)*> [[TMP1]] to <4 x float addrspace(2)*>
+; CHECK-NEXT: ret <4 x float addrspace(2)*> [[Y]]
+;
%y = addrspacecast <4 x i32 addrspace(1)*> %x to <4 x float addrspace(2)*>
ret <4 x float addrspace(2)*> %y
}
define <vscale x 4 x float addrspace(2)*> @combine_addrspacecast_types_scalevector(<vscale x 4 x i32 addrspace(1)*> %x) nounwind {
; CHECK-LABEL: @combine_addrspacecast_types_scalevector(
-; CHECK-NEXT: bitcast <vscale x 4 x i32 addrspace(1)*> %x to <vscale x 4 x float addrspace(1)*>
-; CHECK-NEXT: addrspacecast <vscale x 4 x float addrspace(1)*> %1 to <vscale x 4 x float addrspace(2)*>
-; CHECK-NEXT: ret
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <vscale x 4 x i32 addrspace(1)*> [[X:%.*]] to <vscale x 4 x float addrspace(1)*>
+; CHECK-NEXT: [[Y:%.*]] = addrspacecast <vscale x 4 x float addrspace(1)*> [[TMP1]] to <vscale x 4 x float addrspace(2)*>
+; CHECK-NEXT: ret <vscale x 4 x float addrspace(2)*> [[Y]]
+;
%y = addrspacecast <vscale x 4 x i32 addrspace(1)*> %x to <vscale x 4 x float addrspace(2)*>
ret <vscale x 4 x float addrspace(2)*> %y
}
define i32 @canonicalize_addrspacecast([16 x i32] addrspace(1)* %arr) {
; CHECK-LABEL: @canonicalize_addrspacecast(
-; CHECK-NEXT: getelementptr [16 x i32], [16 x i32] addrspace(1)* %arr, i32 0, i32 0
-; CHECK-NEXT: addrspacecast i32 addrspace(1)* %{{[a-zA-Z0-9]+}} to i32*
-; CHECK-NEXT: load i32, i32*
-; CHECK-NEXT: ret i32
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [16 x i32], [16 x i32] addrspace(1)* [[ARR:%.*]], i32 0, i32 0
+; CHECK-NEXT: [[P:%.*]] = addrspacecast i32 addrspace(1)* [[TMP1]] to i32*
+; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 4
+; CHECK-NEXT: ret i32 [[V]]
+;
%p = addrspacecast [16 x i32] addrspace(1)* %arr to i32*
%v = load i32, i32* %p
ret i32 %v
declare void @foo(i8*) nounwind
; A copy from a constant addrspacecast'ed global
-; CHECK-LABEL: @memcpy_addrspacecast(
-; CHECK-NOT: call void @llvm.memcpy
define i32 @memcpy_addrspacecast() nounwind {
+; CHECK-LABEL: @memcpy_addrspacecast(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
+; CHECK: loop.body:
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP_BODY]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_INC:%.*]], [[LOOP_BODY]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[I]] to i16
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, i8 addrspace(2)* getelementptr inbounds ([60 x i8], [60 x i8] addrspace(2)* @const_array, i16 0, i16 4), i16 [[TMP0]]
+; CHECK-NEXT: [[LOAD:%.*]] = load i8, i8 addrspace(2)* [[PTR]], align 1
+; CHECK-NEXT: [[EXT:%.*]] = zext i8 [[LOAD]] to i32
+; CHECK-NEXT: [[SUM_INC]] = add i32 [[SUM]], [[EXT]]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
+; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[I]], 48
+; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[LOOP_BODY]]
+; CHECK: end:
+; CHECK-NEXT: ret i32 [[SUM_INC]]
+;
entry:
%alloca = alloca i8, i32 48
call void @llvm.memcpy.p0i8.p1i8.i32(i8* align 4 %alloca, i8 addrspace(1)* align 4 addrspacecast (i8 addrspace(2)* getelementptr inbounds ([60 x i8], [60 x i8] addrspace(2)* @const_array, i16 0, i16 4) to i8 addrspace(1)*), i32 48, i1 false) nounwind
ret i32 %sum.inc
}
-; CHECK-LABEL: @constant_fold_null(
-; CHECK: i32 addrspace(3)* null to i32 addrspace(4)*
define void @constant_fold_null() #0 {
+; CHECK-LABEL: @constant_fold_null(
+; CHECK-NEXT: store i32 7, i32 addrspace(4)* addrspacecast (i32 addrspace(3)* null to i32 addrspace(4)*), align 4
+; CHECK-NEXT: ret void
+;
%cast = addrspacecast i32 addrspace(3)* null to i32 addrspace(4)*
store i32 7, i32 addrspace(4)* %cast
ret void
}
-; CHECK-LABEL: @constant_fold_undef(
-; CHECK: ret i32 addrspace(4)* undef
define i32 addrspace(4)* @constant_fold_undef() #0 {
+; CHECK-LABEL: @constant_fold_undef(
+; CHECK-NEXT: ret i32 addrspace(4)* undef
+;
%cast = addrspacecast i32 addrspace(3)* undef to i32 addrspace(4)*
ret i32 addrspace(4)* %cast
}
-; CHECK-LABEL: @constant_fold_null_vector(
-; CHECK: addrspacecast (<4 x i32 addrspace(3)*> zeroinitializer to <4 x i32 addrspace(4)*>)
define <4 x i32 addrspace(4)*> @constant_fold_null_vector() #0 {
+; CHECK-LABEL: @constant_fold_null_vector(
+; CHECK-NEXT: ret <4 x i32 addrspace(4)*> addrspacecast (<4 x i32 addrspace(3)*> zeroinitializer to <4 x i32 addrspace(4)*>)
+;
%cast = addrspacecast <4 x i32 addrspace(3)*> zeroinitializer to <4 x i32 addrspace(4)*>
ret <4 x i32 addrspace(4)*> %cast
}
-; CHECK-LABEL: @constant_fold_inttoptr(
-; CHECK: addrspacecast (i32 addrspace(3)* inttoptr (i32 -1 to i32 addrspace(3)*) to i32 addrspace(4)*)
define void @constant_fold_inttoptr() #0 {
+; CHECK-LABEL: @constant_fold_inttoptr(
+; CHECK-NEXT: store i32 7, i32 addrspace(4)* addrspacecast (i32 addrspace(3)* inttoptr (i32 -1 to i32 addrspace(3)*) to i32 addrspace(4)*), align 4
+; CHECK-NEXT: ret void
+;
%cast = addrspacecast i32 addrspace(3)* inttoptr (i32 -1 to i32 addrspace(3)*) to i32 addrspace(4)*
store i32 7, i32 addrspace(4)* %cast
ret void
}
-; CHECK-LABEL: @constant_fold_gep_inttoptr(
-; CHECK: addrspacecast (i32 addrspace(3)* inttoptr (i64 1274 to i32 addrspace(3)*) to i32 addrspace(4)*)
define void @constant_fold_gep_inttoptr() #0 {
+; CHECK-LABEL: @constant_fold_gep_inttoptr(
+; CHECK-NEXT: store i32 7, i32 addrspace(4)* addrspacecast (i32 addrspace(3)* inttoptr (i64 1274 to i32 addrspace(3)*) to i32 addrspace(4)*), align 4
+; CHECK-NEXT: ret void
+;
%k = inttoptr i32 1234 to i32 addrspace(3)*
%gep = getelementptr i32, i32 addrspace(3)* %k, i32 10
%cast = addrspacecast i32 addrspace(3)* %gep to i32 addrspace(4)*
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -instcombine -instcombine-infinite-loop-threshold=3 -S < %s | FileCheck %s
%struct1 = type { %struct2*, i32, i32, i32 }
%struct4 = type { %struct2, %struct2 }
define i32 @test1(%struct1* %dm, i1 %tmp4, i64 %tmp9, i64 %tmp19) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT1:%.*]], %struct1* [[DM:%.*]], i64 0, i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = load %struct2*, %struct2** [[TMP]], align 8
+; CHECK-NEXT: br i1 [[TMP4:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT2:%.*]], %struct2* [[TMP1]], i64 [[TMP9:%.*]], i32 0
+; CHECK-NEXT: store i32 0, i32* [[TMP11]], align 4
+; CHECK-NEXT: br label [[BB3:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT2]], %struct2* [[TMP1]], i64 [[TMP19:%.*]], i32 0
+; CHECK-NEXT: store i32 0, i32* [[TMP21]], align 4
+; CHECK-NEXT: br label [[BB3]]
+; CHECK: bb3:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[TMP9]], [[BB1]] ], [ [[TMP19]], [[BB2]] ]
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT2]], %struct2* [[TMP1]], i64 [[TMP0]], i32 1
+; CHECK-NEXT: [[TMP25:%.*]] = load i32, i32* [[TMP24]], align 4
+; CHECK-NEXT: ret i32 [[TMP25]]
+;
bb:
%tmp = getelementptr inbounds %struct1, %struct1* %dm, i64 0, i32 0
%tmp1 = load %struct2*, %struct2** %tmp, align 8
%tmp24 = getelementptr inbounds %struct2, %struct2* %phi, i64 0, i32 1
%tmp25 = load i32, i32* %tmp24, align 4
ret i32 %tmp25
-
-; CHECK-LABEL: @test1(
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %tmp9, i32 0
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %tmp19, i32 0
-; CHECK: %[[PHI:[0-9A-Za-z]+]] = phi i64 [ %tmp9, %bb1 ], [ %tmp19, %bb2 ]
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %[[PHI]], i32 1
-
}
define i32 @test2(%struct1* %dm, i1 %tmp4, i64 %tmp9, i64 %tmp19) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT1:%.*]], %struct1* [[DM:%.*]], i64 0, i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = load %struct2*, %struct2** [[TMP]], align 8
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT2:%.*]], %struct2* [[TMP1]], i64 [[TMP9:%.*]], i32 0
+; CHECK-NEXT: store i32 0, i32* [[TMP11]], align 4
+; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT2]], %struct2* [[TMP1]], i64 [[TMP19:%.*]], i32 0
+; CHECK-NEXT: store i32 0, i32* [[TMP21]], align 4
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT2]], %struct2* [[TMP1]], i64 [[TMP9]], i32 1
+; CHECK-NEXT: [[TMP25:%.*]] = load i32, i32* [[TMP24]], align 4
+; CHECK-NEXT: ret i32 [[TMP25]]
+;
bb:
%tmp = getelementptr inbounds %struct1, %struct1* %dm, i64 0, i32 0
%tmp1 = load %struct2*, %struct2** %tmp, align 8
%tmp24 = getelementptr inbounds %struct2, %struct2* %tmp10, i64 0, i32 1
%tmp25 = load i32, i32* %tmp24, align 4
ret i32 %tmp25
-
-; CHECK-LABEL: @test2(
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %tmp9, i32 0
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %tmp19, i32 0
-; CHECK: getelementptr inbounds %struct2, %struct2* %tmp1, i64 %tmp9, i32 1
}
; Check that instcombine doesn't insert GEPs before landingpad.
define i32 @test3(%struct3* %dm, i1 %tmp4, i64 %tmp9, i64 %tmp19, i64 %tmp20, i64 %tmp21) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br i1 [[TMP4:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT3:%.*]], %struct3* [[DM:%.*]], i64 [[TMP19:%.*]], i32 1, i32 0, i32 0
+; CHECK-NEXT: store i32 0, i32* [[TMP11]], align 4
+; CHECK-NEXT: br label [[BB3:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT3]], %struct3* [[DM]], i64 [[TMP20:%.*]], i32 1, i32 0, i32 1
+; CHECK-NEXT: store i32 0, i32* [[TMP12]], align 4
+; CHECK-NEXT: br label [[BB3]]
+; CHECK: bb3:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[TMP19]], [[BB1]] ], [ [[TMP20]], [[BB2]] ]
+; CHECK-NEXT: [[TMP22:%.*]] = invoke i32 @foo1(i32 11)
+; CHECK-NEXT: to label [[BB4:%.*]] unwind label [[BB5:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: ret i32 0
+; CHECK: bb5:
+; CHECK-NEXT: [[TMP27:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT3]], %struct3* [[DM]], i64 [[TMP0]], i32 1
+; CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT4:%.*]], %struct4* [[TMP1]], i64 [[TMP21:%.*]], i32 1, i32 1
+; CHECK-NEXT: [[TMP25:%.*]] = load i32, i32* [[TMP35]], align 4
+; CHECK-NEXT: ret i32 [[TMP25]]
+;
bb:
%tmp = getelementptr inbounds %struct3, %struct3* %dm, i64 0
br i1 %tmp4, label %bb1, label %bb2
%tmp35 = getelementptr inbounds %struct2, %struct2* %tmp34, i64 0, i32 1
%tmp25 = load i32, i32* %tmp35, align 4
ret i32 %tmp25
-
-; CHECK-LABEL: @test3(
-; CHECK: bb5:
-; CHECK-NEXT: {{.*}}landingpad { i8*, i32 }
}
@_ZTIi = external constant i8*
; back-edge.
define i8* @test4(i32 %value, i8* %buffer) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[VALUE:%.*]], 127
+; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]]
+; CHECK: loop.header:
+; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
+; CHECK: loop.body:
+; CHECK-NEXT: [[BUFFER_PN:%.*]] = phi i8* [ [[BUFFER:%.*]], [[LOOP_HEADER]] ], [ [[LOOPPTR:%.*]], [[LOOP_BODY]] ]
+; CHECK-NEXT: [[NEWVAL:%.*]] = phi i32 [ [[VALUE]], [[LOOP_HEADER]] ], [ [[SHR:%.*]], [[LOOP_BODY]] ]
+; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds i8, i8* [[BUFFER_PN]], i64 1
+; CHECK-NEXT: [[SHR]] = lshr i32 [[NEWVAL]], 7
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[NEWVAL]], 16383
+; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]
+; CHECK: loop.exit:
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8* [ [[LOOPPTR]], [[LOOP_EXIT]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 2
+; CHECK-NEXT: ret i8* [[INCPTR3]]
+;
entry:
%incptr = getelementptr inbounds i8, i8* %buffer, i64 1
%cmp = icmp ugt i32 %value, 127
%ptr2 = phi i8* [ %exitptr, %loop.exit ], [ %incptr, %entry ]
%incptr3 = getelementptr inbounds i8, i8* %ptr2, i64 1
ret i8* %incptr3
-
-; CHECK-LABEL: @test4(
-; CHECK: loop.body:
-; CHECK: getelementptr{{.*}}i64 1
-; CHECK: exit:
}
@.str.4 = external unnamed_addr constant [100 x i8], align 1
; Instcombine shouldn't add new PHI nodes while folding GEPs if that will leave
; old PHI nodes behind as this is not clearly beneficial.
-; CHECK-LABEL: @test5(
define void @test5(i16 *%idx, i8 **%in) #0 {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** [[IN:%.*]], align 8
+; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 1
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[INCDEC_PTR]], align 1
+; CHECK-NEXT: [[CMP23:%.*]] = icmp eq i8 [[TMP1]], 54
+; CHECK-NEXT: br i1 [[CMP23]], label [[WHILE_COND:%.*]], label [[IF_THEN_25:%.*]]
+; CHECK: if.then.25:
+; CHECK-NEXT: call void @g(i8* getelementptr inbounds ([100 x i8], [100 x i8]* @.str.4, i64 0, i64 0))
+; CHECK-NEXT: br label [[WHILE_COND]]
+; CHECK: while.cond:
+; CHECK-NEXT: [[PTR:%.*]] = phi i8* [ [[INCDEC_PTR]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR32:%.*]], [[WHILE_BODY:%.*]] ], [ [[INCDEC_PTR]], [[IF_THEN_25]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[PTR]], align 1
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[TMP2]], 64
+; CHECK-NEXT: [[LNOT:%.*]] = icmp eq i8 [[AND]], 0
+; CHECK-NEXT: br i1 [[LNOT]], label [[WHILE_BODY]], label [[WHILE_COND_33:%.*]]
+; CHECK: while.body:
+; CHECK-NEXT: [[INCDEC_PTR32]] = getelementptr inbounds i8, i8* [[PTR]], i64 1
+; CHECK-NEXT: br label [[WHILE_COND]]
+; CHECK: while.cond.33:
+; CHECK-NEXT: [[INCDEC_PTR34:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 1
+; CHECK-NEXT: br label [[WHILE_COND_57:%.*]]
+; CHECK: while.cond.57:
+; CHECK-NEXT: [[TMP3:%.*]] = load i8, i8* [[INCDEC_PTR34]], align 1
+; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i64
+; CHECK-NEXT: [[ARRAYIDX61:%.*]] = getelementptr inbounds i16, i16* [[IDX:%.*]], i64 [[TMP4]]
+; CHECK-NEXT: [[TMP5:%.*]] = load i16, i16* [[ARRAYIDX61]], align 2
+; CHECK-NEXT: [[AND63:%.*]] = and i16 [[TMP5]], 2048
+; CHECK-NEXT: [[TOBOOL64:%.*]] = icmp eq i16 [[AND63]], 0
+; CHECK-NEXT: br i1 [[TOBOOL64]], label [[WHILE_COND_73:%.*]], label [[WHILE_COND_57]]
+; CHECK: while.cond.73:
+; CHECK-NEXT: br label [[WHILE_COND_73]]
+;
entry:
%0 = load i8*, i8** %in
%incdec.ptr = getelementptr inbounds i8, i8* %0, i32 1
br label %while.cond
while.cond:
-; CHECK-LABEL: while.cond
-; CHECK-NOT: phi i8* [ %0, %entry ], [ %Ptr, %while.body ], [ %0, %if.then.25 ]
%Ptr = phi i8* [ %incdec.ptr, %entry ], [ %incdec.ptr32, %while.body], [%incdec.ptr, %if.then.25 ]
%2 = load i8, i8* %Ptr
%and = and i8 %2, 64
while.cond.73:
br label %while.cond.73
-
}
declare void @g(i8*)
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-i64:64-f80:128-n8:16:32:64"
declare i32 @A.foo(%A* nocapture %this)
define void @storeA(%A* %a.ptr) {
-; CHECK-LABEL: storeA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr %A, %A* %a.ptr, i64 0, i32 0
-; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[A:%.*]], %A* [[A_PTR:%.*]], i64 0, i32 0
+; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: ret void
+;
store %A { %A__vtbl* @A__vtblZ }, %A* %a.ptr, align 8
ret void
}
define void @storeB(%B* %b.ptr) {
-; CHECK-LABEL: storeB
-; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0
-; CHECK-NEXT: store i8* null, i8** [[GEP1]], align 8
-; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1
-; CHECK-NEXT: store i64 42, i64* [[GEP2]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeB(
+; CHECK-NEXT: [[B_PTR_REPACK:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
+; CHECK-NEXT: store i8* null, i8** [[B_PTR_REPACK]], align 8
+; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
+; CHECK-NEXT: store i64 42, i64* [[B_PTR_REPACK1]], align 8
+; CHECK-NEXT: ret void
+;
store %B { i8* null, i64 42 }, %B* %b.ptr, align 8
ret void
}
define void @storeStructOfA({ %A }* %sa.ptr) {
-; CHECK-LABEL: storeStructOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0
-; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeStructOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
+; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: ret void
+;
store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8
ret void
}
define void @storeArrayOfA([1 x %A]* %aa.ptr) {
-; CHECK-LABEL: storeArrayOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr [1 x %A], [1 x %A]* %aa.ptr, i64 0, i64 0, i32 0
-; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeArrayOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [1 x %A], [1 x %A]* [[AA_PTR:%.*]], i64 0, i64 0, i32 0
+; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: ret void
+;
store [1 x %A] [%A { %A__vtbl* @A__vtblZ }], [1 x %A]* %aa.ptr, align 8
ret void
}
+; UTC_ARGS: --disable
define void @storeLargeArrayOfA([2000 x %A]* %aa.ptr) {
-; CHECK-LABEL: storeLargeArrayOfA
-; CHECK-NEXT: store [2000 x %A]
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeLargeArrayOfA(
+; CHECK-NEXT: store [2000 x %A]
+; CHECK-NEXT: ret void
+;
%i1 = insertvalue [2000 x %A] undef, %A { %A__vtbl* @A__vtblZ }, 1
store [2000 x %A] %i1, [2000 x %A]* %aa.ptr, align 8
ret void
}
+; UTC_ARGS: --enable
define void @storeStructOfArrayOfA({ [1 x %A] }* %saa.ptr) {
-; CHECK-LABEL: storeStructOfArrayOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr { [1 x %A] }, { [1 x %A] }* %saa.ptr, i64 0, i32 0, i64 0, i32 0
-; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeStructOfArrayOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [1 x %A] }, { [1 x %A] }* [[SAA_PTR:%.*]], i64 0, i32 0, i64 0, i32 0
+; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: ret void
+;
store { [1 x %A] } { [1 x %A] [%A { %A__vtbl* @A__vtblZ }] }, { [1 x %A] }* %saa.ptr, align 8
ret void
}
define void @storeArrayOfB([2 x %B]* %ab.ptr, [2 x %B] %ab) {
-; CHECK-LABEL: storeArrayOfB
-; CHECK-NEXT: [[EVB0:%[a-z0-9\.]+]] = extractvalue [2 x %B] %ab, 0
-; CHECK-NEXT: [[GEP0:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 0
-; CHECK-NEXT: [[EV0:%[a-z0-9\.]+]] = extractvalue %B [[EVB0]], 0
-; CHECK-NEXT: store i8* [[EV0]], i8** [[GEP0]], align 8
-; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 1
-; CHECK-NEXT: [[EV1:%[a-z0-9\.]+]] = extractvalue %B [[EVB0]], 1
-; CHECK-NEXT: store i64 [[EV1]], i64* [[GEP1]], align 8
-; CHECK-NEXT: [[EVB1:%[a-z0-9\.]+]] = extractvalue [2 x %B] %ab, 1
-; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 0
-; CHECK-NEXT: [[EV2:%[a-z0-9\.]+]] = extractvalue %B [[EVB1]], 0
-; CHECK-NEXT: store i8* [[EV2]], i8** [[GEP2]], align 8
-; CHECK-NEXT: [[GEP3:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 1
-; CHECK-NEXT: [[EV3:%[a-z0-9\.]+]] = extractvalue %B [[EVB1]], 1
-; CHECK-NEXT: store i64 [[EV3]], i64* [[GEP3]], align 8
-; CHECK-NEXT: ret void
+; CHECK-LABEL: @storeArrayOfB(
+; CHECK-NEXT: [[AB_ELT:%.*]] = extractvalue [2 x %B] [[AB:%.*]], 0
+; CHECK-NEXT: [[AB_PTR_REPACK_REPACK:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR:%.*]], i64 0, i64 0, i32 0
+; CHECK-NEXT: [[AB_ELT_ELT:%.*]] = extractvalue [[B:%.*]] [[AB_ELT]], 0
+; CHECK-NEXT: store i8* [[AB_ELT_ELT]], i8** [[AB_PTR_REPACK_REPACK]], align 8
+; CHECK-NEXT: [[AB_PTR_REPACK_REPACK3:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 0, i32 1
+; CHECK-NEXT: [[AB_ELT_ELT4:%.*]] = extractvalue [[B]] [[AB_ELT]], 1
+; CHECK-NEXT: store i64 [[AB_ELT_ELT4]], i64* [[AB_PTR_REPACK_REPACK3]], align 8
+; CHECK-NEXT: [[AB_ELT2:%.*]] = extractvalue [2 x %B] [[AB]], 1
+; CHECK-NEXT: [[AB_PTR_REPACK1_REPACK:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 0
+; CHECK-NEXT: [[AB_ELT2_ELT:%.*]] = extractvalue [[B]] [[AB_ELT2]], 0
+; CHECK-NEXT: store i8* [[AB_ELT2_ELT]], i8** [[AB_PTR_REPACK1_REPACK]], align 8
+; CHECK-NEXT: [[AB_PTR_REPACK1_REPACK5:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 1
+; CHECK-NEXT: [[AB_ELT2_ELT6:%.*]] = extractvalue [[B]] [[AB_ELT2]], 1
+; CHECK-NEXT: store i64 [[AB_ELT2_ELT6]], i64* [[AB_PTR_REPACK1_REPACK5]], align 8
+; CHECK-NEXT: ret void
+;
store [2 x %B] %ab, [2 x %B]* %ab.ptr, align 8
ret void
}
define %A @loadA(%A* %a.ptr) {
-; CHECK-LABEL: loadA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr %A, %A* %a.ptr, i64 0, i32 0
-; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: [[IV:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0
-; CHECK-NEXT: ret %A [[IV]]
+; CHECK-LABEL: @loadA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[A:%.*]], %A* [[A_PTR:%.*]], i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[A]] undef, %A__vtbl* [[DOTUNPACK]], 0
+; CHECK-NEXT: ret [[A]] [[TMP2]]
+;
%1 = load %A, %A* %a.ptr, align 8
ret %A %1
}
define %B @loadB(%B* %b.ptr) {
-; CHECK-LABEL: loadB
-; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0
-; CHECK-NEXT: [[LOAD1:%[a-z0-9\.]+]] = load i8*, i8** [[GEP1]], align 8
-; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD1]], 0
-; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1
-; CHECK-NEXT: [[LOAD2:%[a-z0-9\.]+]] = load i64, i64* [[GEP2]], align 8
-; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue %B [[IV1]], i64 [[LOAD2]], 1
-; CHECK-NEXT: ret %B [[IV2]]
+; CHECK-LABEL: @loadB(
+; CHECK-NEXT: [[DOTELT:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK:%.*]] = load i8*, i8** [[DOTELT]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B]] undef, i8* [[DOTUNPACK]], 0
+; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
+; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i64, i64* [[DOTELT1]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK2]], 1
+; CHECK-NEXT: ret [[B]] [[TMP2]]
+;
%1 = load %B, %B* %b.ptr, align 8
ret %B %1
}
define { %A } @loadStructOfA({ %A }* %sa.ptr) {
-; CHECK-LABEL: loadStructOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0
-; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0
-; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue { %A } undef, %A [[IV1]], 0
-; CHECK-NEXT: ret { %A } [[IV2]]
+; CHECK-LABEL: @loadStructOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A]] undef, %A__vtbl* [[DOTUNPACK_UNPACK]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { [[A]] } undef, [[A]] [[DOTUNPACK1]], 0
+; CHECK-NEXT: ret { [[A]] } [[TMP2]]
+;
%1 = load { %A }, { %A }* %sa.ptr, align 8
ret { %A } %1
}
define [1 x %A] @loadArrayOfA([1 x %A]* %aa.ptr) {
-; CHECK-LABEL: loadArrayOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr [1 x %A], [1 x %A]* %aa.ptr, i64 0, i64 0, i32 0
-; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0
-; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue [1 x %A] undef, %A [[IV1]], 0
-; CHECK-NEXT: ret [1 x %A] [[IV2]]
+; CHECK-LABEL: @loadArrayOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [1 x %A], [1 x %A]* [[AA_PTR:%.*]], i64 0, i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [[A:%.*]] undef, %A__vtbl* [[DOTUNPACK_UNPACK]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [1 x %A] undef, [[A]] [[DOTUNPACK1]], 0
+; CHECK-NEXT: ret [1 x %A] [[TMP2]]
+;
%1 = load [1 x %A], [1 x %A]* %aa.ptr, align 8
ret [1 x %A] %1
}
define { [1 x %A] } @loadStructOfArrayOfA({ [1 x %A] }* %saa.ptr) {
-; CHECK-LABEL: loadStructOfArrayOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr { [1 x %A] }, { [1 x %A] }* %saa.ptr, i64 0, i32 0, i64 0, i32 0
-; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0
-; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue [1 x %A] undef, %A [[IV1]], 0
-; CHECK-NEXT: [[IV3:%[a-z0-9\.]+]] = insertvalue { [1 x %A] } undef, [1 x %A] [[IV2]], 0
-; CHECK-NEXT: ret { [1 x %A] } [[IV3]]
+; CHECK-LABEL: @loadStructOfArrayOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [1 x %A] }, { [1 x %A] }* [[SAA_PTR:%.*]], i64 0, i32 0, i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK_UNPACK_UNPACK:%.*]] = load %A__vtbl*, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: [[DOTUNPACK_UNPACK2:%.*]] = insertvalue [[A:%.*]] undef, %A__vtbl* [[DOTUNPACK_UNPACK_UNPACK]], 0
+; CHECK-NEXT: [[DOTUNPACK1:%.*]] = insertvalue [1 x %A] undef, [[A]] [[DOTUNPACK_UNPACK2]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { [1 x %A] } undef, [1 x %A] [[DOTUNPACK1]], 0
+; CHECK-NEXT: ret { [1 x %A] } [[TMP2]]
+;
%1 = load { [1 x %A] }, { [1 x %A] }* %saa.ptr, align 8
ret { [1 x %A] } %1
}
define { %A } @structOfA({ %A }* %sa.ptr) {
-; CHECK-LABEL: structOfA
-; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0
-; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8
-; CHECK-NEXT: ret { %A } { %A { %A__vtbl* @A__vtblZ } }
+; CHECK-LABEL: @structOfA(
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr { [[A:%.*]] }, { [[A]] }* [[SA_PTR:%.*]], i64 0, i32 0, i32 0
+; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[TMP1]], align 8
+; CHECK-NEXT: ret { [[A]] } { [[A]] { %A__vtbl* @A__vtblZ } }
+;
store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8
%1 = load { %A }, { %A }* %sa.ptr, align 8
ret { %A } %1
}
define %B @structB(%B* %b.ptr) {
-; CHECK-LABEL: structB
-; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0
-; CHECK-NEXT: store i8* null, i8** [[GEP1]], align 8
-; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1
-; CHECK-NEXT: store i64 42, i64* [[GEP2]], align 8
-; CHECK-NEXT: ret %B { i8* null, i64 42 }
+; CHECK-LABEL: @structB(
+; CHECK-NEXT: [[B_PTR_REPACK:%.*]] = getelementptr inbounds [[B:%.*]], %B* [[B_PTR:%.*]], i64 0, i32 0
+; CHECK-NEXT: store i8* null, i8** [[B_PTR_REPACK]], align 8
+; CHECK-NEXT: [[B_PTR_REPACK1:%.*]] = getelementptr inbounds [[B]], %B* [[B_PTR]], i64 0, i32 1
+; CHECK-NEXT: store i64 42, i64* [[B_PTR_REPACK1]], align 8
+; CHECK-NEXT: ret [[B]] { i8* null, i64 42 }
+;
store %B { i8* null, i64 42 }, %B* %b.ptr, align 8
%1 = load %B, %B* %b.ptr, align 8
ret %B %1
}
define [2 x %B] @loadArrayOfB([2 x %B]* %ab.ptr) {
-; CHECK-LABEL: loadArrayOfB
-; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 0
-; CHECK-NEXT: [[LOAD1:%[a-z0-9\.]+]] = load i8*, i8** [[GEP1]], align 8
-; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD1]], 0
-; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 1
-; CHECK-NEXT: [[LOAD2:%[a-z0-9\.]+]] = load i64, i64* [[GEP2]], align 8
-; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue %B [[IV1]], i64 [[LOAD2]], 1
-; CHECK-NEXT: [[IV3:%[a-z0-9\.]+]] = insertvalue [2 x %B] undef, %B [[IV2]], 0
-; CHECK-NEXT: [[GEP3:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 0
-; CHECK-NEXT: [[LOAD3:%[a-z0-9\.]+]] = load i8*, i8** [[GEP3]], align 8
-; CHECK-NEXT: [[IV4:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD3]], 0
-; CHECK-NEXT: [[GEP4:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 1
-; CHECK-NEXT: [[LOAD4:%[a-z0-9\.]+]] = load i64, i64* [[GEP4]], align 8
-; CHECK-NEXT: [[IV5:%[a-z0-9\.]+]] = insertvalue %B [[IV4]], i64 [[LOAD4]], 1
-; CHECK-NEXT: [[IV6:%[a-z0-9\.]+]] = insertvalue [2 x %B] [[IV3]], %B [[IV5]], 1
-; CHECK-NEXT: ret [2 x %B] [[IV6]]
+; CHECK-LABEL: @loadArrayOfB(
+; CHECK-NEXT: [[DOTUNPACK_ELT:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR:%.*]], i64 0, i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK_UNPACK:%.*]] = load i8*, i8** [[DOTUNPACK_ELT]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[B:%.*]] undef, i8* [[DOTUNPACK_UNPACK]], 0
+; CHECK-NEXT: [[DOTUNPACK_ELT3:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 0, i32 1
+; CHECK-NEXT: [[DOTUNPACK_UNPACK4:%.*]] = load i64, i64* [[DOTUNPACK_ELT3]], align 8
+; CHECK-NEXT: [[DOTUNPACK5:%.*]] = insertvalue [[B]] [[TMP1]], i64 [[DOTUNPACK_UNPACK4]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [2 x %B] undef, [[B]] [[DOTUNPACK5]], 0
+; CHECK-NEXT: [[DOTUNPACK2_ELT:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 0
+; CHECK-NEXT: [[DOTUNPACK2_UNPACK:%.*]] = load i8*, i8** [[DOTUNPACK2_ELT]], align 8
+; CHECK-NEXT: [[TMP3:%.*]] = insertvalue [[B]] undef, i8* [[DOTUNPACK2_UNPACK]], 0
+; CHECK-NEXT: [[DOTUNPACK2_ELT6:%.*]] = getelementptr inbounds [2 x %B], [2 x %B]* [[AB_PTR]], i64 0, i64 1, i32 1
+; CHECK-NEXT: [[DOTUNPACK2_UNPACK7:%.*]] = load i64, i64* [[DOTUNPACK2_ELT6]], align 8
+; CHECK-NEXT: [[DOTUNPACK28:%.*]] = insertvalue [[B]] [[TMP3]], i64 [[DOTUNPACK2_UNPACK7]], 1
+; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [2 x %B] [[TMP2]], [[B]] [[DOTUNPACK28]], 1
+; CHECK-NEXT: ret [2 x %B] [[TMP4]]
+;
%1 = load [2 x %B], [2 x %B]* %ab.ptr, align 8
ret [2 x %B] %1
}
define [2000 x %B] @loadLargeArrayOfB([2000 x %B]* %ab.ptr) {
-; CHECK-LABEL: loadLargeArrayOfB
-; CHECK-NEXT: load [2000 x %B], [2000 x %B]* %ab.ptr, align 8
-; CHECK-NEXT: ret [2000 x %B]
+; CHECK-LABEL: @loadLargeArrayOfB(
+; CHECK-NEXT: [[TMP1:%.*]] = load [2000 x %B], [2000 x %B]* [[AB_PTR:%.*]], align 8
+; CHECK-NEXT: ret [2000 x %B] [[TMP1]]
+;
%1 = load [2000 x %B], [2000 x %B]* %ab.ptr, align 8
ret [2000 x %B] %1
}
; Make sure that we do not increase alignment of packed struct element
define i32 @packed_alignment(%struct.S* dereferenceable(9) %s) {
-; CHECK-LABEL: packed_alignment
-; CHECK-NEXT: %tv.elt1 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 1, i32 1
-; CHECK-NEXT: %tv.unpack2 = load i32, i32* %tv.elt1, align 1
-; CHECK-NEXT: ret i32 %tv.unpack2
+; CHECK-LABEL: @packed_alignment(
+; CHECK-NEXT: [[TV_ELT1:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], %struct.S* [[S:%.*]], i64 0, i32 1, i32 1
+; CHECK-NEXT: [[TV_UNPACK2:%.*]] = load i32, i32* [[TV_ELT1]], align 1
+; CHECK-NEXT: ret i32 [[TV_UNPACK2]]
+;
%t = getelementptr inbounds %struct.S, %struct.S* %s, i32 0, i32 1
%tv = load %struct.T, %struct.T* %t, align 1
%v = extractvalue %struct.T %tv, 1
%struct.U = type {i8, i8, i8, i8, i8, i8, i8, i8, i64}
define void @check_alignment(%struct.U* %u, %struct.U* %v) {
-; CHECK-LABEL: check_alignment
-; CHECK: load i8, i8* {{.*}}, align 8
-; CHECK: load i8, i8* {{.*}}, align 1
-; CHECK: load i8, i8* {{.*}}, align 2
-; CHECK: load i8, i8* {{.*}}, align 1
-; CHECK: load i8, i8* {{.*}}, align 4
-; CHECK: load i8, i8* {{.*}}, align 1
-; CHECK: load i8, i8* {{.*}}, align 2
-; CHECK: load i8, i8* {{.*}}, align 1
-; CHECK: load i64, i64* {{.*}}, align 8
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 8
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 2
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 4
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 2
-; CHECK: store i8 {{.*}}, i8* {{.*}}, align 1
-; CHECK: store i64 {{.*}}, i64* {{.*}}, align 8
+; CHECK-LABEL: @check_alignment(
+; CHECK-NEXT: [[DOTELT:%.*]] = getelementptr inbounds [[STRUCT_U:%.*]], %struct.U* [[U:%.*]], i64 0, i32 0
+; CHECK-NEXT: [[DOTUNPACK:%.*]] = load i8, i8* [[DOTELT]], align 8
+; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 1
+; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load i8, i8* [[DOTELT1]], align 1
+; CHECK-NEXT: [[DOTELT3:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 2
+; CHECK-NEXT: [[DOTUNPACK4:%.*]] = load i8, i8* [[DOTELT3]], align 2
+; CHECK-NEXT: [[DOTELT5:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 3
+; CHECK-NEXT: [[DOTUNPACK6:%.*]] = load i8, i8* [[DOTELT5]], align 1
+; CHECK-NEXT: [[DOTELT7:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 4
+; CHECK-NEXT: [[DOTUNPACK8:%.*]] = load i8, i8* [[DOTELT7]], align 4
+; CHECK-NEXT: [[DOTELT9:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 5
+; CHECK-NEXT: [[DOTUNPACK10:%.*]] = load i8, i8* [[DOTELT9]], align 1
+; CHECK-NEXT: [[DOTELT11:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 6
+; CHECK-NEXT: [[DOTUNPACK12:%.*]] = load i8, i8* [[DOTELT11]], align 2
+; CHECK-NEXT: [[DOTELT13:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 7
+; CHECK-NEXT: [[DOTUNPACK14:%.*]] = load i8, i8* [[DOTELT13]], align 1
+; CHECK-NEXT: [[DOTELT15:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[U]], i64 0, i32 8
+; CHECK-NEXT: [[DOTUNPACK16:%.*]] = load i64, i64* [[DOTELT15]], align 8
+; CHECK-NEXT: [[V_REPACK:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V:%.*]], i64 0, i32 0
+; CHECK-NEXT: store i8 [[DOTUNPACK]], i8* [[V_REPACK]], align 8
+; CHECK-NEXT: [[V_REPACK18:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 1
+; CHECK-NEXT: store i8 [[DOTUNPACK2]], i8* [[V_REPACK18]], align 1
+; CHECK-NEXT: [[V_REPACK20:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 2
+; CHECK-NEXT: store i8 [[DOTUNPACK4]], i8* [[V_REPACK20]], align 2
+; CHECK-NEXT: [[V_REPACK22:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 3
+; CHECK-NEXT: store i8 [[DOTUNPACK6]], i8* [[V_REPACK22]], align 1
+; CHECK-NEXT: [[V_REPACK24:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 4
+; CHECK-NEXT: store i8 [[DOTUNPACK8]], i8* [[V_REPACK24]], align 4
+; CHECK-NEXT: [[V_REPACK26:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 5
+; CHECK-NEXT: store i8 [[DOTUNPACK10]], i8* [[V_REPACK26]], align 1
+; CHECK-NEXT: [[V_REPACK28:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 6
+; CHECK-NEXT: store i8 [[DOTUNPACK12]], i8* [[V_REPACK28]], align 2
+; CHECK-NEXT: [[V_REPACK30:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 7
+; CHECK-NEXT: store i8 [[DOTUNPACK14]], i8* [[V_REPACK30]], align 1
+; CHECK-NEXT: [[V_REPACK32:%.*]] = getelementptr inbounds [[STRUCT_U]], %struct.U* [[V]], i64 0, i32 8
+; CHECK-NEXT: store i64 [[DOTUNPACK16]], i64* [[V_REPACK32]], align 8
+; CHECK-NEXT: ret void
+;
%1 = load %struct.U, %struct.U* %u
store %struct.U %1, %struct.U* %v
ret void