[PATCH] D91020: [X86] Unbind the ebx with GOT address in regcall calling convention

Xiang Zhang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 7 17:45:13 PST 2020


xiangzhangllvm created this revision.
Herald added subscribers: llvm-commits, pengfei, hiraditya.
Herald added a project: LLVM.
xiangzhangllvm requested review of this revision.

No register can be allocated for indirect call when it use regcall calling convention and passed 5/5+ args.

e.g.

call vreg (ag1, ag2, ag3, ag4, ag5, ...)  --> 5 regs (EAX, ECX, EDX, ESI, EDI) used for pass args, 1 reg (EBX )used for hold GOT point, 
so no regs can be allocated to vreg.

The Intel386 architecture provides 8 general purpose 32-bit registers. RA mostly
use 6 of them (EAX, EBX, ECX, EDX, ESI, EDI).
5 of this regs can be used to pass function arguments (EAX, ECX, EDX, ESI, EDI).
EBX used to hold the GOT pointer when making function calls via the PLT.
ESP and EBP usually be "reserved" in register allocation.

**Reproduce case:**

  //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);
  }


https://reviews.llvm.org/D91020

Files:
  llvm/lib/Target/X86/X86ISelLowering.cpp
  llvm/test/CodeGen/X86/x86-regcall-got.ll


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);
+;}
+
+ at 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 at 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)"}
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 {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91020.303685.patch
Type: text/x-patch
Size: 4060 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201108/66bf65a7/attachment.bin>


More information about the llvm-commits mailing list