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][CIRGen] Support __builtin_isinf_sign #1142

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

PikachuHyA
Copy link
Collaborator

@PikachuHyA PikachuHyA commented Nov 19, 2024

No description provided.

@bcardosolopes
Copy link
Member

Firstly, it uses IsFPClass to determine if a value is infinite, whereas the original CGBuiltin implementation used direct comparisons with infinity constants.

I'm assuming IsFPClass will lead to the same final LLVM? If so LGTM

// see https://github.com/llvm/clangir/issues/480
// fix the issue can eliminate lots of redundant cast instruction
// for IsInf, i1 -> i8 -> i1
// for IsNeg, i1 -> i8 -> i32 -> i1
Copy link
Member

Choose a reason for hiding this comment

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

@orbiri fyi (you might want to track this too)

@orbiri
Copy link
Collaborator

orbiri commented Nov 28, 2024

Can you explain why can’t signbit return a Boolean? What is its other usages? (I don’t have full context so that would help me to understand better this patch 😇)

Looking around, it seems even that C++ is exposing this API with a Boolean. https://en.cppreference.com/w/cpp/numeric/math/signbit

Perhaps it is time to convert this op to Boolean as well? :)

@PikachuHyA
Copy link
Collaborator Author

Can you explain why can’t signbit return a Boolean? What is its other usages?

please see the error in #1187

@PikachuHyA
Copy link
Collaborator Author

Firstly, it uses IsFPClass to determine if a value is infinite, whereas the original CGBuiltin implementation used direct comparisons with infinity constants.

I'm assuming IsFPClass will lead to the same final LLVM?

If you are inquiring whether their semantics are equivalent, the answer is yes.

@orbiri
Copy link
Collaborator

orbiri commented Nov 29, 2024

Can you explain why can’t signbit return a Boolean? What is its other usages?

please see the error in #1187

This error indicates that there’s either an error in your codegen or in the lowering code. In either way, I would not recommend increasing the tech debt with this change.

I would recommend using the -debug flag of cir-opt and inspect the lowering step by step!

@bcardosolopes
Copy link
Member

In either way, I would not recommend increasing the tech debt with this change.

Thanks @orbiri, way to go. Reviewed and landed #1187, @PikachuHyA let me know when this PR is ready again

@PikachuHyA
Copy link
Collaborator Author

@orbiri After updating SignBitOp to return bool, this patch still leads to two unnecessary type conversions: from i1 to i8 and then back to i1. I think it is related to #480 , please feel free to share your thoughts on this.

I left a comment in clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp:

// FIXME: CIR currently converts cir::BoolType to i8 type unconditionally.
// See https://github.com/llvm/clangir/issues/480
// Fixing this issue will eliminate redundant cast instructions
// for IsInf and IsNeg: i1 -> i8 -> i1

The LLVM IR generated by running:

./bin/clang ../clang/test/CIR/CodeGen/builtin-isinf-sign.c -Xclang -emit-llvm -o t.ll -c -fclangir

is as follows:

define dso_local i32 @test_float_isinf_sign(float %0) #0 {
  %2 = alloca float, i64 1, align 4
  %3 = alloca i32, i64 1, align 4
  store float %0, ptr %2, align 4
  %4 = load float, ptr %2, align 4
  %5 = call float @llvm.fabs.f32(float %4)
  %6 = call i1 @llvm.is.fpclass.f32(float %5, i32 516)
  %7 = zext i1 %6 to i8
  %8 = bitcast float %4 to i32
  %9 = icmp slt i32 %8, 0
  %10 = zext i1 %9 to i8
  %11 = trunc i8 %10 to i1
  %12 = select i1 %11, i32 -1, i32 1
  %13 = trunc i8 %7 to i1
  %14 = select i1 %13, i32 %12, i32 0
  store i32 %14, ptr %3, align 4
  %15 = load i32, ptr %3, align 4
  ret i32 %15
}

As shown, there are unnecessary conversions: %6 -> %7 -> %13 and %9 -> %10 -> %11.

Additionally, the LLVM IR generated by running:

./bin/clang ../clang/test/CIR/CodeGen/builtin-isinf-sign.c -Xclang -emit-llvm -o t.orig.ll -c

is:

define dso_local i32 @test_float_isinf_sign(float noundef %x) #0 {
entry:
  %x.addr = alloca float, align 4
  store float %x, ptr %x.addr, align 4
  %0 = load float, ptr %x.addr, align 4
  %1 = call float @llvm.fabs.f32(float %0) #2
  %isinf = fcmp oeq float %1, 0x7FF0000000000000
  %2 = bitcast float %0 to i32
  %3 = icmp slt i32 %2, 0
  %4 = select i1 %3, i32 -1, i32 1
  %5 = select i1 %isinf, i32 %4, i32 0
  ret i32 %5
}

@PikachuHyA
Copy link
Collaborator Author

@orbiri ping

@orbiri
Copy link
Collaborator

orbiri commented Dec 21, 2024

It will be sorted out very soon! Don’t optimize on the llvm output but rather on the CIR output :)

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.

3 participants