Skip to content

Conversation

@vfdff
Copy link
Contributor

@vfdff vfdff commented Jul 24, 2024

Follow #96025, except expf, more FP math libcalls in libm should also be supported.

Fix #86635

Follow PR96025, except expf, more FP math libcalls in libm
should also be supported.

Fix llvm#86635
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Jul 24, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 24, 2024

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Allen (vfdff)

Changes

Follow PR96025, except expf, more FP math libcalls in libm should also be supported.

Fix #86635


Full diff: https://github.com/llvm/llvm-project/pull/100302.diff

1 Files Affected:

  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+7-8)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a0d03b87ccdc9..a9696ebe61e3a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -692,23 +692,22 @@ static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
   RValue Call =
       CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
 
-  // Check the supported intrinsic.
+  ASTContext &Context = CGF.getContext();
   if (unsigned BuiltinID = FD->getBuiltinID()) {
     auto IsErrnoIntrinsic = [&]() -> unsigned {
-      switch (BuiltinID) {
-      case Builtin::BIexpf:
-      case Builtin::BI__builtin_expf:
-      case Builtin::BI__builtin_expf128:
+      // Check whether a FP math builtin function, such as BI__builtin_expf
+      QualType ResultTy = FD->getReturnType();
+      bool IsMathLibCall =
+          Context.BuiltinInfo.isLibFunction(BuiltinID) ||
+          Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID);
+      if (IsMathLibCall && CGF.ConvertType(ResultTy)->isFloatingPointTy())
         return true;
-      }
-      // TODO: support more FP math libcalls
       return false;
     }();
 
     // Restrict to target with errno, for example, MacOS doesn't set errno.
     if (IsErrnoIntrinsic && CGF.CGM.getLangOpts().MathErrno &&
         !CGF.Builder.getIsFPConstrained()) {
-      ASTContext &Context = CGF.getContext();
       // Emit "int" TBAA metadata on FP math libcalls.
       clang::QualType IntTy = Context.IntTy;
       TBAAAccessInfo TBAAInfo = CGF.CGM.getTBAAAccessInfo(IntTy);

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs tests

@vfdff
Copy link
Contributor Author

vfdff commented Jul 24, 2024

Needs tests

Add a new test foo_fabs, and the prior test foo is also works, thanks

// Check the supported intrinsic.
ASTContext &Context = CGF.getContext();
if (unsigned BuiltinID = FD->getBuiltinID()) {
auto IsErrnoIntrinsic = [&]() -> unsigned {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name here IsErrnoIntrinsic is incorrect for fabs which cannot set errno

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, your are right, so maybe list them one by one ?

bool IsMathLibCall =
Context.BuiltinInfo.isLibFunction(BuiltinID) ||
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID);
if (IsMathLibCall && CGF.ConvertType(ResultTy)->isFloatingPointTy())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These conditions do not imply it sets errno. Also this can be return of boolean expression

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to get the floating-point interface from libc/libm, so I has extra constraints **CGF.ConvertType(ResultTy)->isFloatingPointTy() guarding the return type" and CGF.CGM.getLangOpts().MathErrno guarding the errno in the following line 709.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The errno-ness is already a builtin property you should be able to query from BuiltinInfo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although in the context of this patch, I don't see why any of this is relevant for emitting TBAA

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the builtin which doesn't set errno is sure not need add extra TBAA, the origin intend is address these builtins may set errno, such as expf, so we emit "int" TBAA metadata on them will make sure it is safe to reuse the float value from memory.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So check isConstWithoutErrnoAndExceptions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No , we expect it works without explicit disable the MathErrno, just similar to the behavior of gcc, https://gcc.godbolt.org/z/rsbqsGWMv. it is discussed on discourse

Copy link
Contributor Author

@vfdff vfdff Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you are right, I see your idea, the expect list can be get by isConstWithoutErrnoAndExceptions, thanks

@vfdff vfdff requested a review from arsenm July 27, 2024 10:44
bool ConstWithoutErrnoAndExceptions =
Context.BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID);
if (ConstWithoutErrnoAndExceptions &&
CGF.ConvertType(ResultTy)->isFloatingPointTy())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isFloatingPointTy check should be unnecessary. You can then just remove the whole lambda and directly check isConstWithoutErrnoAndExceptions

double tmp = expm2 * num[10];
return tmp;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test a few more functions for good measure? Also test some cases with out arguments, like frexp.

Also test sincos? it has out float arguments so I'm not sure you apply this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add the extra frexp and sincos, but find that both of them don't generate tbaa info with this PR.
a) frexp is similar to fabs, it is not subject to any errors
b) sincos is not a builtin function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

frexp isn't subject to any errors, but also writes to its int pointer out argument, so it could

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, thanks, I'll adjust Negative test to TODO

//
extern "C" float foo (float num[], float r2inv, int n) {
const float expm2 = expf(num[10]); // Emit TBAA metadata on @expf
extern "C" float foo (float num[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also just make this a C test instead of all the extern Cs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks

Comment on lines 701 to 702
if (ConstWithoutErrnoAndExceptions && CGF.CGM.getLangOpts().MathErrno &&
!CGF.Builder.getIsFPConstrained()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this the last check in this expression

// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[COS]]) #[[ATTR9]]
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[NUM]], i64 8
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]]
// CHECK-NEXT: call void @sincos(float noundef [[TMP0]], ptr noundef nonnull [[SIN]], ptr noundef nonnull [[COS]]) #[[ATTR9]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sincos can set errno, so I'm not sure how this managed to skip the tbaa check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the checking callee.isBuiltin() , so need another patch to add sincos as a buildin ?

if (callee.isBuiltin()) {

@vfdff
Copy link
Contributor Author

vfdff commented Jul 30, 2024

If a builtin return a complex type, then it can not be convert into a Instruction* type, so add a new restriction Call.isScalar()

// CHECK-NEXT: ret float [[MUL]]
//
float foo (float num[]) {
const float expm2 = expf(num[10]); // Emit TBAA metadata on @expf
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also test with __builtin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, add foo_buildin

ASTContext &Context = CGF.getContext();
// TODO: Support builtin function with complex type returned, eg: cacosh
if (ConstWithoutErrnoAndExceptions && CGF.CGM.getLangOpts().MathErrno &&
!CGF.Builder.getIsFPConstrained() && Call.isScalar()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need test with the complex type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, add foo_cacoshf

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with test cleanup

// CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], [[CALL]]
// CHECK-NEXT: ret float [[MUL]]
//
float foo_buildin (float num[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix testname. Typo building, and name the function tested instead of just having a foo suffix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply your comment, thanks.

// CHECK-NEXT: [[MUL:%.*]] = fmul double [[TMP0]], [[CALL]]
// CHECK-NEXT: ret double [[MUL]]
//
double foo_remainder (double num[], double a) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the foos

Copy link
Contributor Author

@vfdff vfdff Jul 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the function name remove the foo suffix will conflict to the related math library name, so do you mean adjust the test function name foo_expf to _expf for example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about "test"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks

Comment on lines 3 to 4
// RUN: %clang_cc1 -triple=aarch64-unknown-linux-gnu -fmath-errno -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,NoNewStructPathTBAA
// RUN: %clang_cc1 -triple=aarch64-unknown-linux-gnu -fmath-errno -O3 -new-struct-path-tbaa -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,NewStructPathTBAA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually check prefixes are all caps

@vfdff vfdff merged commit 9589c12 into llvm:main Jul 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aarch64] Prefer use callee save register to avoid repeat load when cross call

3 participants