Skip to content

Commit 8100374

Browse files
committed
[flang] Don't force SET_EXPONENT(I=...) argument to integer(4)
The implementation of the folding code for SET_EXPONENT() was written in such a fashion as to convert the I= actual argument value to a 32-bit integer. Which is usually not a problem, but it's not always correct and a test case ran into trouble with it. Fix to allow any kind of INTEGER without conversion. Differential Revision: https://reviews.llvm.org/D135203
1 parent eac3e5c commit 8100374

File tree

3 files changed

+24
-13
lines changed

3 files changed

+24
-13
lines changed

flang/include/flang/Evaluate/real.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class Real : public common::RealDetails<PREC> {
170170
static constexpr int MINEXPONENT{2 - exponentBias};
171171
Real RRSPACING() const;
172172
Real SPACING() const;
173-
Real SET_EXPONENT(int) const;
173+
Real SET_EXPONENT(std::int64_t) const;
174174
Real FRACTION() const;
175175

176176
// SCALE(); also known as IEEE_SCALB and (in IEEE-754 '08) ScaleB.
@@ -182,16 +182,20 @@ class Real : public common::RealDetails<PREC> {
182182
// be subnormal.)
183183
auto adjust{exponentBias + binaryPrecision - 1};
184184
auto expo{adjust + by.ToInt64()};
185+
Real twoPow;
186+
RealFlags flags;
187+
int rMask{1};
185188
if (IsZero()) {
186189
expo = exponentBias; // ignore by, don't overflow
187190
} else if (by > INT{maxExponent}) {
188191
expo = maxExponent + binaryPrecision - 1;
189-
} else if (by < INT{-adjust}) {
190-
expo = -1;
192+
} else if (by < INT{-adjust}) { // underflow
193+
expo = 0;
194+
rMask = 0;
195+
flags.set(RealFlag::Underflow);
191196
}
192-
Real twoPow;
193-
RealFlags flags{
194-
twoPow.Normalize(false, static_cast<int>(expo), Fraction::MASKR(1))};
197+
flags |=
198+
twoPow.Normalize(false, static_cast<int>(expo), Fraction::MASKR(rMask));
195199
ValueWithRealFlags<Real> result{Multiply(twoPow, rounding)};
196200
result.flags |= flags;
197201
return result;

flang/lib/Evaluate/fold-real.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,18 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
257257
byExpr->u);
258258
}
259259
} else if (name == "set_exponent") {
260-
return FoldElementalIntrinsic<T, T, Int4>(context, std::move(funcRef),
261-
ScalarFunc<T, T, Int4>(
262-
[&](const Scalar<T> &x, const Scalar<Int4> &i) -> Scalar<T> {
263-
return x.SET_EXPONENT(i.ToInt64());
264-
}));
260+
if (const auto *iExpr{UnwrapExpr<Expr<SomeInteger>>(args[1])}) {
261+
return common::visit(
262+
[&](const auto &iVal) {
263+
using TY = ResultType<decltype(iVal)>;
264+
return FoldElementalIntrinsic<T, T, TY>(context, std::move(funcRef),
265+
ScalarFunc<T, T, TY>(
266+
[&](const Scalar<T> &x, const Scalar<TY> &i) -> Scalar<T> {
267+
return x.SET_EXPONENT(i.ToInt64());
268+
}));
269+
},
270+
iExpr->u);
271+
}
265272
} else if (name == "sign") {
266273
return FoldElementalIntrinsic<T, T, T>(
267274
context, std::move(funcRef), &Scalar<T>::SIGN);

flang/lib/Evaluate/real.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,15 +756,15 @@ template <typename W, int P> Real<W, P> Real<W, P>::SPACING() const {
756756

757757
// 16.9.171
758758
template <typename W, int P>
759-
Real<W, P> Real<W, P>::SET_EXPONENT(int expo) const {
759+
Real<W, P> Real<W, P>::SET_EXPONENT(std::int64_t expo) const {
760760
if (IsNotANumber()) {
761761
return *this;
762762
} else if (IsInfinite()) {
763763
return NotANumber();
764764
} else if (IsZero()) {
765765
return *this;
766766
} else {
767-
return SCALE(Integer<32>(expo - UnbiasedExponent() - 1)).value;
767+
return SCALE(Integer<64>(expo - UnbiasedExponent() - 1)).value;
768768
}
769769
}
770770

0 commit comments

Comments
 (0)