mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-07 16:42:07 +00:00
Intrinsics: introduce llvm_any_ty aka ValueType Any
Specifically, gc.result benefits from this greatly. Instead of: gc.result.int.* gc.result.float.* gc.result.ptr.* ... We now have a gc.result.* that can specialize to literally any type. Differential Revision: http://reviews.llvm.org/D7020 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226857 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7ed0364cee
commit
230796b278
@ -236,13 +236,7 @@ Syntax:
|
||||
::
|
||||
|
||||
declare type*
|
||||
@gc.result_ptr(i32 %statepoint_token)
|
||||
|
||||
declare fX
|
||||
@gc.result_float(i32 %statepoint_token)
|
||||
|
||||
declare iX
|
||||
@gc.result_int(i32 %statepoint_token)
|
||||
@gc.result(i32 %statepoint_token)
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
|
@ -152,7 +152,11 @@ namespace llvm {
|
||||
|
||||
// iPTR - An int value the size of the pointer of the current
|
||||
// target. This should only be used internal to tblgen!
|
||||
iPTR = 255
|
||||
iPTR = 255,
|
||||
|
||||
// Any - Any type. This is used for intrinsics that have overloadings.
|
||||
// This is only for tblgen's consumption!
|
||||
Any = 256
|
||||
};
|
||||
|
||||
SimpleValueType SimpleTy;
|
||||
@ -245,7 +249,8 @@ namespace llvm {
|
||||
|
||||
/// isOverloaded - Return true if this is an overloaded type for TableGen.
|
||||
bool isOverloaded() const {
|
||||
return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
|
||||
return (SimpleTy==MVT::Any ||
|
||||
SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
|
||||
SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
|
||||
}
|
||||
|
||||
@ -380,6 +385,7 @@ namespace llvm {
|
||||
case iAny:
|
||||
case fAny:
|
||||
case vAny:
|
||||
case Any:
|
||||
llvm_unreachable("Value type is overloaded.");
|
||||
case Metadata:
|
||||
llvm_unreachable("Value type is metadata.");
|
||||
|
@ -98,3 +98,6 @@ def iAny : ValueType<0 , 254>;
|
||||
|
||||
// Pseudo valuetype mapped to the current pointer size.
|
||||
def iPTR : ValueType<0 , 255>;
|
||||
|
||||
// Pseudo valuetype to represent "any type of any size".
|
||||
def Any : ValueType<0 , 256>;
|
||||
|
@ -41,7 +41,7 @@ namespace Intrinsic {
|
||||
#undef GET_INTRINSIC_ENUM_VALUES
|
||||
, num_intrinsics
|
||||
};
|
||||
|
||||
|
||||
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
|
||||
std::string getName(ID id, ArrayRef<Type*> Tys = None);
|
||||
|
||||
@ -69,7 +69,7 @@ namespace Intrinsic {
|
||||
|
||||
/// Map a MS builtin name to an intrinsic ID.
|
||||
ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName);
|
||||
|
||||
|
||||
/// This is a type descriptor which explains the type requirements of an
|
||||
/// intrinsic. This is returned by getIntrinsicInfoTableEntries.
|
||||
struct IITDescriptor {
|
||||
@ -79,7 +79,7 @@ namespace Intrinsic {
|
||||
Argument, ExtendArgument, TruncArgument, HalfVecArgument,
|
||||
SameVecWidthArgument, PtrToArgument
|
||||
} Kind;
|
||||
|
||||
|
||||
union {
|
||||
unsigned Integer_Width;
|
||||
unsigned Float_Width;
|
||||
@ -88,8 +88,9 @@ namespace Intrinsic {
|
||||
unsigned Struct_NumElements;
|
||||
unsigned Argument_Info;
|
||||
};
|
||||
|
||||
|
||||
enum ArgKind {
|
||||
AK_Any,
|
||||
AK_AnyInteger,
|
||||
AK_AnyFloat,
|
||||
AK_AnyVector,
|
||||
@ -99,25 +100,25 @@ namespace Intrinsic {
|
||||
assert(Kind == Argument || Kind == ExtendArgument ||
|
||||
Kind == TruncArgument || Kind == HalfVecArgument ||
|
||||
Kind == SameVecWidthArgument || Kind == PtrToArgument);
|
||||
return Argument_Info >> 2;
|
||||
return Argument_Info >> 3;
|
||||
}
|
||||
ArgKind getArgumentKind() const {
|
||||
assert(Kind == Argument || Kind == ExtendArgument ||
|
||||
Kind == TruncArgument || Kind == HalfVecArgument ||
|
||||
Kind == SameVecWidthArgument || Kind == PtrToArgument);
|
||||
return (ArgKind)(Argument_Info & 3);
|
||||
return (ArgKind)(Argument_Info & 7);
|
||||
}
|
||||
|
||||
|
||||
static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
|
||||
IITDescriptor Result = { K, { Field } };
|
||||
return Result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Return the IIT table descriptor for the specified intrinsic into an array
|
||||
/// of IITDescriptors.
|
||||
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
|
||||
|
||||
|
||||
} // End Intrinsic namespace
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -123,6 +123,7 @@ class LLVMPointerTo<int num> : LLVMMatchType<num>;
|
||||
class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>;
|
||||
|
||||
def llvm_void_ty : LLVMType<isVoid>;
|
||||
def llvm_any_ty : LLVMType<Any>;
|
||||
def llvm_anyint_ty : LLVMType<iAny>;
|
||||
def llvm_anyfloat_ty : LLVMType<fAny>;
|
||||
def llvm_anyvector_ty : LLVMType<vAny>;
|
||||
@ -516,14 +517,16 @@ def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
|
||||
[llvm_anyptr_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_vararg_ty]>;
|
||||
|
||||
def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
|
||||
def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
|
||||
[llvm_i32_ty]>;
|
||||
def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>;
|
||||
|
||||
def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>;
|
||||
def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
|
||||
[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
|
||||
|
||||
// Deprecated: will be removed in a couple of weeks
|
||||
def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
|
||||
def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
|
||||
[llvm_i32_ty]>;
|
||||
def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>;
|
||||
|
||||
//===-------------------------- Other Intrinsics --------------------------===//
|
||||
//
|
||||
def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
|
||||
|
@ -416,6 +416,7 @@ struct NoTTI final : ImmutablePass, TargetTransformInfo {
|
||||
case Intrinsic::experimental_gc_result_int:
|
||||
case Intrinsic::experimental_gc_result_float:
|
||||
case Intrinsic::experimental_gc_result_ptr:
|
||||
case Intrinsic::experimental_gc_result:
|
||||
case Intrinsic::experimental_gc_relocate:
|
||||
// These intrinsics don't actually represent code after lowering.
|
||||
return TCC_Free;
|
||||
|
@ -5604,7 +5604,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
||||
}
|
||||
case Intrinsic::experimental_gc_result_int:
|
||||
case Intrinsic::experimental_gc_result_float:
|
||||
case Intrinsic::experimental_gc_result_ptr: {
|
||||
case Intrinsic::experimental_gc_result_ptr:
|
||||
case Intrinsic::experimental_gc_result: {
|
||||
visitGCResult(I);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -263,16 +263,7 @@ CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
|
||||
CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,
|
||||
Type *ResultType,
|
||||
const Twine &Name) {
|
||||
Intrinsic::ID ID;
|
||||
if (ResultType->isIntegerTy()) {
|
||||
ID = Intrinsic::experimental_gc_result_int;
|
||||
} else if (ResultType->isFloatingPointTy()) {
|
||||
ID = Intrinsic::experimental_gc_result_float;
|
||||
} else if (ResultType->isPointerTy()) {
|
||||
ID = Intrinsic::experimental_gc_result_ptr;
|
||||
} else {
|
||||
llvm_unreachable("unimplemented result type for gc.result");
|
||||
}
|
||||
Intrinsic::ID ID = Intrinsic::experimental_gc_result;
|
||||
Module *M = BB->getParent()->getParent();
|
||||
Type *Types[] = {ResultType};
|
||||
Value *FnGCResult = Intrinsic::getDeclaration(M, ID, Types);
|
||||
|
@ -54,7 +54,8 @@ bool llvm::isGCResult(const Instruction *inst) {
|
||||
if (Function *F = call->getCalledFunction()) {
|
||||
return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int ||
|
||||
F->getIntrinsicID() == Intrinsic::experimental_gc_result_float ||
|
||||
F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr);
|
||||
F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr ||
|
||||
F->getIntrinsicID() == Intrinsic::experimental_gc_result);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -2391,6 +2391,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
|
||||
ArgTys.push_back(Ty);
|
||||
|
||||
switch (D.getArgumentKind()) {
|
||||
case IITDescriptor::AK_Any: return false; // Success
|
||||
case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy();
|
||||
case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy();
|
||||
case IITDescriptor::AK_AnyVector: return !isa<VectorType>(Ty);
|
||||
@ -2721,7 +2722,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
}
|
||||
case Intrinsic::experimental_gc_result_int:
|
||||
case Intrinsic::experimental_gc_result_float:
|
||||
case Intrinsic::experimental_gc_result_ptr: {
|
||||
case Intrinsic::experimental_gc_result_ptr:
|
||||
case Intrinsic::experimental_gc_result: {
|
||||
// Are we tied to a statepoint properly?
|
||||
CallSite StatepointCS(CI.getArgOperand(0));
|
||||
const Function *StatepointFn =
|
||||
|
@ -21,7 +21,7 @@ define i1 @test_i1_return() gc "statepoint-example" {
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0)
|
||||
%call1 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
|
||||
%call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
|
||||
ret i1 %call1
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ define i32 @test_i32_return() gc "statepoint-example" {
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i32 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0)
|
||||
%call1 = call zeroext i32 @llvm.experimental.gc.result.int.i32(i32 %safepoint_token)
|
||||
%call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
|
||||
ret i32 %call1
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ define i32* @test_i32ptr_return() gc "statepoint-example" {
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i32* ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0)
|
||||
%call1 = call i32* @llvm.experimental.gc.result.ptr.p0i32(i32 %safepoint_token)
|
||||
%call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
|
||||
ret i32* %call1
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ define float @test_float_return() gc "statepoint-example" {
|
||||
; CHECK: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (float ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0)
|
||||
%call1 = call float @llvm.experimental.gc.result.float.f32(i32 %safepoint_token)
|
||||
%call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
|
||||
ret float %call1
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
|
||||
%call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
%call2 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
|
||||
%call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
|
||||
ret i1 %call2
|
||||
}
|
||||
|
||||
@ -88,16 +88,16 @@ entry:
|
||||
}
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
|
||||
declare i1 @llvm.experimental.gc.result.int.i1(i32)
|
||||
declare i1 @llvm.experimental.gc.result.i1(i32)
|
||||
|
||||
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.result.i32(i32)
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...)
|
||||
declare i32* @llvm.experimental.gc.result.ptr.p0i32(i32)
|
||||
declare i32* @llvm.experimental.gc.result.p0i32(i32)
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...)
|
||||
declare float @llvm.experimental.gc.result.float.f32(i32)
|
||||
declare float @llvm.experimental.gc.result.f32(i32)
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...)
|
||||
|
||||
|
@ -22,7 +22,7 @@ entry:
|
||||
%metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
|
||||
store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
|
||||
%call1 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
|
||||
%call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
|
||||
%a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6)
|
||||
%b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
|
||||
;
|
||||
@ -30,7 +30,7 @@ entry:
|
||||
}
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
|
||||
declare i1 @llvm.experimental.gc.result.int.i1(i32)
|
||||
declare i1 @llvm.experimental.gc.result.i1(i32)
|
||||
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) #3
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
|
||||
EnforceVector(TP);
|
||||
else {
|
||||
assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
|
||||
VT == MVT::iPTRAny) && "Not a concrete type!");
|
||||
VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
|
||||
TypeVec.push_back(VT);
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
|
||||
case MVT::i32: return "MVT::i32";
|
||||
case MVT::i64: return "MVT::i64";
|
||||
case MVT::i128: return "MVT::i128";
|
||||
case MVT::Any: return "MVT::Any";
|
||||
case MVT::iAny: return "MVT::iAny";
|
||||
case MVT::fAny: return "MVT::fAny";
|
||||
case MVT::vAny: return "MVT::vAny";
|
||||
|
@ -309,7 +309,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
Sig.push_back(IIT_HALF_VEC_ARG);
|
||||
else if (R->isSubClassOf("LLVMVectorSameWidth")) {
|
||||
Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
|
||||
Sig.push_back((Number << 2) | ArgCodes[Number]);
|
||||
Sig.push_back((Number << 3) | ArgCodes[Number]);
|
||||
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
|
||||
EncodeFixedValueType(VT, Sig);
|
||||
return;
|
||||
@ -319,7 +319,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
}
|
||||
else
|
||||
Sig.push_back(IIT_ARG);
|
||||
return Sig.push_back((Number << 2) | ArgCodes[Number]);
|
||||
return Sig.push_back((Number << 3) | ArgCodes[Number]);
|
||||
}
|
||||
|
||||
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
|
||||
@ -330,7 +330,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
case MVT::iPTRAny: ++Tmp; // FALL THROUGH.
|
||||
case MVT::vAny: ++Tmp; // FALL THROUGH.
|
||||
case MVT::fAny: ++Tmp; // FALL THROUGH.
|
||||
case MVT::iAny: {
|
||||
case MVT::iAny: ++Tmp; // FALL THROUGH.
|
||||
case MVT::Any: {
|
||||
// If this is an "any" valuetype, then the type is the type of the next
|
||||
// type in the list specified to getIntrinsic().
|
||||
Sig.push_back(IIT_ARG);
|
||||
@ -339,8 +340,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
unsigned ArgNo = ArgCodes.size();
|
||||
ArgCodes.push_back(Tmp);
|
||||
|
||||
// Encode what sort of argument it must be in the low 2 bits of the ArgNo.
|
||||
return Sig.push_back((ArgNo << 2) | Tmp);
|
||||
// Encode what sort of argument it must be in the low 3 bits of the ArgNo.
|
||||
return Sig.push_back((ArgNo << 3) | Tmp);
|
||||
}
|
||||
|
||||
case MVT::iPTR: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user