diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -66,6 +66,7 @@ void emitDirectiveOptionNoRVC() override; void emitDirectiveOptionRelax() override; void emitDirectiveOptionNoRelax() override; + void emitDirectiveVariantCC(MCSymbol &Symbol) override; }; } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -13,6 +13,7 @@ #include "RISCVTargetStreamer.h" #include "RISCVBaseInfo.h" #include "RISCVMCTargetDesc.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/RISCVAttributes.h" #include "llvm/Support/RISCVISAInfo.h" @@ -98,6 +99,10 @@ OS << "\t.option\tnorelax\n"; } +void RISCVTargetAsmStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) { + OS << "\t.variant_cc\t" << Symbol.getName() << "\n"; +} + void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { OS << "\t.attribute\t" << Attribute << ", " << Twine(Value) << "\n"; } diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -15,6 +15,7 @@ #include "MCTargetDesc/RISCVMCExpr.h" #include "MCTargetDesc/RISCVTargetStreamer.h" #include "RISCV.h" +#include "RISCVMachineFunctionInfo.h" #include "RISCVTargetMachine.h" #include "TargetInfo/RISCVTargetInfo.h" #include "llvm/ADT/Statistic.h" @@ -81,6 +82,8 @@ void emitStartOfAsmFile(Module &M) override; void emitEndOfAsmFile(Module &M) override; + void emitFunctionEntryLabel() override; + private: void emitAttributes(); }; @@ -225,6 +228,16 @@ RTS.emitTargetAttributes(*MCSTI); } +void RISCVAsmPrinter::emitFunctionEntryLabel() { + const auto *RMFI = MF->getInfo(); + if (RMFI->isVectorCall()) { + auto &RTS = + static_cast(*OutStreamer->getTargetStreamer()); + RTS.emitDirectiveVariantCC(*CurrentFnSym); + } + return AsmPrinter::emitFunctionEntryLabel(); +} + // Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() { RegisterAsmPrinter X(getTheRISCV32Target()); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -11956,6 +11956,10 @@ InVals.push_back(ArgValue); } + if (any_of(ArgLocs, + [](CCValAssign &VA) { return VA.getLocVT().isScalableVector(); })) + MF.getInfo()->setIsVectorCall(); + if (IsVarArg) { ArrayRef ArgRegs = makeArrayRef(ArgGPRs); unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); @@ -12426,7 +12430,7 @@ const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { - const MachineFunction &MF = DAG.getMachineFunction(); + MachineFunction &MF = DAG.getMachineFunction(); const RISCVSubtarget &STI = MF.getSubtarget(); // Stores the assignment of the return value to a location. @@ -12497,6 +12501,10 @@ RetOps.push_back(Glue); } + if (any_of(RVLocs, + [](CCValAssign &VA) { return VA.getLocVT().isScalableVector(); })) + MF.getInfo()->setIsVectorCall(); + unsigned RetOpc = RISCVISD::RET_FLAG; // Interrupt service routines use different return instructions. const Function &Func = DAG.getMachineFunction().getFunction(); diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h --- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h +++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h @@ -65,6 +65,8 @@ uint64_t RVVPadding = 0; /// Size of stack frame to save callee saved registers unsigned CalleeSavedStackSize = 0; + /// Is there any vector argument or return? + bool IsVectorCall = false; /// Registers that have been sign extended from i32. SmallVector SExt32Registers; @@ -124,6 +126,9 @@ void addSExt32Register(Register Reg); bool isSExt32Register(Register Reg) const; + + bool isVectorCall() const { return IsVectorCall; } + void setIsVectorCall() { IsVectorCall = true; } }; } // end namespace llvm diff --git a/llvm/test/CodeGen/RISCV/rvv/variant-cc.ll b/llvm/test/CodeGen/RISCV/rvv/variant-cc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/variant-cc.ll @@ -0,0 +1,51 @@ +; RUN: llc -mtriple=riscv64 -mattr=+v -o - %s | FileCheck %s --check-prefix=CHECK-ASM +; RUN: llc -mtriple=riscv64 -mattr=+v -filetype=obj -o - %s \ +; RUN: | llvm-readobj --symbols - | FileCheck %s --check-prefix=CHECK-OBJ + +define i32 @base_cc() { +; CHECK-ASM-LABEL: base_cc: +; CHECK-ASM-NOT: .variant_cc +; CHECK-OBJ-LABEL: Name: base_cc +; CHECK-OBJ: Other: 0 + ret i32 42 +} + +define <4 x i32> @fixed_vector_cc_1(<4 x i32> %arg) { +; CHECK-ASM: .variant_cc fixed_vector_cc_1 +; CHECK-ASM-NEXT: fixed_vector_cc_1: +; CHECK-OBJ-LABEL: Name: fixed_vector_cc_1 +; CHECK-OBJ: Other [ (0x80) + ret <4 x i32> %arg +} + +define @rvv_vector_cc_1() { +; CHECK-ASM: .variant_cc rvv_vector_cc_1 +; CHECK-ASM-NEXT: rvv_vector_cc_1: +; CHECK-OBJ-LABEL: Name: rvv_vector_cc_1 +; CHECK-OBJ: Other [ (0x80) + ret undef +} + +define @rvv_vector_cc_2() { +; CHECK-ASM: .variant_cc rvv_vector_cc_2 +; CHECK-ASM-NEXT: rvv_vector_cc_2: +; CHECK-OBJ-LABEL: Name: rvv_vector_cc_2 +; CHECK-OBJ: Other [ (0x80) + ret undef +} + +define void @rvv_vector_cc_3( %arg) { +; CHECK-ASM: .variant_cc rvv_vector_cc_3 +; CHECK-ASM-NEXT: rvv_vector_cc_3: +; CHECK-OBJ-LABEL: Name: rvv_vector_cc_3 +; CHECK-OBJ: Other [ (0x80) + ret void +} + +define void @rvv_vector_cc_4( %arg) { +; CHECK-ASM: .variant_cc rvv_vector_cc_4 +; CHECK-ASM-NEXT: rvv_vector_cc_4: +; CHECK-OBJ-LABEL: Name: rvv_vector_cc_4 +; CHECK-OBJ: Other [ (0x80) + ret void +}