[llvm] r326626 - [RISCV] Implement MC relaxations for compressed instructions.

Sameer AbuAsal via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 2 14:04:12 PST 2018


Author: sabuasal
Date: Fri Mar  2 14:04:12 2018
New Revision: 326626

URL: http://llvm.org/viewvc/llvm-project?rev=326626&view=rev
Log:
[RISCV] Implement MC relaxations for compressed instructions.

Summary:
     This patch implements relaxation for RISCV in the MC layer.
      The following relaxations are currently handled:
      1) Relax C_BEQZ to BEQ and C_BNEZ to BNEZ in RISCV.
      2) Relax and C_J $imm  to JAL x0, $imm  and CJAL to JAL ra, $imm.

Reviewers: asb, llvm-commits, efriedma

Reviewed By: asb

Subscribers: shiva0217

Differential Revision: https://reviews.llvm.org/D43055

Added:
    llvm/trunk/test/MC/RISCV/rv32-relaxation.s
    llvm/trunk/test/MC/RISCV/rv64-relaxation.s
Modified:
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
    llvm/trunk/test/MC/RISCV/fixups-compressed.s
    llvm/trunk/test/MC/RISCV/relocations.s

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp?rev=326626&r1=326625&r2=326626&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp Fri Mar  2 14:04:12 2018
@@ -45,9 +45,7 @@ public:
 
   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                             const MCRelaxableFragment *DF,
-                            const MCAsmLayout &Layout) const override {
-    return false;
-  }
+                            const MCAsmLayout &Layout) const override;
 
   unsigned getNumFixupKinds() const override {
     return RISCV::NumTargetFixupKinds;
@@ -79,17 +77,92 @@ public:
     return Infos[Kind - FirstTargetFixupKind];
   }
 
-  bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
+  bool mayNeedRelaxation(const MCInst &Inst) const override;
+  unsigned getRelaxedOpcode(unsigned Op) const;
 
   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
-                        MCInst &Res) const override {
+                        MCInst &Res) const override;
 
-    report_fatal_error("RISCVAsmBackend::relaxInstruction() unimplemented");
-  }
 
   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
 };
 
+
+bool RISCVAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
+                                           uint64_t Value,
+                                           const MCRelaxableFragment *DF,
+                                           const MCAsmLayout &Layout) const {
+  int64_t Offset = int64_t(Value);
+  switch ((unsigned)Fixup.getKind()) {
+  default:
+    return false;
+  case RISCV::fixup_riscv_rvc_branch:
+    // For compressed branch instructions the immediate must be
+    // in the range [-256, 254].
+    return Offset > 254 || Offset < -256;
+  case RISCV::fixup_riscv_rvc_jump:
+    // For compressed jump instructions the immediate must be
+    // in the range [-2048, 2046].
+    return Offset > 2046 || Offset < -2048;
+  }
+}
+
+void RISCVAsmBackend::relaxInstruction(const MCInst &Inst,
+                                       const MCSubtargetInfo &STI,
+                                       MCInst &Res) const {
+  // TODO: replace this with call to auto generated uncompressinstr() function.
+  switch (Inst.getOpcode()) {
+  default:
+    llvm_unreachable("Opcode not expected!");
+  case RISCV::C_BEQZ:
+    // c.beqz $rs1, $imm -> beq $rs1, X0, $imm.
+    Res.setOpcode(RISCV::BEQ);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(MCOperand::createReg(RISCV::X0));
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case RISCV::C_BNEZ:
+    // c.bnez $rs1, $imm -> bne $rs1, X0, $imm.
+    Res.setOpcode(RISCV::BNE);
+    Res.addOperand(Inst.getOperand(0));
+    Res.addOperand(MCOperand::createReg(RISCV::X0));
+    Res.addOperand(Inst.getOperand(1));
+    break;
+  case RISCV::C_J:
+    // c.j $imm -> jal X0, $imm.
+    Res.setOpcode(RISCV::JAL);
+    Res.addOperand(MCOperand::createReg(RISCV::X0));
+    Res.addOperand(Inst.getOperand(0));
+    break;
+  case RISCV::C_JAL:
+    // c.jal $imm -> jal X1, $imm.
+    Res.setOpcode(RISCV::JAL);
+    Res.addOperand(MCOperand::createReg(RISCV::X1));
+    Res.addOperand(Inst.getOperand(0));
+    break;
+  }
+}
+
+// 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;
+  }
+}
+
+bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
+  return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();
+}
+
 bool RISCVAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
   bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC];
   unsigned MinNopLen = HasStdExtC ? 2 : 4;

