[llvm] r198904 - Fix a bug with the ARM thumb2 CBNZ and CBNZ instructions that

Kevin Enderby enderby at apple.com
Thu Jan 9 16:43:32 PST 2014


Author: enderby
Date: Thu Jan  9 18:43:32 2014
New Revision: 198904

URL: http://llvm.org/viewvc/llvm-project?rev=198904&view=rev
Log:
Fix a bug with the ARM thumb2 CBNZ and CBNZ instructions that
branch to the next instruction.  This can not be encoded but can be
turned into a NOP.

rdar://15062072

Added:
    llvm/trunk/test/MC/ARM/thumb2-cbn-to-next-inst.s
Modified:
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp?rev=198904&r1=198903&r2=198904&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp Thu Jan  9 18:43:32 2014
@@ -155,6 +155,8 @@ static unsigned getRelaxedOpcode(unsigne
   case ARM::tLDRpci:    return ARM::t2LDRpci;
   case ARM::tADR:       return ARM::t2ADR;
   case ARM::tB:         return ARM::t2B;
+  case ARM::tCBZ:       return ARM::tHINT;
+  case ARM::tCBNZ:      return ARM::tHINT;
   }
 }
 
@@ -196,6 +198,12 @@ bool ARMAsmBackend::fixupNeedsRelaxation
     int64_t Offset = int64_t(Value) - 4;
     return Offset > 1020 || Offset < 0 || Offset & 3;
   }
+  case ARM::fixup_arm_thumb_cb:
+    // If we have a Thumb CBZ or CBNZ instruction and its target is the next
+    // instruction it is is actually out of range for the instruction.
+    // It will be changed to a NOP.
+    int64_t Offset = (Value & ~1);
+    return Offset == 2;
   }
   llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!");
 }
@@ -212,7 +220,18 @@ void ARMAsmBackend::relaxInstruction(con
     report_fatal_error("unexpected instruction to relax: " + OS.str());
   }
 
-  // The instructions we're relaxing have (so far) the same operands.
+  // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we
+  // have to change the operands too.
+  if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) &&
+      RelaxedOp == ARM::tHINT) {
+    Res.setOpcode(RelaxedOp);
+    Res.addOperand(MCOperand::CreateImm(0));
+    Res.addOperand(MCOperand::CreateImm(14));
+    Res.addOperand(MCOperand::CreateReg(0));
+    return;
+  } 
+
+  // The rest of instructions we're relaxing have the same operands.
   // We just need to update to the proper opcode.
   Res = Inst;
   Res.setOpcode(RelaxedOp);

Added: llvm/trunk/test/MC/ARM/thumb2-cbn-to-next-inst.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-cbn-to-next-inst.s?rev=198904&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-cbn-to-next-inst.s (added)
+++ llvm/trunk/test/MC/ARM/thumb2-cbn-to-next-inst.s Thu Jan  9 18:43:32 2014
@@ -0,0 +1,33 @@
+@ RUN: llvm-mc -triple thumbv7-apple-darwin -filetype=obj -o %t.o %s
+@ RUN: llvm-objdump -triple thumbv7-apple-darwin -d %t.o | FileCheck %s
+
+.thumb
+start:
+.thumb_func start
+	add	 r1, r2, r3
+	cbnz	 r2, L1 @ this can't be encoded, must turn into a nop
+L1:
+	add	r4, r5, r6
+	cbnz	r2, L2
+	sub	r7, r8, r9
+L2:
+	add	r7, r8, r9
+	cbz	r2, L3 @ this can't be encoded, must turn into a nop
+L3:
+	add	r10, r11, r12
+	cbz	r2, L4
+	sub	r7, r8, r9
+L4:
+	add	r3, r4, r5
+
+@ CHECK: 0:	02 eb 03 01	add.w	r1, r2, r3
+@ CHECK: 4:	00 bf		nop
+@ CHECK: 6:	05 eb 06 04	add.w	r4, r5, r6
+@ CHECK: a:	0a b9		cbnz	r2, #2
+@ CHECK: c:	a8 eb 09 07	sub.w	r7, r8, r9
+@ CHECK: 10:	08 eb 09 07	add.w	r7, r8, r9
+@ CHECK: 14:	00 bf		nop
+@ CHECK: 16:	0b eb 0c 0a	add.w	r10, r11, r12
+@ CHECK: 1a:	0a b1		cbz	r2, #2
+@ CHECK: 1c:	a8 eb 09 07	sub.w	r7, r8, r9
+@ CHECK: 20:	04 eb 05 03	add.w	r3, r4, r5





More information about the llvm-commits mailing list