From a83bf35d167c43ff2eb8c61bdea0cb660d2b07d8 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Tue, 21 Dec 2010 20:10:51 +0000 Subject: Add a new transform to DAGCombiner. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122355 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 26 ++++++++++++++++++++++++++ test/CodeGen/X86/x86-64-extend-shift.ll | 10 ++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/CodeGen/X86/x86-64-extend-shift.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index cd26e64..35f4a76 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2972,6 +2972,32 @@ SDValue DAGCombiner::visitSHL(SDNode *N) { return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0.getOperand(0), DAG.getConstant(c1 + c2, N1.getValueType())); } + + // fold (shl (ext (shl x, c1)), c2) -> (ext (shl x, (add c1, c2))) + // For this to be valid, the second form must not preserve any of the bits + // that are shifted out by the inner shift in the first form. This means + // the outer shift size must be >= the number of bits added by the ext. + // As a corollary, we don't care what kind of ext it is. + if (N1C && (N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::ANY_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND) && + N0.getOperand(0).getOpcode() == ISD::SHL && + isa(N0.getOperand(0)->getOperand(1))) { + uint64_t c1 = + cast(N0.getOperand(0)->getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + EVT InnerShiftVT = N0.getOperand(0).getValueType(); + uint64_t InnerShiftSize = InnerShiftVT.getScalarType().getSizeInBits(); + if (c2 >= OpSizeInBits - InnerShiftSize) { + if (c1 + c2 >= OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SHL, N0->getDebugLoc(), VT, + DAG.getNode(N0.getOpcode(), N0->getDebugLoc(), VT, + N0.getOperand(0)->getOperand(0)), + DAG.getConstant(c1 + c2, VT)); + } + } + // fold (shl (srl x, c1), c2) -> (shl (and x, (shl -1, c1)), (sub c2, c1)) or // (srl (and x, (shl -1, c1)), (sub c1, c2)) if (N1C && N0.getOpcode() == ISD::SRL && diff --git a/test/CodeGen/X86/x86-64-extend-shift.ll b/test/CodeGen/X86/x86-64-extend-shift.ll new file mode 100644 index 0000000..6852785 --- /dev/null +++ b/test/CodeGen/X86/x86-64-extend-shift.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s +; Formerly there were two shifts. + +define i64 @baz(i32 %A) nounwind { +; CHECK: shlq $49, %rax + %tmp1 = shl i32 %A, 17 + %tmp2 = zext i32 %tmp1 to i64 + %tmp3 = shl i64 %tmp2, 32 + ret i64 %tmp3 +} -- cgit v1.1