Skip to content
Merged
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
29 changes: 29 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22291,6 +22291,35 @@ unsigned RISCVTargetLowering::getCustomCtpopCost(EVT VT,
return isCtpopFast(VT) ? 0 : 1;
}

bool RISCVTargetLowering::shouldInsertFencesForAtomic(
const Instruction *I) const {
if (Subtarget.hasStdExtZalasr()) {
if (Subtarget.hasStdExtZtso()) {
// Zalasr + TSO means that atomic_load_acquire and atomic_store_release
// should be lowered to plain load/store. The easiest way to do this is
// to say we should insert fences for them, and the fence insertion code
// will just not insert any fences
auto *LI = dyn_cast<LoadInst>(I);
auto *SI = dyn_cast<StoreInst>(I);
if ((LI &&
(LI->getOrdering() == AtomicOrdering::SequentiallyConsistent)) ||
(SI &&
(SI->getOrdering() == AtomicOrdering::SequentiallyConsistent))) {
// Here, this is a load or store which is seq_cst, and needs a .aq or
// .rl therefore we shouldn't try to insert fences
return false;
}
// Here, we are a TSO inst that isn't a seq_cst load/store
return isa<LoadInst>(I) || isa<StoreInst>(I);
}
return false;
}
// Note that one specific case requires fence insertion for an
// AtomicCmpXchgInst but is handled via the RISCVZacasABIFix pass rather
// than this hook due to limitations in the interface here.
return isa<LoadInst>(I) || isa<StoreInst>(I);
}

bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const {

// GISel support is in progress or complete for these opcodes.
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,8 @@ class RISCVTargetLowering : public TargetLowering {
// Note that one specific case requires fence insertion for an
// AtomicCmpXchgInst but is handled via the RISCVZacasABIFix pass rather
// than this hook due to limitations in the interface here.
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
return isa<LoadInst>(I) || isa<StoreInst>(I);
}
bool shouldInsertFencesForAtomic(const Instruction *I) const override;

Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst,
AtomicOrdering Ord) const override;
Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst,
Expand Down
70 changes: 62 additions & 8 deletions llvm/lib/Target/RISCV/RISCVInstrInfoA.td
Original file line number Diff line number Diff line change
Expand Up @@ -118,22 +118,65 @@ defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//

let IsAtomic = 1 in {
// An atomic load operation that does not need either acquire or release
// semantics.
class relaxed_load<PatFrags base>
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
let IsAtomicOrderingAcquireOrStronger = 0;
}

// A atomic load operation that actually needs acquire semantics.
class acquiring_load<PatFrags base>
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
let IsAtomicOrderingAcquire = 1;
}

// An atomic load operation that needs sequential consistency.
class seq_cst_load<PatFrags base>
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
let IsAtomicOrderingSequentiallyConsistent = 1;
}

// An atomic store operation that does not need either acquire or release
// semantics.
class relaxed_store<PatFrag base>
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
let IsAtomicOrderingReleaseOrStronger = 0;
}

// A store operation that actually needs release semantics.
class releasing_store<PatFrag base>
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
let IsAtomicOrderingRelease = 1;
}

// A store operation that actually needs sequential consistency.
class seq_cst_store<PatFrag base>
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
let IsAtomicOrderingSequentiallyConsistent = 1;
}
} // IsAtomic = 1

// Atomic load/store are available under both +a and +force-atomics.
// Fences will be inserted for atomic load/stores according to the logic in
// RISCVTargetLowering::{emitLeadingFence,emitTrailingFence}.
// The normal loads/stores are relaxed (unordered) loads/stores that don't have
// any ordering. This is necessary because AtomicExpandPass has added fences to
// atomic load/stores and changed them to unordered ones.
let Predicates = [HasAtomicLdSt] in {
def : LdPat<atomic_load_8, LB>;
def : LdPat<atomic_load_16, LH>;
def : LdPat<atomic_load_32, LW>;
def : LdPat<relaxed_load<atomic_load_8>, LB>;
def : LdPat<relaxed_load<atomic_load_16>, LH>;
def : LdPat<relaxed_load<atomic_load_32>, LW>;

def : StPat<atomic_store_8, SB, GPR, XLenVT>;
def : StPat<atomic_store_16, SH, GPR, XLenVT>;
def : StPat<atomic_store_32, SW, GPR, XLenVT>;
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>;
}

