Skip to content

Commit 7ff1043

Browse files
committed
Added Floating Point Support and Test Case
1 parent b48993d commit 7ff1043

File tree

3 files changed

+69
-25
lines changed

3 files changed

+69
-25
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,17 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
598598
return true;
599599
}
600600

601+
static inline Floating abs(InterpState &S, const Floating &In) {
602+
if (!In.isNegative())
603+
return In;
604+
605+
Floating Output = S.allocFloat(In.getSemantics());
606+
APFloat New = In.getAPFloat();
607+
New.changeSign();
608+
Output.copy(New);
609+
return Output;
610+
}
611+
601612
// The C standard says "fabs raises no floating-point exceptions,
602613
// even if x is a signaling NaN. The returned value is independent of
603614
// the current rounding direction mode." Therefore constant folding can
@@ -606,16 +617,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
606617
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
607618
const InterpFrame *Frame) {
608619
const Floating &Val = S.Stk.pop<Floating>();
609-
APFloat F = Val.getAPFloat();
610-
if (!F.isNegative()) {
611-
S.Stk.push<Floating>(Val);
612-
return true;
613-
}
614-
615-
Floating Result = S.allocFloat(Val.getSemantics());
616-
F.changeSign();
617-
Result.copy(F);
618-
S.Stk.push<Floating>(Result);
620+
S.Stk.push<Floating>(abs(S, Val));
619621
return true;
620622
}
621623

@@ -1690,19 +1692,23 @@ static bool interp__builtin_elementwise_abs(InterpState &S, CodePtr OpPC,
16901692
const InterpFrame *Frame,
16911693
const CallExpr *Call,
16921694
unsigned BuiltinID) {
1693-
// FIXME: add support of floating point
1694-
assert(!Call->getArg(0)->getType()->isFloatingType() &&
1695-
"floating point is currently not supported");
1696-
16971695
assert(Call->getNumArgs() == 1);
1698-
if (Call->getArg(0)->getType()->isIntegerType()) {
1696+
QualType Ty = Call->getArg(0)->getType();
1697+
if (Ty->isIntegerType()) {
16991698
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
17001699
APSInt Val = popToAPSInt(S.Stk, ArgT);
17011700

17021701
pushInteger(S, Val.abs(), Call->getType());
17031702
return true;
17041703
}
17051704

1705+
if (Ty->isFloatingType()) {
1706+
Floating Val = S.Stk.pop<Floating>();
1707+
Floating Result = abs(S, Val);
1708+
S.Stk.push<Floating>(Result);
1709+
return true;
1710+
}
1711+
17061712
// Otherwise, the argument must be a vector.
17071713
assert(Call->getArg(0)->getType()->isVectorType());
17081714
const Pointer &Arg = S.Stk.pop<Pointer>();
@@ -1715,14 +1721,18 @@ static bool interp__builtin_elementwise_abs(InterpState &S, CodePtr OpPC,
17151721
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
17161722
PrimType ElemT = *S.getContext().classify(ElemType);
17171723
unsigned NumElems = Arg.getNumElems();
1718-
1719-
// FIXME: Reading from uninitialized vector elements?
1724+
// we can either have a vector of integer or a vector of floating point
17201725
for (unsigned I = 0; I != NumElems; ++I) {
1721-
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1722-
Dst.elem<T>(I) = T::from(static_cast<T>(
1723-
APSInt(Arg.elem<T>(I).toAPSInt().abs(),
1724-
ElemType->isUnsignedIntegerOrEnumerationType())));
1725-
});
1726+
if (ElemType->isIntegerType()) {
1727+
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1728+
Dst.elem<T>(I) = T::from(static_cast<T>(
1729+
APSInt(Arg.elem<T>(I).toAPSInt().abs(),
1730+
ElemType->isUnsignedIntegerOrEnumerationType())));
1731+
});
1732+
} else {
1733+
Floating Val = Arg.elem<Floating>(I);
1734+
Dst.elem<Floating>(I) = abs(S, Val);
1735+
}
17261736
}
17271737
Dst.initializeAllElements();
17281738

