More progress on promoting i16 operations to i32 for x86. Work in progress.

llvm-svn: 101808
This commit is contained in:
Evan Cheng 2010-04-19 19:29:22 +00:00
parent 1e95790fd4
commit e19aa5cc52
2 changed files with 153 additions and 17 deletions

View File

@ -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();
} }

View File

@ -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;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//