let Predicates = [HasAtomicLdSt, IsRV64] in {
def : LdPat<atomic_load_64, LD, i64>;
def : StPat<atomic_store_64, SD, GPR, i64>;
def : LdPat<relaxed_load<atomic_load_64>, LD, i64>;
def : StPat<relaxed_store<atomic_store_64>, SD, GPR, i64>;
}

/// AMOs
Expand Down Expand Up @@ -386,3 +429,14 @@ def : Pat<(int_riscv_masked_cmpxchg_i64
(PseudoMaskedCmpXchg32
GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
} // Predicates = [HasStdExtA, IsRV64]

let Predicates = [HasAtomicLdSt] in {
def : LdPat<relaxed_load<atomic_load_8>, LB, i32>;
def : LdPat<relaxed_load<atomic_load_16>, LH, i32>;
def : LdPat<relaxed_load<atomic_load_32>, LW, i32>;

def : StPat<relaxed_store<atomic_store_8>, SB, GPR, i32>;
def : StPat<relaxed_store<atomic_store_16>, SH, GPR, i32>;
def : StPat<relaxed_store<atomic_store_32>, SW, GPR, i32>;
}

47 changes: 47 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,50 @@ let Predicates = [HasStdExtZalasr, IsRV64] in {
defm LD : LAQ_r_aq_rl<0b011, "ld">;
defm SD : SRL_r_aq_rl<0b011, "sd">;
} // Predicates = [HasStdExtZalasr, IsRV64]

//===----------------------------------------------------------------------===//
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//

class PatLAQ<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>
: Pat<(vt (OpNode (vt GPRMemZeroOffset:$rs1))), (Inst GPRMemZeroOffset:$rs1)>;

// n.b. this switches order of arguments
// to deal with the fact that SRL has addr, data
// while atomic_store has data, addr
class PatSRL<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>
: Pat<(OpNode (vt GPR:$rs2), (vt GPRMemZeroOffset:$rs1)),
(Inst GPRMemZeroOffset:$rs1, GPR:$rs2)>;


let Predicates = [HasStdExtZalasr] in {
// the sequentially consistent loads use
// .aq instead of .aqrl to match the psABI/A.7
def : PatLAQ<acquiring_load<atomic_load_8>, LB_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_8>, LB_AQ>;

def : PatLAQ<acquiring_load<atomic_load_16>, LH_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_16>, LH_AQ>;

def : PatLAQ<acquiring_load<atomic_load_32>, LW_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_32>, LW_AQ>;

// the sequentially consistent stores use
// .rl instead of .aqrl to match the psABI/A.7
def : PatSRL<releasing_store<atomic_store_8>, SB_RL>;
def : PatSRL<seq_cst_store<atomic_store_8>, SB_RL>;

def : PatSRL<releasing_store<atomic_store_16>, SH_RL>;
def : PatSRL<seq_cst_store<atomic_store_16>, SH_RL>;

def : PatSRL<releasing_store<atomic_store_32>, SW_RL>;
def : PatSRL<seq_cst_store<atomic_store_32>, SW_RL>;
} // Predicates = [HasStdExtZalasr]

let Predicates = [HasStdExtZalasr, IsRV64] in {
def : PatLAQ<acquiring_load<atomic_load_64>, LD_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_64>, LD_AQ>;

def : PatSRL<releasing_store<atomic_store_64>, SD_RL>;
def : PatSRL<seq_cst_store<atomic_store_64>, SD_RL>;
} // Predicates = [HasStdExtZalasr, IsRV64]
Loading
Loading