Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,9 @@ class InitializationSequence {

// A designated initializer was provided for a non-aggregate type.
FK_DesignatedInitForNonAggregate,

/// HLSL intialization list flattening failed.
FK_HLSLInitListFlatteningFailed,
};

private:
Expand Down
45 changes: 22 additions & 23 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3920,6 +3920,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_AddressOfUnaddressableFunction:
case FK_ParenthesizedListInitFailed:
case FK_DesignatedInitForNonAggregate:
case FK_HLSLInitListFlatteningFailed:
return false;

case FK_ReferenceInitOverloadFailed:
Expand Down Expand Up @@ -4882,8 +4883,10 @@ static void TryListInitialization(Sema &S,
bool TreatUnavailableAsInvalid) {
QualType DestType = Entity.getType();

if (S.getLangOpts().HLSL && !S.HLSL().transformInitList(Entity, InitList))
if (S.getLangOpts().HLSL && !S.HLSL().transformInitList(Entity, InitList)) {
Sequence.SetFailed(InitializationSequence::FK_HLSLInitListFlatteningFailed);
return;
}

// C++ doesn't allow scalar initialization with more than one argument.
// But C99 complex numbers are scalars and it makes sense there.
Expand Down Expand Up @@ -6817,33 +6820,17 @@ void InitializationSequence::InitializeFrom(Sema &S,
assert(Args.size() >= 1 && "Zero-argument case handled above");

// For HLSL ext vector types we allow list initialization behavior for C++
// constructor syntax. This is accomplished by converting initialization
// arguments an InitListExpr late.
// functional cast expressions which look like constructor syntax. This is
// accomplished by converting initialization arguments an InitListExpr.
if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() &&
(SourceType.isNull() ||
!Context.hasSameUnqualifiedType(SourceType, DestType))) {

llvm::SmallVector<Expr *> InitArgs;
for (auto *Arg : Args) {
if (Arg->getType()->isExtVectorType()) {
const auto *VTy = Arg->getType()->castAs<ExtVectorType>();
unsigned Elm = VTy->getNumElements();
for (unsigned Idx = 0; Idx < Elm; ++Idx) {
InitArgs.emplace_back(new (Context) ArraySubscriptExpr(
Arg,
IntegerLiteral::Create(
Context, llvm::APInt(Context.getIntWidth(Context.IntTy), Idx),
Context.IntTy, SourceLocation()),
VTy->getElementType(), Arg->getValueKind(), Arg->getObjectKind(),
SourceLocation()));
}
} else
InitArgs.emplace_back(Arg);
}
InitListExpr *ILE = new (Context) InitListExpr(
S.getASTContext(), SourceLocation(), InitArgs, SourceLocation());
S.getASTContext(), SourceLocation(), Args, SourceLocation());
ILE->setType(DestType);
Args[0] = ILE;
AddListInitializationStep(DestType);
TryListInitialization(S, Entity, Kind, ILE, *this,
TreatUnavailableAsInvalid);
return;
}

Expand Down Expand Up @@ -9302,6 +9289,14 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}

case InitializationSequence::FK_HLSLInitListFlatteningFailed: {
// Unlike C/C++ list initialization, there is no fallback if it fails. This
// allows us to diagnose the failure when it happens in the
// TryListInitialization call instead of delaying the diagnosis, which is
// beneficial because the flattening is also expnsive.
break;
}

