Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][CodeGen] Loose the cast check when emitting builtins #81669

Merged
merged 1 commit into from
Feb 14, 2024

Conversation

shiltian
Copy link
Contributor

This patch looses the cast check (canLosslesslyBitCastTo) and leaves it to the
one inside CreateBitCast. It seems too conservative for the use case here.

This patch looses the cast check (`canLosslesslyBitCastTo`) and leaves it to the
one inside `CreateBitCast`. It seems too conservative for the use case here.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen labels Feb 13, 2024
@shiltian shiltian requested a review from arsenm February 13, 2024 21:43
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 13, 2024

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Shilei Tian (shiltian)

Changes

This patch looses the cast check (canLosslesslyBitCastTo) and leaves it to the
one inside CreateBitCast. It seems too conservative for the use case here.


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

1 Files Affected:

  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (-4)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index ee0b7504769622..9bc60466d09be6 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5912,8 +5912,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
           }
         }
 
-        assert(ArgValue->getType()->canLosslesslyBitCastTo(PTy) &&
-               "Must be able to losslessly bit cast to param");
         // Cast vector type (e.g., v256i32) to x86_amx, this only happen
         // in amx intrinsics.
         if (PTy->isX86_AMXTy())
@@ -5943,8 +5941,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
         }
       }
 
-      assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
-             "Must be able to losslessly bit cast result type");
       // Cast x86_amx to vector type (e.g., v256i32), this only happen
       // in amx intrinsics.
       if (V->getType()->isX86_AMXTy())

@efriedma-quic
Copy link
Collaborator

I can't tell what you're trying to fix here. Is this fixing a crash? Or is the check redundant? Or is it necessary for some followup change you want to make?

@shiltian
Copy link
Contributor Author

I can't tell what you're trying to fix here. Is this fixing a crash? Or is the check redundant? Or is it necessary for some followup change you want to make?

Sorry, I should have clearly mentioned that. Yes, it is for my followup change #80908. In #80908, we changed the type of LLVM builtin but kept the corresponding clang builtin unchanged to avoid breaking existing uses. Specifically, the original builtin accepts some bfloat arguments (either bfloat or <2 x bfloat>) and returns a bfloat value. Because of some historic reasons, the builtin uses i16 to represent bfloat values, and the backend just treats the 16 bits as bfloat. Now we encountered some issues that motivated us to use the right type here, but we still want to maintain sort of backward compatibility, at least on user-facing level. Keeping the corresponding clang builtin unchanged is the path we chose. Given that, it requires the front end to emit corresponding bitcast because the type i16 and bfloat (and the vec type) are not matched. EmitBuiltinExpr is capable of doing that, but the bitcast check here prevents it from doing it. canLosslesslyBitCastTo doesn't think bitcast from i16 to bf16 and vice versa are lossless. I was thinking of just allowing this specific cast in canLosslesslyBitCastTo but I figured that doesn't look very good. On a second thought, it looks like the check here is too conservative.

@arsenm
Copy link
Contributor

arsenm commented Feb 14, 2024

Sorry, I should have clearly mentioned that. Yes, it is for my followup change #80908. In #80908, we changed the type of LLVM builtin but kept the corresponding clang builtin unchanged to avoid breaking existing uses.

Don't see how that could be related; you can losslessly bitconvert between i16 and bfloat

@Pierre-vh
Copy link
Contributor

Sorry, I should have clearly mentioned that. Yes, it is for my followup change #80908. In #80908, we changed the type of LLVM builtin but kept the corresponding clang builtin unchanged to avoid breaking existing uses.

Don't see how that could be related; you can losslessly bitconvert between i16 and bfloat

I guess it's an oversight from that function to not allow FP <-> INT casts when they have the same width?
It seems like it'd let <4 x i16> to <4 x bf16> pass.

I think the right fix is teaching that function about FP <-> INT casts.
What do you think @nikic ?

@nikic
Copy link
Contributor

nikic commented Feb 14, 2024

I think the right fix is teaching that function about FP <-> INT casts.

The documentation for that function says:

  /// Return true if this type could be converted with a lossless BitCast to
  /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
  /// same size only where no re-interpretation of the bits is done.

A cast between float and int sounds like "re-interpretation of the bits" to me. Though the function already allows it if it's a vector of int/float.

TBH I don't really understand what the purpose of this function is. One of the main uses seems to be to restrict what the returned attribute can be used for, but in that case we probably should stop accepting casts at all -- these don't really seem useful, and we've had crashes/miscompiles due to allowing them in the past.

For the purposes of this specific change, I think that just dropping the assert is indeed the right thing to do. The cast in the bitcast itself is sufficient.

@shiltian
Copy link
Contributor Author

Don't see how that could be related; you can losslessly bitconvert between i16 and bfloat

Yes, canLosslesslyBitCastTo doesn't allow cast between i16 and bfloat, but it does between two vectors, as long as their sizes are the same.

A cast between float and int sounds like "re-interpretation of the bits" to me. Though the function already allows it if it's a vector of int/float.

Yeah. I was reluctant to allow it in canLosslesslyBitCastTo also because of that. Since it allows vector conversion, it already breaks the purpose.

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

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

LGTM

(It feels a little weird that the types in the clang AST don't actually match the LLVM builtin, but I guess it's not likely to actually cause any issues.)

@shiltian shiltian merged commit 630f82e into llvm:main Feb 14, 2024
6 of 7 checks passed
@shiltian shiltian deleted the loose_cast_restriction branch February 14, 2024 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants