diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index d2a5541bc9497d77faf7b5a9fe5d0e3b4ae70c65..eb049f1868a6e88a820701fe1db69093f269826b 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -131,8 +131,6 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); - setOperationAction(ISD::AND, MVT::i32, Custom); - setOperationAction(ISD::OR, MVT::i32, Custom); setOperationAction(ISD::SDIV, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); @@ -207,6 +205,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::SDIVREM); setTargetDAGCombine(ISD::UDIVREM); setTargetDAGCombine(ISD::SETCC); + setTargetDAGCombine(ISD::AND); + setTargetDAGCombine(ISD::OR); setMinFunctionAlignment(2); @@ -522,6 +522,102 @@ static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG, return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc()); } +static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + // Pattern match EXT. + // $dst = and ((sra or srl) $src , pos), (2**size - 1) + // => ext $dst, $src, size, pos + if (DCI.isBeforeLegalizeOps() || !Subtarget->isMips32r2()) + return SDValue(); + + SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1); + + // Op's first operand must be a shift right. + if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL) + return SDValue(); + + // The second operand of the shift must be an immediate. + uint64_t Pos; + ConstantSDNode *CN; + if (!(CN = dyn_cast(ShiftRight.getOperand(1)))) + return SDValue(); + + Pos = CN->getZExtValue(); + + uint64_t SMPos, SMSize; + // Op's second operand must be a shifted mask. + if (!(CN = dyn_cast(Mask)) || + !IsShiftedMask(CN->getZExtValue(), 32, SMPos, SMSize)) + return SDValue(); + + // Return if the shifted mask does not start at bit 0 or the sum of its size + // and Pos exceeds the word's size. + if (SMPos != 0 || Pos + SMSize > 32) + return SDValue(); + + return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), MVT::i32, + ShiftRight.getOperand(0), + DAG.getConstant(SMSize, MVT::i32), + DAG.getConstant(Pos, MVT::i32)); +} + +static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + // Pattern match INS. + // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), + // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 + // => ins $dst, $src, size, pos, $src1 + if (DCI.isBeforeLegalizeOps() || !Subtarget->isMips32r2()) + return SDValue(); + + SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); + uint64_t SMPos0, SMSize0, SMPos1, SMSize1; + ConstantSDNode *CN; + + // See if Op's first operand matches (and $src1 , mask0). + if (And0.getOpcode() != ISD::AND) + return SDValue(); + + if (!(CN = dyn_cast(And0.getOperand(1))) || + !IsShiftedMask(~CN->getZExtValue(), 32, SMPos0, SMSize0)) + return SDValue(); + + // See if Op's second operand matches (and (shl $src, pos), mask1). + if (And1.getOpcode() != ISD::AND) + return SDValue(); + + if (!(CN = dyn_cast(And1.getOperand(1))) || + !IsShiftedMask(CN->getZExtValue(), CN->getValueSizeInBits(0), SMPos1, + SMSize1)) + return SDValue(); + + // The shift masks must have the same position and size. + if (SMPos0 != SMPos1 || SMSize0 != SMSize1) + return SDValue(); + + SDValue Shl = And1.getOperand(0); + if (Shl.getOpcode() != ISD::SHL) + return SDValue(); + + if (!(CN = dyn_cast(Shl.getOperand(1)))) + return SDValue(); + + unsigned Shamt = CN->getZExtValue(); + + // Return if the shift amount and the first bit position of mask are not the + // same. + if (Shamt != SMPos0) + return SDValue(); + + return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), MVT::i32, + Shl.getOperand(0), + DAG.getConstant(SMSize0, MVT::i32), + DAG.getConstant(SMPos0, MVT::i32), + And0.getOperand(0)); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -538,6 +634,10 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return PerformDivRemCombine(N, DAG, DCI, Subtarget); case ISD::SETCC: return PerformSETCCCombine(N, DAG, DCI, Subtarget); + case ISD::AND: + return PerformANDCombine(N, DAG, DCI, Subtarget); + case ISD::OR: + return PerformORCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -561,8 +661,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); - case ISD::AND: return LowerAND(Op, DAG); - case ISD::OR: return LowerOR(Op, DAG); } return SDValue(); } @@ -1580,98 +1678,6 @@ SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, DAG.getConstant(SType, MVT::i32)); } -SDValue MipsTargetLowering::LowerAND(SDValue Op, SelectionDAG& DAG) const { - // Pattern match EXT. - // $dst = and ((sra or srl) $src , pos), (2**size - 1) - // => ext $dst, $src, size, pos - if (!Subtarget->isMips32r2()) - return Op; - - SDValue ShiftRight = Op.getOperand(0), Mask = Op.getOperand(1); - - // Op's first operand must be a shift right. - if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL) - return Op; - - // The second operand of the shift must be an immediate. - uint64_t Pos; - ConstantSDNode *CN; - if (!(CN = dyn_cast(ShiftRight.getOperand(1)))) - return Op; - - Pos = CN->getZExtValue(); - - uint64_t SMPos, SMSize; - // Op's second operand must be a shifted mask. - if (!(CN = dyn_cast(Mask)) || - !IsShiftedMask(CN->getZExtValue(), 32, SMPos, SMSize)) - return Op; - - // Return if the shifted mask does not start at bit 0 or the sum of its size - // and Pos exceeds the word's size. - if (SMPos != 0 || Pos + SMSize > 32) - return Op; - - return DAG.getNode(MipsISD::Ext, Op.getDebugLoc(), MVT::i32, - ShiftRight.getOperand(0), - DAG.getConstant(SMSize, MVT::i32), - DAG.getConstant(Pos, MVT::i32)); -} - -SDValue MipsTargetLowering::LowerOR(SDValue Op, SelectionDAG& DAG) const { - // Pattern match INS. - // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), - // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 - // => ins $dst, $src, size, pos - if (!Subtarget->isMips32r2()) - return Op; - - SDValue And0 = Op.getOperand(0), And1 = Op.getOperand(1); - uint64_t SMPos0, SMSize0, SMPos1, SMSize1; - ConstantSDNode *CN; - - // See if Op's first operand matches (and $src1 , mask0). - if (And0.getOpcode() != ISD::AND) - return Op; - - if (!(CN = dyn_cast(And0.getOperand(1))) || - !IsShiftedMask(~CN->getZExtValue(), 32, SMPos0, SMSize0)) - return Op; - - // See if Op's second operand matches (and (shl $src, pos), mask1). - if (And1.getOpcode() != ISD::AND) - return Op; - - if (!(CN = dyn_cast(And1.getOperand(1))) || - !IsShiftedMask(CN->getZExtValue(), CN->getValueSizeInBits(0), SMPos1, - SMSize1)) - return Op; - - // The shift masks must have the same position and size. - if (SMPos0 != SMPos1 || SMSize0 != SMSize1) - return Op; - - SDValue Shl = And1.getOperand(0); - if (Shl.getOpcode() != ISD::SHL) - return Op; - - if (!(CN = dyn_cast(Shl.getOperand(1)))) - return Op; - - unsigned Shamt = CN->getZExtValue(); - - // Return if the shift amount and the first bit position of mask are not the - // same. - if (Shamt != SMPos0) - return Op; - - return DAG.getNode(MipsISD::Ins, Op.getDebugLoc(), MVT::i32, - Shl.getOperand(0), - DAG.getConstant(SMSize0, MVT::i32), - DAG.getConstant(SMPos0, MVT::i32), - And0.getOperand(0)); -} - //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 7e4c1f400bd8505c6cc157712d6febab4702fef7..ac3df7d3cb7005d3cf0f7e000f86d9798f510f86 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -137,8 +137,6 @@ namespace llvm { SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; - SDValue LowerAND(SDValue Op, SelectionDAG& DAG) const; - SDValue LowerOR(SDValue Op, SelectionDAG& DAG) const; virtual SDValue LowerFormalArguments(SDValue Chain,