Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ Changes to the RISC-V Backend
handlers.
* When the experimental extension `Xqcili` is enabled, `qc.e.li` and `qc.li` may
now be used to materialize immediates.
* Adds assembler support for ``.option exact``, which disables automatic compression,
and branch and linker relaxation. This can be disabled with ``.option noexact``,
which is also the default.

Changes to the WebAssembly Backend
----------------------------------
Expand Down
34 changes: 29 additions & 5 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3205,6 +3205,26 @@ bool RISCVAsmParser::parseDirectiveOption() {
return false;
}

if (Option == "exact") {
if (Parser.parseEOL())
return true;

getTargetStreamer().emitDirectiveOptionExact();
setFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
clearFeatureBits(RISCV::FeatureRelax, "relax");
return false;
}

if (Option == "noexact") {
if (Parser.parseEOL())
return true;

getTargetStreamer().emitDirectiveOptionNoExact();
clearFeatureBits(RISCV::FeatureExactAssembly, "exact-asm");
setFeatureBits(RISCV::FeatureRelax, "relax");
return false;
}

if (Option == "rvc") {
if (Parser.parseEOL())
return true;
Expand Down Expand Up @@ -3261,9 +3281,10 @@ bool RISCVAsmParser::parseDirectiveOption() {
}

// Unknown option.
Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
"'rvc', 'norvc', 'arch', 'relax' or "
"'norelax'");
Warning(Parser.getTok().getLoc(),
"unknown option, expected 'push', 'pop', "
"'rvc', 'norvc', 'arch', 'relax', 'norelax', "
"'exact', or 'noexact'");
Parser.eatToEndOfStatement();
return false;
}
Expand Down Expand Up @@ -3473,10 +3494,13 @@ bool RISCVAsmParser::parseDirectiveVariantCC() {

void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
MCInst CInst;
bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
bool Res = false;
const MCSubtargetInfo &STI = getSTI();
if (!STI.hasFeature(RISCV::FeatureExactAssembly))
Res = RISCVRVC::compress(CInst, Inst, STI);
if (Res)
++RISCVNumInstrsCompressed;
S.emitInstruction((Res ? CInst : Inst), getSTI());
S.emitInstruction((Res ? CInst : Inst), STI);
}

void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
Expand Down
65 changes: 37 additions & 28 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,39 @@ bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(
}
}

// Given a compressed control flow instruction this function returns
// the expanded instruction.
static unsigned getRelaxedOpcode(unsigned Op) {
switch (Op) {
default:
return Op;
case RISCV::C_BEQZ:
return RISCV::BEQ;
case RISCV::C_BNEZ:
return RISCV::BNE;
case RISCV::C_J:
case RISCV::C_JAL: // fall through.
return RISCV::JAL;
case RISCV::BEQ:
return RISCV::PseudoLongBEQ;
case RISCV::BNE:
return RISCV::PseudoLongBNE;
case RISCV::BLT:
return RISCV::PseudoLongBLT;
case RISCV::BGE:
return RISCV::PseudoLongBGE;
case RISCV::BLTU:
return RISCV::PseudoLongBLTU;
case RISCV::BGEU:
return RISCV::PseudoLongBGEU;
}
}

void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
const MCSubtargetInfo &STI) const {
if (STI.hasFeature(RISCV::FeatureExactAssembly))
return;

MCInst Res;
switch (Inst.getOpcode()) {
default:
Expand Down Expand Up @@ -341,36 +372,14 @@ std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,
return std::make_pair(Expr.evaluateKnownAbsolute(Value, Asm), false);
}

// Given a compressed control flow instruction this function returns
// the expanded instruction.
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
switch (Op) {
default:
return Op;
case RISCV::C_BEQZ:
return RISCV::BEQ;
case RISCV::C_BNEZ:
return RISCV::BNE;
case RISCV::C_J:
case RISCV::C_JAL: // fall through.
return RISCV::JAL;
case RISCV::BEQ:
return RISCV::PseudoLongBEQ;
case RISCV::BNE:
return RISCV::PseudoLongBNE;
case RISCV::BLT:
return RISCV::PseudoLongBLT;
case RISCV::BGE:
return RISCV::PseudoLongBGE;
case RISCV::BLTU:
return RISCV::PseudoLongBLTU;
case RISCV::BGEU:
return RISCV::PseudoLongBGEU;
}
}

bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,
const MCSubtargetInfo &STI) const {
// This function has access to two STIs, the member of the AsmBackend, and the
// one passed as an argument. The latter is more specific, so we query it for
// specific features.
if (STI.hasFeature(RISCV::FeatureExactAssembly))
return false;

return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();
}

Expand Down
1 change: 0 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ class RISCVAsmBackend : public MCAsmBackend {

bool mayNeedRelaxation(const MCInst &Inst,
const MCSubtargetInfo &STI) const override;
unsigned getRelaxedOpcode(unsigned Op) const;

void relaxInstruction(MCInst &Inst,
const MCSubtargetInfo &STI) const override;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {}
void RISCVTargetELFStreamer::emitDirectiveOptionNoPIC() {}
void RISCVTargetELFStreamer::emitDirectiveOptionRVC() {}
void RISCVTargetELFStreamer::emitDirectiveOptionNoRVC() {}
void RISCVTargetELFStreamer::emitDirectiveOptionExact() {}
void RISCVTargetELFStreamer::emitDirectiveOptionNoExact() {}
void RISCVTargetELFStreamer::emitDirectiveOptionRelax() {}
void RISCVTargetELFStreamer::emitDirectiveOptionNoRelax() {}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class RISCVTargetELFStreamer : public RISCVTargetStreamer {
void emitDirectiveOptionNoPIC() override;
void emitDirectiveOptionRVC() override;
void emitDirectiveOptionNoRVC() override;
void emitDirectiveOptionExact() override;
void emitDirectiveOptionNoExact() override;
void emitDirectiveOptionRelax() override;
void emitDirectiveOptionNoRelax() override;
void emitDirectiveVariantCC(MCSymbol &Symbol) override;
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ void RISCVTargetStreamer::emitDirectiveOptionPIC() {}
void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {}
void RISCVTargetStreamer::emitDirectiveOptionRVC() {}
void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
void RISCVTargetStreamer::emitDirectiveOptionExact() {}
void RISCVTargetStreamer::emitDirectiveOptionNoExact() {}
void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
void RISCVTargetStreamer::emitDirectiveOptionArch(
Expand Down Expand Up @@ -125,6 +127,14 @@ void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
OS << "\t.option\tnorvc\n";
}

void RISCVTargetAsmStreamer::emitDirectiveOptionExact() {
OS << "\t.option\texact\n";
}

void RISCVTargetAsmStreamer::emitDirectiveOptionNoExact() {
OS << "\t.option\tnoexact\n";
}

void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() {
OS << "\t.option\trelax\n";
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class RISCVTargetStreamer : public MCTargetStreamer {
virtual void emitDirectiveOptionNoPIC();
virtual void emitDirectiveOptionRVC();
virtual void emitDirectiveOptionNoRVC();
virtual void emitDirectiveOptionExact();
virtual void emitDirectiveOptionNoExact();
virtual void emitDirectiveOptionRelax();
virtual void emitDirectiveOptionNoRelax();
virtual void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args);
Expand Down Expand Up @@ -84,6 +86,8 @@ class RISCVTargetAsmStreamer : public RISCVTargetStreamer {
void emitDirectiveOptionNoPIC() override;
void emitDirectiveOptionRVC() override;
void emitDirectiveOptionNoRVC() override;
void emitDirectiveOptionExact() override;
void emitDirectiveOptionNoExact() override;
void emitDirectiveOptionRelax() override;
void emitDirectiveOptionNoRelax() override;
void emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args) override;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,10 @@ def FeatureRelax
: SubtargetFeature<"relax", "EnableLinkerRelax", "true",
"Enable Linker relaxation.">;

def FeatureExactAssembly
: SubtargetFeature<"exact-asm", "EnableExactAssembly", "true",
"Enable Exact Assembly (Disables Compression and Relaxation)">;

foreach i = {1-31} in
def FeatureReserveX#i :
SubtargetFeature<"reserve-x"#i, "UserReservedRegister[RISCV::X"#i#"]",
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/RISCV/features-info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
; CHECK-NEXT: disable-latency-sched-heuristic - Disable latency scheduling heuristic.
; CHECK-NEXT: dlen-factor-2 - Vector unit DLEN(data path width) is half of VLEN.
; CHECK-NEXT: e - 'E' (Embedded Instruction Set with 16 GPRs).
; CHECK-NEXT: exact-asm - Enable Exact Assembly (Disables Compression and Relaxation).
; CHECK-NEXT: experimental - Experimental intrinsics.
; CHECK-NEXT: experimental-p - 'P' ('Base P' (Packed SIMD)).
; CHECK-NEXT: experimental-rvm23u32 - RISC-V experimental-rvm23u32 profile.
Expand Down
72 changes: 72 additions & 0 deletions llvm/test/MC/RISCV/option-exact-compression.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# RUN: llvm-mc -triple riscv32 -show-encoding -mattr=+c %s \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-ALIAS %s
# RUN: llvm-mc -triple riscv32 -show-encoding -mattr=+c \
# RUN: -M no-aliases %s | FileCheck -check-prefixes=CHECK,CHECK-INST %s
# RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+c %s \
# RUN: | llvm-objdump --triple=riscv32 --mattr=+c --no-print-imm-hex -d - \
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s
# RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+c %s \
# RUN: | llvm-objdump --triple=riscv32 --mattr=+c --no-print-imm-hex -d -M no-aliases - \
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need so many RUN lines? I think with no-aliases, we do not tests without -M no-aliases (the instruction aliases are the primary concerns of other tests, not this test)

Could this and optin-exact-relaxation.s be combined?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. Combined.

# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s

# RUN: llvm-mc -triple riscv64 -show-encoding -mattr=+c %s \
# RUN: | FileCheck -check-prefixes=CHECK-ALIAS %s
# RUN: llvm-mc -triple riscv64 -show-encoding -mattr=+c \
# RUN: -M no-aliases %s | FileCheck -check-prefixes=CHECK-INST %s
# RUN: llvm-mc -triple riscv64 -filetype=obj -mattr=+c %s \
# RUN: | llvm-objdump --triple=riscv64 --mattr=+c --no-print-imm-hex -d - \
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-ALIAS %s
# RUN: llvm-mc -triple riscv64 -filetype=obj -mattr=+c %s \
# RUN: | llvm-objdump --triple=riscv64 --mattr=+c --no-print-imm-hex -d -M no-aliases - \
# RUN: | FileCheck -check-prefixes=CHECK-BYTES,CHECK-INST %s


## `.option exact` disables a variety of assembler behaviour:
## - automatic compression
## - branch relaxation (of short branches to longer equivalent sequences)
## - linker relaxation (emitting R_RISCV_RELAX)
## `.option noexact` enables these behaviours again. It is also the default.

## This test only checks the automatic compression part of this behaviour.

# CHECK-BYTES: 4108
# CHECK-INST: c.lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x08,0x41]
lw a0, 0(a0)

# CHECK-BYTES: 4108
# CHECK-INST: c.lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x08,0x41]
c.lw a0, 0(a0)

# CHECK: .option exact
.option exact

# CHECK-BYTES: 00052503
# CHECK-INST: lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x03,0x25,0x05,0x00]
lw a0, 0(a0)

# CHECK-BYTES: 4108
# CHECK-INST: c.lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x08,0x41]
c.lw a0, 0(a0)

# CHECK: .option noexact
.option noexact

# CHECK-BYTES: 4108
# CHECK-INST: c.lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x08,0x41]
lw a0, 0(a0)

# CHECK-BYTES: 4108
# CHECK-INST: c.lw a0, 0(a0)
# CHECK-ALIAS: lw a0, 0(a0)
# CHECK: # encoding: [0x08,0x41]
c.lw a0, 0(a0)
20 changes: 20 additions & 0 deletions llvm/test/MC/RISCV/option-exact-inlineasm.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; RUN: llc -mtriple=riscv32 -mattr=+relax,+c %s --filetype=obj -o - \
Copy link
Member

Choose a reason for hiding this comment

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

Move to test/CodeGen/RISCV?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, yeah, this location was a little iffy, happier to have an llc test in the CodeGen directory, though this isn't the only one in the MC/RISCV directory

; RUN: | llvm-objdump --triple=riscv32 --mattr=+c -M no-aliases -dr - \
; RUN: | FileCheck %s

define i32 @foo(ptr noundef %f) nounwind {
; CHECK-LABEL: <foo>:
; CHECK: auipc ra, 0x0
; CHECK-NEXT: R_RISCV_CALL_PLT undefined
; CHECK-NEXT: jalr ra, 0x0(ra)
; CHECK-NEXT: lw a0, 0x0(a0)
; CHECK-NEXT: c.jr ra

entry:
%0 = tail call i32 asm sideeffect "
.option exact
call undefined@plt
lw $0, ($1)
.option noexact", "=^cr,^cr"(ptr %f)
ret i32 %0
}
Loading