From e19aa5cc52fa05dcbfbcd9767797d0ce1631b2ec Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 19 Apr 2010 19:29:22 +0000 Subject: [PATCH] More progress on promoting i16 operations to i32 for x86. Work in progress. llvm-svn: 101808 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 127 ++++++++++++++++-- llvm/lib/Target/X86/X86ISelLowering.cpp | 43 ++++-- 2 files changed, 153 insertions(+), 17 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5fe67b5d3b95..f15c121668f7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -130,6 +130,8 @@ namespace { bool CombineToPostIndexedLoadStore(SDNode *N); SDValue PromoteIntBinOp(SDValue Op); + SDValue PromoteExtend(SDValue Op); + bool PromoteLoad(SDValue Op); /// combine - call the node-specific routine that knows how to fold each /// particular type of node. If that doesn't do anything, try the @@ -167,6 +169,8 @@ namespace { SDValue visitSHL(SDNode *N); SDValue visitSRA(SDNode *N); SDValue visitSRL(SDNode *N); + SDValue visitROTL(SDNode *N); + SDValue visitROTR(SDNode *N); SDValue visitCTLZ(SDNode *N); SDValue visitCTTZ(SDNode *N); SDValue visitCTPOP(SDNode *N); @@ -633,25 +637,44 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { 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, const TargetLowering &TLI) { + DebugLoc dl = Op.getDebugLoc(); if (LoadSDNode *LD = dyn_cast(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->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment()); } - unsigned Opc = ISD::ANY_EXTEND; - if (Op.getOpcode() == ISD::Constant) + unsigned Opc = Op.getOpcode(); + 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 // matter in theory which one we pick, but this tends to give better code? // See DAGTypeLegalizer::PromoteIntRes_Constant. - Opc = Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; - if (!TLI.isOperationLegal(Opc, PVT)) + ExtOpc = + Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + if (!TLI.isOperationLegal(ExtOpc, PVT)) 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, @@ -727,6 +750,80 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) { 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(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 @@ -856,6 +953,8 @@ SDValue DAGCombiner::visit(SDNode *N) { case ISD::SHL: return visitSHL(N); case ISD::SRA: return visitSRA(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::CTTZ: return visitCTTZ(N); case ISD::CTPOP: return visitCTPOP(N); @@ -2975,6 +3074,14 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { 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 N0 = N->getOperand(0); EVT VT = N->getValueType(0); @@ -3369,7 +3476,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { DAG.SignBitIsZero(N0)) return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { @@ -3532,7 +3639,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { N0.getOperand(1))); } - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { @@ -3668,7 +3775,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { return SCC; } - return SDValue(); + return PromoteExtend(SDValue(N, 0)); } /// 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)) return SDValue(N, 0); + if (PromoteLoad(SDValue(N, 0))) + return SDValue(N, 0); return SDValue(); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index ef54276ecd38..f1fbf4a30d09 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -9966,9 +9966,15 @@ bool X86TargetLowering::isTypeDesirableForOp(unsigned Opc, EVT VT) const { switch (Opc) { default: return true; + case ISD::LOAD: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: case ISD::SHL: case ISD::SRA: case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: case ISD::SUB: case ISD::ADD: case ISD::MUL: @@ -9990,27 +9996,47 @@ bool X86TargetLowering::IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const { if (VT != MVT::i16) return false; - bool Commute = true; + bool Promote = false; + bool Commute = false; switch (Op.getOpcode()) { - default: return false; + default: break; + case ISD::LOAD: { + LoadSDNode *LD = cast(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::SRA: - case ISD::SRL: { + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: { SDValue N0 = Op.getOperand(0); // Look out for (store (shl (load), x)). if (isa(N0) && N0.hasOneUse() && Op.hasOneUse() && Op.getNode()->use_begin()->getOpcode() == ISD::STORE) return false; + Promote = true; break; } - case ISD::SUB: - Commute = false; - // fallthrough case ISD::ADD: case ISD::MUL: case ISD::AND: case ISD::OR: - case ISD::XOR: { + case ISD::XOR: + Commute = true; + // fallthrough + case ISD::SUB: { SDValue N0 = Op.getOperand(0); SDValue N1 = Op.getOperand(1); if (!Commute && isa(N1)) @@ -10020,11 +10046,12 @@ bool X86TargetLowering::IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const { return false; if ((isa(N1) && N1.hasOneUse()) && !isa(N0)) return false; + Promote = true; } } PVT = MVT::i32; - return true; + return Promote; } //===----------------------------------------------------------------------===//