LLVM: lib/Support/APFixedPoint.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

16

17#include

18

19namespace llvm {

20

22 OS << "width=" << getWidth() << ", ";

24 OS << "scale=" << getScale() << ", ";

27 OS << "IsSigned=" << IsSigned << ", ";

28 OS << "HasUnsignedPadding=" << HasUnsignedPadding << ", ";

29 OS << "IsSaturated=" << IsSaturated;

30}

31

35

38 std::memcpy(&F, &I, sizeof(F));

39 return F;

40}

41

43 bool *Overflow) const {

46 if (Overflow)

47 *Overflow = false;

48

49 if (RelativeUpscale > 0)

51 NewVal = NewVal.relativeShl(RelativeUpscale);

52

58

59

61

63 NewVal = NewVal.isNegative() ? Mask : ~Mask;

64 else if (Overflow)

65 *Overflow = true;

66 }

67

68

69

71

73 NewVal = 0;

74 else if (Overflow)

75 *Overflow = true;

76 }

77

81}

82

86 bool ThisSigned = Val.isSigned();

87 bool OtherSigned = OtherVal.isSigned();

88

91 unsigned CommonWidth = CommonMsb - CommonLsb + 1;

92

93 ThisVal = ThisVal.extOrTrunc(CommonWidth);

94 OtherVal = OtherVal.extOrTrunc(CommonWidth);

95

97 OtherVal = OtherVal.shl(Other.getLsbWeight() - CommonLsb);

98

99 if (ThisSigned && OtherSigned) {

100 if (ThisVal.sgt(OtherVal))

101 return 1;

102 else if (ThisVal.slt(OtherVal))

103 return -1;

104 } else if (!ThisSigned && !OtherSigned) {

105 if (ThisVal.ugt(OtherVal))

106 return 1;

107 else if (ThisVal.ult(OtherVal))

108 return -1;

109 } else if (ThisSigned && !OtherSigned) {

111 return -1;

112 else if (ThisVal.ugt(OtherVal))

113 return 1;

114 else if (ThisVal.ult(OtherVal))

115 return -1;

116 } else {

117

119 return 1;

120 else if (ThisVal.ugt(OtherVal))

121 return 1;

122 else if (ThisVal.ult(OtherVal))

123 return -1;

124 }

125

126 return 0;

127}

128

130 bool IsUnsigned = !Sema.isSigned();

132 if (IsUnsigned && Sema.hasUnsignedPadding())

133 Val = Val.lshr(1);

135}

136

141

143 APSInt Val(Sema.getWidth(), !Sema.isSigned());

144 Val.setBit(0);

146}

147

150

151

152

153

154

155

156

157

164

169}

170

175 Other.getMsbWeight() - Other.hasSignOrPaddingBit());

176 unsigned CommonWidth = CommonMSb - CommonLsb + 1;

177

178 bool ResultIsSigned = isSigned() || Other.isSigned();

179 bool ResultIsSaturated = isSaturated() || Other.isSaturated();

180 bool ResultHasUnsignedPadding = false;

181 if (!ResultIsSigned) {

182

184 Other.hasUnsignedPadding() && !ResultIsSaturated;

185 }

186

187

188

189

190 if (ResultIsSigned || ResultHasUnsignedPadding)

191 CommonWidth++;

192

194 ResultIsSaturated, ResultHasUnsignedPadding);

195}

196

198 bool *Overflow) const {

199 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());

204 bool Overflowed = false;

205

207 if (CommonFXSema.isSaturated()) {

208 Result = CommonFXSema.isSigned() ? ThisVal.sadd_sat(OtherVal)

209 : ThisVal.uadd_sat(OtherVal);

210 } else {

211 Result = ThisVal.isSigned() ? ThisVal.sadd_ov(OtherVal, Overflowed)

212 : ThisVal.uadd_ov(OtherVal, Overflowed);

213 }

214

215 if (Overflow)

216 *Overflow = Overflowed;

217

219}

220

222 bool *Overflow) const {

223 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());

