Skip to content

Commit

Permalink
[LoongArch] Lower BlockAddress/JumpTable
Browse files Browse the repository at this point in the history
This patch uses a unified interface for lower GlobalAddress ConstantPool
BlockAddress and JumpTable.

This patch allows lowering addresses by using PC-relative addressing
for DSO-local symbols, and accessing the address through the global
offset table for DSO-preemptable symbols.

Remove hardcoded `MininumJumpTableEntries` for test lower JumpTable.

Also updated some test cases using ConstantPool, due to the addition of
relocation information.

Differential Revision: https://reviews.llvm.org/D134431
  • Loading branch information
wangleiat authored and SixWeining committed Sep 26, 2022
1 parent 30b676a commit 75265c7
Show file tree
Hide file tree
Showing 17 changed files with 463 additions and 95 deletions.
1 change: 1 addition & 0 deletions llvm/lib/Target/LoongArch/CMakeLists.txt
Expand Up @@ -17,6 +17,7 @@ add_public_tablegen_target(LoongArchCommonTableGen)
add_llvm_target(LoongArchCodeGen
LoongArchAsmPrinter.cpp
LoongArchExpandAtomicPseudoInsts.cpp
LoongArchExpandPseudoInsts.cpp
LoongArchFrameLowering.cpp
LoongArchInstrInfo.cpp
LoongArchISelDAGToDAG.cpp
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArch.h
Expand Up @@ -36,6 +36,9 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
FunctionPass *createLoongArchExpandAtomicPseudoPass();
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);

FunctionPass *createLoongArchPreRAExpandPseudoPass();
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
} // end namespace llvm

#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
162 changes: 162 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -0,0 +1,162 @@
//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//
//
// 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 a pass that expands pseudo instructions into target
// instructions.
//
//===----------------------------------------------------------------------===//

#include "LoongArch.h"
#include "LoongArchInstrInfo.h"
#include "LoongArchTargetMachine.h"
#include "MCTargetDesc/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/MC/MCContext.h"

using namespace llvm;

#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
"LoongArch Pre-RA pseudo instruction expansion pass"

namespace {

class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
public:
const LoongArchInstrInfo *TII;
static char ID;

LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
}

bool runOnMachineFunction(MachineFunction &MF) override;

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
StringRef getPassName() const override {
return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
}

private:
bool expandMBB(MachineBasicBlock &MBB);
bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
unsigned FlagsHi, unsigned SecondOpcode,
unsigned FlagsLo);
bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
bool expandLoadAddressGot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI);
};

char LoongArchPreRAExpandPseudo::ID = 0;

bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
TII =
static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
bool Modified = false;
for (auto &MBB : MF)
Modified |= expandMBB(MBB);
return Modified;
}

bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
bool Modified = false;

MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
while (MBBI != E) {
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
Modified |= expandMI(MBB, MBBI, NMBBI);
MBBI = NMBBI;
}

return Modified;
}

bool LoongArchPreRAExpandPseudo::expandMI(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
switch (MBBI->getOpcode()) {
case LoongArch::PseudoLA_PCREL:
return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
case LoongArch::PseudoLA_GOT:
return expandLoadAddressGot(MBB, MBBI, NextMBBI);
}
return false;
}

bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
unsigned SecondOpcode, unsigned FlagsLo) {
MachineFunction *MF = MBB.getParent();
MachineInstr &MI = *MBBI;
DebugLoc DL = MI.getDebugLoc();

Register DestReg = MI.getOperand(0).getReg();
Register ScratchReg =
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
MachineOperand &Symbol = MI.getOperand(1);

BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
.addDisp(Symbol, 0, FlagsHi);

MachineInstr *SecondMI =
BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
.addReg(ScratchReg)
.addDisp(Symbol, 0, FlagsLo);

if (MI.hasOneMemOperand())
SecondMI->addMemOperand(*MF, *MI.memoperands_begin());

MI.eraseFromParent();
return true;
}

bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
MachineFunction *MF = MBB.getParent();
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
SecondOpcode, LoongArchII::MO_PCREL_LO);
}

bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
MachineFunction *MF = MBB.getParent();
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
SecondOpcode, LoongArchII::MO_GOT_PC_LO);
}

} // end namespace

INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "LoongArch-prera-expand-pseudo",
LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)

namespace llvm {

FunctionPass *createLoongArchPreRAExpandPseudoPass() {
return new LoongArchPreRAExpandPseudo();
}

} // end namespace llvm
98 changes: 61 additions & 37 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Expand Up @@ -58,7 +58,9 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ROTL, GRLenVT, Expand);
setOperationAction(ISD::CTPOP, GRLenVT, Expand);

setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom);
setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
ISD::JumpTable},
GRLenVT, Custom);

setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);

Expand Down Expand Up @@ -128,8 +130,6 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal);
}

// Effectively disable jump table generation.
setMinimumJumpTableEntries(INT_MAX);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);

