Enhance the truncstore optimization code to handle shifted
authorChris Lattner <sabre@nondot.org>
Sat, 13 Oct 2007 06:58:48 +0000 (06:58 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 13 Oct 2007 06:58:48 +0000 (06:58 +0000)
values and propagate demanded bits through them in simple cases.

This allows this code:
void foo(char *P) {
   strcpy(P, "abc");
}
to compile to:

_foo:
        ldrb r3, [r1]
        ldrb r2, [r1, #+1]
        ldrb r12, [r1, #+2]!
        ldrb r1, [r1, #+1]
        strb r1, [r0, #+3]
        strb r2, [r0, #+1]
        strb r12, [r0, #+2]
        strb r3, [r0]
        bx lr

instead of:

_foo:
        ldrb r3, [r1, #+3]
        ldrb r2, [r1, #+2]
        orr r3, r2, r3, lsl #8
        ldrb r2, [r1, #+1]
        ldrb r1, [r1]
        orr r2, r1, r2, lsl #8
        orr r3, r2, r3, lsl #16
        strb r3, [r0]
        mov r2, r3, lsr #24
        strb r2, [r0, #+3]
        mov r2, r3, lsr #16
        strb r2, [r0, #+2]
        mov r3, r3, lsr #8
        strb r3, [r0, #+1]
        bx lr

testcase here: test/CodeGen/ARM/truncstore-dag-combine.ll

This also helps occasionally for X86 and other cases not involving
unaligned load/stores.

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

lib/CodeGen/SelectionDAG/DAGCombiner.cpp

index ced48166da3fd32cd8b202c9692a30086875bbbe..4d813a0cb4d5780fefee4fd7d8ef2bec8b6c6a7a 100644 (file)
@@ -156,10 +156,10 @@ namespace {
     /// SimplifyDemandedBits - Check the specified integer node value to see if
     /// it can be simplified or if things it uses can be simplified by bit
     /// propagation.  If so, return true.
-    bool SimplifyDemandedBits(SDOperand Op) {
+    bool SimplifyDemandedBits(SDOperand Op, uint64_t Demanded = ~0ULL) {
       TargetLowering::TargetLoweringOpt TLO(DAG);
       uint64_t KnownZero, KnownOne;
-      uint64_t Demanded = MVT::getIntVTBitMask(Op.getValueType());
+      Demanded &= MVT::getIntVTBitMask(Op.getValueType());
       if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
         return false;
 
@@ -2809,6 +2809,20 @@ SDOperand DAGCombiner::GetDemandedBits(SDOperand V, uint64_t Mask) {
     if (DAG.MaskedValueIsZero(V.getOperand(1), Mask))
       return V.getOperand(0);
     break;
+  case ISD::SRL:
+    // Only look at single-use SRLs.
+    if (!V.Val->hasOneUse())
+      break;
+    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
+      // See if we can recursively simplify the LHS.
+      unsigned Amt = RHSC->getValue();
+      Mask = (Mask << Amt) & MVT::getIntVTBitMask(V.getValueType());
+      SDOperand SimplifyLHS = GetDemandedBits(V.getOperand(0), Mask);
+      if (SimplifyLHS.Val) {
+        return DAG.getNode(ISD::SRL, V.getValueType(), 
+                           SimplifyLHS, V.getOperand(1));
+      }
+    }
   }
   return SDOperand();
 }
@@ -4040,6 +4054,11 @@ SDOperand DAGCombiner::visitSTORE(SDNode *N) {
       return DAG.getTruncStore(Chain, Shorter, Ptr, ST->getSrcValue(),
                                ST->getSrcValueOffset(), ST->getStoredVT(),
                                ST->isVolatile(), ST->getAlignment());
+    
+    // Otherwise, see if we can simplify the operation with
+    // SimplifyDemandedBits, which only works if the value has a single use.
+    if (SimplifyDemandedBits(Value, MVT::getIntVTBitMask(ST->getStoredVT())))
+      return SDOperand(N, 0);
   }
   
   return SDOperand();