https://github.com/llvm-beanz updated 
https://github.com/llvm/llvm-project/pull/123141

>From 8457635e366f791d03604384c232bc3d270ce0f8 Mon Sep 17 00:00:00 2001
From: Chris Bieneman <chris.biene...@me.com>
Date: Wed, 15 Jan 2025 13:40:29 -0600
Subject: [PATCH 1/4] [HLSL] Implement HLSL intialization list support

This PR implements HLSL's initialization list behvaior as specified in
the draft language specifcation under
[*Decl.Init.Agg*](https://microsoft.github.io/hlsl-specs/specs/hlsl.html
#Decl.Init.Agg).

This behavior is a bit unusual for C/C++ because intermediate braces in
initializer lists are ignored and a whole array of additional
conversions occur unintuitively to how initializaiton works in C.

The implementaiton in this PR generates a valid C/C++ initialization
list AST for the HLSL initializer so that there are no changes required
to Clang's CodeGen to support this. This design will also allow us to
use Clang's rewrite to convert HLSL initializers to valid C/C++
initializers that are equivalent. It does have the downside that it
will generate often redundant accesses during codegen. The IR optimizer
is extremely good at eliminating those so this will have no impact on
the final executable performance.

There is some opportunity for optimizing the initializer list
generation that we could consider in subsequent commits. One notable
opportunity would be to identify aggregate objects that occur in the
same place in both initializers and do not require converison, those
aggregates could be initialized as aggregates rather than fully
scalarized.

Closes #56067
---
 .../clang/Basic/DiagnosticSemaKinds.td        |   3 +
 clang/include/clang/Sema/SemaHLSL.h           |   5 +
 clang/lib/Sema/SemaChecking.cpp               |   9 +-
 clang/lib/Sema/SemaHLSL.cpp                   | 159 ++++
 clang/lib/Sema/SemaInit.cpp                   |   5 +
 clang/test/CodeGenHLSL/ArrayTemporary.hlsl    |   3 +-
 .../CodeGenHLSL/BasicFeatures/InitLists.hlsl  | 714 ++++++++++++++++++
 clang/test/SemaHLSL/ArrayTemporary.hlsl       |   2 +-
 clang/test/SemaHLSL/Language/InitLists.hlsl   |  69 ++
 9 files changed, 964 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
 create mode 100644 clang/test/SemaHLSL/Language/InitLists.hlsl

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 67c15e7c475943a..9db77aba2304552 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12574,6 +12574,9 @@ def err_hlsl_pointers_unsupported : Error<
   "%select{pointers|references}0 are unsupported in HLSL">;
 def err_hlsl_missing_resource_class : Error<"HLSL resource needs to have 
[[hlsl::resource_class()]] attribute">;
 def err_hlsl_attribute_needs_intangible_type: Error<"attribute %0 can be used 
only on HLSL intangible type %1">;
+def err_hlsl_incorrect_num_initializers: Error<
+  "too %select{few|many}0 initializers in list for type %1 "
+  "(expected %2 but found %3)">;
 
 def err_hlsl_operator_unsupported : Error<
   "the '%select{&|*|->}0' operator is unsupported in HLSL">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index f4cd11f423a84a0..092691d08761c40 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -26,6 +26,8 @@
 namespace clang {
 class AttributeCommonInfo;
 class IdentifierInfo;
+class InitializedEntity;
+class InitializationKind;
 class ParsedAttr;
 class Scope;
 class VarDecl;
@@ -145,6 +147,9 @@ class SemaHLSL : public SemaBase {
 
   QualType getInoutParameterType(QualType Ty);
 
+  bool TransformInitList(const InitializedEntity &Entity,
+                         const InitializationKind &Kind, InitListExpr *Init);
+
 private:
   // HLSL resource type attributes need to be processed all at once.
   // This is a list to collect them.
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 881907ac311a300..cc748e432001e05 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11625,9 +11625,12 @@ static void AnalyzeImplicitConversions(
 
   // Propagate whether we are in a C++ list initialization expression.
   // If so, we do not issue warnings for implicit int-float conversion
-  // precision loss, because C++11 narrowing already handles it.
-  bool IsListInit = Item.IsListInit ||
-                    (isa<InitListExpr>(OrigE) && S.getLangOpts().CPlusPlus);
+  // precision loss, because C++11 narrowing already handles it. HLSL's
+  // initialization lists are special, so they shouldn't observe the C++
+  // behavior here.
+  bool IsListInit =
+      Item.IsListInit || (isa<InitListExpr>(OrigE) &&
+                          S.getLangOpts().CPlusPlus && !S.getLangOpts().HLSL);
 
   if (E->isTypeDependent() || E->isValueDependent())
     return;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 65ddee05a21512c..f9f1473d4e0bab9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2576,3 +2576,162 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl 
*VD) {
     }
   }
 }
+
+static bool CastInitializer(Sema &S, ASTContext &Ctx, Expr *E,
+                            llvm::SmallVectorImpl<Expr *> &List,
+                            llvm::SmallVectorImpl<QualType> &DestTypes) {
+  if (List.size() >= DestTypes.size())
+    return false;
+  InitializedEntity Entity =
+      InitializedEntity::InitializeParameter(Ctx, DestTypes[List.size()], 
false);
+  ExprResult Res =
+      S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
+  if (Res.isInvalid())
+    return false;
+  Expr *Init = Res.get();
+  List.push_back(Init);
+  return true;
+}
+
+static void BuildIntializerList(Sema &S, ASTContext &Ctx, Expr *E,
+                                llvm::SmallVectorImpl<Expr *> &List,
+                                llvm::SmallVectorImpl<QualType> &DestTypes,
+                                bool &ExcessInits) {
+  if (List.size() >= DestTypes.size()) {
+    ExcessInits = true;
+    return;
+  }
+
+  // If this is an initialization list, traverse the sub initializers.
+  if (auto *Init = dyn_cast<InitListExpr>(E)) {
+    for (auto *SubInit : Init->inits())
+      BuildIntializerList(S, Ctx, SubInit, List, DestTypes, ExcessInits);
+    return;
+  }
+
+  // If this is a scalar type, just enqueue the expression.
+  QualType Ty = E->getType();
+  if (Ty->isScalarType()) {
+    (void)CastInitializer(S, Ctx, E, List, DestTypes);
+    return;
+  }
+
+  if (auto *ATy = Ty->getAs<VectorType>()) {
+    uint64_t Size = ATy->getNumElements();
+
+    if (List.size() + Size > DestTypes.size()) {
+      ExcessInits = true;
+      return;
+    }
+    QualType SizeTy = Ctx.getSizeType();
+    uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
+    for (uint64_t I = 0; I < Size; ++I) {
+      auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
+                                         SizeTy, SourceLocation());
+
+      ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(
+          E, E->getBeginLoc(), Idx, E->getEndLoc());
+      if (ElExpr.isInvalid())
+        return;
+      if (!CastInitializer(S, Ctx, ElExpr.get(), List, DestTypes))
+        return;
+    }
+    return;
+  }
+
+  if (auto *VTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
+    uint64_t Size = VTy->getZExtSize();
+    QualType SizeTy = Ctx.getSizeType();
+    uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
+    for (uint64_t I = 0; I < Size; ++I) {
+      auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
+                                         SizeTy, SourceLocation());
+      ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(
+          E, E->getBeginLoc(), Idx, E->getEndLoc());
+      if (ElExpr.isInvalid())
+        return;
+      BuildIntializerList(S, Ctx, ElExpr.get(), List, DestTypes, ExcessInits);
+    }
+    return;
+  }
+
+  if (auto *RTy = Ty->getAs<RecordType>()) {
+    for (auto *FD : RTy->getDecl()->fields()) {
+      DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
+      DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
+      ExprResult Res = S.BuildFieldReferenceExpr(
+          E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
+      if (Res.isInvalid())
+        return;
+      BuildIntializerList(S, Ctx, Res.get(), List, DestTypes, ExcessInits);
+    }
+  }
+}
+
+static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty,
+                               llvm::SmallVectorImpl<Expr *>::iterator &It) {
+  if (Ty->isScalarType()) {
+    return *(It++);
+  }
+  llvm::SmallVector<Expr *> Inits;
+  assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
+  if (Ty->isVectorType() || Ty->isConstantArrayType()) {
+    QualType ElTy;
+    uint64_t Size = 0;
+    if (auto *ATy = Ty->getAs<VectorType>()) {
+      ElTy = ATy->getElementType();
+      Size = ATy->getNumElements();
+    } else {
+      auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
+      ElTy = VTy->getElementType();
+      Size = VTy->getZExtSize();
+    }
+    for (uint64_t I = 0; I < Size; ++I)
+      Inits.push_back(GenerateInitLists(Ctx, ElTy, It));
+  }
+  if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
+    for (auto *FD : RD->fields()) {
+      Inits.push_back(GenerateInitLists(Ctx, FD->getType(), It));
+    }
+  }
+  auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
+                                         Inits, Inits.back()->getEndLoc());
+  NewInit->setType(Ty);
+  return NewInit;
+}
+
+bool SemaHLSL::TransformInitList(const InitializedEntity &Entity,
+                                 const InitializationKind &Kind,
+                                 InitListExpr *Init) {
+  // If the initializer is a scalar, just return it.
+  if (Init->getType()->isScalarType())
+    return true;
+  ASTContext &Ctx = SemaRef.getASTContext();
+  llvm::SmallVector<QualType, 16> DestTypes;
+  // An initializer list might be attempting to initialize a reference or
+  // rvalue-reference. When checking the initializer we should look through the
+  // reference.
+  QualType InitTy = Entity.getType().getNonReferenceType();
+  BuildFlattenedTypeList(InitTy, DestTypes);
+
+  llvm::SmallVector<Expr *, 16> ArgExprs;
+  bool ExcessInits = false;
+  for (Expr *Arg : Init->inits())
+    BuildIntializerList(SemaRef, Ctx, Arg, ArgExprs, DestTypes, ExcessInits);
+
+  if (DestTypes.size() != ArgExprs.size() || ExcessInits) {
+    int TooManyOrFew = ExcessInits ? 1 : 0;
+    SemaRef.Diag(Init->getBeginLoc(), 
diag::err_hlsl_incorrect_num_initializers)
+        << TooManyOrFew << InitTy << DestTypes.size() << ArgExprs.size();
+    return false;
+  }
+
+  auto It = ArgExprs.begin();
+  // GenerateInitLists will always return an InitListExpr here, because the
+  // scalar case is handled above.
+  auto *NewInit = cast<InitListExpr>(GenerateInitLists(Ctx, InitTy, It));
+  Init->resizeInits(Ctx, NewInit->getNumInits());
+  for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
+    Init->updateInit(Ctx, I, NewInit->getInit(I));
+  return true;
+}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b95cbbf42220568..a3c56d37f8b0cdf 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -26,6 +26,7 @@
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaObjC.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -4783,6 +4784,10 @@ static void TryListInitialization(Sema &S,
                                   bool TreatUnavailableAsInvalid) {
   QualType DestType = Entity.getType();
 
+  if (S.getLangOpts().HLSL &&
+      !S.HLSL().TransformInitList(Entity, Kind, InitList))
+    return;
+
   // C++ doesn't allow scalar initialization with more than one argument.
   // But C99 complex numbers are scalars and it makes sense there.
   if (S.getLangOpts().CPlusPlus && DestType->isScalarType() &&
diff --git a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl 
b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
index e5db7eac37a4287..91a283554459d95 100644
--- a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
+++ b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
@@ -1,3 +1,4 @@
+
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm 
-disable-llvm-passes -o - %s | FileCheck %s
 
 void fn(float x[2]) { }
@@ -27,7 +28,7 @@ void fn2(Obj O[4]) { }
 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 
[[Arr]], i32 32, i1 false)
 // CHECK: call void {{.*}}fn2{{.*}}(ptr noundef byval([4 x %struct.Obj]) align 
4 [[Tmp]])
 void call2() {
-  Obj Arr[4] = {};
+  Obj Arr[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
   fn2(Arr);
 }
 
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
new file mode 100644
index 000000000000000..e57724b0ec31fb9
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
@@ -0,0 +1,714 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes 
-emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+struct TwoFloats {
+  float X, Y;
+};
+
+struct TwoInts {
+  int Z, W;
+};
+
+struct Doggo {
+  int4 LegState;
+  int TailState;
+  float HairCount;
+  float4 EarDirection[2];
+};
+
+struct AnimalBits {
+  int Legs[4];
+  uint State;
+  int64_t Counter;
+  float4 LeftDir;
+  float4 RightDir;
+};
+
+struct Kitteh {
+  int4 Legs;
+  int TailState;
+  float HairCount;
+  float4 Claws[2];
+};
+
+struct Zoo {
+  Doggo Dogs[2];
+  Kitteh Cats[4];
+};
+
+// Case 1: Extraneous braces get ignored in literal instantiation.
+// CHECK-LABEL: define void @_Z5case1v(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], 
ptr align 4 @__const._Z5case1v.TF1, i32 8, i1 false)
+// CHECK-NEXT:    ret void
+//
+TwoFloats case1() {
+  TwoFloats TF1 = {{{1.0, 2}}};
+  return TF1;
+}
+
+// Case 2: Valid C/C++ initializer is handled appropriately.
+// CHECK-LABEL: define void @_Z5case2v(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], 
ptr align 4 @__const._Z5case2v.TF2, i32 8, i1 false)
+// CHECK-NEXT:    ret void
+//
+TwoFloats case2() {
+  TwoFloats TF2 = {1, 2};
+  return TF2;
+}
+
+// Case 3: Simple initialization with conversion of an argument.
+// CHECK-LABEL: define void @_Z5case3i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef 
[[VAL:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[TMP0]] to float
+// CHECK-NEXT:    store float [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    store float 2.000000e+00, ptr [[Y]], align 4
+// CHECK-NEXT:    ret void
+//
+TwoFloats case3(int Val) {
+  TwoFloats TF3 = {Val, 2};
+  return TF3;
+}
+
+// Case 4: Initialization from a scalarized vector into a structure with 
element
+// conversions.
+// CHECK-LABEL: define void @_Z5case4Dv2_i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], <2 x i32> noundef 
[[TWOVALS:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TWOVALS_ADDR:%.*]] = alloca <2 x i32>, align 8
+// CHECK-NEXT:    store <2 x i32> [[TWOVALS]], ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x i32> [[TMP0]], i64 0
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[VECEXT]] to float
+// CHECK-NEXT:    store float [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[VECEXT1:%.*]] = extractelement <2 x i32> [[TMP1]], i64 1
+// CHECK-NEXT:    [[CONV2:%.*]] = sitofp i32 [[VECEXT1]] to float
+// CHECK-NEXT:    store float [[CONV2]], ptr [[Y]], align 4
+// CHECK-NEXT:    ret void
+//
+TwoFloats case4(int2 TwoVals) {
+  TwoFloats TF4 = {TwoVals};
+  return TF4;
+}
+
+// Case 5: Initialization from a scalarized vector of matching type.
+// CHECK-LABEL: define void @_Z5case5Dv2_i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], <2 x i32> noundef 
[[TWOVALS:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TWOVALS_ADDR:%.*]] = alloca <2 x i32>, align 8
+// CHECK-NEXT:    store <2 x i32> [[TWOVALS]], ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x i32> [[TMP0]], i64 0
+// CHECK-NEXT:    store i32 [[VECEXT]], ptr [[Z]], align 4
+// CHECK-NEXT:    [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT:    [[VECEXT1:%.*]] = extractelement <2 x i32> [[TMP1]], i64 1
+// CHECK-NEXT:    store i32 [[VECEXT1]], ptr [[W]], align 4
+// CHECK-NEXT:    ret void
+//
+TwoInts case5(int2 TwoVals) {
+  TwoInts TI1 = {TwoVals};
+  return TI1;
+}
+
+// Case 6: Initialization from a scalarized structure of different type with
+// different element types.
+// CHECK-LABEL: define void @_Z5case69TwoFloats(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef 
byval([[STRUCT_TWOFLOATS:%.*]]) align 4 [[TF4:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[TF4]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[X]], align 4
+// CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[TMP0]] to i32
+// CHECK-NEXT:    store i32 [[CONV]], ptr [[Z]], align 4
+// CHECK-NEXT:    [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[TF4]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[Y]], align 4
+// CHECK-NEXT:    [[CONV1:%.*]] = fptosi float [[TMP1]] to i32
+// CHECK-NEXT:    store i32 [[CONV1]], ptr [[W]], align 4
+// CHECK-NEXT:    ret void
+//
+TwoInts case6(TwoFloats TF4) {
+  TwoInts TI2 = {TF4};
+  return TI2;
+}
+
+// Case 7: Initialization of a complex structue, with bogus braces and element
+// conversions from a collection of scalar values, and structures.
+// CHECK-LABEL: define void @_Z5case77TwoIntsS_i9TwoFloatsS0_S0_S0_(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_DOGGO:%.*]]) 
align 16 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOINTS:%.*]]) align 4 
[[TI1:%.*]], ptr noundef byval([[STRUCT_TWOINTS]]) align 4 [[TI2:%.*]], i32 
noundef [[VAL:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 4 
[[TF1:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF2:%.*]], ptr 
noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF3:%.*]], ptr noundef 
byval([[STRUCT_TWOFLOATS]]) align 4 [[TF4:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[LEGSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[TI1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[Z]], align 4
+// CHECK-NEXT:    [[VECINIT:%.*]] = insertelement <4 x i32> poison, i32 
[[TMP0]], i32 0
+// CHECK-NEXT:    [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[TI1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[W]], align 4
+// CHECK-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x i32> [[VECINIT]], i32 
[[TMP1]], i32 1
+// CHECK-NEXT:    [[Z2:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[TI2]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z2]], align 4
+// CHECK-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x i32> [[VECINIT1]], i32 
[[TMP2]], i32 2
+// CHECK-NEXT:    [[W4:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], 
ptr [[TI2]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[W4]], align 4
+// CHECK-NEXT:    [[VECINIT5:%.*]] = insertelement <4 x i32> [[VECINIT3]], i32 
[[TMP3]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT5]], ptr [[LEGSTATE]], align 16
+// CHECK-NEXT:    [[TAILSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP4]], ptr [[TAILSTATE]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[TMP5]] to float
+// CHECK-NEXT:    store float [[CONV]], ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT:    [[EARDIRECTION:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 3
+// CHECK-NEXT:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[TF1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP6:%.*]] = load float, ptr [[X]], align 4
+// CHECK-NEXT:    [[VECINIT6:%.*]] = insertelement <4 x float> poison, float 
[[TMP6]], i32 0
+// CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], 
ptr [[TF1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP7:%.*]] = load float, ptr [[Y]], align 4
+// CHECK-NEXT:    [[VECINIT7:%.*]] = insertelement <4 x float> [[VECINIT6]], 
float [[TMP7]], i32 1
+// CHECK-NEXT:    [[X8:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP8:%.*]] = load float, ptr [[X8]], align 4
+// CHECK-NEXT:    [[VECINIT9:%.*]] = insertelement <4 x float> [[VECINIT7]], 
float [[TMP8]], i32 2
+// CHECK-NEXT:    [[Y10:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP9:%.*]] = load float, ptr [[Y10]], align 4
+// CHECK-NEXT:    [[VECINIT11:%.*]] = insertelement <4 x float> [[VECINIT9]], 
float [[TMP9]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT11]], ptr [[EARDIRECTION]], align 
16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[EARDIRECTION]], i32 1
+// CHECK-NEXT:    [[X12:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF3]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP10:%.*]] = load float, ptr [[X12]], align 4
+// CHECK-NEXT:    [[VECINIT13:%.*]] = insertelement <4 x float> poison, float 
[[TMP10]], i32 0
+// CHECK-NEXT:    [[Y14:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF3]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP11:%.*]] = load float, ptr [[Y14]], align 4
+// CHECK-NEXT:    [[VECINIT15:%.*]] = insertelement <4 x float> [[VECINIT13]], 
float [[TMP11]], i32 1
+// CHECK-NEXT:    [[X16:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP12:%.*]] = load float, ptr [[X16]], align 4
+// CHECK-NEXT:    [[VECINIT17:%.*]] = insertelement <4 x float> [[VECINIT15]], 
float [[TMP12]], i32 2
+// CHECK-NEXT:    [[Y18:%.*]] = getelementptr inbounds nuw 
[[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP13:%.*]] = load float, ptr [[Y18]], align 4
+// CHECK-NEXT:    [[VECINIT19:%.*]] = insertelement <4 x float> [[VECINIT17]], 
float [[TMP13]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT19]], ptr [[ARRAYINIT_ELEMENT]], 
align 16
+// CHECK-NEXT:    ret void
+//
+Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2,
+            TwoFloats TF3, TwoFloats TF4) {
+  Doggo D1 = {TI1, TI2, {Val, Val}, {{TF1, TF2}, {TF3, TF4}}};
+  return D1;
+}
+
+// Case 8: Initialization of a structure from a different structure with
+// significantly different element types and grouping.
+// CHECK-LABEL: define void @_Z5case85Doggo(
+// CHECK-SAME: ptr dead_on_unwind noalias writable 
sret([[STRUCT_ANIMALBITS:%.*]]) align 16 [[AGG_RESULT:%.*]], ptr noundef 
byval([[STRUCT_DOGGO:%.*]]) align 16 [[D1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[LEGS:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i32>, ptr [[LEGSTATE]], align 16
+// CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x i32> [[TMP0]], i64 0
+// CHECK-NEXT:    store i32 [[VECEXT]], ptr [[LEGS]], align 4
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr 
[[LEGS]], i32 1
+// CHECK-NEXT:    [[LEGSTATE1:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP1:%.*]] = load <4 x i32>, ptr [[LEGSTATE1]], align 16
+// CHECK-NEXT:    [[VECEXT2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+// CHECK-NEXT:    store i32 [[VECEXT2]], ptr [[ARRAYINIT_ELEMENT]], align 4
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT3:%.*]] = getelementptr inbounds i32, ptr 
[[LEGS]], i32 2
+// CHECK-NEXT:    [[LEGSTATE4:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load <4 x i32>, ptr [[LEGSTATE4]], align 16
+// CHECK-NEXT:    [[VECEXT5:%.*]] = extractelement <4 x i32> [[TMP2]], i64 2
+// CHECK-NEXT:    store i32 [[VECEXT5]], ptr [[ARRAYINIT_ELEMENT3]], align 4
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT6:%.*]] = getelementptr inbounds i32, ptr 
[[LEGS]], i32 3
+// CHECK-NEXT:    [[LEGSTATE7:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = load <4 x i32>, ptr [[LEGSTATE7]], align 16
+// CHECK-NEXT:    [[VECEXT8:%.*]] = extractelement <4 x i32> [[TMP3]], i64 3
+// CHECK-NEXT:    store i32 [[VECEXT8]], ptr [[ARRAYINIT_ELEMENT6]], align 4
+// CHECK-NEXT:    [[STATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[TAILSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TAILSTATE]], align 16
+// CHECK-NEXT:    store i32 [[TMP4]], ptr [[STATE]], align 16
+// CHECK-NEXT:    [[COUNTER:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT:    [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP5:%.*]] = load float, ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[TMP5]] to i64
+// CHECK-NEXT:    store i64 [[CONV]], ptr [[COUNTER]], align 8
+// CHECK-NEXT:    [[LEFTDIR:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 3
+// CHECK-NEXT:    [[EARDIRECTION:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP6:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 16
+// CHECK-NEXT:    [[VECEXT9:%.*]] = extractelement <4 x float> [[TMP6]], i64 0
+// CHECK-NEXT:    [[VECINIT:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT9]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION10:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION10]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP7:%.*]] = load <4 x float>, ptr [[ARRAYIDX11]], align 16
+// CHECK-NEXT:    [[VECEXT12:%.*]] = extractelement <4 x float> [[TMP7]], i64 1
+// CHECK-NEXT:    [[VECINIT13:%.*]] = insertelement <4 x float> [[VECINIT]], 
float [[VECEXT12]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION14:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION14]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX15]], align 16
+// CHECK-NEXT:    [[VECEXT16:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
+// CHECK-NEXT:    [[VECINIT17:%.*]] = insertelement <4 x float> [[VECINIT13]], 
float [[VECEXT16]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION18:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION18]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP9:%.*]] = load <4 x float>, ptr [[ARRAYIDX19]], align 16
+// CHECK-NEXT:    [[VECEXT20:%.*]] = extractelement <4 x float> [[TMP9]], i64 3
+// CHECK-NEXT:    [[VECINIT21:%.*]] = insertelement <4 x float> [[VECINIT17]], 
float [[VECEXT20]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT21]], ptr [[LEFTDIR]], align 16
+// CHECK-NEXT:    [[RIGHTDIR:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 4
+// CHECK-NEXT:    [[EARDIRECTION22:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX23:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION22]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP10:%.*]] = load <4 x float>, ptr [[ARRAYIDX23]], align 
16
+// CHECK-NEXT:    [[VECEXT24:%.*]] = extractelement <4 x float> [[TMP10]], i64 0
+// CHECK-NEXT:    [[VECINIT25:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT24]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION26:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX27:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION26]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP11:%.*]] = load <4 x float>, ptr [[ARRAYIDX27]], align 
16
+// CHECK-NEXT:    [[VECEXT28:%.*]] = extractelement <4 x float> [[TMP11]], i64 
1
+// CHECK-NEXT:    [[VECINIT29:%.*]] = insertelement <4 x float> [[VECINIT25]], 
float [[VECEXT28]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION30:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX31:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION30]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP12:%.*]] = load <4 x float>, ptr [[ARRAYIDX31]], align 
16
+// CHECK-NEXT:    [[VECEXT32:%.*]] = extractelement <4 x float> [[TMP12]], i64 
2
+// CHECK-NEXT:    [[VECINIT33:%.*]] = insertelement <4 x float> [[VECINIT29]], 
float [[VECEXT32]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION34:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX35:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION34]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP13:%.*]] = load <4 x float>, ptr [[ARRAYIDX35]], align 
16
+// CHECK-NEXT:    [[VECEXT36:%.*]] = extractelement <4 x float> [[TMP13]], i64 
3
+// CHECK-NEXT:    [[VECINIT37:%.*]] = insertelement <4 x float> [[VECINIT33]], 
float [[VECEXT36]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT37]], ptr [[RIGHTDIR]], align 16
+// CHECK-NEXT:    ret void
+//
+AnimalBits case8(Doggo D1) {
+  AnimalBits A1 = {D1};
+  return A1;
+}
+
+// Case 9: Everything everywhere all at once... Initializing mismatched
+// structures from different layouts, different component groupings, with no
+// top-level bracing separation.
+// CHECK-LABEL: define void @_Z5case95Doggo10AnimalBits(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_ZOO:%.*]]) 
align 16 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_DOGGO:%.*]]) align 16 
[[D1:%.*]], ptr noundef byval([[STRUCT_ANIMALBITS:%.*]]) align 16 [[A1:%.*]]) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DOGS:%.*]] = getelementptr inbounds nuw [[STRUCT_ZOO]], 
ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGSTATE1:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i32>, ptr [[LEGSTATE1]], align 16
+// CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x i32> [[TMP0]], i64 0
+// CHECK-NEXT:    [[VECINIT:%.*]] = insertelement <4 x i32> poison, i32 
[[VECEXT]], i32 0
+// CHECK-NEXT:    [[LEGSTATE2:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP1:%.*]] = load <4 x i32>, ptr [[LEGSTATE2]], align 16
+// CHECK-NEXT:    [[VECEXT3:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+// CHECK-NEXT:    [[VECINIT4:%.*]] = insertelement <4 x i32> [[VECINIT]], i32 
[[VECEXT3]], i32 1
+// CHECK-NEXT:    [[LEGSTATE5:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP2:%.*]] = load <4 x i32>, ptr [[LEGSTATE5]], align 16
+// CHECK-NEXT:    [[VECEXT6:%.*]] = extractelement <4 x i32> [[TMP2]], i64 2
+// CHECK-NEXT:    [[VECINIT7:%.*]] = insertelement <4 x i32> [[VECINIT4]], i32 
[[VECEXT6]], i32 2
+// CHECK-NEXT:    [[LEGSTATE8:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = load <4 x i32>, ptr [[LEGSTATE8]], align 16
+// CHECK-NEXT:    [[VECEXT9:%.*]] = extractelement <4 x i32> [[TMP3]], i64 3
+// CHECK-NEXT:    [[VECINIT10:%.*]] = insertelement <4 x i32> [[VECINIT7]], 
i32 [[VECEXT9]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT10]], ptr [[LEGSTATE]], align 16
+// CHECK-NEXT:    [[TAILSTATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 1
+// CHECK-NEXT:    [[TAILSTATE11:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TAILSTATE11]], align 16
+// CHECK-NEXT:    store i32 [[TMP4]], ptr [[TAILSTATE]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 2
+// CHECK-NEXT:    [[HAIRCOUNT12:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP5:%.*]] = load float, ptr [[HAIRCOUNT12]], align 4
+// CHECK-NEXT:    store float [[TMP5]], ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT:    [[EARDIRECTION:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 3
+// CHECK-NEXT:    [[EARDIRECTION13:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION13]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP6:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 16
+// CHECK-NEXT:    [[VECEXT14:%.*]] = extractelement <4 x float> [[TMP6]], i64 0
+// CHECK-NEXT:    [[VECINIT15:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT14]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION16:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION16]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP7:%.*]] = load <4 x float>, ptr [[ARRAYIDX17]], align 16
+// CHECK-NEXT:    [[VECEXT18:%.*]] = extractelement <4 x float> [[TMP7]], i64 1
+// CHECK-NEXT:    [[VECINIT19:%.*]] = insertelement <4 x float> [[VECINIT15]], 
float [[VECEXT18]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION20:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX21:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION20]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX21]], align 16
+// CHECK-NEXT:    [[VECEXT22:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
+// CHECK-NEXT:    [[VECINIT23:%.*]] = insertelement <4 x float> [[VECINIT19]], 
float [[VECEXT22]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION24:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX25:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION24]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP9:%.*]] = load <4 x float>, ptr [[ARRAYIDX25]], align 16
+// CHECK-NEXT:    [[VECEXT26:%.*]] = extractelement <4 x float> [[TMP9]], i64 3
+// CHECK-NEXT:    [[VECINIT27:%.*]] = insertelement <4 x float> [[VECINIT23]], 
float [[VECEXT26]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT27]], ptr [[EARDIRECTION]], align 
16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[EARDIRECTION]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION28:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX29:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION28]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP10:%.*]] = load <4 x float>, ptr [[ARRAYIDX29]], align 
16
+// CHECK-NEXT:    [[VECEXT30:%.*]] = extractelement <4 x float> [[TMP10]], i64 0
+// CHECK-NEXT:    [[VECINIT31:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT30]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION32:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX33:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION32]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP11:%.*]] = load <4 x float>, ptr [[ARRAYIDX33]], align 
16
+// CHECK-NEXT:    [[VECEXT34:%.*]] = extractelement <4 x float> [[TMP11]], i64 
1
+// CHECK-NEXT:    [[VECINIT35:%.*]] = insertelement <4 x float> [[VECINIT31]], 
float [[VECEXT34]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION36:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX37:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION36]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP12:%.*]] = load <4 x float>, ptr [[ARRAYIDX37]], align 
16
+// CHECK-NEXT:    [[VECEXT38:%.*]] = extractelement <4 x float> [[TMP12]], i64 
2
+// CHECK-NEXT:    [[VECINIT39:%.*]] = insertelement <4 x float> [[VECINIT35]], 
float [[VECEXT38]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION40:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX41:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION40]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP13:%.*]] = load <4 x float>, ptr [[ARRAYIDX41]], align 
16
+// CHECK-NEXT:    [[VECEXT42:%.*]] = extractelement <4 x float> [[TMP13]], i64 
3
+// CHECK-NEXT:    [[VECINIT43:%.*]] = insertelement <4 x float> [[VECINIT39]], 
float [[VECEXT42]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT43]], ptr [[ARRAYINIT_ELEMENT]], 
align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT44:%.*]] = getelementptr inbounds 
[[STRUCT_DOGGO]], ptr [[DOGS]], i32 1
+// CHECK-NEXT:    [[LEGSTATE45:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGS:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX46:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP14:%.*]] = load i32, ptr [[ARRAYIDX46]], align 16
+// CHECK-NEXT:    [[VECINIT47:%.*]] = insertelement <4 x i32> poison, i32 
[[TMP14]], i32 0
+// CHECK-NEXT:    [[LEGS48:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX49:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS48]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX49]], align 4
+// CHECK-NEXT:    [[VECINIT50:%.*]] = insertelement <4 x i32> [[VECINIT47]], 
i32 [[TMP15]], i32 1
+// CHECK-NEXT:    [[LEGS51:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX52:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS51]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX52]], align 8
+// CHECK-NEXT:    [[VECINIT53:%.*]] = insertelement <4 x i32> [[VECINIT50]], 
i32 [[TMP16]], i32 2
+// CHECK-NEXT:    [[LEGS54:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX55:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS54]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP17:%.*]] = load i32, ptr [[ARRAYIDX55]], align 4
+// CHECK-NEXT:    [[VECINIT56:%.*]] = insertelement <4 x i32> [[VECINIT53]], 
i32 [[TMP17]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT56]], ptr [[LEGSTATE45]], align 16
+// CHECK-NEXT:    [[TAILSTATE57:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 1
+// CHECK-NEXT:    [[STATE:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP18:%.*]] = load i32, ptr [[STATE]], align 16
+// CHECK-NEXT:    store i32 [[TMP18]], ptr [[TAILSTATE57]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT58:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 2
+// CHECK-NEXT:    [[COUNTER:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP19:%.*]] = load i64, ptr [[COUNTER]], align 8
+// CHECK-NEXT:    [[CONV:%.*]] = sitofp i64 [[TMP19]] to float
+// CHECK-NEXT:    store float [[CONV]], ptr [[HAIRCOUNT58]], align 4
+// CHECK-NEXT:    [[EARDIRECTION59:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 3
+// CHECK-NEXT:    [[LEFTDIR:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP20:%.*]] = load <4 x float>, ptr [[LEFTDIR]], align 16
+// CHECK-NEXT:    [[VECEXT60:%.*]] = extractelement <4 x float> [[TMP20]], i64 0
+// CHECK-NEXT:    [[VECINIT61:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT60]], i32 0
+// CHECK-NEXT:    [[LEFTDIR62:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP21:%.*]] = load <4 x float>, ptr [[LEFTDIR62]], align 16
+// CHECK-NEXT:    [[VECEXT63:%.*]] = extractelement <4 x float> [[TMP21]], i64 
1
+// CHECK-NEXT:    [[VECINIT64:%.*]] = insertelement <4 x float> [[VECINIT61]], 
float [[VECEXT63]], i32 1
+// CHECK-NEXT:    [[LEFTDIR65:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP22:%.*]] = load <4 x float>, ptr [[LEFTDIR65]], align 16
+// CHECK-NEXT:    [[VECEXT66:%.*]] = extractelement <4 x float> [[TMP22]], i64 
2
+// CHECK-NEXT:    [[VECINIT67:%.*]] = insertelement <4 x float> [[VECINIT64]], 
float [[VECEXT66]], i32 2
+// CHECK-NEXT:    [[LEFTDIR68:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP23:%.*]] = load <4 x float>, ptr [[LEFTDIR68]], align 16
+// CHECK-NEXT:    [[VECEXT69:%.*]] = extractelement <4 x float> [[TMP23]], i64 
3
+// CHECK-NEXT:    [[VECINIT70:%.*]] = insertelement <4 x float> [[VECINIT67]], 
float [[VECEXT69]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT70]], ptr [[EARDIRECTION59]], 
align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT71:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[EARDIRECTION59]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP24:%.*]] = load <4 x float>, ptr [[RIGHTDIR]], align 16
+// CHECK-NEXT:    [[VECEXT72:%.*]] = extractelement <4 x float> [[TMP24]], i64 0
+// CHECK-NEXT:    [[VECINIT73:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT72]], i32 0
+// CHECK-NEXT:    [[RIGHTDIR74:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP25:%.*]] = load <4 x float>, ptr [[RIGHTDIR74]], align 
16
+// CHECK-NEXT:    [[VECEXT75:%.*]] = extractelement <4 x float> [[TMP25]], i64 
1
+// CHECK-NEXT:    [[VECINIT76:%.*]] = insertelement <4 x float> [[VECINIT73]], 
float [[VECEXT75]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR77:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP26:%.*]] = load <4 x float>, ptr [[RIGHTDIR77]], align 
16
+// CHECK-NEXT:    [[VECEXT78:%.*]] = extractelement <4 x float> [[TMP26]], i64 
2
+// CHECK-NEXT:    [[VECINIT79:%.*]] = insertelement <4 x float> [[VECINIT76]], 
float [[VECEXT78]], i32 2
+// CHECK-NEXT:    [[RIGHTDIR80:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP27:%.*]] = load <4 x float>, ptr [[RIGHTDIR80]], align 
16
+// CHECK-NEXT:    [[VECEXT81:%.*]] = extractelement <4 x float> [[TMP27]], i64 
3
+// CHECK-NEXT:    [[VECINIT82:%.*]] = insertelement <4 x float> [[VECINIT79]], 
float [[VECEXT81]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT82]], ptr 
[[ARRAYINIT_ELEMENT71]], align 16
+// CHECK-NEXT:    [[CATS:%.*]] = getelementptr inbounds nuw [[STRUCT_ZOO]], 
ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT:    [[LEGS83:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH:%.*]], ptr [[CATS]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGSTATE84:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP28:%.*]] = load <4 x i32>, ptr [[LEGSTATE84]], align 16
+// CHECK-NEXT:    [[VECEXT85:%.*]] = extractelement <4 x i32> [[TMP28]], i64 0
+// CHECK-NEXT:    [[VECINIT86:%.*]] = insertelement <4 x i32> poison, i32 
[[VECEXT85]], i32 0
+// CHECK-NEXT:    [[LEGSTATE87:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP29:%.*]] = load <4 x i32>, ptr [[LEGSTATE87]], align 16
+// CHECK-NEXT:    [[VECEXT88:%.*]] = extractelement <4 x i32> [[TMP29]], i64 1
+// CHECK-NEXT:    [[VECINIT89:%.*]] = insertelement <4 x i32> [[VECINIT86]], 
i32 [[VECEXT88]], i32 1
+// CHECK-NEXT:    [[LEGSTATE90:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP30:%.*]] = load <4 x i32>, ptr [[LEGSTATE90]], align 16
+// CHECK-NEXT:    [[VECEXT91:%.*]] = extractelement <4 x i32> [[TMP30]], i64 2
+// CHECK-NEXT:    [[VECINIT92:%.*]] = insertelement <4 x i32> [[VECINIT89]], 
i32 [[VECEXT91]], i32 2
+// CHECK-NEXT:    [[LEGSTATE93:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP31:%.*]] = load <4 x i32>, ptr [[LEGSTATE93]], align 16
+// CHECK-NEXT:    [[VECEXT94:%.*]] = extractelement <4 x i32> [[TMP31]], i64 3
+// CHECK-NEXT:    [[VECINIT95:%.*]] = insertelement <4 x i32> [[VECINIT92]], 
i32 [[VECEXT94]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT95]], ptr [[LEGS83]], align 16
+// CHECK-NEXT:    [[TAILSTATE96:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 1
+// CHECK-NEXT:    [[TAILSTATE97:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TAILSTATE97]], align 16
+// CHECK-NEXT:    store i32 [[TMP32]], ptr [[TAILSTATE96]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT98:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 2
+// CHECK-NEXT:    [[HAIRCOUNT99:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP33:%.*]] = load float, ptr [[HAIRCOUNT99]], align 4
+// CHECK-NEXT:    store float [[TMP33]], ptr [[HAIRCOUNT98]], align 4
+// CHECK-NEXT:    [[CLAWS:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 3
+// CHECK-NEXT:    [[EARDIRECTION100:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX101:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION100]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP34:%.*]] = load <4 x float>, ptr [[ARRAYIDX101]], align 
16
+// CHECK-NEXT:    [[VECEXT102:%.*]] = extractelement <4 x float> [[TMP34]], 
i64 0
+// CHECK-NEXT:    [[VECINIT103:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT102]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION104:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX105:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION104]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP35:%.*]] = load <4 x float>, ptr [[ARRAYIDX105]], align 
16
+// CHECK-NEXT:    [[VECEXT106:%.*]] = extractelement <4 x float> [[TMP35]], 
i64 1
+// CHECK-NEXT:    [[VECINIT107:%.*]] = insertelement <4 x float> 
[[VECINIT103]], float [[VECEXT106]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION108:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX109:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION108]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP36:%.*]] = load <4 x float>, ptr [[ARRAYIDX109]], align 
16
+// CHECK-NEXT:    [[VECEXT110:%.*]] = extractelement <4 x float> [[TMP36]], 
i64 2
+// CHECK-NEXT:    [[VECINIT111:%.*]] = insertelement <4 x float> 
[[VECINIT107]], float [[VECEXT110]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION112:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX113:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION112]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP37:%.*]] = load <4 x float>, ptr [[ARRAYIDX113]], align 
16
+// CHECK-NEXT:    [[VECEXT114:%.*]] = extractelement <4 x float> [[TMP37]], 
i64 3
+// CHECK-NEXT:    [[VECINIT115:%.*]] = insertelement <4 x float> 
[[VECINIT111]], float [[VECEXT114]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT115]], ptr [[CLAWS]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT116:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[CLAWS]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION117:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX118:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION117]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP38:%.*]] = load <4 x float>, ptr [[ARRAYIDX118]], align 
16
+// CHECK-NEXT:    [[VECEXT119:%.*]] = extractelement <4 x float> [[TMP38]], 
i64 0
+// CHECK-NEXT:    [[VECINIT120:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT119]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION121:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX122:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION121]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP39:%.*]] = load <4 x float>, ptr [[ARRAYIDX122]], align 
16
+// CHECK-NEXT:    [[VECEXT123:%.*]] = extractelement <4 x float> [[TMP39]], 
i64 1
+// CHECK-NEXT:    [[VECINIT124:%.*]] = insertelement <4 x float> 
[[VECINIT120]], float [[VECEXT123]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION125:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX126:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION125]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP40:%.*]] = load <4 x float>, ptr [[ARRAYIDX126]], align 
16
+// CHECK-NEXT:    [[VECEXT127:%.*]] = extractelement <4 x float> [[TMP40]], 
i64 2
+// CHECK-NEXT:    [[VECINIT128:%.*]] = insertelement <4 x float> 
[[VECINIT124]], float [[VECEXT127]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION129:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX130:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION129]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP41:%.*]] = load <4 x float>, ptr [[ARRAYIDX130]], align 
16
+// CHECK-NEXT:    [[VECEXT131:%.*]] = extractelement <4 x float> [[TMP41]], 
i64 3
+// CHECK-NEXT:    [[VECINIT132:%.*]] = insertelement <4 x float> 
[[VECINIT128]], float [[VECEXT131]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT132]], ptr 
[[ARRAYINIT_ELEMENT116]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT133:%.*]] = getelementptr inbounds 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 1
+// CHECK-NEXT:    [[LEGS134:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGS135:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX136:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS135]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP42:%.*]] = load i32, ptr [[ARRAYIDX136]], align 16
+// CHECK-NEXT:    [[VECINIT137:%.*]] = insertelement <4 x i32> poison, i32 
[[TMP42]], i32 0
+// CHECK-NEXT:    [[LEGS138:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX139:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS138]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP43:%.*]] = load i32, ptr [[ARRAYIDX139]], align 4
+// CHECK-NEXT:    [[VECINIT140:%.*]] = insertelement <4 x i32> [[VECINIT137]], 
i32 [[TMP43]], i32 1
+// CHECK-NEXT:    [[LEGS141:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX142:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS141]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP44:%.*]] = load i32, ptr [[ARRAYIDX142]], align 8
+// CHECK-NEXT:    [[VECINIT143:%.*]] = insertelement <4 x i32> [[VECINIT140]], 
i32 [[TMP44]], i32 2
+// CHECK-NEXT:    [[LEGS144:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX145:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS144]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP45:%.*]] = load i32, ptr [[ARRAYIDX145]], align 4
+// CHECK-NEXT:    [[VECINIT146:%.*]] = insertelement <4 x i32> [[VECINIT143]], 
i32 [[TMP45]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT146]], ptr [[LEGS134]], align 16
+// CHECK-NEXT:    [[TAILSTATE147:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 1
+// CHECK-NEXT:    [[STATE148:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP46:%.*]] = load i32, ptr [[STATE148]], align 16
+// CHECK-NEXT:    store i32 [[TMP46]], ptr [[TAILSTATE147]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT149:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 2
+// CHECK-NEXT:    [[COUNTER150:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP47:%.*]] = load i64, ptr [[COUNTER150]], align 8
+// CHECK-NEXT:    [[CONV151:%.*]] = sitofp i64 [[TMP47]] to float
+// CHECK-NEXT:    store float [[CONV151]], ptr [[HAIRCOUNT149]], align 4
+// CHECK-NEXT:    [[CLAWS152:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 3
+// CHECK-NEXT:    [[LEFTDIR153:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP48:%.*]] = load <4 x float>, ptr [[LEFTDIR153]], align 
16
+// CHECK-NEXT:    [[VECEXT154:%.*]] = extractelement <4 x float> [[TMP48]], 
i64 0
+// CHECK-NEXT:    [[VECINIT155:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT154]], i32 0
+// CHECK-NEXT:    [[LEFTDIR156:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP49:%.*]] = load <4 x float>, ptr [[LEFTDIR156]], align 
16
+// CHECK-NEXT:    [[VECEXT157:%.*]] = extractelement <4 x float> [[TMP49]], 
i64 1
+// CHECK-NEXT:    [[VECINIT158:%.*]] = insertelement <4 x float> 
[[VECINIT155]], float [[VECEXT157]], i32 1
+// CHECK-NEXT:    [[LEFTDIR159:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP50:%.*]] = load <4 x float>, ptr [[LEFTDIR159]], align 
16
+// CHECK-NEXT:    [[VECEXT160:%.*]] = extractelement <4 x float> [[TMP50]], 
i64 2
+// CHECK-NEXT:    [[VECINIT161:%.*]] = insertelement <4 x float> 
[[VECINIT158]], float [[VECEXT160]], i32 2
+// CHECK-NEXT:    [[LEFTDIR162:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP51:%.*]] = load <4 x float>, ptr [[LEFTDIR162]], align 
16
+// CHECK-NEXT:    [[VECEXT163:%.*]] = extractelement <4 x float> [[TMP51]], 
i64 3
+// CHECK-NEXT:    [[VECINIT164:%.*]] = insertelement <4 x float> 
[[VECINIT161]], float [[VECEXT163]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT164]], ptr [[CLAWS152]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT165:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[CLAWS152]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR166:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP52:%.*]] = load <4 x float>, ptr [[RIGHTDIR166]], align 
16
+// CHECK-NEXT:    [[VECEXT167:%.*]] = extractelement <4 x float> [[TMP52]], 
i64 0
+// CHECK-NEXT:    [[VECINIT168:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT167]], i32 0
+// CHECK-NEXT:    [[RIGHTDIR169:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP53:%.*]] = load <4 x float>, ptr [[RIGHTDIR169]], align 
16
+// CHECK-NEXT:    [[VECEXT170:%.*]] = extractelement <4 x float> [[TMP53]], 
i64 1
+// CHECK-NEXT:    [[VECINIT171:%.*]] = insertelement <4 x float> 
[[VECINIT168]], float [[VECEXT170]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR172:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP54:%.*]] = load <4 x float>, ptr [[RIGHTDIR172]], align 
16
+// CHECK-NEXT:    [[VECEXT173:%.*]] = extractelement <4 x float> [[TMP54]], 
i64 2
+// CHECK-NEXT:    [[VECINIT174:%.*]] = insertelement <4 x float> 
[[VECINIT171]], float [[VECEXT173]], i32 2
+// CHECK-NEXT:    [[RIGHTDIR175:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP55:%.*]] = load <4 x float>, ptr [[RIGHTDIR175]], align 
16
+// CHECK-NEXT:    [[VECEXT176:%.*]] = extractelement <4 x float> [[TMP55]], 
i64 3
+// CHECK-NEXT:    [[VECINIT177:%.*]] = insertelement <4 x float> 
[[VECINIT174]], float [[VECEXT176]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT177]], ptr 
[[ARRAYINIT_ELEMENT165]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT178:%.*]] = getelementptr inbounds 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 2
+// CHECK-NEXT:    [[LEGS179:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGSTATE180:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP56:%.*]] = load <4 x i32>, ptr [[LEGSTATE180]], align 16
+// CHECK-NEXT:    [[VECEXT181:%.*]] = extractelement <4 x i32> [[TMP56]], i64 0
+// CHECK-NEXT:    [[VECINIT182:%.*]] = insertelement <4 x i32> poison, i32 
[[VECEXT181]], i32 0
+// CHECK-NEXT:    [[LEGSTATE183:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP57:%.*]] = load <4 x i32>, ptr [[LEGSTATE183]], align 16
+// CHECK-NEXT:    [[VECEXT184:%.*]] = extractelement <4 x i32> [[TMP57]], i64 1
+// CHECK-NEXT:    [[VECINIT185:%.*]] = insertelement <4 x i32> [[VECINIT182]], 
i32 [[VECEXT184]], i32 1
+// CHECK-NEXT:    [[LEGSTATE186:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP58:%.*]] = load <4 x i32>, ptr [[LEGSTATE186]], align 16
+// CHECK-NEXT:    [[VECEXT187:%.*]] = extractelement <4 x i32> [[TMP58]], i64 2
+// CHECK-NEXT:    [[VECINIT188:%.*]] = insertelement <4 x i32> [[VECINIT185]], 
i32 [[VECEXT187]], i32 2
+// CHECK-NEXT:    [[LEGSTATE189:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP59:%.*]] = load <4 x i32>, ptr [[LEGSTATE189]], align 16
+// CHECK-NEXT:    [[VECEXT190:%.*]] = extractelement <4 x i32> [[TMP59]], i64 3
+// CHECK-NEXT:    [[VECINIT191:%.*]] = insertelement <4 x i32> [[VECINIT188]], 
i32 [[VECEXT190]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT191]], ptr [[LEGS179]], align 16
+// CHECK-NEXT:    [[TAILSTATE192:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 1
+// CHECK-NEXT:    [[TAILSTATE193:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP60:%.*]] = load i32, ptr [[TAILSTATE193]], align 16
+// CHECK-NEXT:    store i32 [[TMP60]], ptr [[TAILSTATE192]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT194:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 2
+// CHECK-NEXT:    [[HAIRCOUNT195:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP61:%.*]] = load float, ptr [[HAIRCOUNT195]], align 4
+// CHECK-NEXT:    store float [[TMP61]], ptr [[HAIRCOUNT194]], align 4
+// CHECK-NEXT:    [[CLAWS196:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 3
+// CHECK-NEXT:    [[EARDIRECTION197:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX198:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION197]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP62:%.*]] = load <4 x float>, ptr [[ARRAYIDX198]], align 
16
+// CHECK-NEXT:    [[VECEXT199:%.*]] = extractelement <4 x float> [[TMP62]], 
i64 0
+// CHECK-NEXT:    [[VECINIT200:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT199]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION201:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX202:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION201]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP63:%.*]] = load <4 x float>, ptr [[ARRAYIDX202]], align 
16
+// CHECK-NEXT:    [[VECEXT203:%.*]] = extractelement <4 x float> [[TMP63]], 
i64 1
+// CHECK-NEXT:    [[VECINIT204:%.*]] = insertelement <4 x float> 
[[VECINIT200]], float [[VECEXT203]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION205:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX206:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION205]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP64:%.*]] = load <4 x float>, ptr [[ARRAYIDX206]], align 
16
+// CHECK-NEXT:    [[VECEXT207:%.*]] = extractelement <4 x float> [[TMP64]], 
i64 2
+// CHECK-NEXT:    [[VECINIT208:%.*]] = insertelement <4 x float> 
[[VECINIT204]], float [[VECEXT207]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION209:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX210:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION209]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP65:%.*]] = load <4 x float>, ptr [[ARRAYIDX210]], align 
16
+// CHECK-NEXT:    [[VECEXT211:%.*]] = extractelement <4 x float> [[TMP65]], 
i64 3
+// CHECK-NEXT:    [[VECINIT212:%.*]] = insertelement <4 x float> 
[[VECINIT208]], float [[VECEXT211]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT212]], ptr [[CLAWS196]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT213:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[CLAWS196]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION214:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX215:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION214]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP66:%.*]] = load <4 x float>, ptr [[ARRAYIDX215]], align 
16
+// CHECK-NEXT:    [[VECEXT216:%.*]] = extractelement <4 x float> [[TMP66]], 
i64 0
+// CHECK-NEXT:    [[VECINIT217:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT216]], i32 0
+// CHECK-NEXT:    [[EARDIRECTION218:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX219:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION218]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP67:%.*]] = load <4 x float>, ptr [[ARRAYIDX219]], align 
16
+// CHECK-NEXT:    [[VECEXT220:%.*]] = extractelement <4 x float> [[TMP67]], 
i64 1
+// CHECK-NEXT:    [[VECINIT221:%.*]] = insertelement <4 x float> 
[[VECINIT217]], float [[VECEXT220]], i32 1
+// CHECK-NEXT:    [[EARDIRECTION222:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX223:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION222]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP68:%.*]] = load <4 x float>, ptr [[ARRAYIDX223]], align 
16
+// CHECK-NEXT:    [[VECEXT224:%.*]] = extractelement <4 x float> [[TMP68]], 
i64 2
+// CHECK-NEXT:    [[VECINIT225:%.*]] = insertelement <4 x float> 
[[VECINIT221]], float [[VECEXT224]], i32 2
+// CHECK-NEXT:    [[EARDIRECTION226:%.*]] = getelementptr inbounds nuw 
[[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT:    [[ARRAYIDX227:%.*]] = getelementptr inbounds nuw [2 x <4 x 
float>], ptr [[EARDIRECTION226]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP69:%.*]] = load <4 x float>, ptr [[ARRAYIDX227]], align 
16
+// CHECK-NEXT:    [[VECEXT228:%.*]] = extractelement <4 x float> [[TMP69]], 
i64 3
+// CHECK-NEXT:    [[VECINIT229:%.*]] = insertelement <4 x float> 
[[VECINIT225]], float [[VECEXT228]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT229]], ptr 
[[ARRAYINIT_ELEMENT213]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT230:%.*]] = getelementptr inbounds 
[[STRUCT_KITTEH]], ptr [[CATS]], i32 3
+// CHECK-NEXT:    [[LEGS231:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 0
+// CHECK-NEXT:    [[LEGS232:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX233:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS232]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP70:%.*]] = load i32, ptr [[ARRAYIDX233]], align 16
+// CHECK-NEXT:    [[VECINIT234:%.*]] = insertelement <4 x i32> poison, i32 
[[TMP70]], i32 0
+// CHECK-NEXT:    [[LEGS235:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX236:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS235]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP71:%.*]] = load i32, ptr [[ARRAYIDX236]], align 4
+// CHECK-NEXT:    [[VECINIT237:%.*]] = insertelement <4 x i32> [[VECINIT234]], 
i32 [[TMP71]], i32 1
+// CHECK-NEXT:    [[LEGS238:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX239:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS238]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP72:%.*]] = load i32, ptr [[ARRAYIDX239]], align 8
+// CHECK-NEXT:    [[VECINIT240:%.*]] = insertelement <4 x i32> [[VECINIT237]], 
i32 [[TMP72]], i32 2
+// CHECK-NEXT:    [[LEGS241:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT:    [[ARRAYIDX242:%.*]] = getelementptr inbounds nuw [4 x i32], 
ptr [[LEGS241]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP73:%.*]] = load i32, ptr [[ARRAYIDX242]], align 4
+// CHECK-NEXT:    [[VECINIT243:%.*]] = insertelement <4 x i32> [[VECINIT240]], 
i32 [[TMP73]], i32 3
+// CHECK-NEXT:    store <4 x i32> [[VECINIT243]], ptr [[LEGS231]], align 16
+// CHECK-NEXT:    [[TAILSTATE244:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 1
+// CHECK-NEXT:    [[STATE245:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT:    [[TMP74:%.*]] = load i32, ptr [[STATE245]], align 16
+// CHECK-NEXT:    store i32 [[TMP74]], ptr [[TAILSTATE244]], align 16
+// CHECK-NEXT:    [[HAIRCOUNT246:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 2
+// CHECK-NEXT:    [[COUNTER247:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP75:%.*]] = load i64, ptr [[COUNTER247]], align 8
+// CHECK-NEXT:    [[CONV248:%.*]] = sitofp i64 [[TMP75]] to float
+// CHECK-NEXT:    store float [[CONV248]], ptr [[HAIRCOUNT246]], align 4
+// CHECK-NEXT:    [[CLAWS249:%.*]] = getelementptr inbounds nuw 
[[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 3
+// CHECK-NEXT:    [[LEFTDIR250:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP76:%.*]] = load <4 x float>, ptr [[LEFTDIR250]], align 
16
+// CHECK-NEXT:    [[VECEXT251:%.*]] = extractelement <4 x float> [[TMP76]], 
i64 0
+// CHECK-NEXT:    [[VECINIT252:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT251]], i32 0
+// CHECK-NEXT:    [[LEFTDIR253:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP77:%.*]] = load <4 x float>, ptr [[LEFTDIR253]], align 
16
+// CHECK-NEXT:    [[VECEXT254:%.*]] = extractelement <4 x float> [[TMP77]], 
i64 1
+// CHECK-NEXT:    [[VECINIT255:%.*]] = insertelement <4 x float> 
[[VECINIT252]], float [[VECEXT254]], i32 1
+// CHECK-NEXT:    [[LEFTDIR256:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP78:%.*]] = load <4 x float>, ptr [[LEFTDIR256]], align 
16
+// CHECK-NEXT:    [[VECEXT257:%.*]] = extractelement <4 x float> [[TMP78]], 
i64 2
+// CHECK-NEXT:    [[VECINIT258:%.*]] = insertelement <4 x float> 
[[VECINIT255]], float [[VECEXT257]], i32 2
+// CHECK-NEXT:    [[LEFTDIR259:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT:    [[TMP79:%.*]] = load <4 x float>, ptr [[LEFTDIR259]], align 
16
+// CHECK-NEXT:    [[VECEXT260:%.*]] = extractelement <4 x float> [[TMP79]], 
i64 3
+// CHECK-NEXT:    [[VECINIT261:%.*]] = insertelement <4 x float> 
[[VECINIT258]], float [[VECEXT260]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT261]], ptr [[CLAWS249]], align 16
+// CHECK-NEXT:    [[ARRAYINIT_ELEMENT262:%.*]] = getelementptr inbounds <4 x 
float>, ptr [[CLAWS249]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR263:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP80:%.*]] = load <4 x float>, ptr [[RIGHTDIR263]], align 
16
+// CHECK-NEXT:    [[VECEXT264:%.*]] = extractelement <4 x float> [[TMP80]], 
i64 0
+// CHECK-NEXT:    [[VECINIT265:%.*]] = insertelement <4 x float> poison, float 
[[VECEXT264]], i32 0
+// CHECK-NEXT:    [[RIGHTDIR266:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP81:%.*]] = load <4 x float>, ptr [[RIGHTDIR266]], align 
16
+// CHECK-NEXT:    [[VECEXT267:%.*]] = extractelement <4 x float> [[TMP81]], 
i64 1
+// CHECK-NEXT:    [[VECINIT268:%.*]] = insertelement <4 x float> 
[[VECINIT265]], float [[VECEXT267]], i32 1
+// CHECK-NEXT:    [[RIGHTDIR269:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP82:%.*]] = load <4 x float>, ptr [[RIGHTDIR269]], align 
16
+// CHECK-NEXT:    [[VECEXT270:%.*]] = extractelement <4 x float> [[TMP82]], 
i64 2
+// CHECK-NEXT:    [[VECINIT271:%.*]] = insertelement <4 x float> 
[[VECINIT268]], float [[VECEXT270]], i32 2
+// CHECK-NEXT:    [[RIGHTDIR272:%.*]] = getelementptr inbounds nuw 
[[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT:    [[TMP83:%.*]] = load <4 x float>, ptr [[RIGHTDIR272]], align 
16
+// CHECK-NEXT:    [[VECEXT273:%.*]] = extractelement <4 x float> [[TMP83]], 
i64 3
+// CHECK-NEXT:    [[VECINIT274:%.*]] = insertelement <4 x float> 
[[VECINIT271]], float [[VECEXT273]], i32 3
+// CHECK-NEXT:    store <4 x float> [[VECINIT274]], ptr 
[[ARRAYINIT_ELEMENT262]], align 16
+// CHECK-NEXT:    ret void
+//
+Zoo case9(Doggo D1, AnimalBits A1) {
+  Zoo Z1 = {D1, A1, D1, A1, D1, A1};
+  return Z1;
+}
diff --git a/clang/test/SemaHLSL/ArrayTemporary.hlsl 
b/clang/test/SemaHLSL/ArrayTemporary.hlsl
index 0266a198e7ec987..3d713a89adf3b3e 100644
--- a/clang/test/SemaHLSL/ArrayTemporary.hlsl
+++ b/clang/test/SemaHLSL/ArrayTemporary.hlsl
@@ -25,7 +25,7 @@ void fn2(Obj O[4]) { }
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'Obj[4]' <HLSLArrayRValue>
 
 void call2() {
-  Obj Arr[4] = {};
+  Obj Arr[4] = {0, 0, 0, 0, 0, 0, 0, 0};
   fn2(Arr);
 }
 
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl 
b/clang/test/SemaHLSL/Language/InitLists.hlsl
new file mode 100644
index 000000000000000..0059e5b44035f94
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute 
-finclude-default-header -verify -Wdouble-promotion -Wconversion %s
+
+struct TwoFloats {
+  float X, Y;
+};
+
+struct TwoInts {
+  int Z, W;
+};
+
+struct Doggo {
+  int4 LegState;
+  int TailState;
+  float HairCount;
+  float4 EarDirection[2];
+};
+
+struct AnimalBits {
+  int Legs[4];
+  uint State;
+  int64_t Counter;
+  float4 LeftDir;
+  float4 RightDir;
+};
+
+struct Kitteh {
+  int4 Legs;
+  int TailState;
+  float HairCount;
+  float4 Claws[2];
+};
+
+struct Zoo {
+  Doggo Dogs[2];
+  Kitteh Cats[4];
+};
+
+void fn() {
+  TwoFloats TF1 = {{{1.0, 2}}};
+  TwoFloats TF2 = {1,2};
+  int Val = 1;
+  TwoFloats TF3 = {Val, 2}; // expected-warning{{implicit conversion from 
'int' to 'float' may lose precision}}
+  int2 TwoVals = 1.xx;
+  int2 Something = 1.xxx; // expected-warning{{implicit conversion truncates 
vector: 'vector<int, 3>' (vector of 3 'int' values) to 'vector<int, 2>' (vector 
of 2 'int' values)}}
+  TwoFloats TF4 = {TwoVals}; // expected-warning{{implicit conversion from 
'int' to 'float' may lose precision}} expected-warning{{implicit conversion 
from 'int' to 'float' may lose precision}}
+
+  TwoInts TI1 = {TwoVals};
+  TwoInts TI2 = {TF4}; // expected-warning{{implicit conversion turns 
floating-point number into integer: 'float' to 'int'}} 
expected-warning{{implicit conversion turns floating-point number into integer: 
'float' to 'int'}}
+
+  Doggo D1 = {TI1, TI2, {Val, Val}, {{TF1, TF2}, {TF3, TF4}}}; // 
expected-warning{{implicit conversion from 'int' to 'float' may lose precision}}
+  AnimalBits A1 = {D1}; // expected-warning{{implicit conversion turns 
floating-point number into integer: 'float' to 'long'}} 
expected-warning{{implicit conversion changes signedness: 'int' to 'unsigned 
int'}}
+
+  Zoo Z1 = {D1, A1, D1, A1, D1, A1}; // #insanity
+
+  // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 
'long') to 'float' may lose precision}}
+  // expected-warning@#insanity{{implicit conversion changes signedness: 
'uint' (aka 'unsigned int') to 'int'}}
+  // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 
'long') to 'float' may lose precision}}
+  // expected-warning@#insanity{{implicit conversion changes signedness: 
'uint' (aka 'unsigned int') to 'int'}}
+  // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 
'long') to 'float' may lose precision}}
+  // expected-warning@#insanity{{implicit conversion changes signedness: 
'uint' (aka 'unsigned int') to 'int'}}
+}
+
+void Errs() {
+  TwoFloats F1 = {}; // expected-error{{too few initializers in list for type 
'TwoFloats' (expected 2 but found 0)}}
+  TwoFloats F2 = {1}; // expected-error{{too few initializers in list for type 
'TwoFloats' (expected 2 but found 1)}}
+  TwoFloats F3 = {1,2,3}; // expected-error{{too many initializers in list for 
type 'TwoFloats' (expected 2 but found 2)}}
+
+  int2 Something = {1.xxx}; // expected-error{{too many initializers in list 
for type 'int2' (aka 'vector<int, 2>') (expected 2 but found 0)}}
+}

>From f8811e62245edaa602881ab8e56430efdfdf25d9 Mon Sep 17 00:00:00 2001
From: Chris B <cbiene...@microsoft.com>
Date: Mon, 10 Feb 2025 15:01:47 -0600
Subject: [PATCH 2/4] Update clang/test/SemaHLSL/Language/InitLists.hlsl

Doh!

Co-authored-by: Finn Plummer <50529406+inbe...@users.noreply.github.com>
---
 clang/test/SemaHLSL/Language/InitLists.hlsl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl 
b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 0059e5b44035f94..1f7baf35ed2e3ee 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -63,7 +63,7 @@ void fn() {
 void Errs() {
   TwoFloats F1 = {}; // expected-error{{too few initializers in list for type 
'TwoFloats' (expected 2 but found 0)}}
   TwoFloats F2 = {1}; // expected-error{{too few initializers in list for type 
'TwoFloats' (expected 2 but found 1)}}
-  TwoFloats F3 = {1,2,3}; // expected-error{{too many initializers in list for 
type 'TwoFloats' (expected 2 but found 2)}}
+  TwoFloats F3 = {1,2,3}; // expected-error{{too many initializers in list for 
type 'TwoFloats' (expected 2 but found 3)}}
 
   int2 Something = {1.xxx}; // expected-error{{too many initializers in list 
