LLVM: lib/CodeGen/IntrinsicLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23using namespace llvm;

24

25

26

27

28

29template

31 ArgIt ArgBegin, ArgIt ArgEnd,

32 Type *RetTy) {

33

34

36

37 std::vector<Type *> ParamTys;

38 for (ArgIt I = ArgBegin; I != ArgEnd; ++I)

39 ParamTys.push_back((*I)->getType());

41 M->getOrInsertFunction(NewFn, FunctionType::get(RetTy, ParamTys, false));

42

45 CallInst *NewCI = Builder.CreateCall(FCache, Args);

49 return NewCI;

50}

51

52

54 assert(V->getType()->isIntOrIntVectorTy() && "Can't bswap a non-integer type!");

55

56 unsigned BitSize = V->getType()->getScalarSizeInBits();

57

59

60 switch(BitSize) {

61 default: llvm_unreachable("Unhandled type size of value to byteswap!");

62 case 16: {

63 Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),

64 "bswap.2");

65 Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),

66 "bswap.1");

67 V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16");

68 break;

69 }

70 case 32: {

71 Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),

72 "bswap.4");

73 Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),

74 "bswap.3");

75 Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),

76 "bswap.2");

77 Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24),

78 "bswap.1");

79 Tmp3 = Builder.CreateAnd(Tmp3,

80 ConstantInt::get(V->getType(), 0xFF0000),

81 "bswap.and3");

82 Tmp2 = Builder.CreateAnd(Tmp2,

83 ConstantInt::get(V->getType(), 0xFF00),

84 "bswap.and2");

85 Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1");

86 Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2");

87 V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32");

88 break;

89 }

90 case 64: {

91 Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56),

92 "bswap.8");

93 Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40),

94 "bswap.7");

95 Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24),

96 "bswap.6");

97 Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8),

98 "bswap.5");

99 Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8),

100 "bswap.4");

101 Value* Tmp3 = Builder.CreateLShr(V,

102 ConstantInt::get(V->getType(), 24),

103 "bswap.3");

104 Value* Tmp2 = Builder.CreateLShr(V,

105 ConstantInt::get(V->getType(), 40),

106 "bswap.2");

107 Value* Tmp1 = Builder.CreateLShr(V,

108 ConstantInt::get(V->getType(), 56),

109 "bswap.1");

110 Tmp7 = Builder.CreateAnd(Tmp7,

111 ConstantInt::get(V->getType(),

112 0xFF000000000000ULL),

113 "bswap.and7");

114 Tmp6 = Builder.CreateAnd(Tmp6,

115 ConstantInt::get(V->getType(),

116 0xFF0000000000ULL),

117 "bswap.and6");

118 Tmp5 = Builder.CreateAnd(Tmp5,

119 ConstantInt::get(V->getType(),

120 0xFF00000000ULL),

121 "bswap.and5");

122 Tmp4 = Builder.CreateAnd(Tmp4,

123 ConstantInt::get(V->getType(),

124 0xFF000000ULL),

125 "bswap.and4");

126 Tmp3 = Builder.CreateAnd(Tmp3,

127 ConstantInt::get(V->getType(),

128 0xFF0000ULL),

129 "bswap.and3");

130 Tmp2 = Builder.CreateAnd(Tmp2,

131 ConstantInt::get(V->getType(),

132 0xFF00ULL),

133 "bswap.and2");

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");

141 break;

142 }

143 }

144 return V;

145}

146

147

149 assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!");

150

151 static const uint64_t MaskValues[6] = {

152 0x5555555555555555ULL, 0x3333333333333333ULL,

153 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,

154 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL

155 };

156

158

159 unsigned BitSize = V->getType()->getPrimitiveSizeInBits();

160 unsigned WordSize = (BitSize + 63) / 64;

161 Value *Count = ConstantInt::get(V->getType(), 0);

162

163 for (unsigned n = 0; n < WordSize; ++n) {

164 Value *PartValue = V;

165 for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize);

166 i <<= 1, ++ct) {

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),

171 "ctpop.sh");

172 Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2");

173 PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step");

174 }

175 Count = Builder.CreateAdd(PartValue, Count, "ctpop.part");

