Skip to content

[RISCV] Mark symbols used in inline asm for relocations as referenced #104925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 26, 2024

Conversation

asi-sc
Copy link
Contributor

@asi-sc asi-sc commented Aug 20, 2024

Commit 5cd8d53 taught RISCVMergeBaseOffset to handle inline asm, however
there is at least one case uncovered for integrated as.

In the example below compiler generates pcrel relocation (mcmodel=medany)

    volatile double double_val = 1.0;
    void foo() {
        asm volatile("fld f0, %0 \n\t" : : "m"(double_val) : "memory");
    }

And fails with the folliwng error

    error: could not find corresponding %pcrel_hi
          |       "fld f0, %0 \n\t"
    <inline asm>:1:2: note: instantiated into assembly here
          |         fld f0, %pcrel_lo(.Lpcrel_hi0)(a0)

After transformations MachineFunction contains inline asm instructions with
'.Lpcrel_hi0' symbol that is not defined in inline asm, but referenced.

   ... = AUIPC ...(riscv-pcrel-hi) @double_val, pre-instr-symbol <mcsymbol .Lpcrel_hi0>
   INLINEASM &"fld f0, $0 \0A\09" ... target-flags(riscv-pcrel-lo) <mcsymbol .Lpcrel_hi0>

So, when AsmParser processes 'fld', it has to create a new symbol as
'.Lpcrel_hi0' already exists but not known to be referenced in inline asm.
AsmParser avoids conflicts by renaming referenced by 'fld' symbol with
'.Lpcrel_hi00' name which does not exist. Resulting erroneous asm

    .Lpcrel_hi0:
        auipc   a0, %pcrel_hi(double_val)
        #APP
        fld     ft0, %pcrel_lo(.Lpcrel_hi00)(a0)

This change adds symbols used in memory operands to the list of referenced ones.

Godbolt link: https://godbolt.org/z/aqrrsWKoK -- on the left you can find incorrect labels for the integrated-as and on the right an error when compiling to the binary object.

Note that I change tests in the first commit and the second commit shows the real difference after the fix.

@llvmbot
Copy link
Member

llvmbot commented Aug 20, 2024

@llvm/pr-subscribers-backend-risc-v

Author: Anton Sidorenko (asi-sc)

Changes

Commit 5cd8d53 taught RISCVMergeBaseOffset to handle inline asm, however
there is at least one case uncovered for integrated as.

In the example below compiler generates pcrel relocation (mcmodel=medany)

    volatile double double_val = 1.0;
    void foo() {
        asm volatile("fld f0, %0 \n\t" : : "m"(double_val) : "memory");
    }

And fails with the folliwng error

    error: could not find corresponding %pcrel_hi
          |       "fld f0, %0 \n\t"
    &lt;inline asm&gt;:1:2: note: instantiated into assembly here
          |         fld f0, %pcrel_lo(.Lpcrel_hi0)(a0)

After transformations MachineFunction contains inline asm instructions with
'.Lpcrel_hi0' symbol that is not defined in inline asm, but referenced.

   ... = AUIPC ...(riscv-pcrel-hi) @<!-- -->double_val, pre-instr-symbol &lt;mcsymbol .Lpcrel_hi0&gt;
   INLINEASM &amp;"fld f0, $0 \0A\09" ... target-flags(riscv-pcrel-lo) &lt;mcsymbol .Lpcrel_hi0&gt;

So, when AsmParser processes 'fld', it has to create a new symbol as
'.Lpcrel_hi0' already exists but not known to be referenced in inline asm.
AsmParser avoids conflicts by renaming referenced by 'fld' symbol with
'.Lpcrel_hi00' name which does not exist. Resulting erroneous asm

    .Lpcrel_hi0:
        auipc   a0, %pcrel_hi(double_val)
        #APP
        fld     ft0, %pcrel_lo(.Lpcrel_hi00)(a0)

This change adds symbols used in memory operands to the list of referenced ones.

Godbolt link: https://godbolt.org/z/aqrrsWKoK -- on the left you can find incorrect labels for the integrated-as and on the right an error when compiling to the binary object.

Note that I change tests in the first commit and the second commit shows the real difference after the fix.


