LLVM 20.0.0git
Functions | Variables
ExpandLargeFpConvert.cpp File Reference
#include "llvm/CodeGen/ExpandLargeFpConvert.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"

Go to the source code of this file.

Functions

static void expandFPToI (Instruction *FPToI)
 Generate code to convert a fp number to integer, replacing FPToS(U)I with the generated code.
 
static void expandIToFP (Instruction *IToFP)
 Generate code to convert a fp number to integer, replacing S(U)IToFP with the generated code.
 
static void scalarize (Instruction *I, SmallVectorImpl< Instruction * > &Replace)
 
static bool runImpl (Function &F, const TargetLowering &TLI)
 
 INITIALIZE_PASS_BEGIN (ExpandLargeFpConvertLegacyPass, "expand-large-fp-convert", "Expand large fp convert", false, false) INITIALIZE_PASS_END(ExpandLargeFpConvertLegacyPass
 

Variables

static cl::opt< unsignedExpandFpConvertBits ("expand-fp-convert-bits", cl::Hidden, cl::init(llvm::IntegerType::MAX_INT_BITS), cl::desc("fp convert instructions on integers with " "more than <N> bits are expanded."))
 
expand large fp convert
 
expand large fp Expand large fp false
 

Function Documentation

◆ expandFPToI()

static void expandFPToI ( Instruction FPToI)
static

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

This currently generates code similarly to compiler-rt's implementations.

An example IR generated from compiler-rt/fixsfdi.c looks like below: define dso_local i64 @foo(float noundef a) local_unnamed_addr #0 { entry: %0 = bitcast float a to i32 conv.i = zext i32 %0 to i64 tobool.not = icmp sgt i32 %0, -1 conv = select i1 tobool.not, i64 1, i64 -1 and = lshr i64 conv.i, 23 shr = and i64 and, 255 and2 = and i64 conv.i, 8388607 or = or i64 and2, 8388608 cmp = icmp ult i64 shr, 127 br i1 cmp, label cleanup, label if.end

if.end: ; preds = entry sub = add nuw nsw i64 shr, 4294967169 conv5 = and i64 sub, 4294967232 cmp6.not = icmp eq i64 conv5, 0 br i1 cmp6.not, label if.end12, label if.then8

if.then8: ; preds = if.end cond11 = select i1 tobool.not, i64 9223372036854775807, i64 -9223372036854775808 br label cleanup

if.end12: ; preds = if.end cmp13 = icmp ult i64 shr, 150 br i1 cmp13, label if.then15, label if.else

if.then15: ; preds = if.end12 sub16 = sub nuw nsw i64 150, shr shr17 = lshr i64 or, sub16 mul = mul nsw i64 shr17, conv br label cleanup

if.else: ; preds = if.end12 sub18 = add nsw i64 shr, -150 shl = shl i64 or, sub18 mul19 = mul nsw i64 shl, conv br label cleanup

cleanup: ; preds = entry, if.else, if.then15, if.then8 retval.0 = phi i64 [ cond11, if.then8 ], [ mul, if.then15 ], [ mul19, if.else ], [ 0, entry ] ret i64 retval.0 }

Replace fp to integer with generated code.

Definition at line 91 of file ExpandLargeFpConvert.cpp.

References llvm::PHINode::addIncoming(), llvm::And, llvm::BitWidth, llvm::BasicBlock::Create(), llvm::IRBuilderBase::CreateAdd(), llvm::IRBuilderBase::CreateAnd(), llvm::IRBuilderBase::CreateBitCast(), llvm::IRBuilderBase::CreateBr(), llvm::IRBuilderBase::CreateCondBr(), llvm::IRBuilderBase::CreateFPExt(), llvm::IRBuilderBase::CreateFPToSI(), llvm::IRBuilderBase::CreateFPToUI(), llvm::IRBuilderBase::CreateICmpSGT(), llvm::IRBuilderBase::CreateICmpULT(), llvm::IRBuilderBase::CreateLShr(), llvm::IRBuilderBase::CreateMul(), llvm::IRBuilderBase::CreateOr(), llvm::IRBuilderBase::CreatePHI(), llvm::IRBuilderBase::CreateSelect(), llvm::IRBuilderBase::CreateSExt(), llvm::IRBuilderBase::CreateShl(), llvm::IRBuilderBase::CreateSub(), llvm::IRBuilderBase::CreateXor(), llvm::IRBuilderBase::CreateZExt(), llvm::User::dropAllReferences(), End, llvm::Instruction::eraseFromParent(), F, llvm::IRBuilderBase::getContext(), llvm::Type::getFP128Ty(), llvm::IRBuilderBase::GetInsertBlock(), llvm::IRBuilderBase::GetInsertPoint(), llvm::IRBuilderBase::getInt32Ty(), llvm::Type::getIntegerBitWidth(), llvm::IRBuilderBase::getIntN(), llvm::IRBuilderBase::getIntNTy(), llvm::Instruction::getOpcode(), llvm::User::getOperand(), llvm::ConstantInt::getSigned(), llvm::Value::getType(), Mul, llvm::Or, llvm::PowerOf2Ceil(), llvm::Value::replaceAllUsesWith(), and llvm::IRBuilderBase::SetInsertPoint().

Referenced by runImpl().

◆ expandIToFP()

static void expandIToFP ( Instruction IToFP)
static

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 310 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::Intrinsic::getDeclaration(), 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::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().

◆ INITIALIZE_PASS_BEGIN()

INITIALIZE_PASS_BEGIN ( ExpandLargeFpConvertLegacyPass  ,
"expand-large-fp-convert"  ,
"Expand large fp convert"  ,
false  ,
false   
)

◆ runImpl()

static bool runImpl ( Function F,
const TargetLowering TLI 
)
static

◆ scalarize()

static void scalarize ( Instruction I,
SmallVectorImpl< Instruction * > &  Replace 
)
static

Variable Documentation

◆ convert

expand large fp Expand large fp convert

◆ ExpandFpConvertBits

cl::opt< unsigned > ExpandFpConvertBits("expand-fp-convert-bits", cl::Hidden, cl::init(llvm::IntegerType::MAX_INT_BITS), cl::desc("fp convert instructions on integers with " "more than <N> bits are expanded.")) ( "expand-fp-convert-bits"  ,
cl::Hidden  ,
cl::init(llvm::IntegerType::MAX_INT_BITS ,
cl::desc("fp convert instructions on integers with " "more than <N> bits are expanded.")   
)
static

Referenced by runImpl().

◆ false

expand large fp Expand large fp false

Definition at line 704 of file ExpandLargeFpConvert.cpp.