228 bool Overflowed = false;

229

231 if (CommonFXSema.isSaturated()) {

232 Result = CommonFXSema.isSigned() ? ThisVal.ssub_sat(OtherVal)

233 : ThisVal.usub_sat(OtherVal);

234 } else {

235 Result = ThisVal.isSigned() ? ThisVal.ssub_ov(OtherVal, Overflowed)

236 : ThisVal.usub_ov(OtherVal, Overflowed);

237 }

238

239 if (Overflow)

240 *Overflow = Overflowed;

241

243}

244

246 bool *Overflow) const {

247 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());

252 bool Overflowed = false;

253

254

255 unsigned Wide = CommonFXSema.getWidth() * 2;

256 if (CommonFXSema.isSigned()) {

257 ThisVal = ThisVal.sext(Wide);

258 OtherVal = OtherVal.sext(Wide);

259 } else {

260 ThisVal = ThisVal.zext(Wide);

261 OtherVal = OtherVal.zext(Wide);

262 }

263

264

265

266

267

268

269

270

272 if (CommonFXSema.isSigned())

273 Result = ThisVal.smul_ov(OtherVal, Overflowed)

275 else

276 Result = ThisVal.umul_ov(OtherVal, Overflowed)

278 assert(!Overflowed && "Full multiplication cannot overflow!");

279 Result.setIsSigned(CommonFXSema.isSigned());

280

281

282

287 if (CommonFXSema.isSaturated()) {

288 if (Result < Min)

289 Result = Min;

290 else if (Result > Max)

291 Result = Max;

292 } else {

293 Overflowed = Result < Min || Result > Max;

294 }

295

296 if (Overflow)

297 *Overflow = Overflowed;

298

299 return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),

300 CommonFXSema);

301}

302

304 bool *Overflow) const {

305 auto CommonFXSema = Sema.getCommonSemantics(Other.getSemantics());

310 bool Overflowed = false;

311

312

313

314

315 unsigned Wide =

316 CommonFXSema.getWidth() * 2 + std::max(-CommonFXSema.getMsbWeight(), 0);

317 if (CommonFXSema.isSigned()) {

318 ThisVal = ThisVal.sext(Wide);

319 OtherVal = OtherVal.sext(Wide);

320 } else {

321 ThisVal = ThisVal.zext(Wide);

322 OtherVal = OtherVal.zext(Wide);

323 }

324

325

326

327 if (CommonFXSema.getLsbWeight() < 0)

328 ThisVal = ThisVal.shl(-CommonFXSema.getLsbWeight());

329 else if (CommonFXSema.getLsbWeight() > 0)

330 OtherVal = OtherVal.shl(CommonFXSema.getLsbWeight());

332 if (CommonFXSema.isSigned()) {

335

336

338 Result = Result - 1;

339 } else {

340 Result = ThisVal.udiv(OtherVal);

341 }

342 Result.setIsSigned(CommonFXSema.isSigned());

343

344

345

350 if (CommonFXSema.isSaturated()) {

351 if (Result < Min)

352 Result = Min;

353 else if (Result > Max)

354 Result = Max;

355 } else {

356 Overflowed = Result < Min || Result > Max;

357 }

358

359 if (Overflow)

360 *Overflow = Overflowed;

361

362 return APFixedPoint(Result.sextOrTrunc(CommonFXSema.getWidth()),

363 CommonFXSema);

364}

365

367 APSInt ThisVal = Val;

368 bool Overflowed = false;

369

370

371 unsigned Wide = Sema.getWidth() * 2;

372 if (Sema.isSigned())

373 ThisVal = ThisVal.sext(Wide);

374 else

375 ThisVal = ThisVal.zext(Wide);

376

377

378 Amt = std::min(Amt, ThisVal.getBitWidth());

379 APSInt Result = ThisVal << Amt;

380 Result.setIsSigned(Sema.isSigned());

381

382

383

