diff --git a/lld/test/ELF/riscv-relax-align-rvc.s b/lld/test/ELF/riscv-relax-align-rvc.s --- a/lld/test/ELF/riscv-relax-align-rvc.s +++ b/lld/test/ELF/riscv-relax-align-rvc.s @@ -25,10 +25,10 @@ # CHECK-NEXT: c.addi a0, 1 # CHECK-EMPTY: # CHECK-NEXT: : +# CHECK-NEXT: c.nop # CHECK-NEXT: addi zero, zero, 0 # CHECK-NEXT: addi zero, zero, 0 # CHECK-NEXT: addi zero, zero, 0 -# CHECK-NEXT: c.nop # CHECK-EMPTY: # CHECK-NEXT: : # CHECK-NEXT: 10010: c.addi a0, 2 diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -354,20 +354,28 @@ bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const { - bool HasStdExtC = STI->getFeatureBits()[RISCV::FeatureStdExtC]; - unsigned MinNopLen = HasStdExtC ? 2 : 4; + // We mostly follow binutils' convention here: align to even boundary with a + // 0-fill padding. We emit up to 1 2-byte nop, though we use c.nop if RVC is + // enabled or 0-fill otherwise. The remainder is now padded with 4-byte nops. + + // Instructions always are at even addresses. We must be in a data area or + // be unaligned due to some other reason. + if (Count % 2) { + OS.write("\0", 1); + Count -= 1; + } - if ((Count % MinNopLen) != 0) - return false; + // The canonical nop on RVC is c.nop. + if (Count % 4 == 2) { + OS.write(STI->getFeatureBits()[RISCV::FeatureStdExtC] ? "\x01\0" : "\0\0", + 2); + Count -= 2; + } // The canonical nop on RISC-V is addi x0, x0, 0. for (; Count >= 4; Count -= 4) OS.write("\x13\0\0\0", 4); - // The canonical nop on RVC is c.nop. - if (Count && HasStdExtC) - OS.write("\x01\0", 2); - return true; } diff --git a/llvm/test/MC/RISCV/align.s b/llvm/test/MC/RISCV/align.s --- a/llvm/test/MC/RISCV/align.s +++ b/llvm/test/MC/RISCV/align.s @@ -48,8 +48,8 @@ # RELAX-RELOC: R_RISCV_ALIGN - 0x4 # RELAX-INST: addi zero, zero, 0 # C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6 -# C-EXT-RELAX-INST: addi zero, zero, 0 # C-EXT-RELAX-INST: c.nop +# C-EXT-RELAX-INST: addi zero, zero, 0 # C-EXT-NORELAX-INST: addi zero, zero, 0 add a0, a0, a1 .align 4 @@ -75,7 +75,7 @@ # NORELAX-INST: addi zero, zero, 0 # C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6 # C-EXT-RELAX-INST: addi zero, zero, 0 -# C-EXT-RELAX-INST: c.nop +# C-EXT-RELAX-INST-NOT: c.nop # C-EXT-INST: addi zero, zero, 0 # C-EXT-INST: c.nop add a0, a0, a1 diff --git a/llvm/test/MC/RISCV/nop-slide.s b/llvm/test/MC/RISCV/nop-slide.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/nop-slide.s @@ -0,0 +1,27 @@ +# RUN: llvm-mc -triple riscv64 -mattr +c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC-NORELAX +# RUN: llvm-mc -triple riscv64 -mattr +c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s -check-prefix CHECK-RVC-RELAX +# RUN: llvm-mc -triple riscv64 -mattr -c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s +# RUN: llvm-mc -triple riscv64 -mattr -c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s + +.balign 4 +.byte 0 + +.balign 4 +auipc a0, 0 + +# CHECK-RVC-NORELAX: 0000000000000000 <.text>: +# CHECK-RVC-NORELAX-NEXT: 0: 00 00 unimp +# CHECK-RVC-NORELAX-NEXT: 2: 01 00 nop +# CHECK-RVC-NORELAX-NEXT: 4: 17 05 00 00 auipc a0, 0 + +# CHECK-RVC-RELAX: 0000000000000000 <.text>: +# CHECK-RVC-RELAX-NEXT: 0: 01 00 nop +# CHECK-RVC-RELAX-NEXT: 2: 00 01 addi s0, sp, 128 +# CHECK-RVC-RELAX-NEXT: 4: 00 17 addi s0, sp, 928 +# CHECK-RVC-RELAX-NEXT: 6: 05 00 c.nop 1 +# CHECK-RVC-RELAX-NEXT: 8: 00 + +# CHECK: 0000000000000000 <.text>: +# CHECK-NEXT: 0: 00 00 +# CHECK-NEXT: 2: 00 00 +# CHECK-NEXT: 4: 17 05 00 00 auipc a0, 0