diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index ddd8549a09f..87c6cf0f90a 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -455,7 +455,10 @@ static bool MaskedValueIsZero(const SDOperand &Op, uint64_t Mask, // Bit counting instructions can not set the high bits of the result // register. The max number of bits sets depends on the input. return (Mask & (MVT::getSizeInBits(Op.getValueType())*2-1)) == 0; - default: break; + default: + if (Op.getOpcode() >= ISD::BUILTIN_OP_END) + return TLI.isMaskedValueZeroForTargetNode(Op, Mask); + break; } return false; } diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 8e9524ef1e3..e46826e2fae 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -125,3 +125,8 @@ void TargetLowering::computeRegisterProperties() { const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { return NULL; } + +bool isMaskedValueZeroForTargetNode(const SDOperand &Op, + uint64_t Mask) const { + return false; +} diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index ff0cc811a3c..1a926d076e9 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -172,6 +172,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { break; case ISD::GlobalAddress: + case ISD::TargetGlobalAddress: if (AM.GV == 0) { AM.GV = cast(N)->getGlobal(); return false; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 61d3aeeedb9..456a2541f8b 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -122,6 +122,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::SETCC , MVT::i8 , Custom); setOperationAction(ISD::SETCC , MVT::i16 , Custom); setOperationAction(ISD::SETCC , MVT::i32 , Custom); + setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom); } // We don't have line number support yet. @@ -1051,6 +1052,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { } case ISD::GlobalAddress: GlobalValue *GV = cast(Op)->getGlobal(); + SDOperand GVOp = DAG.getTargetGlobalAddress(GV, getPointerTy()); // For Darwin, external and weak symbols are indirect, so we want to load // the value at address GV, not the value of GV itself. This means that // the GlobalAddress must be in the base or index register of the address, @@ -1058,10 +1060,10 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { if (getTargetMachine(). getSubtarget().getIndirectExternAndWeakGlobals() && (GV->hasWeakLinkage() || GV->isExternal())) - return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Op, - DAG.getSrcValue(NULL)); + return DAG.getLoad(MVT::i32, DAG.getEntryNode(), + GVOp, DAG.getSrcValue(NULL)); else - return Op; + return GVOp; break; } } @@ -1086,3 +1088,18 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG"; } } + +bool X86TargetLowering::isMaskedValueZeroForTargetNode(const SDOperand &Op, + uint64_t Mask) const { + + unsigned Opc = Op.getOpcode(); + + switch (Opc) { + default: + assert(Opc >= ISD::BUILTIN_OP_END && "Expected a target specific node"); + break; + case X86ISD::SETCC: return (Mask & 1) == 0; + } + + return false; +} diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index c15e009c90a..8ebbe6161b7 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -155,6 +155,12 @@ namespace llvm { /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; + /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to + /// be zero. Op is expected to be a target specific node. Used by DAG + /// combiner. + virtual bool isMaskedValueZeroForTargetNode(const SDOperand &Op, + uint64_t Mask) const; + SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG); private: diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 074c86d0815..0b0ed822e1a 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -98,8 +98,8 @@ def brtarget : Operand; // Define X86 specific addressing mode. def addr : ComplexPattern; def leaaddr : ComplexPattern; + [add, frameindex, constpool, + globaladdr, tglobaladdr, externalsym]>; //===----------------------------------------------------------------------===// // X86 Instruction Format Definitions.