[llvm] 3c609f3 - [RISCV] Merge int_riscv_masked_atomicrmw_*_i32/i64 intrinsics using llvm_anyint_ty. (#154845)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 22 11:33:30 PDT 2025
Author: Craig Topper
Date: 2025-08-22T11:33:27-07:00
New Revision: 3c609f3984b1a9d9f4e24d61f5d0f65df830498d
URL: https://github.com/llvm/llvm-project/commit/3c609f3984b1a9d9f4e24d61f5d0f65df830498d
DIFF: https://github.com/llvm/llvm-project/commit/3c609f3984b1a9d9f4e24d61f5d0f65df830498d.diff
LOG: [RISCV] Merge int_riscv_masked_atomicrmw_*_i32/i64 intrinsics using llvm_anyint_ty. (#154845)
I think having separate intrinsics for RV32 and RV64 is making
some things more complicated than using type overloading.
This reduces the number of isel patterns in the .td file. They're
still expanded my HwMode so it doesn't reduce the binary size.
getIntrinsicForMaskedAtomicRMWBinOp no longer needs to look at XLen.
Added:
Modified:
llvm/include/llvm/IR/IntrinsicsRISCV.td
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVInstrInfoA.td
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 1784454f1b73a..4b8a9da9688a2 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -15,8 +15,7 @@
// Atomic Intrinsics have multiple versions for
diff erent access widths, which
// all follow one of the following signatures (depending on how many arguments
-// they require). We carefully instantiate only specific versions of these for
-// specific integer widths, rather than using `llvm_anyint_ty`.
+// they require).
//
// In fact, as these intrinsics take `llvm_anyptr_ty`, the given names are the
// canonical names, and the intrinsics used in the code will have a name
@@ -25,52 +24,39 @@
let TargetPrefix = "riscv" in {
- // T @llvm.<name>.T.<p>(any*, T, T, T imm);
- class RISCVMaskedAtomicRMWFourArg<LLVMType itype>
- : Intrinsic<[itype], [llvm_anyptr_ty, itype, itype, itype],
+ // T @llvm.<name>.<i>.<p>(any*, T, T, T imm);
+ class RISCVMaskedAtomicRMWFourArg
+ : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>, LLVMMatchType<0>],
[IntrArgMemOnly, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>;
- // T @llvm.<name>.T.<p>(any*, T, T, T, T imm);
- class RISCVMaskedAtomicRMWFiveArg<LLVMType itype>
- : Intrinsic<[itype], [llvm_anyptr_ty, itype, itype, itype, itype],
+ // T @llvm.<name>.<i>.<p>(any*, T, T, T, T imm);
+ class RISCVMaskedAtomicRMWFiveArg
+ : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, LLVMMatchType<0>,
+ LLVMMatchType<0>, LLVMMatchType<0>,
+ LLVMMatchType<0>],
[IntrArgMemOnly, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<4>>]>;
- // We define 32-bit and 64-bit variants of the above, where T stands for i32
- // or i64 respectively:
- multiclass RISCVMaskedAtomicRMWFourArgIntrinsics {
- // i32 @llvm.<name>.i32.<p>(any*, i32, i32, i32 imm);
- def _i32 : RISCVMaskedAtomicRMWFourArg<llvm_i32_ty>;
- // i64 @llvm.<name>.i32.<p>(any*, i64, i64, i64 imm);
- def _i64 : RISCVMaskedAtomicRMWFourArg<llvm_i64_ty>;
- }
-
- multiclass RISCVMaskedAtomicRMWFiveArgIntrinsics {
- // i32 @llvm.<name>.i32.<p>(any*, i32, i32, i32, i32 imm);
- def _i32 : RISCVMaskedAtomicRMWFiveArg<llvm_i32_ty>;
- // i64 @llvm.<name>.i64.<p>(any*, i64, i64, i64, i64 imm);
- def _i64 : RISCVMaskedAtomicRMWFiveArg<llvm_i64_ty>;
- }
-
// These intrinsics are intended only for internal compiler use (i.e. as
// part of AtomicExpandpass via the emitMaskedAtomic*Intrinsic hooks). Their
// names and semantics could change in the future.
- // @llvm.riscv.masked.atomicrmw.*.{i32,i64}.<p>(
+ // @llvm.riscv.masked.atomicrmw.*.<i>.<p>(
// ptr addr, ixlen oparg, ixlen mask, ixlenimm ordering)
- defm int_riscv_masked_atomicrmw_xchg : RISCVMaskedAtomicRMWFourArgIntrinsics;
- defm int_riscv_masked_atomicrmw_add : RISCVMaskedAtomicRMWFourArgIntrinsics;
- defm int_riscv_masked_atomicrmw_sub : RISCVMaskedAtomicRMWFourArgIntrinsics;
- defm int_riscv_masked_atomicrmw_nand : RISCVMaskedAtomicRMWFourArgIntrinsics;
- defm int_riscv_masked_atomicrmw_umax : RISCVMaskedAtomicRMWFourArgIntrinsics;
- defm int_riscv_masked_atomicrmw_umin : RISCVMaskedAtomicRMWFourArgIntrinsics;
+ def int_riscv_masked_atomicrmw_xchg : RISCVMaskedAtomicRMWFourArg;
+ def int_riscv_masked_atomicrmw_add : RISCVMaskedAtomicRMWFourArg;
+ def int_riscv_masked_atomicrmw_sub : RISCVMaskedAtomicRMWFourArg;
+ def int_riscv_masked_atomicrmw_nand : RISCVMaskedAtomicRMWFourArg;
+ def int_riscv_masked_atomicrmw_umax : RISCVMaskedAtomicRMWFourArg;
+ def int_riscv_masked_atomicrmw_umin : RISCVMaskedAtomicRMWFourArg;
// Signed min and max need an extra operand to do sign extension with.
- // @llvm.riscv.masked.atomicrmw.{max,min}.{i32,i64}.<p>(
+ // @llvm.riscv.masked.atomicrmw.{max,min}.<i>.<p>(
// ptr addr, ixlen oparg, ixlen mask, ixlen shamt, ixlenimm ordering)
- defm int_riscv_masked_atomicrmw_max : RISCVMaskedAtomicRMWFiveArgIntrinsics;
- defm int_riscv_masked_atomicrmw_min : RISCVMaskedAtomicRMWFiveArgIntrinsics;
+ def int_riscv_masked_atomicrmw_max : RISCVMaskedAtomicRMWFiveArg;
+ def int_riscv_masked_atomicrmw_min : RISCVMaskedAtomicRMWFiveArg;
- // @llvm.riscv.masked.cmpxchg.{i32,i64}.<p>(
+ // @llvm.riscv.masked.cmpxchg.<i>.<p>(
// ptr addr, ixlen cmpval, ixlen newval, ixlen mask, ixlenimm ordering)
- defm int_riscv_masked_cmpxchg : RISCVMaskedAtomicRMWFiveArgIntrinsics;
+ def int_riscv_masked_cmpxchg : RISCVMaskedAtomicRMWFiveArg;
} // TargetPrefix = "riscv"
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4a1db80076530..7d4dd148219fb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1800,15 +1800,20 @@ bool RISCVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
switch (Intrinsic) {
default:
return false;
- case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
- case Intrinsic::riscv_masked_atomicrmw_add_i32:
- case Intrinsic::riscv_masked_atomicrmw_sub_i32:
- case Intrinsic::riscv_masked_atomicrmw_nand_i32:
- case Intrinsic::riscv_masked_atomicrmw_max_i32:
- case Intrinsic::riscv_masked_atomicrmw_min_i32:
- case Intrinsic::riscv_masked_atomicrmw_umax_i32:
- case Intrinsic::riscv_masked_atomicrmw_umin_i32:
- case Intrinsic::riscv_masked_cmpxchg_i32:
+ case Intrinsic::riscv_masked_atomicrmw_xchg:
+ case Intrinsic::riscv_masked_atomicrmw_add:
+ case Intrinsic::riscv_masked_atomicrmw_sub:
+ case Intrinsic::riscv_masked_atomicrmw_nand:
+ case Intrinsic::riscv_masked_atomicrmw_max:
+ case Intrinsic::riscv_masked_atomicrmw_min:
+ case Intrinsic::riscv_masked_atomicrmw_umax:
+ case Intrinsic::riscv_masked_atomicrmw_umin:
+ case Intrinsic::riscv_masked_cmpxchg:
+ // riscv_masked_{atomicrmw_*,cmpxchg} intrinsics represent an emulated
+ // narrow atomic operation. These will be expanded to an LR/SC loop that
+ // reads/writes to/from an aligned 4 byte location. And, or, shift, etc.
+ // will be used to modify the appropriate part of the 4 byte data and
+ // preserve the rest.
Info.opc = ISD::INTRINSIC_W_CHAIN;
Info.memVT = MVT::i32;
Info.ptrVal = I.getArgOperand(0);
@@ -21478,24 +21483,23 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode(
switch (IntNo) {
default:
break;
- case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
- case Intrinsic::riscv_masked_atomicrmw_add_i64:
- case Intrinsic::riscv_masked_atomicrmw_sub_i64:
- case Intrinsic::riscv_masked_atomicrmw_nand_i64:
- case Intrinsic::riscv_masked_atomicrmw_max_i64:
- case Intrinsic::riscv_masked_atomicrmw_min_i64:
- case Intrinsic::riscv_masked_atomicrmw_umax_i64:
- case Intrinsic::riscv_masked_atomicrmw_umin_i64:
- case Intrinsic::riscv_masked_cmpxchg_i64:
+ case Intrinsic::riscv_masked_atomicrmw_xchg:
+ case Intrinsic::riscv_masked_atomicrmw_add:
+ case Intrinsic::riscv_masked_atomicrmw_sub:
+ case Intrinsic::riscv_masked_atomicrmw_nand:
+ case Intrinsic::riscv_masked_atomicrmw_max:
+ case Intrinsic::riscv_masked_atomicrmw_min:
+ case Intrinsic::riscv_masked_atomicrmw_umax:
+ case Intrinsic::riscv_masked_atomicrmw_umin:
+ case Intrinsic::riscv_masked_cmpxchg:
// riscv_masked_{atomicrmw_*,cmpxchg} intrinsics represent an emulated
// narrow atomic operation. These are implemented using atomic
// operations at the minimum supported atomicrmw/cmpxchg width whose
// result is then sign extended to XLEN. With +A, the minimum width is
// 32 for both 64 and 32.
- assert(Subtarget.getXLen() == 64);
assert(getMinCmpXchgSizeInBits() == 32);
assert(Subtarget.hasStdExtA());
- return 33;
+ return Op.getValueSizeInBits() - 31;
}
break;
}
@@ -23786,53 +23790,26 @@ RISCVTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
static Intrinsic::ID
getIntrinsicForMaskedAtomicRMWBinOp(unsigned XLen, AtomicRMWInst::BinOp BinOp) {
- if (XLen == 32) {
- switch (BinOp) {
- default:
- llvm_unreachable("Unexpected AtomicRMW BinOp");
- case AtomicRMWInst::Xchg:
- return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
- case AtomicRMWInst::Add:
- return Intrinsic::riscv_masked_atomicrmw_add_i32;
- case AtomicRMWInst::Sub:
- return Intrinsic::riscv_masked_atomicrmw_sub_i32;
- case AtomicRMWInst::Nand:
- return Intrinsic::riscv_masked_atomicrmw_nand_i32;
- case AtomicRMWInst::Max:
- return Intrinsic::riscv_masked_atomicrmw_max_i32;
- case AtomicRMWInst::Min:
- return Intrinsic::riscv_masked_atomicrmw_min_i32;
- case AtomicRMWInst::UMax:
- return Intrinsic::riscv_masked_atomicrmw_umax_i32;
- case AtomicRMWInst::UMin:
- return Intrinsic::riscv_masked_atomicrmw_umin_i32;
- }
- }
-
- if (XLen == 64) {
- switch (BinOp) {
- default:
- llvm_unreachable("Unexpected AtomicRMW BinOp");
- case AtomicRMWInst::Xchg:
- return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
- case AtomicRMWInst::Add:
- return Intrinsic::riscv_masked_atomicrmw_add_i64;
- case AtomicRMWInst::Sub:
- return Intrinsic::riscv_masked_atomicrmw_sub_i64;
- case AtomicRMWInst::Nand:
- return Intrinsic::riscv_masked_atomicrmw_nand_i64;
- case AtomicRMWInst::Max:
- return Intrinsic::riscv_masked_atomicrmw_max_i64;
- case AtomicRMWInst::Min:
- return Intrinsic::riscv_masked_atomicrmw_min_i64;
- case AtomicRMWInst::UMax:
- return Intrinsic::riscv_masked_atomicrmw_umax_i64;
- case AtomicRMWInst::UMin:
- return Intrinsic::riscv_masked_atomicrmw_umin_i64;
- }
+ switch (BinOp) {
+ default:
+ llvm_unreachable("Unexpected AtomicRMW BinOp");
+ case AtomicRMWInst::Xchg:
+ return Intrinsic::riscv_masked_atomicrmw_xchg;
+ case AtomicRMWInst::Add:
+ return Intrinsic::riscv_masked_atomicrmw_add;
+ case AtomicRMWInst::Sub:
+ return Intrinsic::riscv_masked_atomicrmw_sub;
+ case AtomicRMWInst::Nand:
+ return Intrinsic::riscv_masked_atomicrmw_nand;
+ case AtomicRMWInst::Max:
+ return Intrinsic::riscv_masked_atomicrmw_max;
+ case AtomicRMWInst::Min:
+ return Intrinsic::riscv_masked_atomicrmw_min;
+ case AtomicRMWInst::UMax:
+ return Intrinsic::riscv_masked_atomicrmw_umax;
+ case AtomicRMWInst::UMin:
+ return Intrinsic::riscv_masked_atomicrmw_umin;
}
-
- llvm_unreachable("Unexpected XLen\n");
}
Value *RISCVTargetLowering::emitMaskedAtomicRMWIntrinsic(
@@ -23857,7 +23834,7 @@ Value *RISCVTargetLowering::emitMaskedAtomicRMWIntrinsic(
unsigned XLen = Subtarget.getXLen();
Value *Ordering =
Builder.getIntN(XLen, static_cast<uint64_t>(AI->getOrdering()));
- Type *Tys[] = {AlignedAddr->getType()};
+ Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->getType()};
Function *LrwOpScwLoop = Intrinsic::getOrInsertDeclaration(
AI->getModule(),
getIntrinsicForMaskedAtomicRMWBinOp(XLen, AI->getOperation()), Tys);
@@ -23913,14 +23890,13 @@ Value *RISCVTargetLowering::emitMaskedAtomicCmpXchgIntrinsic(
Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const {
unsigned XLen = Subtarget.getXLen();
Value *Ordering = Builder.getIntN(XLen, static_cast<uint64_t>(Ord));
- Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
+ Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
if (XLen == 64) {
CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
- CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
}
- Type *Tys[] = {AlignedAddr->getType()};
+ Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->getType()};
Value *Result = Builder.CreateIntrinsic(
CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
if (XLen == 64)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
index 85fcd2c1462dd..813d62d2a853e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
@@ -293,12 +293,14 @@ multiclass PseudoAMOPat<string AtomicOp, Pseudo AMOInst, ValueType vt = XLenVT>
}
class PseudoMaskedAMOPat<Intrinsic intrin, Pseudo AMOInst>
- : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering),
+ : Pat<(XLenVT (intrin (XLenVT GPR:$addr), (XLenVT GPR:$incr),
+ (XLenVT GPR:$mask), (XLenVT timm:$ordering))),
(AMOInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>;
class PseudoMaskedAMOMinMaxPat<Intrinsic intrin, Pseudo AMOInst>
- : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
- timm:$ordering),
+ : Pat<(XLenVT (intrin (XLenVT GPR:$addr), (XLenVT GPR:$incr),
+ (XLenVT GPR:$mask), (XLenVT GPR:$shiftamt),
+ (XLenVT timm:$ordering))),
(AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt,
timm:$ordering)>;
@@ -324,49 +326,30 @@ let Size = 36 in {
def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax;
def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax;
}
-} // Predicates = [HasStdExtA]
-let Predicates = [HasStdExtA, IsRV32] in {
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg,
PseudoMaskedAtomicSwap32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add,
PseudoMaskedAtomicLoadAdd32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub,
PseudoMaskedAtomicLoadSub32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand,
PseudoMaskedAtomicLoadNand32>;
-def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i32,
+def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max,
PseudoMaskedAtomicLoadMax32>;
-def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i32,
+def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min,
PseudoMaskedAtomicLoadMin32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax,
PseudoMaskedAtomicLoadUMax32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i32,
+def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin,
PseudoMaskedAtomicLoadUMin32>;
-} // Predicates = [HasStdExtA, IsRV32]
+} // Predicates = [HasStdExtA]
let Predicates = [HasStdExtA, IsRV64] in {
let Size = 20 in
def PseudoAtomicLoadNand64 : PseudoAMO;
defm : PseudoAMOPat<"atomic_load_nand_i64", PseudoAtomicLoadNand64, i64>;
-
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_xchg_i64,
- PseudoMaskedAtomicSwap32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_add_i64,
- PseudoMaskedAtomicLoadAdd32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_sub_i64,
- PseudoMaskedAtomicLoadSub32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_nand_i64,
- PseudoMaskedAtomicLoadNand32>;
-def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_max_i64,
- PseudoMaskedAtomicLoadMax32>;
-def : PseudoMaskedAMOMinMaxPat<int_riscv_masked_atomicrmw_min_i64,
- PseudoMaskedAtomicLoadMin32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umax_i64,
- PseudoMaskedAtomicLoadUMax32>;
-def : PseudoMaskedAMOPat<int_riscv_masked_atomicrmw_umin_i64,
- PseudoMaskedAtomicLoadUMin32>;
} // Predicates = [HasStdExtA, IsRV64]
@@ -420,15 +403,9 @@ def PseudoMaskedCmpXchg32
let Size = 32;
}
-def : Pat<(int_riscv_masked_cmpxchg_i32
- GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
+def : Pat<(XLenVT (int_riscv_masked_cmpxchg
+ (XLenVT GPR:$addr), (XLenVT GPR:$cmpval), (XLenVT GPR:$newval),
+ (XLenVT GPR:$mask), (XLenVT timm:$ordering))),
(PseudoMaskedCmpXchg32
GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
} // Predicates = [HasStdExtA]
-
-let Predicates = [HasStdExtA, IsRV64] in {
-def : Pat<(int_riscv_masked_cmpxchg_i64
- GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering),
- (PseudoMaskedCmpXchg32
- GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>;
-} // Predicates = [HasStdExtA, IsRV64]
More information about the llvm-commits
mailing list