diff options
author | Craig Topper <craig.topper@intel.com> | 2019-06-18 04:23:58 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@intel.com> | 2019-06-18 04:23:58 +0000 |
commit | f4284f8a9d972e977ce634b6b84bf86e90a09866 (patch) | |
tree | 9dfe05ea3077ca2cf0367991c020d18b7d15b132 | |
parent | 587427716c3aa923ca51674e8970b9e1c3108754 (diff) | |
download | bcm5719-llvm-f4284f8a9d972e977ce634b6b84bf86e90a09866.tar.gz bcm5719-llvm-f4284f8a9d972e977ce634b6b84bf86e90a09866.zip |
[X86] Move code that shrinks immediates for ((x << C1) op C2) into a helper function. NFCI
Preliminary step for D59909
llvm-svn: 363645
-rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 226 |
1 files changed, 118 insertions, 108 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 3e3d6beee3e..414b6bcdab4 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -502,6 +502,7 @@ namespace { bool shrinkAndImmediate(SDNode *N); bool isMaskZeroExtended(SDNode *N) const; bool tryShiftAmountMod(SDNode *N); + bool tryShrinkShlLogicImm(SDNode *N); bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask); MachineSDNode *emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad, @@ -3567,6 +3568,119 @@ bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *N) { return true; } +bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *N) { + MVT NVT = N->getSimpleValueType(0); + unsigned Opcode = N->getOpcode(); + SDLoc dl(N); + + // For operations of the form (x << C1) op C2, check if we can use a smaller + // encoding for C2 by transforming it into (x op (C2>>C1)) << C1. + SDValue Shift = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1); + if (!Cst) + return false; + + 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? + bool FoundAnyExtend = false; + if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() && + Shift.getOperand(0).getSimpleValueType() == MVT::i32 && + isUInt<32>(Val)) { + FoundAnyExtend = true; + Shift = Shift.getOperand(0); + } + + if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse()) + return false; + + // i8 is unshrinkable, i16 should be promoted to i32. + if (NVT != MVT::i32 && NVT != MVT::i64) + return false; + + ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1)); + if (!ShlCst) + return false; + + uint64_t ShAmt = ShlCst->getZExtValue(); + + // Make sure that we don't change the operation by removing bits. + // This only matters for OR and XOR, AND is unaffected. + uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1; + if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0) + return false; + + // Check the minimum bitwidth for the new constant. + // TODO: Using 16 and 8 bit operations is also possible for or32 & xor32. + auto CanShrinkImmediate = [&](int64_t &ShiftedVal) { + if (Opcode == ISD::AND) { + // AND32ri is the same as AND64ri32 with zext imm. + // Try this before sign extended immediates below. + ShiftedVal = (uint64_t)Val >> ShAmt; + if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal)) + return true; + // Also swap order when the AND can become MOVZX. + if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX) + return true; + } + ShiftedVal = Val >> ShAmt; + if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) || + (!isInt<32>(Val) && isInt<32>(ShiftedVal))) + return true; + if (Opcode != ISD::AND) { + // MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr + ShiftedVal = (uint64_t)Val >> ShAmt; + if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal)) + return true; + } + return false; + }; + + int64_t ShiftedVal; + if (!CanShrinkImmediate(ShiftedVal)) + return false; + + // 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(N->getOperand(0), NeededMask)) + return false; + } + + SDValue X = Shift.getOperand(0); + if (FoundAnyExtend) { + SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X); + insertDAGNode(*CurDAG, SDValue(N, 0), NewX); + X = NewX; + } + + SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT); + insertDAGNode(*CurDAG, SDValue(N, 0), NewCst); + SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst); + insertDAGNode(*CurDAG, SDValue(N, 0), NewBinOp); + SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp, + Shift.getOperand(1)); + ReplaceNode(N, NewSHL.getNode()); + SelectCode(NewSHL.getNode()); + return true; +} + /// If the high bits of an 'and' operand are known zero, try setting the /// high bits of an 'and' constant operand to produce a smaller encoding by /// creating a small, sign-extended negative immediate rather than a large @@ -4131,115 +4245,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) { LLVM_FALLTHROUGH; case ISD::OR: - case ISD::XOR: { - - // For operations of the form (x << C1) op C2, check if we can use a smaller - // encoding for C2 by transforming it into (x op (C2>>C1)) << C1. - SDValue Shift = Node->getOperand(0); - SDValue N1 = Node->getOperand(1); - - ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1); - 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? - bool FoundAnyExtend = false; - if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() && - Shift.getOperand(0).getSimpleValueType() == MVT::i32 && - isUInt<32>(Val)) { - FoundAnyExtend = true; - Shift = Shift.getOperand(0); - } - - if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse()) - break; - - // i8 is unshrinkable, i16 should be promoted to i32. - if (NVT != MVT::i32 && NVT != MVT::i64) - break; - - ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1)); - if (!ShlCst) - break; - - uint64_t ShAmt = ShlCst->getZExtValue(); - - // Make sure that we don't change the operation by removing bits. - // This only matters for OR and XOR, AND is unaffected. - uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1; - if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0) - break; - - // Check the minimum bitwidth for the new constant. - // TODO: Using 16 and 8 bit operations is also possible for or32 & xor32. - auto CanShrinkImmediate = [&](int64_t &ShiftedVal) { - if (Opcode == ISD::AND) { - // AND32ri is the same as AND64ri32 with zext imm. - // Try this before sign extended immediates below. - ShiftedVal = (uint64_t)Val >> ShAmt; - if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal)) - return true; - // Also swap order when the AND can become MOVZX. - if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX) - return true; - } - ShiftedVal = Val >> ShAmt; - if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) || - (!isInt<32>(Val) && isInt<32>(ShiftedVal))) - return true; - if (Opcode != ISD::AND) { - // MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr - ShiftedVal = (uint64_t)Val >> ShAmt; - if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal)) - return true; - } - return false; - }; - - int64_t ShiftedVal; - if (!CanShrinkImmediate(ShiftedVal)) - break; - - // 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; - } - - 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; - } + case ISD::XOR: + if (tryShrinkShlLogicImm(Node)) + return; + 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; - } case X86ISD::SMUL: // i16/i32/i64 are handled with isel patterns. if (NVT != MVT::i8) |