Index: include/llvm/IR/Intrinsics.h =================================================================== --- include/llvm/IR/Intrinsics.h +++ include/llvm/IR/Intrinsics.h @@ -75,7 +75,7 @@ struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, - Integer, Vector, Pointer, Struct, + Integer, Array, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, SameVecWidthArgument, PtrToArgument } Kind; @@ -83,6 +83,7 @@ union { unsigned Integer_Width; unsigned Float_Width; + unsigned Array_Width; unsigned Vector_Width; unsigned Pointer_AddressSpace; unsigned Struct_NumElements; Index: include/llvm/IR/Type.h =================================================================== --- include/llvm/IR/Type.h +++ include/llvm/IR/Type.h @@ -199,7 +199,12 @@ /// integer types. /// bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } - + + /// isIntOrIntVectorOrArVecTy - Return true if this is an integer type or a + /// vector of integer types, or n array of integer types. + /// + bool isIntOrIntArVecTy() const { return getArVecElementType()->isIntegerTy(); } + /// isFunctionTy - True if this is an instance of FunctionType. /// bool isFunctionTy() const { return getTypeID() == FunctionTyID; } @@ -307,6 +312,11 @@ const Type *getScalarType() const LLVM_READONLY; Type *getScalarType() LLVM_READONLY; + /// getScalarType - If this is a vector or array type, return the element + /// type, otherwise return 'this'. + const Type *getArVecElementType() const LLVM_READONLY; + Type *getArVecElementType() LLVM_READONLY; + //===--------------------------------------------------------------------===// // Type Iteration support. // Index: lib/IR/Function.cpp =================================================================== --- lib/IR/Function.cpp +++ lib/IR/Function.cpp @@ -542,7 +542,14 @@ IIT_VARARG = 28, IIT_HALF_VEC_ARG = 29, IIT_SAME_VEC_WIDTH_ARG = 30, - IIT_PTR_TO_ARG = 31 + IIT_PTR_TO_ARG = 31, + IIT_A1 = 32, + IIT_A2 = 33, + IIT_A4 = 34, + IIT_A8 = 35, + IIT_A16 = 36, + IIT_A32 = 37, + IIT_A64 = 38 }; @@ -589,6 +596,34 @@ case IIT_I64: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64)); return; + case IIT_A1: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 1)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A2: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 2)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A4: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 4)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A8: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 8)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A16: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 16)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 32)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_A64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Array, 64)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_V1: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 1)); DecodeIITType(NextElt, Infos, OutputTable); @@ -735,6 +770,8 @@ case IITDescriptor::Integer: return IntegerType::get(Context, D.Integer_Width); + case IITDescriptor::Array: + return ArrayType::get(DecodeFixedType(Infos, Tys, Context), D.Array_Width); case IITDescriptor::Vector: return VectorType::get(DecodeFixedType(Infos, Tys, Context),D.Vector_Width); case IITDescriptor::Pointer: Index: lib/IR/Type.cpp =================================================================== --- lib/IR/Type.cpp +++ lib/IR/Type.cpp @@ -54,6 +54,24 @@ return this; } +/// getScalarType - If this is a vector or array type, return the element type, +/// otherwise return this. +Type *Type::getArVecElementType() { + if (VectorType *VTy = dyn_cast(this)) + return VTy->getElementType(); + if (ArrayType *ATy = dyn_cast(this)) + return ATy->getElementType(); + return this; +} + +const Type *Type::getArVecElementType() const { + if (const VectorType *VTy = dyn_cast(this)) + return VTy->getElementType(); + if (const ArrayType *ATy = dyn_cast(this)) + return ATy->getElementType(); + return this; +} + /// isIntegerTy - Return true if this is an IntegerType of the specified width. bool Type::isIntegerTy(unsigned Bitwidth) const { return isIntegerTy() && cast(this)->getBitWidth() == Bitwidth; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -2357,6 +2357,11 @@ case IITDescriptor::Float: return !Ty->isFloatTy(); case IITDescriptor::Double: return !Ty->isDoubleTy(); case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); + case IITDescriptor::Array: { + ArrayType *AT = dyn_cast(Ty); + return !AT || AT->getNumElements() != D.Array_Width || + VerifyIntrinsicType(AT->getElementType(), Infos, ArgTys); + } case IITDescriptor::Vector: { VectorType *VT = dyn_cast(Ty); return !VT || VT->getNumElements() != D.Vector_Width || @@ -2391,7 +2396,7 @@ ArgTys.push_back(Ty); switch (D.getArgumentKind()) { - case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy(); + case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntArVecTy(); case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); case IITDescriptor::AK_AnyVector: return !isa(Ty); case IITDescriptor::AK_AnyPointer: return !isa(Ty); Index: test/CodeGen/X86/statepoint-call-lowering.ll =================================================================== --- test/CodeGen/X86/statepoint-call-lowering.ll +++ test/CodeGen/X86/statepoint-call-lowering.ll @@ -7,6 +7,7 @@ declare zeroext i1 @return_i1() declare zeroext i32 @return_i32() +declare [2 x i32] @return_i32ar() declare i32* @return_i32ptr() declare float @return_float() @@ -36,6 +37,18 @@ ret i32 %call1 } +define [2 x i32] @test_i32ar_return() { +; CHECK-LABEL: test_i32ar_return +; CHECK: pushq %rax +; CHECK: callq return_i32ar +; CHECK: popq %rcx +; CHECK: retq +entry: + %safepoint_token = tail call i32 ([2 x i32] ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_a2i32f([2 x i32] ()* @return_i32ar, i32 0, i32 0, i32 0) + %call1 = call [2 x i32] @llvm.experimental.gc.result.int.a2i32(i32 %safepoint_token) + ret [2 x i32] %call1 +} + define i32* @test_i32ptr_return() { ; CHECK-LABEL: test_i32ptr_return ; CHECK: pushq %rax @@ -60,12 +73,12 @@ ret float %call1 } -define i1 @test_relocate(i32* %a) { +define i1 @test_relocate_noop(i32* %a) { ; CHECK-LABEL: test_relocate ; Check that an ununsed relocate has no code-generation impact ; CHECK: pushq %rax ; CHECK: callq return_i1 -; CHECK-NEXT: .Ltmp13: +; CHECK-NEXT: .Ltmp16: ; CHECK-NEXT: popq %rdx ; CHECK-NEXT: retq entry: @@ -81,6 +94,9 @@ declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()*, i32, i32, ...) declare i32 @llvm.experimental.gc.result.int.i32(i32) +declare i32 @llvm.experimental.gc.statepoint.p0f_a2i32f([2 x i32] ()*, i32, i32, ...) +declare [2 x i32] @llvm.experimental.gc.result.int.a2i32(i32) + declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...) declare i32* @llvm.experimental.gc.result.ptr.p0i32(i32) Index: utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- utils/TableGen/IntrinsicEmitter.cpp +++ utils/TableGen/IntrinsicEmitter.cpp @@ -259,7 +259,14 @@ IIT_VARARG = 28, IIT_HALF_VEC_ARG = 29, IIT_SAME_VEC_WIDTH_ARG = 30, - IIT_PTR_TO_ARG = 31 + IIT_PTR_TO_ARG = 31, + IIT_A1 = 32, + IIT_A2 = 33, + IIT_A4 = 34, + IIT_A8 = 35, + IIT_A16 = 36, + IIT_A32 = 37, + IIT_A64 = 38 };