From d143bfe0a4035594a36105c09363613a558e6f4c Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 16 Apr 2010 06:14:10 +0000 Subject: [PATCH] Adding support for dag combiner to promote operations for profit. This requires target specific queries. For example, x86 should promote i16 to i32 when it does not impact load folding. x86 support is off by default. It can be enabled with -promote-16bit. Work in progress. llvm-svn: 101448 --- include/llvm/Target/TargetLowering.h | 7 ++++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 53 +++++++++++++++++++++--- lib/Target/X86/X86ISelLowering.cpp | 41 ++++++++++++++++++ lib/Target/X86/X86ISelLowering.h | 2 + 4 files changed, 97 insertions(+), 6 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 3ee87c8c956..fca24539066 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -880,6 +880,13 @@ public: /// more complex transformations. /// virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + /// PerformDAGCombinePromotion - This method query the target whether it is + /// beneficial for dag combiner to promote the specified node. If true, it + /// should return the desired promotion type by reference. + virtual bool PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const { + return false; + } //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index ec70a5ed572..5c53a7f6bd1 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -129,6 +129,7 @@ namespace { bool CombineToPreIndexedLoadStore(SDNode *N); bool CombineToPostIndexedLoadStore(SDNode *N); + SDValue PromoteIntBinOp(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 @@ -633,6 +634,46 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { return true; } +static SDValue PromoteOperand(SDValue Op, EVT PVT, SelectionDAG &DAG) { + unsigned Opc = ISD::ZERO_EXTEND; + if (Op.getOpcode() == 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. + if (Op.getValueType().isByteSized()) + Opc = ISD::SIGN_EXTEND; + } + return DAG.getNode(Opc, Op.getDebugLoc(), PVT, Op); +} + +/// PromoteIntBinOp - Promote the specified integer binary operation if the +/// target indicates it is beneficial. e.g. On x86, it's usually better to +/// promote i16 operations to i32 since i16 instructions are longer. +SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) { + if (!LegalOperations) + return SDValue(); + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return SDValue(); + + EVT PVT = VT; + if (TLI.PerformDAGCombinePromotion(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + + SDValue N0 = PromoteOperand(Op.getOperand(0), PVT, DAG); + AddToWorkList(N0.getNode()); + + SDValue N1 = PromoteOperand(Op.getOperand(1), PVT, DAG); + AddToWorkList(N1.getNode()); + + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ISD::TRUNCATE, dl, VT, + DAG.getNode(Op.getOpcode(), dl, PVT, N0, N1)); + } + return SDValue(); +} + //===----------------------------------------------------------------------===// // Main DAG Combiner implementation //===----------------------------------------------------------------------===// @@ -1112,7 +1153,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) { N0.getOperand(0).getOperand(1), N0.getOperand(1))); - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } SDValue DAGCombiner::visitADDC(SDNode *N) { @@ -1250,7 +1291,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { VT); } - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } SDValue DAGCombiner::visitMUL(SDNode *N) { @@ -1343,7 +1384,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) { if (RMUL.getNode() != 0) return RMUL; - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } SDValue DAGCombiner::visitSDIV(SDNode *N) { @@ -1987,7 +2028,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { } } - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } SDValue DAGCombiner::visitOR(SDNode *N) { @@ -2113,7 +2154,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) { if (SDNode *Rot = MatchRotate(N0, N1, N->getDebugLoc())) return SDValue(Rot, 0); - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } /// MatchRotateHalf - Match "(X shl/srl V1) & V2" where V2 may not be present. @@ -2422,7 +2463,7 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { SimplifyDemandedBits(SDValue(N, 0))) return SDValue(N, 0); - return SDValue(); + return PromoteIntBinOp(SDValue(N, 0)); } /// visitShiftByConstant - Handle transforms common to the three shifts, when diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 03b5942268a..2b8c5408e6c 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -64,6 +64,9 @@ DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX")); static cl::opt Disable16Bit("disable-16bit", cl::Hidden, cl::desc("Disable use of 16-bit instructions")); +static cl::opt +Promote16Bit("promote-16bit", cl::Hidden, + cl::desc("Promote 16-bit instructions")); // Forward declarations. static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, @@ -9906,6 +9909,44 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, return SDValue(); } +/// PerformDAGCombinePromotion - This method query the target whether it is +/// beneficial for dag combiner to promote the specified node. If true, it +/// should return the desired promotion type by reference. +bool X86TargetLowering::PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const { + if (!Promote16Bit) + return false; + + EVT VT = Op.getValueType(); + if (VT != MVT::i16) + return false; + + bool Commute = true; + switch (Op.getOpcode()) { + default: return false; + case ISD::SUB: + Commute = false; + // fallthrough + case ISD::ADD: + case ISD::MUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: { + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + if (!Commute && isa(N1)) + return false; + // Avoid disabling potential load folding opportunities. + if ((isa(N0) && N0.hasOneUse()) && !isa(N1)) + return false; + if ((isa(N1) && N1.hasOneUse()) && !isa(N0)) + return false; + } + } + + PVT = MVT::i32; + return true; +} + //===----------------------------------------------------------------------===// // X86 Inline Assembly Support //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 4e4ba48b1a7..7fa65cb4735 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -452,6 +452,8 @@ namespace llvm { virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + virtual bool PerformDAGCombinePromotion(SDValue Op, EVT &PVT) const; + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB, DenseMap *EM) const;