Since the `RISCVExpandPseudo` pass has been split from `RISCVExpandAtomicPseudo` pass, it would be nice to run the former as early as possible (The latter has to be run as late as possible to ensure correctness). Running earlier means we can reschedule these pairs as we see fit. Running earlier in the machine pass pipeline is good, but would mean teaching many more passes about `hasLabelMustBeEmitted`. Splitting the basic blocks also pessimises possible optimisations because some optimisations are MBB-local, and others are disabled if the block has its address taken (which is notionally what `hasLabelMustBeEmitted` means). This patch uses a new approach of setting the pre-instruction symbol on the AUIPC instruction to a temporary symbol and referencing that. This avoids splitting the basic block, but allows us to reference exactly the instruction that we need to. Notionally, this approach seems more correct because we do actually want to address a specific instruction. This then allows the pass to be moved much earlier in the pass pipeline, before both scheduling and register allocation. However, to do so we must leave the MIR in SSA form (by not redefining registers), and so use a virtual register for the intermediate value. By using this virtual register, this pass now has to come before register allocation. Reviewed By: luismarques, asb Differential Revision: https://reviews.llvm.org/D82988
141 lines
4.4 KiB
C++
141 lines
4.4 KiB
C++
//===-- RISCVMCInstLower.cpp - Convert RISCV MachineInstr to an MCInst ------=//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains code to lower RISCV MachineInstrs to their corresponding
|
|
// MCInst records.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RISCV.h"
|
|
#include "MCTargetDesc/RISCVMCExpr.h"
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCInst.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
|
|
const AsmPrinter &AP) {
|
|
MCContext &Ctx = AP.OutContext;
|
|
RISCVMCExpr::VariantKind Kind;
|
|
|
|
switch (MO.getTargetFlags()) {
|
|
default:
|
|
llvm_unreachable("Unknown target flag on GV operand");
|
|
case RISCVII::MO_None:
|
|
Kind = RISCVMCExpr::VK_RISCV_None;
|
|
break;
|
|
case RISCVII::MO_CALL:
|
|
Kind = RISCVMCExpr::VK_RISCV_CALL;
|
|
break;
|
|
case RISCVII::MO_PLT:
|
|
Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
|
|
break;
|
|
case RISCVII::MO_LO:
|
|
Kind = RISCVMCExpr::VK_RISCV_LO;
|
|
break;
|
|
case RISCVII::MO_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_HI;
|
|
break;
|
|
case RISCVII::MO_PCREL_LO:
|
|
Kind = RISCVMCExpr::VK_RISCV_PCREL_LO;
|
|
break;
|
|
case RISCVII::MO_PCREL_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_PCREL_HI;
|
|
break;
|
|
case RISCVII::MO_GOT_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_GOT_HI;
|
|
break;
|
|
case RISCVII::MO_TPREL_LO:
|
|
Kind = RISCVMCExpr::VK_RISCV_TPREL_LO;
|
|
break;
|
|
case RISCVII::MO_TPREL_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_TPREL_HI;
|
|
break;
|
|
case RISCVII::MO_TPREL_ADD:
|
|
Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD;
|
|
break;
|
|
case RISCVII::MO_TLS_GOT_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI;
|
|
break;
|
|
case RISCVII::MO_TLS_GD_HI:
|
|
Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI;
|
|
break;
|
|
}
|
|
|
|
const MCExpr *ME =
|
|
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
|
|
|
|
if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
|
|
ME = MCBinaryExpr::createAdd(
|
|
ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
|
|
|
|
if (Kind != RISCVMCExpr::VK_RISCV_None)
|
|
ME = RISCVMCExpr::create(ME, Kind, Ctx);
|
|
return MCOperand::createExpr(ME);
|
|
}
|
|
|
|
bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
|
|
MCOperand &MCOp,
|
|
const AsmPrinter &AP) {
|
|
switch (MO.getType()) {
|
|
default:
|
|
report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type");
|
|
case MachineOperand::MO_Register:
|
|
// Ignore all implicit register operands.
|
|
if (MO.isImplicit())
|
|
return false;
|
|
MCOp = MCOperand::createReg(MO.getReg());
|
|
break;
|
|
case MachineOperand::MO_RegisterMask:
|
|
// Regmasks are like implicit defs.
|
|
return false;
|
|
case MachineOperand::MO_Immediate:
|
|
MCOp = MCOperand::createImm(MO.getImm());
|
|
break;
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
|
|
break;
|
|
case MachineOperand::MO_GlobalAddress:
|
|
MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP);
|
|
break;
|
|
case MachineOperand::MO_BlockAddress:
|
|
MCOp = lowerSymbolOperand(
|
|
MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
|
|
break;
|
|
case MachineOperand::MO_ExternalSymbol:
|
|
MCOp = lowerSymbolOperand(
|
|
MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
|
|
break;
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
|
MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
|
|
break;
|
|
case MachineOperand::MO_MCSymbol:
|
|
MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), AP);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
|
|
const AsmPrinter &AP) {
|
|
OutMI.setOpcode(MI->getOpcode());
|
|
|
|
for (const MachineOperand &MO : MI->operands()) {
|
|
MCOperand MCOp;
|
|
if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP))
|
|
OutMI.addOperand(MCOp);
|
|
}
|
|
}
|