Skip to content

[FastISel] Lower call instruction with illegal type returned#180322

Merged
LuoYuanke merged 4 commits intollvm:mainfrom
LuoYuanke:fastISel-v4i1
Mar 10, 2026
Merged

[FastISel] Lower call instruction with illegal type returned#180322
LuoYuanke merged 4 commits intollvm:mainfrom
LuoYuanke:fastISel-v4i1

Conversation

@LuoYuanke
Copy link
Copy Markdown
Contributor

@LuoYuanke LuoYuanke commented Feb 7, 2026

Fix issue #179100
When lowering the call instruction with illegal type returned, we should
bail out and transfer the lowering to DAG. Otherwise the return value is
not promoted to proper type, but DAG would assume it has been promoted.

@llvmbot llvmbot added backend:X86 llvm:SelectionDAG SelectionDAGISel as well labels Feb 7, 2026
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 7, 2026

@llvm/pr-subscribers-llvm-selectiondag

@llvm/pr-subscribers-backend-x86

Author: Luo Yuanke (LuoYuanke)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+8-2)
  • (added) llvm/test/CodeGen/X86/fast-isel-v4i1.ll (+27)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 27131e14141cc..3010c4e6430f2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2019,8 +2019,14 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
 
     std::optional<CallingConv::ID> CallConv;
     auto *CB = dyn_cast<CallBase>(Inst);
-    if (CB && !CB->isInlineAsm())
-      CallConv = CB->getCallingConv();
+
+    if (CB && !CB->isInlineAsm()) {
+      if (Inst->getType()->isFirstClassType()) {
+        EVT VT = TLI.getValueType(DAG.getDataLayout(), Inst->getType());
+        if (!TLI.isTypeLegal(VT))
+          CallConv = CB->getCallingConv();
+      }
+    }
 
     RegsForValue RFV(*DAG.getContext(), TLI, DAG.getDataLayout(), InReg,
                      Inst->getType(), CallConv);
diff --git a/llvm/test/CodeGen/X86/fast-isel-v4i1.ll b/llvm/test/CodeGen/X86/fast-isel-v4i1.ll
new file mode 100644
index 0000000000000..2e9a26a93d507
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fast-isel-v4i1.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc --fast-isel < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
+
+define fastcc i16 @test() #0 nounwind {
+; CHECK-LABEL: test:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    vpxor %xmm0, %xmm0, %xmm0
+; CHECK-NEXT:    xorl %edi, %edi
+; CHECK-NEXT:    callq *%rax
+; CHECK-NEXT:    vpslld $31, %xmm0, %xmm0
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    xorl %edi, %edi
+; CHECK-NEXT:    vpmovd2m %xmm0, %k0
+; CHECK-NEXT:    vpxor %xmm0, %xmm0, %xmm0
+; CHECK-NEXT:    vpmovm2d %k0, %xmm1
+; CHECK-NEXT:    callq *%rax
+; CHECK-NEXT:    popq %rcx
+; CHECK-NEXT:    retq
+entry:
+  %0 = call fastcc <4 x i1> null(ptr null, <4 x i1> zeroinitializer)
+  %1 = call fastcc i16 null(ptr null, <4 x i1> zeroinitializer, <4 x i1> %0)
+  ret i16 %1
+}
+
+attributes #0 = { "target-cpu"="znver5" }

Comment thread llvm/test/CodeGen/X86/fast-isel-v4i1.ll Outdated
Comment on lines 22 to 23
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Avoid UB in tests, and use named values

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Revised

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type legality should not be a factor here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Revised

@LuoYuanke LuoYuanke changed the title [FastISel] Get right type for value from fast isel [FastISel] Lower call instruction with illegal type returned Feb 8, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 8, 2026

✅ With the latest revision this PR passed the undef deprecator.

When lowering the call instruction with illegal type returned, we should
bail out and transfer the lowering to DAG. Otherwise the return value is
not promoted to proper type, but DAG would assume it has been promoted.
Comment thread llvm/lib/Target/X86/X86FastISel.cpp Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This logic kind of makes sense, but this is too narrow, and I would expect would already logically happen. Why wouldn't the same apply for the input arguments? I thought fast isel already gave up on illegally typed operations, so why does this need a new special case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wouldn't use mips as a reference on how to do anything

@nikic
Copy link
Copy Markdown
Contributor

nikic commented Feb 8, 2026

Is this fixing #179100? If so, please reference it in the PR description.

@LuoYuanke
Copy link
Copy Markdown
Contributor Author

Is this fixing #179100? If so, please reference it in the PR description.

Done

@LuoYuanke LuoYuanke requested a review from arsenm February 10, 2026 03:48
Comment thread llvm/lib/Target/X86/X86FastISel.cpp Outdated
Co-authored-by: Craig Topper <craig.topper@sifive.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 10, 2026

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

@LuoYuanke LuoYuanke requested a review from topperc February 10, 2026 07:19
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd prefer this test file was called pr179100.ll for better reference

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Revised.

@RKSimon RKSimon self-requested a review February 18, 2026 09:38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably should be processing the processed return type, instead of this. AArch64 example:

