1 //===- AMDGPUIntrinsicInfo.cpp - AMDGPU Intrinsic Information ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //==-----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// \brief AMDGPU Implementation of the IntrinsicInfo class. 12 // 13 //===-----------------------------------------------------------------------===// 14 15 #include "AMDGPUIntrinsicInfo.h" 16 #include "AMDGPUSubtarget.h" 17 #include "llvm/IR/DerivedTypes.h" 18 #include "llvm/IR/Intrinsics.h" 19 #include "llvm/IR/Module.h" 20 21 using namespace llvm; 22 23 AMDGPUIntrinsicInfo::AMDGPUIntrinsicInfo() 24 : TargetIntrinsicInfo() {} 25 26 static const char *const IntrinsicNameTable[] = { 27 #define GET_INTRINSIC_NAME_TABLE 28 #include "AMDGPUGenIntrinsics.inc" 29 #undef GET_INTRINSIC_NAME_TABLE 30 }; 31 32 namespace { 33 #define GET_INTRINSIC_ATTRIBUTES 34 #include "AMDGPUGenIntrinsics.inc" 35 #undef GET_INTRINSIC_ATTRIBUTES 36 } 37 38 StringRef AMDGPUIntrinsicInfo::getName(unsigned IntrID, 39 ArrayRef<Type *> Tys) const { 40 if (IntrID < Intrinsic::num_intrinsics) 41 return StringRef(); 42 43 assert(IntrID < AMDGPUIntrinsic::num_AMDGPU_intrinsics && 44 "Invalid intrinsic ID"); 45 46 return IntrinsicNameTable[IntrID - Intrinsic::num_intrinsics]; 47 } 48 49 std::string AMDGPUIntrinsicInfo::getName(unsigned IntrID, Type **Tys, 50 unsigned NumTys) const { 51 return getName(IntrID, makeArrayRef(Tys, NumTys)).str(); 52 } 53 54 FunctionType *AMDGPUIntrinsicInfo::getType(LLVMContext &Context, unsigned ID, 55 ArrayRef<Type*> Tys) const { 56 // FIXME: Re-use Intrinsic::getType machinery 57 switch (ID) { 58 case AMDGPUIntrinsic::amdgcn_fdiv_fast: { 59 Type *F32Ty = Type::getFloatTy(Context); 60 return FunctionType::get(F32Ty, { F32Ty, F32Ty }, false); 61 } 62 default: 63 llvm_unreachable("unhandled intrinsic"); 64 } 65 } 66 67 unsigned AMDGPUIntrinsicInfo::lookupName(const char *NameData, 68 unsigned Len) const { 69 StringRef Name(NameData, Len); 70 if (!Name.startswith("llvm.")) 71 return 0; // All intrinsics start with 'llvm.' 72 73 // Look for a name match in our table. If the intrinsic is not overloaded, 74 // require an exact match. If it is overloaded, require a prefix match. The 75 // AMDGPU enum enum starts at Intrinsic::num_intrinsics. 76 int Idx = Intrinsic::lookupLLVMIntrinsicByName(IntrinsicNameTable, Name); 77 if (Idx >= 0) { 78 bool IsPrefixMatch = Name.size() > strlen(IntrinsicNameTable[Idx]); 79 return IsPrefixMatch == isOverloaded(Idx + 1) 80 ? Intrinsic::num_intrinsics + Idx 81 : 0; 82 } 83 84 return 0; 85 } 86 87 bool AMDGPUIntrinsicInfo::isOverloaded(unsigned id) const { 88 // Overload Table 89 #define GET_INTRINSIC_OVERLOAD_TABLE 90 #include "AMDGPUGenIntrinsics.inc" 91 #undef GET_INTRINSIC_OVERLOAD_TABLE 92 } 93 94 Function *AMDGPUIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, 95 ArrayRef<Type *> Tys) const { 96 FunctionType *FTy = getType(M->getContext(), IntrID, Tys); 97 Function *F 98 = cast<Function>(M->getOrInsertFunction(getName(IntrID, Tys), FTy)); 99 100 AttributeSet AS = getAttributes(M->getContext(), 101 static_cast<AMDGPUIntrinsic::ID>(IntrID)); 102 F->setAttributes(AS); 103 return F; 104 } 105 106 Function *AMDGPUIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, 107 Type **Tys, 108 unsigned NumTys) const { 109 return getDeclaration(M, IntrID, makeArrayRef(Tys, NumTys)); 110 } 111