A question about riscv fence instruction

Here is the definition I found for the fence instruction.

let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
                    (ins fencearg:$pred, fencearg:$succ),
                    "fence", "$pred, $succ">, Sched<[]> {
  bits<4> pred;
  bits<4> succ;

  let rs1 = 0;
  let rd = 0;
  let imm12 = {0b0000,pred,succ};
}

I have this question, the fence instruction has no operands, but here is why it has (ins fencearg:$pred, fencearg:$succ).If anyone can help me, I would be grateful.Thanks!

By asking others, I learned that the fence instruction has a default operand.

Specifically via:

def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw

Thanks!I would also like to ask a question, can I use intrinsics to map fence? I don’t know what to use to match the fence.

What do you mean, “to map fence”?

Yes, I want to insert fence manually.

For example.

let TargetPrefix = "riscv" in
def int_riscv_mvin : Intrinsic<[],[llvm_i64_ty, llvm_i64_ty],[]>;

let Predicates = [HasBuddyExt] in
def: PatGprGpr<int_riscv_mvin, MVIN>;

let hasSideEffects = 1, mayLoad = 1, mayStore = 1 , Predicates = [HasBuddyExt] in
def MVIN : RVInstR<0b0000010, 0b011, OPC_CUSTOM_3, (outs),
                   (ins GPR:$rs1, GPR:$rs2), "mvin","$rs1, $rs2"> {
  let rd = 0;              
}

PatGprGpr is used here, but I don’t know what should be used here for fence, I didn’t find any relevant information.

You could use a pseudo-instruction that gets expanded later, you could do custom lowering or you could have an IR pass that inserts the needed fences as explicit instructions in the IR during CodeGenPrepare like AtomicExpandPass does for non-monotonic atomic loads/stores. Though I do have questions about what exactly your instruction is doing and why you need fences here…

The mvin instruction is used to put data into the coprocessor, and mvout is used to pass data out of the coprocessor. I’m currently having this problem, I found that mvout doesn’t work, I found that the correct test case is using fence, I decided that it’s because I didn’t use fence.The original compiler uses gcc, I need to do some support on llvm and I still want to be able to insert fence manually.Thank you for your reply.

Why does fence, something that affects memory, matter for instructions that aren’t loads, stores or AMOs?

At the moment I’m just guessing because I didn’t use fence, I think the coprocessor didn’t have time to transfer the data to the memory of the host, the original toolchain is using gcc, he has his own test cases, in the test cases manually inserted the fence instruction, I need to do some support on llvm, and need to test llvm. Now I write fence in the assembly file and use llvm-mc for testing, but the generated obj file is soft-float, need hard-float, but I don’t find the corresponding option in mc, I am solving this problem, or looking for other ways to test.