diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -37,13 +37,17 @@
 
 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 @@
 #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 @@
   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
--- /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
--- 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
 ; different 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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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