[llvm] r274510 - [Thumb] Reapply r272251 with a fix for PR28348

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 4 09:35:42 PDT 2016


Author: jamesm
Date: Mon Jul  4 11:35:41 2016
New Revision: 274510

URL: http://llvm.org/viewvc/llvm-project?rev=274510&view=rev
Log:
[Thumb] Reapply r272251 with a fix for PR28348

We were using DAG->getConstant instead of DAG->getTargetConstant. This meant that we could inadvertently increase the use count of a constant if stars aligned, which it did in this testcase. Increasing the use count of the constant could cause ISel to fall over (because DAGToDAG lowering assumed the constant had only one use!)

Original commit message:
  [Thumb] Select a BIC instead of AND if the immediate can be encoded more optimally negated

  If an immediate is only used in an AND node, it is possible that the immediate can be more optimally materialized when negated. If this is the case, we can negate the immediate and use a BIC instead;

    int i(int a) {
      return a & 0xfffffeec;
    }

  Used to produce:
      ldr r1, [CONSTPOOL]
      ands r0, r1
    CONSTPOOL: 0xfffffeec

  And now produces:
      movs    r1, #255
      adds    r1, #20  ; Less costly immediate generation
      bics    r0, r1

Added:
    llvm/trunk/test/CodeGen/Thumb/bic_imm.ll
    llvm/trunk/test/CodeGen/Thumb2/bicbfi.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp

Modified: llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=274510&r1=274509&r2=274510&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Mon Jul  4 11:35:41 2016
@@ -2820,6 +2820,45 @@ void ARMDAGToDAGISel::Select(SDNode *N)
     if (tryV6T2BitfieldExtractOp(N, false))
       return;
 
+    // If an immediate is used in an AND node, it is possible that the immediate
+    // can be more optimally materialized when negated. If this is the case we
+    // can negate the immediate and use a BIC instead.
+    auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
+    if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) {
+      uint32_t Imm = (uint32_t) N1C->getZExtValue();
+
+      // In Thumb2 mode, an AND can take a 12-bit immediate. If this
+      // immediate can be negated and fit in the immediate operand of
+      // a t2BIC, don't do any manual transform here as this can be
+      // handled by the generic ISel machinery.
+      bool PreferImmediateEncoding =
+          Subtarget->hasThumb2() && !is_t2_so_imm(Imm) && is_t2_so_imm_not(Imm);
+      if (!PreferImmediateEncoding &&
+          ConstantMaterializationCost(Imm) >
+              ConstantMaterializationCost(~Imm)) {
+        // The current immediate costs more to materialize than a negated
+        // immediate, so negate the immediate and use a BIC.
+        SDValue NewImm =
+            CurDAG->getTargetConstant(~N1C->getZExtValue(), dl, MVT::i32);
+        CurDAG->RepositionNode(N->getIterator(), NewImm.getNode());
+
+        if (!Subtarget->hasThumb2()) {
+          SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32),
+                           N->getOperand(0), NewImm, getAL(CurDAG, dl),
+                           CurDAG->getRegister(0, MVT::i32)};
+          ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops));
+          return;
+        } else {
+          SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl),
+                           CurDAG->getRegister(0, MVT::i32),
+                           CurDAG->getRegister(0, MVT::i32)};
+          ReplaceNode(N,
+                      CurDAG->getMachineNode(ARM::t2BICri, dl, MVT::i32, Ops));
+          return;
+        }
+      }
+    }
+
     // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits
     // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits
     // are entirely contributed by c2 and lower 16-bits are entirely contributed
@@ -2834,7 +2873,7 @@ void ARMDAGToDAGISel::Select(SDNode *N)
     if (!Opc)
       break;
     SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
-    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
+    N1C = dyn_cast<ConstantSDNode>(N1);
     if (!N1C)
       break;
     if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) {

Added: llvm/trunk/test/CodeGen/Thumb/bic_imm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/bic_imm.ll?rev=274510&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb/bic_imm.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb/bic_imm.ll Mon Jul  4 11:35:41 2016
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple=thumbv7-linux-gnueabi -mcpu=cortex-m0 -verify-machineinstrs | FileCheck --check-prefix CHECK-T1 %s
+; RUN: llc < %s -mtriple=thumbv7-linux-gnueabi -mcpu=cortex-m3 -verify-machineinstrs | FileCheck --check-prefix CHECK-T2 %s
+
+; CHECK-T1-LABEL: @i
+; CHECK-T2-LABEL: @i
+; CHECK-T1: bics r0, #275
+; CHECK-T2: bic r0, r0, #275
+define i32 @i(i32 %a) {
+entry:
+  %and = and i32 %a, -276
+  ret i32 %and
+}

Added: llvm/trunk/test/CodeGen/Thumb2/bicbfi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/bicbfi.ll?rev=274510&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/bicbfi.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb2/bicbfi.ll Mon Jul  4 11:35:41 2016
@@ -0,0 +1,17 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7--linux-gnueabihf"
+
+; CHECK-LABEL: f:
+; CHECK: bic
+define void @f(i32* nocapture %b, i32* nocapture %c, i32 %a) {
+  %1 = and i32 %a, -4096
+  store i32 %1, i32* %c, align 4
+  %2 = and i32 %a, 4095
+  %3 = or i32 %2, 4096
+  %4 = load i32, i32* %b, align 4
+  %5 = add nsw i32 %4, %3
+  store i32 %5, i32* %b, align 4
+  ret void
+}
\ No newline at end of file




More information about the llvm-commits mailing list