Skip to content

Commit 7d6e72f

Browse files
ReVe1uvKane Wang
andauthored
[RISCV][GlobalISel] Lower G_ATOMICRMW_SUB via G_ATOMICRMW_ADD (llvm#155972)
RISCV does not provide a native atomic subtract instruction, so this patch lowers `G_ATOMICRMW_SUB` by negating the RHS value and performing an atomic add. The legalization rules in `RISCVLegalizerInfo` are updated accordingly, with libcall fallbacks when `StdExtA` is not available, and intrinsic legalization is extended to support `riscv_masked_atomicrmw_sub`. For example, lowering `%1 = atomicrmw sub ptr %a, i32 1 seq_cst` on riscv32a produces: ``` li a1, -1 amoadd.w.aqrl a0, a1, (a0) ``` On riscv64a, where the RHS type is narrower than XLEN, it currently produces: ``` li a1, 1 neg a1, a1 amoadd.w.aqrl a0, a1, (a0) ``` There is still a constant-folding or InstConbiner gap. For instance, lowering ``` %b = sub i32 %x, %y %1 = atomicrmw sub ptr %a, i32 %b seq_cst ``` generates: ``` subw a1, a1, a2 neg a1, a1 amoadd.w.aqrl a0, a1, (a0) ``` This sequence could be optimized further to eliminate the redundant neg. Addressing this may require improvements in the Combiner or Peephole Optimizer in future work. --------- Co-authored-by: Kane Wang <[email protected]>
1 parent fee17b3 commit 7d6e72f

13 files changed

+1766
-695
lines changed

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4773,6 +4773,16 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
47734773
return lowerVectorReduction(MI);
47744774
case G_VAARG:
47754775
return lowerVAArg(MI);
4776+
case G_ATOMICRMW_SUB: {
4777+
auto [Ret, Mem, Val] = MI.getFirst3Regs();
4778+
const LLT ValTy = MRI.getType(Val);
4779+
MachineMemOperand *MMO = *MI.memoperands_begin();
4780+
4781+
auto VNeg = MIRBuilder.buildNeg(ValTy, Val);
4782+
MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4783+
MI.eraseFromParent();
4784+
return Legalized;
4785+
}
47764786
}
47774787
}
47784788

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
700700
.libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
701701
.clampScalar(0, sXLen, sXLen);
702702

703+
getActionDefinitionsBuilder(G_ATOMICRMW_SUB)
704+
.libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
705+
.clampScalar(0, sXLen, sXLen)
706+
.lower();
707+
703708
getLegacyLegalizerInfo().computeTables();
704709
verify(*ST.getInstrInfo());
705710
}
@@ -738,6 +743,7 @@ bool RISCVLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
738743
return true;
739744
}
740745
case Intrinsic::riscv_masked_atomicrmw_add:
746+
case Intrinsic::riscv_masked_atomicrmw_sub:
741747
return true;
742748
}
743749
}

0 commit comments

Comments
 (0)