Skip to content

[RISCV][MC] MC layer support for the experimental zalasr extension #69685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
9 changes: 9 additions & 0 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
// CHECK-NOT: __riscv_zacas {{.*$}}
// CHECK-NOT: __riscv_zalrsc {{.*$}}
// CHECK-NOT: __riscv_zcmop {{.*$}}
// CHECK-NOT: __riscv_zalasr {{.*$}}
// CHECK-NOT: __riscv_zfbfmin {{.*$}}
// CHECK-NOT: __riscv_zicfilp {{.*$}}
// CHECK-NOT: __riscv_zicfiss {{.*$}}
Expand Down Expand Up @@ -1120,6 +1121,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-SMEPMP-EXT %s
// CHECK-SMEPMP-EXT: __riscv_smepmp 1000000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zalasr1p0 -x c -E -dM %s \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent line continuations 2 spaces and drop -x c. This was recently updated in the reset of the file.

// RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zalasr1p0 -x c -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
// CHECK-ZALASR-EXT: __riscv_zalasr 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32izfa -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZFA-EXT %s
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zacas``
LLVM implements the `1.0-rc1 draft specification <https://github.com/riscv/riscv-zacas/releases/tag/v1.0-rc1>`_.

``experimental-zalasr``
LLVM implements the `most recent specification <https://github.com/mehnadnerd/riscv-zalasr>`_.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we nail this down to a version or a date? "most recent" is wrong if that repo changes.


``experimental-zfbfmin``, ``experimental-zvfbfmin``, ``experimental-zvfbfwma``
LLVM implements assembler support for the `1.0.0-rc2 specification <https://github.com/riscv/riscv-bfloat16/releases/tag/v59042fc71c31a9bcb2f1957621c960ed36fac401>`_.

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Support/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
{"zaamo", {0, 2}},
{"zacas", {1, 0}},
{"zalrsc", {0, 2}},
{"zalasr", {1, 0}},

{"zcmop", {0, 2}},

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,13 @@ def FeatureStdExtSvpbmt
: SubtargetFeature<"svpbmt", "HasStdExtSvpbmt", "true",
"'Svpbmt' (Page-Based Memory Types)">;

def FeatureStdExtZalasr
: SubtargetFeature<"experimental-zalasr", "HasStdExtZalasr", "true",
"'Zalasr' (Load-Acquire and Store-Release Instructions)">;
def HasStdExtZalasr : Predicate<"Subtarget->hasStdExtZalasr()">,
AssemblerPredicate<(all_of FeatureStdExtZalasr),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align AssemblerPredicate with Predicate on the previous line. This file was recently reformatted.

"'Zalasr' (Load-Acquire and Store-Release Instructions)">;

//===----------------------------------------------------------------------===//
// Vendor extensions
//===----------------------------------------------------------------------===//
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20506,6 +20506,14 @@ unsigned RISCVTargetLowering::getCustomCtpopCost(EVT VT,
return isCtpopFast(VT) ? 0 : 1;
}

bool RISCVTargetLowering::shouldInsertFencesForAtomic(
const Instruction *I) const {
if (Subtarget.hasStdExtZalasr()) {
return false;
}
return isa<LoadInst>(I) || isa<StoreInst>(I);
}

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

// GISel support is in progress or complete for G_ADD, G_SUB, G_AND, G_OR, and
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 @@ -689,9 +689,8 @@ class RISCVTargetLowering : public TargetLowering {

bool preferZeroCompareBranch() const override { return true; }

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
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -2144,6 +2144,7 @@ include "RISCVInstrInfoM.td"
// Atomic
include "RISCVInstrInfoA.td"
include "RISCVInstrInfoZa.td"
include "RISCVInstrInfoZalasr.td"

// Scalar FP
include "RISCVInstrInfoF.td"
Expand Down
61 changes: 51 additions & 10 deletions llvm/lib/Target/RISCV/RISCVInstrInfoA.td
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,63 @@ defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">,
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//

// 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 IsAtomic = 1;
let IsAtomicOrderingMonotonic = 1;
}

