r345536 - In swiftcall, don't merge FP/vector types within a chunk.

John McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 29 13:32:36 PDT 2018


Author: rjmccall
Date: Mon Oct 29 13:32:36 2018
New Revision: 345536

URL: http://llvm.org/viewvc/llvm-project?rev=345536&view=rev
Log:
In swiftcall, don't merge FP/vector types within a chunk.

Modified:
    cfe/trunk/include/clang/CodeGen/SwiftCallingConv.h
    cfe/trunk/lib/CodeGen/SwiftCallingConv.cpp
    cfe/trunk/test/CodeGen/64bit-swiftcall.c
    cfe/trunk/test/CodeGen/windows-swiftcall.c

Modified: cfe/trunk/include/clang/CodeGen/SwiftCallingConv.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/SwiftCallingConv.h?rev=345536&r1=345535&r2=345536&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/SwiftCallingConv.h (original)
+++ cfe/trunk/include/clang/CodeGen/SwiftCallingConv.h Mon Oct 29 13:32:36 2018
@@ -114,6 +114,9 @@ private:
   void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
   void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
   void splitVectorEntry(unsigned index);
+  static bool shouldMergeEntries(const StorageEntry &first,
+                                 const StorageEntry &second,
+                                 CharUnits chunkSize);
 };
 
 /// Should an aggregate which expands to the given type sequence

Modified: cfe/trunk/lib/CodeGen/SwiftCallingConv.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/SwiftCallingConv.cpp?rev=345536&r1=345535&r2=345536&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/SwiftCallingConv.cpp (original)
+++ cfe/trunk/lib/CodeGen/SwiftCallingConv.cpp Mon Oct 29 13:32:36 2018
@@ -415,6 +415,40 @@ static bool areBytesInSameUnit(CharUnits
       == getOffsetAtStartOfUnit(second, chunkSize);
 }
 