386 if (Sema.isSaturated()) {

387 if (Result < Min)

388 Result = Min;

389 else if (Result > Max)

390 Result = Max;

391 } else {

392 Overflowed = Result < Min || Result > Max;

393 }

394

395 if (Overflow)

396 *Overflow = Overflowed;

397

398 return APFixedPoint(Result.sextOrTrunc(Sema.getWidth()), Sema);

399}

400

405

406 if (Lsb >= 0) {

410 IntPart.toString(Str, 10);

411 Str.push_back('.');

412 Str.push_back('0');

413 return;

414 }

415

416 if (Val.isSigned() && Val.isNegative()) {

417 Val = -Val;

418 Val.setIsUnsigned(true);

419 Str.push_back('-');

420 }

421

424

425

426 unsigned Width = std::max(OrigWidth, Scale) + 4;

430

431 IntPart.toString(Str, 10);

432 Str.push_back('.');

433 do {

434 (FractPart * RadixInt)

435 .lshr(Scale)

436 .toString(Str, 10, Val.isSigned());

437 FractPart = (FractPart * RadixInt) & FractPartMask;

438 } while (FractPart != 0);

439}

440

442 OS << "APFixedPoint(" << toString() << ", {";

443 Sema.print(OS);

444 OS << "})";

445}

446

447#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

449#endif

450

453 if (Overflow)

454 *Overflow =

455 (isSigned() && Val != 0) || (isSigned() && Val.isMinSignedValue());

457 }

458

459

460 if (Overflow)

461 *Overflow = false;

462

464 return Val.isMinSignedValue() ? getMax(Sema) : APFixedPoint(-Val, Sema);

465 else

467}

468

470 bool *Overflow) const {

472 unsigned SrcWidth = getWidth();

473

476

477 if (SrcWidth < DstWidth) {

478 Result = Result.extend(DstWidth);

479 } else if (SrcWidth > DstWidth) {

480 DstMin = DstMin.extend(SrcWidth);

481 DstMax = DstMax.extend(SrcWidth);

482 }

483

484 if (Overflow) {

485 if (Result.isSigned() && !DstSign) {

486 *Overflow = Result.isNegative() || Result.ugt(DstMax);

487 } else if (Result.isUnsigned() && DstSign) {

488 *Overflow = Result.ugt(DstMax);

489 } else {

490 *Overflow = Result < DstMin || Result > DstMax;

491 }

492 }

493

494 Result.setIsSigned(DstSign);

495 return Result.extOrTrunc(DstWidth);

496}

497

509

511

512

513

516

517

518

520 while (!Sema.fitsInFloatSemantics(*OpSema))

522

523

524

525

528

529

530

531 (void)S;

532

533

534

535 APFloat ScaleFactor(std::pow(2, Sema.getLsbWeight()));

536 bool Ignored;

537 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);

538 Flt.multiply(ScaleFactor, LosslessRM);

539

540 if (OpSema != &FloatSema)

541 Flt.convert(FloatSema, RM, &Ignored);

542

543 return Flt;

544}

545

548 bool *Overflow) {

550 Value.getBitWidth(), Value.isSigned());

551 return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow);

552}

553

557 bool *Overflow) {

558

559

560

561

564

566

567 if (Value.isNaN()) {

568

569 if (Overflow)

570 *Overflow = true;

572 }

573

574

575

579

581

582 bool Ignored;

583 if (&FloatSema != OpSema)

584 Val.convert(*OpSema, LosslessRM, &Ignored);

585

586

587

588

589

591 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);

592 Val.multiply(ScaleFactor, LosslessRM);

593

594

595

597 Val.convertToInteger(Res, RM, &Ignored);

598

599

600

601

602

603

605 ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);

606 Val.roundToIntegral(RM);

607 Val.multiply(ScaleFactor, LosslessRM);

608

609

610

613 bool Overflowed = false;

615 if (Val > FloatMax)

617 else if (Val < FloatMin)

619 } else {

620 Overflowed = Val > FloatMax || Val < FloatMin;

621 }

622

623 if (Overflow)

