diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp index f7d11e921c7de..3b23a14428913 100644 --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -36,6 +36,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/RISCVISAInfo.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" @@ -46,6 +47,10 @@ using namespace llvm; STATISTIC(RISCVNumInstrsCompressed, "Number of RISC-V Compressed instructions emitted"); +namespace llvm { +extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]; +} // namespace llvm + namespace { class RISCVAsmPrinter : public AsmPrinter { const RISCVSubtarget *STI; @@ -83,6 +88,8 @@ class RISCVAsmPrinter : public AsmPrinter { void emitEndOfAsmFile(Module &M) override; void emitFunctionEntryLabel() override; + void emitDirectiveOptionArch(); + bool isSameAttribute(); private: void emitAttributes(); @@ -238,11 +245,45 @@ bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } +void RISCVAsmPrinter::emitDirectiveOptionArch() { + RISCVTargetStreamer &RTS = + static_cast(*OutStreamer->getTargetStreamer()); + SmallVector NeedEmitStdOptionArgs; + const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo(); + for (const auto &Feature : RISCVFeatureKV) { + if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value)) + continue; + + if (!llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key)) + continue; + + auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus + : RISCVOptionArchArgType::Minus; + NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key); + } + if (!NeedEmitStdOptionArgs.empty()) + RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs); +} + +bool RISCVAsmPrinter::isSameAttribute() { + const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo(); + return MCSTI.getFeatureBits() == STI->getFeatureBits(); +} + bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) { STI = &MF.getSubtarget(); + RISCVTargetStreamer &RTS = + static_cast(*OutStreamer->getTargetStreamer()); + if (!isSameAttribute()) { + RTS.emitDirectiveOptionPush(); + emitDirectiveOptionArch(); + } SetupMachineFunction(MF); emitFunctionBody(); + + if (!isSameAttribute()) + RTS.emitDirectiveOptionPop(); return false; } diff --git a/llvm/test/CodeGen/RISCV/riscv-func-target-feature.ll b/llvm/test/CodeGen/RISCV/riscv-func-target-feature.ll new file mode 100644 index 0000000000000..6764b1e850d3f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/riscv-func-target-feature.ll @@ -0,0 +1,36 @@ +; RUN: llc -mtriple=riscv64 -mcpu=sifive-u74 -verify-machineinstrs < %s | FileCheck %s + +; CHECK: .option push +; CHECK-NEXT: .option arch, +v, +zve32f, +zve32x, +zve64d, +zve64f, +zve64x, +zvl128b, +zvl32b, +zvl64b +define void @test1() "target-features"="+a,+d,+f,+m,+c,+v,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" { +; CHECK-LABEL: test1 +; CHECK: .option pop +entry: + ret void +} + +; CHECK: .option push +; CHECK-NEXT: .option arch, +experimental-zihintntl +define void @test2() "target-features"="+a,+d,+f,+m,+experimental-zihintntl,+zifencei" { +; CHECK-LABEL: test2 +; CHECK: .option pop +entry: + ret void +} + +; CHECK: .option push +; CHECK-NEXT: .option arch, -a, -d, -f, -m +define void @test3() "target-features"="-a,-d,-f,-m" { +; CHECK-LABEL: test3 +; CHECK: .option pop +entry: + ret void +} + +; CHECK-NOT: .option push +define void @test4() { +; CHECK-LABEL: test4 +; CHECK-NOT: .option pop +entry: + ret void +}