From d3dc5aaf114e8e1ad830ca821814c952966a550b Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Tue, 11 Aug 2026 18:11:10 +0800 Subject: [RISCV] Preserve narrow cmpxchg results when widening --- backend/unittests/Target/RISCVCodeGenTest.cpp | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'backend/unittests') diff --git a/backend/unittests/Target/RISCVCodeGenTest.cpp b/backend/unittests/Target/RISCVCodeGenTest.cpp index 3a08f92..17987f1 100644 --- a/backend/unittests/Target/RISCVCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVCodeGenTest.cpp @@ -907,6 +907,43 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { Target->validateInstruction(**BuiltAtomic, (*Function)->registerInfo()) && LegalAction && *LegalAction == rcc::LegalizationAction::Legal, "compare-exchange widening must preserve the narrow MMO in a legal i64 container"); + + auto FallbackCompare = (*Function)->registerInfo().createVirtualRegister(*I8); + auto FallbackNewValue = (*Function)->registerInfo().createVirtualRegister(*I8); + auto FallbackResult = (*Function)->registerInfo().createVirtualRegister(*I8); + if (!FallbackCompare || !FallbackNewValue || !FallbackResult || !Builder.setInsertPoint(**Block)) + return; + for (rcc::Register Definition : {*FallbackCompare, *FallbackNewValue}) { + auto Implicit = Builder.buildInstr(rcc::opcode(rcc::GenericOpcode::G_IMPLICIT_DEF)); + if (!Implicit || !Implicit->addDef(Definition) || !Implicit->build()) + return; + } + auto Fallback = Builder.buildInstr(rcc::opcode(rcc::GenericOpcode::G_ATOMIC_CMPXCHG)); + if (!Fallback || !Fallback->addDef(*FallbackResult) || !Fallback->addUse(*Address) || + !Fallback->addUse(*FallbackCompare) || !Fallback->addUse(*FallbackNewValue) || + !Fallback->addMemOperand(**Memory)) + return; + auto BuiltFallback = Fallback->build(); + if (!BuiltFallback) + return; + auto FallbackAction = rcc::riscv::legalizerInfo().classify(**BuiltFallback, **Function, *Target); + auto FallbackLowered = + FallbackAction + ? rcc::riscv::legalizerInfo().lower(**BuiltFallback, **Function, *Target, *FallbackAction) + : rcc::Expected(std::unexpected(FallbackAction.error())); + rcc::MachineInstr *Truncation = (*BuiltFallback)->next(); + const rcc::Register *WideFallbackResult = (*BuiltFallback)->operandAt(0)->getIf(); + const rcc::Register *TruncatedResult = + Truncation == nullptr ? nullptr : Truncation->operandAt(0)->getIf(); + const rcc::Register *TruncationSource = + Truncation == nullptr ? nullptr : Truncation->operandAt(1)->getIf(); + Context.expect(FallbackLowered && WideFallbackResult != nullptr && + *WideFallbackResult != *FallbackResult && Truncation != nullptr && + Truncation->opcode() == rcc::opcode(rcc::GenericOpcode::G_TRUNC) && + TruncatedResult != nullptr && *TruncatedResult == *FallbackResult && + TruncationSource != nullptr && *TruncationSource == *WideFallbackResult && + Target->validateInstruction(*Truncation, (*Function)->registerInfo()), + "general compare-exchange widening must truncate from the new i64 result"); } void testAtomicSelection(TestContext &Context) { -- cgit v1.2.3