OSDN Git Service

radeonsi: initial WIP SI code
[android-x86/external-mesa.git] / src / gallium / drivers / radeon / AMDILIntrinsicInfo.cpp
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 "AMDILTargetMachine.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Intrinsics.h"
19 #include "llvm/Module.h"
20
21 using namespace llvm;
22
23 #define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
24 #include "AMDILGenIntrinsics.inc"
25 #undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
26
27 AMDILIntrinsicInfo::AMDILIntrinsicInfo(AMDILTargetMachine *tm) 
28   : TargetIntrinsicInfo(), mTM(tm)
29 {
30 }
31
32 std::string 
33 AMDILIntrinsicInfo::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
55 checkTruncation(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.
87 static char*
88 atomTranslateIfNeeded(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
106 unsigned int
107 AMDILIntrinsicInfo::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
130 bool 
131 AMDILIntrinsicInfo::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
144 Function*
145 AMDILIntrinsicInfo::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.
176 bool
177 AMDILIntrinsicInfo::isValidIntrinsic(unsigned int IntrID) const
178 {
179   const AMDILSubtarget *stm = mTM->getSubtargetImpl();
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 }