diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -417,8 +417,15 @@ bool isFenceArg() const { if (!isImm()) return false; - const MCExpr *Val = getImm(); - auto *SVal = dyn_cast(Val); + + int64_t Imm; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; + if (evaluateConstantImm(getImm(), Imm, VK)) { + // Only accept 0 as a constant immediate. + return VK == RISCVMCExpr::VK_RISCV_None && Imm == 0; + } + + auto *SVal = dyn_cast(getImm()); if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) return false; @@ -899,14 +906,24 @@ void addFenceArgOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); + + int64_t Constant = 0; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; + if (evaluateConstantImm(getImm(), Constant, VK)) { + if (Constant == 0) { + Inst.addOperand(MCOperand::createImm(Constant)); + return; + } + llvm_unreachable("FenceArg must contain only [iorw] or be 0"); + } + // isFenceArg has validated the operand, meaning this cast is safe auto SE = cast(getImm()); - unsigned Imm = 0; for (char c : SE->getSymbol().getName()) { switch (c) { default: - llvm_unreachable("FenceArg must contain only [iorw]"); + llvm_unreachable("FenceArg must contain only [iorw] or be 0"); case 'i': Imm |= RISCVFenceField::I; break; case 'o': Imm |= RISCVFenceField::O; break; case 'r': Imm |= RISCVFenceField::R; break; @@ -1164,9 +1181,8 @@ } case Match_InvalidFenceArg: { SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); - return Error( - ErrorLoc, - "operand must be formed of letters selected in-order from 'iorw'"); + return Error(ErrorLoc, "operand must be formed of letters selected " + "in-order from 'iorw' or be 0"); } case Match_InvalidFRMArg: { SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -146,7 +146,7 @@ if ((FenceArg & RISCVFenceField::W) != 0) O << 'w'; if (FenceArg == 0) - O << "unknown"; + O << '0'; } void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -713,6 +713,8 @@ def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw +def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w + def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s --- a/llvm/test/MC/RISCV/rv32i-invalid.s +++ b/llvm/test/MC/RISCV/rv32i-invalid.s @@ -2,11 +2,11 @@ # Out of range immediates ## fencearg -fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw' -fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' -fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw' -fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' -fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' +fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw' or be 0 +fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0 +fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw' or be 0 +fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0 +fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0 ## uimm5 slli a0, a0, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31] diff --git a/llvm/test/MC/RISCV/rv32i-valid.s b/llvm/test/MC/RISCV/rv32i-valid.s --- a/llvm/test/MC/RISCV/rv32i-valid.s +++ b/llvm/test/MC/RISCV/rv32i-valid.s @@ -326,6 +326,15 @@ # CHECK-ASM-AND-OBJ: fence w, ir # CHECK-ASM: encoding: [0x0f,0x00,0xa0,0x01] fence w,ir +# CHECK-ASM-AND-OBJ: fence w, 0 +# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x01] +fence w,0 +# CHECK-ASM-AND-OBJ: fence 0, w +# CHECK-ASM: encoding: [0x0f,0x00,0x10,0x00] +fence 0,w +# CHECK-ASM-AND-OBJ: fence 0, 0 +# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x00] +fence 0,0 # CHECK-ASM-AND-OBJ: fence.tso # CHECK-ASM: encoding: [0x0f,0x00,0x30,0x83] fence.tso diff --git a/llvm/test/MC/RISCV/rvi-aliases-valid.s b/llvm/test/MC/RISCV/rvi-aliases-valid.s --- a/llvm/test/MC/RISCV/rvi-aliases-valid.s +++ b/llvm/test/MC/RISCV/rvi-aliases-valid.s @@ -197,6 +197,10 @@ # CHECK-S-OBJ: fence fence +# CHECK-S-OBJ-NOALIAS: fence w, 0 +# CHECK-S-OBJ: pause +pause + # CHECK-S-OBJ-NOALIAS: csrrs s10, instret, zero # CHECK-S-OBJ: rdinstret s10 rdinstret x26