+static bool isMergeableEntryType(llvm::Type *type) {
+  // Opaquely-typed memory is always mergeable.
+  if (type == nullptr) return true;
+
+  // Pointers and integers are always mergeable.  In theory we should not
+  // merge pointers, but (1) it doesn't currently matter in practice because
+  // the chunk size is never greater than the size of a pointer and (2)
+  // Swift IRGen uses integer types for a lot of things that are "really"
+  // just storing pointers (like Optional<SomePointer>).  If we ever have a
+  // target that would otherwise combine pointers, we should put some effort
+  // into fixing those cases in Swift IRGen and then call out pointer types
+  // here.
+
+  // Floating-point and vector types should never be merged.
+  // Most such types are too large and highly-aligned to ever trigger merging
+  // in practice, but it's important for the rule to cover at least 'half'
+  // and 'float', as well as things like small vectors of 'i1' or 'i8'.
+  return (!type->isFloatingPointTy() && !type->isVectorTy());
+}
+
+bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first,
+                                          const StorageEntry &second,
+                                          CharUnits chunkSize) {
+  // Only merge entries that overlap the same chunk.  We test this first
+  // despite being a bit more expensive because this is the condition that
+  // tends to prevent merging.
+  if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin,
+                          chunkSize))
+    return false;
+
+  return (isMergeableEntryType(first.Type) &&
+          isMergeableEntryType(second.Type));
+}
+
 void SwiftAggLowering::finish() {
   if (Entries.empty()) {
     Finished = true;
@@ -425,12 +459,12 @@ void SwiftAggLowering::finish() {
   // which is generally the size of a pointer.
   const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM);
 
-  // First pass: if two entries share a chunk, make them both opaque
+  // First pass: if two entries should be merged, make them both opaque
   // and stretch one to meet the next.
+  // Also, remember if there are any opaque entries.
   bool hasOpaqueEntries = (Entries[0].Type == nullptr);
   for (size_t i = 1, e = Entries.size(); i != e; ++i) {
-    if (areBytesInSameUnit(Entries[i - 1].End - CharUnits::One(),
-                           Entries[i].Begin, chunkSize)) {
+    if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) {
       Entries[i - 1].Type = nullptr;
       Entries[i].Type = nullptr;
       Entries[i - 1].End = Entries[i].Begin;

Modified: cfe/trunk/test/CodeGen/64bit-swiftcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/64bit-swiftcall.c?rev=345536&r1=345535&r2=345536&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/64bit-swiftcall.c (original)
+++ cfe/trunk/test/CodeGen/64bit-swiftcall.c Mon Oct 29 13:32:36 2018
@@ -10,7 +10,7 @@
 #define ERROR __attribute__((swift_error_result))
 #define CONTEXT __attribute__((swift_context))
 
-// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }
 
 /*****************************************************************************/
 /****************************** PARAMETER ABIS *******************************/
@@ -102,8 +102,8 @@ typedef struct {
   int x;
   char c0;
   char c1;
-  float f0;
-  float f1;
+  int f0;
+  int f1;
 } struct_1;
 TEST(struct_1);
 // CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_1() {{.*}}{
@@ -150,8 +150,8 @@ typedef struct {
   int x;
   char c0;
   __attribute__((aligned(2))) char c1;
-  float f0;
-  float f1;
+  int f0;
+  int f1;
 } struct_2;
 TEST(struct_2);
 // CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_2() {{.*}}{
@@ -308,20 +308,30 @@ typedef union {
 TEST(union_hom_fp_partial)
 // CHECK: define void @test_union_hom_fp_partial()
 // CHECK:   [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK:   [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial()
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 8
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK:   call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK:   [[CALL:%.*]] = call swiftcc { float, float, float, float } @return_union_hom_fp_partial()
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 0
+// CHECK:   store float [[T1]], float* [[T0]], align 16
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 1
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 2
+// CHECK:   store float [[T1]], float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 3
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[V0:%.*]] = load float, float* [[T0]], align 16
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[V1:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[V2:%.*]] = load float, float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK:   [[V3:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   call swiftcc void @take_union_hom_fp_partial(float [[V0]], float [[V1]], float [[V2]], float [[V3]])
 // CHECK:   ret void
 // CHECK: }
 
@@ -332,20 +342,25 @@ typedef union {
 TEST(union_het_fpv_partial)
 // CHECK-LABEL: define void @test_union_het_fpv_partial()
 // CHECK:   [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK:   [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial()
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK:   [[CALL:%.*]] = call swiftcc { i64, float, float } @return_union_het_fpv_partial()
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 0
 // CHECK:   store i64 [[T1]], i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 8
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 1
+// CHECK:   store float [[T1]], float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 2
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
 // CHECK:   [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK:   call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[V1:%.*]] = load float, float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[V2:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], float [[V1]], float [[V2]])
 // CHECK:   ret void
 // CHECK: }
 
@@ -464,8 +479,8 @@ typedef struct {
   float f1;
 } struct_f2;
 TEST(struct_f2)
-// CHECK-LABEL: define swiftcc i64 @return_struct_f2()
-// CHECK-LABEL: define swiftcc void @take_struct_f2(i64)
+// CHECK-LABEL: define swiftcc { float, float } @return_struct_f2()
+// CHECK-LABEL: define swiftcc void @take_struct_f2(float, float)
 
 typedef struct {
   float f0;
@@ -473,8 +488,8 @@ typedef struct {
   float f2;
 } struct_f3;
 TEST(struct_f3)
-// CHECK-LABEL: define swiftcc { i64, float } @return_struct_f3()
-// CHECK-LABEL: define swiftcc void @take_struct_f3(i64, float)
+// CHECK-LABEL: define swiftcc { float, float, float } @return_struct_f3()
+// CHECK-LABEL: define swiftcc void @take_struct_f3(float, float, float)
 
 typedef struct {
   float f0;
@@ -483,8 +498,8 @@ typedef struct {
   float f3;
 } struct_f4;
 TEST(struct_f4)
-// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_f4()
-// CHECK-LABEL: define swiftcc void @take_struct_f4(i64, i64)
+// CHECK-LABEL: define swiftcc { float, float, float, float } @return_struct_f4()
+// CHECK-LABEL: define swiftcc void @take_struct_f4(float, float, float, float)
 
 
 typedef struct {
@@ -1016,8 +1031,8 @@ typedef union {
   float3 fv2;
 } union_hom_fp_partial2;
 TEST(union_hom_fp_partial2)
-// X86-64-LABEL: take_union_hom_fp_partial2(i64, float)
-// ARM64-LABEL: take_union_hom_fp_partial2(i64, float)
+// X86-64-LABEL: take_union_hom_fp_partial2(float, float, float)
+// ARM64-LABEL: take_union_hom_fp_partial2(float, float, float)
 
 // At one point, we emitted lifetime.ends without a matching lifetime.start for
 // CoerceAndExpanded args. Since we're not performing optimizations, neither

Modified: cfe/trunk/test/CodeGen/windows-swiftcall.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/windows-swiftcall.c?rev=345536&r1=345535&r2=345536&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/windows-swiftcall.c (original)
+++ cfe/trunk/test/CodeGen/windows-swiftcall.c Mon Oct 29 13:32:36 2018
@@ -5,7 +5,7 @@
 #define ERROR __attribute__((swift_error_result))
 #define CONTEXT __attribute__((swift_context))
 
-// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }
 
 /*****************************************************************************/
 /****************************** PARAMETER ABIS *******************************/
@@ -93,8 +93,8 @@ typedef struct {
   int x;
   char c0;
   char c1;
-  float f0;
-  float f1;
+  int f0;
+  int f1;
 } struct_1;
 TEST(struct_1);
 // CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_1() {{.*}}{
@@ -141,8 +141,8 @@ typedef struct {
   int x;
   char c0;
   __attribute__((aligned(2))) char c1;
-  float f0;
-  float f1;
+  int f0;
+  int f1;
 } struct_2;
 TEST(struct_2);
 // CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{
@@ -299,20 +299,30 @@ typedef union {
 TEST(union_hom_fp_partial)
 // CHECK: define dso_local void @test_union_hom_fp_partial()
 // CHECK:   [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK:   [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial()
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 8
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK:   call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK:   [[CALL:%.*]] = call swiftcc { float, float, float, float } @return_union_hom_fp_partial()
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 0
+// CHECK:   store float [[T1]], float* [[T0]], align 16
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 1
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 2
+// CHECK:   store float [[T1]], float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK:   [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 3
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[V0:%.*]] = load float, float* [[T0]], align 16
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[V1:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[V2:%.*]] = load float, float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3
+// CHECK:   [[V3:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   call swiftcc void @take_union_hom_fp_partial(float [[V0]], float [[V1]], float [[V2]], float [[V3]])
 // CHECK:   ret void
 // CHECK: }
 
@@ -323,20 +333,25 @@ typedef union {
 TEST(union_het_fpv_partial)
 // CHECK-LABEL: define dso_local void @test_union_het_fpv_partial()
 // CHECK:   [[AGG:%.*]] = alloca [[UNION:%.*]], align 16
-// CHECK:   [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial()
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK:   [[CALL:%.*]] = call swiftcc { i64, float, float } @return_union_het_fpv_partial()
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 0
 // CHECK:   store i64 [[T1]], i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
-// CHECK:   store i64 [[T1]], i64* [[T0]], align 8
-// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 1
+// CHECK:   store float [[T1]], float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 2
+// CHECK:   store float [[T1]], float* [[T0]], align 4
+// CHECK:   [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }*
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0
 // CHECK:   [[V0:%.*]] = load i64, i64* [[T0]], align 16
-// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
-// CHECK:   [[V1:%.*]] = load i64, i64* [[T0]], align 8
-// CHECK:   call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1
+// CHECK:   [[V1:%.*]] = load float, float* [[T0]], align 8
+// CHECK:   [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2
+// CHECK:   [[V2:%.*]] = load float, float* [[T0]], align 4
+// CHECK:   call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], float [[V1]], float [[V2]])
 // CHECK:   ret void
 // CHECK: }
 




More information about the cfe-commits mailing list