[v1] LoongArch: Added code generation support for call36 function calls.

Message ID 20231114094500.8160-1-chenglulu@loongson.cn
State Unresolved
Headers
Series [v1] LoongArch: Added code generation support for call36 function calls. |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

chenglulu Nov. 14, 2023, 9:45 a.m. UTC
  When compiling with '-mcmodel=medium', the function call is made through
'pcaddu18i+jirl' if binutils supports call36, otherwise the
native implementation 'pcalau12i+jirl' is used.

gcc/ChangeLog:

	* config.in: Regenerate.
	* config/loongarch/loongarch-opts.h (HAVE_AS_SUPPORT_CALL36): Define macro.
	* config/loongarch/loongarch.cc (loongarch_legitimize_call_address):
	If binutils supports call36, the function call is not split over expand.
	(loongarch_option_override_internal): If use call36, then turn off fipa-ra.
	* config/loongarch/loongarch.md: Add call36 generation code.
	* config/loongarch/predicates.md: Likewise.
	* configure: Regenerate.
	* configure.ac: Check whether binutils supports call36.
---
 gcc/config.in                         |   6 ++
 gcc/config/loongarch/loongarch-opts.h |   4 +
 gcc/config/loongarch/loongarch.cc     |  20 +++-
 gcc/config/loongarch/loongarch.md     | 138 +++++++++++++++++++++-----
 gcc/config/loongarch/predicates.md    |   7 +-
 gcc/configure                         |  32 ++++++
 gcc/configure.ac                      |   6 ++
 7 files changed, 182 insertions(+), 31 deletions(-)
  

Comments

Xi Ruoyao Nov. 14, 2023, 9:55 a.m. UTC | #1
On Tue, 2023-11-14 at 17:45 +0800, Lulu Cheng wrote:
> +      /* When function calls are made through call36, t0 register will be
> +	 implicitly modified, so '-fno-ipa-ra' needs to be set here.  */
>        case CMODEL_MEDIUM:
> +	if (HAVE_AS_SUPPORT_CALL36)
> +	  opts->x_flag_ipa_ra = 0;
> +	break;

Maybe we can add a (clobber (reg:P 12)) to the related insns instead?
  
chenglulu Nov. 14, 2023, 12:46 p.m. UTC | #2
在 2023/11/14 下午5:55, Xi Ruoyao 写道:
> On Tue, 2023-11-14 at 17:45 +0800, Lulu Cheng wrote:
>> +      /* When function calls are made through call36, t0 register will be
>> +	 implicitly modified, so '-fno-ipa-ra' needs to be set here.  */
>>         case CMODEL_MEDIUM:
>> +	if (HAVE_AS_SUPPORT_CALL36)
>> +	  opts->x_flag_ipa_ra = 0;
>> +	break;
> Maybe we can add a (clobber (reg:P 12)) to the related insns instead?
>
Sorry, this was modified in accordance with the call36 macro instruction 
during the test.
I will use clobber, and add test cases.
  
Xi Ruoyao Nov. 14, 2023, 8:26 p.m. UTC | #3
On Tue, 2023-11-14 at 20:46 +0800, chenglulu wrote:
> 
> 在 2023/11/14 下午5:55, Xi Ruoyao 写道:
> > On Tue, 2023-11-14 at 17:45 +0800, Lulu Cheng wrote:
> > > +      /* When function calls are made through call36, t0 register
> > > will be
> > > +	 implicitly modified, so '-fno-ipa-ra' needs to be set
> > > here.  */
> > >         case CMODEL_MEDIUM:
> > > +	if (HAVE_AS_SUPPORT_CALL36)
> > > +	  opts->x_flag_ipa_ra = 0;
> > > +	break;
> > Maybe we can add a (clobber (reg:P 12)) to the related insns
> > instead?
> > 
> Sorry, this was modified in accordance with the call36 macro
> instruction 
> during the test.
> I will use clobber, and add test cases.