// A atomic load operation that actually needs acquire semantics.
class acquiring_load<PatFrags base>
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
let IsAtomic = 1;
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 IsAtomic = 1;
let IsAtomicOrderingSequentiallyConsistent = 1;
}

// An atomic store operation that doesn't actually need to be atomic on RISCV.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RISCV -> RISC-V

class relaxed_store<PatFrag base>
: PatFrag<(ops node:$ptr, node:$val), (base node:$val, node:$ptr)> {
let IsAtomic = 1;
let IsAtomicOrderingMonotonic = 1;
}

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

// A store operation that actually needs sequential consistency.
class seq_cst_store<PatFrag base>
: PatFrag<(ops node:$ptr, node:$val), (base node:$val, node:$ptr)> {
let IsAtomic = 1;
let IsAtomicOrderingSequentiallyConsistent = 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}.
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>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an MC patch as the title says, we shouldn't be touching any isel patterns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was originally an MC patch but I am adding isel support as well. What should I change the title to?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually want MC and CodeGen changes as separate PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. I will separate it out then.

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
98 changes: 98 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//===-- RISCVInstrInfoZalasr.td - RISC-V 'Zalasr' instructions -------*- tablegen -*-===//
//
// 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 describes the RISC-V instructions from the Zalasr (Load-Acquire
// and Store-Release) extension
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//

let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
class LAQ_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
: RVInstRAtomic<0b00110, aq, rl, funct3, OPC_AMO,
(outs GPR:$rd), (ins GPRMemZeroOffset:$rs1),
opcodestr, "$rd, $rs1"> {
let rs2 = 0;
}

let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
class SRL_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
: RVInstRAtomic<0b00111, aq, rl, funct3, OPC_AMO,
(outs ), (ins GPRMemZeroOffset:$rs1, GPR:$rs2),
opcodestr, "$rs2, $rs1"> {
let rd = 0;
}
multiclass LAQ_r_aq_rl<bits<3> funct3, string opcodestr> {
def _AQ : LAQ_r<1, 0, funct3, opcodestr # ".aq">;
def _AQ_RL : LAQ_r<1, 1, funct3, opcodestr # ".aqrl">;
}

multiclass SRL_r_aq_rl<bits<3> funct3, string opcodestr> {
def _RL : SRL_r<0, 1, funct3, opcodestr # ".rl">;
def _AQ_RL : SRL_r<1, 1, funct3, opcodestr # ".aqrl">;
}

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//


let Predicates = [HasStdExtZalasr] in {
defm LB_AQ : LAQ_r_aq_rl<0b000, "lb">;
defm LH_AQ : LAQ_r_aq_rl<0b001, "lh">;
defm LW_AQ : LAQ_r_aq_rl<0b010, "lw">;
defm SB_RL : SRL_r_aq_rl<0b000, "sb">;
defm SH_RL : SRL_r_aq_rl<0b001, "sh">;
defm SW_RL : SRL_r_aq_rl<0b010, "sw">;
} // Predicates = [HasStdExtZalasr]

let Predicates = [HasStdExtZalasr, IsRV64] in {
defm LD_AQ : LAQ_r_aq_rl<0b011, "ld">;
defm SD_RL : SRL_r_aq_rl<0b011, "sd">;
} // Predicates = [HasStdExtZalasr, IsRV64]

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

class PatLAQ<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add patterns in MC patch.

: Pat<(vt (OpNode (vt GPRMemZeroOffset:$rs1))), (Inst GPRMemZeroOffset:$rs1)>;

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

let Predicates = [HasStdExtZalasr] in {
def : PatLAQ<acquiring_load<atomic_load_8>, LB_AQ_AQ>;
def : PatLAQ<seq_cst_load<atomic_load_8>, LB_AQ_AQ>; // these use lb.aq instead of lb.aqrl to match the psABI

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

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

def : PatSRL<releasing_store<atomic_store_8>, SB_RL_RL>;
def : PatSRL<seq_cst_store<atomic_store_8>, SB_RL_RL>; // these use sb.rl instead of sb.aqrl to match the psABI

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

def : PatSRL<releasing_store<atomic_store_32>, SW_RL_RL>;
def : PatSRL<seq_cst_store<atomic_store_32>, SW_RL_RL>;
} // Predicates HasStdExtZalasr

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

