LLVM 17.0.0git
Functions | Variables
ExpandLargeFpConvert.cpp File Reference
#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"
Include dependency graph for ExpandLargeFpConvert.cpp:

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 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 90 of file ExpandLargeFpConvert.cpp.

References llvm::PHINode::addIncoming(), llvm::And, llvm::BitWidth, Builder, llvm::BasicBlock::Create(), llvm::User::dropAllReferences(), llvm::Instruction::eraseFromParent(), F, llvm::Type::getFP128Ty(), llvm::Type::getIntegerBitWidth(), llvm::Instruction::getOpcode(), llvm::User::getOperand(), llvm::ConstantInt::getSigned(), llvm::Value::getType(), Mul, llvm::Or, llvm::PowerOf2Ceil(), and llvm::Value::replaceAllUsesWith().

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 307 of file ExpandLargeFpConvert.cpp.

References llvm::Add, llvm::PHINode::addIncoming(), llvm::And, assert(), llvm::BitWidth, Builder, llvm::BasicBlock::Create(), llvm::User::dropAllReferences(), llvm::Instruction::eraseFromParent(), F, llvm::Intrinsic::getDeclaration(), llvm::Type::getFloatTy(), llvm::Type::getFP128Ty(), llvm::Type::getFPMantissaWidth(), llvm::Instruction::getOpcode(), llvm::User::getOperand(), llvm::ConstantInt::getSigned(), llvm::Value::getType(), llvm::ConstantFP::getZero(), llvm::Type::isDoubleTy(), llvm::Type::isHalfTy(), llvm::Type::isX86_FP80Ty(), llvm::Or, llvm::PowerOf2Ceil(), llvm::Value::replaceAllUsesWith(), SI, 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

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 660 of file ExpandLargeFpConvert.cpp.