@@ -81,10 +81,30 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
81
81
setOperationAction (ISD::STACKSAVE, MVT::Other, Expand);
82
82
setOperationAction (ISD::STACKRESTORE, MVT::Other, Expand);
83
83
84
- // Set unsupported atomic operations as Custom so
85
- // we can emit better error messages than fatal error
86
- // from selectiondag.
87
- for (auto VT : {MVT::i8 , MVT::i16 , MVT::i32 }) {
84
+ for (auto VT : {MVT::i8 , MVT::i16 , MVT::i32 , MVT::i32 , MVT::i64 }) {
85
+ if (Subtarget->isSolana ()) {
86
+ // Implement custom lowering for all atomic operations
87
+ setOperationAction (ISD::ATOMIC_SWAP, VT, Custom);
88
+ setOperationAction (ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Custom);
89
+ setOperationAction (ISD::ATOMIC_LOAD_ADD, VT, Custom);
90
+ setOperationAction (ISD::ATOMIC_LOAD_AND, VT, Custom);
91
+ setOperationAction (ISD::ATOMIC_LOAD_MAX, VT, Custom);
92
+ setOperationAction (ISD::ATOMIC_LOAD_MIN, VT, Custom);
93
+ setOperationAction (ISD::ATOMIC_LOAD_NAND, VT, Custom);
94
+ setOperationAction (ISD::ATOMIC_LOAD_OR, VT, Custom);
95
+ setOperationAction (ISD::ATOMIC_LOAD_SUB, VT, Custom);
96
+ setOperationAction (ISD::ATOMIC_LOAD_UMAX, VT, Custom);
97
+ setOperationAction (ISD::ATOMIC_LOAD_UMIN, VT, Custom);
98
+ setOperationAction (ISD::ATOMIC_LOAD_XOR, VT, Custom);
99
+ continue ;
100
+ }
101
+
102
+ if (VT == MVT::i64 ) {
103
+ continue ;
104
+ }
105
+
106
+ // Set unsupported atomic operations as Custom so we can emit better error
107
+ // messages than fatal error from selectiondag.
88
108
if (VT == MVT::i32 ) {
89
109
if (STI.getHasAlu32 ())
90
110
continue ;
@@ -222,7 +242,17 @@ bool BPFTargetLowering::allowsMisalignedMemoryAccesses(
222
242
return isSolana;
223
243
}
224
244
225
- bool BPFTargetLowering::isOffsetFoldingLegal (const GlobalAddressSDNode *GA) const {
245
+ bool BPFTargetLowering::lowerAtomicStoreAsStoreSDNode (
246
+ const StoreInst &SI) const {
247
+ return Subtarget->isSolana ();
248
+ }
249
+
250
+ bool BPFTargetLowering::lowerAtomicLoadAsLoadSDNode (const LoadInst &LI) const {
251
+ return Subtarget->isSolana ();
252
+ }
253
+
254
+ bool BPFTargetLowering::isOffsetFoldingLegal (
255
+ const GlobalAddressSDNode *GA) const {
226
256
return false ;
227
257
}
228
258
@@ -318,6 +348,21 @@ void BPFTargetLowering::ReplaceNodeResults(
318
348
case ISD::ATOMIC_LOAD_XOR:
319
349
case ISD::ATOMIC_SWAP:
320
350
case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
351
+ case ISD::ATOMIC_LOAD_ADD:
352
+ case ISD::ATOMIC_LOAD_AND:
353
+ case ISD::ATOMIC_LOAD_MAX:
354
+ case ISD::ATOMIC_LOAD_MIN:
355
+ case ISD::ATOMIC_LOAD_NAND:
356
+ case ISD::ATOMIC_LOAD_OR:
357
+ case ISD::ATOMIC_LOAD_SUB:
358
+ case ISD::ATOMIC_LOAD_UMAX:
359
+ case ISD::ATOMIC_LOAD_UMIN:
360
+ case ISD::ATOMIC_LOAD_XOR:
361
+ if (Subtarget->isSolana ()) {
362
+ // We do lowering during legalization, see LowerOperation()
363
+ return ;
364
+ }
365
+
321
366
if (HasAlu32 || Opcode == ISD::ATOMIC_LOAD_ADD)
322
367
Msg = " unsupported atomic operation, please use 32/64 bit version" ;
323
368
else
@@ -346,6 +391,23 @@ SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
346
391
return LowerSDIVSREM (Op, DAG);
347
392
case ISD::DYNAMIC_STACKALLOC:
348
393
return LowerDYNAMIC_STACKALLOC (Op, DAG);
394
+ case ISD::ATOMIC_SWAP:
395
+ case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
396
+ case ISD::ATOMIC_LOAD_ADD:
397
+ case ISD::ATOMIC_LOAD_AND:
398
+ case ISD::ATOMIC_LOAD_MAX:
399
+ case ISD::ATOMIC_LOAD_MIN:
400
+ case ISD::ATOMIC_LOAD_NAND:
401
+ case ISD::ATOMIC_LOAD_OR:
402
+ case ISD::ATOMIC_LOAD_SUB:
403
+ case ISD::ATOMIC_LOAD_UMAX:
404
+ case ISD::ATOMIC_LOAD_UMIN:
405
+ case ISD::ATOMIC_LOAD_XOR:
406
+ return LowerATOMICRMW (Op, DAG);
407
+ case ISD::DYNAMIC_STACKALLOC:
408
+ report_fatal_error (" Unsupported dynamic stack allocation" );
409
+ default :
410
+ llvm_unreachable (" unimplemented atomic operand" );
349
411
}
350
412
}
351
413
@@ -444,7 +506,6 @@ SDValue BPFTargetLowering::LowerFormalArguments(
444
506
fail (DL, DAG, " functions with VarArgs or StructRet are not supported" );
445
507
}
446
508
447
-
448
509
return Chain;
449
510
}
450
511
@@ -788,6 +849,114 @@ SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
788
849
return DAG.getNode (BPFISD::SELECT_CC, DL, VTs, Ops);
789
850
}
790
851
852
+ SDValue BPFTargetLowering::LowerATOMICRMW (SDValue Op, SelectionDAG &DAG) const {
853
+ SDLoc DL (Op);
854
+ AtomicSDNode *AN = cast<AtomicSDNode>(Op);
855
+ assert (AN && " Expected custom lowering of an atomic load node" );
856
+
857
+ SDValue Chain = AN->getChain ();
858
+ SDValue Ptr = AN->getBasePtr ();
859
+ EVT PtrVT = AN->getMemoryVT ();
860
+ EVT RetVT = Op.getValueType ();
861
+
862
+ // Load the current value
863
+ SDValue Load =
864
+ DAG.getExtLoad (ISD::EXTLOAD, DL, RetVT, Chain, Ptr, MachinePointerInfo (),
865
+ PtrVT, AN->getAlignment ());
866
+ Chain = Load.getValue (1 );
867
+
868
+ // Most ops return the current value, except CMP_SWAP_WITH_SUCCESS see below
869
+ SDValue Ret = Load;
870
+ SDValue RetFlag;
871
+
872
+ // Val contains the new value we want to set. For CMP_SWAP, Cmp contains the
873
+ // expected current value.
874
+ SDValue Cmp, Val;
875
+ if (AN->isCompareAndSwap ()) {
876
+ Cmp = Op.getOperand (2 );
877
+ Val = Op.getOperand (3 );
878
+
879
+ // The Cmp value must match the pointer type
880
+ EVT CmpVT = Cmp->getValueType (0 );
881
+ if (CmpVT != RetVT) {
882
+ Cmp = RetVT.bitsGT (CmpVT) ? DAG.getNode (ISD::SIGN_EXTEND, DL, RetVT, Cmp)
883
+ : DAG.getNode (ISD::TRUNCATE, DL, RetVT, Cmp);
884
+ }
885
+ } else {
886
+ Val = AN->getVal ();
887
+ }
888
+
889
+ // The new value type must match the pointer type
890
+ EVT ValVT = Val->getValueType (0 );
891
+ if (ValVT != RetVT) {
892
+ Val = RetVT.bitsGT (ValVT) ? DAG.getNode (ISD::SIGN_EXTEND, DL, RetVT, Val)
893
+ : DAG.getNode (ISD::TRUNCATE, DL, RetVT, Val);
894
+ ValVT = Val->getValueType (0 );
895
+ }
896
+
897
+ SDValue NewVal;
898
+ switch (Op.getOpcode ()) {
899
+ case ISD::ATOMIC_SWAP:
900
+ NewVal = Val;
901
+ break ;
902
+ case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: {
903
+ EVT RetFlagVT = AN->getValueType (1 );
904
+ NewVal = DAG.getSelectCC (DL, Load, Cmp, Val, Load, ISD::SETEQ);
905
+ RetFlag = DAG.getSelectCC (
906
+ DL, Load, Cmp, DAG.getBoolConstant (true , DL, RetFlagVT, RetFlagVT),
907
+ DAG.getBoolConstant (false , DL, RetFlagVT, RetFlagVT), ISD::SETEQ);
908
+ break ;
909
+ }
910
+ case ISD::ATOMIC_LOAD_ADD:
911
+ NewVal = DAG.getNode (ISD::ADD, DL, ValVT, Load, Val);
912
+ break ;
913
+ case ISD::ATOMIC_LOAD_SUB:
914
+ NewVal = DAG.getNode (ISD::SUB, DL, ValVT, Load, Val);
915
+ break ;
916
+ case ISD::ATOMIC_LOAD_AND:
917
+ NewVal = DAG.getNode (ISD::AND, DL, ValVT, Load, Val);
918
+ break ;
919
+ case ISD::ATOMIC_LOAD_NAND: {
920
+ NewVal =
921
+ DAG.getNOT (DL, DAG.getNode (ISD::AND, DL, ValVT, Load, Val), ValVT);
922
+ break ;
923
+ }
924
+ case ISD::ATOMIC_LOAD_OR:
925
+ NewVal = DAG.getNode (ISD::OR, DL, ValVT, Load, Val);
926
+ break ;
927
+ case ISD::ATOMIC_LOAD_XOR:
928
+ NewVal = DAG.getNode (ISD::XOR, DL, ValVT, Load, Val);
929
+ break ;
930
+ case ISD::ATOMIC_LOAD_MIN:
931
+ NewVal = DAG.getNode (ISD::SMIN, DL, ValVT, Load, Val);
932
+ break ;
933
+ case ISD::ATOMIC_LOAD_UMIN:
934
+ NewVal = DAG.getNode (ISD::UMIN, DL, ValVT, Load, Val);
935
+ break ;
936
+ case ISD::ATOMIC_LOAD_MAX:
937
+ NewVal = DAG.getNode (ISD::SMAX, DL, ValVT, Load, Val);
938
+ break ;
939
+ case ISD::ATOMIC_LOAD_UMAX:
940
+ NewVal = DAG.getNode (ISD::UMAX, DL, ValVT, Load, Val);
941
+ break ;
942
+ default :
943
+ llvm_unreachable (" unknown atomicrmw op" );
944
+ }
945
+
946
+ Chain =
947
+ DAG.getTruncStore (Chain, DL, NewVal, Ptr, MachinePointerInfo (), PtrVT);
948
+
949
+ if (RetFlag) {
950
+ // CMP_SWAP_WITH_SUCCESS returns {value, success, chain}
951
+ Ret = DAG.getMergeValues ({Ret, RetFlag, Chain}, DL);
952
+ } else {
953
+ // All the other ops return {value, chain}
954
+ Ret = DAG.getMergeValues ({Ret, Chain}, DL);
955
+ }
956
+
957
+ return Ret;
958
+ }
959
+
791
960
const char *BPFTargetLowering::getTargetNodeName (unsigned Opcode) const {
792
961
switch ((BPFISD::NodeType)Opcode) {
793
962
case BPFISD::FIRST_NUMBER:
@@ -897,6 +1066,7 @@ BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
897
1066
Opc == BPF::Select_32_64);
898
1067
899
1068
bool isMemcpyOp = Opc == BPF::MEMCPY;
1069
+ bool isAtomicFence = Opc == BPF::ATOMIC_FENCE;
900
1070
901
1071
#ifndef NDEBUG
902
1072
bool isSelectRIOp = (Opc == BPF::Select_Ri ||
@@ -911,6 +1081,12 @@ BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
911
1081
if (isMemcpyOp)
912
1082
return EmitInstrWithCustomInserterMemcpy (MI, BB);
913
1083
1084
+ if (isAtomicFence) {
1085
+ // this is currently a nop
1086
+ MI.eraseFromParent ();
1087
+ return BB;
1088
+ }
1089
+
914
1090
bool is32BitCmp = (Opc == BPF::Select_32 ||
915
1091
Opc == BPF::Select_32_64 ||
916
1092
Opc == BPF::Select_Ri_32 ||
0 commit comments