Skip to content

Commit 1d24a02

Browse files
committed
Add missing barrier, fix codegen bugs, optimize codegen
1 parent 2e5cdd3 commit 1d24a02

File tree

5 files changed

+49
-23
lines changed

5 files changed

+49
-23
lines changed

src/coreclr/jit/codegenarm.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,8 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
703703
emitAttr dataSize = emitActualTypeSize(data);
704704

705705
regNumber tempReg = treeNode->ExtractTempReg(RBM_ALLINT);
706-
regNumber loadReg = (targetReg != REG_NA) ? targetReg : treeNode->ExtractTempReg(RBM_ALLINT);
707-
regNumber storeReg = dataReg;
706+
regNumber storeReg = (treeNode->OperGet() == GT_XCHG) ? dataReg : treeNode->ExtractTempReg(RBM_ALLINT);
707+
regNumber loadReg = (targetReg != REG_NA) ? targetReg : storeReg;
708708

709709
// Check allocator assumptions
710710
//
@@ -743,9 +743,6 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
743743
// bne retry
744744
// dmb ish
745745

746-
BasicBlock* labelRetry = genCreateTempLabel();
747-
genDefineTempLabel(labelRetry);
748-
749746
instruction insLd = INS_ldrex;
750747
instruction insSt = INS_strex;
751748
if (varTypeIsByte(treeNode->TypeGet()))
@@ -759,12 +756,16 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
759756
insSt = INS_strexh;
760757
}
761758

759+
instGen_MemoryBarrier();
760+
761+
BasicBlock* labelRetry = genCreateTempLabel();
762+
genDefineTempLabel(labelRetry);
763+
762764
// The following instruction includes a acquire half barrier
763765
GetEmitter()->emitIns_R_R(insLd, dataSize, loadReg, addrReg);
764766

