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 @@ -31,6 +31,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Casting.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributes.h" @@ -1856,34 +1857,11 @@ Expr = RE->getSubExpr(); } - // It's a simple symbol reference or constant with no addend. - if (isa(Expr) || isa(Expr)) - return true; - - const MCBinaryExpr *BE = dyn_cast(Expr); - if (!BE) - return false; - - if (!isa(BE->getLHS())) - return false; - - if (BE->getOpcode() != MCBinaryExpr::Add && - BE->getOpcode() != MCBinaryExpr::Sub) - return false; - - // We are able to support the subtraction of two symbol references - if (BE->getOpcode() == MCBinaryExpr::Sub && - isa(BE->getRHS())) - return true; - - // See if the addend is a constant, otherwise there's more going - // on here than we can deal with. - auto AddendExpr = dyn_cast(BE->getRHS()); - if (!AddendExpr) - return false; - - // It's some symbol reference + a constant addend - return Kind != RISCVMCExpr::VK_RISCV_Invalid; + MCValue Res; + MCFixup Fixup; + if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) + return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None; + return false; } bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { diff --git a/llvm/test/MC/RISCV/rvi-pseudos-invalid.s b/llvm/test/MC/RISCV/rvi-pseudos-invalid.s --- a/llvm/test/MC/RISCV/rvi-pseudos-invalid.s +++ b/llvm/test/MC/RISCV/rvi-pseudos-invalid.s @@ -27,3 +27,5 @@ # Too few operands must be rejected sw a2, a_symbol # CHECK: :[[@LINE]]:1: error: too few operands for instruction + +la a1, foo+foo # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name diff --git a/llvm/test/MC/RISCV/rvi-pseudos.s b/llvm/test/MC/RISCV/rvi-pseudos.s --- a/llvm/test/MC/RISCV/rvi-pseudos.s +++ b/llvm/test/MC/RISCV/rvi-pseudos.s @@ -181,3 +181,9 @@ # CHECK: auipc a4, %pcrel_hi(zero) # CHECK: sw a3, %pcrel_lo(.Lpcrel_hi29)(a4) sw a3, zero, a4 + +## Check that a complex expression can be simplified and matched. +# CHECK: .Lpcrel_hi30: +# CHECK: auipc a5, %pcrel_hi((255+a_symbol)-4) +# CHECK: addi a5, a5, %pcrel_lo(.Lpcrel_hi30) +lla a5, (0xFF + a_symbol) - 4