clang/lib/AST/ExprConstant.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11610,7 +11610,6 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1161011610
switch (E->getBuiltinCallee()) {
1161111611
default:
1161211612
return false;
11613-
case Builtin::BI__builtin_elementwise_abs:
1161411613
case Builtin::BI__builtin_elementwise_popcount:
1161511614
case Builtin::BI__builtin_elementwise_bitreverse: {
1161611615
APValue Source;
@@ -11646,6 +11645,28 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1164611645

1164711646
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
1164811647
}
11648+
case Builtin::BI__builtin_elementwise_abs: {
11649+
APValue Source;
11650+
if (!EvaluateAsRValue(Info, E->getArg(0), Source))
11651+
return false;
11652+
11653+
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11654+
unsigned SourceLen = Source.getVectorLength();
11655+
SmallVector<APValue, 4> ResultElements;
11656+
ResultElements.reserve(SourceLen);
11657+
11658+
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11659+
APValue CurrentEle = Source.getVectorElt(EltNum);
11660+
APValue Val = DestEltTy->isFloatingType()
11661+
? APValue(llvm::abs(CurrentEle.getFloat()))
11662+
: APValue(APSInt(
11663+
CurrentEle.getInt().abs(),
11664+
DestEltTy->isUnsignedIntegerOrEnumerationType()));
11665+
ResultElements.push_back(Val);
11666+
}
11667+
11668+
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11669+
}
1164911670

1165011671
case Builtin::BI__builtin_elementwise_add_sat:
1165111672
case Builtin::BI__builtin_elementwise_sub_sat:
@@ -15894,6 +15915,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
1589415915
return Error(E);
1589515916
return true;
1589615917

15918+
case Builtin::BI__builtin_elementwise_abs:
1589715919
case Builtin::BI__builtin_fabs:
1589815920
case Builtin::BI__builtin_fabsf:
1589915921
case Builtin::BI__builtin_fabsl:

clang/test/Sema/constant-builtins-vector.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -880,5 +880,17 @@ static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_min((
880880
static_assert(__builtin_elementwise_abs(10) == 10);
881881
static_assert(__builtin_elementwise_abs(-10) == 10);
882882
static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_abs((vector4char){-1, -2, -3, 4})) == (LITTLE_END ? 0x04030201 : 0x01020304));
883-
// the absolute value of the most negative integer remains the most negative integer
884-
static_assert(__builtin_elementwise_abs((int)(-2147483648)) == (int)(-2147483648));
883+
static_assert(__builtin_elementwise_abs((int)(-2147483648)) == (int)(-2147483648)); // the absolute value of the most negative integer remains the most negative integer
884+
885+
// check floating point for elementwise abs
886+
#define CHECK_FOUR_FLOAT_VEC(vec1, vec2) \
887+
static_assert(__builtin_fabs(vec1[0] - vec2[0]) < 1e-6); \
888+
static_assert(__builtin_fabs(vec1[1] - vec2[1]) < 1e-6); \
889+
static_assert(__builtin_fabs(vec1[2] - vec2[2]) < 1e-6); \
890+
static_assert(__builtin_fabs(vec1[3] - vec2[3]) < 1e-6);
891+
892+
// checking floating point vector
893+
CHECK_FOUR_FLOAT_VEC(__builtin_elementwise_abs((vector4float){-1.123, 2.123, -3.123, 4.123}), ((vector4float){1.123, 2.123, 3.123, 4.123}))
894+
CHECK_FOUR_FLOAT_VEC(__builtin_elementwise_abs((vector4double){-1.123, 2.123, -3.123, 4.123}), ((vector4double){1.123, 2.123, 3.123, 4.123}))
895+
static_assert(__builtin_elementwise_abs((float)-1.123) - (float)1.123 < 1e-6); // making sure one element works
896+
#undef CHECK_FOUR_FLOAT_VEC

0 commit comments

Comments
 (0)