176 if (BitSize > 64) {

177 V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64),

178 "ctpop.part.sh");

179 BitSize -= 64;

180 }

181 }

182

184}

185

186

188

190

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");

196 }

197

198 V = Builder.CreateNot(V);

200}

201

203 const char *Dname,

204 const char *LDname) {

210 break;

214 break;

220 break;

221 }

222}

223

227

229 assert(Callee && "Cannot lower an indirect call!");

230

231 switch (Callee->getIntrinsicID()) {

233 report_fatal_error("Cannot lower a call to a non-intrinsic function '"+

234 Callee->getName() + "'!");

235 default:

236 report_fatal_error("Code generator does not support intrinsic function '"+

237 Callee->getName()+"'!");

238

239 case Intrinsic::expect:

240 case Intrinsic::expect_with_probability: {

241

242

245 break;

246 }

247

248 case Intrinsic::allow_runtime_check:

249 case Intrinsic::allow_ubsan_check:

251 return;

252

253 case Intrinsic::ctpop:

255 break;

256

257 case Intrinsic::bswap:

259 break;

260

261 case Intrinsic::ctlz:

263 break;

264

265 case Intrinsic::cttz: {

266

268 Value *NotSrc = Builder.CreateNot(Src);

269 NotSrc->setName(Src->getName() + ".not");

270 Value *SrcM1 = ConstantInt::get(Src->getType(), 1);

271 SrcM1 = Builder.CreateSub(Src, SrcM1);

272 Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI);

274 break;

275 }

276

277 case Intrinsic::stacksave:

278 case Intrinsic::stackrestore: {

279 if (!Warned)

280 errs() << "WARNING: this target does not support the llvm.stack"

281 << (Callee->getIntrinsicID() == Intrinsic::stacksave ?

282 "save" : "restore") << " intrinsic.\n";

283 Warned = true;

284 if (Callee->getIntrinsicID() == Intrinsic::stacksave)

286 break;

287 }

288

289 case Intrinsic::get_dynamic_area_offset:

290 errs() << "WARNING: this target does not support the custom llvm.get."

291 "dynamic.area.offset. It is being lowered to a constant 0\n";

292

293

295 break;

296 case Intrinsic::returnaddress:

297 case Intrinsic::frameaddress:

298 errs() << "WARNING: this target does not support the llvm."

299 << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?

300 "return" : "frame") << "address intrinsic.\n";

303 break;

304 case Intrinsic::addressofreturnaddress:

305 errs() << "WARNING: this target does not support the "

306 "llvm.addressofreturnaddress intrinsic.\n";

309 break;

310

311 case Intrinsic::prefetch:

312 break;

313

314 case Intrinsic::pcmarker:

315 break;

316 case Intrinsic::readcyclecounter: {

317 errs() << "WARNING: this target does not support the llvm.readcyclecoun"

318 << "ter intrinsic. It is being lowered to a constant 0\n";

320 break;

321 }

322 case Intrinsic::readsteadycounter: {

323 errs() << "WARNING: this target does not support the llvm.readsteadycounter"

324 << " intrinsic. It is being lowered to a constant 0\n";

326 break;

327 }

328

329 case Intrinsic::dbg_declare:

330 case Intrinsic::dbg_label:

331 break;

332

333 case Intrinsic::eh_typeid_for:

334

336 break;

337

338 case Intrinsic::annotation:

339 case Intrinsic::ptr_annotation:

340

342 break;

343

344 case Intrinsic::assume:

345 case Intrinsic::experimental_noalias_scope_decl:

346 case Intrinsic::var_annotation:

347 break;

348

349 case Intrinsic::memcpy: {

350 Type *IntPtr = DL.getIntPtrType(Context);

352 false);

358 break;

359 }

360 case Intrinsic::memmove: {

361 Type *IntPtr = DL.getIntPtrType(Context);

363 false);

369 break;

370 }

371 case Intrinsic::memset: {

373 Type *IntPtr = DL.getIntPtrType(Op0->getType());

375 false);

377 Ops[0] = Op0;

378

381 false);

384 break;

385 }