Modified: llvm/trunk/test/MC/RISCV/fixups-compressed.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/fixups-compressed.s?rev=326626&r1=326625&r2=326626&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/fixups-compressed.s (original)
+++ llvm/trunk/test/MC/RISCV/fixups-compressed.s Fri Mar  2 14:04:12 2018
@@ -2,13 +2,15 @@
 # RUN:     | FileCheck -check-prefix=CHECK-FIXUP %s
 # RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+c < %s \
 # RUN:     | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc -filetype=obj -mattr=+c -triple=riscv32 %s \
+# RUN:     | llvm-readobj -r | FileCheck %s -check-prefix=CHECK-REL
 
 .LBB0_2:
 # CHECK-FIXUP:   fixup A - offset: 0, value: .LBB0_2, kind: fixup_riscv_rvc_jump
 # CHECK-INSTR: c.j     0
 c.j     .LBB0_2
 # CHECK:   fixup A - offset: 0, value: func1, kind: fixup_riscv_rvc_jump
-# CHECK-INSTR: c.jal   0
+# CHECK-INSTR: c.jal   6
 c.jal   func1
 # CHECK-FIXUP:   fixup A - offset: 0, value: .LBB0_2, kind: fixup_riscv_rvc_branch
 # CHECK-INSTR: c.beqz  a3, -4
@@ -16,3 +18,8 @@ c.beqz  a3, .LBB0_2
 # CHECK-FIXUP:   fixup A - offset: 0, value: .LBB0_2, kind: fixup_riscv_rvc_branch
 # CHECK-INSTR: c.bnez  a5, -6
 c.bnez  a5, .LBB0_2
+
+func1:
+  nop
+
+# CHECK-REL-NOT: R_RISCV

Modified: llvm/trunk/test/MC/RISCV/relocations.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/relocations.s?rev=326626&r1=326625&r2=326626&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/relocations.s (original)
+++ llvm/trunk/test/MC/RISCV/relocations.s Fri Mar  2 14:04:12 2018
@@ -85,11 +85,13 @@ bgeu a0, a1, foo
 # FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_branch
 
 c.jal foo
-# RELOC: R_RISCV_RVC_JUMP
+# A compressed jump (c.j) to an unresolved symbol will be relaxed to a (jal).
+# RELOC: R_RISCV_JAL
 # INSTR: c.jal foo
 # FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_rvc_jump
 
 c.bnez a0, foo
-# RELOC: R_RISCV_RVC_BRANCH
+# A compressed branch (c.bnez) to an unresolved symbol will be relaxed to a (bnez).
+# RELOC: R_RISCV_BRANCH
 # INSTR: c.bnez a0, foo
 # FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_rvc_branch