for type 'int2' (aka 'vector<int, 2>') (expected 2 but found 0)}}
 }

>From 091a7330402f34d95b90bb119a554c3ce8f22f86 Mon Sep 17 00:00:00 2001
From: Chris B <cbiene...@microsoft.com>
Date: Mon, 10 Feb 2025 15:02:21 -0600
Subject: [PATCH 3/4] Update clang/lib/Sema/SemaHLSL.cpp

I swear I can spell...

Co-authored-by: Helena Kotas <heko...@microsoft.com>
---
 clang/lib/Sema/SemaHLSL.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f9f1473d4e0bab9..8b30ec2c07d72a9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2593,7 +2593,7 @@ static bool CastInitializer(Sema &S, ASTContext &Ctx, 
Expr *E,
   return true;
 }
 
-static void BuildIntializerList(Sema &S, ASTContext &Ctx, Expr *E,
+static void BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E,
                                 llvm::SmallVectorImpl<Expr *> &List,
                                 llvm::SmallVectorImpl<QualType> &DestTypes,
                                 bool &ExcessInits) {

>From 34124c6388895d7dddd774dbd78d44ed8b7360cc Mon Sep 17 00:00:00 2001
From: Chris B <cbiene...@microsoft.com>
Date: Mon, 10 Feb 2025 15:06:25 -0600
Subject: [PATCH 4/4] Update clang/test/SemaHLSL/Language/InitLists.hlsl

Co-authored-by: Finn Plummer <50529406+inbe...@users.noreply.github.com>
---
 clang/test/SemaHLSL/Language/InitLists.hlsl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl 
b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 1f7baf35ed2e3ee..79ba126758589c4 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -65,5 +65,5 @@ void Errs() {
   TwoFloats F2 = {1}; // expected-error{{too few initializers in list for type 
'TwoFloats' (expected 2 but found 1)}}
   TwoFloats F3 = {1,2,3}; // expected-error{{too many initializers in list for 
type 'TwoFloats' (expected 2 but found 3)}}
 
-  int2 Something = {1.xxx}; // expected-error{{too many initializers in list 
for type 'int2' (aka 'vector<int, 2>') (expected 2 but found 0)}}
+  int2 Something = {1.xxx}; // expected-error{{too many initializers in list 
for type 'int2' (aka 'vector<int, 2>') (expected 2 but found 3)}}
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to