if (!isTypeLegal(Val->getType(), VT) &&

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think CLI.OutVals is not the returned values. X86 has code to check it at https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/X86/X86FastISel.cpp#L3306

@alexrp
Copy link
Copy Markdown
Member

alexrp commented Mar 9, 2026

Friendly ping on reviews since the bug this is fixing will be a problem for Zig's LLVM 22 upgrade.

@LuoYuanke LuoYuanke requested a review from arsenm March 9, 2026 01:09
@LuoYuanke
Copy link
Copy Markdown
Contributor Author

ping

Copy link
Copy Markdown
Contributor

@phoebewang phoebewang left a comment

Choose a reason for hiding this comment

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

LGTM.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These are redundant but functional correct. I think it's not a big problem for fast isel.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think that's true? Adding a "redundant" fpext/fptrunc will canonicalize, which is not allowed for just function return / argument passing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, I think this may be a more general issue with SDAG getCopyFromParts/getCopyToParts. It does it via FP_EXTEND/FP_ROUND, which is not really correct, but also tricky to avoid (except maybe in this specific bfloat case, where the trunc could just be a shift, as long as we know that the low bits must be zero).

@LuoYuanke
Copy link
Copy Markdown
Contributor Author

I think the required change from @arsenm has been addressed. I'll land the patch if there is no objection.

@LuoYuanke LuoYuanke merged commit 41ef3d0 into llvm:main Mar 10, 2026
10 checks passed
@LuoYuanke LuoYuanke deleted the fastISel-v4i1 branch March 10, 2026 03:56
@alexrp alexrp added this to the LLVM 22.x Release milestone Mar 10, 2026
@github-project-automation github-project-automation Bot moved this to Needs Triage in LLVM Release Status Mar 10, 2026
@github-project-automation github-project-automation Bot moved this from Needs Triage to Done in LLVM Release Status Mar 10, 2026
@nikic
Copy link
Copy Markdown
Contributor

nikic commented Mar 10, 2026

For the record, this causes an -O0 compile-time regression for tramp3d-v4: https://llvm-compile-time-tracker.com/compare.php?from=351d900e6c96ee51cbb40c933969b5ebd15a4122&to=41ef3d083a0925cb9c184057f76a0d42ad5680ab&stat=instructions:u I assume it often uses some illegal type for returns, but I haven't checked what it is. My guess would be i1.

@LuoYuanke
Copy link
Copy Markdown
Contributor Author

For the record, this causes an -O0 compile-time regression for tramp3d-v4: https://llvm-compile-time-tracker.com/compare.php?from=351d900e6c96ee51cbb40c933969b5ebd15a4122&to=41ef3d083a0925cb9c184057f76a0d42ad5680ab&stat=instructions:u I assume it often uses some illegal type for returns, but I haven't checked what it is. My guess would be i1.

Switching from fast ISel to DAG ISel would spent more compile-time on ISel. The i1 return type is promoted to i8 which is the same in ISel promotion. The bf16 return type is bf16, while it is promoted to f32 in ISel. Maybe we can check if the promoted type is the same to abi return type before switching form fast ISel to DAG ISel.

dyung pushed a commit to llvmbot/llvm-project that referenced this pull request Mar 12, 2026
…0322)

Fix issue llvm#179100
When lowering the call instruction with illegal type returned, we should
bail out and transfer the lowering to DAG. Otherwise the return value is
not promoted to proper type, but DAG would assume it has been promoted.

---------

Co-authored-by: Yuanke Luo <ykluo@birentech.com>
(cherry picked from commit 41ef3d0)
@LuoYuanke
Copy link
Copy Markdown
Contributor Author

LuoYuanke commented Mar 16, 2026

I create a PR (#186723) to improve the compile-time.

nikic added a commit to rust-lang/llvm-project that referenced this pull request Mar 28, 2026
nikic added a commit to rust-lang/llvm-project that referenced this pull request Mar 28, 2026
…lvm#180322)"

This reverts commit 4dfb4b6.

This causes a large compile-time regression for debug builds.
@nikic
Copy link
Copy Markdown
Contributor

nikic commented Apr 24, 2026

I create a PR (#186723) to improve the compile-time.

We're still seeing large regressions for debug builds in Rust -- the reason is struct returns. It would be easy enough to fix this by looping over ComputeValueTypes of the RetTy, but I'm not sure this change is really doing the right thing in the first place...

nikic added a commit to nikic/llvm-project that referenced this pull request Apr 28, 2026
After llvm#180322, X86 FastISel forces SDAG fallback for any call with
a struct return. This caused major compile-time regressions for
debug builds in Rust, where struct returns are very common.

The type legality check should work on the de-aggregated types,
not on the return type directly.
nikic added a commit to nikic/llvm-project that referenced this pull request Apr 28, 2026
After llvm#180322, X86 FastISel forces SDAG fallback for any call with
a struct return. This caused major compile-time regressions for
debug builds in Rust, where struct returns are very common.

The type legality check should work on the de-aggregated types,
not on the return type directly.
nikic added a commit that referenced this pull request Apr 29, 2026
After #180322, X86 FastISel forces SDAG fallback for any call with a
struct return. This caused major compile-time regressions for debug
builds in Rust, where struct returns are very common.

The type legality check should work on the de-aggregated types, not on
the return type directly.
kirthana14m pushed a commit to ROCm/llvm-project that referenced this pull request Apr 30, 2026
After llvm#180322, X86 FastISel forces SDAG fallback for any call with a
struct return. This caused major compile-time regressions for debug
builds in Rust, where struct returns are very common.

The type legality check should work on the de-aggregated types, not on
the return type directly.
dyung pushed a commit to llvmbot/llvm-project that referenced this pull request May 1, 2026
After llvm#180322, X86 FastISel forces SDAG fallback for any call with a
struct return. This caused major compile-time regressions for debug
builds in Rust, where struct returns are very common.

The type legality check should work on the de-aggregated types, not on
the return type directly.

(cherry picked from commit 30fa415)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:X86 llvm:SelectionDAG SelectionDAGISel as well

Projects

Development

Successfully merging this pull request may close these issues.

8 participants