1 //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the IntrinsicLowering class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/CodeGen/IntrinsicLowering.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/DataLayout.h"
17 #include "llvm/IR/DerivedTypes.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/Type.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/raw_ostream.h"
25 /// This function is used when we want to lower an intrinsic call to a call of
26 /// an external function. This handles hard cases such as when there was already
27 /// a prototype for the external function, but that prototype doesn't match the
28 /// arguments we expect to pass in.
29 template <class ArgIt
>
30 static CallInst
*ReplaceCallWith(const char *NewFn
, CallInst
*CI
,
31 ArgIt ArgBegin
, ArgIt ArgEnd
,
33 // If we haven't already looked up this function, check to see if the
34 // program already contains a function with this name.
35 Module
*M
= CI
->getModule();
36 // Get or insert the definition now.
37 std::vector
<Type
*> ParamTys
;
38 for (ArgIt I
= ArgBegin
; I
!= ArgEnd
; ++I
)
39 ParamTys
.push_back((*I
)->getType());
40 FunctionCallee FCache
=
41 M
->getOrInsertFunction(NewFn
, FunctionType::get(RetTy
, ParamTys
, false));
43 IRBuilder
<> Builder(CI
->getParent(), CI
->getIterator());
44 SmallVector
<Value
*, 8> Args(ArgBegin
, ArgEnd
);
45 CallInst
*NewCI
= Builder
.CreateCall(FCache
, Args
);
46 NewCI
->setName(CI
->getName());
48 CI
->replaceAllUsesWith(NewCI
);
52 /// Emit the code to lower bswap of V before the specified instruction IP.
53 static Value
*LowerBSWAP(LLVMContext
&Context
, Value
*V
, Instruction
*IP
) {
54 assert(V
->getType()->isIntOrIntVectorTy() && "Can't bswap a non-integer type!");
56 unsigned BitSize
= V
->getType()->getScalarSizeInBits();
58 IRBuilder
<> Builder(IP
);
61 default: llvm_unreachable("Unhandled type size of value to byteswap!");
63 Value
*Tmp1
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 8),
65 Value
*Tmp2
= Builder
.CreateLShr(V
, ConstantInt::get(V
->getType(), 8),
67 V
= Builder
.CreateOr(Tmp1
, Tmp2
, "bswap.i16");
71 Value
*Tmp4
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 24),
73 Value
*Tmp3
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 8),
75 Value
*Tmp2
= Builder
.CreateLShr(V
, ConstantInt::get(V
->getType(), 8),
77 Value
*Tmp1
= Builder
.CreateLShr(V
,ConstantInt::get(V
->getType(), 24),
79 Tmp3
= Builder
.CreateAnd(Tmp3
,
80 ConstantInt::get(V
->getType(), 0xFF0000),
82 Tmp2
= Builder
.CreateAnd(Tmp2
,
83 ConstantInt::get(V
->getType(), 0xFF00),
85 Tmp4
= Builder
.CreateOr(Tmp4
, Tmp3
, "bswap.or1");
86 Tmp2
= Builder
.CreateOr(Tmp2
, Tmp1
, "bswap.or2");
87 V
= Builder
.CreateOr(Tmp4
, Tmp2
, "bswap.i32");
91 Value
*Tmp8
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 56),
93 Value
*Tmp7
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 40),
95 Value
*Tmp6
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 24),
97 Value
*Tmp5
= Builder
.CreateShl(V
, ConstantInt::get(V
->getType(), 8),
99 Value
* Tmp4
= Builder
.CreateLShr(V
, ConstantInt::get(V
->getType(), 8),
101 Value
* Tmp3
= Builder
.CreateLShr(V
,
102 ConstantInt::get(V
->getType(), 24),
104 Value
* Tmp2
= Builder
.CreateLShr(V
,
105 ConstantInt::get(V
->getType(), 40),
107 Value
* Tmp1
= Builder
.CreateLShr(V
,
108 ConstantInt::get(V
->getType(), 56),
110 Tmp7
= Builder
.CreateAnd(Tmp7
,
111 ConstantInt::get(V
->getType(),
112 0xFF000000000000ULL
),
114 Tmp6
= Builder
.CreateAnd(Tmp6
,
115 ConstantInt::get(V
->getType(),
118 Tmp5
= Builder
.CreateAnd(Tmp5
,
119 ConstantInt::get(V
->getType(),
122 Tmp4
= Builder
.CreateAnd(Tmp4
,
123 ConstantInt::get(V
->getType(),
126 Tmp3
= Builder
.CreateAnd(Tmp3
,
127 ConstantInt::get(V
->getType(),
130 Tmp2
= Builder
.CreateAnd(Tmp2
,
131 ConstantInt::get(V
->getType(),
134 Tmp8
= Builder
.CreateOr(Tmp8
, Tmp7
, "bswap.or1");
135 Tmp6
= Builder
.CreateOr(Tmp6
, Tmp5
, "bswap.or2");
136 Tmp4
= Builder
.CreateOr(Tmp4
, Tmp3
, "bswap.or3");
137 Tmp2
= Builder
.CreateOr(Tmp2
, Tmp1
, "bswap.or4");
138 Tmp8
= Builder
.CreateOr(Tmp8
, Tmp6
, "bswap.or5");
139 Tmp4
= Builder
.CreateOr(Tmp4
, Tmp2
, "bswap.or6");
140 V
= Builder
.CreateOr(Tmp8
, Tmp4
, "bswap.i64");
147 /// Emit the code to lower ctpop of V before the specified instruction IP.
148 static Value
*LowerCTPOP(LLVMContext
&Context
, Value
*V
, Instruction
*IP
) {
149 assert(V
->getType()->isIntegerTy() && "Can't ctpop a non-integer type!");
151 static const uint64_t MaskValues
[6] = {
152 0x5555555555555555ULL
, 0x3333333333333333ULL
,
153 0x0F0F0F0F0F0F0F0FULL
, 0x00FF00FF00FF00FFULL
,
154 0x0000FFFF0000FFFFULL
, 0x00000000FFFFFFFFULL
157 IRBuilder
<> Builder(IP
);
159 unsigned BitSize
= V
->getType()->getPrimitiveSizeInBits();
160 unsigned WordSize
= (BitSize
+ 63) / 64;
161 Value
*Count
= ConstantInt::get(V
->getType(), 0);
163 for (unsigned n
= 0; n
< WordSize
; ++n
) {
164 Value
*PartValue
= V
;
165 for (unsigned i
= 1, ct
= 0; i
< (BitSize
>64 ? 64 : BitSize
);
167 Value
*MaskCst
= ConstantInt::get(V
->getType(), MaskValues
[ct
]);
168 Value
*LHS
= Builder
.CreateAnd(PartValue
, MaskCst
, "cppop.and1");
169 Value
*VShift
= Builder
.CreateLShr(PartValue
,
170 ConstantInt::get(V
->getType(), i
),
172 Value
*RHS
= Builder
.CreateAnd(VShift
, MaskCst
, "cppop.and2");
173 PartValue
= Builder
.CreateAdd(LHS
, RHS
, "ctpop.step");
175 Count
= Builder
.CreateAdd(PartValue
, Count
, "ctpop.part");
177 V
= Builder
.CreateLShr(V
, ConstantInt::get(V
->getType(), 64),
186 /// Emit the code to lower ctlz of V before the specified instruction IP.
187 static Value
*LowerCTLZ(LLVMContext
&Context
, Value
*V
, Instruction
*IP
) {
189 IRBuilder
<> Builder(IP
);
191 unsigned BitSize
= V
->getType()->getPrimitiveSizeInBits();
192 for (unsigned i
= 1; i
< BitSize
; i
<<= 1) {
193 Value
*ShVal
= ConstantInt::get(V
->getType(), i
);
194 ShVal
= Builder
.CreateLShr(V
, ShVal
, "ctlz.sh");
195 V
= Builder
.CreateOr(V
, ShVal
, "ctlz.step");
198 V
= Builder
.CreateNot(V
);
199 return LowerCTPOP(Context
, V
, IP
);
202 static void ReplaceFPIntrinsicWithCall(CallInst
*CI
, const char *Fname
,
204 const char *LDname
) {
205 switch (CI
->getArgOperand(0)->getType()->getTypeID()) {
206 default: llvm_unreachable("Invalid type in intrinsic");
207 case Type::FloatTyID
:
208 ReplaceCallWith(Fname
, CI
, CI
->arg_begin(), CI
->arg_end(),
209 Type::getFloatTy(CI
->getContext()));
211 case Type::DoubleTyID
:
212 ReplaceCallWith(Dname
, CI
, CI
->arg_begin(), CI
->arg_end(),
213 Type::getDoubleTy(CI
->getContext()));
215 case Type::X86_FP80TyID
:
216 case Type::FP128TyID
:
217 case Type::PPC_FP128TyID
:
218 ReplaceCallWith(LDname
, CI
, CI
->arg_begin(), CI
->arg_end(),
219 CI
->getArgOperand(0)->getType());
224 void IntrinsicLowering::LowerIntrinsicCall(CallInst
*CI
) {
225 IRBuilder
<> Builder(CI
);
226 LLVMContext
&Context
= CI
->getContext();
228 const Function
*Callee
= CI
->getCalledFunction();
229 assert(Callee
&& "Cannot lower an indirect call!");
231 switch (Callee
->getIntrinsicID()) {
232 case Intrinsic::not_intrinsic
:
233 report_fatal_error("Cannot lower a call to a non-intrinsic function '"+
234 Callee
->getName() + "'!");
236 report_fatal_error("Code generator does not support intrinsic function '"+
237 Callee
->getName()+"'!");
239 case Intrinsic::expect
: {
240 // Just replace __builtin_expect(exp, c) with EXP.
241 Value
*V
= CI
->getArgOperand(0);
242 CI
->replaceAllUsesWith(V
);
246 case Intrinsic::ctpop
:
247 CI
->replaceAllUsesWith(LowerCTPOP(Context
, CI
->getArgOperand(0), CI
));
250 case Intrinsic::bswap
:
251 CI
->replaceAllUsesWith(LowerBSWAP(Context
, CI
->getArgOperand(0), CI
));
254 case Intrinsic::ctlz
:
255 CI
->replaceAllUsesWith(LowerCTLZ(Context
, CI
->getArgOperand(0), CI
));
258 case Intrinsic::cttz
: {
259 // cttz(x) -> ctpop(~X & (X-1))
260 Value
*Src
= CI
->getArgOperand(0);
261 Value
*NotSrc
= Builder
.CreateNot(Src
);
262 NotSrc
->setName(Src
->getName() + ".not");
263 Value
*SrcM1
= ConstantInt::get(Src
->getType(), 1);
264 SrcM1
= Builder
.CreateSub(Src
, SrcM1
);
265 Src
= LowerCTPOP(Context
, Builder
.CreateAnd(NotSrc
, SrcM1
), CI
);
266 CI
->replaceAllUsesWith(Src
);
270 case Intrinsic::stacksave
:
271 case Intrinsic::stackrestore
: {
273 errs() << "WARNING: this target does not support the llvm.stack"
274 << (Callee
->getIntrinsicID() == Intrinsic::stacksave
?
275 "save" : "restore") << " intrinsic.\n";
277 if (Callee
->getIntrinsicID() == Intrinsic::stacksave
)
278 CI
->replaceAllUsesWith(Constant::getNullValue(CI
->getType()));
282 case Intrinsic::get_dynamic_area_offset
:
283 errs() << "WARNING: this target does not support the custom llvm.get."
284 "dynamic.area.offset. It is being lowered to a constant 0\n";
285 // Just lower it to a constant 0 because for most targets
286 // @llvm.get.dynamic.area.offset is lowered to zero.
287 CI
->replaceAllUsesWith(ConstantInt::get(CI
->getType(), 0));
289 case Intrinsic::returnaddress
:
290 case Intrinsic::frameaddress
:
291 errs() << "WARNING: this target does not support the llvm."
292 << (Callee
->getIntrinsicID() == Intrinsic::returnaddress
?
293 "return" : "frame") << "address intrinsic.\n";
294 CI
->replaceAllUsesWith(
295 ConstantPointerNull::get(cast
<PointerType
>(CI
->getType())));
297 case Intrinsic::addressofreturnaddress
:
298 errs() << "WARNING: this target does not support the "
299 "llvm.addressofreturnaddress intrinsic.\n";
300 CI
->replaceAllUsesWith(
301 ConstantPointerNull::get(cast
<PointerType
>(CI
->getType())));
304 case Intrinsic::prefetch
:
305 break; // Simply strip out prefetches on unsupported architectures
307 case Intrinsic::pcmarker
:
308 break; // Simply strip out pcmarker on unsupported architectures
309 case Intrinsic::readcyclecounter
: {
310 errs() << "WARNING: this target does not support the llvm.readcyclecoun"
311 << "ter intrinsic. It is being lowered to a constant 0\n";
312 CI
->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context
), 0));
316 case Intrinsic::dbg_declare
:
317 case Intrinsic::dbg_label
:
318 break; // Simply strip out debugging intrinsics
320 case Intrinsic::eh_typeid_for
:
321 // Return something different to eh_selector.
322 CI
->replaceAllUsesWith(ConstantInt::get(CI
->getType(), 1));
325 case Intrinsic::annotation
:
326 case Intrinsic::ptr_annotation
:
327 // Just drop the annotation, but forward the value
328 CI
->replaceAllUsesWith(CI
->getOperand(0));
331 case Intrinsic::assume
:
332 case Intrinsic::experimental_noalias_scope_decl
:
333 case Intrinsic::var_annotation
:
334 break; // Strip out these intrinsics
336 case Intrinsic::memcpy
: {
337 Type
*IntPtr
= DL
.getIntPtrType(Context
);
338 Value
*Size
= Builder
.CreateIntCast(CI
->getArgOperand(2), IntPtr
,
339 /* isSigned */ false);
341 Ops
[0] = CI
->getArgOperand(0);
342 Ops
[1] = CI
->getArgOperand(1);
344 ReplaceCallWith("memcpy", CI
, Ops
, Ops
+3, CI
->getArgOperand(0)->getType());
347 case Intrinsic::memmove
: {
348 Type
*IntPtr
= DL
.getIntPtrType(Context
);
349 Value
*Size
= Builder
.CreateIntCast(CI
->getArgOperand(2), IntPtr
,
350 /* isSigned */ false);
352 Ops
[0] = CI
->getArgOperand(0);
353 Ops
[1] = CI
->getArgOperand(1);
355 ReplaceCallWith("memmove", CI
, Ops
, Ops
+3, CI
->getArgOperand(0)->getType());
358 case Intrinsic::memset
: {
359 Value
*Op0
= CI
->getArgOperand(0);
360 Type
*IntPtr
= DL
.getIntPtrType(Op0
->getType());
361 Value
*Size
= Builder
.CreateIntCast(CI
->getArgOperand(2), IntPtr
,
362 /* isSigned */ false);
365 // Extend the amount to i32.
366 Ops
[1] = Builder
.CreateIntCast(CI
->getArgOperand(1),
367 Type::getInt32Ty(Context
),
368 /* isSigned */ false);
370 ReplaceCallWith("memset", CI
, Ops
, Ops
+3, CI
->getArgOperand(0)->getType());
373 case Intrinsic::sqrt
: {
374 ReplaceFPIntrinsicWithCall(CI
, "sqrtf", "sqrt", "sqrtl");
377 case Intrinsic::log
: {
378 ReplaceFPIntrinsicWithCall(CI
, "logf", "log", "logl");
381 case Intrinsic::log2
: {
382 ReplaceFPIntrinsicWithCall(CI
, "log2f", "log2", "log2l");
385 case Intrinsic::log10
: {
386 ReplaceFPIntrinsicWithCall(CI
, "log10f", "log10", "log10l");
389 case Intrinsic::exp
: {
390 ReplaceFPIntrinsicWithCall(CI
, "expf", "exp", "expl");
393 case Intrinsic::exp2
: {
394 ReplaceFPIntrinsicWithCall(CI
, "exp2f", "exp2", "exp2l");
397 case Intrinsic::pow
: {
398 ReplaceFPIntrinsicWithCall(CI
, "powf", "pow", "powl");
401 case Intrinsic::sin
: {
402 ReplaceFPIntrinsicWithCall(CI
, "sinf", "sin", "sinl");
405 case Intrinsic::cos
: {
406 ReplaceFPIntrinsicWithCall(CI
, "cosf", "cos", "cosl");
409 case Intrinsic::floor
: {
410 ReplaceFPIntrinsicWithCall(CI
, "floorf", "floor", "floorl");
413 case Intrinsic::ceil
: {
414 ReplaceFPIntrinsicWithCall(CI
, "ceilf", "ceil", "ceill");
417 case Intrinsic::trunc
: {
418 ReplaceFPIntrinsicWithCall(CI
, "truncf", "trunc", "truncl");
421 case Intrinsic::round
: {
422 ReplaceFPIntrinsicWithCall(CI
, "roundf", "round", "roundl");
425 case Intrinsic::roundeven
: {
426 ReplaceFPIntrinsicWithCall(CI
, "roundevenf", "roundeven", "roundevenl");
429 case Intrinsic::copysign
: {
430 ReplaceFPIntrinsicWithCall(CI
, "copysignf", "copysign", "copysignl");
433 case Intrinsic::flt_rounds
:
434 // Lower to "round to the nearest"
435 if (!CI
->getType()->isVoidTy())
436 CI
->replaceAllUsesWith(ConstantInt::get(CI
->getType(), 1));
438 case Intrinsic::invariant_start
:
439 case Intrinsic::lifetime_start
:
440 // Discard region information.
441 CI
->replaceAllUsesWith(UndefValue::get(CI
->getType()));
443 case Intrinsic::invariant_end
:
444 case Intrinsic::lifetime_end
:
445 // Discard region information.
449 assert(CI
->use_empty() &&
450 "Lowering should have eliminated any uses of the intrinsic call!");
451 CI
->eraseFromParent();
454 bool IntrinsicLowering::LowerToByteSwap(CallInst
*CI
) {
455 // Verify this is a simple bswap.
456 if (CI
->arg_size() != 1 || CI
->getType() != CI
->getArgOperand(0)->getType() ||
457 !CI
->getType()->isIntegerTy())
460 IntegerType
*Ty
= dyn_cast
<IntegerType
>(CI
->getType());
464 // Okay, we can do this xform, do so now.
465 Module
*M
= CI
->getModule();
466 Function
*Int
= Intrinsic::getDeclaration(M
, Intrinsic::bswap
, Ty
);
468 Value
*Op
= CI
->getArgOperand(0);
469 Op
= CallInst::Create(Int
, Op
, CI
->getName(), CI
);
471 CI
->replaceAllUsesWith(Op
);
472 CI
->eraseFromParent();