-
Notifications
You must be signed in to change notification settings - Fork 17k
[X86] Improve illegal return type handling in FastISel #186723
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3200,11 +3200,25 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) { | |
| bool Is64Bit = Subtarget->is64Bit(); | ||
| bool IsWin64 = Subtarget->isCallingConvWin64(CC); | ||
|
|
||
| // If the return type is illegal, don't bother to promote it, just fall back | ||
| // to DAG ISel. | ||
| // If the return type is illegal, check if the ABI requires a type conversion | ||
| // that FastISel cannot handle. Fall back to DAG ISel in such cases. | ||
| // For example, bfloat is returned as f16 in XMM0, however FastISel would | ||
| // assign f32 register type and store it in FuncInfo.ValueMap. This would | ||
| // cause DAG incorrectly perform type conversion from f32 to bfloat after get | ||
| // the value from FuncInfo.ValueMap. | ||
| // However, i1 is promoted to i8 and return i8 defined by ABI, so FastISel can | ||
| // lower it without switching to DAGISel. | ||
| MVT RetVT; | ||
| if (!isTypeLegal(CLI.RetTy, RetVT) && !CLI.RetTy->isVoidTy()) | ||
| return false; | ||
| if (!isTypeLegal(CLI.RetTy, RetVT) && !CLI.RetTy->isVoidTy()) { | ||
| EVT RetEVT = EVT::getEVT(CLI.RetTy, /*HandleUnknown=*/true); | ||
| if (RetEVT == MVT::Other) | ||
| return false; // Unknown type, let DAG ISel handle it. | ||
| EVT RetABIEVT = TLI.getRegisterTypeForCallingConv(CLI.RetTy->getContext(), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revised |
||
| CLI.CallConv, RetEVT); | ||
| MVT RegVT = TLI.getRegisterType(CLI.RetTy->getContext(), RetEVT); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revised. Now I use |
||
| if (RetABIEVT != RegVT) | ||
| return false; | ||
| } | ||
|
|
||
| // Call / invoke instructions with NoCfCheck attribute require special | ||
| // handling. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| ; 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 i8 @test_direct_call(ptr %f) nounwind { | ||
| ; CHECK-LABEL: test_direct_call: | ||
| ; CHECK: # %bb.0: # %entry | ||
| ; CHECK-NEXT: pushq %rax | ||
| ; CHECK-NEXT: callq foo@PLT | ||
| ; CHECK-NEXT: movzbl %al, %edi | ||
| ; CHECK-NEXT: callq bar@PLT | ||
| ; CHECK-NEXT: popq %rcx | ||
| ; CHECK-NEXT: retq | ||
| entry: | ||
| %call = call i1 @foo(ptr %f) | ||
| %call2 = call zeroext i8 @bar(i1 %call) | ||
| ret i8 %call2 | ||
| } | ||
|
|
||
| define i8 @test_fast_direct_call(ptr %f) nounwind { | ||
| ; CHECK-LABEL: test_fast_direct_call: | ||
| ; CHECK: # %bb.0: # %entry | ||
| ; CHECK-NEXT: pushq %rax | ||
| ; CHECK-NEXT: callq foo_fast@PLT | ||
| ; CHECK-NEXT: movzbl %al, %edi | ||
| ; CHECK-NEXT: callq bar@PLT | ||
| ; CHECK-NEXT: popq %rcx | ||
| ; CHECK-NEXT: retq | ||
| entry: | ||
| %call = call fastcc i1 @foo_fast(ptr %f) | ||
| %call2 = call zeroext i8 @bar(i1 %call) | ||
| ret i8 %call2 | ||
| } | ||
|
|
||
| define i8 @test_indirect_all(ptr %fptr, ptr %f) nounwind { | ||
| ; CHECK-LABEL: test_indirect_all: | ||
| ; CHECK: # %bb.0: # %entry | ||
| ; CHECK-NEXT: pushq %rbx | ||
| ; CHECK-NEXT: movq %rdi, %rbx | ||
| ; CHECK-NEXT: movq %rsi, %rdi | ||
| ; CHECK-NEXT: callq foo@PLT | ||
| ; CHECK-NEXT: movzbl %al, %edi | ||
| ; CHECK-NEXT: callq *%rbx | ||
| ; CHECK-NEXT: popq %rbx | ||
| ; CHECK-NEXT: retq | ||
| entry: | ||
| %call = call i1 @foo(ptr %f) | ||
| %call2 = call zeroext i8 %fptr(i1 %call) | ||
| ret i8 %call2 | ||
| } | ||
|
|
||
| define i8 @test_indirect_all2(ptr %fptr, ptr %f, i1 %cond) nounwind { | ||
| ; CHECK-LABEL: test_indirect_all2: | ||
| ; CHECK: # %bb.0: # %entry | ||
| ; CHECK-NEXT: pushq %rbp | ||
| ; CHECK-NEXT: pushq %rbx | ||
| ; CHECK-NEXT: pushq %rax | ||
| ; CHECK-NEXT: movl %edx, %ebp | ||
| ; CHECK-NEXT: movq %rdi, %rbx | ||
| ; CHECK-NEXT: movq %rsi, %rdi | ||
| ; CHECK-NEXT: callq foo@PLT | ||
| ; CHECK-NEXT: testb $1, %bpl | ||
| ; CHECK-NEXT: je .LBB3_2 | ||
| ; CHECK-NEXT: # %bb.1: # %exit | ||
| ; CHECK-NEXT: movzbl %al, %edi | ||
| ; CHECK-NEXT: callq *%rbx | ||
| ; CHECK-NEXT: jmp .LBB3_3 | ||
| ; CHECK-NEXT: .LBB3_2: # %exit2 | ||
| ; CHECK-NEXT: movb $3, %al | ||
| ; CHECK-NEXT: .LBB3_3: # %exit2 | ||
| ; CHECK-NEXT: addq $8, %rsp | ||
| ; CHECK-NEXT: popq %rbx | ||
| ; CHECK-NEXT: popq %rbp | ||
| ; CHECK-NEXT: retq | ||
| entry: | ||
| %call = call i1 @foo(ptr %f) | ||
| br i1 %cond, label %exit, label %exit2 | ||
|
|
||
| exit: | ||
| %call2 = call zeroext i8 %fptr(i1 %call) | ||
| ret i8 %call2 | ||
|
|
||
| exit2: | ||
| ret i8 3 | ||
| } | ||
|
|
||
|
|
||
| define i8 @test_fast_indirect_all(ptr %fptr, ptr %f) nounwind { | ||
| ; CHECK-LABEL: test_fast_indirect_all: | ||
| ; CHECK: # %bb.0: # %entry | ||
| ; CHECK-NEXT: pushq %rbx | ||
| ; CHECK-NEXT: movq %rdi, %rbx | ||
| ; CHECK-NEXT: movq %rsi, %rdi | ||
| ; CHECK-NEXT: callq foo@PLT | ||
| ; CHECK-NEXT: movzbl %al, %edi | ||
| ; CHECK-NEXT: callq *%rbx | ||
| ; CHECK-NEXT: popq %rbx | ||
| ; CHECK-NEXT: retq | ||
| entry: | ||
| %call = call fastcc i1 @foo(ptr %f) | ||
| %call2 = call zeroext i8 %fptr(i1 %call) | ||
| ret i8 %call2 | ||
| } | ||
|
|
||
| declare i1 @foo(ptr %f) | ||
| declare zeroext i8 @bar(i1) | ||
| declare fastcc i1 @foo_fast(ptr %f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use
RetVThere?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revised.