Don't bother sign/zext_inreg'ing the result of an and operation if we know
authorChris Lattner <sabre@nondot.org>
Sun, 10 Apr 2005 23:37:16 +0000 (23:37 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 10 Apr 2005 23:37:16 +0000 (23:37 +0000)
the result does change as a result of the extend.

This improves codegen for Alpha on this testcase:

int %a(ushort* %i) {
        %tmp.1 = load ushort* %i
        %tmp.2 = cast ushort %tmp.1 to int
        %tmp.4 = and int %tmp.2, 1
        ret int %tmp.4
}

Generating:

a:
        ldgp $29, 0($27)
        ldwu $0,0($16)
        and $0,1,$0
        ret $31,($26),1

instead of:

a:
        ldgp $29, 0($27)
        ldwu $0,0($16)
        and $0,1,$0
        addl $0,0,$0
        ret $31,($26),1

btw, alpha really should switch to livein/outs for args :)

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

lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index 6b94adf1d8edebbd4a39e4ec1fcb06ea7403bc09..513bab2f538958a9242e1948441f3c6738bdef05 100644 (file)
@@ -1119,6 +1119,25 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,SDOperand N1,
         if (Opcode == ISD::SIGN_EXTEND_INREG) return N1;
         break;
       }
+
+    // If we are sign extending the result of an (and X, C) operation, and we
+    // know the extended bits are zeros already, don't do the extend.
+    if (N1.getOpcode() == ISD::AND)
+      if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getOperand(1))) {
+        uint64_t Mask = N1C->getValue();
+        unsigned NumBits = MVT::getSizeInBits(EVT);
+        if (Opcode == ISD::ZERO_EXTEND_INREG) {
+          if ((Mask & (~0ULL << NumBits)) == 0)
+            return N1;
+          else
+            return getNode(ISD::AND, VT, N1.getOperand(0),
+                           getConstant(Mask & (~0ULL >> (64-NumBits)), VT));
+        } else {
+          assert(Opcode == ISD::SIGN_EXTEND_INREG);
+          if ((Mask & (~0ULL << (NumBits-1))) == 0)
+            return N1;
+        }
+      }
     break;
   }