setOperationAction(ISD::BR_CC, GRLenVT, Expand);
Expand Down Expand Up @@ -180,6 +180,10 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerGlobalAddress(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN:
return lowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::BlockAddress:
return lowerBlockAddress(Op, DAG);
case ISD::JumpTable:
return lowerJumpTable(Op, DAG);
case ISD::SHL_PARTS:
return lowerShiftLeftParts(Op, DAG);
case ISD::SRA_PARTS:
Expand Down Expand Up @@ -272,46 +276,66 @@ SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op,
return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc);
}

static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,
SelectionDAG &DAG, unsigned Flags) {
return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
}

static SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty,
SelectionDAG &DAG, unsigned Flags) {
return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
Flags);
}

static SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty,
SelectionDAG &DAG, unsigned Flags) {
return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
N->getOffset(), Flags);
}

static SDValue getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,
SelectionDAG &DAG, unsigned Flags) {
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
}

template <class NodeTy>
SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
bool IsLocal) const {
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
// TODO: Check CodeModel.
if (IsLocal)
// This generates the pattern (PseudoLA_PCREL sym), which expands to
// (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr),
0);

// This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
// (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);
}

SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
return getAddr(cast<BlockAddressSDNode>(Op), DAG);
}

SDValue LoongArchTargetLowering::lowerJumpTable(SDValue Op,
SelectionDAG &DAG) const {
return getAddr(cast<JumpTableSDNode>(Op), DAG);
}

SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT Ty = Op.getValueType();
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);

// FIXME: Only support PC-relative addressing to access the symbol.
// Target flags will be added later.
if (!isPositionIndependent()) {
SDValue ConstantN = DAG.getTargetConstantPool(
N->getConstVal(), Ty, N->getAlign(), N->getOffset());
SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN),
0);
SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D
: LoongArch::ADDI_W,
DL, Ty, AddrHi, ConstantN),
0);
return Addr;
}
report_fatal_error("Unable to lower ConstantPool");
return getAddr(cast<ConstantPoolSDNode>(Op), DAG);
}

SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT Ty = getPointerTy(DAG.getDataLayout());
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;

// TODO: Support dso_preemptable and target flags.
if (GV->isDSOLocal()) {
SDValue GAHi =
DAG.getTargetGlobalAddress(GV, DL, Ty, 0, LoongArchII::MO_PCREL_HI);
SDValue GALo =
DAG.getTargetGlobalAddress(GV, DL, Ty, 0, LoongArchII::MO_PCREL_LO);
SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GAHi), 0);

return SDValue(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GALo), 0);
}
report_fatal_error("Unable to lowerGlobalAddress");
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
assert(N->getOffset() == 0 && "unexpected offset in global node");
return getAddr(N, DAG, N->getGlobal()->isDSOLocal());
}

SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Expand Up @@ -130,7 +130,11 @@ class LoongArchTargetLowering : public TargetLowering {
bool IsRet, CallLoweringInfo *CLI,
LoongArchCCAssignFn Fn) const;

template <class NodeTy>
SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;

Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Expand Up @@ -919,6 +919,12 @@ let isBarrier = 1, isReturn = 1, isTerminator = 1 in
def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
PseudoInstExpansion<(JIRL R0, R1, 0)>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;

let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;

/// BSTRINS and BSTRPICK

let Predicates = [IsLA32] in {
Expand Down
11 changes: 10 additions & 1 deletion llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
Expand Up @@ -47,6 +47,12 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case LoongArchII::MO_PCREL_LO:
Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
break;
case LoongArchII::MO_GOT_PC_HI:
Kind = LoongArchMCExpr::VK_LoongArch_GOT_HI20;
break;
case LoongArchII::MO_GOT_PC_LO:
Kind = LoongArchMCExpr::VK_LoongArch_GOT_LO12;
break;
// TODO: Handle more target-flags.
}

Expand Down Expand Up @@ -94,9 +100,12 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
MCOp = lowerSymbolOperand(
MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
break;
// TODO: lower special operands
case MachineOperand::MO_BlockAddress:
MCOp = lowerSymbolOperand(
MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
break;
case MachineOperand::MO_JumpTableIndex:
MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
break;
}
return true;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
Expand Up @@ -27,6 +27,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
// Register the target.
RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
auto *PR = PassRegistry::getPassRegistry();
initializeLoongArchPreRAExpandPseudoPass(*PR);
}

static std::string computeDataLayout(const Triple &TT) {
Expand Down Expand Up @@ -103,6 +105,7 @@ class LoongArchPassConfig : public TargetPassConfig {
void addIRPasses() override;
bool addInstSelector() override;
void addPreEmitPass2() override;
void addPreRegAlloc() override;
};
} // end namespace

Expand All @@ -129,3 +132,7 @@ void LoongArchPassConfig::addPreEmitPass2() {
// forward progress in the LL/SC block.
addPass(createLoongArchExpandAtomicPseudoPass());
}

void LoongArchPassConfig::addPreRegAlloc() {
addPass(createLoongArchPreRAExpandPseudoPass());
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
Expand Up @@ -31,6 +31,8 @@ enum {
MO_CALL_PLT,
MO_PCREL_HI,
MO_PCREL_LO,
MO_GOT_PC_HI,
MO_GOT_PC_LO,
// TODO: Add more flags.
};
} // end namespace LoongArchII
Expand Down

0 comments on commit 75265c7

Please sign in to comment.