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