[llvm] ca950a6 - [RISCV] Compress instructions based on function features

Simon Cook via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 28 04:02:19 PST 2020


Author: Simon Cook
Date: 2020-02-28T11:52:55Z
New Revision: ca950a6bb1972d142a8f6932f33f61386aabd949

URL: https://github.com/llvm/llvm-project/commit/ca950a6bb1972d142a8f6932f33f61386aabd949
DIFF: https://github.com/llvm/llvm-project/commit/ca950a6bb1972d142a8f6932f33f61386aabd949.diff

LOG: [RISCV] Compress instructions based on function features

When running under LTO, it is common to not specify the architecture
spec, which is used for setting up the target machine, and instead rely
on features specified in each function to generate the correct
instructions.

This works for the code generator, but the RISC-V backend uses the
AsmPrinter to do instruction compression, which does not see these
features but instead uses a MCSubtargetInfo object to see whether
compression is enabled. Since this is configured based on the
TargetMachine at startup, it will result in compressed instructions not
being emitted when it has not been given the 'c' TargetFeature, but the
function has it.

This changes the RISCVAsmPrinter to re-initialize the STI feature set
based on the current MachineFunction, such that compressed instructions
are now correctly emitted regardless of the method used to enable them.

Differential revision: https://reviews.llvm.org/D73339

Added: 
    llvm/test/CodeGen/RISCV/compress-float.ll

Modified: 
    llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
    llvm/test/CodeGen/RISCV/compress.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 893dc8ddab86..fc7e7c1efe1a 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -37,13 +37,17 @@ STATISTIC(RISCVNumInstrsCompressed,
 
 namespace {
 class RISCVAsmPrinter : public AsmPrinter {
+  const MCSubtargetInfo *STI;
+
 public:
   explicit RISCVAsmPrinter(TargetMachine &TM,
                            std::unique_ptr<MCStreamer> Streamer)
-      : AsmPrinter(TM, std::move(Streamer)) {}
+      : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {}
 
   StringRef getPassName() const override { return "RISCV Assembly Printer"; }
 
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
   void emitInstruction(const MachineInstr *MI) override;
 
   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -66,8 +70,7 @@ class RISCVAsmPrinter : public AsmPrinter {
 #include "RISCVGenCompressInstEmitter.inc"
 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
   MCInst CInst;
-  bool Res = compressInst(CInst, Inst, *TM.getMCSubtargetInfo(),
-                          OutStreamer->getContext());
+  bool Res = compressInst(CInst, Inst, *STI, OutStreamer->getContext());
   if (Res)
     ++RISCVNumInstrsCompressed;
   AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
@@ -154,6 +157,19 @@ bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
   return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
 }
 
+bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  // Set the current MCSubtargetInfo to a copy which has the correct
+  // feature bits for the current MachineFunction
+  MCSubtargetInfo &NewSTI =
+    OutStreamer->getContext().getSubtargetCopy(*TM.getMCSubtargetInfo());
+  NewSTI.setFeatureBits(MF.getSubtarget().getFeatureBits());
+  STI = &NewSTI;
+
+  SetupMachineFunction(MF);
+  emitFunctionBody();
+  return false;
+}
+
 // Force static initialization.
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
   RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());

diff  --git a/llvm/test/CodeGen/RISCV/compress-float.ll b/llvm/test/CodeGen/RISCV/compress-float.ll
new file mode 100644
index 000000000000..6c170b69b588
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/compress-float.ll
@@ -0,0 +1,48 @@
+; This test is designed to run three times, once with function attributes, once
+; with all target attributes added on the command line, and once with compress
+; added with the command line and float added via function attributes, all
+; three of these should result in the same output.
+;
+; RUN: cat %s > %t.tgtattr
+; RUN: echo 'attributes #0 = { nounwind }' >> %t.tgtattr
+; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c,+f,+d -filetype=obj \
+; RUN:   -disable-block-placement < %t.tgtattr \
+; RUN:   | llvm-objdump -d -triple=riscv32 -mattr=+c,+f,+d -M no-aliases - \
+; RUN:   | FileCheck -check-prefix=RV32IFDC %s
+;
+; RUN: cat %s > %t.fnattr
+; RUN: echo 'attributes #0 = { nounwind "target-features"="+c,+f,+d" }' >> %t.fnattr
+; RUN: llc -mtriple=riscv32 -target-abi ilp32d -filetype=obj \
+; RUN:   -disable-block-placement < %t.fnattr \
+; RUN:   | llvm-objdump -d -triple=riscv32 -mattr=+c,+f,+d -M no-aliases - \
+; RUN:   | FileCheck -check-prefix=RV32IFDC %s
+;
+; RUN: cat %s > %t.mixedattr
+; RUN: echo 'attributes #0 = { nounwind "target-features"="+f,+d" }' >> %t.mixedattr
+; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+c -filetype=obj \
+; RUN:   -disable-block-placement < %t.mixedattr \
+; RUN:   | llvm-objdump -d -triple=riscv32 -mattr=+c,+f,+d -M no-aliases - \
+; RUN:   | FileCheck -check-prefix=RV32IFDC %s
+
+; This acts as a sanity check for the codegen instruction compression path,
+; verifying that the assembled file contains compressed instructions when
+; expected. Handling of the compressed ISA is implemented so the same
+; transformation patterns should be used whether compressing an input .s file or
+; compressing codegen output. This file contains sanity checks using
+; instructions which also require one of the floating point extensions.
+
+define float @float_load(float *%a) #0 {
+; RV32IFDC-LABEL: float_load:
+; RV32IFDC:         c.flw fa0, 0(a0)
+; RV32IFDC-NEXT:    c.jr ra
+  %1 = load volatile float, float* %a
+  ret float %1
+}
+
+define double @double_load(double *%a) #0 {
+; RV32IFDC-LABEL: double_load:
+; RV32IFDC:         c.fld fa0, 0(a0)
+; RV32IFDC-NEXT:    c.jr ra
+  %1 = load volatile double, double* %a
+  ret double %1
+}

