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
4 changes: 4 additions & 0 deletions llvm/lib/Target/AIE/AIEBaseInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,10 @@ struct AIEBaseInstrInfo : public TargetInstrInfo {
virtual int getCoreStallCycleAfterLock() const;
/// Return cycles for core to resume after lock instruction.
virtual int getCoreResumeCycleAfterLock() const;
/// Return true if the target supports lock no_fence semantics: when a
/// lock has no in-flight memory predecessor, no forward latency to subsequent
/// memory ops is required.
virtual bool hasLockNoFenceSemantics() const { return false; }

/// Return the schedclass for the given instruction descriptor based on
/// operand regclass.
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/AIE/AIEBaseSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ class LockDelays : public ScheduleDAGMutation {
if (SuccEdge.getKind() != SDep::Order || !LdSt->mayLoadOrStore()) {
continue;
}
// lock no_fence: when the target supports it, no forward latency is
// needed for ACQ/REL. The predecessor loop above already enforces the
// MEM->lock gap (draining any in-flight memory before the lock issues),
// so no memory can be in-flight at lock issue regardless of whether a
// memory pred exists in the DAG.
// Note: DONE is excluded — it keeps conservative forward latency.
if (TII->isLock(MI->getOpcode()) && TII->hasLockNoFenceSemantics())
continue;
auto OptFirstMemCycle =
TII->getFirstMemoryCycle(LdSt->getDesc().SchedClass);
assert(!ExactLatencies || OptFirstMemCycle);
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/AIE/AIERegMemEventTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,12 @@ unsigned AIERegMemEventTracker::getSafeOperandsDistanceFromBottom(
MaxLatency =
checkMemoryDependency(MaxLatency, LoadStoreCycle, MIMemoryCycle, true);
}
// Lock instructions: all subsequent memory operations must wait
if (TII->isLock(MI.getOpcode())) {
// Lock instructions: all subsequent memory operations must wait.
// lock no_fence: for targets that support it, no forward latency is
// needed — LockDelays already enforces MEM->lock gaps large enough to drain
// the pipeline before the lock issues, so no memory is ever in-flight at
// lock issue time.
if (TII->isLock(MI.getOpcode()) && !TII->hasLockNoFenceSemantics()) {
if (getFirstMemoryAccessCycle() > INT_MIN) {
const int CoreResumeCycle = TII->getCoreResumeCycleAfterLock();
const int MemCycle = getFirstMemoryAccessCycle();
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AIE/aie2p/AIE2PInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class AIE2PInstrInfo : public AIE2PGenInstrInfo {
unsigned getGenericExtractSubvectorOpcode() const override;
unsigned getGenericIntegerComparisonOpcode() const override;
bool isLock(unsigned Opc) const override;
bool hasLockNoFenceSemantics() const override { return true; }
std::optional<unsigned> getDoneLatency(unsigned) const override;
bool isDelayedSchedBarrier(const MachineInstr &MI) const override;
bool isSchedBarrier(const MachineInstr &MI) const override;
Expand Down
Loading
Loading