Bug Summary

File:build/source/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp
Warning:line 590, column 11
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ExpandLargeFpConvert.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/CodeGen -I /build/source/llvm/lib/CodeGen -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp
1//===--- ExpandLargeFpConvert.cpp - Expand large fp convert----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9
10// This pass expands ‘fptoui .. to’, ‘fptosi .. to’, ‘uitofp .. to’,
11// ‘sitofp .. to’ instructions with a bitwidth above a threshold into
12// auto-generated functions. This is useful for targets like x86_64 that cannot
13// lower fp convertions with more than 128 bits.
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/Analysis/GlobalsModRef.h"
20#include "llvm/CodeGen/Passes.h"
21#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetPassConfig.h"
23#include "llvm/CodeGen/TargetSubtargetInfo.h"
24#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/InstIterator.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/InitializePasses.h"
28#include "llvm/Pass.h"
29#include "llvm/Support/CommandLine.h"
30#include "llvm/Target/TargetMachine.h"
31
32using namespace llvm;
33
34static cl::opt<unsigned>
35 ExpandFpConvertBits("expand-fp-convert-bits", cl::Hidden,
36 cl::init(llvm::IntegerType::MAX_INT_BITS),
37 cl::desc("fp convert instructions on integers with "
38 "more than <N> bits are expanded."));
39
40/// Generate code to convert a fp number to integer, replacing FPToS(U)I with
41/// the generated code. This currently generates code similarly to compiler-rt's
42/// implementations.
43///
44/// An example IR generated from compiler-rt/fixsfdi.c looks like below:
45/// define dso_local i64 @foo(float noundef %a) local_unnamed_addr #0 {
46/// entry:
47/// %0 = bitcast float %a to i32
48/// %conv.i = zext i32 %0 to i64
49/// %tobool.not = icmp sgt i32 %0, -1
50/// %conv = select i1 %tobool.not, i64 1, i64 -1
51/// %and = lshr i64 %conv.i, 23
52/// %shr = and i64 %and, 255
53/// %and2 = and i64 %conv.i, 8388607
54/// %or = or i64 %and2, 8388608
55/// %cmp = icmp ult i64 %shr, 127
56/// br i1 %cmp, label %cleanup, label %if.end
57///
58/// if.end: ; preds = %entry
59/// %sub = add nuw nsw i64 %shr, 4294967169
60/// %conv5 = and i64 %sub, 4294967232
61/// %cmp6.not = icmp eq i64 %conv5, 0
62/// br i1 %cmp6.not, label %if.end12, label %if.then8
63///
64/// if.then8: ; preds = %if.end
65/// %cond11 = select i1 %tobool.not, i64 9223372036854775807, i64 -9223372036854775808
66/// br label %cleanup
67///
68/// if.end12: ; preds = %if.end
69/// %cmp13 = icmp ult i64 %shr, 150
70/// br i1 %cmp13, label %if.then15, label %if.else
71///
72/// if.then15: ; preds = %if.end12
73/// %sub16 = sub nuw nsw i64 150, %shr
74/// %shr17 = lshr i64 %or, %sub16
75/// %mul = mul nsw i64 %shr17, %conv
76/// br label %cleanup
77///
78/// if.else: ; preds = %if.end12
79/// %sub18 = add nsw i64 %shr, -150
80/// %shl = shl i64 %or, %sub18
81/// %mul19 = mul nsw i64 %shl, %conv
82/// br label %cleanup
83///
84/// cleanup: ; preds = %entry, %if.else, %if.then15, %if.then8
85/// %retval.0 = phi i64 [ %cond11, %if.then8 ], [ %mul, %if.then15 ], [ %mul19, %if.else ], [ 0, %entry ]
86/// ret i64 %retval.0
87/// }
88///
89/// Replace fp to integer with generated code.
90static void expandFPToI(Instruction *FPToI) {
91 IRBuilder<> Builder(FPToI);
92 auto *FloatVal = FPToI->getOperand(0);
93 IntegerType *IntTy = cast<IntegerType>(FPToI->getType());
94
95 unsigned BitWidth = FPToI->getType()->getIntegerBitWidth();
96 unsigned FPMantissaWidth = FloatVal->getType()->getFPMantissaWidth() - 1;
97
98 // FIXME: fp16's range is covered by i32. So `fptoi half` can convert
99 // to i32 first following a sext/zext to target integer type.
100 Value *A1 = nullptr;
101 if (FloatVal->getType()->isHalfTy()) {
102 if (FPToI->getOpcode() == Instruction::FPToUI) {
103 Value *A0 = Builder.CreateFPToUI(FloatVal, Builder.getIntNTy(32));
104 A1 = Builder.CreateZExt(A0, IntTy);
105 } else { // FPToSI
106 Value *A0 = Builder.CreateFPToSI(FloatVal, Builder.getIntNTy(32));
107 A1 = Builder.CreateSExt(A0, IntTy);
108 }
109 FPToI->replaceAllUsesWith(A1);
110 FPToI->dropAllReferences();
111 FPToI->eraseFromParent();
112 return;
113 }
114
115 // fp80 conversion is implemented by fpext to fp128 first then do the
116 // conversion.
117 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
118 unsigned FloatWidth = PowerOf2Ceil(FPMantissaWidth);
119 unsigned ExponentWidth = FloatWidth - FPMantissaWidth - 1;
120 unsigned ExponentBias = (1 << (ExponentWidth - 1)) - 1;
121 Value *ImplicitBit = Builder.CreateShl(
122 Builder.getIntN(BitWidth, 1), Builder.getIntN(BitWidth, FPMantissaWidth));
123 Value *SignificandMask =
124 Builder.CreateSub(ImplicitBit, Builder.getIntN(BitWidth, 1));
125 Value *NegOne = Builder.CreateSExt(
126 ConstantInt::getSigned(Builder.getInt32Ty(), -1), IntTy);
127 Value *NegInf =
128 Builder.CreateShl(ConstantInt::getSigned(IntTy, 1),
129 ConstantInt::getSigned(IntTy, BitWidth - 1));
130
131 BasicBlock *Entry = Builder.GetInsertBlock();
132 Function *F = Entry->getParent();
133 Entry->setName(Twine(Entry->getName(), "fp-to-i-entry"));
134 BasicBlock *End =
135 Entry->splitBasicBlock(Builder.GetInsertPoint(), "fp-to-i-cleanup");
136 BasicBlock *IfEnd =
137 BasicBlock::Create(Builder.getContext(), "fp-to-i-if-end", F, End);
138 BasicBlock *IfThen5 =
139 BasicBlock::Create(Builder.getContext(), "fp-to-i-if-then5", F, End);
140 BasicBlock *IfEnd9 =
141 BasicBlock::Create(Builder.getContext(), "fp-to-i-if-end9", F, End);
142 BasicBlock *IfThen12 =
143 BasicBlock::Create(Builder.getContext(), "fp-to-i-if-then12", F, End);
144 BasicBlock *IfElse =
145 BasicBlock::Create(Builder.getContext(), "fp-to-i-if-else", F, End);
146
147 Entry->getTerminator()->eraseFromParent();
148
149 // entry:
150 Builder.SetInsertPoint(Entry);
151 Value *FloatVal0 = FloatVal;
152 // fp80 conversion is implemented by fpext to fp128 first then do the
153 // conversion.
154 if (FloatVal->getType()->isX86_FP80Ty())
155 FloatVal0 =
156 Builder.CreateFPExt(FloatVal, Type::getFP128Ty(Builder.getContext()));
157 Value *ARep0 =
158 Builder.CreateBitCast(FloatVal0, Builder.getIntNTy(FloatWidth));
159 Value *ARep = Builder.CreateZExt(ARep0, FPToI->getType());
160 Value *PosOrNeg = Builder.CreateICmpSGT(
161 ARep0, ConstantInt::getSigned(Builder.getIntNTy(FloatWidth), -1));
162 Value *Sign = Builder.CreateSelect(PosOrNeg, ConstantInt::getSigned(IntTy, 1),
163 ConstantInt::getSigned(IntTy, -1));
164 Value *And =
165 Builder.CreateLShr(ARep, Builder.getIntN(BitWidth, FPMantissaWidth));
166 Value *And2 = Builder.CreateAnd(
167 And, Builder.getIntN(BitWidth, (1 << ExponentWidth) - 1));
168 Value *Abs = Builder.CreateAnd(ARep, SignificandMask);
169 Value *Or = Builder.CreateOr(Abs, ImplicitBit);
170 Value *Cmp =
171 Builder.CreateICmpULT(And2, Builder.getIntN(BitWidth, ExponentBias));
172 Builder.CreateCondBr(Cmp, End, IfEnd);
173
174 // if.end:
175 Builder.SetInsertPoint(IfEnd);
176 Value *Add1 = Builder.CreateAdd(
177 And2, ConstantInt::getSigned(IntTy, -int64_t(ExponentBias + BitWidth)));
178 Value *Cmp3 =
179 Builder.CreateICmpULT(Add1, ConstantInt::getSigned(IntTy, -BitWidth));
180 Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9);
181
182 // if.then5:
183 Builder.SetInsertPoint(IfThen5);
184 Value *PosInf = Builder.CreateXor(NegOne, NegInf);
185 Value *Cond8 = Builder.CreateSelect(PosOrNeg, PosInf, NegInf);
186 Builder.CreateBr(End);
187
188 // if.end9:
189 Builder.SetInsertPoint(IfEnd9);
190 Value *Cmp10 = Builder.CreateICmpULT(
191 And2, Builder.getIntN(BitWidth, ExponentBias + FPMantissaWidth));
192 Builder.CreateCondBr(Cmp10, IfThen12, IfElse);
193
194 // if.then12:
195 Builder.SetInsertPoint(IfThen12);
196 Value *Sub13 = Builder.CreateSub(
197 Builder.getIntN(BitWidth, ExponentBias + FPMantissaWidth), And2);
198 Value *Shr14 = Builder.CreateLShr(Or, Sub13);
199 Value *Mul = Builder.CreateMul(Shr14, Sign);
200 Builder.CreateBr(End);
201
202 // if.else:
203 Builder.SetInsertPoint(IfElse);
204 Value *Sub15 = Builder.CreateAdd(
205 And2,
206 ConstantInt::getSigned(IntTy, -(ExponentBias + FPMantissaWidth)));
207 Value *Shl = Builder.CreateShl(Or, Sub15);
208 Value *Mul16 = Builder.CreateMul(Shl, Sign);
209 Builder.CreateBr(End);
210
211 // cleanup:
212 Builder.SetInsertPoint(End, End->begin());
213 PHINode *Retval0 = Builder.CreatePHI(FPToI->getType(), 4);
214
215 Retval0->addIncoming(Cond8, IfThen5);
216 Retval0->addIncoming(Mul, IfThen12);
217 Retval0->addIncoming(Mul16, IfElse);
218 Retval0->addIncoming(Builder.getIntN(BitWidth, 0), Entry);
219
220 FPToI->replaceAllUsesWith(Retval0);
221 FPToI->dropAllReferences();
222 FPToI->eraseFromParent();
223}
224
225/// Generate code to convert a fp number to integer, replacing S(U)IToFP with
226/// the generated code. This currently generates code similarly to compiler-rt's
227/// implementations. This implementation has an implicit assumption that integer
228/// width is larger than fp.
229///
230/// An example IR generated from compiler-rt/floatdisf.c looks like below:
231/// define dso_local float @__floatdisf(i64 noundef %a) local_unnamed_addr #0 {
232/// entry:
233/// %cmp = icmp eq i64 %a, 0
234/// br i1 %cmp, label %return, label %if.end
235///
236/// if.end: ; preds = %entry
237/// %shr = ashr i64 %a, 63
238/// %xor = xor i64 %shr, %a
239/// %sub = sub nsw i64 %xor, %shr
240/// %0 = tail call i64 @llvm.ctlz.i64(i64 %sub, i1 true), !range !5
241/// %cast = trunc i64 %0 to i32
242/// %sub1 = sub nuw nsw i32 64, %cast
243/// %sub2 = xor i32 %cast, 63
244/// %cmp3 = icmp ult i32 %cast, 40
245/// br i1 %cmp3, label %if.then4, label %if.else
246///
247/// if.then4: ; preds = %if.end
248/// switch i32 %sub1, label %sw.default [
249/// i32 25, label %sw.bb
250/// i32 26, label %sw.epilog
251/// ]
252///
253/// sw.bb: ; preds = %if.then4
254/// %shl = shl i64 %sub, 1
255/// br label %sw.epilog
256///
257/// sw.default: ; preds = %if.then4
258/// %sub5 = sub nsw i64 38, %0
259/// %sh_prom = and i64 %sub5, 4294967295
260/// %shr6 = lshr i64 %sub, %sh_prom
261/// %shr9 = lshr i64 274877906943, %0
262/// %and = and i64 %shr9, %sub
263/// %cmp10 = icmp ne i64 %and, 0
264/// %conv11 = zext i1 %cmp10 to i64
265/// %or = or i64 %shr6, %conv11
266/// br label %sw.epilog
267///
268/// sw.epilog: ; preds = %sw.default, %if.then4, %sw.bb
269/// %a.addr.0 = phi i64 [ %or, %sw.default ], [ %sub, %if.then4 ], [ %shl, %sw.bb ]
270/// %1 = lshr i64 %a.addr.0, 2
271/// %2 = and i64 %1, 1
272/// %or16 = or i64 %2, %a.addr.0
273/// %inc = add nsw i64 %or16, 1
274/// %3 = and i64 %inc, 67108864
275/// %tobool.not = icmp eq i64 %3, 0
276/// %spec.select.v = select i1 %tobool.not, i64 2, i64 3
277/// %spec.select = ashr i64 %inc, %spec.select.v
278/// %spec.select56 = select i1 %tobool.not, i32 %sub2, i32 %sub1
279/// br label %if.end26
280///
281/// if.else: ; preds = %if.end
282/// %sub23 = add nuw nsw i64 %0, 4294967256
283/// %sh_prom24 = and i64 %sub23, 4294967295
284/// %shl25 = shl i64 %sub, %sh_prom24
285/// br label %if.end26
286///
287/// if.end26: ; preds = %sw.epilog, %if.else
288/// %a.addr.1 = phi i64 [ %shl25, %if.else ], [ %spec.select, %sw.epilog ]
289/// %e.0 = phi i32 [ %sub2, %if.else ], [ %spec.select56, %sw.epilog ]
290/// %conv27 = trunc i64 %shr to i32
291/// %and28 = and i32 %conv27, -2147483648
292/// %add = shl nuw nsw i32 %e.0, 23
293/// %shl29 = add nuw nsw i32 %add, 1065353216
294/// %conv31 = trunc i64 %a.addr.1 to i32
295/// %and32 = and i32 %conv31, 8388607
296/// %or30 = or i32 %and32, %and28
297/// %or33 = or i32 %or30, %shl29
298/// %4 = bitcast i32 %or33 to float
299/// br label %return
300///
301/// return: ; preds = %entry, %if.end26
302/// %retval.0 = phi float [ %4, %if.end26 ], [ 0.000000e+00, %entry ]
303/// ret float %retval.0
304/// }
305///
306/// Replace integer to fp with generated code.
307static void expandIToFP(Instruction *IToFP) {
308 IRBuilder<> Builder(IToFP);
309 auto *IntVal = IToFP->getOperand(0);
310 IntegerType *IntTy = cast<IntegerType>(IntVal->getType());
311
312 unsigned BitWidth = IntVal->getType()->getIntegerBitWidth();
313 unsigned FPMantissaWidth = IToFP->getType()->getFPMantissaWidth() - 1;
314 // fp80 conversion is implemented by conversion tp fp128 first following
315 // a fptrunc to fp80.
316 FPMantissaWidth = FPMantissaWidth == 63 ? 112 : FPMantissaWidth;
317 // FIXME: As there is no related builtins added in compliler-rt,
318 // here currently utilized the fp32 <-> fp16 lib calls to implement.
319 FPMantissaWidth = FPMantissaWidth == 10 ? 23 : FPMantissaWidth;
320 unsigned FloatWidth = PowerOf2Ceil(FPMantissaWidth);
321 bool IsSigned = IToFP->getOpcode() == Instruction::SIToFP;
322
323 assert(BitWidth > FloatWidth && "Unexpected conversion. expandIToFP() "(static_cast <bool> (BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() " "assumes integer width is larger than fp."
) ? void (0) : __assert_fail ("BitWidth > FloatWidth && \"Unexpected conversion. expandIToFP() \" \"assumes integer width is larger than fp.\""
, "llvm/lib/CodeGen/ExpandLargeFpConvert.cpp", 324, __extension__
__PRETTY_FUNCTION__))
324 "assumes integer width is larger than fp.")(static_cast <bool> (BitWidth > FloatWidth &&
"Unexpected conversion. expandIToFP() " "assumes integer width is larger than fp."
) ? void (0) : __assert_fail ("BitWidth > FloatWidth && \"Unexpected conversion. expandIToFP() \" \"assumes integer width is larger than fp.\""
, "llvm/lib/CodeGen/ExpandLargeFpConvert.cpp", 324, __extension__
__PRETTY_FUNCTION__))
;
325
326 Value *Temp1 =
327 Builder.CreateShl(Builder.getIntN(BitWidth, 1),
328 Builder.getIntN(BitWidth, FPMantissaWidth + 3));
329
330 BasicBlock *Entry = Builder.GetInsertBlock();
331 Function *F = Entry->getParent();
332 Entry->setName(Twine(Entry->getName(), "itofp-entry"));
333 BasicBlock *End =
334 Entry->splitBasicBlock(Builder.GetInsertPoint(), "itofp-return");
335 BasicBlock *IfEnd =
336 BasicBlock::Create(Builder.getContext(), "itofp-if-end", F, End);
337 BasicBlock *IfThen4 =
338 BasicBlock::Create(Builder.getContext(), "itofp-if-then4", F, End);
339 BasicBlock *SwBB =
340 BasicBlock::Create(Builder.getContext(), "itofp-sw-bb", F, End);
341 BasicBlock *SwDefault =
342 BasicBlock::Create(Builder.getContext(), "itofp-sw-default", F, End);
343 BasicBlock *SwEpilog =
344 BasicBlock::Create(Builder.getContext(), "itofp-sw-epilog", F, End);
345 BasicBlock *IfThen20 =
346 BasicBlock::Create(Builder.getContext(), "itofp-if-then20", F, End);
347 BasicBlock *IfElse =
348 BasicBlock::Create(Builder.getContext(), "itofp-if-else", F, End);
349 BasicBlock *IfEnd26 =
350 BasicBlock::Create(Builder.getContext(), "itofp-if-end26", F, End);
351
352 Entry->getTerminator()->eraseFromParent();
353
354 Function *CTLZ =
355 Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz, IntTy);
356 ConstantInt *True = Builder.getTrue();
357
358 // entry:
359 Builder.SetInsertPoint(Entry);
360 Value *Cmp = Builder.CreateICmpEQ(IntVal, ConstantInt::getSigned(IntTy, 0));
361 Builder.CreateCondBr(Cmp, End, IfEnd);
362
363 // if.end:
364 Builder.SetInsertPoint(IfEnd);
365 Value *Shr =
366 Builder.CreateAShr(IntVal, Builder.getIntN(BitWidth, BitWidth - 1));
367 Value *Xor = Builder.CreateXor(Shr, IntVal);
368 Value *Sub = Builder.CreateSub(Xor, Shr);
369 Value *Call = Builder.CreateCall(CTLZ, {IsSigned ? Sub : IntVal, True});
370 Value *Cast = Builder.CreateTrunc(Call, Builder.getInt32Ty());
371 int BitWidthNew = FloatWidth == 128 ? BitWidth : 32;
372 Value *Sub1 = Builder.CreateSub(Builder.getIntN(BitWidthNew, BitWidth),
373 FloatWidth == 128 ? Call : Cast);
374 Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew, BitWidth - 1),
375 FloatWidth == 128 ? Call : Cast);
376 Value *Cmp3 = Builder.CreateICmpSGT(
377 Sub2, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1));
378 Builder.CreateCondBr(Cmp3, IfThen4, IfElse);
379
380 // if.then4:
381 Builder.SetInsertPoint(IfThen4);
382 llvm::SwitchInst *SI = Builder.CreateSwitch(Sub1, SwDefault);
383 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 2), SwBB);
384 SI->addCase(Builder.getIntN(BitWidthNew, FPMantissaWidth + 3), SwEpilog);
385
386 // sw.bb:
387 Builder.SetInsertPoint(SwBB);
388 Value *Shl =
389 Builder.CreateShl(IsSigned ? Sub : IntVal, Builder.getIntN(BitWidth, 1));
390 Builder.CreateBr(SwEpilog);
391
392 // sw.default:
393 Builder.SetInsertPoint(SwDefault);
394 Value *Sub5 = Builder.CreateSub(
395 Builder.getIntN(BitWidthNew, BitWidth - FPMantissaWidth - 3),
396 FloatWidth == 128 ? Call : Cast);
397 Value *ShProm = Builder.CreateZExt(Sub5, IntTy);
398 Value *Shr6 = Builder.CreateLShr(IsSigned ? Sub : IntVal,
399 FloatWidth == 128 ? Sub5 : ShProm);
400 Value *Sub8 =
401 Builder.CreateAdd(FloatWidth == 128 ? Call : Cast,
402 Builder.getIntN(BitWidthNew, FPMantissaWidth + 3));
403 Value *ShProm9 = Builder.CreateZExt(Sub8, IntTy);
404 Value *Shr9 = Builder.CreateLShr(ConstantInt::getSigned(IntTy, -1),
405 FloatWidth == 128 ? Sub8 : ShProm9);
406 Value *And = Builder.CreateAnd(Shr9, IsSigned ? Sub : IntVal);
407 Value *Cmp10 = Builder.CreateICmpNE(And, Builder.getIntN(BitWidth, 0));
408 Value *Conv11 = Builder.CreateZExt(Cmp10, IntTy);
409 Value *Or = Builder.CreateOr(Shr6, Conv11);
410 Builder.CreateBr(SwEpilog);
411
412 // sw.epilog:
413 Builder.SetInsertPoint(SwEpilog);
414 PHINode *AAddr0 = Builder.CreatePHI(IntTy, 3);
415 AAddr0->addIncoming(Or, SwDefault);
416 AAddr0->addIncoming(IsSigned ? Sub : IntVal, IfThen4);
417 AAddr0->addIncoming(Shl, SwBB);
418 Value *A0 = Builder.CreateTrunc(AAddr0, Builder.getInt32Ty());
419 Value *A1 = Builder.CreateLShr(A0, Builder.getIntN(32, 2));
420 Value *A2 = Builder.CreateAnd(A1, Builder.getIntN(32, 1));
421 Value *Conv16 = Builder.CreateZExt(A2, IntTy);
422 Value *Or17 = Builder.CreateOr(AAddr0, Conv16);
423 Value *Inc = Builder.CreateAdd(Or17, Builder.getIntN(BitWidth, 1));
424 Value *Shr18 = nullptr;
425 if (IsSigned)
426 Shr18 = Builder.CreateAShr(Inc, Builder.getIntN(BitWidth, 2));
427 else
428 Shr18 = Builder.CreateLShr(Inc, Builder.getIntN(BitWidth, 2));
429 Value *A3 = Builder.CreateAnd(Inc, Temp1, "a3");
430 Value *PosOrNeg = Builder.CreateICmpEQ(A3, Builder.getIntN(BitWidth, 0));
431 Value *ExtractT60 = Builder.CreateTrunc(Shr18, Builder.getIntNTy(FloatWidth));
432 Value *Extract63 = Builder.CreateLShr(Shr18, Builder.getIntN(BitWidth, 32));
433 Value *ExtractT64 = nullptr;
434 if (FloatWidth > 80)
435 ExtractT64 = Builder.CreateTrunc(Sub2, Builder.getInt64Ty());
436 else
437 ExtractT64 = Builder.CreateTrunc(Extract63, Builder.getInt32Ty());
438 Builder.CreateCondBr(PosOrNeg, IfEnd26, IfThen20);
439
440 // if.then20
441 Builder.SetInsertPoint(IfThen20);
442 Value *Shr21 = nullptr;
443 if (IsSigned)
444 Shr21 = Builder.CreateAShr(Inc, Builder.getIntN(BitWidth, 3));
445 else
446 Shr21 = Builder.CreateLShr(Inc, Builder.getIntN(BitWidth, 3));
447 Value *ExtractT = Builder.CreateTrunc(Shr21, Builder.getIntNTy(FloatWidth));
448 Value *Extract = Builder.CreateLShr(Shr21, Builder.getIntN(BitWidth, 32));
449 Value *ExtractT62 = nullptr;
450 if (FloatWidth > 80)
451 ExtractT62 = Builder.CreateTrunc(Sub1, Builder.getIntNTy(64));
452 else
453 ExtractT62 = Builder.CreateTrunc(Extract, Builder.getIntNTy(32));
454 Builder.CreateBr(IfEnd26);
455
456 // if.else:
457 Builder.SetInsertPoint(IfElse);
458 Value *Sub24 = Builder.CreateAdd(
459 FloatWidth == 128 ? Call : Cast,
460 ConstantInt::getSigned(Builder.getIntNTy(BitWidthNew),
461 -(BitWidth - FPMantissaWidth - 1)));
462 Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
463 Value *Shl26 = Builder.CreateShl(IsSigned ? Sub : IntVal,
464 FloatWidth == 128 ? Sub24 : ShProm25);
465 Value *ExtractT61 = Builder.CreateTrunc(Shl26, Builder.getIntNTy(FloatWidth));
466 Value *Extract65 = Builder.CreateLShr(Shl26, Builder.getIntN(BitWidth, 32));
467 Value *ExtractT66 = nullptr;
468 if (FloatWidth > 80)
469 ExtractT66 = Builder.CreateTrunc(Sub2, Builder.getIntNTy(64));
470 else
471 ExtractT66 = Builder.CreateTrunc(Extract65, Builder.getInt32Ty());
472 Builder.CreateBr(IfEnd26);
473
474 // if.end26:
475 Builder.SetInsertPoint(IfEnd26);
476 PHINode *AAddr1Off0 = Builder.CreatePHI(Builder.getIntNTy(FloatWidth), 3);
477 AAddr1Off0->addIncoming(ExtractT, IfThen20);
478 AAddr1Off0->addIncoming(ExtractT60, SwEpilog);
479 AAddr1Off0->addIncoming(ExtractT61, IfElse);
480 PHINode *AAddr1Off32 = nullptr;
481 if (FloatWidth > 32) {
482 AAddr1Off32 =
483 Builder.CreatePHI(Builder.getIntNTy(FloatWidth > 80 ? 64 : 32), 3);
484 AAddr1Off32->addIncoming(ExtractT62, IfThen20);
485 AAddr1Off32->addIncoming(ExtractT64, SwEpilog);
486 AAddr1Off32->addIncoming(ExtractT66, IfElse);
487 }
488 PHINode *E0 = nullptr;
489 if (FloatWidth <= 80) {
490 E0 = Builder.CreatePHI(Builder.getIntNTy(BitWidthNew), 3);
491 E0->addIncoming(Sub1, IfThen20);
492 E0->addIncoming(Sub2, SwEpilog);
493 E0->addIncoming(Sub2, IfElse);
494 }
495 Value *And29 = nullptr;
496 if (FloatWidth > 80) {
497 Value *Temp2 = Builder.CreateShl(Builder.getIntN(BitWidth, 1),
498 Builder.getIntN(BitWidth, 63));
499 And29 = Builder.CreateAnd(Shr, Temp2, "and29");
500 } else {
501 Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getIntNTy(32));
502 And29 = Builder.CreateAnd(
503 Conv28, ConstantInt::getSigned(Builder.getIntNTy(32), 0x80000000));
504 }
505 unsigned TempMod = FPMantissaWidth % 32;
506 Value *And34 = nullptr;
507 Value *Shl30 = nullptr;
508 if (FloatWidth > 80) {
509 TempMod += 32;
510 Value *Add = Builder.CreateShl(AAddr1Off32, Builder.getIntN(64, TempMod));
511 Shl30 = Builder.CreateAdd(
512 Add,
513 Builder.getIntN(64, ((1ull << (62ull - TempMod)) - 1ull) << TempMod));
514 And34 = Builder.CreateZExt(Shl30, Builder.getIntNTy(128));
515 } else {
516 Value *Add = Builder.CreateShl(E0, Builder.getIntN(32, TempMod));
517 Shl30 = Builder.CreateAdd(
518 Add, Builder.getIntN(32, ((1 << (30 - TempMod)) - 1) << TempMod));
519 And34 = Builder.CreateAnd(FloatWidth > 32 ? AAddr1Off32 : AAddr1Off0,
520 Builder.getIntN(32, (1 << TempMod) - 1));
521 }
522 Value *Or35 = nullptr;
523 if (FloatWidth > 80) {
524 Value *And29Trunc = Builder.CreateTrunc(And29, Builder.getIntNTy(128));
525 Value *Or31 = Builder.CreateOr(And29Trunc, And34);
526 Value *Or34 = Builder.CreateShl(Or31, Builder.getIntN(128, 64));
527 Value *Temp3 = Builder.CreateShl(Builder.getIntN(128, 1),
528 Builder.getIntN(128, FPMantissaWidth));
529 Value *Temp4 = Builder.CreateSub(Temp3, Builder.getIntN(128, 1));
530 Value *A6 = Builder.CreateAnd(AAddr1Off0, Temp4);
531 Or35 = Builder.CreateOr(Or34, A6);
532 } else {
533 Value *Or31 = Builder.CreateOr(And34, And29);
534 Or35 = Builder.CreateOr(IsSigned ? Or31 : And34, Shl30);
535 }
536 Value *A4 = nullptr;
537 if (IToFP->getType()->isDoubleTy()) {
538 Value *ZExt1 = Builder.CreateZExt(Or35, Builder.getIntNTy(FloatWidth));
539 Value *Shl1 = Builder.CreateShl(ZExt1, Builder.getIntN(FloatWidth, 32));
540 Value *And1 =
541 Builder.CreateAnd(AAddr1Off0, Builder.getIntN(FloatWidth, 0xFFFFFFFF));
542 Value *Or1 = Builder.CreateOr(Shl1, And1);
543 A4 = Builder.CreateBitCast(Or1, IToFP->getType());
544 } else if (IToFP->getType()->isX86_FP80Ty()) {
545 Value *A40 =
546 Builder.CreateBitCast(Or35, Type::getFP128Ty(Builder.getContext()));
547 A4 = Builder.CreateFPTrunc(A40, IToFP->getType());
548 } else if (IToFP->getType()->isHalfTy()) {
549 // Deal with "half" situation. This is a workaround since we don't have
550 // floattihf.c currently as referring.
551 Value *A40 =
552 Builder.CreateBitCast(Or35, Type::getFloatTy(Builder.getContext()));
553 A4 = Builder.CreateFPTrunc(A40, IToFP->getType());
554 } else // float type
555 A4 = Builder.CreateBitCast(Or35, IToFP->getType());
556 Builder.CreateBr(End);
557
558 // return:
559 Builder.SetInsertPoint(End, End->begin());
560 PHINode *Retval0 = Builder.CreatePHI(IToFP->getType(), 2);
561 Retval0->addIncoming(A4, IfEnd26);
562 Retval0->addIncoming(ConstantFP::getZero(IToFP->getType(), false), Entry);
563
564 IToFP->replaceAllUsesWith(Retval0);
565 IToFP->dropAllReferences();
566 IToFP->eraseFromParent();
567}
568
569static bool runImpl(Function &F, const TargetLowering &TLI) {
570 SmallVector<Instruction *, 4> Replace;
571 bool Modified = false;
572
573 unsigned MaxLegalFpConvertBitWidth =
574 TLI.getMaxLargeFPConvertBitWidthSupported();
575 if (ExpandFpConvertBits != llvm::IntegerType::MAX_INT_BITS)
2
Assuming the condition is false
3
Taking false branch
576 MaxLegalFpConvertBitWidth = ExpandFpConvertBits;
577
578 if (MaxLegalFpConvertBitWidth >= llvm::IntegerType::MAX_INT_BITS)
4
Assuming 'MaxLegalFpConvertBitWidth' is < MAX_INT_BITS
5
Taking false branch
579 return false;
580
581 for (auto &I : instructions(F)) {
582 switch (I.getOpcode()) {
6
Control jumps to 'case FPToSI:' at line 584
583 case Instruction::FPToUI:
584 case Instruction::FPToSI: {
585 // TODO: This pass doesn't handle vectors.
586 if (I.getOperand(0)->getType()->isVectorTy())
7
Taking false branch
587 continue;
588
589 auto *IntTy = dyn_cast<IntegerType>(I.getType());
8
Assuming the object is not a 'CastReturnType'
9
'IntTy' initialized to a null pointer value
590 if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth)
10
Called C++ object pointer is null
591 continue;
592
593 Replace.push_back(&I);
594 Modified = true;
595 break;
596 }
597 case Instruction::UIToFP:
598 case Instruction::SIToFP: {
599 // TODO: This pass doesn't handle vectors.
600 if (I.getOperand(0)->getType()->isVectorTy())
601 continue;
602
603 auto *IntTy = dyn_cast<IntegerType>(I.getOperand(0)->getType());
604 if (IntTy->getIntegerBitWidth() <= MaxLegalFpConvertBitWidth)
605 continue;
606
607 Replace.push_back(&I);
608 Modified = true;
609 break;
610 }
611 default:
612 break;
613 }
614 }
615
616 if (Replace.empty())
617 return false;
618
619 while (!Replace.empty()) {
620 Instruction *I = Replace.pop_back_val();
621 if (I->getOpcode() == Instruction::FPToUI ||
622 I->getOpcode() == Instruction::FPToSI) {
623 expandFPToI(I);
624 } else {
625 expandIToFP(I);
626 }
627 }
628
629 return Modified;
630}
631
632namespace {
633class ExpandLargeFpConvertLegacyPass : public FunctionPass {
634public:
635 static char ID;
636
637 ExpandLargeFpConvertLegacyPass() : FunctionPass(ID) {
638 initializeExpandLargeFpConvertLegacyPassPass(
639 *PassRegistry::getPassRegistry());
640 }
641
642 bool runOnFunction(Function &F) override {
643 auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
644 auto *TLI = TM->getSubtargetImpl(F)->getTargetLowering();
645 return runImpl(F, *TLI);
1
Calling 'runImpl'
646 }
647
648 void getAnalysisUsage(AnalysisUsage &AU) const override {
649 AU.addRequired<TargetPassConfig>();
650 AU.addPreserved<AAResultsWrapperPass>();
651 AU.addPreserved<GlobalsAAWrapperPass>();
652 }
653};
654} // namespace
655
656char ExpandLargeFpConvertLegacyPass::ID = 0;
657INITIALIZE_PASS_BEGIN(ExpandLargeFpConvertLegacyPass, "expand-large-fp-convert",static void *initializeExpandLargeFpConvertLegacyPassPassOnce
(PassRegistry &Registry) {
658 "Expand large fp convert", false, false)static void *initializeExpandLargeFpConvertLegacyPassPassOnce
(PassRegistry &Registry) {
659INITIALIZE_PASS_END(ExpandLargeFpConvertLegacyPass, "expand-large-fp-convert",PassInfo *PI = new PassInfo( "Expand large fp convert", "expand-large-fp-convert"
, &ExpandLargeFpConvertLegacyPass::ID, PassInfo::NormalCtor_t
(callDefaultCtor<ExpandLargeFpConvertLegacyPass>), false
, false); Registry.registerPass(*PI, true); return PI; } static
llvm::once_flag InitializeExpandLargeFpConvertLegacyPassPassFlag
; void llvm::initializeExpandLargeFpConvertLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeExpandLargeFpConvertLegacyPassPassFlag
, initializeExpandLargeFpConvertLegacyPassPassOnce, std::ref(
Registry)); }
660 "Expand large fp convert", false, false)PassInfo *PI = new PassInfo( "Expand large fp convert", "expand-large-fp-convert"
, &ExpandLargeFpConvertLegacyPass::ID, PassInfo::NormalCtor_t
(callDefaultCtor<ExpandLargeFpConvertLegacyPass>), false
, false); Registry.registerPass(*PI, true); return PI; } static
llvm::once_flag InitializeExpandLargeFpConvertLegacyPassPassFlag
; void llvm::initializeExpandLargeFpConvertLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeExpandLargeFpConvertLegacyPassPassFlag
, initializeExpandLargeFpConvertLegacyPassPassOnce, std::ref(
Registry)); }
661
662FunctionPass *llvm::createExpandLargeFpConvertPass() {
663 return new ExpandLargeFpConvertLegacyPass();
664}