765767
if (treeNode->OperGet() == GT_XADD)
766768
{
767-
storeReg = loadReg;
768769
if (data->isContainedIntOrIImmed())
769770
{
770771
genInstrWithConstant(INS_add, dataSize, storeReg, loadReg, data->AsIntConCommon()->IconValue(),
@@ -864,10 +865,6 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode)
864865
// compareFail:
865866
// dmb ish
866867

867-
BasicBlock* labelRetry = genCreateTempLabel();
868-
BasicBlock* labelCompareFail = genCreateTempLabel();
869-
genDefineTempLabel(labelRetry);
870-
871868
instruction insLd = INS_ldrex;
872869
instruction insSt = INS_strex;
873870
if (varTypeIsByte(treeNode->TypeGet()))
@@ -881,20 +878,34 @@ void CodeGen::genCodeForCmpXchg(GenTreeCmpXchg* treeNode)
881878
insSt = INS_strexh;
882879
}
883880

881+
instGen_MemoryBarrier();
882+
883+
BasicBlock* labelRetry = genCreateTempLabel();
884+
BasicBlock* labelCompareFail = genCreateTempLabel();
885+
genDefineTempLabel(labelRetry);
886+
884887
// The following instruction includes a acquire half barrier
885888
GetEmitter()->emitIns_R_R(insLd, dataSize, targetReg, addrReg);
886889

887890
if (comparand->isContainedIntOrIImmed())
888891
{
889-
assert(comparand->AsIntConCommon()->IconValue() <= INT32_MAX);
890-
GetEmitter()->emitIns_R_I(INS_cmp, EA_4BYTE, targetReg,
891-
(target_ssize_t)comparand->AsIntConCommon()->IconValue());
892+
if (comparand->IsIntegralConst(0))
893+
{
894+
GetEmitter()->emitIns_J_R(INS_cbnz, EA_4BYTE, labelCompareFail, targetReg);
895+
}
896+
else
897+
{
898+
assert(comparand->AsIntConCommon()->IconValue() <= INT32_MAX);
899+
GetEmitter()->emitIns_R_I(INS_cmp, EA_4BYTE, targetReg,
900+
(target_ssize_t)comparand->AsIntConCommon()->IconValue());
901+
GetEmitter()->emitIns_J(INS_bne, labelCompareFail);
902+
}
892903
}
893904
else
894905
{
895906
GetEmitter()->emitIns_R_R(INS_cmp, EA_4BYTE, targetReg, comparandReg);
907+
GetEmitter()->emitIns_J(INS_bne, labelCompareFail);
896908
}
897-
GetEmitter()->emitIns_J(INS_bne, labelCompareFail);
898909

899910
// The following instruction includes a release half barrier
900911
GetEmitter()->emitIns_R_R_R(insSt, dataSize, exResultReg, dataReg, addrReg);

src/coreclr/jit/instrsarm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ INST1(strd, "strd", 0,ST, IF_T2_G0, 0xE8400000)
439439
// Rt,RT,[Rn],+-i8{!}T2_G0 1110100PU1W0nnnn ttttTTTTiiiiiiii E840 0000
440440
INST1(strex, "strex", 0,ST, IF_T2_O3, 0xE8400000)
441441
// Rd,Rt,[Rn+i8] T2_H1 111010000100nnnn ttttddddiiiiiiii E840 0F00 imm(0-255)
442-
INST1(strexb, "strexb", 0,ST, IF_T2_O2, 0xE8C00F50)
442+
INST1(strexb, "strexb", 0,ST, IF_T2_O2, 0xE8C00F40)
443443
// Rd,Rt,[Rn] T2_E1 111010001100nnnn tttt11110100dddd E8C0 0F4F
444444
INST1(strexd, "strexd", 0,ST, IF_T2_O1, 0xE8C00070)
445445
// Rd,Rt,RT,[Rn] T2_G1 111010001100nnnn ttttTTTT0111dddd E8C0 007F

src/coreclr/jit/lower.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,13 +629,15 @@ GenTree* Lowering::LowerNode(GenTree* node)
629629
LowerStoreLocCommon(node->AsLclVarCommon());
630630
break;
631631

632-
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
632+
#if defined(TARGET_ARM64) || defined(TARGET_ARM) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
633633
case GT_CMPXCHG:
634634
CheckImmedAndMakeContained(node, node->AsCmpXchg()->Comparand());
635635
break;
636636

637+
#ifndef TARGET_ARM
637638
case GT_XORR:
638639
case GT_XAND:
640+
#endif // TARGET_ARM
639641
case GT_XADD:
640642
CheckImmedAndMakeContained(node, node->AsOp()->gtOp2);
641643
break;

src/coreclr/jit/lowerarmarch.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,29 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) const
8282
{
8383
case GT_ADD:
8484
case GT_SUB:
85-
#ifdef TARGET_ARM64
85+
#ifdef TARGET_ARM
86+
case GT_XADD:
87+
return emitter::emitIns_valid_imm_for_add(immVal, flags);
88+
#else
8689
return emitter::emitIns_valid_imm_for_add(immVal, size);
87-
case GT_CMPXCHG:
90+
91+
case GT_XADD:
8892
case GT_LOCKADD:
8993
case GT_XORR:
9094
case GT_XAND:
91-
case GT_XADD:
9295
return comp->compOpportunisticallyDependsOn(InstructionSet_Atomics)
9396
? false
9497
: emitter::emitIns_valid_imm_for_add(immVal, size);
95-
#elif defined(TARGET_ARM)
96-
return emitter::emitIns_valid_imm_for_add(immVal, flags);
97-
#endif
98-
break;
98+
#endif // TARGET_ARM
99+
100+
case GT_CMPXCHG:
101+
#ifdef TARGET_ARM
102+
return emitter::emitIns_valid_imm_for_cmp(immVal, flags);
103+
#else
104+
return comp->compOpportunisticallyDependsOn(InstructionSet_Atomics)
105+
? false
106+
: emitter::emitIns_valid_imm_for_cmp(immVal, size);
107+
#endif // TARGET_ARM
99108

100109
#ifdef TARGET_ARM64
101110
case GT_EQ:

src/coreclr/jit/lsraarm.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,10 @@ int LinearScan::BuildNode(GenTree* tree)
609609
srcCount = tree->gtGetOp2()->isContained() ? 1 : 2;
610610

611611
buildInternalIntRegisterDefForNode(tree);
612+
if (tree->OperGet() != GT_XCHG)
613+
{
614+
buildInternalIntRegisterDefForNode(tree);
615+
}
612616

613617
assert(!tree->gtGetOp1()->isContained());
614618
RefPosition* op1Use = BuildUse(tree->gtGetOp1());

0 commit comments

Comments
 (0)