Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4118,9 +4118,10 @@ if (Subtarget.isPICStyleGOT()) { // ELF / PIC requires GOT in the EBX register before function calls via PLT - // GOT pointer. + // GOT pointer (except regcall). if (!isTailCall) { - RegsToPass.push_back(std::make_pair( + if (CallConv != CallingConv::X86_RegCall) + RegsToPass.push_back(std::make_pair( Register(X86::EBX), DAG.getNode(X86ISD::GlobalBaseReg, SDLoc(), getPointerTy(DAG.getDataLayout())))); } else { Index: llvm/test/CodeGen/X86/x86-regcall-got.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/x86-regcall-got.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=i386-unknown-linux-gnu -relocation-model=pic < %s | FileCheck %s + +; Unbind the ebx with GOT address in regcall calling convention, or the following +; case will failed in register allocation by no register can be used. + +;//clang -target i386-unknown-linux-gnu -S -fpic t.c +;#define REGCALL __attribute__((regcall)) +;int REGCALL func (int i1, int i2, int i3, int i4, int i5); +;int (REGCALL *fptr) (int, int, int, int, int) = func; +;int test() { +; return fptr(1,2,3,4,5); +;} + +@fptr = global i32 (i32, i32, i32, i32, i32)* @__regcall3__func, align 4 + +declare x86_regcallcc i32 @__regcall3__func(i32 inreg, i32 inreg, i32 inreg, i32 inreg, i32 inreg) #0 + +; Function Attrs: noinline nounwind optnone +define i32 @test() #1 { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushl %ebp +; CHECK-NEXT: movl %esp, %ebp +; CHECK-NEXT: pushl %ebx +; CHECK-NEXT: pushl %edi +; CHECK-NEXT: pushl %esi +; CHECK-NEXT: subl $12, %esp +; CHECK-NEXT: calll .L0$pb +; CHECK-NEXT: .L0$pb: +; CHECK-NEXT: popl %eax +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %eax +; CHECK-NEXT: movl fptr@GOT(%eax), %eax +; CHECK-NEXT: movl (%eax), %ebx +; CHECK-NEXT: movl $1, %eax +; CHECK-NEXT: movl $2, %ecx +; CHECK-NEXT: movl $3, %edx +; CHECK-NEXT: movl $4, %edi +; CHECK-NEXT: movl $5, %esi +; CHECK-NEXT: calll *%ebx +; CHECK-NEXT: addl $12, %esp +; CHECK-NEXT: popl %esi +; CHECK-NEXT: popl %edi +; CHECK-NEXT: popl %ebx +; CHECK-NEXT: popl %ebp +; CHECK-NEXT: retl +entry: + %0 = load i32 (i32, i32, i32, i32, i32)*, i32 (i32, i32, i32, i32, i32)** @fptr, align 4 + %call = call x86_regcallcc i32 %0(i32 inreg 1, i32 inreg 2, i32 inreg 3, i32 inreg 4, i32 inreg 5) + ret i32 %call +} + +attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0, !1, !2} +!llvm.ident = !{!3} + +!0 = !{i32 1, !"NumRegisterParameters", i32 0} +!1 = !{i32 1, !"wchar_size", i32 4} +!2 = !{i32 7, !"PIC Level", i32 1} +!3 = !{!"Intel(R) oneAPI DPC++ Compiler 2021.1 (YYYY.x.0.MMDD)"}