LLVM 20.0.0git
|
#include "llvm/CodeGen/ExpandLargeFpConvert.h"
#include "llvm/ADT/SmallVector.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< 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 large fp | convert |
expand large fp Expand large fp | false |
|
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, 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().
|
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 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().
INITIALIZE_PASS_BEGIN | ( | ExpandLargeFpConvertLegacyPass | , |
"expand-large-fp-convert" | , | ||
"Expand large fp convert" | , | ||
false | , | ||
false | |||
) |
|
static |
Definition at line 592 of file ExpandLargeFpConvert.cpp.
References llvm::SmallVectorBase< Size_T >::empty(), ExpandFpConvertBits, expandFPToI(), expandIToFP(), F, llvm::TargetLoweringBase::getMaxLargeFPConvertBitWidthSupported(), I, instructions, llvm::IntegerType::MAX_INT_BITS, Modified, llvm::SmallVectorImpl< T >::pop_back_val(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), and scalarize().
|
static |
Definition at line 572 of file ExpandLargeFpConvert.cpp.
References llvm::IRBuilderBase::CreateCast(), llvm::IRBuilderBase::CreateExtractElement(), llvm::IRBuilderBase::CreateInsertElement(), llvm::PoisonValue::get(), getOpcode(), I, Idx, and llvm::SmallVectorTemplateBase< T, bool >::push_back().
Referenced by runImpl().
expand large fp Expand large fp convert |
Definition at line 702 of file ExpandLargeFpConvert.cpp.
Referenced by llvm::APFixedPoint::add(), llvm::APFixedPoint::div(), llvm::APFixedPoint::mul(), llvm::MIRPrinter::print(), and llvm::APFixedPoint::sub().
|
static |
Referenced by runImpl().
expand large fp Expand large fp false |
Definition at line 703 of file ExpandLargeFpConvert.cpp.