309 return gen->createFunction(
310 OP_INFO.name, OP_INFO.arity,
311 [gen](llvm::ArrayRef<llvm::Value*> args) -> llvm::Value* {
314 auto* min_norm_pos = gen->getInt32Constant(0x00800000);
315 auto* inv_mant_mask = gen->getInt32Constant(~0x7F800000);
316 auto* sqrt_1_2 = gen->getConstant(0.707106781186547524F);
317 auto* log_p0 = gen->getConstant(7.0376836292E-2F);
318 auto* log_p1 = gen->getConstant(-1.1514610310E-1F);
319 auto* log_p2 = gen->getConstant(1.1676998740E-1F);
320 auto* log_p3 = gen->getConstant(-1.2420140846E-1F);
321 auto* log_p4 = gen->getConstant(1.4249322787E-1F);
322 auto* log_p5 = gen->getConstant(-1.6668057665E-1F);
323 auto* log_p6 = gen->getConstant(2.0000714765E-1F);
324 auto* log_p7 = gen->getConstant(-2.4999993993E-1F);
325 auto* log_p8 = gen->getConstant(3.3333331174E-1F);
326 auto* log_q2 = gen->getConstant(0.693359375F);
327 auto* log_q1 = gen->getConstant(-2.12194440e-4F);
328 auto* one = gen->getConstant(1.0F);
329 auto* neg_half = gen->getConstant(-0.5F);
330 auto* const_0x7f = gen->getInt32Constant(0x7F);
331 auto* const_23 = gen->getInt32Constant(23);
333 auto* is_one = gen->builder.CreateFCmpOEQ(x, one);
334 auto* min_norm_pos_float = gen->builder.CreateBitCast(
335 min_norm_pos, gen->getFloatType());
336 x = gen->createIntrinsicCall(llvm::Intrinsic::maxnum,
337 {x, min_norm_pos_float});
339 gen->builder.CreateBitCast(x, gen->getInt32Type());
340 auto* emm0i = gen->builder.CreateLShr(x_as_int, const_23);
342 gen->builder.CreateAnd(x_as_int, inv_mant_mask);
343 auto* half_as_int = gen->builder.CreateBitCast(
346 gen->getInt32Type());
347 x_masked = gen->builder.CreateOr(x_masked, half_as_int);
348 x = gen->builder.CreateBitCast(x_masked, gen->getFloatType());
349 emm0i = gen->builder.CreateSub(emm0i, const_0x7f);
351 gen->builder.CreateSIToFP(emm0i, gen->getFloatType());
352 emm0 = gen->builder.CreateFAdd(emm0, one);
353 auto* mask = gen->builder.CreateFCmpOLT(x, sqrt_1_2);
355 gen->builder.CreateSExt(mask, gen->getInt32Type());
356 x_as_int = gen->builder.CreateBitCast(x, gen->getInt32Type());
357 auto* etmp_as_int = gen->builder.CreateAnd(ext_mask, x_as_int);
358 auto* etmp = gen->builder.CreateBitCast(etmp_as_int,
359 gen->getFloatType());
360 x = gen->builder.CreateFSub(x, one);
362 gen->builder.CreateBitCast(one, gen->getInt32Type());
364 gen->builder.CreateAnd(ext_mask, one_as_int);
365 auto* maskf = gen->builder.CreateBitCast(maskf_as_int,
366 gen->getFloatType());
367 emm0 = gen->builder.CreateFSub(emm0, maskf);
368 x = gen->builder.CreateFAdd(x, etmp);
369 auto* z = gen->builder.CreateFMul(x, x);
370 llvm::Value* y = log_p0;
371 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
373 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
375 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
377 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
379 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
381 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
383 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
385 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
387 y = gen->builder.CreateFMul(y, x);
388 y = gen->builder.CreateFMul(y, z);
389 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
391 y = gen->createIntrinsicCall(llvm::Intrinsic::fma,
393 x = gen->builder.CreateFAdd(x, y);
394 x = gen->createIntrinsicCall(llvm::Intrinsic::fma,
396 x_as_int = gen->builder.CreateBitCast(x, gen->getInt32Type());
398 gen->builder.CreateSExt(is_one, gen->getInt32Type());
399 auto* not_ext_is_one = gen->builder.CreateNot(ext_is_one);
400 auto* result_as_int =
401 gen->builder.CreateAnd(not_ext_is_one, x_as_int);
402 x = gen->builder.CreateBitCast(result_as_int,
403 gen->getFloatType());