Skip to content

[CIR][Lowering] Fix Vector Comparison Lowering with -fno-signed-char/unsigned operand #1770

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

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

Conversation

RiverDave
Copy link
Collaborator

@RiverDave RiverDave commented Jul 30, 2025

While working on _mm_movepi8_mask, intrinsic (and similar sign-bit checking intrinsics containing 8-bit integers) was being optimized away when using -fno-signed-char. Effectively replacing a cmp expression for 0.

Since unsigned values can never be less than zero, the CIR lowering was directly generating a constant 0 (I suppose we fold a vec filled with 0's to our target, which is a scalar mask, which in turn is 0) instead of the intended comparison operation, completely eliminating the icmp instruction.

See when passing as arg -fno-signed-char (no cmp generated):

OG:

define dso_local i16 @test_mm_movepi8_mask(<2 x i64> %0) #0 {
...
  %8 = bitcast <2 x i64> %7 to <16 x i8>
  %9 = icmp slt <16 x i8> %8, zeroinitializer
  store i16 %10, ptr %3, align 2
  ...
  ret i16 %12
}

CIR:

define dso_local i16 @test_mm_movepi8_mask(<2 x i64> %0) #0 {
...
  %8 = bitcast <2 x i64> %7 to <16 x i8>
  store i16 0, ptr %3, align 2 // I believe our vector cmp is folded here?
...
  ret i16 %10
}

Since integer signedness is something we can track, the behaviour CIR is enforcing makes sense; however, if we want to preserve parity with OG, I believe this patch will match that. I can close this PR if that's not applicable to this case.

Added special case detection for sign-bit extraction patterns (lt comparison with cir::ZeroAttr) to force signed comparison regardless of the element type's signedness. This preserves the semantic intent of checking sign bits rather than performing mathematical unsigned comparisons.

@RiverDave RiverDave added the IR difference A difference in ClangIR-generated LLVM IR that could complicate reusing original CodeGen tests label Jul 31, 2025
// Special treatment For sign-bit extraction patterns (lt comparison with
// zero), always use signed comparison to preserve the semantic intent
if (op.getKind() == cir::CmpOpKind::lt && isCIRZeroVector(op.getRhs())) {
shouldUseSigned = true;
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be forcing signedness for no good reason, like you previously stated in the description, we know this comes from unsigned. This is a fair IR difference to live with, the question is weather this is too aggressive for the canonicalizer to be doing or if we want to move this into CIR simplify. I think the current behavior is good enough. Can you instead add a C source test for both unsigned and signed versions and capture that the canonicalizer kicks for one and not for the other?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks a lot for the detailed response. Just to confirm — in the context of this PR, we want to preserve the current lowering logic, and my next step would be to add tests documenting the current behavior. Is that correct?

@bcardosolopes
Copy link
Member

We just went through a rebase, this PR needs to be updated.

@RiverDave
Copy link
Collaborator Author

We just went through a rebase, this PR needs to be updated.

Updated this along with my other currently open PR's

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
IR difference A difference in ClangIR-generated LLVM IR that could complicate reusing original CodeGen tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants