[llvm] [RISCV][GISel] Fix 2 indirect call bugs. (PR #73170)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 22 13:08:15 PST 2023


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/73170

We can't set MO_PLT on an indirect call.
We need to constrain the register class for the operand to the call instruction.

>From ba5a3e14aa93f488d1f9c395549c587119f80997 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 22 Nov 2023 12:57:16 -0800
Subject: [PATCH] [RISCV][GISel] Fix 2 indirect call bugs.

We can't set MO_PLT on an indirect call.
We need to constrain the register class for the operand to the call instruction.
---
 .../Target/RISCV/GISel/RISCVCallLowering.cpp  | 14 +++++++++--
 .../RISCV/GlobalISel/irtranslator/calls.ll    | 24 +++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
index 1aba8a8f52e96fc..3108ce9837891b5 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
@@ -505,14 +505,15 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   Info.IsTailCall = false;
 
   // Select the recommended relocation type R_RISCV_CALL_PLT.
-  Info.Callee.setTargetFlags(RISCVII::MO_PLT);
+  if (!Info.Callee.isReg())
+    Info.Callee.setTargetFlags(RISCVII::MO_PLT);
 
   MachineInstrBuilder Call =
       MIRBuilder
           .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
                                                   : RISCV::PseudoCALL)
           .add(Info.Callee);
-  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+  const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
   Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
 
   RISCVOutgoingValueAssigner ArgAssigner(
@@ -530,6 +531,15 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
       .addImm(ArgAssigner.StackSize)
       .addImm(0);
 
+  // If Callee is a reg, since it is used by a target specific
+  // instruction, it must have a register class matching the
+  // constraint of that instruction.
+  if (Call->getOperand(0).isReg())
+    constrainOperandRegClass(MF, *TRI, MF.getRegInfo(),
+                             *Subtarget.getInstrInfo(),
+                             *Subtarget.getRegBankInfo(), *Call,
+                             Call->getDesc(), Call->getOperand(0), 0);
+
   if (Info.OrigRet.Ty->isVoidTy())
     return true;
 
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calls.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calls.ll
index 14c86a3e99e4493..e7e093f7110b863 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calls.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calls.ll
@@ -441,3 +441,27 @@ entry:
   call void @dso_local_function()
   ret void
 }
+
+define void @test_indirect_call(ptr %func) {
+  ; RV32I-LABEL: name: test_indirect_call
+  ; RV32I: bb.1 (%ir-block.0):
+  ; RV32I-NEXT:   liveins: $x10
+  ; RV32I-NEXT: {{  $}}
+  ; RV32I-NEXT:   [[COPY:%[0-9]+]]:gprjalr(p0) = COPY $x10
+  ; RV32I-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+  ; RV32I-NEXT:   PseudoCALLIndirect [[COPY]](p0), csr_ilp32_lp64, implicit-def $x1
+  ; RV32I-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+  ; RV32I-NEXT:   PseudoRET
+  ;
+  ; RV64I-LABEL: name: test_indirect_call
+  ; RV64I: bb.1 (%ir-block.0):
+  ; RV64I-NEXT:   liveins: $x10
+  ; RV64I-NEXT: {{  $}}
+  ; RV64I-NEXT:   [[COPY:%[0-9]+]]:gprjalr(p0) = COPY $x10
+  ; RV64I-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
+  ; RV64I-NEXT:   PseudoCALLIndirect [[COPY]](p0), csr_ilp32_lp64, implicit-def $x1
+  ; RV64I-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
+  ; RV64I-NEXT:   PseudoRET
+  call void %func()
+  ret void
+}



More information about the llvm-commits mailing list