ARM: make Thumb1 instructions non-flag-setting in IT block.
authorTim Northover <t.p.northover@gmail.com>
Mon, 27 Jul 2020 13:37:14 +0000 (14:37 +0100)
committerTim Northover <t.p.northover@gmail.com>
Tue, 28 Jul 2020 12:31:17 +0000 (13:31 +0100)
Many Thumb1 instructions are defined to set CPSR if executed outside an IT
block, but leave it alone from inside one. In MachineIR this is represented by
whether an optional register is CPSR or NoReg (0), and affects how the
instructions are printed.

This sets the instruction to the appropriate form during if-conversion.

llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
llvm/lib/Target/ARM/ARMInstrFormats.td
llvm/test/CodeGen/ARM/thumb2-it-block.ll
llvm/test/CodeGen/Thumb2/ifcvt-rescan-diamonds.ll

index 4cc2b6b..d340931 100644 (file)
@@ -537,6 +537,18 @@ bool ARMBaseInstrInfo::PredicateInstruction(
     MachineOperand &PMO = MI.getOperand(PIdx);
     PMO.setImm(Pred[0].getImm());
     MI.getOperand(PIdx+1).setReg(Pred[1].getReg());
+
+    // Thumb 1 arithmetic instructions do not set CPSR when executed inside an
+    // IT block. This affects how they are printed.
+    const MCInstrDesc &MCID = MI.getDesc();
+    if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
+      assert(MCID.OpInfo[1].isOptionalDef() && "CPSR def isn't expected operand");
+      assert((MI.getOperand(1).isDead() ||
+              MI.getOperand(1).getReg() != ARM::CPSR) &&
+             "if conversion tried to stop defining used CPSR");
+      MI.getOperand(1).setReg(ARM::NoRegister);
+    }
+
     return true;
   }
   return false;
index e13f343..85da7c5 100644 (file)
@@ -403,8 +403,9 @@ class InstTemplate<AddrMode am, int sz, IndexMode im,
   bit isUnaryDataProc = 0;
   bit canXformTo16Bit = 0;
   // The instruction is a 16-bit flag setting Thumb instruction. Used
-  // by the parser to determine whether to require the 'S' suffix on the
-  // mnemonic (when not in an IT block) or preclude it (when in an IT block).
+  // by the parser and if-converter to determine whether to require the 'S'
+  // suffix on the mnemonic (when not in an IT block) or preclude it (when
+  // in an IT block).
   bit thumbArithFlagSetting = 0;
 
   bit validForTailPredication = 0;
index 6d93869..c1c1c74 100644 (file)
@@ -16,9 +16,7 @@ entry:
 
 ; CHECK:        cmp
 ; CHECK-NEXT:   it    mi
-; We shouldn't need to check for the extra 's' here; tRSB should be printed as
-; "rsb" inside an IT block, not "rsbs".
-; CHECK-NEXT:   rsb{{s?}}mi
+; CHECK-NEXT:   rsbmi
 ; CHECK-NEXT:   cmp
 ; CHECK-NEXT:   it    mi
 ; CHECK-NEXT:   rsb{{s?}}mi
index b7ba741..116084b 100644 (file)
@@ -22,7 +22,8 @@ while.cond38:                                     ; preds = %if.end111, %entry
 ; CHECK-NEXT: it eq
 ; CHECK-NEXT: ldreq
 ; CHECK-NEXT: it ne
-; CHECK-NEXT: movsne
+  ; N.b. 16-bit mov instruction in IT block does not set flags.
+; CHECK-NEXT: movne
 ; CHECK-NEXT: mvns
 ; CHECK-NEXT: b
 cond.true77:                                      ; preds = %while.cond38