386 case Intrinsic::sqrt: {

388 break;

389 }

390 case Intrinsic:🪵 {

392 break;

393 }

394 case Intrinsic::log2: {

396 break;

397 }

398 case Intrinsic::log10: {

400 break;

401 }

402 case Intrinsic::exp: {

404 break;

405 }

406 case Intrinsic::exp2: {

408 break;

409 }

410 case Intrinsic::pow: {

412 break;

413 }

414 case Intrinsic::sin: {

416 break;

417 }

418 case Intrinsic::cos: {

420 break;

421 }

422 case Intrinsic:🤣 {

424 break;

425 }

426 case Intrinsic::ceil: {

428 break;

429 }

430 case Intrinsic::trunc: {

432 break;

433 }

434 case Intrinsic::round: {

436 break;

437 }

438 case Intrinsic::roundeven: {

440 break;

441 }

442 case Intrinsic::copysign: {

444 break;

445 }

446 case Intrinsic::get_rounding:

447

450 break;

451 case Intrinsic::invariant_start:

452 case Intrinsic::lifetime_start:

453

455 break;

456 case Intrinsic::invariant_end:

457 case Intrinsic::lifetime_end:

458

459 break;

460 }

461

463 "Lowering should have eliminated any uses of the intrinsic call!");

465}

466

468

471 return false;

472

474 if (!Ty)

475 return false;

476

477

480

483

486 return true;

487}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

Module.h This file contains the declarations for the Module class.

static Value * LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP)

Emit the code to lower ctlz of V before the specified instruction IP.

Definition IntrinsicLowering.cpp:187

static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname, const char *Dname, const char *LDname)

Definition IntrinsicLowering.cpp:202

static CallInst * ReplaceCallWith(const char *NewFn, CallInst *CI, ArgIt ArgBegin, ArgIt ArgEnd, Type *RetTy)

This function is used when we want to lower an intrinsic call to a call of an external function.

Definition IntrinsicLowering.cpp:30

static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)

Emit the code to lower ctpop of V before the specified instruction IP.

Definition IntrinsicLowering.cpp:148

static Value * LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP)

Emit the code to lower bswap of V before the specified instruction IP.

Definition IntrinsicLowering.cpp:53

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

This file defines the SmallVector class.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

User::op_iterator arg_begin()

Return the iterator pointing to the beginning of the argument list.

Value * getArgOperand(unsigned i) const

User::op_iterator arg_end()

Return the iterator pointing to the end of the argument list.

unsigned arg_size() const

This class represents a function call, abstracting a target machine's calling convention.

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)

static LLVM_ABI ConstantPointerNull * get(PointerType *T)

Static factory methods - Return objects of the specified value.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

LLVM_ABI const Module * getModule() const

Return the module owning the function this instruction belongs to or nullptr it the function does not...

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

Class to represent integer types.

void LowerIntrinsicCall(CallInst *CI)

Replace a call to the specified intrinsic function.

Definition IntrinsicLowering.cpp:224

static bool LowerToByteSwap(CallInst *CI)

Try to replace a call instruction with a call to a bswap intrinsic.

Definition IntrinsicLowering.cpp:467

This is an important class for using LLVM in a threaded context.

A Module instance is used to store all the information related to an LLVM module.

static LLVM_ABI PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

@ FloatTyID

32-bit floating point type

@ DoubleTyID

64-bit floating point type

@ X86_FP80TyID

80-bit floating point type (X87)

@ PPC_FP128TyID

128-bit floating point type (two 64-bits, PowerPC)

@ FP128TyID

128-bit floating point type (112-bit significand)

bool isIntegerTy() const

True if this is an instance of IntegerType.

TypeID getTypeID() const

Return the type id for the type.

static LLVM_ABI Type * getDoubleTy(LLVMContext &C)

static LLVM_ABI Type * getFloatTy(LLVMContext &C)

bool isVoidTy() const

Return true if this is 'void'.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI void setName(const Twine &Name)

Change the name of the value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

LLVM_ABI LLVMContext & getContext() const

All values hold a context through their type.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

const ParentTy * getParent() const

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionAddr VTableAddr Count

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.