Patch is 90.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104925.diff

3 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+9)
  • (added) llvm/test/CodeGen/RISCV/inline-asm-mem-constraint-2.ll (+95)
  • (modified) llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll (+1039-597)
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 93677433c04405..476dde2be39e57 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -396,6 +396,15 @@ bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
     OS << MCO.getImm();
   else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
     OS << *MCO.getExpr();
+
+  if (Offset.isMCSymbol())
+    MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
+  if (Offset.isBlockAddress()) {
+    const BlockAddress *BA = Offset.getBlockAddress();
+    MCSymbol *Sym = GetBlockAddressSymbol(BA);
+    MMI->getContext().registerInlineAsmLabel(Sym);
+  }
+
   OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
   return false;
 }
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint-2.ll b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint-2.ll
new file mode 100644
index 00000000000000..f0bad08bd44388
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint-2.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; integrated-as fails with error: unexpected token
+;   sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0)
+;                        ^
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
+; RUN:   | FileCheck -check-prefixes=RV32I %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %s \
+; RUN:   | FileCheck -check-prefixes=RV64I %s
+; RUN: llc -mtriple=riscv32 -code-model=medium -verify-machineinstrs -no-integrated-as < %s \
+; RUN:   | FileCheck -check-prefixes=RV32I-MEDIUM %s
+; RUN: llc -mtriple=riscv64 -code-model=medium -verify-machineinstrs -no-integrated-as < %s \
+; RUN:   | FileCheck -check-prefixes=RV64I-MEDIUM %s
+
+@eg = external global [4000 x i32], align 4
+@ewg = extern_weak global [4000 x i32], align 4
+
+define void @constraint_o_with_multi_operands() nounwind {
+; RV32I-LABEL: constraint_o_with_multi_operands:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a0, %hi(eg)
+; RV32I-NEXT:    #APP
+; RV32I-NEXT:    sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0)
+; RV32I-NEXT:    #NO_APP
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: constraint_o_with_multi_operands:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a0, %hi(eg)
+; RV64I-NEXT:    #APP
+; RV64I-NEXT:    sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0)
+; RV64I-NEXT:    #NO_APP
+; RV64I-NEXT:    ret
+;
+; RV32I-MEDIUM-LABEL: constraint_o_with_multi_operands:
+; RV32I-MEDIUM:       # %bb.0:
+; RV32I-MEDIUM-NEXT:  .Lpcrel_hi0:
+; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT:    #APP
+; RV32I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi0)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi0)(a0)
+; RV32I-MEDIUM-NEXT:    #NO_APP
+; RV32I-MEDIUM-NEXT:    ret
+;
+; RV64I-MEDIUM-LABEL: constraint_o_with_multi_operands:
+; RV64I-MEDIUM:       # %bb.0:
+; RV64I-MEDIUM-NEXT:  .Lpcrel_hi0:
+; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT:    #APP
+; RV64I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi0)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi0)(a0)
+; RV64I-MEDIUM-NEXT:    #NO_APP
+; RV64I-MEDIUM-NEXT:    ret
+  call void asm "sw zero, $0 \n sw zero, $1", "=*o,=*o"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg)
+  ret void
+}
+
+define void @constraint_A_with_multi_operands() nounwind {
+; RV32I-LABEL: constraint_A_with_multi_operands:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a0, %hi(eg)
+; RV32I-NEXT:    addi a0, a0, %lo(eg)
+; RV32I-NEXT:    #APP
+; RV32I-NEXT:    sw zero, 0(a0) \n sw zero, 0(a0)
+; RV32I-NEXT:    #NO_APP
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: constraint_A_with_multi_operands:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    lui a0, %hi(eg)
+; RV64I-NEXT:    addi a0, a0, %lo(eg)
+; RV64I-NEXT:    #APP
+; RV64I-NEXT:    sw zero, 0(a0) \n sw zero, 0(a0)
+; RV64I-NEXT:    #NO_APP
+; RV64I-NEXT:    ret
+;
+; RV32I-MEDIUM-LABEL: constraint_A_with_multi_operands:
+; RV32I-MEDIUM:       # %bb.0:
+; RV32I-MEDIUM-NEXT:  .Lpcrel_hi1:
+; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.Lpcrel_hi1)
+; RV32I-MEDIUM-NEXT:    #APP
+; RV32I-MEDIUM-NEXT:    sw zero, 0(a0) \n sw zero, 0(a0)
+; RV32I-MEDIUM-NEXT:    #NO_APP
+; RV32I-MEDIUM-NEXT:    ret
+;
+; RV64I-MEDIUM-LABEL: constraint_A_with_multi_operands:
+; RV64I-MEDIUM:       # %bb.0:
+; RV64I-MEDIUM-NEXT:  .Lpcrel_hi1:
+; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.Lpcrel_hi1)
+; RV64I-MEDIUM-NEXT:    #APP
+; RV64I-MEDIUM-NEXT:    sw zero, 0(a0) \n sw zero, 0(a0)
+; RV64I-MEDIUM-NEXT:    #NO_APP
+; RV64I-MEDIUM-NEXT:    ret
+  call void asm "sw zero, $0 \n sw zero, $1", "=*A,=*A"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg)
+  ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
index 6666d92feaac2e..82798a22014ec6 100644
--- a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
+++ b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
@@ -1,12 +1,20 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
-; RUN:   | FileCheck -check-prefixes=RV32I %s
+; RUN:   | FileCheck -check-prefixes=RV32I,RV32I-NO-INTEGRATED %s
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %s \
-; RUN:   | FileCheck -check-prefixes=RV64I %s
+; RUN:   | FileCheck -check-prefixes=RV64I,RV64I-NO-INTEGRATED %s
 ; RUN: llc -mtriple=riscv32 -code-model=medium -verify-machineinstrs -no-integrated-as < %s \
-; RUN:   | FileCheck -check-prefixes=RV32I-MEDIUM %s
+; RUN:   | FileCheck -check-prefixes=RV32I-MEDIUM,RV32I-MEDIUM-NO-INTEGRATED %s
 ; RUN: llc -mtriple=riscv64 -code-model=medium -verify-machineinstrs -no-integrated-as < %s \
-; RUN:   | FileCheck -check-prefixes=RV64I-MEDIUM %s
+; RUN:   | FileCheck -check-prefixes=RV64I-MEDIUM,RV64I-MEDIUM-NO-INTEGRATED %s
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32I,RV32I-INTEGRATED %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64I,RV64I-INTEGRATED %s
+; RUN: llc -mtriple=riscv32 -code-model=medium -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV32I-MEDIUM,RV32I-MEDIUM-INTEGRATED %s
+; RUN: llc -mtriple=riscv64 -code-model=medium -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=RV64I-MEDIUM,RV64I-MEDIUM-INTEGRATED %s
 
 @eg = external global [4000 x i32], align 4
 @ewg = extern_weak global [4000 x i32], align 4
@@ -495,39 +503,77 @@ label:
 }
 
 define void @constraint_m_with_multi_operands() nounwind {
-; RV32I-LABEL: constraint_m_with_multi_operands:
-; RV32I:       # %bb.0:
-; RV32I-NEXT:    lui a0, %hi(eg)
-; RV32I-NEXT:    #APP
-; RV32I-NEXT:    sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0)
-; RV32I-NEXT:    #NO_APP
-; RV32I-NEXT:    ret
-;
-; RV64I-LABEL: constraint_m_with_multi_operands:
-; RV64I:       # %bb.0:
-; RV64I-NEXT:    lui a0, %hi(eg)
-; RV64I-NEXT:    #APP
-; RV64I-NEXT:    sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0)
-; RV64I-NEXT:    #NO_APP
-; RV64I-NEXT:    ret
-;
-; RV32I-MEDIUM-LABEL: constraint_m_with_multi_operands:
-; RV32I-MEDIUM:       # %bb.0:
-; RV32I-MEDIUM-NEXT:  .Lpcrel_hi9:
-; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
-; RV32I-MEDIUM-NEXT:    #APP
-; RV32I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
-; RV32I-MEDIUM-NEXT:    #NO_APP
-; RV32I-MEDIUM-NEXT:    ret
-;
-; RV64I-MEDIUM-LABEL: constraint_m_with_multi_operands:
-; RV64I-MEDIUM:       # %bb.0:
-; RV64I-MEDIUM-NEXT:  .Lpcrel_hi9:
-; RV64I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(eg)
-; RV64I-MEDIUM-NEXT:    #APP
-; RV64I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
-; RV64I-MEDIUM-NEXT:    #NO_APP
-; RV64I-MEDIUM-NEXT:    ret
+; RV32I-NO-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV32I-NO-INTEGRATED:       # %bb.0:
+; RV32I-NO-INTEGRATED-NEXT:    lui a0, %hi(eg)
+; RV32I-NO-INTEGRATED-NEXT:    #APP
+; RV32I-NO-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0)
+; RV32I-NO-INTEGRATED-NEXT:    #NO_APP
+; RV32I-NO-INTEGRATED-NEXT:    ret
+;
+; RV64I-NO-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV64I-NO-INTEGRATED:       # %bb.0:
+; RV64I-NO-INTEGRATED-NEXT:    lui a0, %hi(eg)
+; RV64I-NO-INTEGRATED-NEXT:    #APP
+; RV64I-NO-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0)
+; RV64I-NO-INTEGRATED-NEXT:    #NO_APP
+; RV64I-NO-INTEGRATED-NEXT:    ret
+;
+; RV32I-MEDIUM-NO-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV32I-MEDIUM-NO-INTEGRATED:       # %bb.0:
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:  .Lpcrel_hi9:
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    #APP
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    #NO_APP
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+;
+; RV64I-MEDIUM-NO-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV64I-MEDIUM-NO-INTEGRATED:       # %bb.0:
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:  .Lpcrel_hi9:
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    #APP
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    #NO_APP
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+;
+; RV32I-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV32I-INTEGRATED:       # %bb.0:
+; RV32I-INTEGRATED-NEXT:    lui a0, %hi(eg)
+; RV32I-INTEGRATED-NEXT:    #APP
+; RV32I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0)
+; RV32I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0)
+; RV32I-INTEGRATED-NEXT:    #NO_APP
+; RV32I-INTEGRATED-NEXT:    ret
+;
+; RV64I-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV64I-INTEGRATED:       # %bb.0:
+; RV64I-INTEGRATED-NEXT:    lui a0, %hi(eg)
+; RV64I-INTEGRATED-NEXT:    #APP
+; RV64I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0)
+; RV64I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a0)
+; RV64I-INTEGRATED-NEXT:    #NO_APP
+; RV64I-INTEGRATED-NEXT:    ret
+;
+; RV32I-MEDIUM-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV32I-MEDIUM-INTEGRATED:       # %bb.0:
+; RV32I-MEDIUM-INTEGRATED-NEXT:  .Lpcrel_hi9:
+; RV32I-MEDIUM-INTEGRATED-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    #APP
+; RV32I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    #NO_APP
+; RV32I-MEDIUM-INTEGRATED-NEXT:    ret
+;
+; RV64I-MEDIUM-INTEGRATED-LABEL: constraint_m_with_multi_operands:
+; RV64I-MEDIUM-INTEGRATED:       # %bb.0:
+; RV64I-MEDIUM-INTEGRATED-NEXT:  .Lpcrel_hi9:
+; RV64I-MEDIUM-INTEGRATED-NEXT:    auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    #APP
+; RV64I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    #NO_APP
+; RV64I-MEDIUM-INTEGRATED-NEXT:    ret
   call void asm "sw zero, $0; sw zero, $1", "=*m,=*m"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg)
   ret void
 }