case FK_ExplicitConstructor: {
S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
<< Args[0]->getSourceRange();
Expand Down Expand Up @@ -9500,6 +9495,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case FK_DesignatedInitForNonAggregate:
OS << "designated initializer for non-aggregate type";
break;

case FK_HLSLInitListFlatteningFailed:
OS << "HLSL initialization list flattening failed";
break;
}
OS << '\n';
return;
Expand Down
23 changes: 2 additions & 21 deletions clang/test/AST/HLSL/vector-constructors.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ void entry() {
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue
// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'Vec2' 'float2':'vector<float, 2>'
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 0
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue
// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue Var {{.*}} 'Vec2' 'float2':'vector<float, 2>'
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
// CHECK-NEXT: IntegerLiteral {{.*}} '__size_t':'unsigned long' 1
// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.000000e+00

// CHECK: VarDecl {{.*}} 'float3':'vector<float, 3>' cinit
Expand Down Expand Up @@ -93,25 +93,6 @@ void entry() {
// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .f {{.*}}
// CHECK-NEXT: DeclRefExpr {{.*}} 'struct S' lvalue Var {{.*}} 's' 'struct S'

struct T {
operator float() const { return 1.0f; }
} t;
float2 foo5 = float2(t, t); // user-defined cast operator

// CHECK-LABEL: VarDecl {{.*}} foo5 'float2'
// CHECK-NEXT: CXXFunctionalCastExpr
// CHECK-NEXT: InitListExpr
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <UserDefinedConversion>
// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'float'
// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .operator float {{.*}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const T' lvalue <NoOp>
// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T' lvalue Var {{.*}} 't' 'struct T'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <UserDefinedConversion>
// CHECK-NEXT: CXXMemberCallExpr {{.*}} 'float'
// CHECK-NEXT: MemberExpr {{.*}} '<bound member function type>' .operator float {{.*}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'const T' lvalue <NoOp>
// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T' lvalue Var {{.*}} 't' 'struct T'

typedef float2 second_level_of_typedefs;
second_level_of_typedefs foo6 = float2(1.0f, 2.0f);

Expand Down
173 changes: 124 additions & 49 deletions clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ struct EmptyDerived : Empty {};

struct UnnamedDerived : UnnamedOnly {};

// CHECK-DAG: [[ConstE:@.*]] = private unnamed_addr constant %struct.Empty undef, align 1
// CHECK-DAG: [[ConstUO:@.*]] = private unnamed_addr constant %struct.UnnamedOnly undef, align 1
// CHECK-DAG: [[ConstED:@.*]] = private unnamed_addr constant %struct.EmptyDerived undef, align 1
// CHECK-DAG: [[ConstUD:@.*]] = private unnamed_addr constant %struct.UnnamedDerived undef, align 1

// Case 1: Extraneous braces get ignored in literal instantiation.
// CHECK-LABEL: define hidden void @_Z5case1v(
Expand Down Expand Up @@ -911,15 +907,15 @@ TwoFloats case15(SlicyBits SB) {
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 4, !nonnull [[META3:![0-9]+]], !align [[META4:![0-9]+]]
// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4
// CHECK-NEXT: store float [[TMP1]], ptr [[X1]], align 1
// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[X_ADDR]], align 4, !nonnull [[META3]], !align [[META4]]
// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4
// CHECK-NEXT: [[MUL:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP3]], 1.500000e+00
// CHECK-NEXT: store float [[MUL]], ptr [[Y]], align 1
// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[X_ADDR]], align 4, !nonnull [[META3]], !align [[META4]]
// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[TMP4]], align 4
// CHECK-NEXT: [[MUL2:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP5]], 2.000000e+00
// CHECK-NEXT: store float [[MUL2]], ptr [[TMP4]], align 4
Expand Down Expand Up @@ -964,94 +960,173 @@ FourFloats case16() {
}


// CHECK-LABEL: define hidden noundef i32 @_Z12case17Helperi(
// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// CHECK-NEXT: ret i32 [[TMP0]]
//
int case17Helper(int x) {
return x;
}

// InitList with OpaqueValueExpr
// CHECK-LABEL: define hidden void {{.*}}case17
// CHECK: [[X:%.*]] = alloca <2 x i32>, align 8
// CHECK-NEXT: [[C:%.*]] = call noundef i32 {{.*}}case17Helper{{.*}}(i32 noundef 0)
// CHECK-NEXT: [[C1:%.*]] = call noundef i32 {{.*}}case17Helper{{.*}}(i32 noundef 1)
// CHECK-NEXT: [[VI:%.*]] = insertelement <2 x i32> poison, i32 [[C]], i32 0
// CHECK-NEXT: [[VI2:%.*]] = insertelement <2 x i32> [[VI]], i32 [[C1]], i32 1
// CHECK-NEXT: store <2 x i32> [[VI2]], ptr [[X]], align 8
// CHECK-NEXT: ret void
// CHECK-LABEL: define hidden void @_Z6case17v(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[X:%.*]] = alloca <2 x i32>, align 8
// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_Z12case17Helperi(i32 noundef 0) #[[ATTR2]]
// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_Z12case17Helperi(i32 noundef 1) #[[ATTR2]]
// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <2 x i32> poison, i32 [[CALL]], i32 0
// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <2 x i32> [[VECINIT]], i32 [[CALL1]], i32 1
// CHECK-NEXT: store <2 x i32> [[VECINIT2]], ptr [[X]], align 8
// CHECK-NEXT: ret void
//
void case17() {
int2 X = {case17Helper(0), case17Helper(1)};
}

// InitList with Struct with unnamed bitfield on LHS
// CHECK-LABEL: case18
// CHECK: [[U:%.*]] = alloca %struct.Unnamed, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[U]], ptr align 1 {{.*}}, i32 5, i1 false)
// CHECK-LABEL: define hidden void @_Z6case18v(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[U:%.*]] = alloca [[STRUCT_UNNAMED:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[U]], ptr align 1 @__const._Z6case18v.U, i32 5, i1 false)
// CHECK-NEXT: ret void
//
void case18() {
Unnamed U = {1};
}

// InitList with Struct with unnamed bitfield on RHS
// CHECK-LABEL: case19
// CHECK: [[TI:%.*]] = alloca %struct.TwoInts, align 1
// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw %struct.TwoInts, ptr [[TI]], i32 0, i32 0
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw %struct.Unnamed, ptr %U, i32 0, i32 0
// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 1
// CHECK-NEXT: store i32 [[L]], ptr [[Z]], align 1
// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw %struct.TwoInts, ptr [[TI]], i32 0, i32 1
// CHECK-NEXT: store i32 1, ptr [[W]], align 1
// CHECK-LABEL: define hidden void @_Z6case197Unnamed(
// CHECK-SAME: ptr noundef byval([[STRUCT_UNNAMED:%.*]]) align 1 [[U:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TI:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1
// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0
// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_UNNAMED]], ptr [[U]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 1
// CHECK-NEXT: store i32 [[TMP0]], ptr [[Z]], align 1
// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1
// CHECK-NEXT: store i32 1, ptr [[W]], align 1
// CHECK-NEXT: ret void
//
void case19(Unnamed U) {
TwoInts TI = {U, 1};
}

// InitList with Empty Struct on LHS
// CHECK-LABEL: case20
// CHECK: [[E:%.*]] = alloca %struct.Empty, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[E]], ptr align 1 [[ConstE]], i32 1, i1 false)
// CHECK-LABEL: define hidden void @_Z6case20v(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[E:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[E]], ptr align 1 @__const._Z6case20v.E, i32 1, i1 false)
// CHECK-NEXT: ret void
//
void case20() {
Empty E = {};
}

// InitList with Empty Struct on RHS
// CHECK-LABEL: case21
// CHECK: [[TI:%.*]] = alloca %struct.TwoInts, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI, ptr align 1 {{.*}}, i32 8, i1 false)
// CHECK-LABEL: define hidden void @_Z6case215Empty(
// CHECK-SAME: ptr noundef byval([[STRUCT_EMPTY:%.*]]) align 1 [[E:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TI:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI]], ptr align 1 @__const._Z6case215Empty.TI, i32 8, i1 false)
// CHECK-NEXT: ret void
//
void case21(Empty E) {
TwoInts TI = {E, 1, 2};
}

// InitList with Struct with only unnamed bitfield on LHS
// CHECK-LABEL: case22
// CHECK: [[UO:%.*]] = alloca %struct.UnnamedOnly, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[UO]], ptr align 1 [[ConstUO]], i32 1, i1 false)
// CHECK-LABEL: define hidden void @_Z6case22v(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[UO:%.*]] = alloca [[STRUCT_UNNAMEDONLY:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[UO]], ptr align 1 @__const._Z6case22v.UO, i32 1, i1 false)
// CHECK-NEXT: ret void
//
void case22() {
UnnamedOnly UO = {};
UnnamedOnly UO = {};
}

// InitList with Struct with only unnamed bitfield on RHS
// CHECK-LABEL: case23
// CHECK: [[TI:%.*]] = alloca %struct.TwoInts, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI]], ptr align 1 {{.*}}, i32 8, i1 false)
// CHECK-LABEL: define hidden void @_Z6case2311UnnamedOnly(
// CHECK-SAME: ptr noundef byval([[STRUCT_UNNAMEDONLY:%.*]]) align 1 [[UO:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TI:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI]], ptr align 1 @__const._Z6case2311UnnamedOnly.TI, i32 8, i1 false)
// CHECK-NEXT: ret void
//
void case23(UnnamedOnly UO) {
TwoInts TI = {UO, 1, 2};
}

// InitList with Derived empty struct on LHS
// InitList with Derived unnamed bitfield on LHS
// CHECK-LABEL: case24
// CHECK: [[ED:%.*]] = alloca %struct.EmptyDerived, align 1
// CHECK-NEXT: [[UD:%.*]] = alloca %struct.UnnamedDerived, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %ED, ptr align 1 [[ConstED]], i32 1, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %UD, ptr align 1 [[ConstUD]], i32 1, i1 false)
// CHECK-LABEL: define hidden void @_Z6case24v(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[ED:%.*]] = alloca [[STRUCT_EMPTYDERIVED:%.*]], align 1
// CHECK-NEXT: [[UD:%.*]] = alloca [[STRUCT_UNNAMEDDERIVED:%.*]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[ED]], ptr align 1 @__const._Z6case24v.ED, i32 1, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[UD]], ptr align 1 @__const._Z6case24v.UD, i32 1, i1 false)
// CHECK-NEXT: ret void
//
void case24() {
EmptyDerived ED = {};
UnnamedDerived UD = {};
}

// CHECK-LABEL: case25
// CHECK: [[TI1:%.*]] = alloca %struct.TwoInts, align 1
// CHECK-NEXT: [[TI2:%.*]] = alloca %struct.TwoInts, align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI1, ptr align 1 {{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 %TI2, ptr align 1 {{.*}}, i32 8, i1 false)
// CHECK-LABEL: define hidden void @_Z6case2512EmptyDerived14UnnamedDerived(
// CHECK-SAME: ptr noundef byval([[STRUCT_EMPTYDERIVED:%.*]]) align 1 [[ED:%.*]], ptr noundef byval([[STRUCT_UNNAMEDDERIVED:%.*]]) align 1 [[UD:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TI1:%.*]] = alloca [[STRUCT_TWOINTS:%.*]], align 1
// CHECK-NEXT: [[TI2:%.*]] = alloca [[STRUCT_TWOINTS]], align 1
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI1]], ptr align 1 @__const._Z6case2512EmptyDerived14UnnamedDerived.TI1, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TI2]], ptr align 1 @__const._Z6case2512EmptyDerived14UnnamedDerived.TI2, i32 8, i1 false)
// CHECK-NEXT: ret void
//
void case25(EmptyDerived ED, UnnamedDerived UD) {
TwoInts TI1 = {ED, 1, 2};
TwoInts TI2 = {UD, 1, 2};
}

// CHECK-LABEL: define hidden void @_Z6case267TwoInts(
// CHECK-SAME: ptr noundef byval([[STRUCT_TWOINTS:%.*]]) align 1 [[TI:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[F:%.*]] = alloca <4 x float>, align 16
// CHECK-NEXT: [[F2:%.*]] = alloca <3 x float>, align 16
// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Z]], align 1
// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP0]] to float
// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x float> poison, float [[CONV]], i32 0
// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[W]], align 1
// CHECK-NEXT: [[CONV1:%.*]] = sitofp i32 [[TMP1]] to float
// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x float> [[VECINIT]], float [[CONV1]], i32 1
// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x float> [[VECINIT2]], float 1.000000e+00, i32 2
// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <4 x float> [[VECINIT3]], float 2.000000e+00, i32 3
// CHECK-NEXT: store <4 x float> [[VECINIT4]], ptr [[F]], align 16
// CHECK-NEXT: [[Z5:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[Z5]], align 1
// CHECK-NEXT: [[CONV6:%.*]] = sitofp i32 [[TMP2]] to float
// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <3 x float> <float 3.000000e+00, float poison, float poison>, float [[CONV6]], i32 1
// CHECK-NEXT: [[W8:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1
// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[W8]], align 1
// CHECK-NEXT: [[CONV9:%.*]] = sitofp i32 [[TMP3]] to float
// CHECK-NEXT: [[VECINIT10:%.*]] = insertelement <3 x float> [[VECINIT7]], float [[CONV9]], i32 2
// CHECK-NEXT: store <3 x float> [[VECINIT10]], ptr [[F2]], align 16
// CHECK-NEXT: ret void
//
void case26(TwoInts TI) {
float4 F = float4(TI, 1, 2);
float3 F2 = float3(3, TI);
}
//.
// CHECK: [[META3]] = !{}
// CHECK: [[META4]] = !{i64 4}
//.
Loading