def : PatSRL<releasing_store<atomic_store_64>, SD_RL_RL>;
def : PatSRL<seq_cst_store<atomic_store_64>, SD_RL_RL>;
} // Predicates HasStdExtZalasr, IsRV64
4 changes: 4 additions & 0 deletions llvm/test/CodeGen/RISCV/attributes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zacas %s -o - | FileCheck --check-prefix=RV32ZACAS %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfilp %s -o - | FileCheck --check-prefix=RV32ZICFILP %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zalasr %s -o - | FileCheck --check-prefix=RV32ZALASR %s

; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s
; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s
Expand Down Expand Up @@ -201,6 +202,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zacas %s -o - | FileCheck --check-prefix=RV64ZACAS %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalrsc %s -o - | FileCheck --check-prefix=RV64ZALRSC %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp %s -o - | FileCheck --check-prefix=RV64ZICFILP %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zalasr %s -o - | FileCheck --check-prefix=RV64ZALASR %s

; CHECK: .attribute 4, 16

Expand Down Expand Up @@ -300,6 +302,7 @@
; RV32ZACAS: .attribute 5, "rv32i2p1_a2p1_zacas1p0"
; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc0p2"
; RV32ZICFILP: .attribute 5, "rv32i2p1_zicfilp0p4"
; RV32ZALASR: .attribute 5, "rv32i2p1_zalasr1p0"

; RV64M: .attribute 5, "rv64i2p1_m2p0"
; RV64ZMMUL: .attribute 5, "rv64i2p1_zmmul1p0"
Expand Down Expand Up @@ -403,6 +406,7 @@
; RV64ZACAS: .attribute 5, "rv64i2p1_a2p1_zacas1p0"
; RV64ZALRSC: .attribute 5, "rv64i2p1_zalrsc0p2"
; RV64ZICFILP: .attribute 5, "rv64i2p1_zicfilp0p4"
; RV64ZALASR: .attribute 5, "rv64i2p1_zalasr1p0"

define i32 @addi(i32 %a) {
%1 = add i32 %a, 1
Expand Down
3 changes: 3 additions & 0 deletions llvm/test/MC/RISCV/attribute-arch.s
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@
.attribute arch, "rv32izacas1p0"
# CHECK: attribute 5, "rv32i2p1_a2p1_zacas1p0"

.attribute arch, "rv32izalasr1p0"
# CHECK: attribute 5, "rv32i2p1_zalasr1p0"

.attribute arch, "rv32i_xcvalu"
# CHECK: attribute 5, "rv32i2p1_xcvalu1p0"

Expand Down
40 changes: 40 additions & 0 deletions llvm/test/MC/RISCV/rv32zalasr-invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zalasr < %s 2>&1 | FileCheck -check-prefixes=CHECK %s

# CHECK: error: instruction requires the following: RV64I Base Instruction Set{{$}}
ld.aq a1, (t0)

# CHECK: error: instruction requires the following: RV64I Base Instruction Set{{$}}
ld.aqrl a1, (t0)

# CHECK: error: instruction requires the following: RV64I Base Instruction Set{{$}}
sd.rl a1, (t0)

# CHECK: error: instruction requires the following: RV64I Base Instruction Set{{$}}
sd.aqrl a1, (t0)

# CHECK: error: unrecognized instruction mnemonic
lw. a1, (t0)

# CHECK: error: unrecognized instruction mnemonic
lw.rl t3, 0(t5)

# CHECK: error: unrecognized instruction mnemonic
lh.rlaq t4, (t6)

# CHECK: error: unrecognized instruction mnemonic
sb. a1, (t0)

# CHECK: error: unrecognized instruction mnemonic
sh.aq t3, 0(t5)

# CHECK: error: unrecognized instruction mnemonic
sh.rlaq t4, (t6)

# CHECK: error: optional integer offset must be 0
lw.aq zero, 1(a0)

# CHECK: error: optional integer offset must be 0
sw.rl t1, 2(s0)

# CHECK: error: optional integer offset must be 0
sb.aqrl sp, 3(s2)
Loading