AMDILIntrinsicInfo.cpp revision 49fb99bd131a4ed89e6f55cf360f67618acafec4
1//===- AMDILIntrinsicInfo.cpp - AMDIL 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// This file contains the AMDIL Implementation of the IntrinsicInfo class. 11// 12//===-----------------------------------------------------------------------===// 13 14#include "AMDILIntrinsicInfo.h" 15#include "AMDIL.h" 16#include "AMDILSubtarget.h" 17#include "llvm/DerivedTypes.h" 18#include "llvm/Intrinsics.h" 19#include "llvm/Module.h" 20 21using namespace llvm; 22 23#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN 24#include "AMDILGenIntrinsics.inc" 25#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN 26 27AMDILIntrinsicInfo::AMDILIntrinsicInfo(TargetMachine *tm) 28 : TargetIntrinsicInfo(), mTM(tm) 29{ 30} 31 32std::string 33AMDILIntrinsicInfo::getName(unsigned int IntrID, Type **Tys, 34 unsigned int numTys) const 35{ 36 static const char* const names[] = { 37#define GET_INTRINSIC_NAME_TABLE 38#include "AMDILGenIntrinsics.inc" 39#undef GET_INTRINSIC_NAME_TABLE 40 }; 41 42 //assert(!isOverloaded(IntrID) 43 //&& "AMDIL Intrinsics are not overloaded"); 44 if (IntrID < Intrinsic::num_intrinsics) { 45 return 0; 46 } 47 assert(IntrID < AMDGPUIntrinsic::num_AMDIL_intrinsics 48 && "Invalid intrinsic ID"); 49 50 std::string Result(names[IntrID - Intrinsic::num_intrinsics]); 51 return Result; 52} 53 54 static bool 55checkTruncation(const char *Name, unsigned int& Len) 56{ 57 const char *ptr = Name + (Len - 1); 58 while(ptr != Name && *ptr != '_') { 59 --ptr; 60 } 61 // We don't want to truncate on atomic instructions 62 // but we do want to enter the check Truncation 63 // section so that we can translate the atomic 64 // instructions if we need to. 65 if (!strncmp(Name, "__atom", 6)) { 66 return true; 67 } 68 if (strstr(ptr, "i32") 69 || strstr(ptr, "u32") 70 || strstr(ptr, "i64") 71 || strstr(ptr, "u64") 72 || strstr(ptr, "f32") 73 || strstr(ptr, "f64") 74 || strstr(ptr, "i16") 75 || strstr(ptr, "u16") 76 || strstr(ptr, "i8") 77 || strstr(ptr, "u8")) { 78 Len = (unsigned int)(ptr - Name); 79 return true; 80 } 81 return false; 82} 83 84// We don't want to support both the OpenCL 1.0 atomics 85// and the 1.1 atomics with different names, so we translate 86// the 1.0 atomics to the 1.1 naming here if needed. 87static char* 88atomTranslateIfNeeded(const char *Name, unsigned int Len) 89{ 90 char *buffer = NULL; 91 if (strncmp(Name, "__atom_", 7)) { 92 // If we are not starting with __atom_, then 93 // go ahead and continue on with the allocation. 94 buffer = new char[Len + 1]; 95 memcpy(buffer, Name, Len); 96 } else { 97 buffer = new char[Len + 3]; 98 memcpy(buffer, "__atomic_", 9); 99 memcpy(buffer + 9, Name + 7, Len - 7); 100 Len += 2; 101 } 102 buffer[Len] = '\0'; 103 return buffer; 104} 105 106unsigned int 107AMDILIntrinsicInfo::lookupName(const char *Name, unsigned int Len) const 108{ 109#define GET_FUNCTION_RECOGNIZER 110#include "AMDILGenIntrinsics.inc" 111#undef GET_FUNCTION_RECOGNIZER 112 AMDGPUIntrinsic::ID IntrinsicID 113 = (AMDGPUIntrinsic::ID)Intrinsic::not_intrinsic; 114 if (checkTruncation(Name, Len)) { 115 char *buffer = atomTranslateIfNeeded(Name, Len); 116 IntrinsicID = getIntrinsicForGCCBuiltin("AMDIL", buffer); 117 delete [] buffer; 118 } else { 119 IntrinsicID = getIntrinsicForGCCBuiltin("AMDIL", Name); 120 } 121 if (!isValidIntrinsic(IntrinsicID)) { 122 return 0; 123 } 124 if (IntrinsicID != (AMDGPUIntrinsic::ID)Intrinsic::not_intrinsic) { 125 return IntrinsicID; 126 } 127 return 0; 128} 129 130bool 131AMDILIntrinsicInfo::isOverloaded(unsigned id) const 132{ 133 // Overload Table 134#define GET_INTRINSIC_OVERLOAD_TABLE 135#include "AMDILGenIntrinsics.inc" 136#undef GET_INTRINSIC_OVERLOAD_TABLE 137} 138 139/// This defines the "getAttributes(ID id)" method. 140#define GET_INTRINSIC_ATTRIBUTES 141#include "AMDILGenIntrinsics.inc" 142#undef GET_INTRINSIC_ATTRIBUTES 143 144Function* 145AMDILIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, 146 Type **Tys, 147 unsigned numTys) const 148{ 149 assert(!isOverloaded(IntrID) && "AMDIL intrinsics are not overloaded"); 150 AttrListPtr AList = getAttributes((AMDGPUIntrinsic::ID) IntrID); 151 LLVMContext& Context = M->getContext(); 152 unsigned int id = IntrID; 153 Type *ResultTy = NULL; 154 std::vector<Type*> ArgTys; 155 bool IsVarArg = false; 156 157#define GET_INTRINSIC_GENERATOR 158#include "AMDILGenIntrinsics.inc" 159#undef GET_INTRINSIC_GENERATOR 160 // We need to add the resource ID argument for atomics. 161 if (id >= AMDGPUIntrinsic::AMDIL_atomic_add_gi32 162 && id <= AMDGPUIntrinsic::AMDIL_atomic_xor_ru32_noret) { 163 ArgTys.push_back(IntegerType::get(Context, 32)); 164 } 165 166 return cast<Function>(M->getOrInsertFunction(getName(IntrID), 167 FunctionType::get(ResultTy, ArgTys, IsVarArg), 168 AList)); 169} 170 171/// Because the code generator has to support different SC versions, 172/// this function is added to check that the intrinsic being used 173/// is actually valid. In the case where it isn't valid, the 174/// function call is not translated into an intrinsic and the 175/// fall back software emulated path should pick up the result. 176bool 177AMDILIntrinsicInfo::isValidIntrinsic(unsigned int IntrID) const 178{ 179 const AMDILSubtarget &STM = mTM->getSubtarget<AMDILSubtarget>(); 180 switch (IntrID) { 181 default: 182 return true; 183 case AMDGPUIntrinsic::AMDIL_convert_f32_i32_rpi: 184 case AMDGPUIntrinsic::AMDIL_convert_f32_i32_flr: 185 case AMDGPUIntrinsic::AMDIL_convert_f32_f16_near: 186 case AMDGPUIntrinsic::AMDIL_convert_f32_f16_neg_inf: 187 case AMDGPUIntrinsic::AMDIL_convert_f32_f16_plus_inf: 188 return STM.calVersion() >= CAL_VERSION_SC_139; 189 }; 190} 191