-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Support .option {no}exact #122483
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
Conversation
This is the implementation of a new assembler-only option to allow the automatic compression of RISC-V instructions to be switched off without changing the currently enabled architectural features. This allows users better control over the autocompression feature of the assembler, so they can get the exact instructions they want. This will become more useful as the following things happen: - `.option norvc` is deprecated/removed (which is sometimes used for this purpose). - Extensions are added where the destination instruction cannot be disabled separately to the source instruction, either because the destination is in the base architecture, or because it is in the same extension as the source. - Extensions wider than 32-bits are added, which make CompressPats more complex to use intuitively, especially if the destination is a 32-bit instruction.
The assembly manual proposal is here: riscv-non-isa/riscv-asm-manual#122 |
Thanks for doing this. Kito and I have talked about something similar in the past. .option rvc has been broken since Zca/Zcf/Zcd was introduced. |
Yeah. Just like EF_RVC conflates two things (C extension being present and IALIGN=16), |
✅ With the latest revision this PR passed the C/C++ code formatter. |
@llvm/pr-subscribers-mc Author: Sam Elliott (lenary) ChangesThis implements the
Full diff: https://github.com/llvm/llvm-project/pull/122483.diff 10 Files Affected:
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index ce25380cbdda2..8dd428a1ba461 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -3173,6 +3173,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;
@@ -3229,9 +3249,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;
}
@@ -3441,10 +3462,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,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index e752b0ec5f58c..83e6f7169e957 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -344,6 +344,10 @@ std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,
// Given a compressed control flow instruction this function returns
// the expanded instruction.
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
+ // Disable relaxation if FeatureExactAssembly
+ if (STI.hasFeature(RISCV::FeatureExactAssembly))
+ return Op;
+
switch (Op) {
default:
return Op;
@@ -371,6 +375,12 @@ unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
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();
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index 9eabc61331832..1814ca2a077f3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -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() {}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
index e1765805b4a26..bf84f8e700e6d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
@@ -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;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index ce64c61034901..04a0feb98eec2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -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(
@@ -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";
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
index cb8bc21cb6355..a23ac19c0cabb 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
@@ -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);
@@ -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;
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 12519c86bf44b..225b9fb88cdaf 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -254,7 +254,9 @@ void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
const MCSubtargetInfo &SubtargetInfo) {
MCInst CInst;
- bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
+ bool Res = false;
+ if (!SubtargetInfo.hasFeature(RISCV::FeatureExactAssembly))
+ Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
if (Res)
++RISCVNumInstrsCompressed;
S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index f23a855e7049f..57029b971193a 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1470,6 +1470,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#"]",
diff --git a/llvm/test/MC/RISCV/option-exact-compression.s b/llvm/test/MC/RISCV/option-exact-compression.s
new file mode 100644
index 0000000000000..ae38bf6647d17
--- /dev/null
+++ b/llvm/test/MC/RISCV/option-exact-compression.s
@@ -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 - \
+# 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)
diff --git a/llvm/test/MC/RISCV/option-exact-relaxation.s b/llvm/test/MC/RISCV/option-exact-relaxation.s
new file mode 100644
index 0000000000000..ed0a18290c67d
--- /dev/null
+++ b/llvm/test/MC/RISCV/option-exact-relaxation.s
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -triple riscv32 -show-encoding -mattr=+relax %s \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
+# RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+relax %s \
+# RUN: | llvm-objdump --triple=riscv32 --no-show-raw-insn -dr - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s
+
+# RUN: llvm-mc -triple riscv64 -show-encoding -mattr=+relax %s \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
+# RUN: llvm-mc -triple riscv64 -filetype=obj -mattr=+relax %s \
+# RUN: | llvm-objdump --triple=riscv64 --no-show-raw-insn -dr - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %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 branch and linker relaxation part of this behaviour.
+
+
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: bne a0, a1, 0x10
+# CHECK-OBJDUMP-NEXT: j 0xc
+# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
+beq a0, a1, undefined
+
+# CHECK-ASM: .option exact
+.option exact
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NOT: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NOT: R_RISCV_RELAX
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: beq a0, a1, 0x18
+# CHECK-OBJDUMP-NEXT: R_RISCV_BRANCH undefined
+beq a0, a1, undefined
+
+# CHECK-ASM: .option noexact
+.option noexact
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: bne a0, a1, 0x2c
+# CHECK-OBJDUMP-NEXT: j 0x28
+# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
+beq a0, a1, undefined
|
@llvm/pr-subscribers-backend-risc-v Author: Sam Elliott (lenary) ChangesThis implements the
Full diff: https://github.com/llvm/llvm-project/pull/122483.diff 10 Files Affected:
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index ce25380cbdda2..8dd428a1ba461 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -3173,6 +3173,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;
@@ -3229,9 +3249,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;
}
@@ -3441,10 +3462,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,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index e752b0ec5f58c..83e6f7169e957 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -344,6 +344,10 @@ std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,
// Given a compressed control flow instruction this function returns
// the expanded instruction.
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
+ // Disable relaxation if FeatureExactAssembly
+ if (STI.hasFeature(RISCV::FeatureExactAssembly))
+ return Op;
+
switch (Op) {
default:
return Op;
@@ -371,6 +375,12 @@ unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
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();
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index 9eabc61331832..1814ca2a077f3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -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() {}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
index e1765805b4a26..bf84f8e700e6d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
@@ -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;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index ce64c61034901..04a0feb98eec2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -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(
@@ -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";
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
index cb8bc21cb6355..a23ac19c0cabb 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h
@@ -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);
@@ -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;
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 12519c86bf44b..225b9fb88cdaf 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -254,7 +254,9 @@ void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
const MCSubtargetInfo &SubtargetInfo) {
MCInst CInst;
- bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
+ bool Res = false;
+ if (!SubtargetInfo.hasFeature(RISCV::FeatureExactAssembly))
+ Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
if (Res)
++RISCVNumInstrsCompressed;
S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index f23a855e7049f..57029b971193a 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1470,6 +1470,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#"]",
diff --git a/llvm/test/MC/RISCV/option-exact-compression.s b/llvm/test/MC/RISCV/option-exact-compression.s
new file mode 100644
index 0000000000000..ae38bf6647d17
--- /dev/null
+++ b/llvm/test/MC/RISCV/option-exact-compression.s
@@ -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 - \
+# 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)
diff --git a/llvm/test/MC/RISCV/option-exact-relaxation.s b/llvm/test/MC/RISCV/option-exact-relaxation.s
new file mode 100644
index 0000000000000..ed0a18290c67d
--- /dev/null
+++ b/llvm/test/MC/RISCV/option-exact-relaxation.s
@@ -0,0 +1,74 @@
+# RUN: llvm-mc -triple riscv32 -show-encoding -mattr=+relax %s \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
+# RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+relax %s \
+# RUN: | llvm-objdump --triple=riscv32 --no-show-raw-insn -dr - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s
+
+# RUN: llvm-mc -triple riscv64 -show-encoding -mattr=+relax %s \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
+# RUN: llvm-mc -triple riscv64 -filetype=obj -mattr=+relax %s \
+# RUN: | llvm-objdump --triple=riscv64 --no-show-raw-insn -dr - \
+# RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %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 branch and linker relaxation part of this behaviour.
+
+
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: bne a0, a1, 0x10
+# CHECK-OBJDUMP-NEXT: j 0xc
+# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
+beq a0, a1, undefined
+
+# CHECK-ASM: .option exact
+.option exact
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NOT: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NOT: R_RISCV_RELAX
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: beq a0, a1, 0x18
+# CHECK-OBJDUMP-NEXT: R_RISCV_BRANCH undefined
+beq a0, a1, undefined
+
+# CHECK-ASM: .option noexact
+.option noexact
+
+# CHECK-ASM: call undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_call_plt
+# CHECK-ASM-NEXT: fixup B - offset: 0, value: 0, kind: fixup_riscv_relax
+# CHECK-OBJDUMP: auipc ra, 0x0
+# CHECK-OBJDUMP-NEXT: R_RISCV_CALL_PLT undefined
+# CHECK-OBJDUMP-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-OBJDUMP-NEXT: jalr ra
+call undefined@plt
+
+# CHECK-ASM: beq a0, a1, undefined
+# CHECK-ASM-NEXT: fixup A - offset: 0, value: undefined, kind: fixup_riscv_branch
+# CHECK-OBJDUMP: bne a0, a1, 0x2c
+# CHECK-OBJDUMP-NEXT: j 0x28
+# CHECK-OBJDUMP-NEXT: R_RISCV_JAL undefined
+beq a0, a1, undefined
|
@@ -254,7 +254,9 @@ void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, | |||
bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst, | |||
const MCSubtargetInfo &SubtargetInfo) { | |||
MCInst CInst; | |||
bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo); | |||
bool Res = false; | |||
if (!SubtargetInfo.hasFeature(RISCV::FeatureExactAssembly)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I think this would need a LLC test - let me work out what to do here - I'm not sure which EmitToStreamer is used for inline assembly.
I think I only want to keep this if inline assembly hits it, otherwise I don't want to present this as something for compilation - exact mode is trying to just be for assembly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inline assembly does not use this emit function, so I have removed this change.
@@ -344,6 +344,10 @@ std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm, | |||
// Given a compressed control flow instruction this function returns | |||
// the expanded instruction. | |||
unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const { | |||
// Disable relaxation if FeatureExactAssembly | |||
if (STI.hasFeature(RISCV::FeatureExactAssembly)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a different STI than what mayNeedRelaxation
is using right?
Should we check in relaxInstruction
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is indeed a different STI to mayNeedRelaxation
.
I wasn't sure about changing relaxInstruction
, because of the llvm_unreachable
which suggested to me it would never be called if mayNeedRelaxation
returned false, and I also wasn't sure what would happen if we never updated Inst
. I can certainly try that approach, I agree the current check is not actually very good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure getRelaxedOpcode should be a member. It only has 2 callers, it's not virtual, and it doesn't use any members variables. It could be a file local static function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I will do that refactoring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Warning(Parser.getTok().getLoc(), | ||
"unknown option, expected 'push', 'pop', " | ||
"'rvc', 'norvc', 'arch', 'relax', 'norelax', " | ||
"'exact' or 'noexact'"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you're here. oxford comma
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Learnt, the community is a good place to learn new English phrases. :-)
@@ -8,6 +8,7 @@ | |||
|
|||
#include "RISCVAsmBackend.h" | |||
#include "RISCVMCExpr.h" | |||
#include "RISCVMCTargetDesc.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think this is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
.option noexact", "=^cr,^cr"(ptr %f) | ||
ret i32 %0 | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Two new lines at the end of the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -0,0 +1,20 @@ | |||
; RUN: llc -mtriple=riscv32 -mattr=+relax,+c %s --filetype=obj -o - \ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 --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 - \ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Combined.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122>. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively). cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122>. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively). cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively). cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively). cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) without single instruction encoding are not fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) are not guaranteed to be fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). The main purpose of this mode is to emit desired machine code as the user writes, assuming the user knows constraints of their code. So, macros like "li" (known to be expanded into possibly complex sequences) are not guaranteed to be fully aware of this mode. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). Macros like "li" (known to be expanded into possibly complex sequences) may still expand to complex instruction sequences but at least each instruction emitted by macros is still subject to the behavior above. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/li32.s: Enable exact mode by external option. * testsuite/gas/riscv/li64.s: Likewise. * testsuite/gas/riscv/exact-li32.d: li32.d but enable exact mode to make sure that no automatic instruction compression occurs. * testsuite/gas/riscv/exact-li64.d: Likewise. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). Macros like "li" (known to be expanded into possibly complex sequences) may still expand to complex instruction sequences but at least each instruction emitted by macros is still subject to the behavior above. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/li32.s: Enable exact mode by external option. * testsuite/gas/riscv/li64.s: Likewise. * testsuite/gas/riscv/exact-li32.d: li32.d but enable exact mode to make sure that no automatic instruction compression occurs. * testsuite/gas/riscv/exact-li64.d: Likewise. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). Macros like "li" (known to be expanded into possibly complex sequences) may still expand to complex instruction sequences but at least each instruction emitted by macros is still subject to the behavior above. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/li32.s: Enable exact mode by external option. * testsuite/gas/riscv/li64.s: Likewise. * testsuite/gas/riscv/exact-li32.d: li32.d but enable exact mode to make sure that no automatic instruction compression occurs. * testsuite/gas/riscv/exact-li64.d: Likewise. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This commit adds two assembler directives: ".option exact" and ".option noexact" (enable/disable the exact mode) as discussed in <riscv-non-isa/riscv-asm-manual#122> and already implemented in LLVM. When the exact mode is enabled, 1. Linker relaxations are turned off, 2. Instruction aliases that will change the encoding from the (likely non-alias) instruction with the same name are disabled (e.g. "addi" will never turn into "c.addi" even if optimizable) and 3. Assembler relaxation of branch instructions are disabled (e.g. "blt" with a long offset will not turn into "bge + j"). Macros like "li" (known to be expanded into possibly complex sequences) may still expand to complex instruction sequences but at least each instruction emitted by macros is still subject to the behavior above. Currently, interactions between ".option relax/norelax" and ".option exact/noexact" are designed to be LLVM-compatible (i.e. ".option exact/noexact" imply ".option norelax/relax", respectively) but considered flaky and strongly discouraged from using both. cf. <llvm/llvm-project#122483> gas/ChangeLog: * config/tc-riscv.c (struct riscv_set_options): Add exact option. (RELAX_BRANCH_ENCODE): Encode exact option. (RELAX_BRANCH_EXACT): New predicate macro. (relaxed_branch_length): Handle exact mode cases. (append_insn): Pass exact option to RELAX_BRANCH_ENCODE. (riscv_ip): Skip instructions that would change the encoding when the exact mode is enabled. (s_riscv_option): Parse ".option exact" and ".option noexact" assembler directives. * doc/c-riscv.texi: Document new assembler directives. * testsuite/gas/riscv/exact.s: Test exact mode basics. * testsuite/gas/riscv/exact.d: Ditto. * testsuite/gas/riscv/exact-branch-local.s: Test conditional branches and unconditional jumps relative to a local symbol. * testsuite/gas/riscv/exact-branch-local-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-ok.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.d: Ditto. * testsuite/gas/riscv/exact-branch-local-exact-fail.l: Ditto. * testsuite/gas/riscv/exact-branch-extern.s: Test conditional branches and unconditional jumps relative to an external symbol. * testsuite/gas/riscv/exact-branch-extern-noexact.d: Ditto. * testsuite/gas/riscv/exact-branch-extern-exact.d: Ditto. * testsuite/gas/riscv/li32.s: Enable exact mode by external option. * testsuite/gas/riscv/li64.s: Likewise. * testsuite/gas/riscv/exact-li32.d: li32.d but enable exact mode to make sure that no automatic instruction compression occurs. * testsuite/gas/riscv/exact-li64.d: Likewise. * testsuite/gas/riscv/no-relax-branch-offset-fail.s: Use exact mode to test various configurations and instructions. * testsuite/gas/riscv/no-relax-branch-offset-fail.d: Ditto. * testsuite/gas/riscv/no-relax-branch-offset-fail.l: Ditto. include/ChangeLog: * opcode/riscv.h (INSN_NON_EXACT): New flag to represent aliases to reject on the exact mode. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add INSN_NON_EXACT flag to all instructions that should be rejected on the exact mode.
This implements the
.option exact
and.option noexact
proposal for RISC-V..option exact
turns off:.option noexact
turns these back on, and is also the default, matching the current behaviour.