There seems a better solution as suggested by the GCC internal doc. 
Section 18.9.16 mentions -fipa-ra:

 -- Target Hook: bool TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
     Set to true if each call that binds to a local definition
     explicitly clobbers or sets all non-fixed registers modified by
     performing the call.  That is, by the call pattern itself, or by
     code that might be inserted by the linker (e.g. stubs, veneers,
     branch islands), but not including those modifiable by the callee.
     The affected registers may be mentioned explicitly in the call
     pattern, or included as clobbers in CALL_INSN_FUNCTION_USAGE. The
     default version of this hook is set to false.  The purpose of this
     hook is to enable the fipa-ra optimization.

So we can add t0 into CALL_INSN_FUNCTION_USAGE of the call insn, like:

diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index ea36542b1c3..96e7e98e6b3 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3274,7 +3274,14 @@ (define_expand "sibcall"
 					    XEXP (target, 1),
 					    operands[1]));
   else
-    emit_call_insn (gen_sibcall_internal (target, operands[1]));
+    {
+      rtx call = gen_sibcall_internal (target, operands[1]);
+
+      if (TARGET_CMODEL_MEDIUM && !REG_P (target))
+	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
+		     gen_rtx_REG (Pmode, T0_REGNUM));
+      emit_call_insn (call);
+    }
   DONE;
 })

Likewise for sibcall_value.

By the way we'd better have a command line switch to override the build-
time check for assembler call36 support, because it makes writing test
cases and inter-operating with different versions of assembler easier.
  
Xi Ruoyao Nov. 14, 2023, 8:42 p.m. UTC | #4
On Wed, 2023-11-15 at 04:26 +0800, Xi Ruoyao wrote:
> On Tue, 2023-11-14 at 20:46 +0800, chenglulu wrote:
> > 
> > 在 2023/11/14 下午5:55, Xi Ruoyao 写道:
> > > On Tue, 2023-11-14 at 17:45 +0800, Lulu Cheng wrote:
> > > > +      /* When function calls are made through call36, t0 register
> > > > will be
> > > > +	 implicitly modified, so '-fno-ipa-ra' needs to be set
> > > > here.  */
> > > >         case CMODEL_MEDIUM:
> > > > +	if (HAVE_AS_SUPPORT_CALL36)
> > > > +	  opts->x_flag_ipa_ra = 0;
> > > > +	break;
> > > Maybe we can add a (clobber (reg:P 12)) to the related insns
> > > instead?
> > > 
> > Sorry, this was modified in accordance with the call36 macro
> > instruction 
> > during the test.
> > I will use clobber, and add test cases.
> 
> There seems a better solution as suggested by the GCC internal doc. 
> Section 18.9.16 mentions -fipa-ra:
> 
>  -- Target Hook: bool TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
>      Set to true if each call that binds to a local definition
>      explicitly clobbers or sets all non-fixed registers modified by
>      performing the call.  That is, by the call pattern itself, or by
>      code that might be inserted by the linker (e.g. stubs, veneers,
>      branch islands), but not including those modifiable by the callee.
>      The affected registers may be mentioned explicitly in the call
>      pattern, or included as clobbers in CALL_INSN_FUNCTION_USAGE. The
>      default version of this hook is set to false.  The purpose of this
>      hook is to enable the fipa-ra optimization.
> 
> So we can add t0 into CALL_INSN_FUNCTION_USAGE of the call insn, like:
> 
> diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
> index ea36542b1c3..96e7e98e6b3 100644
> --- a/gcc/config/loongarch/loongarch.md
> +++ b/gcc/config/loongarch/loongarch.md
> @@ -3274,7 +3274,14 @@ (define_expand "sibcall"
>  					    XEXP (target, 1),
>  					    operands[1]));
>    else
> -    emit_call_insn (gen_sibcall_internal (target, operands[1]));
> +    {
> +      rtx call = gen_sibcall_internal (target, operands[1]);
> +
> +      if (TARGET_CMODEL_MEDIUM && !REG_P (target))
> +	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
> +		     gen_rtx_REG (Pmode, T0_REGNUM));
> +      emit_call_insn (call);
> +    }
>    DONE;
>  })
> 
> Likewise for sibcall_value.

Nope.  This does not work for

__attribute__((noinline)) void q() { asm ("":::"memory"); }
__attribute__((noinline)) static void t() { q(); }

int
main ()
{
  int x0 = 114514;

  asm("":"+r"(x0));
  t();
  if (x0 != 114514)
    __builtin_trap ();
}

Not sure why...

> 
> By the way we'd better have a command line switch to override the build-
> time check for assembler call36 support, because it makes writing test
> cases and inter-operating with different versions of assembler easier.
>
  
Xi Ruoyao Nov. 14, 2023, 8:46 p.m. UTC | #5
On Wed, 2023-11-15 at 04:42 +0800, Xi Ruoyao wrote:
> > There seems a better solution as suggested by the GCC internal doc. 
> > Section 18.9.16 mentions -fipa-ra:
> > 
> >  -- Target Hook: bool TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
> >      Set to true if each call that binds to a local definition
> >      explicitly clobbers or sets all non-fixed registers modified by
> >      performing the call.  That is, by the call pattern itself, or by
> >      code that might be inserted by the linker (e.g. stubs, veneers,
> >      branch islands), but not including those modifiable by the callee.
> >      The affected registers may be mentioned explicitly in the call
> >      pattern, or included as clobbers in CALL_INSN_FUNCTION_USAGE. The
> >      default version of this hook is set to false.  The purpose of this
> >      hook is to enable the fipa-ra optimization.
> > 
> > So we can add t0 into CALL_INSN_FUNCTION_USAGE of the call insn, like:
> > 
> > diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
> > index ea36542b1c3..96e7e98e6b3 100644
> > --- a/gcc/config/loongarch/loongarch.md
> > +++ b/gcc/config/loongarch/loongarch.md
> > @@ -3274,7 +3274,14 @@ (define_expand "sibcall"
> >  					    XEXP (target, 1),
> >  					    operands[1]));
> >    else
> > -    emit_call_insn (gen_sibcall_internal (target, operands[1]));
> > +    {
> > +      rtx call = gen_sibcall_internal (target, operands[1]);
> > +
> > +      if (TARGET_CMODEL_MEDIUM && !REG_P (target))
> > +	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
> > +		     gen_rtx_REG (Pmode, T0_REGNUM));
> > +      emit_call_insn (call);
> > +    }
> >    DONE;
> >  })
> > 
> > Likewise for sibcall_value.
> 
> Nope.  This does not work for
> 
> __attribute__((noinline)) void q() { asm ("":::"memory"); }
> __attribute__((noinline)) static void t() { q(); }
> 
> int
> main ()
> {
>   int x0 = 114514;
> 
>   asm("":"+r"(x0));
>   t();
>   if (x0 != 114514)
>     __builtin_trap ();
> }
> 
> Not sure why...

Alright, it should be

diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index ea36542b1c3..75c595abad7 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3274,7 +3274,13 @@ (define_expand "sibcall"
 					    XEXP (target, 1),
 					    operands[1]));
   else
-    emit_call_insn (gen_sibcall_internal (target, operands[1]));
+    {
+      rtx call = emit_call_insn (gen_sibcall_internal (target, operands[1]));
+
+      if (TARGET_CMODEL_MEDIUM && !REG_P (target))
+	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
+		     gen_rtx_REG (Pmode, T0_REGNUM));
+    }
   DONE;
 })

instead.
  

Patch

diff --git a/gcc/config.in b/gcc/config.in
index 0509ba7e6a7..946b8fe39c7 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -775,6 +775,12 @@ 
 #endif
 
 
+/* Define if your assembler supports call36. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SUPPORT_CALL36
+#endif
+
+
 /* Define if your assembler and linker support thread-local storage. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_TLS
diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h
index f204828015e..f1d36e8acfd 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -97,6 +97,10 @@  loongarch_update_gcc_opt_status (struct loongarch_target *target,
 #define HAVE_AS_EXPLICIT_RELOCS 0
 #endif
 
+#ifndef HAVE_AS_SUPPORT_CALL36
+#define HAVE_AS_SUPPORT_CALL36 0
+#endif
+
 #ifndef HAVE_AS_MRELAX_OPTION
 #define HAVE_AS_MRELAX_OPTION 0
 #endif
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index c782f571abc..5c8ba96118e 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -3006,12 +3006,16 @@  loongarch_legitimize_call_address (rtx addr)
 
   enum loongarch_symbol_type symbol_type = loongarch_classify_symbol (addr);
 
-  /* Split function call insn 'bl sym' or 'bl %plt(sym)' to :
-     pcalau12i $rd, %pc_hi20(sym)
-     jr $rd, %pc_lo12(sym).  */
+  /* If add the compilation option '-cmodel=medium', and the assembler does
+     not support call36.  The following sequence of instructions will be
+     used for the function call:
+	pcalau12i $rd, %pc_hi20(sym)
+	jr $rd, %pc_lo12(sym)
+  */
 
   if (TARGET_CMODEL_MEDIUM
-      && TARGET_EXPLICIT_RELOCS
+      && !HAVE_AS_SUPPORT_CALL36
+      && (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE)
       && (SYMBOL_REF_P (addr) || LABEL_REF_P (addr))
       && (symbol_type == SYMBOL_PCREL
 	  || (symbol_type == SYMBOL_GOT_DISP && flag_plt)))
@@ -7478,8 +7482,14 @@  loongarch_option_override_internal (struct gcc_options *opts,
 	  }
 	break;
 
-      case CMODEL_TINY_STATIC:
+      /* When function calls are made through call36, t0 register will be
+	 implicitly modified, so '-fno-ipa-ra' needs to be set here.  */
       case CMODEL_MEDIUM:
+	if (HAVE_AS_SUPPORT_CALL36)
+	  opts->x_flag_ipa_ra = 0;
+	break;
+
+      case CMODEL_TINY_STATIC:
       case CMODEL_NORMAL:
       case CMODEL_TINY:
       case CMODEL_LARGE:
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 4dd716e1941..7febb7bf8ba 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3274,10 +3274,25 @@  (define_insn "sibcall_internal"
   [(call (mem:SI (match_operand 0 "call_insn_operand" "j,c,b"))
 	 (match_operand 1 "" ""))]
   "SIBLING_CALL_P (insn)"
-  "@
-   jr\t%0
-   b\t%0
-   b\t%%plt(%0)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jr\t%0";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%0)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%0";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%0)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%%plt(%0)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@sibcall_internal_1<mode>"
@@ -3337,10 +3352,25 @@  (define_insn "sibcall_value_internal"
 	(call (mem:SI (match_operand 1 "call_insn_operand" "j,c,b"))
 	      (match_operand 2 "" "")))]
   "SIBLING_CALL_P (insn)"
-  "@
-   jr\t%1
-   b\t%1
-   b\t%%plt(%1)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jr\t%1";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%1";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%%plt(%1)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@sibcall_value_internal_1<mode>"
@@ -3360,10 +3390,25 @@  (define_insn "sibcall_value_multiple_internal"
 	(call (mem:SI (match_dup 1))
 	      (match_dup 2)))]
   "SIBLING_CALL_P (insn)"
-  "@
-   jr\t%1
-   b\t%1
-   b\t%%plt(%1)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jr\t%1";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%1";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
+      else
+	return "b\t%%plt(%1)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@sibcall_value_multiple_internal_1<mode>"
@@ -3403,10 +3448,25 @@  (define_insn "call_internal"
 	 (match_operand 1 "" ""))
    (clobber (reg:SI RETURN_ADDR_REGNUM))]
   ""
-  "@
-   jirl\t$r1,%0,0
-   bl\t%0
-   bl\t%%plt(%0)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jirl\t$r1,%0,0";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%0)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%0";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%0)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%%plt(%0)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@call_internal_1<mode>"
@@ -3465,10 +3525,25 @@  (define_insn "call_value_internal"
 	      (match_operand 2 "" "")))
    (clobber (reg:SI RETURN_ADDR_REGNUM))]
   ""
-  "@
-   jirl\t$r1,%1,0
-   bl\t%1
-   bl\t%%plt(%1)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jirl\t$r1,%1,0";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%1";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%%plt(%1)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@call_value_internal_1<mode>"
@@ -3490,10 +3565,25 @@  (define_insn "call_value_multiple_internal"
 	      (match_dup 2)))
    (clobber (reg:SI RETURN_ADDR_REGNUM))]
   ""
-  "@
-   jirl\t$r1,%1,0
-   bl\t%1
-   bl\t%%plt(%1)"
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "jirl\t$r1,%1,0";
+    case 1:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%1";
+    case 2:
+      if (TARGET_CMODEL_MEDIUM)
+	return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
+      else
+	return "bl\t%%plt(%1)";
+    default:
+      gcc_unreachable ();
+    }
+}
   [(set_attr "jirl" "indirect,direct,direct")])
 
 (define_insn "@call_value_multiple_internal_1<mode>"
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index 946ed0d8212..56f7c48e126 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -443,7 +443,9 @@  (define_predicate "const_call_insn_operand"
     {
     case SYMBOL_PCREL:
       if (TARGET_CMODEL_EXTREME
-	  || (TARGET_CMODEL_MEDIUM && !TARGET_EXPLICIT_RELOCS))
+	  || (TARGET_CMODEL_MEDIUM
+	      && HAVE_AS_SUPPORT_CALL36
+	      && (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE)))
 	return false;
       else
 	return 1;
@@ -452,7 +454,8 @@  (define_predicate "const_call_insn_operand"
       if (TARGET_CMODEL_EXTREME
 	  || !flag_plt
 	  || (flag_plt && TARGET_CMODEL_MEDIUM
-	      && !TARGET_EXPLICIT_RELOCS))
+	      && HAVE_AS_SUPPORT_CALL36
+	      && (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE)))
 	return false;
       else
 	return 1;
diff --git a/gcc/configure b/gcc/configure
index 0d818ae6850..d28a4536f45 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -29349,6 +29349,38 @@  if test $gcc_cv_as_loongarch_explicit_relocs = yes; then
 
 $as_echo "#define HAVE_AS_EXPLICIT_RELOCS 1" >>confdefs.h
 
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for call36 support" >&5
+$as_echo_n "checking assembler for call36 support... " >&6; }
+if ${gcc_cv_as_loongarch_call36+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_loongarch_call36=no
+  if test x$gcc_cv_as != x; then
+    $as_echo 'pcaddu18i $r1, %call36(a)
+       jirl $r1, $r1, 0' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_loongarch_call36=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_loongarch_call36" >&5
+$as_echo "$gcc_cv_as_loongarch_call36" >&6; }
+if test $gcc_cv_as_loongarch_call36 = yes; then
+
+$as_echo "#define HAVE_AS_SUPPORT_CALL36 1" >>confdefs.h
+
 fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for eh_frame pcrel encoding support" >&5
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 764a33f0b04..c489ba6a39b 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5441,6 +5441,12 @@  x:
       [a:pcalau12i $t0,%pc_hi20(a)],,
       [AC_DEFINE(HAVE_AS_EXPLICIT_RELOCS, 1,
 	  [Define if your assembler supports explicit relocation.])])
+    gcc_GAS_CHECK_FEATURE([call36 support],
+      gcc_cv_as_loongarch_call36,,
+      [pcaddu18i $r1, %call36(a)
+       jirl $r1, $r1, 0],,
+      [AC_DEFINE(HAVE_AS_SUPPORT_CALL36, 1,
+	  [Define if your assembler supports call36.])])
     gcc_GAS_CHECK_FEATURE([eh_frame pcrel encoding support],
       gcc_cv_as_loongarch_eh_frame_pcrel_encoding_support,,
       [.cfi_startproc