LLVM: lib/CodeGen/ExpandLargeFpConvert.cpp File Reference (original) (raw)

Generate code to convert a fp number to integer, replacing S(U)IToFP with the generated code.

This currently generates code similarly to compiler-rt's implementations. This implementation has an implicit assumption that integer width is larger than fp.

An example IR generated from compiler-rt/floatdisf.c looks like below: define dso_local float @__floatdisf(i64 noundef a) local_unnamed_addr #0 { entry: cmp = icmp eq i64 a, 0 br i1 cmp, label return, label if.end

if.end: ; preds = entry shr = ashr i64 a, 63 xor = xor i64 shr, a sub = sub nsw i64 xor, shr %0 = tail call i64 @llvm.ctlz.i64(i64 sub, i1 true), !range !5 cast = trunc i64 %0 to i32 sub1 = sub nuw nsw i32 64, cast sub2 = xor i32 cast, 63 cmp3 = icmp ult i32 cast, 40 br i1 cmp3, label if.then4, label if.else

if.then4: ; preds = if.end switch i32 sub1, label sw.default [ i32 25, label sw.bb i32 26, label sw.epilog ]

sw.bb: ; preds = if.then4 shl = shl i64 sub, 1 br label sw.epilog

sw.default: ; preds = if.then4 sub5 = sub nsw i64 38, %0 sh_prom = and i64 sub5, 4294967295 shr6 = lshr i64 sub, sh_prom shr9 = lshr i64 274877906943, %0 and = and i64 shr9, sub cmp10 = icmp ne i64 and, 0 conv11 = zext i1 cmp10 to i64 or = or i64 shr6, conv11 br label sw.epilog

sw.epilog: ; preds = sw.default, if.then4, sw.bb a.addr.0 = phi i64 [ or, sw.default ], [ sub, if.then4 ], [ shl, sw.bb ] %1 = lshr i64 a.addr.0, 2 %2 = and i64 %1, 1 or16 = or i64 %2, a.addr.0 inc = add nsw i64 or16, 1 %3 = and i64 inc, 67108864 tobool.not = icmp eq i64 %3, 0 spec.select.v = select i1 tobool.not, i64 2, i64 3 spec.select = ashr i64 inc, spec.select.v spec.select56 = select i1 tobool.not, i32 sub2, i32 sub1 br label if.end26

if.else: ; preds = if.end sub23 = add nuw nsw i64 %0, 4294967256 sh_prom24 = and i64 sub23, 4294967295 shl25 = shl i64 sub, sh_prom24 br label if.end26

if.end26: ; preds = sw.epilog, if.else a.addr.1 = phi i64 [ shl25, if.else ], [ spec.select, sw.epilog ] e.0 = phi i32 [ sub2, if.else ], [ spec.select56, sw.epilog ] conv27 = trunc i64 shr to i32 and28 = and i32 conv27, -2147483648 add = shl nuw nsw i32 e.0, 23 shl29 = add nuw nsw i32 add, 1065353216 conv31 = trunc i64 a.addr.1 to i32 and32 = and i32 conv31, 8388607 or30 = or i32 and32, and28 or33 = or i32 or30, shl29 %4 = bitcast i32 or33 to float br label return

return: ; preds = entry, if.end26 retval.0 = phi float [ %4, if.end26 ], [ 0.000000e+00, entry ] ret float retval.0 }

Replace integer to fp with generated code.

Definition at line 309 of file ExpandLargeFpConvert.cpp.

References llvm::Add, llvm::PHINode::addIncoming(), llvm::And, assert(), llvm::BitWidth, llvm::BasicBlock::Create(), llvm::IRBuilderBase::CreateAdd(), llvm::IRBuilderBase::CreateAnd(), llvm::IRBuilderBase::CreateAShr(), llvm::IRBuilderBase::CreateBitCast(), llvm::IRBuilderBase::CreateBr(), llvm::IRBuilderBase::CreateCall(), llvm::IRBuilderBase::CreateCondBr(), llvm::IRBuilderBase::CreateFPTrunc(), llvm::IRBuilderBase::CreateICmpEQ(), llvm::IRBuilderBase::CreateICmpNE(), llvm::IRBuilderBase::CreateICmpSGT(), llvm::IRBuilderBase::CreateLShr(), llvm::IRBuilderBase::CreateOr(), llvm::IRBuilderBase::CreatePHI(), llvm::IRBuilderBase::CreateShl(), llvm::IRBuilderBase::CreateSub(), llvm::IRBuilderBase::CreateSwitch(), llvm::IRBuilderBase::CreateTrunc(), llvm::IRBuilderBase::CreateXor(), llvm::IRBuilderBase::CreateZExt(), llvm::User::dropAllReferences(), End, llvm::Instruction::eraseFromParent(), F, llvm::IRBuilderBase::getContext(), llvm::Type::getFloatTy(), llvm::Type::getFP128Ty(), llvm::Type::getFPMantissaWidth(), llvm::IRBuilderBase::GetInsertBlock(), llvm::IRBuilderBase::GetInsertPoint(), llvm::IRBuilderBase::getInt32Ty(), llvm::IRBuilderBase::getInt64Ty(), llvm::IRBuilderBase::getIntN(), llvm::IRBuilderBase::getIntNTy(), llvm::Instruction::getOpcode(), llvm::User::getOperand(), llvm::Intrinsic::getOrInsertDeclaration(), llvm::ConstantInt::getSigned(), llvm::IRBuilderBase::getTrue(), llvm::Value::getType(), llvm::ConstantFP::getZero(), llvm::Type::isBFloatTy(), llvm::Type::isDoubleTy(), llvm::Type::isHalfTy(), llvm::Type::isX86_FP80Ty(), llvm::Or, llvm::PowerOf2Ceil(), llvm::Value::replaceAllUsesWith(), llvm::IRBuilderBase::SetInsertPoint(), and llvm::Xor.

Referenced by runImpl().