[clang] [clang] Implement constexpr bit_cast for vectors (PR #66894)
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 27 17:34:16 PDT 2023
================
@@ -2732,6 +2732,92 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E,
return true;
}
+static bool BitcastAPIntToVector(EvalInfo &Info, const VectorType *VTy,
+ const llvm::APInt &SValInt,
+ SmallVectorImpl<APValue> &Elts) {
+ QualType EltTy = VTy->getElementType();
+ unsigned NElts = VTy->getNumElements();
+ unsigned EltSize =
+ VTy->isExtVectorBoolType() ? 1 : Info.Ctx.getTypeSize(EltTy);
+
+ if ((NElts * EltSize) % Info.Ctx.getCharWidth() != 0) {
+ // The vector's size in bits is not a multiple of the target's byte size,
+ // so its layout is unspecified. For now, we'll simply treat these cases as
+ // unsupported (this should only be possible with OpenCL bool vectors whose
+ // element count isn't a multiple of the byte size).
+ return false;
+ }
+
+ Elts.reserve(NElts);
+ bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian();
+ if (EltTy->isRealFloatingType()) {
+ const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy);
+ unsigned FloatEltSize = EltSize;
+ if (&Sem == &APFloat::x87DoubleExtended())
+ FloatEltSize = 80;
+ for (unsigned i = 0; i < NElts; i++) {
+ llvm::APInt Elt;
+ if (BigEndian)
+ Elt = SValInt.rotl(i * EltSize + FloatEltSize).trunc(FloatEltSize);
+ else
+ Elt = SValInt.rotr(i * EltSize).trunc(FloatEltSize);
+ Elts.push_back(APValue(APFloat(Sem, Elt)));
+ }
+ } else if (EltTy->isIntegerType()) {
+ for (unsigned i = 0; i < NElts; i++) {
+ llvm::APInt Elt;
+ if (BigEndian)
+ Elt = SValInt.rotl(i * EltSize + EltSize).zextOrTrunc(EltSize);
+ else
+ Elt = SValInt.rotr(i * EltSize).zextOrTrunc(EltSize);
+ Elts.push_back(APValue(APSInt(Elt, !EltTy->isSignedIntegerType())));
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static bool BitcastVectorToAPInt(EvalInfo &Info, const VectorType *VTy,
+ const APValue &SVal, llvm::APInt &Res) {
+ QualType EltTy = VTy->getElementType();
+ unsigned NElts = VTy->getNumElements();
+ unsigned EltSize =
+ VTy->isExtVectorBoolType() ? 1 : Info.Ctx.getTypeSize(EltTy);
+ unsigned VecSize = Info.Ctx.getTypeSize(VTy);
+
+ if ((NElts * EltSize) % Info.Ctx.getCharWidth() != 0) {
+ // The vector's size in bits is not a multiple of the target's byte size,
+ // so its layout is unspecified. For now, we'll simply treat these cases as
+ // unsupported (this should only be possible with OpenCL bool vectors whose
+ // element count isn't a multiple of the byte size).
+ return false;
+ }
+
+ bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian();
+ Res = llvm::APInt::getZero(VecSize);
+ for (unsigned i = 0; i < SVal.getVectorLength(); i++) {
+ const APValue &Elt = SVal.getVectorElt(i);
+ llvm::APInt EltAsInt;
+ if (Elt.isInt()) {
+ EltAsInt = Elt.getInt();
+ } else if (Elt.isFloat()) {
+ EltAsInt = Elt.getFloat().bitcastToAPInt();
+ } else {
+ // Don't try to handle vectors of anything other than int or float
+ // (not sure if it's possible to hit this case).
+ return false;
+ }
+ unsigned BaseEltSize = EltAsInt.getBitWidth();
+ if (BigEndian)
+ Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i * EltSize + BaseEltSize);
+ else
+ Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i * EltSize);
----------------
zygoloid wrote:
```suggestion
Res.insertBits(EltAsInt, BigEndian ? (NElts - i) * EltSize - BaseEltSize : i * EltSize);
```
Avoid another heap allocation.
https://github.com/llvm/llvm-project/pull/66894
More information about the cfe-commits
mailing list