diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2020-12-01 13:30:14 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2020-12-01 13:30:14 +0000 |
commit | 7f433b1b8cc6c4e59fd40ccf6c8bd00642ccd8fd (patch) | |
tree | 61b71474ddaf99549952102c82bd594c8555efe2 /gnu | |
parent | 3b62c1161f7bae29d5920d4ce12309099b69afa5 (diff) |
Implement Loongson 2F BTB bug workaround in clang
This adapts the -mfix-loongson2f-btb workaround from as(1) to
LLVM/clang. Because LLVM emits machine code directly without using
assembly as intermediary form, the workaround has to be applied
in the compiler backend in addition to the integrated assembler.
Discussed with miod@
OK mortimer@
Diffstat (limited to 'gnu')
8 files changed, 162 insertions, 1 deletions
diff --git a/gnu/llvm/clang/include/clang/Driver/Options.td b/gnu/llvm/clang/include/clang/Driver/Options.td index 98991a57abb..ff76bcb7ef7 100644 --- a/gnu/llvm/clang/include/clang/Driver/Options.td +++ b/gnu/llvm/clang/include/clang/Driver/Options.td @@ -2536,6 +2536,8 @@ def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, Group<m_mips_Features_Group>; def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group<m_mips_Features_Group>; +def mfix_loongson2f_btb : Flag<["-"], "mfix-loongson2f-btb">, + Group<m_mips_Features_Group>; def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>, IgnoredGCCCompat; def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group<m_Group>, diff --git a/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp b/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp index c8e4003875a..03f637113d1 100644 --- a/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp +++ b/gnu/llvm/clang/lib/Driver/ToolChains/Clang.cpp @@ -2366,6 +2366,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-soft-float"); continue; } + if (Value.startswith("-mfix-loongson2f-btb")) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-fix-loongson2f-btb"); + continue; + } MipsTargetFeature = llvm::StringSwitch<const char *>(Value) .Case("-mips1", "+mips1") diff --git a/gnu/llvm/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/gnu/llvm/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index e467ed36938..05bc5b2e23a 100644 --- a/gnu/llvm/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/gnu/llvm/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -68,6 +68,7 @@ class MCInstrInfo; } // end namespace llvm extern cl::opt<bool> EmitJalrReloc; +extern cl::opt<bool> FixLoongson2FBTB; namespace { @@ -234,6 +235,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym); + bool emitLoongson2FBTBFlush(MCInst &Inst, MipsTargetStreamer &TOut, + SMLoc IDLoc, const MCSubtargetInfo *STI); + bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -2088,6 +2092,19 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Inst = BInst; } + if (FixLoongson2FBTB) { + switch (Inst.getOpcode()) { + case Mips::JALR: + case Mips::JR: + case Mips::JalOneReg: + case Mips::JalTwoReg: + if (emitLoongson2FBTBFlush(Inst, TOut, IDLoc, STI)) + return true; + default: + break; + } + } + // This expansion is not in a function called by tryExpandInstruction() // because the pseudo-instruction doesn't have a distinct opcode. if ((Opcode == Mips::JAL || Opcode == Mips::JAL_MM) && inPicMode()) { @@ -3309,6 +3326,39 @@ bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, return false; } +bool MipsAsmParser::emitLoongson2FBTBFlush(MCInst &Inst, + MipsTargetStreamer &TOut, + SMLoc IDLoc, + const MCSubtargetInfo *STI) { + unsigned SReg = Inst.getOperand(0).getReg(); + if (SReg == Mips::ZERO || SReg == Mips::ZERO_64 || + SReg == Mips::K0 || SReg == Mips::K0_64 || + SReg == Mips::K1 || SReg == Mips::K1_64) + return false; + + unsigned ATReg = getATReg(IDLoc); + if (ATReg == 0) + return true; + + // Direct comparison of SReg and ATReg is not reliable because + // the register classes may differ. + unsigned ATRegIndex = AssemblerOptions.back()->getATRegIndex(); + if (ATRegIndex == 0) + return true; + if (SReg == getReg(Mips::GPR32RegClassID, ATRegIndex) || + SReg == getReg(Mips::GPR64RegClassID, ATRegIndex)) + return false; + + warnIfNoMacro(IDLoc); + + // li $at, COP_0_BTB_CLEAR | COP_0_RAS_DISABLE + TOut.emitRRI(Mips::ORi, ATReg, Mips::ZERO, 3, IDLoc, STI); + // dmtc0 $at, COP_0_DIAG + TOut.emitRRI(Mips::DMTC0, Mips::COP022, ATReg, 0, IDLoc, STI); + + return false; +} + static uint64_t convertIntToDoubleImm(uint64_t ImmOp64) { // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the // exponent field), convert it to double (e.g. 1 to 1.0) diff --git a/gnu/llvm/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/gnu/llvm/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 37e970f2f15..8a1bee71b8d 100644 --- a/gnu/llvm/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/gnu/llvm/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -22,6 +22,11 @@ EmitJalrReloc("mips-jalr-reloc", cl::Hidden, cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), cl::init(true)); +cl::opt<bool> +FixLoongson2FBTB("fix-loongson2f-btb", cl::Hidden, + cl::desc("MIPS: Enable Loongson 2F BTB workaround"), + cl::init(false)); + namespace { static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; diff --git a/gnu/llvm/llvm/lib/Target/Mips/Mips.h b/gnu/llvm/llvm/lib/Target/Mips/Mips.h index b3faaab436f..3729a328159 100644 --- a/gnu/llvm/llvm/lib/Target/Mips/Mips.h +++ b/gnu/llvm/llvm/lib/Target/Mips/Mips.h @@ -38,6 +38,7 @@ namespace llvm { FunctionPass *createMicroMipsSizeReducePass(); FunctionPass *createMipsExpandPseudoPass(); FunctionPass *createMipsPreLegalizeCombiner(); + FunctionPass *createMipsLoongson2FBTBFix(); InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &, MipsSubtarget &, @@ -47,6 +48,7 @@ namespace llvm { void initializeMipsBranchExpansionPass(PassRegistry &); void initializeMicroMipsSizeReducePass(PassRegistry &); void initializeMipsPreLegalizerCombinerPass(PassRegistry&); + void initializeMipsLoongson2FBTBFixPass(PassRegistry &); } // end namespace llvm; #endif diff --git a/gnu/llvm/llvm/lib/Target/Mips/MipsLoongson2FBTBFix.cpp b/gnu/llvm/llvm/lib/Target/Mips/MipsLoongson2FBTBFix.cpp new file mode 100644 index 00000000000..44fb84a3018 --- /dev/null +++ b/gnu/llvm/llvm/lib/Target/Mips/MipsLoongson2FBTBFix.cpp @@ -0,0 +1,91 @@ +//===- MipsLoongson2FBTBFix.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Mips.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +namespace { + +class MipsLoongson2FBTBFix : public MachineFunctionPass { +public: + static char ID; + + MipsLoongson2FBTBFix() : MachineFunctionPass(ID) { + initializeMipsLoongson2FBTBFixPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + StringRef getPassName() const override { + return "Loongson 2F BTB erratum workaround pass"; + } + +private: + bool runOnBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB); +}; + +} // end of anonymous namespace + +char MipsLoongson2FBTBFix::ID = 0; + +INITIALIZE_PASS(MipsLoongson2FBTBFix, "loongson2f-btb-fix-pass", + "Mips Loongson 2F BTB erratum workaround", false, false) + +FunctionPass *llvm::createMipsLoongson2FBTBFix() { + return new MipsLoongson2FBTBFix(); +} + +bool MipsLoongson2FBTBFix::runOnMachineFunction(MachineFunction &MF) { + bool Changed = false; + + for (auto &MBB : MF) { + Changed |= runOnBasicBlock(MF, MBB); + } + return Changed; +} + +bool MipsLoongson2FBTBFix::runOnBasicBlock( + MachineFunction &MF, MachineBasicBlock &MBB) { + MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + bool Changed = false; + + for (auto &MI : MBB) { + if (!MI.isCall() && !MI.isIndirectBranch() && !MI.isReturn()) + continue; + + // Skip calls that are not through a register. + if (MI.isCall()) { + if (MI.getNumOperands() == 0) + continue; + const MachineOperand &MO = MI.getOperand(0); + if (!MO.isReg()) + continue; + } + + Changed = true; + + DebugLoc MBBDL = MI.getDebugLoc(); + Register TempReg = MRI.createVirtualRegister(&Mips::GPR64RegClass); + + // li $TempReg, COP_0_BTB_CLEAR | COP_0_RAS_DISABLE + BuildMI(MBB, MI, MBBDL, TII->get(Mips::ORi), TempReg) + .addReg(Mips::ZERO) + .addImm(3); + // dmtc0 $TempReg, COP_0_DIAG + BuildMI(MBB, MI, MBBDL, TII->get(Mips::DMTC0)) + .addReg(Mips::COP022) + .addReg(TempReg) + .addImm(0); + } + return Changed; +} diff --git a/gnu/llvm/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/gnu/llvm/llvm/lib/Target/Mips/MipsTargetMachine.cpp index 8fec6db00cb..607b8302b43 100644 --- a/gnu/llvm/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/gnu/llvm/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -45,6 +45,8 @@ using namespace llvm; #define DEBUG_TYPE "mips" +extern cl::opt<bool> FixLoongson2FBTB; + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() { // Register the target. RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget()); @@ -277,6 +279,9 @@ bool MipsPassConfig::addInstSelector() { void MipsPassConfig::addPreRegAlloc() { addPass(createMipsOptimizePICCallPass()); + + if (FixLoongson2FBTB) + addPass(createMipsLoongson2FBTBFix()); } TargetTransformInfo diff --git a/gnu/usr.bin/clang/libLLVMMipsCodeGen/Makefile b/gnu/usr.bin/clang/libLLVMMipsCodeGen/Makefile index 85d7aaffe9a..899e2b64389 100644 --- a/gnu/usr.bin/clang/libLLVMMipsCodeGen/Makefile +++ b/gnu/usr.bin/clang/libLLVMMipsCodeGen/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.8 2020/08/03 14:45:26 patrick Exp $ +# $OpenBSD: Makefile,v 1.9 2020/12/01 13:30:13 visa Exp $ LIB= LLVMMipsCodeGen NOPROFILE= @@ -28,6 +28,7 @@ SRCS+= MicroMipsSizeReduction.cpp \ MipsInstrInfo.cpp \ MipsInstructionSelector.cpp \ MipsLegalizerInfo.cpp \ + MipsLoongson2FBTBFix.cpp \ MipsMCInstLower.cpp \ MipsMachineFunction.cpp \ MipsModuleISelDAGToDAG.cpp \ |