DAGCombine (shl (anyext x, c)) to (anyext (shl x, c)) if the high bits
authorDan Gohman <gohman@apple.com>
Fri, 23 Jul 2010 18:03:30 +0000 (18:03 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 23 Jul 2010 18:03:30 +0000 (18:03 +0000)
are not demanded. This often allows the anyext to be folded away.

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

lib/CodeGen/SelectionDAG/TargetLowering.cpp
test/CodeGen/X86/shl-anyext.ll [new file with mode: 0644]

index 6e6fedeb2e407d3d738e80939621537aa1291e14..389f2ea5ff163cdbd5734bca3448ad153b7fa6b6 100644 (file)
@@ -1367,9 +1367,29 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
         }
       }      
       
-      if (SimplifyDemandedBits(Op.getOperand(0), NewMask.lshr(ShAmt),
+      if (SimplifyDemandedBits(InOp, NewMask.lshr(ShAmt),
                                KnownZero, KnownOne, TLO, Depth+1))
         return true;
+
+      // Convert (shl (anyext x, c)) to (anyext (shl x, c)) if the high bits
+      // are not demanded. This will likely allow the anyext to be folded away.
+      if (InOp.getNode()->getOpcode() == ISD::ANY_EXTEND) {
+        SDValue InnerOp = InOp.getNode()->getOperand(0);
+        EVT InnerVT = InnerOp.getValueType();
+        if ((APInt::getHighBitsSet(BitWidth,
+                                   BitWidth - InnerVT.getSizeInBits()) &
+               DemandedMask) == 0 &&
+            isTypeDesirableForOp(ISD::SHL, InnerVT)) {
+          SDValue NarrowShl =
+            TLO.DAG.getNode(ISD::SHL, dl, InnerVT, InnerOp,
+                            TLO.DAG.getConstant(ShAmt, InnerVT));
+          return
+            TLO.CombineTo(Op,
+                          TLO.DAG.getNode(ISD::ANY_EXTEND, dl, Op.getValueType(),
+                                          NarrowShl));
+        }
+      }
+
       KnownZero <<= SA->getZExtValue();
       KnownOne  <<= SA->getZExtValue();
       // low bits known zero.
diff --git a/test/CodeGen/X86/shl-anyext.ll b/test/CodeGen/X86/shl-anyext.ll
new file mode 100644 (file)
index 0000000..6dc9531
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: llc -march=x86-64 < %s | FileCheck %s
+
+; Codegen should be able to use a 32-bit shift instead of a 64-bit shift.
+; CHECK: shll $16
+
+define fastcc void @test(i32 %level, i64 %a, i64 %b, i64 %c, i64 %d, i32* %p) nounwind {
+if.end523:                                        ; preds = %if.end453
+  %conv7981749 = zext i32 %level to i64           ; <i64> [#uses=1]
+  %and799 = shl i64 %conv7981749, 16              ; <i64> [#uses=1]
+  %shl800 = and i64 %and799, 16711680             ; <i64> [#uses=1]
+  %or801 = or i64 %shl800, %a                     ; <i64> [#uses=1]
+  %or806 = or i64 %or801, %b                      ; <i64> [#uses=1]
+  %or811 = or i64 %or806, %c                      ; <i64> [#uses=1]
+  %or819 = or i64 %or811, %d                      ; <i64> [#uses=1]
+  %conv820 = trunc i64 %or819 to i32              ; <i32> [#uses=1]
+  store i32 %conv820, i32* %p
+  ret void
+}