aboutsummaryrefslogtreecommitdiff
path: root/backend/unittests
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-11 18:11:10 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-11 18:11:10 +0800
commitd3dc5aaf114e8e1ad830ca821814c952966a550b (patch)
tree2accc3b216c9a105e065ff61d2be199c641379d5 /backend/unittests
parent1e0003ec107dff77cd579d245f6314cbf7d4f3fc (diff)
downloadrcc-project-d3dc5aaf114e8e1ad830ca821814c952966a550b.tar.gz
rcc-project-d3dc5aaf114e8e1ad830ca821814c952966a550b.tar.xz
[RISCV] Preserve narrow cmpxchg results when widening
Diffstat (limited to 'backend/unittests')
-rw-r--r--backend/unittests/Target/RISCVCodeGenTest.cpp37
1 files changed, 37 insertions, 0 deletions
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<void>(std::unexpected(FallbackAction.error()));
+ rcc::MachineInstr *Truncation = (*BuiltFallback)->next();
+ const rcc::Register *WideFallbackResult = (*BuiltFallback)->operandAt(0)->getIf<rcc::Register>();
+ const rcc::Register *TruncatedResult =
+ Truncation == nullptr ? nullptr : Truncation->operandAt(0)->getIf<rcc::Register>();
+ const rcc::Register *TruncationSource =
+ Truncation == nullptr ? nullptr : Truncation->operandAt(1)->getIf<rcc::Register>();
+ 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) {