@@ -584,67 +630,137 @@ define void @constraint_m_with_multi_asm() nounwind {
 }
 
 define i32 @constraint_m_with_callbr_multi_operands(i32 %a) {
-; RV32I-LABEL: constraint_m_with_callbr_multi_operands:
-; RV32I:       # %bb.0: # %entry
-; RV32I-NEXT:    lui a1, %hi(eg)
-; RV32I-NEXT:    #APP
-; RV32I-NEXT:    sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB14_2
-; RV32I-NEXT:    #NO_APP
-; RV32I-NEXT:  # %bb.1: # %normal
-; RV32I-NEXT:    li a0, 0
-; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB14_2: # Block address taken
-; RV32I-NEXT:    # %fail
-; RV32I-NEXT:    # Label of block must be emitted
-; RV32I-NEXT:    li a0, 1
-; RV32I-NEXT:    ret
-;
-; RV64I-LABEL: constraint_m_with_callbr_multi_operands:
-; RV64I:       # %bb.0: # %entry
-; RV64I-NEXT:    lui a1, %hi(eg)
-; RV64I-NEXT:    #APP
-; RV64I-NEXT:    sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB14_2
-; RV64I-NEXT:    #NO_APP
-; RV64I-NEXT:  # %bb.1: # %normal
-; RV64I-NEXT:    li a0, 0
-; RV64I-NEXT:    ret
-; RV64I-NEXT:  .LBB14_2: # Block address taken
-; RV64I-NEXT:    # %fail
-; RV64I-NEXT:    # Label of block must be emitted
-; RV64I-NEXT:    li a0, 1
-; RV64I-NEXT:    ret
-;
-; RV32I-MEDIUM-LABEL: constraint_m_with_callbr_multi_operands:
-; RV32I-MEDIUM:       # %bb.0: # %entry
-; RV32I-MEDIUM-NEXT:  .Lpcrel_hi11:
-; RV32I-MEDIUM-NEXT:    auipc a1, %pcrel_hi(eg)
-; RV32I-MEDIUM-NEXT:    #APP
-; RV32I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
-; RV32I-MEDIUM-NEXT:    #NO_APP
-; RV32I-MEDIUM-NEXT:  # %bb.1: # %normal
-; RV32I-MEDIUM-NEXT:    li a0, 0
-; RV32I-MEDIUM-NEXT:    ret
-; RV32I-MEDIUM-NEXT:  .LBB14_2: # Block address taken
-; RV32I-MEDIUM-NEXT:    # %fail
-; RV32I-MEDIUM-NEXT:    # Label of block must be emitted
-; RV32I-MEDIUM-NEXT:    li a0, 1
-; RV32I-MEDIUM-NEXT:    ret
-;
-; RV64I-MEDIUM-LABEL: constraint_m_with_callbr_multi_operands:
-; RV64I-MEDIUM:       # %bb.0: # %entry
-; RV64I-MEDIUM-NEXT:  .Lpcrel_hi11:
-; RV64I-MEDIUM-NEXT:    auipc a1, %pcrel_hi(eg)
-; RV64I-MEDIUM-NEXT:    #APP
-; RV64I-MEDIUM-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
-; RV64I-MEDIUM-NEXT:    #NO_APP
-; RV64I-MEDIUM-NEXT:  # %bb.1: # %normal
-; RV64I-MEDIUM-NEXT:    li a0, 0
-; RV64I-MEDIUM-NEXT:    ret
-; RV64I-MEDIUM-NEXT:  .LBB14_2: # Block address taken
-; RV64I-MEDIUM-NEXT:    # %fail
-; RV64I-MEDIUM-NEXT:    # Label of block must be emitted
-; RV64I-MEDIUM-NEXT:    li a0, 1
-; RV64I-MEDIUM-NEXT:    ret
+; RV32I-NO-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV32I-NO-INTEGRATED:       # %bb.0: # %entry
+; RV32I-NO-INTEGRATED-NEXT:    lui a1, %hi(eg)
+; RV32I-NO-INTEGRATED-NEXT:    #APP
+; RV32I-NO-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB14_2
+; RV32I-NO-INTEGRATED-NEXT:    #NO_APP
+; RV32I-NO-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV32I-NO-INTEGRATED-NEXT:    li a0, 0
+; RV32I-NO-INTEGRATED-NEXT:    ret
+; RV32I-NO-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV32I-NO-INTEGRATED-NEXT:    # %fail
+; RV32I-NO-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV32I-NO-INTEGRATED-NEXT:    li a0, 1
+; RV32I-NO-INTEGRATED-NEXT:    ret
+;
+; RV64I-NO-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV64I-NO-INTEGRATED:       # %bb.0: # %entry
+; RV64I-NO-INTEGRATED-NEXT:    lui a1, %hi(eg)
+; RV64I-NO-INTEGRATED-NEXT:    #APP
+; RV64I-NO-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB14_2
+; RV64I-NO-INTEGRATED-NEXT:    #NO_APP
+; RV64I-NO-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV64I-NO-INTEGRATED-NEXT:    li a0, 0
+; RV64I-NO-INTEGRATED-NEXT:    ret
+; RV64I-NO-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV64I-NO-INTEGRATED-NEXT:    # %fail
+; RV64I-NO-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV64I-NO-INTEGRATED-NEXT:    li a0, 1
+; RV64I-NO-INTEGRATED-NEXT:    ret
+;
+; RV32I-MEDIUM-NO-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV32I-MEDIUM-NO-INTEGRATED:       # %bb.0: # %entry
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:  .Lpcrel_hi11:
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    #APP
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    #NO_APP
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    li a0, 0
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    # %fail
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    li a0, 1
+; RV32I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+;
+; RV64I-MEDIUM-NO-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV64I-MEDIUM-NO-INTEGRATED:       # %bb.0: # %entry
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:  .Lpcrel_hi11:
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    #APP
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    #NO_APP
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    li a0, 0
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    # %fail
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    li a0, 1
+; RV64I-MEDIUM-NO-INTEGRATED-NEXT:    ret
+;
+; RV32I-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV32I-INTEGRATED:       # %bb.0: # %entry
+; RV32I-INTEGRATED-NEXT:    lui a1, %hi(eg)
+; RV32I-INTEGRATED-NEXT:    #APP
+; RV32I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1)
+; RV32I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1)
+; RV32I-INTEGRATED-NEXT:    beqz a0, .LBB14_2
+; RV32I-INTEGRATED-NEXT:    #NO_APP
+; RV32I-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV32I-INTEGRATED-NEXT:    li a0, 0
+; RV32I-INTEGRATED-NEXT:    ret
+; RV32I-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV32I-INTEGRATED-NEXT:    # %fail
+; RV32I-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV32I-INTEGRATED-NEXT:    li a0, 1
+; RV32I-INTEGRATED-NEXT:    ret
+;
+; RV64I-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV64I-INTEGRATED:       # %bb.0: # %entry
+; RV64I-INTEGRATED-NEXT:    lui a1, %hi(eg)
+; RV64I-INTEGRATED-NEXT:    #APP
+; RV64I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1)
+; RV64I-INTEGRATED-NEXT:    sw zero, %lo(eg)(a1)
+; RV64I-INTEGRATED-NEXT:    beqz a0, .LBB14_2
+; RV64I-INTEGRATED-NEXT:    #NO_APP
+; RV64I-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV64I-INTEGRATED-NEXT:    li a0, 0
+; RV64I-INTEGRATED-NEXT:    ret
+; RV64I-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV64I-INTEGRATED-NEXT:    # %fail
+; RV64I-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV64I-INTEGRATED-NEXT:    li a0, 1
+; RV64I-INTEGRATED-NEXT:    ret
+;
+; RV32I-MEDIUM-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV32I-MEDIUM-INTEGRATED:       # %bb.0: # %entry
+; RV32I-MEDIUM-INTEGRATED-NEXT:  .Lpcrel_hi11:
+; RV32I-MEDIUM-INTEGRATED-NEXT:    auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    #APP
+; RV32I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1)
+; RV32I-MEDIUM-INTEGRATED-NEXT:    beqz a0, .LBB14_2
+; RV32I-MEDIUM-INTEGRATED-NEXT:    #NO_APP
+; RV32I-MEDIUM-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV32I-MEDIUM-INTEGRATED-NEXT:    li a0, 0
+; RV32I-MEDIUM-INTEGRATED-NEXT:    ret
+; RV32I-MEDIUM-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV32I-MEDIUM-INTEGRATED-NEXT:    # %fail
+; RV32I-MEDIUM-INTEGRATED-NEXT:    # Label of block must be emitted
+; RV32I-MEDIUM-INTEGRATED-NEXT:    li a0, 1
+; RV32I-MEDIUM-INTEGRATED-NEXT:    ret
+;
+; RV64I-MEDIUM-INTEGRATED-LABEL: constraint_m_with_callbr_multi_operands:
+; RV64I-MEDIUM-INTEGRATED:       # %bb.0: # %entry
+; RV64I-MEDIUM-INTEGRATED-NEXT:  .Lpcrel_hi11:
+; RV64I-MEDIUM-INTEGRATED-NEXT:    auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    #APP
+; RV64I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    sw zero, %pcrel_lo(.Lpcrel_hi11)(a1)
+; RV64I-MEDIUM-INTEGRATED-NEXT:    beqz a0, .LBB14_2
+; RV64I-MEDIUM-INTEGRATED-NEXT:    #NO_APP
+; RV64I-MEDIUM-INTEGRATED-NEXT:  # %bb.1: # %normal
+; RV64I-MEDIUM-INTEGRATED-NEXT:    li a0, 0
+; RV64I-MEDIUM-INTEGRATED-NEXT:    ret
+; RV64I-MEDIUM-INTEGRATED-NEXT:  .LBB14_2: # Block address taken
+; RV64I-MEDIUM-INTEGRATED-NEXT:    # %fail
+; RV64I-MEDIUM-INTEGRATED-NEXT:    # Label of...
[truncated]