624 *Overflow = Overflowed;

625

627}

628

629}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Defines the fixed point number interface.

This file declares a class to represent arbitrary precision floating point values and provide a varie...

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

The APFixedPoint class works similarly to APInt/APSInt in that it is a functional replacement for a s...

LLVM_ABI APFixedPoint convert(const FixedPointSemantics &DstSema, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:42

APFixedPoint(const APInt &Val, const FixedPointSemantics &Sema)

static LLVM_ABI APFixedPoint getMin(const FixedPointSemantics &Sema)

Definition APFixedPoint.cpp:137

LLVM_ABI int compare(const APFixedPoint &Other) const

Definition APFixedPoint.cpp:83

LLVM_ABI APSInt convertToInt(unsigned DstWidth, bool DstSign, bool *Overflow=nullptr) const

Return the integral part of this fixed point number, rounded towards zero.

Definition APFixedPoint.cpp:469

static LLVM_ABI APFixedPoint getFromFloatValue(const APFloat &Value, const FixedPointSemantics &DstFXSema, bool *Overflow=nullptr)

Create an APFixedPoint with a value equal to that of the provided floating point value,...

Definition APFixedPoint.cpp:555

LLVM_ABI APFixedPoint sub(const APFixedPoint &Other, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:221

LLVM_ABI APFloat convertToFloat(const fltSemantics &FloatSema) const

Convert this fixed point number to a floating point value with the provided semantics.

Definition APFixedPoint.cpp:510

LLVM_DUMP_METHOD void dump() const

Definition APFixedPoint.cpp:448

static LLVM_ABI APFixedPoint getFromIntValue(const APSInt &Value, const FixedPointSemantics &DstFXSema, bool *Overflow=nullptr)

Create an APFixedPoint with a value equal to that of the provided integer, and in the same semantics ...

Definition APFixedPoint.cpp:546

std::string toString() const

LLVM_ABI void print(raw_ostream &) const

Definition APFixedPoint.cpp:441

unsigned getWidth() const

LLVM_ABI APFixedPoint negate(bool *Overflow=nullptr) const

Perform a unary negation (-X) on this fixed point type, taking into account saturation if applicable.

Definition APFixedPoint.cpp:451

LLVM_ABI APFixedPoint shl(unsigned Amt, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:366

static LLVM_ABI APFixedPoint getEpsilon(const FixedPointSemantics &Sema)

Definition APFixedPoint.cpp:142

static LLVM_ABI const fltSemantics * promoteFloatSemantics(const fltSemantics *S)

Given a floating point semantic, return the next floating point semantic with a larger exponent and l...

Definition APFixedPoint.cpp:498

LLVM_ABI APFixedPoint div(const APFixedPoint &Other, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:303

LLVM_ABI APFixedPoint mul(const APFixedPoint &Other, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:245

APSInt getIntPart() const

Return the integral part of this fixed point number, rounded towards zero.

LLVM_ABI APFixedPoint add(const APFixedPoint &Other, bool *Overflow=nullptr) const

Definition APFixedPoint.cpp:197

static LLVM_ABI APFixedPoint getMax(const FixedPointSemantics &Sema)

Definition APFixedPoint.cpp:129

static const fltSemantics & IEEEsingle()

static constexpr roundingMode rmTowardZero

llvm::RoundingMode roundingMode

IEEE-754R 4.3: Rounding-direction attributes.

static const fltSemantics & BFloat()

static const fltSemantics & IEEEquad()

static const fltSemantics & IEEEdouble()

static constexpr roundingMode rmNearestTiesToEven

static const fltSemantics & IEEEhalf()

static constexpr roundingMode rmNearestTiesToAway

opStatus

IEEE-754R 7: Default exception handling.

LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)

opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)

opStatus multiply(const APFloat &RHS, roundingMode RM)

Class for arbitrary precision integers.

LLVM_ABI APInt umul_ov(const APInt &RHS, bool &Overflow) const

LLVM_ABI APInt usub_sat(const APInt &RHS) const

LLVM_ABI APInt udiv(const APInt &RHS) const

Unsigned division operation.

static APInt getAllOnes(unsigned numBits)

Return an APInt of a specified width with all bits set.

LLVM_ABI APInt zext(unsigned width) const

Zero extend to a new width.

static LLVM_ABI void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)

LLVM_ABI APInt zextOrTrunc(unsigned width) const

Zero extend or truncate to width.

APInt relativeLShl(int RelativeShift) const

relative logical shift left

LLVM_ABI APInt sadd_sat(const APInt &RHS) const

bool sgt(const APInt &RHS) const

Signed greater than comparison.

LLVM_ABI APInt usub_ov(const APInt &RHS, bool &Overflow) const

bool ugt(const APInt &RHS) const

Unsigned greater than comparison.

bool isZero() const

Determine if this value is zero, i.e. all bits are clear.

unsigned getBitWidth() const

Return the number of bits in the APInt.

bool ult(const APInt &RHS) const

Unsigned less than comparison.

LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const

APInt relativeAShl(int RelativeShift) const

relative arithmetic shift left

LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const

LLVM_ABI APInt uadd_sat(const APInt &RHS) const

LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const

LLVM_ABI APInt sext(unsigned width) const

Sign extend to a new width.

APInt shl(unsigned shiftAmt) const

Left-shift function.

bool isSignBitSet() const

Determine if sign bit of this APInt is set.

bool slt(const APInt &RHS) const

Signed less than comparison.

LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const

static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)

Constructs an APInt value that has a contiguous range of bits set.

LLVM_ABI APInt ssub_sat(const APInt &RHS) const

An arbitrary precision integer that knows its signedness.

APSInt extOrTrunc(uint32_t width) const

static APSInt getMinValue(uint32_t numBits, bool Unsigned)

Return the APSInt representing the minimum integer value with the given bit width and signedness.

static APSInt get(int64_t X)

bool isNegative() const

Determine sign of this APSInt.

static APSInt getMaxValue(uint32_t numBits, bool Unsigned)

Return the APSInt representing the maximum integer value with the given bit width and signedness.

void setIsSigned(bool Val)

APSInt relativeShl(unsigned Amt) const

APSInt extend(uint32_t width) const

The fixed point semantics work similarly to fltSemantics.

static LLVM_ABI FixedPointSemantics getFromOpaqueInt(uint32_t)

Create a FixedPointSemantics object from an integer created via toOpaqueInt().

Definition APFixedPoint.cpp:36

unsigned getWidth() const

bool hasUnsignedPadding() const

unsigned getScale() const

unsigned getIntegralBits() const

Return the number of integral bits represented by these semantics.

LLVM_ABI FixedPointSemantics getCommonSemantics(const FixedPointSemantics &Other) const

Return the FixedPointSemantics that allows for calculating the full precision semantic that can preci...

Definition APFixedPoint.cpp:171

LLVM_ABI void print(llvm::raw_ostream &OS) const

Print semantics for debug purposes.

Definition APFixedPoint.cpp:21

LLVM_ABI bool fitsInFloatSemantics(const fltSemantics &FloatSema) const

Returns true if this fixed-point semantic with its value bits interpreted as an integer can fit in th...

Definition APFixedPoint.cpp:148

bool hasSignOrPaddingBit() const

return true if the first bit doesn't have a strictly positive weight

LLVM_ABI uint32_t toOpaqueInt() const

Convert the semantics to a 32-bit unsigned integer.

Definition APFixedPoint.cpp:32

FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned, bool IsSaturated, bool HasUnsignedPadding)

bool isValidLegacySema() const

Check if the Semantic follow the requirements of an older more limited version of this class.

static FixedPointSemantics GetIntegerSemantics(unsigned Width, bool IsSigned)

Return the FixedPointSemantics for an integer type.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

LLVM Value Representation.

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

To bit_cast(const From &from) noexcept

Used to differentiate between constructors with Width and Lsb from the default Width and scale.