Skip to content

Commit be0dac2

Browse files
committed
[RISCV] Improve codegen for i8/i16 'atomicrmw xchg a, {0,-1}'
As noted in <#64090>, it's more efficient to lower a partword 'atomicrmw xchg a, 0` to and amoand with appropriate mask. There are a range of possible ways to go about this - e.g. writing a combine based on the `llvm.riscv.masked.atomicrmw.xchg` intrinsic, or introducing a new interface to AtomicExpandPass to allow target-specific atomics conversions, or trying to lift the conversion into AtomicExpandPass itself based on querying some target hook. Ultimately I've gone with what appears to be the simplest approach - just covering this case in emitMaskedAtomicRMWIntrinsic. I perhaps should have given that hook a different name way back when it was introduced. This also handles the `atomicrmw xchg a, -1` case suggested by Craig during review. Fixes #64090 Differential Revision: https://reviews.llvm.org/D156801
1 parent 8af016a commit be0dac2

File tree

2 files changed

+118
-402
lines changed

2 files changed

+118
-402
lines changed

Diff for: llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -16747,6 +16747,22 @@ getIntrinsicForMaskedAtomicRMWBinOp(unsigned XLen, AtomicRMWInst::BinOp BinOp) {
1674716747
Value *RISCVTargetLowering::emitMaskedAtomicRMWIntrinsic(
1674816748
IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr,
1674916749
Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const {
16750+
// In the case of an atomicrmw xchg with a constant 0/-1 operand, replace
16751+
// the atomic instruction with an AtomicRMWInst::And/Or with appropriate
16752+
// mask, as this produces better code than the LR/SC loop emitted by
16753+
// int_riscv_masked_atomicrmw_xchg.
16754+
if (AI->getOperation() == AtomicRMWInst::Xchg &&
16755+
isa<ConstantInt>(AI->getValOperand())) {
16756+
ConstantInt *CVal = cast<ConstantInt>(AI->getValOperand());
16757+
if (CVal->isZero())
16758+
return Builder.CreateAtomicRMW(AtomicRMWInst::And, AlignedAddr,
16759+
Builder.CreateNot(Mask, "Inv_Mask"),
16760+
AI->getAlign(), Ord);
16761+
if (CVal->isMinusOne())
16762+
return Builder.CreateAtomicRMW(AtomicRMWInst::Or, AlignedAddr, Mask,
16763+
AI->getAlign(), Ord);
16764+
}
16765+
1675016766
unsigned XLen = Subtarget.getXLen();
1675116767
Value *Ordering =
1675216768
Builder.getIntN(XLen, static_cast<uint64_t>(AI->getOrdering()));

0 commit comments

Comments
 (0)