More progress on promoting i16 operations to i32 for x86. Work in progress.
llvm-svn: 101808
This commit is contained in:
parent
1e95790fd4
commit
e19aa5cc52
|
@ -130,6 +130,8 @@ namespace {
|
||||||
bool CombineToPostIndexedLoadStore(SDNode *N);
|
bool CombineToPostIndexedLoadStore(SDNode *N);
|
||||||
|
|
||||||
SDValue PromoteIntBinOp(SDValue Op);
|
SDValue PromoteIntBinOp(SDValue Op);
|
||||||
|
SDValue PromoteExtend(SDValue Op);
|
||||||
|
bool PromoteLoad(SDValue Op);
|
||||||
|
|
||||||
/// combine - call the node-specific routine that knows how to fold each
|
/// combine - call the node-specific routine that knows how to fold each
|
||||||
/// particular type of node. If that doesn't do anything, try the
|
/// particular type of node. If that doesn't do anything, try the
|
||||||
|
@ -167,6 +169,8 @@ namespace {
|
||||||
SDValue visitSHL(SDNode *N);
|
SDValue visitSHL(SDNode *N);
|
||||||
SDValue visitSRA(SDNode *N);
|
SDValue visitSRA(SDNode *N);
|
||||||
SDValue visitSRL(SDNode *N);
|
SDValue visitSRL(SDNode *N);
|
||||||
|
SDValue visitROTL(SDNode *N);
|
||||||
|
SDValue visitROTR(SDNode *N);
|
||||||
SDValue visitCTLZ(SDNode *N);
|
SDValue visitCTLZ(SDNode *N);
|
||||||
SDValue visitCTTZ(SDNode *N);
|
SDValue visitCTTZ(SDNode *N);
|
||||||
SDValue visitCTPOP(SDNode *N);
|
SDValue visitCTPOP(SDNode *N);
|
||||||
|
@ -633,25 +637,44 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDValue SExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
||||||
|
const TargetLowering &TLI);
|
||||||
|
static SDValue ZExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
||||||
|
const TargetLowering &TLI);
|
||||||
|
|
||||||
static SDValue PromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
static SDValue PromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
||||||
const TargetLowering &TLI) {
|
const TargetLowering &TLI) {
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) {
|
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) {
|
||||||
return DAG.getExtLoad(ISD::EXTLOAD, Op.getDebugLoc(), PVT,
|
ISD::LoadExtType ExtType =
|
||||||
|
ISD::isNON_EXTLoad(LD) ? ISD::EXTLOAD : LD->getExtensionType();
|
||||||
|
return DAG.getExtLoad(ExtType, dl, PVT,
|
||||||
LD->getChain(), LD->getBasePtr(),
|
LD->getChain(), LD->getBasePtr(),
|
||||||
LD->getSrcValue(), LD->getSrcValueOffset(),
|
LD->getSrcValue(), LD->getSrcValueOffset(),
|
||||||
LD->getMemoryVT(), LD->isVolatile(),
|
LD->getMemoryVT(), LD->isVolatile(),
|
||||||
LD->isNonTemporal(), LD->getAlignment());
|
LD->isNonTemporal(), LD->getAlignment());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Opc = ISD::ANY_EXTEND;
|
unsigned Opc = Op.getOpcode();
|
||||||
if (Op.getOpcode() == ISD::Constant)
|
if (Opc == ISD::AssertSext)
|
||||||
|
return DAG.getNode(ISD::AssertSext, dl, PVT,
|
||||||
|
SExtPromoteOperand(Op.getOperand(0), PVT, DAG, TLI),
|
||||||
|
Op.getOperand(1));
|
||||||
|
else if (Opc == ISD::AssertZext)
|
||||||
|
return DAG.getNode(ISD::AssertZext, dl, PVT,
|
||||||
|
ZExtPromoteOperand(Op.getOperand(0), PVT, DAG, TLI),
|
||||||
|
Op.getOperand(1));
|
||||||
|
|
||||||
|
unsigned ExtOpc = ISD::ANY_EXTEND;
|
||||||
|
if (Opc == ISD::Constant)
|
||||||
// Zero extend things like i1, sign extend everything else. It shouldn't
|
// Zero extend things like i1, sign extend everything else. It shouldn't
|
||||||
// matter in theory which one we pick, but this tends to give better code?
|
// matter in theory which one we pick, but this tends to give better code?
|
||||||
// See DAGTypeLegalizer::PromoteIntRes_Constant.
|
// See DAGTypeLegalizer::PromoteIntRes_Constant.
|
||||||
Opc = Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
|
ExtOpc =
|
||||||
if (!TLI.isOperationLegal(Opc, PVT))
|
Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
|
||||||
|
if (!TLI.isOperationLegal(ExtOpc, PVT))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
return DAG.getNode(Opc, Op.getDebugLoc(), PVT, Op);
|
return DAG.getNode(ExtOpc, dl, PVT, Op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue SExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
static SDValue SExtPromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG,
|
||||||
|
@ -727,6 +750,80 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) {
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDValue DAGCombiner::PromoteExtend(SDValue Op) {
|
||||||
|
if (!LegalOperations)
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
EVT VT = Op.getValueType();
|
||||||
|
if (VT.isVector() || !VT.isInteger())
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
// If operation type is 'undesirable', e.g. i16 on x86, consider
|
||||||
|
// promoting it.
|
||||||
|
unsigned Opc = Op.getOpcode();
|
||||||
|
if (TLI.isTypeDesirableForOp(Opc, VT))
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
EVT PVT = VT;
|
||||||
|
// Consult target whether it is a good idea to promote this operation and
|
||||||
|
// what's the right type to promote it to.
|
||||||
|
if (TLI.IsDesirableToPromoteOp(Op, PVT)) {
|
||||||
|
assert(PVT != VT && "Don't know what type to promote to!");
|
||||||
|
// fold (aext (aext x)) -> (aext x)
|
||||||
|
// fold (aext (zext x)) -> (zext x)
|
||||||
|
// fold (aext (sext x)) -> (sext x)
|
||||||
|
return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), VT, Op.getOperand(0));
|
||||||
|
}
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DAGCombiner::PromoteLoad(SDValue Op) {
|
||||||
|
if (!LegalOperations)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EVT VT = Op.getValueType();
|
||||||
|
if (VT.isVector() || !VT.isInteger())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If operation type is 'undesirable', e.g. i16 on x86, consider
|
||||||
|
// promoting it.
|
||||||
|
unsigned Opc = Op.getOpcode();
|
||||||
|
if (TLI.isTypeDesirableForOp(Opc, VT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EVT PVT = VT;
|
||||||
|
// Consult target whether it is a good idea to promote this operation and
|
||||||
|
// what's the right type to promote it to.
|
||||||
|
if (TLI.IsDesirableToPromoteOp(Op, PVT)) {
|
||||||
|
assert(PVT != VT && "Don't know what type to promote to!");
|
||||||
|
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
SDNode *N = Op.getNode();
|
||||||
|
LoadSDNode *LD = cast<LoadSDNode>(N);
|
||||||
|
ISD::LoadExtType ExtType =
|
||||||
|
ISD::isNON_EXTLoad(LD) ? ISD::EXTLOAD : LD->getExtensionType();
|
||||||
|
SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT,
|
||||||
|
LD->getChain(), LD->getBasePtr(),
|
||||||
|
LD->getSrcValue(), LD->getSrcValueOffset(),
|
||||||
|
LD->getMemoryVT(), LD->isVolatile(),
|
||||||
|
LD->isNonTemporal(), LD->getAlignment());
|
||||||
|
SDValue Result = DAG.getNode(ISD::TRUNCATE, dl, VT, NewLD);
|
||||||
|
|
||||||
|
DEBUG(dbgs() << "\nReplacing.x ";
|
||||||
|
N->dump(&DAG);
|
||||||
|
dbgs() << "\nWith: ";
|
||||||
|
Result.getNode()->dump(&DAG);
|
||||||
|
dbgs() << '\n');
|
||||||
|
WorkListRemover DeadNodes(*this);
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result, &DeadNodes);
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), NewLD.getValue(1), &DeadNodes);
|
||||||
|
removeFromWorkList(N);
|
||||||
|
DAG.DeleteNode(N);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Main DAG Combiner implementation
|
// Main DAG Combiner implementation
|
||||||
|
@ -856,6 +953,8 @@ SDValue DAGCombiner::visit(SDNode *N) {
|
||||||
case ISD::SHL: return visitSHL(N);
|
case ISD::SHL: return visitSHL(N);
|
||||||
case ISD::SRA: return visitSRA(N);
|
case ISD::SRA: return visitSRA(N);
|
||||||
case ISD::SRL: return visitSRL(N);
|
case ISD::SRL: return visitSRL(N);
|
||||||
|
case ISD::ROTL: return visitROTL(N);
|
||||||
|
case ISD::ROTR: return visitROTR(N);
|
||||||
case ISD::CTLZ: return visitCTLZ(N);
|
case ISD::CTLZ: return visitCTLZ(N);
|
||||||
case ISD::CTTZ: return visitCTTZ(N);
|
case ISD::CTTZ: return visitCTTZ(N);
|
||||||
case ISD::CTPOP: return visitCTPOP(N);
|
case ISD::CTPOP: return visitCTPOP(N);
|
||||||
|
@ -2975,6 +3074,14 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
|
||||||
return PromoteIntBinOp(SDValue(N, 0));
|
return PromoteIntBinOp(SDValue(N, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDValue DAGCombiner::visitROTL(SDNode *N) {
|
||||||
|
return PromoteIntBinOp(SDValue(N, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDValue DAGCombiner::visitROTR(SDNode *N) {
|
||||||
|
return PromoteIntBinOp(SDValue(N, 0));
|
||||||
|
}
|
||||||
|
|
||||||
SDValue DAGCombiner::visitCTLZ(SDNode *N) {
|
SDValue DAGCombiner::visitCTLZ(SDNode *N) {
|
||||||
SDValue N0 = N->getOperand(0);
|
SDValue N0 = N->getOperand(0);
|
||||||
EVT VT = N->getValueType(0);
|
EVT VT = N->getValueType(0);
|
||||||
|
@ -3369,7 +3476,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
|
||||||
DAG.SignBitIsZero(N0))
|
DAG.SignBitIsZero(N0))
|
||||||
return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0);
|
return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0);
|
||||||
|
|
||||||
return SDValue();
|
return PromoteExtend(SDValue(N, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
|
SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
|
||||||
|
@ -3532,7 +3639,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
|
||||||
N0.getOperand(1)));
|
N0.getOperand(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDValue();
|
return PromoteExtend(SDValue(N, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
|
SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
|
||||||
|
@ -3668,7 +3775,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
|
||||||
return SCC;
|
return SCC;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDValue();
|
return PromoteExtend(SDValue(N, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GetDemandedBits - See if the specified operand can be simplified with the
|
/// GetDemandedBits - See if the specified operand can be simplified with the
|
||||||
|
@ -5270,6 +5377,8 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) {
|
||||||
if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
|
if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
|
||||||
return SDValue(N, 0);
|
return SDValue(N, 0);
|
||||||
|
|
||||||
|
if (PromoteLoad(SDValue(N, 0)))
|
||||||
|
return SDValue(N, 0);
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9966,9 +9966,15 @@ bool X86TargetLowering::isTypeDesirableForOp(unsigned Opc, EVT VT) const {
|
||||||
switch (Opc) {
|
switch (Opc) {
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
case ISD::LOAD:
|
||||||
|
case ISD::SIGN_EXTEND:
|
||||||
|
case ISD::ZERO_EXTEND:
|
||||||
|
case ISD::ANY_EXTEND:
|
||||||
case ISD::SHL:
|
case ISD::SHL:
|
||||||
case ISD::SRA:
|
case ISD::SRA:
|
||||||
case ISD::SRL:
|
case ISD::SRL:
|
||||||
|
case ISD::ROTL:
|
||||||
|
case ISD::ROTR:
|
||||||
case ISD::SUB:
|
case ISD::SUB:
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
case ISD::MUL:
|
case ISD::MUL:
|
||||||
|
@ -9990,27 +9996,47 @@ bool X86TargetLowering::IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const {
|
||||||
if (VT != MVT::i16)
|
if (VT != MVT::i16)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool Commute = true;
|
bool Promote = false;
|
||||||
|
bool Commute = false;
|
||||||
switch (Op.getOpcode()) {
|
switch (Op.getOpcode()) {
|
||||||
default: return false;
|
default: break;
|
||||||
|
case ISD::LOAD: {
|
||||||
|
LoadSDNode *LD = cast<LoadSDNode>(Op);
|
||||||
|
// If the non-extending load has a single use and it's not live out, then it
|
||||||
|
// might be folded.
|
||||||
|
if (LD->getExtensionType() == ISD::NON_EXTLOAD &&
|
||||||
|
Op.hasOneUse() &&
|
||||||
|
Op.getNode()->use_begin()->getOpcode() != ISD::CopyToReg)
|
||||||
|
return false;
|
||||||
|
Promote = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ISD::SIGN_EXTEND:
|
||||||
|
case ISD::ZERO_EXTEND:
|
||||||
|
case ISD::ANY_EXTEND:
|
||||||
|
Promote = true;
|
||||||
|
break;
|
||||||
case ISD::SHL:
|
case ISD::SHL:
|
||||||
case ISD::SRA:
|
case ISD::SRA:
|
||||||
case ISD::SRL: {
|
case ISD::SRL:
|
||||||
|
case ISD::ROTL:
|
||||||
|
case ISD::ROTR: {
|
||||||
SDValue N0 = Op.getOperand(0);
|
SDValue N0 = Op.getOperand(0);
|
||||||
// Look out for (store (shl (load), x)).
|
// Look out for (store (shl (load), x)).
|
||||||
if (isa<LoadSDNode>(N0) && N0.hasOneUse() &&
|
if (isa<LoadSDNode>(N0) && N0.hasOneUse() &&
|
||||||
Op.hasOneUse() && Op.getNode()->use_begin()->getOpcode() == ISD::STORE)
|
Op.hasOneUse() && Op.getNode()->use_begin()->getOpcode() == ISD::STORE)
|
||||||
return false;
|
return false;
|
||||||
|
Promote = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ISD::SUB:
|
|
||||||
Commute = false;
|
|
||||||
// fallthrough
|
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
case ISD::MUL:
|
case ISD::MUL:
|
||||||
case ISD::AND:
|
case ISD::AND:
|
||||||
case ISD::OR:
|
case ISD::OR:
|
||||||
case ISD::XOR: {
|
case ISD::XOR:
|
||||||
|
Commute = true;
|
||||||
|
// fallthrough
|
||||||
|
case ISD::SUB: {
|
||||||
SDValue N0 = Op.getOperand(0);
|
SDValue N0 = Op.getOperand(0);
|
||||||
SDValue N1 = Op.getOperand(1);
|
SDValue N1 = Op.getOperand(1);
|
||||||
if (!Commute && isa<LoadSDNode>(N1))
|
if (!Commute && isa<LoadSDNode>(N1))
|
||||||
|
@ -10020,11 +10046,12 @@ bool X86TargetLowering::IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const {
|
||||||
return false;
|
return false;
|
||||||
if ((isa<LoadSDNode>(N1) && N1.hasOneUse()) && !isa<ConstantSDNode>(N0))
|
if ((isa<LoadSDNode>(N1) && N1.hasOneUse()) && !isa<ConstantSDNode>(N0))
|
||||||
return false;
|
return false;
|
||||||
|
Promote = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PVT = MVT::i32;
|
PVT = MVT::i32;
|
||||||
return true;
|
return Promote;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
Loading…
Reference in New Issue