Let targets provide hooks that compute known zero and ones for any_extend
authorEvan Cheng <evan.cheng@apple.com>
Thu, 6 Dec 2012 01:28:01 +0000 (01:28 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 6 Dec 2012 01:28:01 +0000 (01:28 +0000)
and extload's. If they are implemented as zero-extend, or implicitly
zero-extend, then this can enable more demanded bits optimizations. e.g.

define void @foo(i16* %ptr, i32 %a) nounwind {
entry:
  %tmp1 = icmp ult i32 %a, 100
  br i1 %tmp1, label %bb1, label %bb2
bb1:
  %tmp2 = load i16* %ptr, align 2
  br label %bb2
bb2:
  %tmp3 = phi i16 [ 0, %entry ], [ %tmp2, %bb1 ]
  %cmp = icmp ult i16 %tmp3, 24
  br i1 %cmp, label %bb3, label %exit
bb3:
  call void @bar() nounwind
  br label %exit
exit:
  ret void
}

This compiles to the followings before:
        push    {lr}
        mov     r2, #0
        cmp     r1, #99
        bhi     LBB0_2
@ BB#1:                                 @ %bb1
        ldrh    r2, [r0]
LBB0_2:                                 @ %bb2
        uxth    r0, r2
        cmp     r0, #23
        bhi     LBB0_4
@ BB#3:                                 @ %bb3
        bl      _bar
LBB0_4:                                 @ %exit
        pop     {lr}
        bx      lr

The uxth is not needed since ldrh implicitly zero-extend the high bits. With
this change it's eliminated.

rdar://12771555

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169459 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/ARM/extload-knownzero.ll [new file with mode: 0644]

index 687109a1b0d328d6ffd0481cf9d059ca1eb00ae7..2cdc05096b8fdc62fcab3647500e87eae63e3b30 100644 (file)
@@ -935,6 +935,16 @@ public:
                                               const SelectionDAG &DAG,
                                               unsigned Depth = 0) const;
 
+  /// computeMaskedBitsForAnyExtend - Since each target implement ANY_EXTEND
+  /// and ExtLoad nodes specifically, let the target determine which of the bits
+  /// specified in Mask are known to be either zero or one and return them in
+  /// the KnownZero/KnownOne bitsets.
+  virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
+                                             APInt &KnownZero,
+                                             APInt &KnownOne,
+                                             const SelectionDAG &DAG,
+                                             unsigned Depth = 0) const;
+
   /// ComputeNumSignBitsForTargetNode - This method can be implemented by
   /// targets that want to expose additional information about sign bits to the
   /// DAG Combiner.
index 7dd57d542016631db78904477fa972573078afda..631449ca79a16f58ae3b08385d9eebd05bab560c 100644 (file)
@@ -1930,6 +1930,8 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, APInt &KnownZero,
       KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
     } else if (const MDNode *Ranges = LD->getRanges()) {
       computeMaskedBitsLoad(*Ranges, KnownZero);
+    } else if (ISD::isEXTLoad(Op.getNode())) {
+      TLI.computeMaskedBitsForAnyExtend(Op, KnownZero, KnownOne, *this, Depth);
     }
     return;
   }
@@ -1972,13 +1974,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, APInt &KnownZero,
     return;
   }
   case ISD::ANY_EXTEND: {
-    EVT InVT = Op.getOperand(0).getValueType();
-    unsigned InBits = InVT.getScalarType().getSizeInBits();
-    KnownZero = KnownZero.trunc(InBits);
-    KnownOne = KnownOne.trunc(InBits);
-    ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
-    KnownZero = KnownZero.zext(BitWidth);
-    KnownOne = KnownOne.zext(BitWidth);
+    TLI.computeMaskedBitsForAnyExtend(Op, KnownZero, KnownOne, *this, Depth);
     return;
   }
   case ISD::TRUNCATE: {
index 931c569d4229f2850ff7b233cdd4fb4fa31487ec..b410988dbde630a75a442bb4bdb2d17f9adfae87 100644 (file)
@@ -1856,6 +1856,30 @@ void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
   KnownZero = KnownOne = APInt(KnownOne.getBitWidth(), 0);
 }
 
+void TargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
+                                                   APInt &KnownZero,
+                                                   APInt &KnownOne,
+                                                   const SelectionDAG &DAG,
+                                                   unsigned Depth) const {
+  unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
+  if (Op.getOpcode() == ISD::ANY_EXTEND) {
+    EVT InVT = Op.getOperand(0).getValueType();
+    unsigned InBits = InVT.getScalarType().getSizeInBits();
+    KnownZero = KnownZero.trunc(InBits);
+    KnownOne = KnownOne.trunc(InBits);
+    DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
+    KnownZero = KnownZero.zext(BitWidth);
+    KnownOne = KnownOne.zext(BitWidth);
+    return;
+  } else if (ISD::isEXTLoad(Op.getNode())) {
+    KnownZero = KnownOne = APInt(BitWidth, 0);
+    return;
+  }
+  
+  assert(0 && "Expecting an ANY_EXTEND or extload!");
+}
+
+
 /// ComputeNumSignBitsForTargetNode - This method can be implemented by
 /// targets that want to expose additional information about sign bits to the
 /// DAG Combiner.
index c1b31b3c9f15bc6aafe4b544f17b15be33bc0b8c..c0a785338d6aef4d05b4a0225f737aef67b1cb3f 100644 (file)
@@ -9878,6 +9878,36 @@ void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
   }
 }
 
+void ARMTargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
+                                                      APInt &KnownZero,
+                                                      APInt &KnownOne,
+                                                      const SelectionDAG &DAG,
+                                                      unsigned Depth) const {
+  unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
+  if (Op.getOpcode() == ISD::ANY_EXTEND) {
+    // Implemented as a zero_extend.
+    EVT InVT = Op.getOperand(0).getValueType();
+    unsigned InBits = InVT.getScalarType().getSizeInBits();
+    KnownZero = KnownZero.trunc(InBits);
+    KnownOne = KnownOne.trunc(InBits);
+    DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
+    KnownZero = KnownZero.zext(BitWidth);
+    KnownOne = KnownOne.zext(BitWidth);
+    APInt NewBits   = APInt::getHighBitsSet(BitWidth, BitWidth - InBits);
+    KnownZero |= NewBits;
+    return;
+  } else if (ISD::isEXTLoad(Op.getNode())) {
+    // Implemented as zextloads.
+    LoadSDNode *LD = cast<LoadSDNode>(Op);
+    EVT VT = LD->getMemoryVT();
+    unsigned MemBits = VT.getScalarType().getSizeInBits();
+    KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
+    return;
+  }
+  
+  assert(0 && "Expecting an ANY_EXTEND or extload!");
+}
+
 //===----------------------------------------------------------------------===//
 //                           ARM Inline Assembly Support
 //===----------------------------------------------------------------------===//
index 487c925dd9b14377a57bd56af012ae42a7d92ebf..bde2ad49245b8d84a3de6c9c13ab11521efe279f 100644 (file)
@@ -333,6 +333,11 @@ namespace llvm {
                                                 const SelectionDAG &DAG,
                                                 unsigned Depth) const;
 
+    virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
+                                               APInt &KnownZero,
+                                               APInt &KnownOne,
+                                               const SelectionDAG &DAG,
+                                               unsigned Depth) const;
 
     virtual bool ExpandInlineAsm(CallInst *CI) const;
 
index b3ff4ee98e3dbcfcfddc7c536b73c7c7638defa4..20fe41dc3bf9283190bad19029b0d6e51b80c4ad 100644 (file)
@@ -14112,6 +14112,38 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
   }
 }
 
+void X86TargetLowering::computeMaskedBitsForAnyExtend(const SDValue Op,
+                                                      APInt &KnownZero,
+                                                      APInt &KnownOne,
+                                                      const SelectionDAG &DAG,
+                                                      unsigned Depth) const {
+  unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
+  if (Op.getOpcode() == ISD::ANY_EXTEND) {
+    // Implemented as a zero_extend except for i16 -> i32
+    EVT InVT = Op.getOperand(0).getValueType();
+    unsigned InBits = InVT.getScalarType().getSizeInBits();
+    KnownZero = KnownZero.trunc(InBits);
+    KnownOne = KnownOne.trunc(InBits);
+    DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero, KnownOne, Depth+1);
+    KnownZero = KnownZero.zext(BitWidth);
+    KnownOne = KnownOne.zext(BitWidth);
+    if (BitWidth != 32 || InBits != 16) {
+      APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits);
+      KnownZero |= NewBits;
+    }
+    return;
+  } else if (ISD::isEXTLoad(Op.getNode())) {
+    // Implemented as zextloads or implicitly zero-extended (i32 -> i64)
+    LoadSDNode *LD = cast<LoadSDNode>(Op);
+    EVT VT = LD->getMemoryVT();
+    unsigned MemBits = VT.getScalarType().getSizeInBits();
+    KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
+    return;
+  }
+  
+  assert(0 && "Expecting an ANY_EXTEND or extload!");
+}
+
 unsigned X86TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
                                                          unsigned Depth) const {
   // SETCC_CARRY sets the dest to ~0 for true or 0 for false.
index e830c5fef62a9528ce4196bdaa60874309c79f1a..099f1d884e75d864d13aa33de606ae76343e6b6d 100644 (file)
@@ -558,6 +558,12 @@ namespace llvm {
                                                 const SelectionDAG &DAG,
                                                 unsigned Depth = 0) const;
 
+    virtual void computeMaskedBitsForAnyExtend(const SDValue Op,
+                                               APInt &KnownZero,
+                                               APInt &KnownOne,
+                                               const SelectionDAG &DAG,
+                                               unsigned Depth) const;
+
     // ComputeNumSignBitsForTargetNode - Determine the number of bits in the
     // operation that are sign bits.
     virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op,
diff --git a/test/CodeGen/ARM/extload-knownzero.ll b/test/CodeGen/ARM/extload-knownzero.ll
new file mode 100644 (file)
index 0000000..3482853
--- /dev/null
@@ -0,0 +1,27 @@
+; RUN: llc < %s -march=arm | FileCheck %s
+; rdar://12771555
+
+define void @foo(i16* %ptr, i32 %a) nounwind {
+entry:
+; CHECK: foo:
+  %tmp1 = icmp ult i32 %a, 100
+  br i1 %tmp1, label %bb1, label %bb2
+bb1:
+; CHECK: %bb1
+; CHECK: ldrh
+  %tmp2 = load i16* %ptr, align 2
+  br label %bb2
+bb2:
+; CHECK-NOT: uxth
+; CHECK: cmp
+  %tmp3 = phi i16 [ 0, %entry ], [ %tmp2, %bb1 ]
+  %cmp = icmp ult i16 %tmp3, 24
+  br i1 %cmp, label %bb3, label %exit
+bb3:
+  call void @bar() nounwind
+  br label %exit
+exit:
+  ret void
+}
+
+declare void @bar ()