================
@@ -2714,12 +2714,440 @@ static void ClearPadding(CodeGenFunction &CGF, Address 
Src,
   }
 }
 
+/// Lower builtins that operate on ARM64EC's software x87 long double.  The
+/// ones that are required to be exact (fabs, copysign, signbit, isnan, isinf,
+/// isfinite, isnormal, fpclassify) are implemented with integer operations on
+/// the image itself; everything else is evaluated in `double` exactly like the
+/// C library does for its own long double entry points.  Return false when the
+/// builtin does not involve such a value.
+bool CodeGenFunction::EmitSoftX87LongDoubleBuiltin(unsigned BuiltinID,
+                                                   const CallExpr *E,
+                                                   RValue &Result) {
+  // The 'nan' and 'inf' families produce a `long double`, so they do not
+  // consume one but do need the integer image constructed below: they are the
+  // only builtins that yield a constant.  Match the bare name, since some of
+  // them are also reachable with a `__builtin_` prefix.
+  std::string Name = getContext().BuiltinInfo.getName(BuiltinID);
+  StringRef BaseName = Name;
+  BaseName.consume_front("__builtin_");
+  bool ProducesLongDouble = false;
+  for (const char *Str : {"nanl", "nansl", "infl", "huge_vall"})
+    ProducesLongDouble |= BaseName == Str;
+
+  // Everything below rewrites a call into its binary64 equivalent, which only
+  // makes sense when a `long double` is *consumed*.
+  bool ConsumesLongDouble = false;
+  for (const Expr *Arg : E->arguments()) {
+    QualType Ty = Arg->getType();
+    if (const auto *CTy = Ty->getAs<ComplexType>())
+      Ty = CTy->getElementType();
+    ConsumesLongDouble |= Ty->isSpecificBuiltinType(BuiltinType::LongDouble);
+  }
+
+  if (!ProducesLongDouble && !ConsumesLongDouble)
+    return false;
+
+  // `fabsl`: Set the sign bit to zero.
+  if (BaseName == "fabsl") {
+    if (!E->getType()->isSpecificBuiltinType(BuiltinType::LongDouble))
+      return false;
+    llvm::Value *V = EmitScalarExpr(E->getArg(0));
+    llvm::Constant *MagnitudeMask = llvm::ConstantInt::get(
+        V->getType(), ~llvm::APInt::getOneBitSet(128, 79));
+    Result = RValue::get(Builder.CreateAnd(V, MagnitudeMask));
+    return true;
+  }
+
+  // `copysignl`: Take the magnitude from the first operand and the sign bit
+  // from the second one.
+  if (BaseName == "copysignl") {
+    if (!E->getType()->isSpecificBuiltinType(BuiltinType::LongDouble))
+      return false;
+    llvm::Value *X = EmitScalarExpr(E->getArg(0));
+    llvm::Value *Y = EmitScalarExpr(E->getArg(1));
+    llvm::Constant *MagnitudeMask = llvm::ConstantInt::get(
+        X->getType(), ~llvm::APInt::getOneBitSet(128, 79));
+    llvm::Value *Magnitude = Builder.CreateAnd(X, MagnitudeMask);
+    llvm::Value *Sign = Builder.CreateAnd(Y, Builder.CreateNot(MagnitudeMask));
+    Result = RValue::get(Builder.CreateOr(Magnitude, Sign));
+    return true;
+  }
+
+  // `signbit`: Take the sign bit and normalize it to boolean.
+  if (Name == "__builtin_signbit" || BaseName == "signbitl") {
+    if (!E->getArg(0)->getType()->isSpecificBuiltinType(
+            BuiltinType::LongDouble))
+      return false;
+    llvm::Value *V = EmitScalarExpr(E->getArg(0));
+    llvm::Value *Sign =
+        Builder.CreateTrunc(Builder.CreateLShr(V, 79), Builder.getInt1Ty());
+    Result = RValue::get(Builder.CreateZExt(Sign, ConvertType(E->getType())));
+    return true;
+  }
+
+  // `__builtin_isnan`: Check if the value is a NaN.  An unnormal or pseudo
+  // denormal image is undefined behavior, since it will never be produced in a
+  // constant expression.
+  if (Name == "__builtin_isnan") {
+    if (!E->getArg(0)->getType()->isSpecificBuiltinType(
+            BuiltinType::LongDouble))
+      return false;
+    llvm::Value *V = EmitScalarExpr(E->getArg(0));
+    llvm::Constant *MagnitudeMask = llvm::ConstantInt::get(
+        V->getType(), ~llvm::APInt::getOneBitSet(128, 79));
----------------
lhmouse wrote:

Fixed in 29da274f4cd33a80e943a3f0316fc5ecda624e7e.

https://github.com/llvm/llvm-project/pull/237057
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to