[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())));
----------------
zygoloid wrote:

```suggestion
      llvm::APInt Elt = SValInt.extractBits(FloatEltSize, (BigEndian ? NElts - i - 1 : i) * EltSize));
      Elts.push_back(APValue(APSInt(std::move(Elt), !EltTy->isSignedIntegerType())));
```
As above, but also `std::move` the `APInt` into the `APSInt` to avoid another heap allocation if the element size is > 64 bits.

https://github.com/llvm/llvm-project/pull/66894


More information about the cfe-commits mailing list