https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114673

            Bug ID: 114673
           Summary: RISC-V: "L" constraint cannot be used for lui in
                    inline asm
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: cmuellner at gcc dot gnu.org
  Target Milestone: ---

The RISC-V-specific "L" constraint is neither documented nor tested.
In constraints.md it is defined as "A U-type 20-bit signed immediate.".
It tests if the value is a constant int that satisfies LUI_OPERAND(),
i.e. a value with the lowest 12 bits zero.

One obvious use-case is to use "L" for "lui" in inline asm.
However, it does not work as expected:

long getB()
{
    //lui a0,0x1800
    return 3<<23; //0x01800000
}

long getB_asm_i()
{
    long reg;
    //lui a0,0x1800
    asm("lui %0, %1" : "=r"(reg) : "i"((3<<23) >> 12));
    return reg;
}

long getB_asm_L()
{
    long reg;
    //Assembler error: lui expression not in range 0..1048575
    asm("lui %0, %1" : "=r"(reg) : "L"(3ul<<23));
    return reg;
}

long getB_asm_Lshift()
{
    long reg;
    //Compiler error: impossible constraint in 'asm'
    asm("lui %0, %1" : "=r"(reg) : "L"((3<<23) >> 12));
    return reg;
}

The "L" constraint was introduced as part of the initial RISC-V port.
I could not find any tests/documentation, so I am unsure if it can be fixed
or if a new constraint should be introduced.

My preferred fix would be to shift the provided constant right by 12
if it satisfies LUI_OPERAND(), so that getB_asm_L() would work.

Reply via email to