@@ -0,0 +1,95 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; integrated-as fails with error: unexpected token
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this comment below the RUN lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

; RUN: | FileCheck -check-prefixes=RV64I-MEDIUM %s
;
; integrated-as fails with error: unexpected token
; sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use \0A instead of \n?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was in the test before my chagne. I just split inline-asm-mem-contriant.ll into two tests: the one that fails with intergrated-as and the second one that works correctly.

I mean I can change it, not a problem. But originally it was added with '\n'.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok we can leave them split then.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@wangpc-pp wangpc-pp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!
(Actually, this is a problem I have already found when I was implementing it, but I didn't put it in mind).

Commit 5cd8d53 taught RISCVMergeBaseOffset to handle inline asm, however
there is at least one case uncovered for integrated as.

In the example below compiler generates pcrel relocation (mcmodel=medany)
    volatile double double_val = 1.0;
    void foo() {
        asm volatile("fld f0, %0 \n\t" : : "m"(double_val) : "memory");
    }

And fails with the folliwng error
    error: could not find corresponding %pcrel_hi
          |       "fld f0, %0 \n\t"
    <inline asm>:1:2: note: instantiated into assembly here
          |         fld f0, %pcrel_lo(.Lpcrel_hi0)(a0)

After transformations MachineFunction contains inline asm instructions with
'.Lpcrel_hi0' symbol that is not defined in inline asm, but referenced.
   ... = AUIPC ...(riscv-pcrel-hi) @double_val, pre-instr-symbol <mcsymbol .Lpcrel_hi0>
   INLINEASM &"fld f0, $0 \0A\09" ... target-flags(riscv-pcrel-lo) <mcsymbol .Lpcrel_hi0>

So, when AsmParser processes 'fld', it has to create a new symbol as
'.Lpcrel_hi0' already exists but not known to be referenced in inline asm.
AsmParser avoids conflicts by renaming referenced by 'fld' symbol with
'.Lpcrel_hi00' name which does not exist. Resulting erroneous asm
    .Lpcrel_hi0:
        auipc   a0, %pcrel_hi(double_val)
        #APP
        fld     ft0, %pcrel_lo(.Lpcrel_hi00)(a0)

This change adds symbols used in memory operands to the list of referenced ones.
@asi-sc
Copy link
Contributor Author

asi-sc commented Aug 26, 2024

Rebased on top of precommitted test.

@asi-sc asi-sc merged commit 2f91e98 into llvm:main Aug 26, 2024
8 checks passed
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Sep 30, 2024
…d5842fd7a

Local branch amd-gfx 58ed584 Merged main:4549a8d251cfa91cc6230139595f0b7efdf199d9 into amd-gfx:757aa7b5f1a5
Remote branch main 2f91e98 [RISCV] Mark symbols used in inline asm for relocations as referenced (llvm#104925)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants