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

[CIR] [CodeGen] Introduce IsFPClassOp to support builtin_isfpclass #971

Merged
merged 1 commit into from
Oct 21, 2024

Conversation

ChuanqiXu9
Copy link
Member

The llvm's intrinsic llvm.is.fpclass is used to support multiple float point builtins: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass

The __builtin_isfpclass() builtin is a generalization of functions
isnan, isinf, isfinite and some others defined by the C standard. It tests
if the floating-point value, specified by the first argument, falls into
any of data classes, specified by the second argument.

I meant to support this by creating IntrinsicCallOp directly. But I can't make it due to #480 since the return type of the intrinsic will mismatch. So I have to create a new Op for it. But I feel it might not be too bad. At least it is more explicit and more expressive.

clang/include/clang/CIR/Dialect/IR/CIROps.td Outdated Show resolved Hide resolved
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp Outdated Show resolved Hide resolved
clang/include/clang/CIR/Dialect/IR/CIRTypes.td Outdated Show resolved Hide resolved
Copy link

github-actions bot commented Oct 15, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@Lancern Lancern left a comment

Choose a reason for hiding this comment

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

One last nit and the rest of this PR LGTM!

clang/include/clang/CIR/Dialect/IR/CIROps.td Outdated Show resolved Hide resolved
@ghehg
Copy link
Collaborator

ghehg commented Oct 16, 2024

The llvm's intrinsic llvm.is.fpclass is used to support multiple float point builtins: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass

The __builtin_isfpclass() builtin is a generalization of functions
isnan, isinf, isfinite and some others defined by the C standard. It tests
if the floating-point value, specified by the first argument, falls into
any of data classes, specified by the second argument.

I meant to support this by creating IntrinsicCallOp directly. But I can't make it due to #480 since the return type of the intrinsic will mismatch. So I have to create a new Op for it. But I feel it might not be too bad. At least it is more explicit and more expressive.

Thank you for looking into the issue! Really glad you are offering a hand to tackle builtins and intrinsics.
However, I believe it is still better to just use IntrinsicCallOp, not introducing new CIR Op.
The thing is, if the only problem is intrinsic function signature mismatch, we could always work around at LLVM Lowering, instead of introducing a new type of OP to solve the problem.
For example, we could call getI1Type during lowering to give i1 result type and choose mlir::LLVM::IsFPClass during lowering.
You might feel uncomfortable giving special ad-hoc treatment in LLVM lowering, but creating a CIR OP just for a specific intrinsic (there are many such intrinsic ops in LLVM dialect, I doubt if we want have 1-1 match of them in CIR) is much more of special ad-hoc treatment.
That being said, changes to CIRTypes.td is very good and needed by itself!

@ghehg ghehg self-requested a review October 16, 2024 02:14
ghehg
ghehg previously requested changes Oct 16, 2024
Copy link
Collaborator

@ghehg ghehg left a comment

Choose a reason for hiding this comment

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

I'd like us try to use IntrinsicCallOp instead of introducing new CIR Op.
details below.
#971 (comment)

@ChuanqiXu9
Copy link
Member Author

You might feel uncomfortable giving special ad-hoc treatment in LLVM lowering, but creating a CIR OP just for a specific intrinsic (there are many such intrinsic ops in LLVM dialect, I doubt if we want have 1-1 match of them in CIR) is much more of special ad-hoc treatment.

@ghehg in mlir, we have https://github.com/llvm/llvm-project/blob/bb89988174e5f1a9a419637cadae07e4e8c61c3e/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td#L103-L107

So I think it makes sense to match their structure there and I think a new CIR Op maybe helpful to improve the readability and more expressive.

@bcardosolopes
Copy link
Member

bcardosolopes commented Oct 16, 2024

@ghehg thanks for the review. I think I see where you come from for the general point of view, but this sounds like a nice abstraction (and it already covers a bunch of other builtins). The level of abstraction that @ChuanqiXu9 picked feels good to me. I'm also a bit confused with your suggestion for using IntrinsicCallOp given that LLVM even has a specialized instruction to lower this: mlir::LLVM::IsFPClass, given that IntrinsicCallOp is usually a handy for 1-1 to actual LLVM intrinsic calls (not the case here).

@ghehg
Copy link
Collaborator

ghehg commented Oct 16, 2024

@ghehg thanks for the review. I think I see where you come from for the general point of view, but this sounds like a nice abstraction (and it already covers a bunch of other builtins). The level of abstraction that @ChuanqiXu9 picked feels good to me. I'm also a bit confused with your suggestion for using IntrinsicCallOp given that LLVM even has a specialized instruction to lower this: mlir::LLVM::IsFPClass, given that IntrinsicCallOp is usually a handy for 1-1 to actual LLVM intrinsic calls (not the case here).

Oh, sorry for IntrinsicCallOp confusion ( I probably should change the name of CIR::IntrinsicCallOp to CIR::LLVMIntrinsicOp or something). What I meant is that I imagine that CIR::IntrinsicCallOp should not be a 1-1 match to LLVM::CallIntrinsicOp, instead, it should represent all intrinsic calls that we will leave to LLVM, and lowering could choose to use LLVM::CallIntrinsicOp or other LLVM dialect llvm.intri ops Operations for LLVM IR Intrinsics.
Otherwise, there are dozens of llvm.intr LLVM Ops, and I don't think we want to them all have corresponding CIR Ops, that would defeat the purpose of having CIR as higher level IR.
Let me know what you think,

@ghehg
Copy link
Collaborator

ghehg commented Oct 16, 2024

You might feel uncomfortable giving special ad-hoc treatment in LLVM lowering, but creating a CIR OP just for a specific intrinsic (there are many such intrinsic ops in LLVM dialect, I doubt if we want have 1-1 match of them in CIR) is much more of special ad-hoc treatment.

@ghehg in mlir, we have https://github.com/llvm/llvm-project/blob/bb89988174e5f1a9a419637cadae07e4e8c61c3e/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td#L103-L107

So I think it makes sense to match their structure there and I think a new CIR Op maybe helpful to improve the readability and more expressive.

That's exactly my concern that we just move LLVM Ops into CIR, especially given LLVM dialect has dozens of such intrinsic Ops.
We'd like to keep CIR as a higher level IR. However, if you feel a need to introduce this Op for goo, I'll let it go.

@ghehg ghehg dismissed their stale review October 16, 2024 12:12

sounds like we think this Op has enough abstraction level to be added into CIR, so let's have it then!

@bcardosolopes
Copy link
Member

What I meant is that I imagine that CIR::IntrinsicCallOp should not be a 1-1 match to LLVM::CallIntrinsicOp

@ghehg The sole purpose of IntrinsicCallOp is to forward things 1-1 to LLVM intrinsics, mainly because we have tons of LLVM intrinsics that wouldn't have any specific higher level meaning and are not worth getting their specific op.

Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

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

LGTM after minor style fix

Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

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

Good to go once conflict is fixed

@bcardosolopes
Copy link
Member

Oh boy, I was reviewing/merging in chronological order and you just got bitten by refactoring again!

@ChuanqiXu9
Copy link
Member Author

I saw the main was force updated. So I have to rebase any way : ) Hope we can work on the real trunk some day : )

@bcardosolopes
Copy link
Member

Hope we can work on the real trunk some day

That's going to be speed up pretty soon, stay tuned!

@bcardosolopes bcardosolopes merged commit f50ca24 into llvm:main Oct 21, 2024
6 checks passed
lanza pushed a commit that referenced this pull request Nov 5, 2024
)

The llvm's intrinsic `llvm.is.fpclass` is used to support multiple float
point builtins:
https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass

> The `__builtin_isfpclass()` builtin is a generalization of functions
> isnan, isinf, isfinite and some others defined by the C standard. It
tests
> if the floating-point value, specified by the first argument, falls
into
> any of data classes, specified by the second argument.

I meant to support this by creating IntrinsicCallOp directly. But I
can't make it due to #480 since
the return type of the intrinsic will mismatch. So I have to create a
new Op for it. But I feel it might not be too bad. At least it is more
explicit and more expressive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants