@@ -36,6 +36,15 @@ struct Zoo {
3636 Kitteh Cats[4 ];
3737};
3838
39+ struct FourFloats : TwoFloats {
40+ float Z, W;
41+ };
42+
43+ struct SlicyBits {
44+ int Z : 8 ;
45+ int W : 8 ;
46+ };
47+
3948// Case 1: Extraneous braces get ignored in literal instantiation.
4049// CHECK-LABEL: define void @_Z5case1v(
4150// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -712,3 +721,183 @@ Zoo case9(Doggo D1, AnimalBits A1) {
712721 Zoo Z1 = {D1, A1, D1, A1, D1, A1};
713722 return Z1;
714723}
724+
725+ // Case 10: Initialize an object with a base class from two objects.
726+ // CHECK-LABEL: define void @_Z6case109TwoFloatsS_(
727+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FOURFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 4 [[TF1:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF2:%.*]]) #[[ATTR0]] {
728+ // CHECK-NEXT: [[ENTRY:.*:]]
729+ // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
730+ // CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 0
731+ // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X1]], align 4
732+ // CHECK-NEXT: store float [[TMP0]], ptr [[X]], align 4
733+ // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
734+ // CHECK-NEXT: [[Y2:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 1
735+ // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[Y2]], align 4
736+ // CHECK-NEXT: store float [[TMP1]], ptr [[Y]], align 4
737+ // CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
738+ // CHECK-NEXT: [[X3:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 0
739+ // CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[X3]], align 4
740+ // CHECK-NEXT: store float [[TMP2]], ptr [[Z]], align 4
741+ // CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 2
742+ // CHECK-NEXT: [[Y4:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 1
743+ // CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[Y4]], align 4
744+ // CHECK-NEXT: store float [[TMP3]], ptr [[W]], align 4
745+ // CHECK-NEXT: ret void
746+ //
747+ FourFloats case10 (TwoFloats TF1, TwoFloats TF2) {
748+ FourFloats FF1 = {TF1, TF2};
749+ return FF1;
750+ }
751+
752+ // Case 11: Initialize an object with a base class from a vector splat.
753+ // CHECK-LABEL: define void @_Z6case11f(
754+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FOURFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] {
755+ // CHECK-NEXT: [[ENTRY:.*:]]
756+ // CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4
757+ // CHECK-NEXT: [[REF_TMP:%.*]] = alloca <4 x float>, align 16
758+ // CHECK-NEXT: [[REF_TMP1:%.*]] = alloca <4 x float>, align 16
759+ // CHECK-NEXT: [[REF_TMP4:%.*]] = alloca <4 x float>, align 16
760+ // CHECK-NEXT: [[REF_TMP7:%.*]] = alloca <4 x float>, align 16
761+ // CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4
762+ // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS:%.*]], ptr [[AGG_RESULT]], i32 0, i32 0
763+ // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_ADDR]], align 4
764+ // CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x float> poison, float [[TMP0]], i64 0
765+ // CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x float> [[CAST_SPLAT]], <1 x float> poison, <4 x i32> zeroinitializer
766+ // CHECK-NEXT: store <4 x float> [[TMP1]], ptr [[REF_TMP]], align 16
767+ // CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[REF_TMP]], align 16
768+ // CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x float> [[TMP2]], i64 0
769+ // CHECK-NEXT: store float [[VECEXT]], ptr [[X]], align 4
770+ // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
771+ // CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[F_ADDR]], align 4
772+ // CHECK-NEXT: [[CAST_SPLAT2:%.*]] = insertelement <1 x float> poison, float [[TMP3]], i64 0
773+ // CHECK-NEXT: [[TMP4:%.*]] = shufflevector <1 x float> [[CAST_SPLAT2]], <1 x float> poison, <4 x i32> zeroinitializer
774+ // CHECK-NEXT: store <4 x float> [[TMP4]], ptr [[REF_TMP1]], align 16
775+ // CHECK-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[REF_TMP1]], align 16
776+ // CHECK-NEXT: [[VECEXT3:%.*]] = extractelement <4 x float> [[TMP5]], i64 1
777+ // CHECK-NEXT: store float [[VECEXT3]], ptr [[Y]], align 4
778+ // CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
779+ // CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[F_ADDR]], align 4
780+ // CHECK-NEXT: [[CAST_SPLAT5:%.*]] = insertelement <1 x float> poison, float [[TMP6]], i64 0
781+ // CHECK-NEXT: [[TMP7:%.*]] = shufflevector <1 x float> [[CAST_SPLAT5]], <1 x float> poison, <4 x i32> zeroinitializer
782+ // CHECK-NEXT: store <4 x float> [[TMP7]], ptr [[REF_TMP4]], align 16
783+ // CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[REF_TMP4]], align 16
784+ // CHECK-NEXT: [[VECEXT6:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
785+ // CHECK-NEXT: store float [[VECEXT6]], ptr [[Z]], align 4
786+ // CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 2
787+ // CHECK-NEXT: [[TMP9:%.*]] = load float, ptr [[F_ADDR]], align 4
788+ // CHECK-NEXT: [[CAST_SPLAT8:%.*]] = insertelement <1 x float> poison, float [[TMP9]], i64 0
789+ // CHECK-NEXT: [[TMP10:%.*]] = shufflevector <1 x float> [[CAST_SPLAT8]], <1 x float> poison, <4 x i32> zeroinitializer
790+ // CHECK-NEXT: store <4 x float> [[TMP10]], ptr [[REF_TMP7]], align 16
791+ // CHECK-NEXT: [[TMP11:%.*]] = load <4 x float>, ptr [[REF_TMP7]], align 16
792+ // CHECK-NEXT: [[VECEXT9:%.*]] = extractelement <4 x float> [[TMP11]], i64 3
793+ // CHECK-NEXT: store float [[VECEXT9]], ptr [[W]], align 4
794+ // CHECK-NEXT: ret void
795+ //
796+ FourFloats case11 (float F) {
797+ FourFloats FF1 = {F.xxxx};
798+ return FF1;
799+ }
800+
801+ // Case 12: Initialize bitfield from two integers.
802+ // CHECK-LABEL: define void @_Z6case12ii(
803+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_SLICYBITS:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) #[[ATTR0]] {
804+ // CHECK-NEXT: [[ENTRY:.*:]]
805+ // CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4
806+ // CHECK-NEXT: [[J_ADDR:%.*]] = alloca i32, align 4
807+ // CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4
808+ // CHECK-NEXT: store i32 [[J]], ptr [[J_ADDR]], align 4
809+ // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
810+ // CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i16
811+ // CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
812+ // CHECK-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255
813+ // CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -256
814+ // CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
815+ // CHECK-NEXT: store i16 [[BF_SET]], ptr [[AGG_RESULT]], align 4
816+ // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[J_ADDR]], align 4
817+ // CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
818+ // CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
819+ // CHECK-NEXT: [[BF_VALUE2:%.*]] = and i16 [[TMP3]], 255
820+ // CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_VALUE2]], 8
821+ // CHECK-NEXT: [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD1]], 255
822+ // CHECK-NEXT: [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], [[BF_SHL]]
823+ // CHECK-NEXT: store i16 [[BF_SET4]], ptr [[AGG_RESULT]], align 4
824+ // CHECK-NEXT: ret void
825+ //
826+ SlicyBits case12 (int I, int J) {
827+ SlicyBits SB = {I, J};
828+ return SB;
829+ }
830+
831+ // Case 13: Initialize bitfield from a struct of two ints.
832+ // CHECK-LABEL: define void @_Z6case137TwoInts(
833+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_SLICYBITS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOINTS:%.*]]) align 4 [[TI:%.*]]) #[[ATTR0]] {
834+ // CHECK-NEXT: [[ENTRY:.*:]]
835+ // CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0
836+ // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Z]], align 4
837+ // CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i16
838+ // CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
839+ // CHECK-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255
840+ // CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -256
841+ // CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
842+ // CHECK-NEXT: store i16 [[BF_SET]], ptr [[AGG_RESULT]], align 4
843+ // CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1
844+ // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[W]], align 4
845+ // CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
846+ // CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
847+ // CHECK-NEXT: [[BF_VALUE2:%.*]] = and i16 [[TMP3]], 255
848+ // CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_VALUE2]], 8
849+ // CHECK-NEXT: [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD1]], 255
850+ // CHECK-NEXT: [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], [[BF_SHL]]
851+ // CHECK-NEXT: store i16 [[BF_SET4]], ptr [[AGG_RESULT]], align 4
852+ // CHECK-NEXT: ret void
853+ //
854+ SlicyBits case13 (TwoInts TI) {
855+ SlicyBits SB = {TI};
856+ return SB;
857+ }
858+
859+ // Case 14: Initialize struct of ints from struct with bitfields.
860+ // CHECK-LABEL: define void @_Z6case149SlicyBits(
861+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_SLICYBITS:%.*]]) align 4 [[SB:%.*]]) #[[ATTR0]] {
862+ // CHECK-NEXT: [[ENTRY:.*:]]
863+ // CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 0
864+ // CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[SB]], align 4
865+ // CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8
866+ // CHECK-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8
867+ // CHECK-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32
868+ // CHECK-NEXT: store i32 [[BF_CAST]], ptr [[Z]], align 4
869+ // CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 1
870+ // CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[SB]], align 4
871+ // CHECK-NEXT: [[BF_ASHR2:%.*]] = ashr i16 [[BF_LOAD1]], 8
872+ // CHECK-NEXT: [[BF_CAST3:%.*]] = sext i16 [[BF_ASHR2]] to i32
873+ // CHECK-NEXT: store i32 [[BF_CAST3]], ptr [[W]], align 4
874+ // CHECK-NEXT: ret void
875+ //
876+ TwoInts case14 (SlicyBits SB) {
877+ TwoInts TI = {SB};
878+ return TI;
879+ }
880+
881+ // Case 15: Initialize struct of floats from struct with bitfields.
882+ // CHECK-LABEL: define void @_Z6case159SlicyBits(
883+ // CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_SLICYBITS:%.*]]) align 4 [[SB:%.*]]) #[[ATTR0]] {
884+ // CHECK-NEXT: [[ENTRY:.*:]]
885+ // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
886+ // CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[SB]], align 4
887+ // CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8
888+ // CHECK-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8
889+ // CHECK-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32
890+ // CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[BF_CAST]] to float
891+ // CHECK-NEXT: store float [[CONV]], ptr [[X]], align 4
892+ // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
893+ // CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[SB]], align 4
894+ // CHECK-NEXT: [[BF_ASHR2:%.*]] = ashr i16 [[BF_LOAD1]], 8
895+ // CHECK-NEXT: [[BF_CAST3:%.*]] = sext i16 [[BF_ASHR2]] to i32
896+ // CHECK-NEXT: [[CONV4:%.*]] = sitofp i32 [[BF_CAST3]] to float
897+ // CHECK-NEXT: store float [[CONV4]], ptr [[Y]], align 4
898+ // CHECK-NEXT: ret void
899+ //
900+ TwoFloats case15 (SlicyBits SB) {
901+ TwoFloats TI = {SB};
902+ return TI;
903+ }
0 commit comments