mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 22:04:55 +00:00
Move pattern matching for EXT and INS to post-legalization DAGCombine per Bruno's comment.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137831 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
83e3f67fb6
commit
77b85b6474
@ -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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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<ConstantSDNode>(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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user