@@ -73,6 +73,8 @@ class RISCVInstructionSelector : public InstructionSelector {
73
73
MachineRegisterInfo &MRI) const ;
74
74
bool selectIntrinsicWithSideEffects (MachineInstr &MI, MachineIRBuilder &MIB,
75
75
MachineRegisterInfo &MRI) const ;
76
+ void emitFence (AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID,
77
+ MachineIRBuilder &MIB) const ;
76
78
77
79
ComplexRendererFns selectShiftMask (MachineOperand &Root) const ;
78
80
ComplexRendererFns selectAddrRegImm (MachineOperand &Root) const ;
@@ -612,6 +614,15 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
612
614
return selectFPCompare (MI, MIB, MRI);
613
615
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
614
616
return selectIntrinsicWithSideEffects (MI, MIB, MRI);
617
+ case TargetOpcode::G_FENCE: {
618
+ AtomicOrdering FenceOrdering =
619
+ static_cast <AtomicOrdering>(MI.getOperand (0 ).getImm ());
620
+ SyncScope::ID FenceSSID =
621
+ static_cast <SyncScope::ID>(MI.getOperand (1 ).getImm ());
622
+ emitFence (FenceOrdering, FenceSSID, MIB);
623
+ MI.eraseFromParent ();
624
+ return true ;
625
+ }
615
626
default :
616
627
return false ;
617
628
}
@@ -1087,6 +1098,63 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
1087
1098
return true ;
1088
1099
}
1089
1100
1101
+ void RISCVInstructionSelector::emitFence (AtomicOrdering FenceOrdering,
1102
+ SyncScope::ID FenceSSID,
1103
+ MachineIRBuilder &MIB) const {
1104
+ if (STI.hasStdExtZtso ()) {
1105
+ // The only fence that needs an instruction is a sequentially-consistent
1106
+ // cross-thread fence.
1107
+ if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1108
+ FenceSSID == SyncScope::System) {
1109
+ // fence rw, rw
1110
+ MIB.buildInstr (RISCV::FENCE, {}, {})
1111
+ .addImm (RISCVFenceField::R | RISCVFenceField::W)
1112
+ .addImm (RISCVFenceField::R | RISCVFenceField::W);
1113
+ return ;
1114
+ }
1115
+
1116
+ // MEMBARRIER is a compiler barrier; it codegens to a no-op.
1117
+ MIB.buildInstr (TargetOpcode::MEMBARRIER, {}, {});
1118
+ return ;
1119
+ }
1120
+
1121
+ // singlethread fences only synchronize with signal handlers on the same
1122
+ // thread and thus only need to preserve instruction order, not actually
1123
+ // enforce memory ordering.
1124
+ if (FenceSSID == SyncScope::SingleThread) {
1125
+ MIB.buildInstr (TargetOpcode::MEMBARRIER, {}, {});
1126
+ return ;
1127
+ }
1128
+
1129
+ // Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
1130
+ // Manual: Volume I.
1131
+ unsigned Pred, Succ;
1132
+ switch (FenceOrdering) {
1133
+ default :
1134
+ llvm_unreachable (" Unexpected ordering" );
1135
+ case AtomicOrdering::AcquireRelease:
1136
+ // fence acq_rel -> fence.tso
1137
+ MIB.buildInstr (RISCV::FENCE_TSO, {}, {});
1138
+ return ;
1139
+ case AtomicOrdering::Acquire:
1140
+ // fence acquire -> fence r, rw
1141
+ Pred = RISCVFenceField::R;
1142
+ Succ = RISCVFenceField::R | RISCVFenceField::W;
1143
+ break ;
1144
+ case AtomicOrdering::Release:
1145
+ // fence release -> fence rw, w
1146
+ Pred = RISCVFenceField::R | RISCVFenceField::W;
1147
+ Succ = RISCVFenceField::W;
1148
+ break ;
1149
+ case AtomicOrdering::SequentiallyConsistent:
1150
+ // fence seq_cst -> fence rw, rw
1151
+ Pred = RISCVFenceField::R | RISCVFenceField::W;
1152
+ Succ = RISCVFenceField::R | RISCVFenceField::W;
1153
+ break ;
1154
+ }
1155
+ MIB.buildInstr (RISCV::FENCE, {}, {}).addImm (Pred).addImm (Succ);
1156
+ }
1157
+
1090
1158
namespace llvm {
1091
1159
InstructionSelector *
1092
1160
createRISCVInstructionSelector (const RISCVTargetMachine &TM,
0 commit comments