Added: llvm/trunk/test/MC/RISCV/rv32-relaxation.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rv32-relaxation.s?rev=326626&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/rv32-relaxation.s (added)
+++ llvm/trunk/test/MC/RISCV/rv32-relaxation.s Fri Mar  2 14:04:12 2018
@@ -0,0 +1,75 @@
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c < %s \
+# RUN:     | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s
+
+FAR_JUMP_NEGATIVE:
+  c.nop
+.space 2000
+
+FAR_BRANCH_NEGATIVE:
+  c.nop
+.space 256
+
+NEAR_NEGATIVE:
+  c.nop
+
+start:
+  c.bnez a0, NEAR
+#INSTR: c.bnez a0, 72
+  c.bnez a0, NEAR_NEGATIVE
+#INSTR: c.bnez a0, -4
+  c.bnez a0, FAR_BRANCH
+#INSTR-NEXT: bnez a0, 326
+  c.bnez a0, FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: bnez a0, -268
+  c.bnez a0, FAR_JUMP
+#INSTR-NEXT: bnez a0, 2320
+  c.bnez a0, FAR_JUMP_NEGATIVE
+#INSTR-NEXT: bnez a0, -2278
+
+  c.beqz a0, NEAR
+#INSTR-NEXT: c.beqz a0, 52
+  c.beqz a0, NEAR_NEGATIVE
+#INSTR-NEXT: c.beqz a0, -24
+  c.beqz a0, FAR_BRANCH
+#INSTR-NEXT: beqz a0, 306
+  c.beqz a0, FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: beqz a0, -288
+  c.beqz a0, FAR_JUMP
+#INSTR-NEXT: beqz a0, 2300
+  c.beqz a0, FAR_JUMP_NEGATIVE
+#INSTR-NEXT: beqz a0, -2298
+
+  c.j NEAR
+#INSTR-NEXT: c.j 32
+  c.j NEAR_NEGATIVE
+#INSTR-NEXT: c.j -44
+  c.j FAR_BRANCH
+#INSTR-NEXT: c.j 286
+  c.j FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: c.j -306
+  c.j FAR_JUMP
+#INSTR-NEXT: j 2284
+  c.j FAR_JUMP_NEGATIVE
+#INSTR-NEXT: j -2314
+
+  c.jal NEAR
+#INSTR: c.jal 16
+  c.jal NEAR_NEGATIVE
+#INSTR: c.jal -60
+  c.jal FAR_BRANCH
+#INSTR-NEXT: c.jal 270
+  c.jal FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: c.jal -322
+  c.jal FAR_JUMP
+#INSTR-NEXT: jal 2268
+  c.jal FAR_JUMP_NEGATIVE
+#INSTR-NEXT: jal -2330
+
+NEAR:
+  c.nop
+.space 256
+FAR_BRANCH:
+  c.nop
+.space 2000
+FAR_JUMP:
+  c.nop

Added: llvm/trunk/test/MC/RISCV/rv64-relaxation.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rv64-relaxation.s?rev=326626&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/rv64-relaxation.s (added)
+++ llvm/trunk/test/MC/RISCV/rv64-relaxation.s Fri Mar  2 14:04:12 2018
@@ -0,0 +1,64 @@
+# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+c < %s \
+# RUN:     | llvm-objdump -d - | FileCheck -check-prefix=INSTR %s
+
+FAR_JUMP_NEGATIVE:
+  c.nop
+.space 2000
+
+FAR_BRANCH_NEGATIVE:
+  c.nop
+.space 256
+
+NEAR_NEGATIVE:
+  c.nop
+
+start:
+  c.bnez a0, NEAR
+#INSTR: c.bnez a0, 56
+  c.bnez a0, NEAR_NEGATIVE
+#INSTR: c.bnez a0, -4
+  c.bnez a0, FAR_BRANCH
+#INSTR-NEXT: bnez a0, 310
+  c.bnez a0, FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: bnez a0, -268
+  c.bnez a0, FAR_JUMP
+#INSTR-NEXT: bnez a0, 2304
+  c.bnez a0, FAR_JUMP_NEGATIVE
+#INSTR-NEXT: bnez a0, -2278
+
+  c.beqz a0, NEAR
+#INSTR-NEXT: c.beqz a0, 36
+  c.beqz a0, NEAR_NEGATIVE
+#INSTR-NEXT: c.beqz a0, -24
+  c.beqz a0, FAR_BRANCH
+#INSTR-NEXT: beqz a0, 290
+  c.beqz a0, FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: beqz a0, -288
+  c.beqz a0, FAR_JUMP
+#INSTR-NEXT: beqz a0, 2284
+  c.beqz a0, FAR_JUMP_NEGATIVE
+#INSTR-NEXT: beqz a0, -2298
+
+  c.j NEAR
+#INSTR-NEXT: c.j 16
+  c.j NEAR_NEGATIVE
+#INSTR-NEXT: c.j -44
+  c.j FAR_BRANCH
+#INSTR-NEXT: c.j 270
+  c.j FAR_BRANCH_NEGATIVE
+#INSTR-NEXT: c.j -306
+  c.j FAR_JUMP
+#INSTR-NEXT: j 2268
+  c.j FAR_JUMP_NEGATIVE
+#INSTR-NEXT: j -2314
+
+NEAR:
+  c.nop
+
+.space 256
+FAR_BRANCH:
+  c.nop
+
+.space 2000
+FAR_JUMP:
+  c.nop




More information about the llvm-commits mailing list