Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,45 @@ static void getOperandsForBranch(Register CondReg, RISCVCC::CondCode &CC,
CC = getRISCVCCFromICmp(Pred);
}

/// Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation
/// \p GenericOpc, appropriate for the GPR register bank and of memory access
/// size \p OpSize.
static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
switch (OpSize) {
default:
llvm_unreachable("Unexpected memory size");
case 8:
return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
case 16:
return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
case 32:
return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
case 64:
return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
}
}

/// Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation
/// \p GenericOpc, appropriate for the GPR register bank and of memory access
/// size \p OpSize. \returns \p GenericOpc if the combination is unsupported.
static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
switch (OpSize) {
case 8:
// Prefer unsigned due to no c.lb in Zcb.
return IsStore ? RISCV::SB : RISCV::LBU;
case 16:
return IsStore ? RISCV::SH : RISCV::LH;
case 32:
return IsStore ? RISCV::SW : RISCV::LW;
case 64:
return IsStore ? RISCV::SD : RISCV::LD;
}

return GenericOpc;
}

bool RISCVInstructionSelector::select(MachineInstr &MI) {
MachineIRBuilder MIB(MI);

Expand Down Expand Up @@ -836,6 +875,59 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectImplicitDef(MI, MIB);
case TargetOpcode::G_UNMERGE_VALUES:
return selectUnmergeValues(MI, MIB);
case TargetOpcode::G_LOAD:
case TargetOpcode::G_STORE: {
GLoadStore &LdSt = cast<GLoadStore>(MI);
const Register ValReg = LdSt.getReg(0);
const Register PtrReg = LdSt.getPointerReg();
LLT PtrTy = MRI->getType(PtrReg);

const RegisterBank &RB = *RBI.getRegBank(ValReg, *MRI, TRI);
if (RB.getID() != RISCV::GPRBRegBankID)
return false;

#ifndef NDEBUG
const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, *MRI, TRI);
// Check that the pointer register is valid.
assert(PtrRB.getID() == RISCV::GPRBRegBankID &&
"Load/Store pointer operand isn't a GPR");
assert(PtrTy.isPointer() && "Load/Store pointer operand isn't a pointer");
#endif

// Can only handle AddressSpace 0.
if (PtrTy.getAddressSpace() != 0)
return false;

unsigned MemSize = LdSt.getMemSizeInBits().getValue();
AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();

if (isStrongerThanMonotonic(Order)) {
MI.setDesc(TII.get(selectZalasrLoadStoreOp(Opc, MemSize)));
return constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
}

const unsigned NewOpc = selectRegImmLoadStoreOp(MI.getOpcode(), MemSize);
if (NewOpc == MI.getOpcode())
return false;

// Check if we can fold anything into the addressing mode.
auto AddrModeFns = selectAddrRegImm(MI.getOperand(1));
if (!AddrModeFns)
return false;

// Folded something. Create a new instruction and return it.
auto NewInst = MIB.buildInstr(NewOpc, {}, {}, MI.getFlags());
if (isa<GStore>(MI))
NewInst.addUse(ValReg);
else
NewInst.addDef(ValReg);
NewInst.cloneMemRefs(MI);
for (auto &Fn : *AddrModeFns)
Fn(NewInst);
MI.eraseFromParent();

return constrainSelectedInstRegOperands(*NewInst, TII, TRI, RBI);
}
default:
return false;
}
Expand Down
28 changes: 0 additions & 28 deletions llvm/lib/Target/RISCV/RISCVGISel.td
Original file line number Diff line number Diff line change
Expand Up @@ -100,39 +100,11 @@ def : LdPat<load, LD, PtrVT>;
def : StPat<store, SD, GPR, PtrVT>;
}

// Load and store patterns for i16, needed because Zfh makes s16 load/store
// legal and regbank select may not constrain registers to FP.
def : LdPat<load, LH, i16>;
def : StPat<store, SH, GPR, i16>;

def : LdPat<extloadi8, LBU, i16>; // Prefer unsigned due to no c.lb in Zcb.
def : StPat<truncstorei8, SB, GPR, i16>;

let Predicates = [HasAtomicLdSt] in {
// Prefer unsigned due to no c.lb in Zcb.
def : LdPat<relaxed_load<atomic_load_aext_8>, LBU, i16>;
def : LdPat<relaxed_load<atomic_load_nonext_16>, LH, i16>;

def : StPat<relaxed_store<atomic_store_8>, SB, GPR, i16>;
def : StPat<relaxed_store<atomic_store_16>, SH, GPR, i16>;
}

let Predicates = [HasAtomicLdSt, IsRV64] in {
// Load pattern is in RISCVInstrInfoA.td and shared with RV32.
def : StPat<relaxed_store<atomic_store_32>, SW, GPR, i32>;
}

//===----------------------------------------------------------------------===//
// RV64 i32 patterns not used by SelectionDAG
//===----------------------------------------------------------------------===//

let Predicates = [IsRV64] in {
def : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb.
def : LdPat<extloadi16, LH, i32>;

def : StPat<truncstorei8, SB, GPR, i32>;
def : StPat<truncstorei16, SH, GPR, i32>;

def : Pat<(sext (i32 GPR:$src)), (ADDIW GPR:$src, 0)>;

def : Pat<(sext_inreg (i64 (add GPR:$rs1, simm12_lo:$imm)), i32),
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ def : LdPat<sextloadi8, LB>;
def : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb.
def : LdPat<sextloadi16, LH>;
def : LdPat<extloadi16, LH>;
def : LdPat<load, LW, i32>;
def : LdPat<load, LW, i32>, Requires<[IsRV32]>;
def : LdPat<zextloadi8, LBU>;
def : LdPat<zextloadi16, LHU>;

Expand All @@ -1994,7 +1994,7 @@ class StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,

def : StPat<truncstorei8, SB, GPR, XLenVT>;
def : StPat<truncstorei16, SH, GPR, XLenVT>;
def : StPat<store, SW, GPR, i32>;
def : StPat<store, SW, GPR, i32>, Requires<[IsRV32]>;

/// Fences

Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfoA.td
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,9 @@ let Predicates = [HasAtomicLdSt] in {
def : StPat<relaxed_store<atomic_store_8>, SB, GPR, XLenVT>;
def : StPat<relaxed_store<atomic_store_16>, SH, GPR, XLenVT>;
def : StPat<relaxed_store<atomic_store_32>, SW, GPR, XLenVT>;
}

// Used by GISel for RV32 and RV64.
let Predicates = [HasAtomicLdSt, IsRV32] in {
def : LdPat<relaxed_load<atomic_load_nonext_32>, LW, i32>;
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ let Predicates = [HasStdExtZalasr] in {
} // Predicates = [HasStdExtZalasr]

let Predicates = [HasStdExtZalasr, IsRV32] in {
def : PatLAQ<acquiring_load<atomic_load_nonext_32>, LW_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_nonext_32>, LW_AQ>;
def : PatLAQ<acquiring_load<atomic_load_nonext_32>, LW_AQ, i32>;
def : PatLAQ<seq_cst_load<atomic_load_nonext_32>, LW_AQ, i32>;
} // Predicates = [HasStdExtZalasr, IsRV32]

let Predicates = [HasStdExtZalasr, IsRV64] in {
Expand Down
Loading