diff  --git a/llvm/test/CodeGen/RISCV/compress.ll b/llvm/test/CodeGen/RISCV/compress.ll
index b58adb848fcc..798e6552014f 100644
--- a/llvm/test/CodeGen/RISCV/compress.ll
+++ b/llvm/test/CodeGen/RISCV/compress.ll
@@ -1,5 +1,17 @@
+; This test is designed to run twice, once with function attributes and once
+; with target attributes added on the command line.
+;
+; RUN: cat %s > %t.tgtattr
+; RUN: echo 'attributes #0 = { nounwind }' >> %t.tgtattr
 ; RUN: llc -mtriple=riscv32 -mattr=+c -filetype=obj \
-; RUN:   -disable-block-placement < %s \
+; RUN:   -disable-block-placement < %t.tgtattr \
+; RUN:   | llvm-objdump -d -triple=riscv32 -mattr=+c -M no-aliases - \
+; RUN:   | FileCheck -check-prefix=RV32IC %s
+;
+; RUN: cat %s > %t.fnattr
+; RUN: echo 'attributes #0 = { nounwind "target-features"="+c" }' >> %t.fnattr
+; RUN: llc -mtriple=riscv32 -filetype=obj \
+; RUN:   -disable-block-placement < %t.fnattr \
 ; RUN:   | llvm-objdump -d -triple=riscv32 -mattr=+c -M no-aliases - \
 ; RUN:   | FileCheck -check-prefix=RV32IC %s
 
@@ -17,7 +29,7 @@
 ; possible if alternative codegen choices were made, but they belong in a
 ; 
diff erent test file.
 
-define i32 @simple_arith(i32 %a, i32 %b) nounwind {
+define i32 @simple_arith(i32 %a, i32 %b) #0 {
 ; RV32IC-LABEL: simple_arith:
 ; RV32IC:         addi a2, a0, 1
 ; RV32IC-NEXT:    c.andi a2, 11
@@ -35,7 +47,7 @@ define i32 @simple_arith(i32 %a, i32 %b) nounwind {
   ret i32 %6
 }
 
-define i32 @select(i32 %a, i32 *%b) nounwind {
+define i32 @select(i32 %a, i32 *%b) #0 {
 ; RV32IC-LABEL: select:
 ; RV32IC:         c.lw a2, 0(a1)
 ; RV32IC-NEXT:    c.beqz a2, 4
@@ -111,14 +123,14 @@ define i32 @select(i32 %a, i32 *%b) nounwind {
   ret i32 %val20
 }
 
-define i32 @pos_tiny() nounwind {
+define i32 @pos_tiny() #0 {
 ; RV32IC-LABEL: pos_tiny:
 ; RV32IC:         c.li a0, 18
 ; RV32IC-NEXT:    c.jr ra
   ret i32 18
 }
 
-define i32 @pos_i32() nounwind {
+define i32 @pos_i32() #0 {
 ; RV32IC-LABEL: pos_i32:
 ; RV32IC:         lui a0, 423811
 ; RV32IC-NEXT:    addi a0, a0, -1297
@@ -126,7 +138,7 @@ define i32 @pos_i32() nounwind {
   ret i32 1735928559
 }
 
-define i32 @pos_i32_half_compressible() nounwind {
+define i32 @pos_i32_half_compressible() #0 {
 ; RV32IC-LABEL: pos_i32_half_compressible:
 ; RV32IC:         lui a0, 423810
 ; RV32IC-NEXT:    c.addi  a0, 28
@@ -134,15 +146,14 @@ define i32 @pos_i32_half_compressible() nounwind {
   ret i32 1735925788
 }
 
-
-define i32 @neg_tiny() nounwind {
+define i32 @neg_tiny() #0 {
 ; RV32IC-LABEL: neg_tiny:
 ; RV32IC:       c.li a0, -19
 ; RV32IC-NEXT:  c.jr ra
   ret i32 -19
 }
 
-define i32 @neg_i32() nounwind {
+define i32 @neg_i32() #0 {
 ; RV32IC-LABEL: neg_i32:
 ; RV32IC:       lui a0, 912092
 ; RV32IC-NEXT:  addi a0, a0, -273
@@ -150,14 +161,14 @@ define i32 @neg_i32() nounwind {
   ret i32 -559038737
 }
 
-define i32 @pos_i32_hi20_only() nounwind {
+define i32 @pos_i32_hi20_only() #0 {
 ; RV32IC-LABEL: pos_i32_hi20_only:
 ; RV32IC:       c.lui a0, 16
 ; RV32IC-NEXT:  c.jr ra
   ret i32 65536
 }
 
-define i32 @neg_i32_hi20_only() nounwind {
+define i32 @neg_i32_hi20_only() #0 {
 ; RV32IC-LABEL: neg_i32_hi20_only:
 ; RV32IC:       c.lui a0, 1048560
 ; RV32IC-NEXT:  c.jr ra


        


More information about the llvm-commits mailing list