diff options
| author | Craig Topper <craig.topper@intel.com> | 2019-04-20 04:38:53 +0000 |
|---|---|---|
| committer | Craig Topper <craig.topper@intel.com> | 2019-04-20 04:38:53 +0000 |
| commit | 4d4b5d952e4587d320fa94db5bce783a915d03ee (patch) | |
| tree | 3d1c75312d2bf77ba2d8a64a1f39a88f92e00c21 /llvm/lib/Target | |
| parent | 8b8264828cbc4de633dfce90a7185c52a83687dc (diff) | |
| download | bcm5719-llvm-4d4b5d952e4587d320fa94db5bce783a915d03ee.tar.gz bcm5719-llvm-4d4b5d952e4587d320fa94db5bce783a915d03ee.zip | |
[X86] Don't turn (and (shl X, C1), C2) into (shl (and X, (C1 >> C2), C2) if the original AND can represented by MOVZX.
The MOVZX doesn't require an immediate to be encoded at all. Though it does use
a 2 byte opcode so its the same size as a 1 byte immediate. But it has a
separate source and dest register so can help avoid copies.
llvm-svn: 358805
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index f6c82cb2b35..fff6bb8571e 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -3983,10 +3983,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) { if (!Cst) break; + int64_t Val = Cst->getSExtValue(); + // If we have an any_extend feeding the AND, look through it to see if there // is a shift behind it. But only if the AND doesn't use the extended bits. // FIXME: Generalize this to other ANY_EXTEND than i32 to i64? - int64_t Val = Cst->getSExtValue(); bool FoundAnyExtend = false; if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() && Shift.getOperand(0).getSimpleValueType() == MVT::i32 && @@ -4041,26 +4042,44 @@ void X86DAGToDAGISel::Select(SDNode *Node) { }; int64_t ShiftedVal; - if (CanShrinkImmediate(ShiftedVal)) { - SDValue X = Shift.getOperand(0); - if (FoundAnyExtend) { - SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X); - insertDAGNode(*CurDAG, SDValue(Node, 0), NewX); - X = NewX; - } + if (!CanShrinkImmediate(ShiftedVal)) + break; - SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT); - insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst); - SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst); - insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp); - SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp, - Shift.getOperand(1)); - ReplaceNode(Node, NewSHL.getNode()); - SelectCode(NewSHL.getNode()); - return; + // Ok, we can reorder to get a smaller immediate. + + // But, its possible the original immediate allowed an AND to become MOVZX. + // Doing this late due to avoid the MakedValueIsZero call as late as + // possible. + if (Opcode == ISD::AND) { + // Find the smallest zext this could possibly be. + unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits(); + ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U)); + + // Figure out which bits need to be zero to achieve that mask. + APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(), + ZExtWidth); + NeededMask &= ~Cst->getAPIntValue(); + + if (CurDAG->MaskedValueIsZero(Node->getOperand(0), NeededMask)) + break; } - break; + SDValue X = Shift.getOperand(0); + if (FoundAnyExtend) { + SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X); + insertDAGNode(*CurDAG, SDValue(Node, 0), NewX); + X = NewX; + } + + SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT); + insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst); + SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst); + insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp); + SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp, + Shift.getOperand(1)); + ReplaceNode(Node, NewSHL.getNode()); + SelectCode(NewSHL.getNode()); + return; } case X86ISD::SMUL: // i16/i32/i64 are handled with isel patterns. |

