IntrinsicLowering.cpp revision 691ef2ba066dda14ae4ac0ad645054fbc967785a
1//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the default intrinsic lowering implementation. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/CodeGen/IntrinsicLowering.h" 15#include "llvm/Constants.h" 16#include "llvm/DerivedTypes.h" 17#include "llvm/Module.h" 18#include "llvm/Instructions.h" 19#include "llvm/Type.h" 20#include <iostream> 21 22using namespace llvm; 23 24template <class ArgIt> 25static Function *EnsureFunctionExists(Module &M, const char *Name, 26 ArgIt ArgBegin, ArgIt ArgEnd, 27 const Type *RetTy) { 28 if (Function *F = M.getNamedFunction(Name)) return F; 29 // It doesn't already exist in the program, insert a new definition now. 30 std::vector<const Type *> ParamTys; 31 for (ArgIt I = ArgBegin; I != ArgEnd; ++I) 32 ParamTys.push_back(I->getType()); 33 return M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false)); 34} 35 36/// ReplaceCallWith - This function is used when we want to lower an intrinsic 37/// call to a call of an external function. This handles hard cases such as 38/// when there was already a prototype for the external function, and if that 39/// prototype doesn't match the arguments we expect to pass in. 40template <class ArgIt> 41static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI, 42 ArgIt ArgBegin, ArgIt ArgEnd, 43 const Type *RetTy, Function *&FCache) { 44 if (!FCache) { 45 // If we haven't already looked up this function, check to see if the 46 // program already contains a function with this name. 47 Module *M = CI->getParent()->getParent()->getParent(); 48 FCache = M->getNamedFunction(NewFn); 49 if (!FCache) { 50 // It doesn't already exist in the program, insert a new definition now. 51 std::vector<const Type *> ParamTys; 52 for (ArgIt I = ArgBegin; I != ArgEnd; ++I) 53 ParamTys.push_back((*I)->getType()); 54 FCache = M->getOrInsertFunction(NewFn, 55 FunctionType::get(RetTy, ParamTys, false)); 56 } 57 } 58 59 const FunctionType *FT = FCache->getFunctionType(); 60 std::vector<Value*> Operands; 61 unsigned ArgNo = 0; 62 for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams(); 63 ++I, ++ArgNo) { 64 Value *Arg = *I; 65 if (Arg->getType() != FT->getParamType(ArgNo)) 66 Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI); 67 Operands.push_back(Arg); 68 } 69 // Pass nulls into any additional arguments... 70 for (; ArgNo != FT->getNumParams(); ++ArgNo) 71 Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo))); 72 73 std::string Name = CI->getName(); CI->setName(""); 74 if (FT->getReturnType() == Type::VoidTy) Name.clear(); 75 CallInst *NewCI = new CallInst(FCache, Operands, Name, CI); 76 if (!CI->use_empty()) { 77 Value *V = NewCI; 78 if (CI->getType() != NewCI->getType()) 79 V = new CastInst(NewCI, CI->getType(), Name, CI); 80 CI->replaceAllUsesWith(V); 81 } 82 return NewCI; 83} 84 85void DefaultIntrinsicLowering::AddPrototypes(Module &M) { 86 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 87 if (I->isExternal() && !I->use_empty()) 88 switch (I->getIntrinsicID()) { 89 default: break; 90 case Intrinsic::setjmp: 91 EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), Type::IntTy); 92 break; 93 case Intrinsic::longjmp: 94 EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),Type::VoidTy); 95 break; 96 case Intrinsic::siglongjmp: 97 EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), Type::VoidTy); 98 break; 99 case Intrinsic::memcpy: 100 EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(), 101 I->arg_begin()->getType()); 102 break; 103 case Intrinsic::memmove: 104 EnsureFunctionExists(M, "memmove", I->arg_begin(), --I->arg_end(), 105 I->arg_begin()->getType()); 106 break; 107 case Intrinsic::memset: 108 EnsureFunctionExists(M, "memset", I->arg_begin(), --I->arg_end(), 109 I->arg_begin()->getType()); 110 break; 111 case Intrinsic::isunordered: 112 EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy); 113 break; 114 case Intrinsic::sqrt: 115 if(I->arg_begin()->getType() == Type::FloatTy) 116 EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy); 117 else 118 EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy); 119 break; 120 } 121} 122 123void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { 124 Function *Callee = CI->getCalledFunction(); 125 assert(Callee && "Cannot lower an indirect call!"); 126 127 switch (Callee->getIntrinsicID()) { 128 case Intrinsic::not_intrinsic: 129 std::cerr << "Cannot lower a call to a non-intrinsic function '" 130 << Callee->getName() << "'!\n"; 131 abort(); 132 default: 133 std::cerr << "Error: Code generator does not support intrinsic function '" 134 << Callee->getName() << "'!\n"; 135 abort(); 136 137 // The setjmp/longjmp intrinsics should only exist in the code if it was 138 // never optimized (ie, right out of the CFE), or if it has been hacked on 139 // by the lowerinvoke pass. In both cases, the right thing to do is to 140 // convert the call to an explicit setjmp or longjmp call. 141 case Intrinsic::setjmp: { 142 static Function *SetjmpFCache = 0; 143 Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(), 144 Type::IntTy, SetjmpFCache); 145 if (CI->getType() != Type::VoidTy) 146 CI->replaceAllUsesWith(V); 147 break; 148 } 149 case Intrinsic::sigsetjmp: 150 if (CI->getType() != Type::VoidTy) 151 CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); 152 break; 153 154 case Intrinsic::longjmp: { 155 static Function *LongjmpFCache = 0; 156 ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(), 157 Type::VoidTy, LongjmpFCache); 158 break; 159 } 160 161 case Intrinsic::siglongjmp: { 162 // Insert the call to abort 163 static Function *AbortFCache = 0; 164 ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy, 165 AbortFCache); 166 break; 167 } 168 case Intrinsic::ctpop: { 169 Value *Src = CI->getOperand(1); 170 switch (CI->getOperand(0)->getType()->getTypeID()) 171 { 172 case Type::SByteTyID: 173 case Type::UByteTyID: 174 { 175 Value* SA = ConstantUInt::get(Type::UByteTy, 1); 176 Value* MA = ConstantUInt::get(Type::UIntTy, 0x55); 177 Src = BinaryOperator::create(Instruction::Add, 178 BinaryOperator::create(Instruction::And, Src, MA), 179 BinaryOperator::create(Instruction::And, 180 new ShiftInst(Instruction::Shr, Src, SA), 181 MA)); 182 SA = ConstantUInt::get(Type::UByteTy, 2); 183 MA = ConstantUInt::get(Type::UIntTy, 0x33); 184 Src = BinaryOperator::create(Instruction::Add, 185 BinaryOperator::create(Instruction::And, Src, MA), 186 BinaryOperator::create(Instruction::And, 187 new ShiftInst(Instruction::Shr, Src, SA), 188 MA)); 189 SA = ConstantUInt::get(Type::UByteTy, 4); 190 MA = ConstantUInt::get(Type::UIntTy, 0x0F); 191 Src = BinaryOperator::create(Instruction::Add, 192 BinaryOperator::create(Instruction::And, Src, MA), 193 BinaryOperator::create(Instruction::And, 194 new ShiftInst(Instruction::Shr, Src, SA), 195 MA), "ctpop"); 196 } 197 break; 198 case Type::ShortTyID: 199 case Type::UShortTyID: 200 { 201 Value* SA = ConstantUInt::get(Type::UByteTy, 1); 202 Value* MA = ConstantUInt::get(Type::UIntTy, 0x5555); 203 Src = BinaryOperator::create(Instruction::Add, 204 BinaryOperator::create(Instruction::And, Src, MA), 205 BinaryOperator::create(Instruction::And, 206 new ShiftInst(Instruction::Shr, Src, SA), 207 MA)); 208 SA = ConstantUInt::get(Type::UByteTy, 2); 209 MA = ConstantUInt::get(Type::UIntTy, 0x3333); 210 Src = BinaryOperator::create(Instruction::Add, 211 BinaryOperator::create(Instruction::And, Src, MA), 212 BinaryOperator::create(Instruction::And, 213 new ShiftInst(Instruction::Shr, Src, SA), 214 MA)); 215 SA = ConstantUInt::get(Type::UByteTy, 4); 216 MA = ConstantUInt::get(Type::UIntTy, 0x0F0F); 217 Src = BinaryOperator::create(Instruction::Add, 218 BinaryOperator::create(Instruction::And, Src, MA), 219 BinaryOperator::create(Instruction::And, 220 new ShiftInst(Instruction::Shr, Src, SA), 221 MA)); 222 SA = ConstantUInt::get(Type::UByteTy, 8); 223 MA = ConstantUInt::get(Type::UIntTy, 0x00FF); 224 Src = BinaryOperator::create(Instruction::Add, 225 BinaryOperator::create(Instruction::And, Src, MA), 226 BinaryOperator::create(Instruction::And, 227 new ShiftInst(Instruction::Shr, Src, SA), 228 MA), "ctpop"); 229 230 } 231 break; 232 case Type::IntTyID: 233 case Type::UIntTyID: 234 { 235 Value* SA = ConstantUInt::get(Type::UByteTy, 1); 236 Value* MA = ConstantUInt::get(Type::UIntTy, 0x55555555); 237 Src = BinaryOperator::create(Instruction::Add, 238 BinaryOperator::create(Instruction::And, Src, MA), 239 BinaryOperator::create(Instruction::And, 240 new ShiftInst(Instruction::Shr, Src, SA), 241 MA)); 242 SA = ConstantUInt::get(Type::UByteTy, 2); 243 MA = ConstantUInt::get(Type::UIntTy, 0x33333333); 244 Src = BinaryOperator::create(Instruction::Add, 245 BinaryOperator::create(Instruction::And, Src, MA), 246 BinaryOperator::create(Instruction::And, 247 new ShiftInst(Instruction::Shr, Src, SA), 248 MA)); 249 SA = ConstantUInt::get(Type::UByteTy, 4); 250 MA = ConstantUInt::get(Type::UIntTy, 0x0F0F0F0F); 251 Src = BinaryOperator::create(Instruction::Add, 252 BinaryOperator::create(Instruction::And, Src, MA), 253 BinaryOperator::create(Instruction::And, 254 new ShiftInst(Instruction::Shr, Src, SA), 255 MA)); 256 SA = ConstantUInt::get(Type::UByteTy, 8); 257 MA = ConstantUInt::get(Type::UIntTy, 0x00FF00FF); 258 Src = BinaryOperator::create(Instruction::Add, 259 BinaryOperator::create(Instruction::And, Src, MA), 260 BinaryOperator::create(Instruction::And, 261 new ShiftInst(Instruction::Shr, Src, SA), 262 MA)); 263 SA = ConstantUInt::get(Type::UByteTy, 8); 264 MA = ConstantUInt::get(Type::UIntTy, 0x0000FFFF); 265 Src = BinaryOperator::create(Instruction::Add, 266 BinaryOperator::create(Instruction::And, Src, MA), 267 BinaryOperator::create(Instruction::And, 268 new ShiftInst(Instruction::Shr, Src, SA), 269 MA), "ctpop"); 270 } 271 break; 272 case Type::LongTyID: 273 case Type::ULongTyID: 274 { 275 Value* SA = ConstantUInt::get(Type::UByteTy, 1); 276 Value* MA = ConstantUInt::get(Type::ULongTy, 0x5555555555555555ULL); 277 Src = BinaryOperator::create(Instruction::Add, 278 BinaryOperator::create(Instruction::And, Src, MA), 279 BinaryOperator::create(Instruction::And, 280 new ShiftInst(Instruction::Shr, Src, SA), 281 MA)); 282 SA = ConstantUInt::get(Type::UByteTy, 2); 283 MA = ConstantUInt::get(Type::ULongTy, 0x3333333333333333ULL); 284 Src = BinaryOperator::create(Instruction::Add, 285 BinaryOperator::create(Instruction::And, Src, MA), 286 BinaryOperator::create(Instruction::And, 287 new ShiftInst(Instruction::Shr, Src, SA), 288 MA)); 289 SA = ConstantUInt::get(Type::UByteTy, 4); 290 MA = ConstantUInt::get(Type::ULongTy, 0x0F0F0F0F0F0F0F0FULL); 291 Src = BinaryOperator::create(Instruction::Add, 292 BinaryOperator::create(Instruction::And, Src, MA), 293 BinaryOperator::create(Instruction::And, 294 new ShiftInst(Instruction::Shr, Src, SA), 295 MA)); 296 SA = ConstantUInt::get(Type::UByteTy, 8); 297 MA = ConstantUInt::get(Type::ULongTy, 0x00FF00FF00FF00FFULL); 298 Src = BinaryOperator::create(Instruction::Add, 299 BinaryOperator::create(Instruction::And, Src, MA), 300 BinaryOperator::create(Instruction::And, 301 new ShiftInst(Instruction::Shr, Src, SA), 302 MA)); 303 SA = ConstantUInt::get(Type::UByteTy, 16); 304 MA = ConstantUInt::get(Type::ULongTy, 0x00000000FFFFFFFFULL); 305 Src = BinaryOperator::create(Instruction::Add, 306 BinaryOperator::create(Instruction::And, Src, MA), 307 BinaryOperator::create(Instruction::And, 308 new ShiftInst(Instruction::Shr, Src, SA), 309 MA), "ctpop"); 310 } 311 break; 312 default: 313 abort(); 314 } 315 316 CI->replaceAllUsesWith(Src); 317 break; 318 } 319 case Intrinsic::ctlz: { 320 Value *Src = CI->getOperand(1); 321 Value* SA; 322 switch (CI->getOperand(0)->getType()->getTypeID()) 323 { 324 case Type::LongTyID: 325 case Type::ULongTyID: 326 SA = ConstantUInt::get(Type::UByteTy, 32); 327 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 328 case Type::IntTyID: 329 case Type::UIntTyID: 330 SA = ConstantUInt::get(Type::UByteTy, 16); 331 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 332 case Type::ShortTyID: 333 case Type::UShortTyID: 334 SA = ConstantUInt::get(Type::UByteTy, 8); 335 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 336 default: 337 SA = ConstantUInt::get(Type::UByteTy, 1); 338 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 339 SA = ConstantUInt::get(Type::UByteTy, 2); 340 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 341 SA = ConstantUInt::get(Type::UByteTy, 4); 342 Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA)); 343 }; 344 Src = BinaryOperator::createNot(Src); 345 346 Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(), 347 CI->getCalledFunction()->getLinkage(), 348 "llvm.ctpop"), Src); 349 CI->replaceAllUsesWith(Src); 350 break; 351 } 352 case Intrinsic::cttz: { 353 Value *Src = CI->getOperand(1); 354 Src = BinaryOperator::create(Instruction::And, BinaryOperator::createNot(Src), 355 BinaryOperator::create(Instruction::Sub, Src, 356 ConstantUInt::get(CI->getOperand(0)->getType(), 1))); 357 Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(), 358 CI->getCalledFunction()->getLinkage(), 359 "llvm.ctpop"), Src); 360 CI->replaceAllUsesWith(Src); 361 break; 362 } 363 364 case Intrinsic::returnaddress: 365 case Intrinsic::frameaddress: 366 std::cerr << "WARNING: this target does not support the llvm." 367 << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? 368 "return" : "frame") << "address intrinsic.\n"; 369 CI->replaceAllUsesWith(ConstantPointerNull::get( 370 cast<PointerType>(CI->getType()))); 371 break; 372 373 case Intrinsic::prefetch: 374 break; // Simply strip out prefetches on unsupported architectures 375 376 case Intrinsic::pcmarker: 377 break; // Simply strip out pcmarker on unsupported architectures 378 379 case Intrinsic::dbg_stoppoint: 380 case Intrinsic::dbg_region_start: 381 case Intrinsic::dbg_region_end: 382 case Intrinsic::dbg_declare: 383 case Intrinsic::dbg_func_start: 384 if (CI->getType() != Type::VoidTy) 385 CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); 386 break; // Simply strip out debugging intrinsics 387 388 case Intrinsic::memcpy: { 389 // The memcpy intrinsic take an extra alignment argument that the memcpy 390 // libc function does not. 391 static Function *MemcpyFCache = 0; 392 ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1, 393 (*(CI->op_begin()+1))->getType(), MemcpyFCache); 394 break; 395 } 396 case Intrinsic::memmove: { 397 // The memmove intrinsic take an extra alignment argument that the memmove 398 // libc function does not. 399 static Function *MemmoveFCache = 0; 400 ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1, 401 (*(CI->op_begin()+1))->getType(), MemmoveFCache); 402 break; 403 } 404 case Intrinsic::memset: { 405 // The memset intrinsic take an extra alignment argument that the memset 406 // libc function does not. 407 static Function *MemsetFCache = 0; 408 ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1, 409 (*(CI->op_begin()+1))->getType(), MemsetFCache); 410 break; 411 } 412 case Intrinsic::isunordered: { 413 Value *L = CI->getOperand(1); 414 Value *R = CI->getOperand(2); 415 416 Value *LIsNan = new SetCondInst(Instruction::SetNE, L, L, "LIsNan", CI); 417 Value *RIsNan = new SetCondInst(Instruction::SetNE, R, R, "RIsNan", CI); 418 CI->replaceAllUsesWith( 419 BinaryOperator::create(Instruction::Or, LIsNan, RIsNan, 420 "isunordered", CI)); 421 break; 422 } 423 case Intrinsic::sqrt: { 424 static Function *sqrtFCache = 0; 425 static Function *sqrtfFCache = 0; 426 if(CI->getType() == Type::FloatTy) 427 ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(), 428 Type::FloatTy, sqrtfFCache); 429 else 430 ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(), 431 Type::DoubleTy, sqrtFCache); 432 break; 433 } 434 } 435 436 assert(CI->use_empty() && 437 "Lowering should have eliminated any uses of the intrinsic call!"); 438 CI->getParent()->getInstList().erase(CI); 439} 440