189f36dd8SFreddy Ye //===--- ExpandLargeFpConvert.cpp - Expand large fp convert----------------===// 289f36dd8SFreddy Ye // 389f36dd8SFreddy Ye // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 489f36dd8SFreddy Ye // See https://llvm.org/LICENSE.txt for license information. 589f36dd8SFreddy Ye // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 689f36dd8SFreddy Ye // 789f36dd8SFreddy Ye //===----------------------------------------------------------------------===// 889f36dd8SFreddy Ye // 989f36dd8SFreddy Ye 1089f36dd8SFreddy Ye // This pass expands ‘fptoui .. to’, ‘fptosi .. to’, ‘uitofp .. to’, 1189f36dd8SFreddy Ye // ‘sitofp .. to’ instructions with a bitwidth above a threshold into 1289f36dd8SFreddy Ye // auto-generated functions. This is useful for targets like x86_64 that cannot 1389f36dd8SFreddy Ye // lower fp convertions with more than 128 bits. 1489f36dd8SFreddy Ye // 1589f36dd8SFreddy Ye //===----------------------------------------------------------------------===// 1689f36dd8SFreddy Ye 173cef582aSMatt Arsenault #include "llvm/CodeGen/ExpandLargeFpConvert.h" 1889f36dd8SFreddy Ye #include "llvm/ADT/SmallVector.h" 1989f36dd8SFreddy Ye #include "llvm/Analysis/GlobalsModRef.h" 2089f36dd8SFreddy Ye #include "llvm/CodeGen/Passes.h" 2189f36dd8SFreddy Ye #include "llvm/CodeGen/TargetLowering.h" 2289f36dd8SFreddy Ye #include "llvm/CodeGen/TargetPassConfig.h" 2389f36dd8SFreddy Ye #include "llvm/CodeGen/TargetSubtargetInfo.h" 2489f36dd8SFreddy Ye #include "llvm/IR/IRBuilder.h" 2589f36dd8SFreddy Ye #include "llvm/IR/InstIterator.h" 2689f36dd8SFreddy Ye #include "llvm/IR/PassManager.h" 2789f36dd8SFreddy Ye #include "llvm/InitializePasses.h" 2889f36dd8SFreddy Ye #include "llvm/Pass.h" 2989f36dd8SFreddy Ye #include "llvm/Support/CommandLine.h" 3089f36dd8SFreddy Ye #include "llvm/Target/TargetMachine.h" 3189f36dd8SFreddy Ye 3289f36dd8SFreddy Ye using namespace llvm; 3389f36dd8SFreddy Ye 3489f36dd8SFreddy Ye static cl::opt<unsigned> 3589f36dd8SFreddy Ye ExpandFpConvertBits("expand-fp-convert-bits", cl::Hidden, 3689f36dd8SFreddy Ye cl::init(llvm::IntegerType::MAX_INT_BITS), 3789f36dd8SFreddy Ye cl::desc("fp convert instructions on integers with " 3889f36dd8SFreddy Ye "more than <N> bits are expanded.")); 3989f36dd8SFreddy Ye 4089f36dd8SFreddy Ye /// Generate code to convert a fp number to integer, replacing FPToS(U)I with 4189f36dd8SFreddy Ye /// the generated code. This currently generates code similarly to compiler-rt's 4289f36dd8SFreddy Ye /// implementations. 4389f36dd8SFreddy Ye /// 4489f36dd8SFreddy Ye /// An example IR generated from compiler-rt/fixsfdi.c looks like below: 4589f36dd8SFreddy Ye /// define dso_local i64 @foo(float noundef %a) local_unnamed_addr #0 { 4689f36dd8SFreddy Ye /// entry: 4789f36dd8SFreddy Ye /// %0 = bitcast float %a to i32 4889f36dd8SFreddy Ye /// %conv.i = zext i32 %0 to i64 4989f36dd8SFreddy Ye /// %tobool.not = icmp sgt i32 %0, -1 5089f36dd8SFreddy Ye /// %conv = select i1 %tobool.not, i64 1, i64 -1 5189f36dd8SFreddy Ye /// %and = lshr i64 %conv.i, 23 5289f36dd8SFreddy Ye /// %shr = and i64 %and, 255 5389f36dd8SFreddy Ye /// %and2 = and i64 %conv.i, 8388607 5489f36dd8SFreddy Ye /// %or = or i64 %and2, 8388608 5589f36dd8SFreddy Ye /// %cmp = icmp ult i64 %shr, 127 5689f36dd8SFreddy Ye /// br i1 %cmp, label %cleanup, label %if.end 5789f36dd8SFreddy Ye /// 5889f36dd8SFreddy Ye /// if.end: ; preds = %entry 5989f36dd8SFreddy Ye /// %sub = add nuw nsw i64 %shr, 4294967169 6089f36dd8SFreddy Ye /// %conv5 = and i64 %sub, 4294967232 6189f36dd8SFreddy Ye /// %cmp6.not = icmp eq i64 %conv5, 0 6289f36dd8SFreddy Ye /// br i1 %cmp6.not, label %if.end12, label %if.then8 6389f36dd8SFreddy Ye /// 6489f36dd8SFreddy Ye /// if.then8: ; preds = %if.end 6589f36dd8SFreddy Ye /// %cond11 = select i1 %tobool.not, i64 9223372036854775807, i64 -9223372036854775808 6689f36dd8SFreddy Ye /// br label %cleanup 6789f36dd8SFreddy Ye /// 6889f36dd8SFreddy Ye /// if.end12: ; preds = %if.end 6989f36dd8SFreddy Ye /// %cmp13 = icmp ult i64 %shr, 150 7089f36dd8SFreddy Ye /// br i1 %cmp13, label %if.then15, label %if.else 7189f36dd8SFreddy Ye /// 7289f36dd8SFreddy Ye /// if.then15: ; preds = %if.end12 7389f36dd8SFreddy Ye /// %sub16 = sub nuw nsw i64 150, %shr 7489f36dd8SFreddy Ye /// %shr17 = lshr i64 %or, %sub16 7589f36dd8SFreddy Ye /// %mul = mul nsw i64 %shr17, %conv 7689f36dd8SFreddy Ye /// br label %cleanup 7789f36dd8SFreddy Ye /// 7889f36dd8SFreddy Ye /// if.else: ; preds = %if.end12 7989f36dd8SFreddy Ye /// %sub18 = add nsw i64 %shr, -150 8089f36dd8SFreddy Ye /// %shl = shl i64 %or, %sub18 8189f36dd8SFreddy Ye /// %mul19 = mul nsw i64 %shl, %conv 8289f36dd8SFreddy Ye /// br label %cleanup 8389f36dd8SFreddy Ye /// 8489f36dd8SFreddy Ye /// cleanup: ; preds = %entry, %if.else, %if.then15, %if.then8 8589f36dd8SFreddy Ye /// %retval.0 = phi i64 [ %cond11, %if.then8 ], [ %mul, %if.then15 ], [ %mul19, %if.else ], [ 0, %entry ] 8689f36dd8SFreddy Ye /// ret i64 %retval.0 8789f36dd8SFreddy Ye /// } 8889f36dd8SFreddy Ye /// 8989f36dd8SFreddy Ye /// Replace fp to integer with generated code. 9089f36dd8SFreddy Ye static void expandFPToI(Instruction *FPToI) { 9189f36dd8SFreddy Ye IRBuilder<> Builder(FPToI); 9289f36dd8SFreddy Ye auto *FloatVal = FPToI->getOperand(0); 9389f36dd8SFreddy Ye IntegerType *IntTy = cast<IntegerType>(FPToI->getType()); 9489f36dd8SFreddy Ye 9589f36dd8SFreddy Ye unsigned BitWidth = FPToI->getType()->getIntegerBitWidth(); 9689f36dd8SFreddy Ye unsigned FPMantissaWidth = FloatVal->getType()->getFPMantissaWidth() - 1; 9789f36dd8SFreddy Ye 9889f36dd8SFreddy Ye // FIXME: fp16's range is covered by i32. So `fptoi half` can convert 9989f36dd8SFreddy Ye // to i32 first following a sext/zext to target integer type. 10089f36dd8SFreddy Ye Value *A1 = nullptr; 10189f36dd8SFreddy Ye if (FloatVal->getType()->isHalfTy()) { 10289f36dd8SFreddy Ye if (FPToI->getOpcode() == Instruction::FPToUI) { 10389f36dd8SFreddy Ye Value *A0 = Builder.CreateFPToUI(FloatVal, Builder.getIntNTy(32)); 10489f36dd8SFreddy Ye A1 = Builder.CreateZExt(A0, IntTy); 10589f36dd8SFreddy Ye } else { // FPToSI 10689f36dd8SFreddy Ye Value *A0 = Builder.CreateFPToSI(FloatVal, Builder.getIntNTy(32)); 10789f36dd8SFreddy Ye A1 = Builder.CreateSExt(A0, IntTy); 10889f36dd8SFreddy Ye } 10989f36dd8SFreddy Ye FPToI->replaceAllUsesWith(A1); 11089f36dd8SFreddy Ye FPToI->dropAllReferences(); 11189f36dd8SFreddy Ye FPToI->eraseFromParent(); 11289f36dd8SFreddy Ye return; 11389f36dd8SFreddy Ye } 11489f36dd8SFreddy Ye 11589f36dd8SFreddy Ye // fp80 conversion is implemented by fpext to fp128 first then do the 11689f36dd8SFreddy Ye // conversion. 11789f36dd8SFreddy Ye FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth; 118110c22feSBevin Hansson unsigned FloatWidth = 119110c22feSBevin Hansson PowerOf2Ceil(FloatVal->getType()->getScalarSizeInBits()); 12089f36dd8SFreddy Ye unsigned ExponentWidth = FloatWidth - FPMantissaWidth - 1; 12189f36dd8SFreddy Ye unsigned ExponentBias = (1 << (ExponentWidth - 1)) - 1; 12289f36dd8SFreddy Ye Value *ImplicitBit = Builder.CreateShl( 12389f36dd8SFreddy Ye Builder.getIntN(BitWidth, 1), Builder.getIntN(BitWidth, FPMantissaWidth)); 12489f36dd8SFreddy Ye Value *SignificandMask = 12589f36dd8SFreddy Ye Builder.CreateSub(ImplicitBit, Builder.getIntN(BitWidth, 1)); 12689f36dd8SFreddy Ye Value *NegOne = Builder.CreateSExt( 12789f36dd8SFreddy Ye ConstantInt::getSigned(Builder.getInt32Ty(), -1), IntTy); 12889f36dd8SFreddy Ye Value *NegInf = 12989f36dd8SFreddy Ye Builder.CreateShl(ConstantInt::getSigned(IntTy, 1), 13089f36dd8SFreddy Ye ConstantInt::getSigned(IntTy, BitWidth - 1)); 13189f36dd8SFreddy Ye 13289f36dd8SFreddy Ye BasicBlock *Entry = Builder.GetInsertBlock(); 13389f36dd8SFreddy Ye Function *F = Entry->getParent(); 13489f36dd8SFreddy Ye Entry->setName(Twine(Entry->getName(), "fp-to-i-entry")); 13589f36dd8SFreddy Ye BasicBlock *End = 13689f36dd8SFreddy Ye Entry->splitBasicBlock(Builder.GetInsertPoint(), "fp-to-i-cleanup"); 13789f36dd8SFreddy Ye BasicBlock *IfEnd = 13889f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "fp-to-i-if-end", F, End); 13989f36dd8SFreddy Ye BasicBlock *IfThen5 = 14089f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "fp-to-i-if-then5", F, End); 14189f36dd8SFreddy Ye BasicBlock *IfEnd9 = 14289f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "fp-to-i-if-end9", F, End); 14389f36dd8SFreddy Ye BasicBlock *IfThen12 = 14489f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "fp-to-i-if-then12", F, End); 14589f36dd8SFreddy Ye BasicBlock *IfElse = 14689f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "fp-to-i-if-else", F, End); 14789f36dd8SFreddy Ye 14889f36dd8SFreddy Ye Entry->getTerminator()->eraseFromParent(); 14989f36dd8SFreddy Ye 15089f36dd8SFreddy Ye // entry: 15189f36dd8SFreddy Ye Builder.SetInsertPoint(Entry); 15289f36dd8SFreddy Ye Value *FloatVal0 = FloatVal; 15389f36dd8SFreddy Ye // fp80 conversion is implemented by fpext to fp128 first then do the 15489f36dd8SFreddy Ye // conversion. 15589f36dd8SFreddy Ye if (FloatVal->getType()->isX86_FP80Ty()) 15689f36dd8SFreddy Ye FloatVal0 = 15789f36dd8SFreddy Ye Builder.CreateFPExt(FloatVal, Type::getFP128Ty(Builder.getContext())); 15889f36dd8SFreddy Ye Value *ARep0 = 15989f36dd8SFreddy Ye Builder.CreateBitCast(FloatVal0, Builder.getIntNTy(FloatWidth)); 16089f36dd8SFreddy Ye Value *ARep = Builder.CreateZExt(ARep0, FPToI->getType()); 16189f36dd8SFreddy Ye Value *PosOrNeg = Builder.CreateICmpSGT( 16289f36dd8SFreddy Ye ARep0, ConstantInt::getSigned(Builder.getIntNTy(FloatWidth), -1)); 16389f36dd8SFreddy Ye Value *Sign = Builder.CreateSelect(PosOrNeg, ConstantInt::getSigned(IntTy, 1), 16489f36dd8SFreddy Ye ConstantInt::getSigned(IntTy, -1)); 16589f36dd8SFreddy Ye Value *And = 16689f36dd8SFreddy Ye Builder.CreateLShr(ARep, Builder.getIntN(BitWidth, FPMantissaWidth)); 16789f36dd8SFreddy Ye Value *And2 = Builder.CreateAnd( 16889f36dd8SFreddy Ye And, Builder.getIntN(BitWidth, (1 << ExponentWidth) - 1)); 16989f36dd8SFreddy Ye Value *Abs = Builder.CreateAnd(ARep, SignificandMask); 17089f36dd8SFreddy Ye Value *Or = Builder.CreateOr(Abs, ImplicitBit); 17189f36dd8SFreddy Ye Value *Cmp = 17289f36dd8SFreddy Ye Builder.CreateICmpULT(And2, Builder.getIntN(BitWidth, ExponentBias)); 17389f36dd8SFreddy Ye Builder.CreateCondBr(Cmp, End, IfEnd); 17489f36dd8SFreddy Ye 17589f36dd8SFreddy Ye // if.end: 17689f36dd8SFreddy Ye Builder.SetInsertPoint(IfEnd); 17789f36dd8SFreddy Ye Value *Add1 = Builder.CreateAdd( 17814c30189SBevin Hansson And2, ConstantInt::getSigned( 17914c30189SBevin Hansson IntTy, -static_cast<int64_t>(ExponentBias + BitWidth))); 18014c30189SBevin Hansson Value *Cmp3 = Builder.CreateICmpULT( 18114c30189SBevin Hansson Add1, ConstantInt::getSigned(IntTy, -static_cast<int64_t>(BitWidth))); 18289f36dd8SFreddy Ye Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9); 18389f36dd8SFreddy Ye 18489f36dd8SFreddy Ye // if.then5: 18589f36dd8SFreddy Ye Builder.SetInsertPoint(IfThen5); 18689f36dd8SFreddy Ye Value *PosInf = Builder.CreateXor(NegOne, NegInf); 18789f36dd8SFreddy Ye Value *Cond8 = Builder.CreateSelect(PosOrNeg, PosInf, NegInf); 18889f36dd8SFreddy Ye Builder.CreateBr(End); 18989f36dd8SFreddy Ye 19089f36dd8SFreddy Ye // if.end9: 19189f36dd8SFreddy Ye Builder.SetInsertPoint(IfEnd9); 19289f36dd8SFreddy Ye Value *Cmp10 = Builder.CreateICmpULT( 19389f36dd8SFreddy Ye And2, Builder.getIntN(BitWidth, ExponentBias + FPMantissaWidth)); 19489f36dd8SFreddy Ye Builder.CreateCondBr(Cmp10, IfThen12, IfElse); 19589f36dd8SFreddy Ye 19689f36dd8SFreddy Ye // if.then12: 19789f36dd8SFreddy Ye Builder.SetInsertPoint(IfThen12); 19889f36dd8SFreddy Ye Value *Sub13 = Builder.CreateSub( 19989f36dd8SFreddy Ye Builder.getIntN(BitWidth, ExponentBias + FPMantissaWidth), And2); 20089f36dd8SFreddy Ye Value *Shr14 = Builder.CreateLShr(Or, Sub13); 20189f36dd8SFreddy Ye Value *Mul = Builder.CreateMul(Shr14, Sign); 20289f36dd8SFreddy Ye Builder.CreateBr(End); 20389f36dd8SFreddy Ye 20489f36dd8SFreddy Ye // if.else: 20589f36dd8SFreddy Ye Builder.SetInsertPoint(IfElse); 20689f36dd8SFreddy Ye Value *Sub15 = Builder.CreateAdd( 20714c30189SBevin Hansson And2, ConstantInt::getSigned( 20814c30189SBevin Hansson IntTy, -static_cast<int64_t>(ExponentBias + FPMantissaWidth))); 20989f36dd8SFreddy Ye Value *Shl = Builder.CreateShl(Or, Sub15); 21089f36dd8SFreddy Ye Value *Mul16 = Builder.CreateMul(Shl, Sign); 21189f36dd8SFreddy Ye Builder.CreateBr(End); 21289f36dd8SFreddy Ye 21389f36dd8SFreddy Ye // cleanup: 214d75f9dd1SStephen Tozer Builder.SetInsertPoint(End, End->begin()); 21589f36dd8SFreddy Ye PHINode *Retval0 = Builder.CreatePHI(FPToI->getType(), 4); 21689f36dd8SFreddy Ye 21789f36dd8SFreddy Ye Retval0->addIncoming(Cond8, IfThen5); 21889f36dd8SFreddy Ye Retval0->addIncoming(Mul, IfThen12); 21989f36dd8SFreddy Ye Retval0->addIncoming(Mul16, IfElse); 22089f36dd8SFreddy Ye Retval0->addIncoming(Builder.getIntN(BitWidth, 0), Entry); 22189f36dd8SFreddy Ye 22289f36dd8SFreddy Ye FPToI->replaceAllUsesWith(Retval0); 22389f36dd8SFreddy Ye FPToI->dropAllReferences(); 22489f36dd8SFreddy Ye FPToI->eraseFromParent(); 22589f36dd8SFreddy Ye } 22689f36dd8SFreddy Ye 22789f36dd8SFreddy Ye /// Generate code to convert a fp number to integer, replacing S(U)IToFP with 22889f36dd8SFreddy Ye /// the generated code. This currently generates code similarly to compiler-rt's 22989f36dd8SFreddy Ye /// implementations. This implementation has an implicit assumption that integer 23089f36dd8SFreddy Ye /// width is larger than fp. 23189f36dd8SFreddy Ye /// 23289f36dd8SFreddy Ye /// An example IR generated from compiler-rt/floatdisf.c looks like below: 23389f36dd8SFreddy Ye /// define dso_local float @__floatdisf(i64 noundef %a) local_unnamed_addr #0 { 23489f36dd8SFreddy Ye /// entry: 23589f36dd8SFreddy Ye /// %cmp = icmp eq i64 %a, 0 23689f36dd8SFreddy Ye /// br i1 %cmp, label %return, label %if.end 23789f36dd8SFreddy Ye /// 23889f36dd8SFreddy Ye /// if.end: ; preds = %entry 23989f36dd8SFreddy Ye /// %shr = ashr i64 %a, 63 24089f36dd8SFreddy Ye /// %xor = xor i64 %shr, %a 24189f36dd8SFreddy Ye /// %sub = sub nsw i64 %xor, %shr 24289f36dd8SFreddy Ye /// %0 = tail call i64 @llvm.ctlz.i64(i64 %sub, i1 true), !range !5 24389f36dd8SFreddy Ye /// %cast = trunc i64 %0 to i32 24489f36dd8SFreddy Ye /// %sub1 = sub nuw nsw i32 64, %cast 24589f36dd8SFreddy Ye /// %sub2 = xor i32 %cast, 63 24689f36dd8SFreddy Ye /// %cmp3 = icmp ult i32 %cast, 40 24789f36dd8SFreddy Ye /// br i1 %cmp3, label %if.then4, label %if.else 24889f36dd8SFreddy Ye /// 24989f36dd8SFreddy Ye /// if.then4: ; preds = %if.end 25089f36dd8SFreddy Ye /// switch i32 %sub1, label %sw.default [ 25189f36dd8SFreddy Ye /// i32 25, label %sw.bb 25289f36dd8SFreddy Ye /// i32 26, label %sw.epilog 25389f36dd8SFreddy Ye /// ] 25489f36dd8SFreddy Ye /// 25589f36dd8SFreddy Ye /// sw.bb: ; preds = %if.then4 25689f36dd8SFreddy Ye /// %shl = shl i64 %sub, 1 25789f36dd8SFreddy Ye /// br label %sw.epilog 25889f36dd8SFreddy Ye /// 25989f36dd8SFreddy Ye /// sw.default: ; preds = %if.then4 26089f36dd8SFreddy Ye /// %sub5 = sub nsw i64 38, %0 26189f36dd8SFreddy Ye /// %sh_prom = and i64 %sub5, 4294967295 26289f36dd8SFreddy Ye /// %shr6 = lshr i64 %sub, %sh_prom 26389f36dd8SFreddy Ye /// %shr9 = lshr i64 274877906943, %0 26489f36dd8SFreddy Ye /// %and = and i64 %shr9, %sub 26589f36dd8SFreddy Ye /// %cmp10 = icmp ne i64 %and, 0 26689f36dd8SFreddy Ye /// %conv11 = zext i1 %cmp10 to i64 26789f36dd8SFreddy Ye /// %or = or i64 %shr6, %conv11 26889f36dd8SFreddy Ye /// br label %sw.epilog 26989f36dd8SFreddy Ye /// 27089f36dd8SFreddy Ye /// sw.epilog: ; preds = %sw.default, %if.then4, %sw.bb 27189f36dd8SFreddy Ye /// %a.addr.0 = phi i64 [ %or, %sw.default ], [ %sub, %if.then4 ], [ %shl, %sw.bb ] 27289f36dd8SFreddy Ye /// %1 = lshr i64 %a.addr.0, 2 27389f36dd8SFreddy Ye /// %2 = and i64 %1, 1 27489f36dd8SFreddy Ye /// %or16 = or i64 %2, %a.addr.0 27589f36dd8SFreddy Ye /// %inc = add nsw i64 %or16, 1 27689f36dd8SFreddy Ye /// %3 = and i64 %inc, 67108864 27789f36dd8SFreddy Ye /// %tobool.not = icmp eq i64 %3, 0 27889f36dd8SFreddy Ye /// %spec.select.v = select i1 %tobool.not, i64 2, i64 3 27989f36dd8SFreddy Ye /// %spec.select = ashr i64 %inc, %spec.select.v 28089f36dd8SFreddy Ye /// %spec.select56 = select i1 %tobool.not, i32 %sub2, i32 %sub1 28189f36dd8SFreddy Ye /// br label %if.end26 28289f36dd8SFreddy Ye /// 28389f36dd8SFreddy Ye /// if.else: ; preds = %if.end 28489f36dd8SFreddy Ye /// %sub23 = add nuw nsw i64 %0, 4294967256 28589f36dd8SFreddy Ye /// %sh_prom24 = and i64 %sub23, 4294967295 28689f36dd8SFreddy Ye /// %shl25 = shl i64 %sub, %sh_prom24 28789f36dd8SFreddy Ye /// br label %if.end26 28889f36dd8SFreddy Ye /// 28989f36dd8SFreddy Ye /// if.end26: ; preds = %sw.epilog, %if.else 29089f36dd8SFreddy Ye /// %a.addr.1 = phi i64 [ %shl25, %if.else ], [ %spec.select, %sw.epilog ] 29189f36dd8SFreddy Ye /// %e.0 = phi i32 [ %sub2, %if.else ], [ %spec.select56, %sw.epilog ] 29289f36dd8SFreddy Ye /// %conv27 = trunc i64 %shr to i32 29389f36dd8SFreddy Ye /// %and28 = and i32 %conv27, -2147483648 29489f36dd8SFreddy Ye /// %add = shl nuw nsw i32 %e.0, 23 29589f36dd8SFreddy Ye /// %shl29 = add nuw nsw i32 %add, 1065353216 29689f36dd8SFreddy Ye /// %conv31 = trunc i64 %a.addr.1 to i32 29789f36dd8SFreddy Ye /// %and32 = and i32 %conv31, 8388607 29889f36dd8SFreddy Ye /// %or30 = or i32 %and32, %and28 29989f36dd8SFreddy Ye /// %or33 = or i32 %or30, %shl29 30089f36dd8SFreddy Ye /// %4 = bitcast i32 %or33 to float 30189f36dd8SFreddy Ye /// br label %return 30289f36dd8SFreddy Ye /// 30389f36dd8SFreddy Ye /// return: ; preds = %entry, %if.end26 30489f36dd8SFreddy Ye /// %retval.0 = phi float [ %4, %if.end26 ], [ 0.000000e+00, %entry ] 30589f36dd8SFreddy Ye /// ret float %retval.0 30689f36dd8SFreddy Ye /// } 30789f36dd8SFreddy Ye /// 30889f36dd8SFreddy Ye /// Replace integer to fp with generated code. 30989f36dd8SFreddy Ye static void expandIToFP(Instruction *IToFP) { 31089f36dd8SFreddy Ye IRBuilder<> Builder(IToFP); 31189f36dd8SFreddy Ye auto *IntVal = IToFP->getOperand(0); 31289f36dd8SFreddy Ye IntegerType *IntTy = cast<IntegerType>(IntVal->getType()); 31389f36dd8SFreddy Ye 31489f36dd8SFreddy Ye unsigned BitWidth = IntVal->getType()->getIntegerBitWidth(); 31589f36dd8SFreddy Ye unsigned FPMantissaWidth = IToFP->getType()->getFPMantissaWidth() - 1; 31689f36dd8SFreddy Ye // fp80 conversion is implemented by conversion tp fp128 first following 31789f36dd8SFreddy Ye // a fptrunc to fp80. 31889f36dd8SFreddy Ye FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth; 31989f36dd8SFreddy Ye // FIXME: As there is no related builtins added in compliler-rt, 32089f36dd8SFreddy Ye // here currently utilized the fp32 <-> fp16 lib calls to implement. 32189f36dd8SFreddy Ye FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth; 322110c22feSBevin Hansson FPMantissaWidth = FPMantissaWidth == 7 ? 23 : FPMantissaWidth; 32389f36dd8SFreddy Ye unsigned FloatWidth = PowerOf2Ceil(FPMantissaWidth); 32489f36dd8SFreddy Ye bool IsSigned = IToFP->getOpcode() == Instruction::SIToFP; 32589f36dd8SFreddy Ye 32689f36dd8SFreddy Ye assert(BitWidth > FloatWidth && "Unexpected conversion. expandIToFP() " 32789f36dd8SFreddy Ye "assumes integer width is larger than fp."); 32889f36dd8SFreddy Ye 32989f36dd8SFreddy Ye Value *Temp1 = 33089f36dd8SFreddy Ye Builder.CreateShl(Builder.getIntN(BitWidth, 1), 33189f36dd8SFreddy Ye Builder.getIntN(BitWidth, FPMantissaWidth + 3)); 33289f36dd8SFreddy Ye 33389f36dd8SFreddy Ye BasicBlock *Entry = Builder.GetInsertBlock(); 33489f36dd8SFreddy Ye Function *F = Entry->getParent(); 33589f36dd8SFreddy Ye Entry->setName(Twine(Entry->getName(), "itofp-entry")); 33689f36dd8SFreddy Ye BasicBlock *End = 33789f36dd8SFreddy Ye Entry->splitBasicBlock(Builder.GetInsertPoint(), "itofp-return"); 33889f36dd8SFreddy Ye BasicBlock *IfEnd = 33989f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-if-end", F, End); 34089f36dd8SFreddy Ye BasicBlock *IfThen4 = 34189f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-if-then4", F, End); 34289f36dd8SFreddy Ye BasicBlock *SwBB = 34389f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-sw-bb", F, End); 34489f36dd8SFreddy Ye BasicBlock *SwDefault = 34589f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-sw-default", F, End); 34689f36dd8SFreddy Ye BasicBlock *SwEpilog = 34789f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-sw-epilog", F, End); 34889f36dd8SFreddy Ye BasicBlock *IfThen20 = 34989f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-if-then20", F, End); 35089f36dd8SFreddy Ye BasicBlock *IfElse = 35189f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-if-else", F, End); 35289f36dd8SFreddy Ye BasicBlock *IfEnd26 = 35389f36dd8SFreddy Ye BasicBlock::Create(Builder.getContext(), "itofp-if-end26", F, End); 35489f36dd8SFreddy Ye 35589f36dd8SFreddy Ye Entry->getTerminator()->eraseFromParent(); 35689f36dd8SFreddy Ye 35789f36dd8SFreddy Ye Function *CTLZ = 358*fa789dffSRahul Joshi Intrinsic::getOrInsertDeclaration(F->getParent(), Intrinsic::ctlz, IntTy); 35989f36dd8SFreddy Ye ConstantInt *True = Builder.getTrue(); 36089f36dd8SFreddy Ye 36189f36dd8SFreddy Ye // entry: 36289f36dd8SFreddy Ye Builder.SetInsertPoint(Entry); 36389f36dd8SFreddy Ye Value *Cmp = Builder.CreateICmpEQ(IntVal, ConstantInt::getSigned(IntTy, 0)); 36489f36dd8SFreddy Ye Builder.CreateCondBr(Cmp, End, IfEnd); 36589f36dd8SFreddy Ye 36689f36dd8SFreddy Ye // if.end: 36789f36dd8SFreddy Ye Builder.SetInsertPoint(IfEnd); 36889f36dd8SFreddy Ye Value *Shr = 36989f36dd8SFreddy Ye Builder.CreateAShr(IntVal, Builder.getIntN(BitWidth, BitWidth - 1)); 37089f36dd8SFreddy Ye Value *Xor = Builder.CreateXor(Shr, IntVal); 37189f36dd8SFreddy Ye Value *Sub = Builder.CreateSub(Xor, Shr); 37289f36dd8SFreddy Ye Value *Call = Builder.CreateCall(CTLZ, {IsSigned ? Sub : IntVal, True}); 37389f36dd8SFreddy Ye Value *Cast = Builder.CreateTrunc(Call, Builder.getInt32Ty()); 37489f36dd8SFreddy Ye int BitWidthNew = FloatWidth == 128 ? BitWidth : 32; 37589f36dd8SFreddy Ye Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew, BitWidth), 37689f36dd8SFreddy Ye FloatWidth == 128 ? Call : Cast); 37789f36dd8SFreddy Ye Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew, BitWidth - 1), 37889f36dd8SFreddy Ye FloatWidth == 128 ? Call : Cast); 37989f36dd8SFreddy Ye Value *Cmp3 = Builder.CreateICmpSGT( 380f623adbbSBevin Hansson Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1)); 38189f36dd8SFreddy Ye Builder.CreateCondBr(Cmp3, IfThen4, IfElse); 38289f36dd8SFreddy Ye 38389f36dd8SFreddy Ye // if.then4: 38489f36dd8SFreddy Ye Builder.SetInsertPoint(IfThen4); 38589f36dd8SFreddy Ye llvm::SwitchInst *SI = Builder.CreateSwitch(Sub1, SwDefault); 38689f36dd8SFreddy Ye SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB); 38789f36dd8SFreddy Ye SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog); 38889f36dd8SFreddy Ye 38989f36dd8SFreddy Ye // sw.bb: 39089f36dd8SFreddy Ye Builder.SetInsertPoint(SwBB); 39189f36dd8SFreddy Ye Value *Shl = 39289f36dd8SFreddy Ye Builder.CreateShl(IsSigned ? Sub : IntVal, Builder.getIntN(BitWidth, 1)); 39389f36dd8SFreddy Ye Builder.CreateBr(SwEpilog); 39489f36dd8SFreddy Ye 39589f36dd8SFreddy Ye // sw.default: 39689f36dd8SFreddy Ye Builder.SetInsertPoint(SwDefault); 39789f36dd8SFreddy Ye Value *Sub5 = Builder.CreateSub( 39889f36dd8SFreddy Ye Builder.getIntN(BitWidthNew, BitWidth - FPMantissaWidth - 3), 39989f36dd8SFreddy Ye FloatWidth == 128 ? Call : Cast); 40089f36dd8SFreddy Ye Value *ShProm = Builder.CreateZExt(Sub5, IntTy); 40189f36dd8SFreddy Ye Value *Shr6 = Builder.CreateLShr(IsSigned ? Sub : IntVal, 40289f36dd8SFreddy Ye FloatWidth == 128 ? Sub5 : ShProm); 40389f36dd8SFreddy Ye Value *Sub8 = 40489f36dd8SFreddy Ye Builder.CreateAdd(FloatWidth == 128 ? Call : Cast, 40589f36dd8SFreddy Ye Builder.getIntN(BitWidthNew, FPMantissaWidth + 3)); 40689f36dd8SFreddy Ye Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy); 40789f36dd8SFreddy Ye Value *Shr9 = Builder.CreateLShr(ConstantInt::getSigned(IntTy, -1), 40889f36dd8SFreddy Ye FloatWidth == 128 ? Sub8 : ShProm9); 40989f36dd8SFreddy Ye Value *And = Builder.CreateAnd(Shr9, IsSigned ? Sub : IntVal); 41089f36dd8SFreddy Ye Value *Cmp10 = Builder.CreateICmpNE(And, Builder.getIntN(BitWidth, 0)); 41189f36dd8SFreddy Ye Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy); 41289f36dd8SFreddy Ye Value *Or = Builder.CreateOr(Shr6, Conv11); 41389f36dd8SFreddy Ye Builder.CreateBr(SwEpilog); 41489f36dd8SFreddy Ye 41589f36dd8SFreddy Ye // sw.epilog: 41689f36dd8SFreddy Ye Builder.SetInsertPoint(SwEpilog); 41789f36dd8SFreddy Ye PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3); 41889f36dd8SFreddy Ye AAddr0->addIncoming(Or, SwDefault); 41989f36dd8SFreddy Ye AAddr0->addIncoming(IsSigned ? Sub : IntVal, IfThen4); 42089f36dd8SFreddy Ye AAddr0->addIncoming(Shl, SwBB); 42189f36dd8SFreddy Ye Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty()); 42289f36dd8SFreddy Ye Value *A1 = Builder.CreateLShr(A0, Builder.getIntN(32, 2)); 42389f36dd8SFreddy Ye Value *A2 = Builder.CreateAnd(A1, Builder.getIntN(32, 1)); 42489f36dd8SFreddy Ye Value *Conv16 = Builder.CreateZExt(A2, IntTy); 42589f36dd8SFreddy Ye Value *Or17 = Builder.CreateOr(AAddr0, Conv16); 42689f36dd8SFreddy Ye Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(BitWidth, 1)); 42789f36dd8SFreddy Ye Value *Shr18 = nullptr; 42889f36dd8SFreddy Ye if (IsSigned) 42989f36dd8SFreddy Ye Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(BitWidth, 2)); 43089f36dd8SFreddy Ye else 43189f36dd8SFreddy Ye Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(BitWidth, 2)); 43289f36dd8SFreddy Ye Value *A3 = Builder.CreateAnd(Inc, Temp1, "a3"); 43389f36dd8SFreddy Ye Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(BitWidth, 0)); 43489f36dd8SFreddy Ye Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth)); 43589f36dd8SFreddy Ye Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(BitWidth, 32)); 43689f36dd8SFreddy Ye Value *ExtractT64 = nullptr; 43789f36dd8SFreddy Ye if (FloatWidth > 80) 43889f36dd8SFreddy Ye ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty()); 43989f36dd8SFreddy Ye else 44089f36dd8SFreddy Ye ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty()); 44189f36dd8SFreddy Ye Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20); 44289f36dd8SFreddy Ye 44389f36dd8SFreddy Ye // if.then20 44489f36dd8SFreddy Ye Builder.SetInsertPoint(IfThen20); 44589f36dd8SFreddy Ye Value *Shr21 = nullptr; 44689f36dd8SFreddy Ye if (IsSigned) 44789f36dd8SFreddy Ye Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(BitWidth, 3)); 44889f36dd8SFreddy Ye else 44989f36dd8SFreddy Ye Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(BitWidth, 3)); 45089f36dd8SFreddy Ye Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth)); 45189f36dd8SFreddy Ye Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(BitWidth, 32)); 45289f36dd8SFreddy Ye Value *ExtractT62 = nullptr; 45389f36dd8SFreddy Ye if (FloatWidth > 80) 45489f36dd8SFreddy Ye ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getIntNTy(64)); 45589f36dd8SFreddy Ye else 45689f36dd8SFreddy Ye ExtractT62 = Builder.CreateTrunc(Extract, Builder.getIntNTy(32)); 45789f36dd8SFreddy Ye Builder.CreateBr(IfEnd26); 45889f36dd8SFreddy Ye 45989f36dd8SFreddy Ye // if.else: 46089f36dd8SFreddy Ye Builder.SetInsertPoint(IfElse); 46189f36dd8SFreddy Ye Value *Sub24 = Builder.CreateAdd( 46289f36dd8SFreddy Ye FloatWidth == 128 ? Call : Cast, 46389f36dd8SFreddy Ye ConstantInt::getSigned(Builder.getIntNTy(BitWidthNew), 46489f36dd8SFreddy Ye -(BitWidth - FPMantissaWidth - 1))); 46589f36dd8SFreddy Ye Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy); 46689f36dd8SFreddy Ye Value *Shl26 = Builder.CreateShl(IsSigned ? Sub : IntVal, 46789f36dd8SFreddy Ye FloatWidth == 128 ? Sub24 : ShProm25); 46889f36dd8SFreddy Ye Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth)); 46989f36dd8SFreddy Ye Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(BitWidth, 32)); 47089f36dd8SFreddy Ye Value *ExtractT66 = nullptr; 47189f36dd8SFreddy Ye if (FloatWidth > 80) 47289f36dd8SFreddy Ye ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getIntNTy(64)); 47389f36dd8SFreddy Ye else 47489f36dd8SFreddy Ye ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty()); 47589f36dd8SFreddy Ye Builder.CreateBr(IfEnd26); 47689f36dd8SFreddy Ye 47789f36dd8SFreddy Ye // if.end26: 47889f36dd8SFreddy Ye Builder.SetInsertPoint(IfEnd26); 47989f36dd8SFreddy Ye PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3); 48089f36dd8SFreddy Ye AAddr1Off0->addIncoming(ExtractT, IfThen20); 48189f36dd8SFreddy Ye AAddr1Off0->addIncoming(ExtractT60, SwEpilog); 48289f36dd8SFreddy Ye AAddr1Off0->addIncoming(ExtractT61, IfElse); 48389f36dd8SFreddy Ye PHINode *AAddr1Off32 = nullptr; 48489f36dd8SFreddy Ye if (FloatWidth > 32) { 48589f36dd8SFreddy Ye AAddr1Off32 = 48689f36dd8SFreddy Ye Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3); 48789f36dd8SFreddy Ye AAddr1Off32->addIncoming(ExtractT62, IfThen20); 48889f36dd8SFreddy Ye AAddr1Off32->addIncoming(ExtractT64, SwEpilog); 48989f36dd8SFreddy Ye AAddr1Off32->addIncoming(ExtractT66, IfElse); 49089f36dd8SFreddy Ye } 49189f36dd8SFreddy Ye PHINode *E0 = nullptr; 49289f36dd8SFreddy Ye if (FloatWidth <= 80) { 49389f36dd8SFreddy Ye E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3); 49489f36dd8SFreddy Ye E0->addIncoming(Sub1, IfThen20); 49589f36dd8SFreddy Ye E0->addIncoming(Sub2, SwEpilog); 49689f36dd8SFreddy Ye E0->addIncoming(Sub2, IfElse); 49789f36dd8SFreddy Ye } 49889f36dd8SFreddy Ye Value *And29 = nullptr; 49989f36dd8SFreddy Ye if (FloatWidth > 80) { 50089f36dd8SFreddy Ye Value *Temp2 = Builder.CreateShl(Builder.getIntN(BitWidth, 1), 50189f36dd8SFreddy Ye Builder.getIntN(BitWidth, 63)); 50289f36dd8SFreddy Ye And29 = Builder.CreateAnd(Shr, Temp2, "and29"); 50389f36dd8SFreddy Ye } else { 50489f36dd8SFreddy Ye Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getIntNTy(32)); 50589f36dd8SFreddy Ye And29 = Builder.CreateAnd( 50689f36dd8SFreddy Ye Conv28, ConstantInt::getSigned(Builder.getIntNTy(32), 0x80000000)); 50789f36dd8SFreddy Ye } 50889f36dd8SFreddy Ye unsigned TempMod = FPMantissaWidth % 32; 50989f36dd8SFreddy Ye Value *And34 = nullptr; 51089f36dd8SFreddy Ye Value *Shl30 = nullptr; 51189f36dd8SFreddy Ye if (FloatWidth > 80) { 51289f36dd8SFreddy Ye TempMod += 32; 51389f36dd8SFreddy Ye Value *Add = Builder.CreateShl(AAddr1Off32, Builder.getIntN(64, TempMod)); 51489f36dd8SFreddy Ye Shl30 = Builder.CreateAdd( 51589f36dd8SFreddy Ye Add, 51689f36dd8SFreddy Ye Builder.getIntN(64, ((1ull << (62ull - TempMod)) - 1ull) << TempMod)); 51789f36dd8SFreddy Ye And34 = Builder.CreateZExt(Shl30, Builder.getIntNTy(128)); 51889f36dd8SFreddy Ye } else { 51989f36dd8SFreddy Ye Value *Add = Builder.CreateShl(E0, Builder.getIntN(32, TempMod)); 52089f36dd8SFreddy Ye Shl30 = Builder.CreateAdd( 52189f36dd8SFreddy Ye Add, Builder.getIntN(32, ((1 << (30 - TempMod)) - 1) << TempMod)); 52289f36dd8SFreddy Ye And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0, 52389f36dd8SFreddy Ye Builder.getIntN(32, (1 << TempMod) - 1)); 52489f36dd8SFreddy Ye } 52589f36dd8SFreddy Ye Value *Or35 = nullptr; 52689f36dd8SFreddy Ye if (FloatWidth > 80) { 52789f36dd8SFreddy Ye Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getIntNTy(128)); 52889f36dd8SFreddy Ye Value *Or31 = Builder.CreateOr(And29Trunc, And34); 52989f36dd8SFreddy Ye Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64)); 53089f36dd8SFreddy Ye Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1), 53189f36dd8SFreddy Ye Builder.getIntN(128, FPMantissaWidth)); 53289f36dd8SFreddy Ye Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1)); 53389f36dd8SFreddy Ye Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4); 53489f36dd8SFreddy Ye Or35 = Builder.CreateOr(Or34, A6); 53589f36dd8SFreddy Ye } else { 53689f36dd8SFreddy Ye Value *Or31 = Builder.CreateOr(And34, And29); 53789f36dd8SFreddy Ye Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30); 53889f36dd8SFreddy Ye } 53989f36dd8SFreddy Ye Value *A4 = nullptr; 54089f36dd8SFreddy Ye if (IToFP->getType()->isDoubleTy()) { 54189f36dd8SFreddy Ye Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth)); 54289f36dd8SFreddy Ye Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32)); 54389f36dd8SFreddy Ye Value *And1 = 54489f36dd8SFreddy Ye Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF)); 54589f36dd8SFreddy Ye Value *Or1 = Builder.CreateOr(Shl1, And1); 54689f36dd8SFreddy Ye A4 = Builder.CreateBitCast(Or1, IToFP->getType()); 54789f36dd8SFreddy Ye } else if (IToFP->getType()->isX86_FP80Ty()) { 54889f36dd8SFreddy Ye Value *A40 = 54989f36dd8SFreddy Ye Builder.CreateBitCast(Or35, Type::getFP128Ty(Builder.getContext())); 55089f36dd8SFreddy Ye A4 = Builder.CreateFPTrunc(A40, IToFP->getType()); 551110c22feSBevin Hansson } else if (IToFP->getType()->isHalfTy() || IToFP->getType()->isBFloatTy()) { 55289f36dd8SFreddy Ye // Deal with "half" situation. This is a workaround since we don't have 55389f36dd8SFreddy Ye // floattihf.c currently as referring. 55489f36dd8SFreddy Ye Value *A40 = 55589f36dd8SFreddy Ye Builder.CreateBitCast(Or35, Type::getFloatTy(Builder.getContext())); 55689f36dd8SFreddy Ye A4 = Builder.CreateFPTrunc(A40, IToFP->getType()); 55789f36dd8SFreddy Ye } else // float type 55889f36dd8SFreddy Ye A4 = Builder.CreateBitCast(Or35, IToFP->getType()); 55989f36dd8SFreddy Ye Builder.CreateBr(End); 56089f36dd8SFreddy Ye 56189f36dd8SFreddy Ye // return: 562d75f9dd1SStephen Tozer Builder.SetInsertPoint(End, End->begin()); 56389f36dd8SFreddy Ye PHINode *Retval0 = Builder.CreatePHI(IToFP->getType(), 2); 56489f36dd8SFreddy Ye Retval0->addIncoming(A4, IfEnd26); 56589f36dd8SFreddy Ye Retval0->addIncoming(ConstantFP::getZero(IToFP->getType(), false), Entry); 56689f36dd8SFreddy Ye 56789f36dd8SFreddy Ye IToFP->replaceAllUsesWith(Retval0); 56889f36dd8SFreddy Ye IToFP->dropAllReferences(); 56989f36dd8SFreddy Ye IToFP->eraseFromParent(); 57089f36dd8SFreddy Ye } 57189f36dd8SFreddy Ye 5727edddee2SBevin Hansson static void scalarize(Instruction *I, SmallVectorImpl<Instruction *> &Replace) { 5737edddee2SBevin Hansson VectorType *VTy = cast<FixedVectorType>(I->getType()); 5747edddee2SBevin Hansson 5757edddee2SBevin Hansson IRBuilder<> Builder(I); 5767edddee2SBevin Hansson 5777edddee2SBevin Hansson unsigned NumElements = VTy->getElementCount().getFixedValue(); 5787edddee2SBevin Hansson Value *Result = PoisonValue::get(VTy); 5797edddee2SBevin Hansson for (unsigned Idx = 0; Idx < NumElements; ++Idx) { 5807edddee2SBevin Hansson Value *Ext = Builder.CreateExtractElement(I->getOperand(0), Idx); 5817edddee2SBevin Hansson Value *Cast = Builder.CreateCast(cast<CastInst>(I)->getOpcode(), Ext, 5827edddee2SBevin Hansson I->getType()->getScalarType()); 5837edddee2SBevin Hansson Result = Builder.CreateInsertElement(Result, Cast, Idx); 5847edddee2SBevin Hansson if (isa<Instruction>(Cast)) 5857edddee2SBevin Hansson Replace.push_back(cast<Instruction>(Cast)); 5867edddee2SBevin Hansson } 5877edddee2SBevin Hansson I->replaceAllUsesWith(Result); 5887edddee2SBevin Hansson I->dropAllReferences(); 5897edddee2SBevin Hansson I->eraseFromParent(); 5907edddee2SBevin Hansson } 5917edddee2SBevin Hansson 59289f36dd8SFreddy Ye static bool runImpl(Function &F, const TargetLowering &TLI) { 59389f36dd8SFreddy Ye SmallVector<Instruction *, 4> Replace; 5947edddee2SBevin Hansson SmallVector<Instruction *, 4> ReplaceVector; 59589f36dd8SFreddy Ye bool Modified = false; 59689f36dd8SFreddy Ye 59789f36dd8SFreddy Ye unsigned MaxLegalFpConvertBitWidth = 59889f36dd8SFreddy Ye TLI.getMaxLargeFPConvertBitWidthSupported(); 59989f36dd8SFreddy Ye if (ExpandFpConvertBits != llvm::IntegerType::MAX_INT_BITS) 60089f36dd8SFreddy Ye MaxLegalFpConvertBitWidth = ExpandFpConvertBits; 60189f36dd8SFreddy Ye 60289f36dd8SFreddy Ye if (MaxLegalFpConvertBitWidth >= llvm::IntegerType::MAX_INT_BITS) 60389f36dd8SFreddy Ye return false; 60489f36dd8SFreddy Ye 60589f36dd8SFreddy Ye for (auto &I : instructions(F)) { 60689f36dd8SFreddy Ye switch (I.getOpcode()) { 60789f36dd8SFreddy Ye case Instruction::FPToUI: 60889f36dd8SFreddy Ye case Instruction::FPToSI: { 6097edddee2SBevin Hansson // TODO: This pass doesn't handle scalable vectors. 6107edddee2SBevin Hansson if (I.getOperand(0)->getType()->isScalableTy()) 61189f36dd8SFreddy Ye continue; 61289f36dd8SFreddy Ye 613f991a167SSimon Pilgrim auto *IntTy = cast<IntegerType>(I.getType()->getScalarType()); 61489f36dd8SFreddy Ye if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth) 61589f36dd8SFreddy Ye continue; 61689f36dd8SFreddy Ye 6177edddee2SBevin Hansson if (I.getOperand(0)->getType()->isVectorTy()) 6187edddee2SBevin Hansson ReplaceVector.push_back(&I); 6197edddee2SBevin Hansson else 62089f36dd8SFreddy Ye Replace.push_back(&I); 62189f36dd8SFreddy Ye Modified = true; 62289f36dd8SFreddy Ye break; 62389f36dd8SFreddy Ye } 62489f36dd8SFreddy Ye case Instruction::UIToFP: 62589f36dd8SFreddy Ye case Instruction::SIToFP: { 6267edddee2SBevin Hansson // TODO: This pass doesn't handle scalable vectors. 6277edddee2SBevin Hansson if (I.getOperand(0)->getType()->isScalableTy()) 62889f36dd8SFreddy Ye continue; 62989f36dd8SFreddy Ye 6307edddee2SBevin Hansson auto *IntTy = 631f991a167SSimon Pilgrim cast<IntegerType>(I.getOperand(0)->getType()->getScalarType()); 63289f36dd8SFreddy Ye if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth) 63389f36dd8SFreddy Ye continue; 63489f36dd8SFreddy Ye 6357edddee2SBevin Hansson if (I.getOperand(0)->getType()->isVectorTy()) 6367edddee2SBevin Hansson ReplaceVector.push_back(&I); 6377edddee2SBevin Hansson else 63889f36dd8SFreddy Ye Replace.push_back(&I); 63989f36dd8SFreddy Ye Modified = true; 64089f36dd8SFreddy Ye break; 64189f36dd8SFreddy Ye } 64289f36dd8SFreddy Ye default: 64389f36dd8SFreddy Ye break; 64489f36dd8SFreddy Ye } 64589f36dd8SFreddy Ye } 64689f36dd8SFreddy Ye 6477edddee2SBevin Hansson while (!ReplaceVector.empty()) { 6487edddee2SBevin Hansson Instruction *I = ReplaceVector.pop_back_val(); 6497edddee2SBevin Hansson scalarize(I, Replace); 6507edddee2SBevin Hansson } 6517edddee2SBevin Hansson 65289f36dd8SFreddy Ye if (Replace.empty()) 65389f36dd8SFreddy Ye return false; 65489f36dd8SFreddy Ye 65589f36dd8SFreddy Ye while (!Replace.empty()) { 65689f36dd8SFreddy Ye Instruction *I = Replace.pop_back_val(); 65789f36dd8SFreddy Ye if (I->getOpcode() == Instruction::FPToUI || 65889f36dd8SFreddy Ye I->getOpcode() == Instruction::FPToSI) { 65989f36dd8SFreddy Ye expandFPToI(I); 66089f36dd8SFreddy Ye } else { 66189f36dd8SFreddy Ye expandIToFP(I); 66289f36dd8SFreddy Ye } 66389f36dd8SFreddy Ye } 66489f36dd8SFreddy Ye 66589f36dd8SFreddy Ye return Modified; 66689f36dd8SFreddy Ye } 66789f36dd8SFreddy Ye 668b6942a28SBenjamin Kramer namespace { 66989f36dd8SFreddy Ye class ExpandLargeFpConvertLegacyPass : public FunctionPass { 67089f36dd8SFreddy Ye public: 67189f36dd8SFreddy Ye static char ID; 67289f36dd8SFreddy Ye 67389f36dd8SFreddy Ye ExpandLargeFpConvertLegacyPass() : FunctionPass(ID) { 67489f36dd8SFreddy Ye initializeExpandLargeFpConvertLegacyPassPass( 67589f36dd8SFreddy Ye *PassRegistry::getPassRegistry()); 67689f36dd8SFreddy Ye } 67789f36dd8SFreddy Ye 67889f36dd8SFreddy Ye bool runOnFunction(Function &F) override { 67989f36dd8SFreddy Ye auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>(); 68089f36dd8SFreddy Ye auto *TLI = TM->getSubtargetImpl(F)->getTargetLowering(); 68189f36dd8SFreddy Ye return runImpl(F, *TLI); 68289f36dd8SFreddy Ye } 68389f36dd8SFreddy Ye 68489f36dd8SFreddy Ye void getAnalysisUsage(AnalysisUsage &AU) const override { 68589f36dd8SFreddy Ye AU.addRequired<TargetPassConfig>(); 68689f36dd8SFreddy Ye AU.addPreserved<AAResultsWrapperPass>(); 68789f36dd8SFreddy Ye AU.addPreserved<GlobalsAAWrapperPass>(); 68889f36dd8SFreddy Ye } 68989f36dd8SFreddy Ye }; 690b6942a28SBenjamin Kramer } // namespace 69189f36dd8SFreddy Ye 6923cef582aSMatt Arsenault PreservedAnalyses ExpandLargeFpConvertPass::run(Function &F, 6933cef582aSMatt Arsenault FunctionAnalysisManager &FAM) { 6943cef582aSMatt Arsenault const TargetSubtargetInfo *STI = TM->getSubtargetImpl(F); 6953cef582aSMatt Arsenault return runImpl(F, *STI->getTargetLowering()) ? PreservedAnalyses::none() 6963cef582aSMatt Arsenault : PreservedAnalyses::all(); 6973cef582aSMatt Arsenault } 6983cef582aSMatt Arsenault 69989f36dd8SFreddy Ye char ExpandLargeFpConvertLegacyPass::ID = 0; 70089f36dd8SFreddy Ye INITIALIZE_PASS_BEGIN(ExpandLargeFpConvertLegacyPass, "expand-large-fp-convert", 70189f36dd8SFreddy Ye "Expand large fp convert", false, false) 70289f36dd8SFreddy Ye INITIALIZE_PASS_END(ExpandLargeFpConvertLegacyPass, "expand-large-fp-convert", 70389f36dd8SFreddy Ye "Expand large fp convert", false, false) 70489f36dd8SFreddy Ye 70589f36dd8SFreddy Ye FunctionPass *llvm::createExpandLargeFpConvertPass() { 70689f36dd8SFreddy Ye return new ExpandLargeFpConvertLegacyPass(); 70789f36dd8SFreddy Ye } 708