2005-01-07 15:47:09 +08:00
|
|
|
//===-- LegalizeDAG.cpp - Implement SelectionDAG::Legalize ----------------===//
|
2005-04-22 06:36:52 +08:00
|
|
|
//
|
2005-01-07 15:47:09 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 06:36:52 +08:00
|
|
|
//
|
2005-01-07 15:47:09 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the SelectionDAG::Legalize method.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2005-01-15 15:15:18 +08:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2006-12-15 03:17:33 +08:00
|
|
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
2007-12-31 12:13:23 +08:00
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2009-01-13 08:35:13 +08:00
|
|
|
#include "llvm/CodeGen/DwarfWriter.h"
|
|
|
|
#include "llvm/Analysis/DebugInfo.h"
|
2008-02-07 06:27:42 +08:00
|
|
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
2007-08-17 07:50:06 +08:00
|
|
|
#include "llvm/Target/TargetFrameInfo.h"
|
2005-01-07 15:47:09 +08:00
|
|
|
#include "llvm/Target/TargetLowering.h"
|
2005-01-11 13:57:22 +08:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2006-10-30 16:00:44 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2005-01-15 14:18:18 +08:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
Drop ISD::MEMSET, ISD::MEMMOVE, and ISD::MEMCPY, which are not Legal
on any current target and aren't optimized in DAGCombiner. Instead
of using intermediate nodes, expand the operations, choosing between
simple loads/stores, target-specific code, and library calls,
immediately.
Previously, the code to emit optimized code for these operations
was only used at initial SelectionDAG construction time; now it is
used at all times. This fixes some cases where rep;movs was being
used for small copies where simple loads/stores would be better.
This also cleans up code that checks for alignments less than 4;
let the targets make that decision instead of doing it in
target-independent code. This allows x86 to use rep;movs in
low-alignment cases.
Also, this fixes a bug that resulted in the use of rep;stos for
memsets of 0 with non-constant memory size when the alignment was
at least 4. It's better to use the library in this case, which
can be significantly faster when the size is large.
This also preserves more SourceValue information when memory
intrinsics are lowered into simple loads/stores.
llvm-svn: 49572
2008-04-12 12:36:06 +08:00
|
|
|
#include "llvm/Target/TargetSubtarget.h"
|
2005-05-14 02:50:42 +08:00
|
|
|
#include "llvm/CallingConv.h"
|
2005-01-07 15:47:09 +08:00
|
|
|
#include "llvm/Constants.h"
|
2007-01-20 05:13:56 +08:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2009-02-17 09:04:54 +08:00
|
|
|
#include "llvm/Function.h"
|
2009-01-13 08:35:13 +08:00
|
|
|
#include "llvm/GlobalVariable.h"
|
2006-04-02 11:07:27 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2006-08-27 20:54:02 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2007-10-28 20:59:45 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2007-02-03 09:12:36 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2006-08-08 09:09:31 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2007-02-04 08:27:56 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2006-03-24 09:17:21 +08:00
|
|
|
#include <map>
|
2005-01-07 15:47:09 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and
|
|
|
|
/// hacks on it until the target machine can handle it. This involves
|
|
|
|
/// eliminating value sizes the machine cannot handle (promoting small sizes to
|
|
|
|
/// large sizes or splitting up large values into small values) as well as
|
|
|
|
/// eliminating operations the machine cannot handle.
|
|
|
|
///
|
|
|
|
/// This code also does a small amount of optimization and recognition of idioms
|
|
|
|
/// as part of its processing. For example, if a target does not support a
|
|
|
|
/// 'setcc' instruction efficiently, but does support 'brcc' instruction, this
|
|
|
|
/// will attempt merge setcc and brc instructions into brcc's.
|
|
|
|
///
|
|
|
|
namespace {
|
2006-06-29 05:58:30 +08:00
|
|
|
class VISIBILITY_HIDDEN SelectionDAGLegalize {
|
2005-01-07 15:47:09 +08:00
|
|
|
TargetLowering &TLI;
|
|
|
|
SelectionDAG &DAG;
|
2009-04-30 07:29:43 +08:00
|
|
|
CodeGenOpt::Level OptLevel;
|
2005-01-07 15:47:09 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Libcall insertion helpers.
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
/// LastCALLSEQ_END - This keeps track of the CALLSEQ_END node that has been
|
|
|
|
/// legalized. We use this to ensure that calls are properly serialized
|
|
|
|
/// against each other, including inserted libcalls.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue LastCALLSEQ_END;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
/// IsLegalizingCall - This member is used *only* for purposes of providing
|
2009-02-18 06:15:04 +08:00
|
|
|
/// helpful assertions that a libcall isn't created while another call is
|
2006-02-13 17:18:02 +08:00
|
|
|
/// being legalized (which could lead to non-serialized call sequences).
|
|
|
|
bool IsLegalizingCall;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-01-07 15:47:09 +08:00
|
|
|
enum LegalizeAction {
|
2006-01-29 16:42:06 +08:00
|
|
|
Legal, // The target natively supports this operation.
|
|
|
|
Promote, // This operation should be executed in a larger type.
|
2006-05-25 01:04:05 +08:00
|
|
|
Expand // Try to expand this to other ops, otherwise use a libcall.
|
2005-01-07 15:47:09 +08:00
|
|
|
};
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-01-07 15:47:09 +08:00
|
|
|
/// ValueTypeActions - This is a bitvector that contains two bits for each
|
|
|
|
/// value type, where the two bits correspond to the LegalizeAction enum.
|
|
|
|
/// This can be queried with "getTypeAction(VT)".
|
2006-01-29 16:42:06 +08:00
|
|
|
TargetLowering::ValueTypeActionImpl ValueTypeActions;
|
2005-01-07 15:47:09 +08:00
|
|
|
|
|
|
|
/// LegalizedNodes - For nodes that are of legal width, and that have more
|
|
|
|
/// than one use, this map indicates what regularized operand to use. This
|
|
|
|
/// allows us to avoid legalizing the same thing more than once.
|
2008-07-28 05:46:04 +08:00
|
|
|
DenseMap<SDValue, SDValue> LegalizedNodes;
|
2005-01-07 15:47:09 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
void AddLegalizedOperand(SDValue From, SDValue To) {
|
2005-12-20 08:53:54 +08:00
|
|
|
LegalizedNodes.insert(std::make_pair(From, To));
|
|
|
|
// If someone requests legalization of the new node, return itself.
|
|
|
|
if (From != To)
|
|
|
|
LegalizedNodes.insert(std::make_pair(To, To));
|
2005-01-08 06:28:47 +08:00
|
|
|
}
|
|
|
|
|
2005-01-07 15:47:09 +08:00
|
|
|
public:
|
2009-05-24 10:46:31 +08:00
|
|
|
SelectionDAGLegalize(SelectionDAG &DAG, CodeGenOpt::Level ol);
|
2005-01-07 15:47:09 +08:00
|
|
|
|
|
|
|
/// getTypeAction - Return how we should legalize values of this type, either
|
|
|
|
/// it is already legal or we need to expand it into multiple registers of
|
|
|
|
/// smaller integer type, or we need to promote it to a larger type.
|
2008-06-06 20:08:01 +08:00
|
|
|
LegalizeAction getTypeAction(MVT VT) const {
|
2006-01-29 16:42:06 +08:00
|
|
|
return (LegalizeAction)ValueTypeActions.getTypeAction(VT);
|
2005-01-07 15:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// isTypeLegal - Return true if this type is legal on this target.
|
|
|
|
///
|
2008-06-06 20:08:01 +08:00
|
|
|
bool isTypeLegal(MVT VT) const {
|
2005-01-07 15:47:09 +08:00
|
|
|
return getTypeAction(VT) == Legal;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LegalizeDAG();
|
|
|
|
|
2006-01-28 15:39:30 +08:00
|
|
|
private:
|
2006-03-18 09:44:44 +08:00
|
|
|
/// LegalizeOp - We know that the specified value has a legal type.
|
|
|
|
/// Recursively ensure that the operands have legal types, then return the
|
|
|
|
/// result.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue LegalizeOp(SDValue O);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-04-26 02:07:40 +08:00
|
|
|
/// PerformInsertVectorEltInMemory - Some target cannot handle a variable
|
|
|
|
/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it
|
|
|
|
/// is necessary to spill the vector being inserted into to memory, perform
|
|
|
|
/// the insert there, and then read the result back.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val,
|
2009-05-27 10:16:40 +08:00
|
|
|
SDValue Idx, DebugLoc dl);
|
|
|
|
SDValue ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val,
|
|
|
|
SDValue Idx, DebugLoc dl);
|
2007-10-12 07:57:53 +08:00
|
|
|
|
2009-04-29 13:20:52 +08:00
|
|
|
/// ShuffleWithNarrowerEltType - Return a vector shuffle operation which
|
|
|
|
/// performs the same shuffe in terms of order or result bytes, but on a type
|
|
|
|
/// whose vector element type is narrower than the original shuffle type.
|
|
|
|
/// e.g. <v4i32> <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3>
|
|
|
|
SDValue ShuffleWithNarrowerEltType(MVT NVT, MVT VT, DebugLoc dl,
|
|
|
|
SDValue N1, SDValue N2,
|
|
|
|
SmallVectorImpl<int> &Mask) const;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-07-27 07:55:56 +08:00
|
|
|
bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest,
|
2007-02-04 08:27:56 +08:00
|
|
|
SmallPtrSet<SDNode*, 32> &NodesLeadingTo);
|
2006-02-13 17:18:02 +08:00
|
|
|
|
2009-02-03 04:41:04 +08:00
|
|
|
void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC,
|
|
|
|
DebugLoc dl);
|
|
|
|
void LegalizeSetCCCondCode(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC,
|
|
|
|
DebugLoc dl);
|
|
|
|
void LegalizeSetCC(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC,
|
|
|
|
DebugLoc dl) {
|
|
|
|
LegalizeSetCCOperands(LHS, RHS, CC, dl);
|
|
|
|
LegalizeSetCCCondCode(VT, LHS, RHS, CC, dl);
|
2008-10-15 10:05:31 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2009-05-27 10:21:29 +08:00
|
|
|
SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned);
|
2009-05-27 11:33:44 +08:00
|
|
|
SDValue ExpandFPLibCall(SDNode *Node, RTLIB::Libcall Call_F32,
|
|
|
|
RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80,
|
|
|
|
RTLIB::Libcall Call_PPCF128);
|
|
|
|
SDValue ExpandIntLibCall(SDNode *Node, bool isSigned, RTLIB::Libcall Call_I16,
|
|
|
|
RTLIB::Libcall Call_I32, RTLIB::Libcall Call_I64,
|
|
|
|
RTLIB::Libcall Call_I128);
|
2008-07-28 05:46:04 +08:00
|
|
|
|
2009-02-03 06:12:50 +08:00
|
|
|
SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT, DebugLoc dl);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ExpandBUILD_VECTOR(SDNode *Node);
|
|
|
|
SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node);
|
2009-05-27 20:20:41 +08:00
|
|
|
SDValue ExpandDBG_STOPPOINT(SDNode *Node);
|
|
|
|
void ExpandDYNAMIC_STACKALLOC(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results);
|
|
|
|
SDValue ExpandFCOPYSIGN(SDNode *Node);
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, MVT DestVT,
|
|
|
|
DebugLoc dl);
|
|
|
|
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned,
|
|
|
|
DebugLoc dl);
|
|
|
|
SDValue PromoteLegalFP_TO_INT(SDValue LegalOp, MVT DestVT, bool isSigned,
|
|
|
|
DebugLoc dl);
|
2008-07-28 05:46:04 +08:00
|
|
|
|
2009-02-03 06:12:50 +08:00
|
|
|
SDValue ExpandBSWAP(SDValue Op, DebugLoc dl);
|
|
|
|
SDValue ExpandBitCount(unsigned Opc, SDValue Op, DebugLoc dl);
|
2008-07-28 05:46:04 +08:00
|
|
|
|
2009-05-24 06:37:25 +08:00
|
|
|
SDValue ExpandExtractFromVectorThroughStack(SDValue Op);
|
2009-05-27 09:25:56 +08:00
|
|
|
|
|
|
|
void ExpandNode(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
|
|
|
void PromoteNode(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2005-01-07 15:47:09 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2009-04-29 13:20:52 +08:00
|
|
|
/// ShuffleWithNarrowerEltType - Return a vector shuffle operation which
|
|
|
|
/// performs the same shuffe in terms of order or result bytes, but on a type
|
|
|
|
/// whose vector element type is narrower than the original shuffle type.
|
2009-04-28 02:41:29 +08:00
|
|
|
/// e.g. <v4i32> <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3>
|
2009-04-29 13:20:52 +08:00
|
|
|
SDValue
|
|
|
|
SelectionDAGLegalize::ShuffleWithNarrowerEltType(MVT NVT, MVT VT, DebugLoc dl,
|
|
|
|
SDValue N1, SDValue N2,
|
2009-04-28 02:41:29 +08:00
|
|
|
SmallVectorImpl<int> &Mask) const {
|
|
|
|
MVT EltVT = NVT.getVectorElementType();
|
2009-04-29 13:20:52 +08:00
|
|
|
unsigned NumMaskElts = VT.getVectorNumElements();
|
|
|
|
unsigned NumDestElts = NVT.getVectorNumElements();
|
2009-04-28 02:41:29 +08:00
|
|
|
unsigned NumEltsGrowth = NumDestElts / NumMaskElts;
|
|
|
|
|
|
|
|
assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!");
|
|
|
|
|
|
|
|
if (NumEltsGrowth == 1)
|
|
|
|
return DAG.getVectorShuffle(NVT, dl, N1, N2, &Mask[0]);
|
|
|
|
|
|
|
|
SmallVector<int, 8> NewMask;
|
2009-04-29 13:20:52 +08:00
|
|
|
for (unsigned i = 0; i != NumMaskElts; ++i) {
|
2009-04-28 02:41:29 +08:00
|
|
|
int Idx = Mask[i];
|
|
|
|
for (unsigned j = 0; j != NumEltsGrowth; ++j) {
|
|
|
|
if (Idx < 0)
|
|
|
|
NewMask.push_back(-1);
|
|
|
|
else
|
|
|
|
NewMask.push_back(Idx * NumEltsGrowth + j);
|
2006-04-05 01:23:26 +08:00
|
|
|
}
|
2009-04-24 20:40:33 +08:00
|
|
|
}
|
2009-04-29 13:20:52 +08:00
|
|
|
assert(NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?");
|
2009-04-28 02:41:29 +08:00
|
|
|
assert(TLI.isShuffleMaskLegal(NewMask, NVT) && "Shuffle not legal?");
|
|
|
|
return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]);
|
2006-04-05 01:23:26 +08:00
|
|
|
}
|
|
|
|
|
2009-02-24 10:35:30 +08:00
|
|
|
SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag,
|
2009-05-24 10:46:31 +08:00
|
|
|
CodeGenOpt::Level ol)
|
2009-04-29 08:15:41 +08:00
|
|
|
: TLI(dag.getTargetLoweringInfo()), DAG(dag), OptLevel(ol),
|
2009-05-24 10:46:31 +08:00
|
|
|
ValueTypeActions(TLI.getValueTypeActions()) {
|
2005-11-29 13:45:29 +08:00
|
|
|
assert(MVT::LAST_VALUETYPE <= 32 &&
|
2005-01-07 15:47:09 +08:00
|
|
|
"Too many value types for ValueTypeActions to hold!");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SelectionDAGLegalize::LegalizeDAG() {
|
2006-02-13 17:18:02 +08:00
|
|
|
LastCALLSEQ_END = DAG.getEntryNode();
|
|
|
|
IsLegalizingCall = false;
|
2009-02-05 03:38:14 +08:00
|
|
|
|
2005-10-03 01:49:46 +08:00
|
|
|
// The legalize process is inherently a bottom-up recursive process (users
|
|
|
|
// legalize their uses before themselves). Given infinite stack space, we
|
|
|
|
// could just start legalizing on the root and traverse the whole graph. In
|
|
|
|
// practice however, this causes us to run out of stack space on large basic
|
2005-10-06 09:20:27 +08:00
|
|
|
// blocks. To avoid this problem, compute an ordering of the nodes where each
|
|
|
|
// node is only legalized after all of its operands are legalized.
|
2008-10-01 02:30:35 +08:00
|
|
|
DAG.AssignTopologicalOrder();
|
|
|
|
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
|
|
|
|
E = prior(DAG.allnodes_end()); I != next(E); ++I)
|
2009-05-27 20:42:55 +08:00
|
|
|
LegalizeOp(SDValue(I, 0));
|
2005-10-06 09:20:27 +08:00
|
|
|
|
|
|
|
// Finally, it's possible the root changed. Get the new root.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue OldRoot = DAG.getRoot();
|
2005-10-06 09:20:27 +08:00
|
|
|
assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
|
|
|
|
DAG.setRoot(LegalizedNodes[OldRoot]);
|
2005-01-07 15:47:09 +08:00
|
|
|
|
|
|
|
LegalizedNodes.clear();
|
|
|
|
|
|
|
|
// Remove dead nodes now.
|
2006-08-05 01:45:20 +08:00
|
|
|
DAG.RemoveDeadNodes();
|
2005-01-07 15:47:09 +08:00
|
|
|
}
|
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
|
|
|
|
/// FindCallEndFromCallStart - Given a chained node that is part of a call
|
|
|
|
/// sequence, find the CALLSEQ_END node that terminates the call sequence.
|
|
|
|
static SDNode *FindCallEndFromCallStart(SDNode *Node) {
|
|
|
|
if (Node->getOpcode() == ISD::CALLSEQ_END)
|
|
|
|
return Node;
|
|
|
|
if (Node->use_empty())
|
|
|
|
return 0; // No CallSeqEnd
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// The chain is usually at the end.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue TheChain(Node, Node->getNumValues()-1);
|
2006-02-13 17:18:02 +08:00
|
|
|
if (TheChain.getValueType() != MVT::Other) {
|
|
|
|
// Sometimes it's at the beginning.
|
2008-07-28 05:46:04 +08:00
|
|
|
TheChain = SDValue(Node, 0);
|
2006-02-13 17:18:02 +08:00
|
|
|
if (TheChain.getValueType() != MVT::Other) {
|
|
|
|
// Otherwise, hunt for it.
|
|
|
|
for (unsigned i = 1, e = Node->getNumValues(); i != e; ++i)
|
|
|
|
if (Node->getValueType(i) == MVT::Other) {
|
2008-07-28 05:46:04 +08:00
|
|
|
TheChain = SDValue(Node, i);
|
2006-02-13 17:18:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
// Otherwise, we walked into a node without a chain.
|
2006-02-13 17:18:02 +08:00
|
|
|
if (TheChain.getValueType() != MVT::Other)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
for (SDNode::use_iterator UI = Node->use_begin(),
|
|
|
|
E = Node->use_end(); UI != E; ++UI) {
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Make sure to only follow users of our token chain.
|
2008-07-28 04:43:25 +08:00
|
|
|
SDNode *User = *UI;
|
2006-02-13 17:18:02 +08:00
|
|
|
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i)
|
|
|
|
if (User->getOperand(i) == TheChain)
|
|
|
|
if (SDNode *Result = FindCallEndFromCallStart(User))
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-18 06:15:04 +08:00
|
|
|
/// FindCallStartFromCallEnd - Given a chained node that is part of a call
|
2006-02-13 17:18:02 +08:00
|
|
|
/// sequence, find the CALLSEQ_START node that initiates the call sequence.
|
|
|
|
static SDNode *FindCallStartFromCallEnd(SDNode *Node) {
|
|
|
|
assert(Node && "Didn't find callseq_start for a call??");
|
|
|
|
if (Node->getOpcode() == ISD::CALLSEQ_START) return Node;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
assert(Node->getOperand(0).getValueType() == MVT::Other &&
|
|
|
|
"Node doesn't have a token chain argument!");
|
2008-08-29 05:40:38 +08:00
|
|
|
return FindCallStartFromCallEnd(Node->getOperand(0).getNode());
|
2006-02-13 17:18:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to
|
2009-02-18 06:15:04 +08:00
|
|
|
/// see if any uses can reach Dest. If no dest operands can get to dest,
|
2006-02-13 17:18:02 +08:00
|
|
|
/// legalize them, legalize ourself, and return false, otherwise, return true.
|
2006-07-27 07:55:56 +08:00
|
|
|
///
|
|
|
|
/// Keep track of the nodes we fine that actually do lead to Dest in
|
|
|
|
/// NodesLeadingTo. This avoids retraversing them exponential number of times.
|
|
|
|
///
|
|
|
|
bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest,
|
2007-02-04 08:27:56 +08:00
|
|
|
SmallPtrSet<SDNode*, 32> &NodesLeadingTo) {
|
2006-02-13 17:18:02 +08:00
|
|
|
if (N == Dest) return true; // N certainly leads to Dest :)
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-07-27 07:55:56 +08:00
|
|
|
// If we've already processed this node and it does lead to Dest, there is no
|
|
|
|
// need to reprocess it.
|
|
|
|
if (NodesLeadingTo.count(N)) return true;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// If the first result of this node has been already legalized, then it cannot
|
|
|
|
// reach N.
|
2009-05-26 16:55:52 +08:00
|
|
|
if (LegalizedNodes.count(SDValue(N, 0))) return false;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Okay, this node has not already been legalized. Check and legalize all
|
|
|
|
// operands. If none lead to Dest, then we can legalize this node.
|
|
|
|
bool OperandsLeadToDest = false;
|
|
|
|
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
|
|
|
|
OperandsLeadToDest |= // If an operand leads to Dest, so do we.
|
2008-08-29 05:40:38 +08:00
|
|
|
LegalizeAllNodesNotLeadingTo(N->getOperand(i).getNode(), Dest, NodesLeadingTo);
|
2006-02-13 17:18:02 +08:00
|
|
|
|
2006-07-27 07:55:56 +08:00
|
|
|
if (OperandsLeadToDest) {
|
|
|
|
NodesLeadingTo.insert(N);
|
|
|
|
return true;
|
|
|
|
}
|
2006-02-13 17:18:02 +08:00
|
|
|
|
|
|
|
// Okay, this node looks safe, legalize it and return false.
|
2009-05-27 20:42:55 +08:00
|
|
|
LegalizeOp(SDValue(N, 0));
|
2006-02-13 17:18:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-12-14 04:57:08 +08:00
|
|
|
/// ExpandConstantFP - Expands the ConstantFP node to an integer constant or
|
|
|
|
/// a load from the constant pool.
|
2008-07-28 05:46:04 +08:00
|
|
|
static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP,
|
2009-01-16 00:43:02 +08:00
|
|
|
SelectionDAG &DAG, const TargetLowering &TLI) {
|
2006-12-13 05:32:44 +08:00
|
|
|
bool Extend = false;
|
2009-02-05 04:06:27 +08:00
|
|
|
DebugLoc dl = CFP->getDebugLoc();
|
2006-12-13 05:32:44 +08:00
|
|
|
|
|
|
|
// If a FP immediate is precise when represented as a float and if the
|
|
|
|
// target can do an extending load from float to double, we put it into
|
|
|
|
// the constant pool as a float, even if it's is statically typed as a
|
2008-03-05 14:46:58 +08:00
|
|
|
// double. This shrinks FP constants and canonicalizes them for targets where
|
|
|
|
// an FP extending load is the same cost as a normal load (such as on the x87
|
|
|
|
// fp stack or PPC FP unit).
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = CFP->getValueType(0);
|
2008-09-13 02:08:03 +08:00
|
|
|
ConstantFP *LLVMC = const_cast<ConstantFP*>(CFP->getConstantFPValue());
|
2006-12-14 04:57:08 +08:00
|
|
|
if (!UseCP) {
|
2009-03-08 09:47:41 +08:00
|
|
|
assert((VT == MVT::f64 || VT == MVT::f32) && "Invalid type expansion");
|
2008-10-10 02:53:47 +08:00
|
|
|
return DAG.getConstant(LLVMC->getValueAPF().bitcastToAPInt(),
|
2008-03-04 16:05:30 +08:00
|
|
|
(VT == MVT::f64) ? MVT::i64 : MVT::i32);
|
2006-12-13 06:19:28 +08:00
|
|
|
}
|
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT OrigVT = VT;
|
|
|
|
MVT SVT = VT;
|
2008-03-04 16:05:30 +08:00
|
|
|
while (SVT != MVT::f32) {
|
2008-06-06 20:08:01 +08:00
|
|
|
SVT = (MVT::SimpleValueType)(SVT.getSimpleVT() - 1);
|
2008-03-04 16:05:30 +08:00
|
|
|
if (CFP->isValueValidForType(SVT, CFP->getValueAPF()) &&
|
|
|
|
// Only do this if the target has a native EXTLOAD instruction from
|
|
|
|
// smaller type.
|
2008-10-15 05:26:46 +08:00
|
|
|
TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) &&
|
2008-03-05 14:46:58 +08:00
|
|
|
TLI.ShouldShrinkFPConstant(OrigVT)) {
|
2008-06-06 20:08:01 +08:00
|
|
|
const Type *SType = SVT.getTypeForMVT();
|
2008-03-04 16:05:30 +08:00
|
|
|
LLVMC = cast<ConstantFP>(ConstantExpr::getFPTrunc(LLVMC, SType));
|
|
|
|
VT = SVT;
|
|
|
|
Extend = true;
|
|
|
|
}
|
2006-12-13 05:32:44 +08:00
|
|
|
}
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy());
|
2009-03-13 15:51:59 +08:00
|
|
|
unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
|
2008-03-04 16:05:30 +08:00
|
|
|
if (Extend)
|
2009-02-05 04:06:27 +08:00
|
|
|
return DAG.getExtLoad(ISD::EXTLOAD, dl,
|
2009-02-04 10:34:38 +08:00
|
|
|
OrigVT, DAG.getEntryNode(),
|
2008-02-08 02:41:25 +08:00
|
|
|
CPIdx, PseudoSourceValue::getConstantPool(),
|
2008-09-17 06:05:41 +08:00
|
|
|
0, VT, false, Alignment);
|
2009-02-05 04:06:27 +08:00
|
|
|
return DAG.getLoad(OrigVT, dl, DAG.getEntryNode(), CPIdx,
|
2008-09-17 06:05:41 +08:00
|
|
|
PseudoSourceValue::getConstantPool(), 0, false, Alignment);
|
2006-12-13 05:32:44 +08:00
|
|
|
}
|
|
|
|
|
2007-08-02 03:34:21 +08:00
|
|
|
/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores.
|
|
|
|
static
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
|
2009-01-16 00:43:02 +08:00
|
|
|
const TargetLowering &TLI) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Chain = ST->getChain();
|
|
|
|
SDValue Ptr = ST->getBasePtr();
|
|
|
|
SDValue Val = ST->getValue();
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Val.getValueType();
|
2007-09-09 03:29:23 +08:00
|
|
|
int Alignment = ST->getAlignment();
|
|
|
|
int SVOffset = ST->getSrcValueOffset();
|
2009-02-03 04:41:04 +08:00
|
|
|
DebugLoc dl = ST->getDebugLoc();
|
2008-06-06 20:08:01 +08:00
|
|
|
if (ST->getMemoryVT().isFloatingPoint() ||
|
|
|
|
ST->getMemoryVT().isVector()) {
|
2008-12-13 05:47:02 +08:00
|
|
|
MVT intVT = MVT::getIntegerVT(VT.getSizeInBits());
|
|
|
|
if (TLI.isTypeLegal(intVT)) {
|
|
|
|
// Expand to a bitconvert of the value to the integer type of the
|
|
|
|
// same size, then a (misaligned) int store.
|
|
|
|
// FIXME: Does not handle truncating floating point stores!
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, intVT, Val);
|
|
|
|
return DAG.getStore(Chain, dl, Result, Ptr, ST->getSrcValue(),
|
2008-12-13 05:47:02 +08:00
|
|
|
SVOffset, ST->isVolatile(), Alignment);
|
|
|
|
} else {
|
|
|
|
// Do a (aligned) store to a stack slot, then copy from the stack slot
|
|
|
|
// to the final destination using (unaligned) integer loads and stores.
|
|
|
|
MVT StoredVT = ST->getMemoryVT();
|
|
|
|
MVT RegVT =
|
|
|
|
TLI.getRegisterType(MVT::getIntegerVT(StoredVT.getSizeInBits()));
|
|
|
|
unsigned StoredBytes = StoredVT.getSizeInBits() / 8;
|
|
|
|
unsigned RegBytes = RegVT.getSizeInBits() / 8;
|
|
|
|
unsigned NumRegs = (StoredBytes + RegBytes - 1) / RegBytes;
|
|
|
|
|
2008-12-13 15:18:38 +08:00
|
|
|
// Make sure the stack slot is also aligned for the register type.
|
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(StoredVT, RegVT);
|
|
|
|
|
|
|
|
// Perform the original store, only redirected to the stack slot.
|
2009-02-18 06:15:04 +08:00
|
|
|
SDValue Store = DAG.getTruncStore(Chain, dl,
|
2009-04-11 02:48:47 +08:00
|
|
|
Val, StackPtr, NULL, 0, StoredVT);
|
2008-12-13 05:47:02 +08:00
|
|
|
SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy());
|
|
|
|
SmallVector<SDValue, 8> Stores;
|
|
|
|
unsigned Offset = 0;
|
|
|
|
|
|
|
|
// Do all but one copies using the full register width.
|
|
|
|
for (unsigned i = 1; i < NumRegs; i++) {
|
|
|
|
// Load one integer register's worth from the stack slot.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0);
|
2008-12-13 05:47:02 +08:00
|
|
|
// Store it to the final location. Remember the store.
|
2009-02-03 04:41:04 +08:00
|
|
|
Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, Ptr,
|
2008-12-13 05:47:02 +08:00
|
|
|
ST->getSrcValue(), SVOffset + Offset,
|
|
|
|
ST->isVolatile(),
|
|
|
|
MinAlign(ST->getAlignment(), Offset)));
|
|
|
|
// Increment the pointers.
|
|
|
|
Offset += RegBytes;
|
2009-02-03 04:41:04 +08:00
|
|
|
StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
|
2008-12-13 05:47:02 +08:00
|
|
|
Increment);
|
2009-02-03 04:41:04 +08:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment);
|
2008-12-13 05:47:02 +08:00
|
|
|
}
|
|
|
|
|
2008-12-13 15:18:38 +08:00
|
|
|
// The last store may be partial. Do a truncating store. On big-endian
|
|
|
|
// machines this requires an extending load from the stack slot to ensure
|
|
|
|
// that the bits are in the right place.
|
|
|
|
MVT MemVT = MVT::getIntegerVT(8 * (StoredBytes - Offset));
|
|
|
|
|
|
|
|
// Load from the stack slot.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Store, StackPtr,
|
2008-12-13 15:18:38 +08:00
|
|
|
NULL, 0, MemVT);
|
2008-12-13 05:47:02 +08:00
|
|
|
|
2009-02-03 04:41:04 +08:00
|
|
|
Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, Ptr,
|
2008-12-13 05:47:02 +08:00
|
|
|
ST->getSrcValue(), SVOffset + Offset,
|
2008-12-13 15:18:38 +08:00
|
|
|
MemVT, ST->isVolatile(),
|
2008-12-13 05:47:02 +08:00
|
|
|
MinAlign(ST->getAlignment(), Offset)));
|
|
|
|
// The order of the stores doesn't matter - say it with a TokenFactor.
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0],
|
2008-12-13 05:47:02 +08:00
|
|
|
Stores.size());
|
|
|
|
}
|
2007-09-09 03:29:23 +08:00
|
|
|
}
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(ST->getMemoryVT().isInteger() &&
|
|
|
|
!ST->getMemoryVT().isVector() &&
|
2007-09-09 03:29:23 +08:00
|
|
|
"Unaligned store of unknown type.");
|
2007-08-02 03:34:21 +08:00
|
|
|
// Get the half-size VT
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NewStoredVT =
|
|
|
|
(MVT::SimpleValueType)(ST->getMemoryVT().getSimpleVT() - 1);
|
|
|
|
int NumBits = NewStoredVT.getSizeInBits();
|
2007-08-02 03:34:21 +08:00
|
|
|
int IncrementSize = NumBits / 8;
|
|
|
|
|
|
|
|
// Divide the stored value in two parts.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
|
|
|
|
SDValue Lo = Val;
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount);
|
2007-08-02 03:34:21 +08:00
|
|
|
|
|
|
|
// Store the two parts
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Store1, Store2;
|
2009-02-03 04:41:04 +08:00
|
|
|
Store1 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Lo:Hi, Ptr,
|
2007-08-02 03:34:21 +08:00
|
|
|
ST->getSrcValue(), SVOffset, NewStoredVT,
|
|
|
|
ST->isVolatile(), Alignment);
|
2009-02-03 04:41:04 +08:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
|
2007-08-02 03:34:21 +08:00
|
|
|
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
|
2007-10-28 20:59:45 +08:00
|
|
|
Alignment = MinAlign(Alignment, IncrementSize);
|
2009-02-03 04:41:04 +08:00
|
|
|
Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr,
|
2007-08-02 03:34:21 +08:00
|
|
|
ST->getSrcValue(), SVOffset + IncrementSize,
|
|
|
|
NewStoredVT, ST->isVolatile(), Alignment);
|
|
|
|
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2);
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads.
|
|
|
|
static
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
|
2009-01-16 00:58:17 +08:00
|
|
|
const TargetLowering &TLI) {
|
2007-08-02 03:34:21 +08:00
|
|
|
int SVOffset = LD->getSrcValueOffset();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Chain = LD->getChain();
|
|
|
|
SDValue Ptr = LD->getBasePtr();
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = LD->getValueType(0);
|
|
|
|
MVT LoadedVT = LD->getMemoryVT();
|
2009-02-03 04:41:04 +08:00
|
|
|
DebugLoc dl = LD->getDebugLoc();
|
2008-06-06 20:08:01 +08:00
|
|
|
if (VT.isFloatingPoint() || VT.isVector()) {
|
2008-12-13 05:47:02 +08:00
|
|
|
MVT intVT = MVT::getIntegerVT(LoadedVT.getSizeInBits());
|
|
|
|
if (TLI.isTypeLegal(intVT)) {
|
|
|
|
// Expand to a (misaligned) integer load of the same size,
|
|
|
|
// then bitconvert to floating point or vector.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue newLoad = DAG.getLoad(intVT, dl, Chain, Ptr, LD->getSrcValue(),
|
2008-12-13 05:47:02 +08:00
|
|
|
SVOffset, LD->isVolatile(),
|
2007-09-09 03:29:23 +08:00
|
|
|
LD->getAlignment());
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, LoadedVT, newLoad);
|
2008-12-13 05:47:02 +08:00
|
|
|
if (VT.isFloatingPoint() && LoadedVT != VT)
|
2009-02-03 04:41:04 +08:00
|
|
|
Result = DAG.getNode(ISD::FP_EXTEND, dl, VT, Result);
|
2007-09-09 03:29:23 +08:00
|
|
|
|
2008-12-13 05:47:02 +08:00
|
|
|
SDValue Ops[] = { Result, Chain };
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getMergeValues(Ops, 2, dl);
|
2008-12-13 05:47:02 +08:00
|
|
|
} else {
|
|
|
|
// Copy the value to a (aligned) stack slot using (unaligned) integer
|
|
|
|
// loads and stores, then do a (aligned) load from the stack slot.
|
|
|
|
MVT RegVT = TLI.getRegisterType(intVT);
|
|
|
|
unsigned LoadedBytes = LoadedVT.getSizeInBits() / 8;
|
|
|
|
unsigned RegBytes = RegVT.getSizeInBits() / 8;
|
|
|
|
unsigned NumRegs = (LoadedBytes + RegBytes - 1) / RegBytes;
|
|
|
|
|
2008-12-13 15:18:38 +08:00
|
|
|
// Make sure the stack slot is also aligned for the register type.
|
|
|
|
SDValue StackBase = DAG.CreateStackTemporary(LoadedVT, RegVT);
|
|
|
|
|
2008-12-13 05:47:02 +08:00
|
|
|
SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy());
|
|
|
|
SmallVector<SDValue, 8> Stores;
|
|
|
|
SDValue StackPtr = StackBase;
|
|
|
|
unsigned Offset = 0;
|
|
|
|
|
|
|
|
// Do all but one copies using the full register width.
|
|
|
|
for (unsigned i = 1; i < NumRegs; i++) {
|
|
|
|
// Load one integer register's worth from the original location.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Load = DAG.getLoad(RegVT, dl, Chain, Ptr, LD->getSrcValue(),
|
2008-12-13 05:47:02 +08:00
|
|
|
SVOffset + Offset, LD->isVolatile(),
|
|
|
|
MinAlign(LD->getAlignment(), Offset));
|
|
|
|
// Follow the load with a store to the stack slot. Remember the store.
|
2009-02-03 04:41:04 +08:00
|
|
|
Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr,
|
2008-12-13 05:47:02 +08:00
|
|
|
NULL, 0));
|
|
|
|
// Increment the pointers.
|
|
|
|
Offset += RegBytes;
|
2009-02-03 04:41:04 +08:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment);
|
|
|
|
StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
|
2008-12-13 05:47:02 +08:00
|
|
|
Increment);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The last copy may be partial. Do an extending load.
|
2008-12-13 15:18:38 +08:00
|
|
|
MVT MemVT = MVT::getIntegerVT(8 * (LoadedBytes - Offset));
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Chain, Ptr,
|
2008-12-13 05:47:02 +08:00
|
|
|
LD->getSrcValue(), SVOffset + Offset,
|
2008-12-13 15:18:38 +08:00
|
|
|
MemVT, LD->isVolatile(),
|
2008-12-13 05:47:02 +08:00
|
|
|
MinAlign(LD->getAlignment(), Offset));
|
|
|
|
// Follow the load with a store to the stack slot. Remember the store.
|
2008-12-13 15:18:38 +08:00
|
|
|
// On big-endian machines this requires a truncating store to ensure
|
|
|
|
// that the bits end up in the right place.
|
2009-02-03 04:41:04 +08:00
|
|
|
Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, StackPtr,
|
2008-12-13 15:18:38 +08:00
|
|
|
NULL, 0, MemVT));
|
2008-12-13 05:47:02 +08:00
|
|
|
|
|
|
|
// The order of the stores doesn't matter - say it with a TokenFactor.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0],
|
2008-12-13 05:47:02 +08:00
|
|
|
Stores.size());
|
|
|
|
|
|
|
|
// Finally, perform the original load only redirected to the stack slot.
|
2009-02-03 04:41:04 +08:00
|
|
|
Load = DAG.getExtLoad(LD->getExtensionType(), dl, VT, TF, StackBase,
|
2008-12-13 05:47:02 +08:00
|
|
|
NULL, 0, LoadedVT);
|
|
|
|
|
|
|
|
// Callers expect a MERGE_VALUES node.
|
|
|
|
SDValue Ops[] = { Load, TF };
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getMergeValues(Ops, 2, dl);
|
2008-12-13 05:47:02 +08:00
|
|
|
}
|
2007-09-09 03:29:23 +08:00
|
|
|
}
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(LoadedVT.isInteger() && !LoadedVT.isVector() &&
|
2007-11-20 05:38:03 +08:00
|
|
|
"Unaligned load of unsupported type.");
|
|
|
|
|
2008-02-28 06:36:00 +08:00
|
|
|
// Compute the new VT that is half the size of the old one. This is an
|
|
|
|
// integer MVT.
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned NumBits = LoadedVT.getSizeInBits();
|
|
|
|
MVT NewLoadedVT;
|
|
|
|
NewLoadedVT = MVT::getIntegerVT(NumBits/2);
|
2007-11-20 05:38:03 +08:00
|
|
|
NumBits >>= 1;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2007-11-20 05:38:03 +08:00
|
|
|
unsigned Alignment = LD->getAlignment();
|
|
|
|
unsigned IncrementSize = NumBits / 8;
|
2007-08-02 03:34:21 +08:00
|
|
|
ISD::LoadExtType HiExtType = LD->getExtensionType();
|
|
|
|
|
|
|
|
// If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD.
|
|
|
|
if (HiExtType == ISD::NON_EXTLOAD)
|
|
|
|
HiExtType = ISD::ZEXTLOAD;
|
|
|
|
|
|
|
|
// Load the value in two parts
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Lo, Hi;
|
2007-08-02 03:34:21 +08:00
|
|
|
if (TLI.isLittleEndian()) {
|
2009-02-03 04:41:04 +08:00
|
|
|
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(),
|
2007-08-02 03:34:21 +08:00
|
|
|
SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
|
2009-02-03 04:41:04 +08:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
|
2007-08-02 03:34:21 +08:00
|
|
|
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
|
2009-02-03 04:41:04 +08:00
|
|
|
Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(),
|
2007-08-02 03:34:21 +08:00
|
|
|
SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
|
2007-10-28 20:59:45 +08:00
|
|
|
MinAlign(Alignment, IncrementSize));
|
2007-08-02 03:34:21 +08:00
|
|
|
} else {
|
2009-02-03 04:41:04 +08:00
|
|
|
Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(),
|
2009-04-11 02:48:47 +08:00
|
|
|
SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
|
2009-02-03 04:41:04 +08:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
|
2007-08-02 03:34:21 +08:00
|
|
|
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
|
2009-02-03 04:41:04 +08:00
|
|
|
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(),
|
2007-08-02 03:34:21 +08:00
|
|
|
SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
|
2007-10-28 20:59:45 +08:00
|
|
|
MinAlign(Alignment, IncrementSize));
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// aggregate the two parts
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount);
|
|
|
|
Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo);
|
2007-08-02 03:34:21 +08:00
|
|
|
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
|
2007-08-02 03:34:21 +08:00
|
|
|
Hi.getValue(1));
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Ops[] = { Result, TF };
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getMergeValues(Ops, 2, dl);
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
2007-01-05 05:56:39 +08:00
|
|
|
|
2008-04-26 02:07:40 +08:00
|
|
|
/// PerformInsertVectorEltInMemory - Some target cannot handle a variable
|
|
|
|
/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it
|
|
|
|
/// is necessary to spill the vector being inserted into to memory, perform
|
|
|
|
/// the insert there, and then read the result back.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::
|
2009-02-03 04:41:04 +08:00
|
|
|
PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx,
|
|
|
|
DebugLoc dl) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Tmp1 = Vec;
|
|
|
|
SDValue Tmp2 = Val;
|
|
|
|
SDValue Tmp3 = Idx;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-04-26 02:07:40 +08:00
|
|
|
// If the target doesn't support this, we have to spill the input vector
|
|
|
|
// to a temporary stack slot, update the element, then reload it. This is
|
|
|
|
// badness. We could also load the value into a vector register (either
|
|
|
|
// with a "move to register" or "extload into register" instruction, then
|
|
|
|
// permute it into place, if the idx is a constant and if the idx is
|
|
|
|
// supported by the target.
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Tmp1.getValueType();
|
|
|
|
MVT EltVT = VT.getVectorElementType();
|
|
|
|
MVT IdxVT = Tmp3.getValueType();
|
|
|
|
MVT PtrVT = TLI.getPointerTy();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(VT);
|
2008-04-26 02:07:40 +08:00
|
|
|
|
2008-08-29 05:40:38 +08:00
|
|
|
int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
|
2008-04-26 02:07:40 +08:00
|
|
|
|
|
|
|
// Store the vector.
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Tmp1, StackPtr,
|
2008-10-30 16:01:45 +08:00
|
|
|
PseudoSourceValue::getFixedStack(SPFI), 0);
|
2008-04-26 02:07:40 +08:00
|
|
|
|
|
|
|
// Truncate or zero extend offset to target pointer type.
|
2008-06-09 04:54:56 +08:00
|
|
|
unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
|
2009-02-03 04:41:04 +08:00
|
|
|
Tmp3 = DAG.getNode(CastOpc, dl, PtrVT, Tmp3);
|
2008-04-26 02:07:40 +08:00
|
|
|
// Add the offset to the index.
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned EltSize = EltVT.getSizeInBits()/8;
|
2009-02-03 04:41:04 +08:00
|
|
|
Tmp3 = DAG.getNode(ISD::MUL, dl, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT));
|
|
|
|
SDValue StackPtr2 = DAG.getNode(ISD::ADD, dl, IdxVT, Tmp3, StackPtr);
|
2008-04-26 02:07:40 +08:00
|
|
|
// Store the scalar value.
|
2009-02-03 04:41:04 +08:00
|
|
|
Ch = DAG.getTruncStore(Ch, dl, Tmp2, StackPtr2,
|
2008-07-12 06:44:52 +08:00
|
|
|
PseudoSourceValue::getFixedStack(SPFI), 0, EltVT);
|
2008-04-26 02:07:40 +08:00
|
|
|
// Load the updated vector.
|
2009-02-03 04:41:04 +08:00
|
|
|
return DAG.getLoad(VT, dl, Ch, StackPtr,
|
2008-07-12 06:44:52 +08:00
|
|
|
PseudoSourceValue::getFixedStack(SPFI), 0);
|
2008-04-26 02:07:40 +08:00
|
|
|
}
|
|
|
|
|
2008-12-09 13:46:39 +08:00
|
|
|
|
2009-05-27 10:16:40 +08:00
|
|
|
SDValue SelectionDAGLegalize::
|
|
|
|
ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, DebugLoc dl) {
|
|
|
|
if (ConstantSDNode *InsertPos = dyn_cast<ConstantSDNode>(Idx)) {
|
|
|
|
// SCALAR_TO_VECTOR requires that the type of the value being inserted
|
|
|
|
// match the element type of the vector being created, except for
|
|
|
|
// integers in which case the inserted value can be over width.
|
|
|
|
MVT EltVT = Vec.getValueType().getVectorElementType();
|
|
|
|
if (Val.getValueType() == EltVT ||
|
|
|
|
(EltVT.isInteger() && Val.getValueType().bitsGE(EltVT))) {
|
|
|
|
SDValue ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl,
|
|
|
|
Vec.getValueType(), Val);
|
|
|
|
|
|
|
|
unsigned NumElts = Vec.getValueType().getVectorNumElements();
|
|
|
|
// We generate a shuffle of InVec and ScVec, so the shuffle mask
|
|
|
|
// should be 0,1,2,3,4,5... with the appropriate element replaced with
|
|
|
|
// elt 0 of the RHS.
|
|
|
|
SmallVector<int, 8> ShufOps;
|
|
|
|
for (unsigned i = 0; i != NumElts; ++i)
|
|
|
|
ShufOps.push_back(i != InsertPos->getZExtValue() ? i : NumElts);
|
|
|
|
|
|
|
|
return DAG.getVectorShuffle(Vec.getValueType(), dl, Vec, ScVec,
|
|
|
|
&ShufOps[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl);
|
|
|
|
}
|
|
|
|
|
2007-07-14 04:14:11 +08:00
|
|
|
/// LegalizeOp - We know that the specified value has a legal type, and
|
|
|
|
/// that its operands are legal. Now ensure that the operation itself
|
|
|
|
/// is legal, recursively ensuring that the operands' operations remain
|
|
|
|
/// legal.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
2007-08-25 09:00:22 +08:00
|
|
|
if (Op.getOpcode() == ISD::TargetConstant) // Allow illegal target nodes.
|
|
|
|
return Op;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-08-29 05:40:38 +08:00
|
|
|
SDNode *Node = Op.getNode();
|
2009-01-31 07:10:59 +08:00
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
2005-01-09 04:35:13 +08:00
|
|
|
|
2009-05-24 10:46:31 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
|
|
|
|
assert(getTypeAction(Node->getValueType(i)) == Legal &&
|
|
|
|
"Unexpected illegal type!");
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
|
|
|
|
assert((isTypeLegal(Node->getOperand(i).getValueType()) ||
|
|
|
|
Node->getOperand(i).getOpcode() == ISD::TargetConstant) &&
|
|
|
|
"Unexpected illegal type!");
|
2005-01-07 15:47:09 +08:00
|
|
|
|
2005-05-13 00:53:42 +08:00
|
|
|
// Note that LegalizeOp may be reentered even from single-use nodes, which
|
|
|
|
// means that we always must cache transformed nodes.
|
2008-07-28 05:46:04 +08:00
|
|
|
DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
|
2005-01-11 13:57:22 +08:00
|
|
|
if (I != LegalizedNodes.end()) return I->second;
|
2005-01-07 15:47:09 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Tmp1, Tmp2, Tmp3, Tmp4;
|
|
|
|
SDValue Result = Op;
|
2006-01-28 15:39:30 +08:00
|
|
|
bool isCustom = false;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2009-05-27 09:25:56 +08:00
|
|
|
// Figure out the correct action; the way to query this varies by opcode
|
|
|
|
TargetLowering::LegalizeAction Action;
|
|
|
|
bool SimpleFinishLegalizing = true;
|
2005-01-07 15:47:09 +08:00
|
|
|
switch (Node->getOpcode()) {
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::INTRINSIC_W_CHAIN:
|
|
|
|
case ISD::INTRINSIC_WO_CHAIN:
|
|
|
|
case ISD::INTRINSIC_VOID:
|
|
|
|
case ISD::VAARG:
|
|
|
|
case ISD::STACKSAVE:
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), MVT::Other);
|
|
|
|
break;
|
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
case ISD::UINT_TO_FP:
|
|
|
|
case ISD::EXTRACT_VECTOR_ELT:
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(),
|
|
|
|
Node->getOperand(0).getValueType());
|
|
|
|
break;
|
|
|
|
case ISD::FP_ROUND_INREG:
|
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
|
|
|
MVT InnerType = cast<VTSDNode>(Node->getOperand(1))->getVT();
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), InnerType);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-28 11:06:16 +08:00
|
|
|
case ISD::SELECT_CC:
|
|
|
|
case ISD::SETCC:
|
|
|
|
case ISD::BR_CC: {
|
|
|
|
unsigned CCOperand = Node->getOpcode() == ISD::SELECT_CC ? 4 :
|
|
|
|
Node->getOpcode() == ISD::SETCC ? 2 : 1;
|
|
|
|
unsigned CompareOperand = Node->getOpcode() == ISD::BR_CC ? 2 : 0;
|
|
|
|
MVT OpVT = Node->getOperand(CompareOperand).getValueType();
|
|
|
|
ISD::CondCode CCCode =
|
|
|
|
cast<CondCodeSDNode>(Node->getOperand(CCOperand))->get();
|
|
|
|
Action = TLI.getCondCodeAction(CCCode, OpVT);
|
|
|
|
if (Action == TargetLowering::Legal) {
|
|
|
|
if (Node->getOpcode() == ISD::SELECT_CC)
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(),
|
|
|
|
Node->getValueType(0));
|
|
|
|
else
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), OpVT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::LOAD:
|
|
|
|
case ISD::STORE:
|
|
|
|
case ISD::FORMAL_ARGUMENTS:
|
|
|
|
case ISD::CALL:
|
|
|
|
case ISD::CALLSEQ_START:
|
|
|
|
case ISD::CALLSEQ_END:
|
|
|
|
// These instructions have properties that aren't modeled in the
|
|
|
|
// generic codepath
|
|
|
|
SimpleFinishLegalizing = false;
|
|
|
|
break;
|
|
|
|
case ISD::EXTRACT_ELEMENT:
|
|
|
|
case ISD::FLT_ROUNDS_:
|
|
|
|
case ISD::SADDO:
|
|
|
|
case ISD::SSUBO:
|
|
|
|
case ISD::UADDO:
|
|
|
|
case ISD::USUBO:
|
|
|
|
case ISD::SMULO:
|
|
|
|
case ISD::UMULO:
|
|
|
|
case ISD::FPOWI:
|
|
|
|
case ISD::MERGE_VALUES:
|
|
|
|
case ISD::EH_RETURN:
|
|
|
|
case ISD::FRAME_TO_ARGS_OFFSET:
|
2009-05-27 11:33:44 +08:00
|
|
|
// These operations lie about being legal: when they claim to be legal,
|
|
|
|
// they should actually be expanded.
|
2009-05-27 09:25:56 +08:00
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
|
|
|
if (Action == TargetLowering::Legal)
|
|
|
|
Action = TargetLowering::Expand;
|
|
|
|
break;
|
|
|
|
case ISD::TRAMPOLINE:
|
|
|
|
case ISD::FRAMEADDR:
|
|
|
|
case ISD::RETURNADDR:
|
2009-05-27 20:20:41 +08:00
|
|
|
// These operations lie about being legal: when they claim to be legal,
|
|
|
|
// they should actually be custom-lowered.
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
|
|
|
if (Action == TargetLowering::Legal)
|
|
|
|
Action = TargetLowering::Custom;
|
2009-05-27 09:25:56 +08:00
|
|
|
break;
|
|
|
|
case ISD::BUILD_VECTOR:
|
2009-05-27 20:42:55 +08:00
|
|
|
// A weird case: legalization for BUILD_VECTOR never legalizes the
|
|
|
|
// operands!
|
|
|
|
// FIXME: This really sucks... changing it isn't semantically incorrect,
|
|
|
|
// but it massively pessimizes the code for floating-point BUILD_VECTORs
|
|
|
|
// because ConstantFP operands get legalized into constant pool loads
|
|
|
|
// before the BUILD_VECTOR code can see them. It doesn't usually bite,
|
|
|
|
// though, because BUILD_VECTORS usually get lowered into other nodes
|
|
|
|
// which get legalized properly.
|
2009-05-27 09:25:56 +08:00
|
|
|
SimpleFinishLegalizing = false;
|
2006-01-28 16:31:04 +08:00
|
|
|
break;
|
2005-01-07 15:47:09 +08:00
|
|
|
default:
|
2005-05-14 14:34:48 +08:00
|
|
|
if (Node->getOpcode() >= ISD::BUILTIN_OP_END) {
|
2009-05-27 09:25:56 +08:00
|
|
|
Action = TargetLowering::Legal;
|
|
|
|
} else {
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-05-14 14:34:48 +08:00
|
|
|
|
2009-05-27 09:25:56 +08:00
|
|
|
if (SimpleFinishLegalizing) {
|
|
|
|
SmallVector<SDValue, 8> Ops, ResultVals;
|
|
|
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
|
|
|
|
Ops.push_back(LegalizeOp(Node->getOperand(i)));
|
|
|
|
switch (Node->getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case ISD::BR:
|
|
|
|
case ISD::BRIND:
|
|
|
|
case ISD::BR_JT:
|
|
|
|
case ISD::BR_CC:
|
|
|
|
case ISD::BRCOND:
|
|
|
|
case ISD::RET:
|
|
|
|
// Branches tweak the chain to include LastCALLSEQ_END
|
|
|
|
Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0],
|
|
|
|
LastCALLSEQ_END);
|
|
|
|
Ops[0] = LegalizeOp(Ops[0]);
|
|
|
|
LastCALLSEQ_END = DAG.getEntryNode();
|
|
|
|
break;
|
|
|
|
case ISD::SHL:
|
|
|
|
case ISD::SRL:
|
|
|
|
case ISD::SRA:
|
|
|
|
case ISD::ROTL:
|
|
|
|
case ISD::ROTR:
|
|
|
|
// Legalizing shifts/rotates requires adjusting the shift amount
|
|
|
|
// to the appropriate width.
|
|
|
|
if (!Ops[1].getValueType().isVector())
|
|
|
|
Ops[1] = LegalizeOp(DAG.getShiftAmountOperand(Ops[1]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result = DAG.UpdateNodeOperands(Result.getValue(0), Ops.data(),
|
|
|
|
Ops.size());
|
|
|
|
switch (Action) {
|
|
|
|
case TargetLowering::Legal:
|
2005-05-14 14:34:48 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
|
2009-05-27 09:25:56 +08:00
|
|
|
ResultVals.push_back(Result.getValue(i));
|
|
|
|
break;
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
// FIXME: The handling for custom lowering with multiple results is
|
|
|
|
// a complete mess.
|
|
|
|
Tmp1 = TLI.LowerOperation(Result, DAG);
|
|
|
|
if (Tmp1.getNode()) {
|
|
|
|
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) {
|
|
|
|
if (e == 1)
|
|
|
|
ResultVals.push_back(Tmp1);
|
|
|
|
else
|
|
|
|
ResultVals.push_back(Tmp1.getValue(i));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FALL THROUGH
|
|
|
|
case TargetLowering::Expand:
|
|
|
|
ExpandNode(Result.getNode(), ResultVals);
|
|
|
|
break;
|
|
|
|
case TargetLowering::Promote:
|
|
|
|
PromoteNode(Result.getNode(), ResultVals);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ResultVals.empty()) {
|
|
|
|
for (unsigned i = 0, e = ResultVals.size(); i != e; ++i) {
|
|
|
|
if (ResultVals[i] != SDValue(Node, i))
|
|
|
|
ResultVals[i] = LegalizeOp(ResultVals[i]);
|
|
|
|
AddLegalizedOperand(SDValue(Node, i), ResultVals[i]);
|
|
|
|
}
|
|
|
|
return ResultVals[Op.getResNo()];
|
2005-05-14 14:34:48 +08:00
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (Node->getOpcode()) {
|
|
|
|
default:
|
2006-07-12 01:58:07 +08:00
|
|
|
#ifndef NDEBUG
|
2007-06-05 00:17:33 +08:00
|
|
|
cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
|
2006-07-12 01:58:07 +08:00
|
|
|
#endif
|
2005-01-07 15:47:09 +08:00
|
|
|
assert(0 && "Do not know how to legalize this operator!");
|
|
|
|
abort();
|
2006-04-13 00:20:43 +08:00
|
|
|
case ISD::FORMAL_ARGUMENTS:
|
2006-05-17 06:53:20 +08:00
|
|
|
case ISD::CALL:
|
2006-04-13 00:20:43 +08:00
|
|
|
// The only option for this is to custom lower it.
|
2006-05-18 01:55:45 +08:00
|
|
|
Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
assert(Tmp3.getNode() && "Target didn't custom lower this node!");
|
2008-03-06 03:14:03 +08:00
|
|
|
// A call within a calling sequence must be legalized to something
|
|
|
|
// other than the normal CALLSEQ_END. Violating this gets Legalize
|
|
|
|
// into an infinite loop.
|
|
|
|
assert ((!IsLegalizingCall ||
|
|
|
|
Node->getOpcode() != ISD::CALL ||
|
2008-08-29 05:40:38 +08:00
|
|
|
Tmp3.getNode()->getOpcode() != ISD::CALLSEQ_END) &&
|
2008-03-06 03:14:03 +08:00
|
|
|
"Nested CALLSEQ_START..CALLSEQ_END not supported.");
|
2007-11-13 08:44:25 +08:00
|
|
|
|
|
|
|
// The number of incoming and outgoing values should match; unless the final
|
|
|
|
// outgoing value is a flag.
|
2008-08-29 05:40:38 +08:00
|
|
|
assert((Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() ||
|
|
|
|
(Tmp3.getNode()->getNumValues() == Result.getNode()->getNumValues() + 1 &&
|
|
|
|
Tmp3.getNode()->getValueType(Tmp3.getNode()->getNumValues() - 1) ==
|
2007-11-13 08:44:25 +08:00
|
|
|
MVT::Flag)) &&
|
2006-05-18 01:55:45 +08:00
|
|
|
"Lowering call/formal_arguments produced unexpected # results!");
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-05-17 06:53:20 +08:00
|
|
|
// Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
|
2006-05-16 13:49:56 +08:00
|
|
|
// remember that we legalized all of them, so it doesn't get relegalized.
|
2008-08-29 05:40:38 +08:00
|
|
|
for (unsigned i = 0, e = Tmp3.getNode()->getNumValues(); i != e; ++i) {
|
|
|
|
if (Tmp3.getNode()->getValueType(i) == MVT::Flag)
|
2007-11-13 08:44:25 +08:00
|
|
|
continue;
|
2006-05-18 01:55:45 +08:00
|
|
|
Tmp1 = LegalizeOp(Tmp3.getValue(i));
|
2008-08-27 06:36:50 +08:00
|
|
|
if (Op.getResNo() == i)
|
2006-05-16 13:49:56 +08:00
|
|
|
Tmp2 = Tmp1;
|
2008-07-28 05:46:04 +08:00
|
|
|
AddLegalizedOperand(SDValue(Node, i), Tmp1);
|
2006-05-16 13:49:56 +08:00
|
|
|
}
|
|
|
|
return Tmp2;
|
2006-03-19 08:52:58 +08:00
|
|
|
case ISD::BUILD_VECTOR:
|
|
|
|
switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
|
2006-03-19 09:17:20 +08:00
|
|
|
default: assert(0 && "This action is not supported yet!");
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
Tmp3 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp3.getNode()) {
|
2006-03-19 09:17:20 +08:00
|
|
|
Result = Tmp3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// FALLTHROUGH
|
2006-03-19 14:31:19 +08:00
|
|
|
case TargetLowering::Expand:
|
2008-08-29 05:40:38 +08:00
|
|
|
Result = ExpandBUILD_VECTOR(Result.getNode());
|
2006-03-19 08:52:58 +08:00
|
|
|
break;
|
2006-03-19 09:17:20 +08:00
|
|
|
}
|
|
|
|
break;
|
2006-02-13 17:18:02 +08:00
|
|
|
case ISD::CALLSEQ_START: {
|
|
|
|
SDNode *CallEnd = FindCallEndFromCallStart(Node);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Recursively Legalize all of the inputs of the call end that do not lead
|
|
|
|
// to this call start. This ensures that any libcalls that need be inserted
|
|
|
|
// are inserted *before* the CALLSEQ_START.
|
2007-02-04 08:27:56 +08:00
|
|
|
{SmallPtrSet<SDNode*, 32> NodesLeadingTo;
|
2006-02-13 17:18:02 +08:00
|
|
|
for (unsigned i = 0, e = CallEnd->getNumOperands(); i != e; ++i)
|
2008-08-29 05:40:38 +08:00
|
|
|
LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).getNode(), Node,
|
2006-07-27 07:55:56 +08:00
|
|
|
NodesLeadingTo);
|
|
|
|
}
|
2006-02-13 17:18:02 +08:00
|
|
|
|
|
|
|
// Now that we legalized all of the inputs (which may have inserted
|
|
|
|
// libcalls) create the new CALLSEQ_START node.
|
|
|
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
|
|
|
|
|
|
|
// Merge in the last call, to ensure that this call start after the last
|
|
|
|
// call ended.
|
2006-05-18 02:00:08 +08:00
|
|
|
if (LastCALLSEQ_END.getOpcode() != ISD::EntryToken) {
|
2009-02-18 06:15:04 +08:00
|
|
|
Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp1, LastCALLSEQ_END);
|
2006-05-18 01:55:45 +08:00
|
|
|
Tmp1 = LegalizeOp(Tmp1);
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Do not try to legalize the target-specific arguments (#1+).
|
|
|
|
if (Tmp1 != Node->getOperand(0)) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SmallVector<SDValue, 8> Ops(Node->op_begin(), Node->op_end());
|
2006-02-13 17:18:02 +08:00
|
|
|
Ops[0] = Tmp1;
|
2006-08-08 09:09:31 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size());
|
2006-02-13 17:18:02 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Remember that the CALLSEQ_START is legalized.
|
2006-02-14 08:55:02 +08:00
|
|
|
AddLegalizedOperand(Op.getValue(0), Result);
|
|
|
|
if (Node->getNumValues() == 2) // If this has a flag result, remember it.
|
|
|
|
AddLegalizedOperand(Op.getValue(1), Result.getValue(1));
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Now that the callseq_start and all of the non-call nodes above this call
|
2009-02-18 06:15:04 +08:00
|
|
|
// sequence have been legalized, legalize the call itself. During this
|
2006-02-13 17:18:02 +08:00
|
|
|
// process, no libcalls can/will be inserted, guaranteeing that no calls
|
|
|
|
// can overlap.
|
|
|
|
assert(!IsLegalizingCall && "Inconsistent sequentialization of calls!");
|
|
|
|
// Note that we are selecting this call!
|
2008-07-28 05:46:04 +08:00
|
|
|
LastCALLSEQ_END = SDValue(CallEnd, 0);
|
2006-02-13 17:18:02 +08:00
|
|
|
IsLegalizingCall = true;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Legalize the call, starting from the CALLSEQ_END.
|
|
|
|
LegalizeOp(LastCALLSEQ_END);
|
|
|
|
assert(!IsLegalizingCall && "CALLSEQ_END should have cleared this!");
|
|
|
|
return Result;
|
|
|
|
}
|
2005-05-13 07:24:06 +08:00
|
|
|
case ISD::CALLSEQ_END:
|
2006-02-13 17:18:02 +08:00
|
|
|
// If the CALLSEQ_START node hasn't been legalized first, legalize it. This
|
|
|
|
// will cause this node to be legalized as well as handling libcalls right.
|
2008-08-29 05:40:38 +08:00
|
|
|
if (LastCALLSEQ_END.getNode() != Node) {
|
2008-07-28 05:46:04 +08:00
|
|
|
LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0));
|
|
|
|
DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
|
2006-02-13 17:18:02 +08:00
|
|
|
assert(I != LegalizedNodes.end() &&
|
|
|
|
"Legalizing the call start should have legalized this node!");
|
|
|
|
return I->second;
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
// Otherwise, the call start has been legalized and everything is going
|
2006-02-13 17:18:02 +08:00
|
|
|
// according to plan. Just legalize ourselves normally here.
|
2005-01-07 15:47:09 +08:00
|
|
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
2006-01-29 15:58:15 +08:00
|
|
|
// Do not try to legalize the target-specific arguments (#1+), except for
|
|
|
|
// an optional flag input.
|
|
|
|
if (Node->getOperand(Node->getNumOperands()-1).getValueType() != MVT::Flag){
|
|
|
|
if (Tmp1 != Node->getOperand(0)) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SmallVector<SDValue, 8> Ops(Node->op_begin(), Node->op_end());
|
2006-01-29 15:58:15 +08:00
|
|
|
Ops[0] = Tmp1;
|
2006-08-08 09:09:31 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size());
|
2006-01-29 15:58:15 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Tmp2 = LegalizeOp(Node->getOperand(Node->getNumOperands()-1));
|
|
|
|
if (Tmp1 != Node->getOperand(0) ||
|
|
|
|
Tmp2 != Node->getOperand(Node->getNumOperands()-1)) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SmallVector<SDValue, 8> Ops(Node->op_begin(), Node->op_end());
|
2006-01-29 15:58:15 +08:00
|
|
|
Ops[0] = Tmp1;
|
|
|
|
Ops.back() = Tmp2;
|
2006-08-08 09:09:31 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size());
|
2006-01-29 15:58:15 +08:00
|
|
|
}
|
2006-01-24 13:48:21 +08:00
|
|
|
}
|
2006-02-14 08:55:02 +08:00
|
|
|
assert(IsLegalizingCall && "Call sequence imbalance between start/end?");
|
2006-02-13 17:18:02 +08:00
|
|
|
// This finishes up call legalization.
|
|
|
|
IsLegalizingCall = false;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-02-14 08:55:02 +08:00
|
|
|
// If the CALLSEQ_END node has a flag, remember that we legalized it.
|
2008-07-28 05:46:04 +08:00
|
|
|
AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0));
|
2006-02-14 08:55:02 +08:00
|
|
|
if (Node->getNumValues() == 2)
|
2008-07-28 05:46:04 +08:00
|
|
|
AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1));
|
2008-08-27 06:36:50 +08:00
|
|
|
return Result.getValue(Op.getResNo());
|
2005-08-17 03:49:35 +08:00
|
|
|
case ISD::BR_CC:
|
|
|
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
2006-02-13 17:18:02 +08:00
|
|
|
// Ensure that libcalls are emitted before a branch.
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Tmp1, LastCALLSEQ_END);
|
2006-02-13 17:18:02 +08:00
|
|
|
Tmp1 = LegalizeOp(Tmp1);
|
2009-02-18 06:15:04 +08:00
|
|
|
Tmp2 = Node->getOperand(2); // LHS
|
2006-02-01 15:19:44 +08:00
|
|
|
Tmp3 = Node->getOperand(3); // RHS
|
|
|
|
Tmp4 = Node->getOperand(1); // CC
|
2005-12-18 07:46:46 +08:00
|
|
|
|
2009-02-18 06:15:04 +08:00
|
|
|
LegalizeSetCC(TLI.getSetCCResultType(Tmp2.getValueType()),
|
2009-02-03 04:41:04 +08:00
|
|
|
Tmp2, Tmp3, Tmp4, dl);
|
2006-12-19 06:55:34 +08:00
|
|
|
LastCALLSEQ_END = DAG.getEntryNode();
|
|
|
|
|
2008-10-15 10:05:31 +08:00
|
|
|
// If we didn't get both a LHS and RHS back from LegalizeSetCC,
|
2006-02-01 15:19:44 +08:00
|
|
|
// the LHS is a legal SETCC itself. In this case, we need to compare
|
|
|
|
// the result against zero to select between true and false values.
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp3.getNode() == 0) {
|
2006-02-01 15:19:44 +08:00
|
|
|
Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
|
|
|
|
Tmp4 = DAG.getCondCode(ISD::SETNE);
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp4, Tmp2, Tmp3,
|
2006-02-01 15:19:44 +08:00
|
|
|
Node->getOperand(4));
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-12-18 07:46:46 +08:00
|
|
|
switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) {
|
|
|
|
default: assert(0 && "Unexpected action for BR_CC!");
|
2006-01-28 15:39:30 +08:00
|
|
|
case TargetLowering::Legal: break;
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
Tmp4 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp4.getNode()) Result = Tmp4;
|
2005-12-18 07:46:46 +08:00
|
|
|
break;
|
2005-08-17 03:49:35 +08:00
|
|
|
}
|
2005-01-07 16:19:42 +08:00
|
|
|
break;
|
2005-12-23 15:29:34 +08:00
|
|
|
case ISD::LOAD: {
|
2006-10-10 04:57:25 +08:00
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(Node);
|
|
|
|
Tmp1 = LegalizeOp(LD->getChain()); // Legalize the chain.
|
|
|
|
Tmp2 = LegalizeOp(LD->getBasePtr()); // Legalize the base pointer.
|
2005-04-28 04:10:01 +08:00
|
|
|
|
2006-10-10 04:57:25 +08:00
|
|
|
ISD::LoadExtType ExtType = LD->getExtensionType();
|
|
|
|
if (ExtType == ISD::NON_EXTLOAD) {
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Node->getValueType(0);
|
2006-10-10 04:57:25 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset());
|
|
|
|
Tmp3 = Result.getValue(0);
|
|
|
|
Tmp4 = Result.getValue(1);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-10-10 04:57:25 +08:00
|
|
|
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
|
|
|
|
default: assert(0 && "This action is not supported yet!");
|
2007-08-02 03:34:21 +08:00
|
|
|
case TargetLowering::Legal:
|
|
|
|
// If this is an unaligned load and the target doesn't support it,
|
|
|
|
// expand it.
|
|
|
|
if (!TLI.allowsUnalignedMemoryAccesses()) {
|
|
|
|
unsigned ABIAlignment = TLI.getTargetData()->
|
2008-06-06 20:08:01 +08:00
|
|
|
getABITypeAlignment(LD->getMemoryVT().getTypeForMVT());
|
2007-08-02 03:34:21 +08:00
|
|
|
if (LD->getAlignment() < ABIAlignment){
|
2008-08-29 05:40:38 +08:00
|
|
|
Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.getNode()), DAG,
|
2007-08-02 03:34:21 +08:00
|
|
|
TLI);
|
|
|
|
Tmp3 = Result.getOperand(0);
|
|
|
|
Tmp4 = Result.getOperand(1);
|
2007-09-09 03:29:23 +08:00
|
|
|
Tmp3 = LegalizeOp(Tmp3);
|
|
|
|
Tmp4 = LegalizeOp(Tmp4);
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-10-10 04:57:25 +08:00
|
|
|
case TargetLowering::Custom:
|
|
|
|
Tmp1 = TLI.LowerOperation(Tmp3, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp1.getNode()) {
|
2006-10-10 04:57:25 +08:00
|
|
|
Tmp3 = LegalizeOp(Tmp1);
|
|
|
|
Tmp4 = LegalizeOp(Tmp1.getValue(1));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TargetLowering::Promote: {
|
|
|
|
// Only promote a load of vector type to another.
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(VT.isVector() && "Cannot promote this load!");
|
2006-10-10 04:57:25 +08:00
|
|
|
// Change base type to a different vector type.
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
|
2006-10-10 04:57:25 +08:00
|
|
|
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp1 = DAG.getLoad(NVT, dl, Tmp1, Tmp2, LD->getSrcValue(),
|
2007-07-10 06:18:38 +08:00
|
|
|
LD->getSrcValueOffset(),
|
|
|
|
LD->isVolatile(), LD->getAlignment());
|
2009-02-07 08:55:49 +08:00
|
|
|
Tmp3 = LegalizeOp(DAG.getNode(ISD::BIT_CONVERT, dl, VT, Tmp1));
|
2006-04-13 00:33:18 +08:00
|
|
|
Tmp4 = LegalizeOp(Tmp1.getValue(1));
|
2006-10-10 04:57:25 +08:00
|
|
|
break;
|
2005-12-23 15:29:34 +08:00
|
|
|
}
|
2006-10-10 04:57:25 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
// Since loads produce two values, make sure to remember that we
|
2006-10-10 04:57:25 +08:00
|
|
|
// legalized both of them.
|
2008-07-28 05:46:04 +08:00
|
|
|
AddLegalizedOperand(SDValue(Node, 0), Tmp3);
|
|
|
|
AddLegalizedOperand(SDValue(Node, 1), Tmp4);
|
2008-08-27 06:36:50 +08:00
|
|
|
return Op.getResNo() ? Tmp4 : Tmp3;
|
2006-10-10 04:57:25 +08:00
|
|
|
} else {
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT SrcVT = LD->getMemoryVT();
|
|
|
|
unsigned SrcWidth = SrcVT.getSizeInBits();
|
2008-01-24 04:39:46 +08:00
|
|
|
int SVOffset = LD->getSrcValueOffset();
|
|
|
|
unsigned Alignment = LD->getAlignment();
|
|
|
|
bool isVolatile = LD->isVolatile();
|
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
if (SrcWidth != SrcVT.getStoreSizeInBits() &&
|
2008-01-24 04:39:46 +08:00
|
|
|
// Some targets pretend to have an i1 loading operation, and actually
|
|
|
|
// load an i8. This trick is correct for ZEXTLOAD because the top 7
|
|
|
|
// bits are guaranteed to be zero; it helps the optimizers understand
|
|
|
|
// that these bits are zero. It is also useful for EXTLOAD, since it
|
|
|
|
// tells the optimizers that those bits are undefined. It would be
|
|
|
|
// nice to have an effective generic way of getting these benefits...
|
|
|
|
// Until such a way is found, don't insist on promoting i1 here.
|
|
|
|
(SrcVT != MVT::i1 ||
|
2008-10-15 05:26:46 +08:00
|
|
|
TLI.getLoadExtAction(ExtType, MVT::i1) == TargetLowering::Promote)) {
|
2008-01-24 04:39:46 +08:00
|
|
|
// Promote to a byte-sized load if not loading an integral number of
|
|
|
|
// bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned NewWidth = SrcVT.getStoreSizeInBits();
|
|
|
|
MVT NVT = MVT::getIntegerVT(NewWidth);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Ch;
|
2008-01-24 04:39:46 +08:00
|
|
|
|
|
|
|
// The extra bits are guaranteed to be zero, since we stored them that
|
|
|
|
// way. A zext load from NVT thus automatically gives zext from SrcVT.
|
|
|
|
|
|
|
|
ISD::LoadExtType NewExtType =
|
|
|
|
ExtType == ISD::ZEXTLOAD ? ISD::ZEXTLOAD : ISD::EXTLOAD;
|
|
|
|
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0),
|
2008-01-24 04:39:46 +08:00
|
|
|
Tmp1, Tmp2, LD->getSrcValue(), SVOffset,
|
|
|
|
NVT, isVolatile, Alignment);
|
|
|
|
|
|
|
|
Ch = Result.getValue(1); // The chain.
|
|
|
|
|
|
|
|
if (ExtType == ISD::SEXTLOAD)
|
|
|
|
// Having the top bits zero doesn't help when sign extending.
|
2009-02-18 06:15:04 +08:00
|
|
|
Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl,
|
2009-02-03 07:46:53 +08:00
|
|
|
Result.getValueType(),
|
2008-01-24 04:39:46 +08:00
|
|
|
Result, DAG.getValueType(SrcVT));
|
|
|
|
else if (ExtType == ISD::ZEXTLOAD || NVT == Result.getValueType())
|
|
|
|
// All the top bits are guaranteed to be zero - inform the optimizers.
|
2009-02-18 06:15:04 +08:00
|
|
|
Result = DAG.getNode(ISD::AssertZext, dl,
|
2009-02-03 07:46:53 +08:00
|
|
|
Result.getValueType(), Result,
|
2008-01-24 04:39:46 +08:00
|
|
|
DAG.getValueType(SrcVT));
|
|
|
|
|
|
|
|
Tmp1 = LegalizeOp(Result);
|
|
|
|
Tmp2 = LegalizeOp(Ch);
|
|
|
|
} else if (SrcWidth & (SrcWidth - 1)) {
|
|
|
|
// If not loading a power-of-2 number of bits, expand as two loads.
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(SrcVT.isExtended() && !SrcVT.isVector() &&
|
2008-01-24 04:39:46 +08:00
|
|
|
"Unsupported extload!");
|
|
|
|
unsigned RoundWidth = 1 << Log2_32(SrcWidth);
|
|
|
|
assert(RoundWidth < SrcWidth);
|
|
|
|
unsigned ExtraWidth = SrcWidth - RoundWidth;
|
|
|
|
assert(ExtraWidth < RoundWidth);
|
|
|
|
assert(!(RoundWidth % 8) && !(ExtraWidth % 8) &&
|
|
|
|
"Load size not an integral number of bytes!");
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT RoundVT = MVT::getIntegerVT(RoundWidth);
|
|
|
|
MVT ExtraVT = MVT::getIntegerVT(ExtraWidth);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Lo, Hi, Ch;
|
2008-01-24 04:39:46 +08:00
|
|
|
unsigned IncrementSize;
|
|
|
|
|
|
|
|
if (TLI.isLittleEndian()) {
|
|
|
|
// EXTLOAD:i24 -> ZEXTLOAD:i16 | (shl EXTLOAD@+2:i8, 16)
|
|
|
|
// Load the bottom RoundWidth bits.
|
2009-02-03 07:46:53 +08:00
|
|
|
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl,
|
|
|
|
Node->getValueType(0), Tmp1, Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
LD->getSrcValue(), SVOffset, RoundVT, isVolatile,
|
|
|
|
Alignment);
|
|
|
|
|
|
|
|
// Load the remaining ExtraWidth bits.
|
|
|
|
IncrementSize = RoundWidth / 8;
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
LD->getSrcValue(), SVOffset + IncrementSize,
|
|
|
|
ExtraVT, isVolatile,
|
|
|
|
MinAlign(Alignment, IncrementSize));
|
|
|
|
|
|
|
|
// Build a factor node to remember that this load is independent of the
|
|
|
|
// other one.
|
2009-02-03 07:46:53 +08:00
|
|
|
Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
|
2008-01-24 04:39:46 +08:00
|
|
|
Hi.getValue(1));
|
|
|
|
|
|
|
|
// Move the top bits to the right place.
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
|
2008-01-24 04:39:46 +08:00
|
|
|
DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
|
|
|
|
|
|
|
|
// Join the hi and lo parts.
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
|
2007-08-02 03:34:21 +08:00
|
|
|
} else {
|
2008-01-24 04:39:46 +08:00
|
|
|
// Big endian - avoid unaligned loads.
|
|
|
|
// EXTLOAD:i24 -> (shl EXTLOAD:i16, 8) | ZEXTLOAD@+2:i8
|
|
|
|
// Load the top RoundWidth bits.
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
LD->getSrcValue(), SVOffset, RoundVT, isVolatile,
|
|
|
|
Alignment);
|
|
|
|
|
|
|
|
// Load the remaining ExtraWidth bits.
|
|
|
|
IncrementSize = RoundWidth / 8;
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2009-02-18 06:15:04 +08:00
|
|
|
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl,
|
2009-02-03 07:46:53 +08:00
|
|
|
Node->getValueType(0), Tmp1, Tmp2,
|
2008-01-24 04:39:46 +08:00
|
|
|
LD->getSrcValue(), SVOffset + IncrementSize,
|
|
|
|
ExtraVT, isVolatile,
|
|
|
|
MinAlign(Alignment, IncrementSize));
|
|
|
|
|
|
|
|
// Build a factor node to remember that this load is independent of the
|
|
|
|
// other one.
|
2009-02-03 07:46:53 +08:00
|
|
|
Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
|
2008-01-24 04:39:46 +08:00
|
|
|
Hi.getValue(1));
|
|
|
|
|
|
|
|
// Move the top bits to the right place.
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
|
2008-01-24 04:39:46 +08:00
|
|
|
DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
|
|
|
|
|
|
|
|
// Join the hi and lo parts.
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
|
2008-01-24 04:39:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Tmp1 = LegalizeOp(Result);
|
|
|
|
Tmp2 = LegalizeOp(Ch);
|
|
|
|
} else {
|
2008-10-15 05:26:46 +08:00
|
|
|
switch (TLI.getLoadExtAction(ExtType, SrcVT)) {
|
2008-01-24 04:39:46 +08:00
|
|
|
default: assert(0 && "This action is not supported yet!");
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
isCustom = true;
|
|
|
|
// FALLTHROUGH
|
|
|
|
case TargetLowering::Legal:
|
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset());
|
|
|
|
Tmp1 = Result.getValue(0);
|
|
|
|
Tmp2 = Result.getValue(1);
|
|
|
|
|
|
|
|
if (isCustom) {
|
|
|
|
Tmp3 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp3.getNode()) {
|
2008-01-24 04:39:46 +08:00
|
|
|
Tmp1 = LegalizeOp(Tmp3);
|
|
|
|
Tmp2 = LegalizeOp(Tmp3.getValue(1));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If this is an unaligned load and the target doesn't support it,
|
|
|
|
// expand it.
|
|
|
|
if (!TLI.allowsUnalignedMemoryAccesses()) {
|
|
|
|
unsigned ABIAlignment = TLI.getTargetData()->
|
2008-06-06 20:08:01 +08:00
|
|
|
getABITypeAlignment(LD->getMemoryVT().getTypeForMVT());
|
2008-01-24 04:39:46 +08:00
|
|
|
if (LD->getAlignment() < ABIAlignment){
|
2008-08-29 05:40:38 +08:00
|
|
|
Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.getNode()), DAG,
|
2008-01-24 04:39:46 +08:00
|
|
|
TLI);
|
|
|
|
Tmp1 = Result.getOperand(0);
|
|
|
|
Tmp2 = Result.getOperand(1);
|
|
|
|
Tmp1 = LegalizeOp(Tmp1);
|
|
|
|
Tmp2 = LegalizeOp(Tmp2);
|
|
|
|
}
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
|
|
|
}
|
2008-01-24 04:39:46 +08:00
|
|
|
break;
|
|
|
|
case TargetLowering::Expand:
|
|
|
|
// f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
|
|
|
|
if (SrcVT == MVT::f32 && Node->getValueType(0) == MVT::f64) {
|
2009-02-03 07:46:53 +08:00
|
|
|
SDValue Load = DAG.getLoad(SrcVT, dl, Tmp1, Tmp2, LD->getSrcValue(),
|
2008-01-24 04:39:46 +08:00
|
|
|
LD->getSrcValueOffset(),
|
|
|
|
LD->isVolatile(), LD->getAlignment());
|
2009-02-18 06:15:04 +08:00
|
|
|
Result = DAG.getNode(ISD::FP_EXTEND, dl,
|
2009-02-03 07:46:53 +08:00
|
|
|
Node->getValueType(0), Load);
|
2008-01-24 04:39:46 +08:00
|
|
|
Tmp1 = LegalizeOp(Result); // Relegalize new nodes.
|
|
|
|
Tmp2 = LegalizeOp(Load.getValue(1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert(ExtType != ISD::EXTLOAD &&"EXTLOAD should always be supported!");
|
|
|
|
// Turn the unsupported load into an EXTLOAD followed by an explicit
|
|
|
|
// zero/sign extend inreg.
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getExtLoad(ISD::EXTLOAD, dl, Node->getValueType(0),
|
2008-01-24 04:39:46 +08:00
|
|
|
Tmp1, Tmp2, LD->getSrcValue(),
|
|
|
|
LD->getSrcValueOffset(), SrcVT,
|
|
|
|
LD->isVolatile(), LD->getAlignment());
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue ValRes;
|
2008-01-24 04:39:46 +08:00
|
|
|
if (ExtType == ISD::SEXTLOAD)
|
2009-02-03 07:46:53 +08:00
|
|
|
ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl,
|
|
|
|
Result.getValueType(),
|
2008-01-24 04:39:46 +08:00
|
|
|
Result, DAG.getValueType(SrcVT));
|
|
|
|
else
|
2009-02-03 07:46:53 +08:00
|
|
|
ValRes = DAG.getZeroExtendInReg(Result, dl, SrcVT);
|
2008-01-24 04:39:46 +08:00
|
|
|
Tmp1 = LegalizeOp(ValRes); // Relegalize new nodes.
|
|
|
|
Tmp2 = LegalizeOp(Result.getValue(1)); // Relegalize new nodes.
|
2006-10-10 04:57:25 +08:00
|
|
|
break;
|
|
|
|
}
|
2005-07-01 03:22:37 +08:00
|
|
|
}
|
2008-01-24 04:39:46 +08:00
|
|
|
|
2006-10-10 04:57:25 +08:00
|
|
|
// Since loads produce two values, make sure to remember that we legalized
|
|
|
|
// both of them.
|
2008-07-28 05:46:04 +08:00
|
|
|
AddLegalizedOperand(SDValue(Node, 0), Tmp1);
|
|
|
|
AddLegalizedOperand(SDValue(Node, 1), Tmp2);
|
2008-08-27 06:36:50 +08:00
|
|
|
return Op.getResNo() ? Tmp2 : Tmp1;
|
2005-04-11 06:54:25 +08:00
|
|
|
}
|
|
|
|
}
|
2005-12-23 15:29:34 +08:00
|
|
|
case ISD::STORE: {
|
2006-10-14 05:14:26 +08:00
|
|
|
StoreSDNode *ST = cast<StoreSDNode>(Node);
|
|
|
|
Tmp1 = LegalizeOp(ST->getChain()); // Legalize the chain.
|
|
|
|
Tmp2 = LegalizeOp(ST->getBasePtr()); // Legalize the pointer.
|
2007-07-10 06:18:38 +08:00
|
|
|
int SVOffset = ST->getSrcValueOffset();
|
|
|
|
unsigned Alignment = ST->getAlignment();
|
|
|
|
bool isVolatile = ST->isVolatile();
|
2006-10-14 05:14:26 +08:00
|
|
|
|
|
|
|
if (!ST->isTruncatingStore()) {
|
2006-12-12 12:18:56 +08:00
|
|
|
// Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr'
|
|
|
|
// FIXME: We shouldn't do this for TargetConstantFP's.
|
|
|
|
// FIXME: move this to the DAG Combiner! Note that we can't regress due
|
|
|
|
// to phase ordering between legalized code and the dag combiner. This
|
|
|
|
// probably means that we need to integrate dag combiner and legalizer
|
|
|
|
// together.
|
2007-09-15 06:26:36 +08:00
|
|
|
// We generally can't do this one for long doubles.
|
2007-10-13 14:35:54 +08:00
|
|
|
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
|
2009-02-18 06:15:04 +08:00
|
|
|
if (CFP->getValueType(0) == MVT::f32 &&
|
2007-10-15 13:46:06 +08:00
|
|
|
getTypeAction(MVT::i32) == Legal) {
|
2008-03-11 08:11:06 +08:00
|
|
|
Tmp3 = DAG.getConstant(CFP->getValueAPF().
|
2008-10-10 02:53:47 +08:00
|
|
|
bitcastToAPInt().zextOrTrunc(32),
|
2007-09-12 02:32:33 +08:00
|
|
|
MVT::i32);
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
2007-09-15 06:26:36 +08:00
|
|
|
SVOffset, isVolatile, Alignment);
|
|
|
|
break;
|
|
|
|
} else if (CFP->getValueType(0) == MVT::f64) {
|
2007-10-15 13:46:06 +08:00
|
|
|
// If this target supports 64-bit registers, do a single 64-bit store.
|
|
|
|
if (getTypeAction(MVT::i64) == Legal) {
|
2008-10-10 02:53:47 +08:00
|
|
|
Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt().
|
2008-03-11 08:11:06 +08:00
|
|
|
zextOrTrunc(64), MVT::i64);
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
2007-10-15 13:46:06 +08:00
|
|
|
SVOffset, isVolatile, Alignment);
|
|
|
|
break;
|
Disable some DAG combiner optimizations that may be
wrong for volatile loads and stores. In fact this
is almost all of them! There are three types of
problems: (1) it is wrong to change the width of
a volatile memory access. These may be used to
do memory mapped i/o, in which case a load can have
an effect even if the result is not used. Consider
loading an i32 but only using the lower 8 bits. It
is wrong to change this into a load of an i8, because
you are no longer tickling the other three bytes. It
is also unwise to make a load/store wider. For
example, changing an i16 load into an i32 load is
wrong no matter how aligned things are, since the
fact of loading an additional 2 bytes can have
i/o side-effects. (2) it is wrong to change the
number of volatile load/stores: they may be counted
by the hardware. (3) it is wrong to change a volatile
load/store that requires one memory access into one
that requires several. For example on x86-32, you
can store a double in one processor operation, but to
store an i64 requires two (two i32 stores). In a
multi-threaded program you may want to bitcast an i64
to a double and store as a double because that will
occur atomically, and be indivisible to other threads.
So it would be wrong to convert the store-of-double
into a store of an i64, because this will become two
i32 stores - no longer atomic. My policy here is
to say that the number of processor operations for
an illegal operation is undefined. So it is alright
to change a store of an i64 (requires at least two
stores; but could be validly lowered to memcpy for
example) into a store of double (one processor op).
In short, if the new store is legal and has the same
size then I say that the transform is ok. It would
also be possible to say that transforms are always
ok if before they were illegal, whether after they
are illegal or not, but that's more awkward to do
and I doubt it buys us anything much.
However this exposed an interesting thing - on x86-32
a store of i64 is considered legal! That is because
operations are marked legal by default, regardless of
whether the type is legal or not. In some ways this
is clever: before type legalization this means that
operations on illegal types are considered legal;
after type legalization there are no illegal types
so now operations are only legal if they really are.
But I consider this to be too cunning for mere mortals.
Better to do things explicitly by testing AfterLegalize.
So I have changed things so that operations with illegal
types are considered illegal - indeed they can never
map to a machine operation. However this means that
the DAG combiner is more conservative because before
it was "accidentally" performing transforms where the
type was illegal because the operation was nonetheless
marked legal. So in a few such places I added a check
on AfterLegalize, which I suppose was actually just
forgotten before. This causes the DAG combiner to do
slightly more than it used to, which resulted in the X86
backend blowing up because it got a slightly surprising
node it wasn't expecting, so I tweaked it.
llvm-svn: 52254
2008-06-14 03:07:40 +08:00
|
|
|
} else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) {
|
2007-10-15 13:46:06 +08:00
|
|
|
// Otherwise, if the target supports 32-bit registers, use 2 32-bit
|
|
|
|
// stores. If the target supports neither 32- nor 64-bits, this
|
|
|
|
// xform is certainly not worth it.
|
2008-10-10 02:53:47 +08:00
|
|
|
const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32);
|
|
|
|
SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32);
|
2008-02-11 18:37:04 +08:00
|
|
|
if (TLI.isBigEndian()) std::swap(Lo, Hi);
|
2007-10-15 13:46:06 +08:00
|
|
|
|
2009-02-03 07:46:53 +08:00
|
|
|
Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(),
|
2007-10-15 13:46:06 +08:00
|
|
|
SVOffset, isVolatile, Alignment);
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
2008-01-17 15:00:52 +08:00
|
|
|
DAG.getIntPtrConstant(4));
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
|
2007-10-28 20:59:45 +08:00
|
|
|
isVolatile, MinAlign(Alignment, 4U));
|
2007-10-15 13:46:06 +08:00
|
|
|
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi);
|
2007-10-15 13:46:06 +08:00
|
|
|
break;
|
|
|
|
}
|
2006-12-12 12:18:56 +08:00
|
|
|
}
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2009-05-24 16:42:01 +08:00
|
|
|
{
|
2006-10-14 05:14:26 +08:00
|
|
|
Tmp3 = LegalizeOp(ST->getValue());
|
2009-02-18 06:15:04 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2,
|
2006-10-14 05:14:26 +08:00
|
|
|
ST->getOffset());
|
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Tmp3.getValueType();
|
2006-10-14 05:14:26 +08:00
|
|
|
switch (TLI.getOperationAction(ISD::STORE, VT)) {
|
|
|
|
default: assert(0 && "This action is not supported yet!");
|
2007-08-02 03:34:21 +08:00
|
|
|
case TargetLowering::Legal:
|
|
|
|
// If this is an unaligned store and the target doesn't support it,
|
|
|
|
// expand it.
|
|
|
|
if (!TLI.allowsUnalignedMemoryAccesses()) {
|
|
|
|
unsigned ABIAlignment = TLI.getTargetData()->
|
2008-06-06 20:08:01 +08:00
|
|
|
getABITypeAlignment(ST->getMemoryVT().getTypeForMVT());
|
2007-08-02 03:34:21 +08:00
|
|
|
if (ST->getAlignment() < ABIAlignment)
|
2008-08-29 05:40:38 +08:00
|
|
|
Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.getNode()), DAG,
|
2007-08-02 03:34:21 +08:00
|
|
|
TLI);
|
|
|
|
}
|
|
|
|
break;
|
2006-10-14 05:14:26 +08:00
|
|
|
case TargetLowering::Custom:
|
|
|
|
Tmp1 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp1.getNode()) Result = Tmp1;
|
2006-10-14 05:14:26 +08:00
|
|
|
break;
|
|
|
|
case TargetLowering::Promote:
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(VT.isVector() && "Unknown legal promote case!");
|
2009-02-18 06:15:04 +08:00
|
|
|
Tmp3 = DAG.getNode(ISD::BIT_CONVERT, dl,
|
2006-10-14 05:14:26 +08:00
|
|
|
TLI.getTypeToPromoteTo(ISD::STORE, VT), Tmp3);
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2,
|
2007-07-10 06:18:38 +08:00
|
|
|
ST->getSrcValue(), SVOffset, isVolatile,
|
|
|
|
Alignment);
|
2006-10-14 05:14:26 +08:00
|
|
|
break;
|
|
|
|
}
|
2006-04-16 09:36:45 +08:00
|
|
|
break;
|
2005-12-23 15:29:34 +08:00
|
|
|
}
|
2006-10-14 05:14:26 +08:00
|
|
|
} else {
|
2009-05-24 16:42:01 +08:00
|
|
|
Tmp3 = LegalizeOp(ST->getValue());
|
2008-01-22 15:17:34 +08:00
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT StVT = ST->getMemoryVT();
|
|
|
|
unsigned StWidth = StVT.getSizeInBits();
|
2008-01-22 15:17:34 +08:00
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
if (StWidth != StVT.getStoreSizeInBits()) {
|
2008-01-22 15:17:34 +08:00
|
|
|
// Promote to a byte-sized store with upper bits zero if not
|
|
|
|
// storing an integral number of bytes. For example, promote
|
|
|
|
// TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1)
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NVT = MVT::getIntegerVT(StVT.getStoreSizeInBits());
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp3 = DAG.getZeroExtendInReg(Tmp3, dl, StVT);
|
|
|
|
Result = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
2008-01-22 15:17:34 +08:00
|
|
|
SVOffset, NVT, isVolatile, Alignment);
|
|
|
|
} else if (StWidth & (StWidth - 1)) {
|
|
|
|
// If not storing a power-of-2 number of bits, expand as two stores.
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(StVT.isExtended() && !StVT.isVector() &&
|
2008-01-22 15:17:34 +08:00
|
|
|
"Unsupported truncstore!");
|
|
|
|
unsigned RoundWidth = 1 << Log2_32(StWidth);
|
|
|
|
assert(RoundWidth < StWidth);
|
|
|
|
unsigned ExtraWidth = StWidth - RoundWidth;
|
|
|
|
assert(ExtraWidth < RoundWidth);
|
|
|
|
assert(!(RoundWidth % 8) && !(ExtraWidth % 8) &&
|
|
|
|
"Store size not an integral number of bytes!");
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT RoundVT = MVT::getIntegerVT(RoundWidth);
|
|
|
|
MVT ExtraVT = MVT::getIntegerVT(ExtraWidth);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Lo, Hi;
|
2008-01-22 15:17:34 +08:00
|
|
|
unsigned IncrementSize;
|
|
|
|
|
|
|
|
if (TLI.isLittleEndian()) {
|
|
|
|
// TRUNCSTORE:i24 X -> TRUNCSTORE:i16 X, TRUNCSTORE@+2:i8 (srl X, 16)
|
|
|
|
// Store the bottom RoundWidth bits.
|
2009-02-03 07:46:53 +08:00
|
|
|
Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
2008-01-22 15:17:34 +08:00
|
|
|
SVOffset, RoundVT,
|
|
|
|
isVolatile, Alignment);
|
|
|
|
|
|
|
|
// Store the remaining ExtraWidth bits.
|
|
|
|
IncrementSize = RoundWidth / 8;
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
2008-01-22 15:17:34 +08:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
|
2008-01-22 15:17:34 +08:00
|
|
|
DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(),
|
2008-01-22 15:17:34 +08:00
|
|
|
SVOffset + IncrementSize, ExtraVT, isVolatile,
|
|
|
|
MinAlign(Alignment, IncrementSize));
|
|
|
|
} else {
|
|
|
|
// Big endian - avoid unaligned stores.
|
|
|
|
// TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X
|
|
|
|
// Store the top RoundWidth bits.
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
|
2008-01-22 15:17:34 +08:00
|
|
|
DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
|
2009-02-03 07:46:53 +08:00
|
|
|
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(),
|
|
|
|
SVOffset, RoundVT, isVolatile, Alignment);
|
2008-01-22 15:17:34 +08:00
|
|
|
|
|
|
|
// Store the remaining ExtraWidth bits.
|
|
|
|
IncrementSize = RoundWidth / 8;
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
2008-01-22 15:17:34 +08:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2009-02-03 07:46:53 +08:00
|
|
|
Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
2008-01-22 15:17:34 +08:00
|
|
|
SVOffset + IncrementSize, ExtraVT, isVolatile,
|
|
|
|
MinAlign(Alignment, IncrementSize));
|
|
|
|
}
|
2006-03-18 09:44:44 +08:00
|
|
|
|
2008-01-22 15:17:34 +08:00
|
|
|
// The order of the stores doesn't matter.
|
2009-02-03 07:46:53 +08:00
|
|
|
Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi);
|
2008-01-22 15:17:34 +08:00
|
|
|
} else {
|
|
|
|
if (Tmp1 != ST->getChain() || Tmp3 != ST->getValue() ||
|
|
|
|
Tmp2 != ST->getBasePtr())
|
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2,
|
|
|
|
ST->getOffset());
|
|
|
|
|
|
|
|
switch (TLI.getTruncStoreAction(ST->getValue().getValueType(), StVT)) {
|
|
|
|
default: assert(0 && "This action is not supported yet!");
|
|
|
|
case TargetLowering::Legal:
|
|
|
|
// If this is an unaligned store and the target doesn't support it,
|
|
|
|
// expand it.
|
|
|
|
if (!TLI.allowsUnalignedMemoryAccesses()) {
|
|
|
|
unsigned ABIAlignment = TLI.getTargetData()->
|
2008-06-06 20:08:01 +08:00
|
|
|
getABITypeAlignment(ST->getMemoryVT().getTypeForMVT());
|
2008-01-22 15:17:34 +08:00
|
|
|
if (ST->getAlignment() < ABIAlignment)
|
2008-08-29 05:40:38 +08:00
|
|
|
Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.getNode()), DAG,
|
2008-01-22 15:17:34 +08:00
|
|
|
TLI);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
Result = TLI.LowerOperation(Result, DAG);
|
|
|
|
break;
|
|
|
|
case Expand:
|
|
|
|
// TRUNCSTORE:i16 i32 -> STORE i16
|
|
|
|
assert(isTypeLegal(StVT) && "Do not know how to expand this store!");
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp3 = DAG.getNode(ISD::TRUNCATE, dl, StVT, Tmp3);
|
|
|
|
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
|
|
|
SVOffset, isVolatile, Alignment);
|
2008-01-22 15:17:34 +08:00
|
|
|
break;
|
2007-08-02 03:34:21 +08:00
|
|
|
}
|
2006-10-14 05:14:26 +08:00
|
|
|
}
|
2005-01-07 15:47:09 +08:00
|
|
|
}
|
|
|
|
break;
|
2005-12-23 15:29:34 +08:00
|
|
|
}
|
2006-02-01 15:19:44 +08:00
|
|
|
case ISD::SELECT_CC: {
|
|
|
|
Tmp1 = Node->getOperand(0); // LHS
|
|
|
|
Tmp2 = Node->getOperand(1); // RHS
|
2005-08-11 04:51:12 +08:00
|
|
|
Tmp3 = LegalizeOp(Node->getOperand(2)); // True
|
|
|
|
Tmp4 = LegalizeOp(Node->getOperand(3)); // False
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue CC = Node->getOperand(4);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
LegalizeSetCC(TLI.getSetCCResultType(Tmp1.getValueType()),
|
2009-02-03 04:41:04 +08:00
|
|
|
Tmp1, Tmp2, CC, dl);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-10-15 10:05:31 +08:00
|
|
|
// If we didn't get both a LHS and RHS back from LegalizeSetCC,
|
2006-02-01 15:19:44 +08:00
|
|
|
// the LHS is a legal SETCC itself. In this case, we need to compare
|
|
|
|
// the result against zero to select between true and false values.
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp2.getNode() == 0) {
|
2006-02-01 15:19:44 +08:00
|
|
|
Tmp2 = DAG.getConstant(0, Tmp1.getValueType());
|
|
|
|
CC = DAG.getCondCode(ISD::SETNE);
|
|
|
|
}
|
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, CC);
|
|
|
|
|
|
|
|
// Everything is legal, see if we should expand this op or something.
|
|
|
|
switch (TLI.getOperationAction(ISD::SELECT_CC, Tmp3.getValueType())) {
|
|
|
|
default: assert(0 && "This action is not supported yet!");
|
|
|
|
case TargetLowering::Legal: break;
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
Tmp1 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp1.getNode()) Result = Tmp1;
|
2005-08-11 04:51:12 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2006-02-01 15:19:44 +08:00
|
|
|
}
|
2005-01-07 15:47:09 +08:00
|
|
|
case ISD::SETCC:
|
2006-02-01 15:19:44 +08:00
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
Tmp2 = Node->getOperand(1);
|
|
|
|
Tmp3 = Node->getOperand(2);
|
2009-02-03 04:41:04 +08:00
|
|
|
LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, Tmp3, dl);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
// If we had to Expand the SetCC operands into a SELECT node, then it may
|
|
|
|
// not always be possible to return a true LHS & RHS. In this case, just
|
2006-02-01 15:19:44 +08:00
|
|
|
// return the value we legalized, returned in the LHS
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp2.getNode() == 0) {
|
2006-02-01 15:19:44 +08:00
|
|
|
Result = Tmp1;
|
2005-01-07 15:47:09 +08:00
|
|
|
break;
|
|
|
|
}
|
2005-08-23 12:29:48 +08:00
|
|
|
|
2006-01-31 06:43:50 +08:00
|
|
|
switch (TLI.getOperationAction(ISD::SETCC, Tmp1.getValueType())) {
|
2006-01-28 15:39:30 +08:00
|
|
|
default: assert(0 && "Cannot handle this action for SETCC yet!");
|
|
|
|
case TargetLowering::Custom:
|
|
|
|
isCustom = true;
|
|
|
|
// FALLTHROUGH.
|
|
|
|
case TargetLowering::Legal:
|
2006-12-15 10:59:56 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
|
2006-01-28 15:39:30 +08:00
|
|
|
if (isCustom) {
|
2006-12-15 10:59:56 +08:00
|
|
|
Tmp4 = TLI.LowerOperation(Result, DAG);
|
2008-08-29 05:40:38 +08:00
|
|
|
if (Tmp4.getNode()) Result = Tmp4;
|
2006-01-28 15:39:30 +08:00
|
|
|
}
|
2005-08-23 12:29:48 +08:00
|
|
|
break;
|
2005-12-01 01:12:26 +08:00
|
|
|
case TargetLowering::Promote: {
|
|
|
|
// First step, figure out the appropriate operation to use.
|
|
|
|
// Allow SETCC to not be supported for all legal data types
|
|
|
|
// Mostly this targets FP
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NewInTy = Node->getOperand(0).getValueType();
|
|
|
|
MVT OldVT = NewInTy; OldVT = OldVT;
|
2005-12-01 01:12:26 +08:00
|
|
|
|
|
|
|
// Scan for the appropriate larger type to use.
|
|
|
|
while (1) {
|
2008-06-06 20:08:01 +08:00
|
|
|
NewInTy = (MVT::SimpleValueType)(NewInTy.getSimpleVT()+1);
|
2005-12-01 01:12:26 +08:00
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(NewInTy.isInteger() == OldVT.isInteger() &&
|
2005-12-01 01:12:26 +08:00
|
|
|
"Fell off of the edge of the integer world");
|
2008-06-06 20:08:01 +08:00
|
|
|
assert(NewInTy.isFloatingPoint() == OldVT.isFloatingPoint() &&
|
2005-12-01 01:12:26 +08:00
|
|
|
"Fell off of the edge of the floating point world");
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-12-01 01:12:26 +08:00
|
|
|
// If the target supports SETCC of this type, use it.
|
2009-01-29 01:46:25 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::SETCC, NewInTy))
|
2005-12-01 01:12:26 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-06-06 20:08:01 +08:00
|
|
|
if (NewInTy.isInteger())
|
2005-12-01 01:12:26 +08:00
|
|
|
assert(0 && "Cannot promote Legal Integer SETCC yet");
|
|
|
|
else {
|
2009-02-03 07:46:53 +08:00
|
|
|
Tmp1 = DAG.getNode(ISD::FP_EXTEND, dl, NewInTy, Tmp1);
|
|
|
|
Tmp2 = DAG.getNode(ISD::FP_EXTEND, dl, NewInTy, Tmp2);
|
2005-12-01 01:12:26 +08:00
|
|
|
}
|
2006-01-28 18:58:55 +08:00
|
|
|
Tmp1 = LegalizeOp(Tmp1);
|
|
|
|
Tmp2 = LegalizeOp(Tmp2);
|
2006-12-15 10:59:56 +08:00
|
|
|
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
|
2006-01-18 03:47:13 +08:00
|
|
|
Result = LegalizeOp(Result);
|
2005-08-30 04:46:51 +08:00
|
|
|
break;
|
2005-12-01 01:12:26 +08:00
|
|
|
}
|
2005-08-23 12:29:48 +08:00
|
|
|
case TargetLowering::Expand:
|
|
|
|
// Expand a setcc node into a select_cc of the same condition, lhs, and
|
|
|
|
// rhs that selects between const 1 (true) and const 0 (false).
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Node->getValueType(0);
|
2009-02-18 06:15:04 +08:00
|
|
|
Result = DAG.getNode(ISD::SELECT_CC, dl, VT, Tmp1, Tmp2,
|
2005-08-23 12:29:48 +08:00
|
|
|
DAG.getConstant(1, VT), DAG.getConstant(0, VT),
|
2006-12-15 10:59:56 +08:00
|
|
|
Tmp3);
|
2005-08-23 12:29:48 +08:00
|
|
|
break;
|
|
|
|
}
|
2005-01-07 15:47:09 +08:00
|
|
|
break;
|
2005-01-15 15:15:18 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-04-08 12:13:17 +08:00
|
|
|
assert(Result.getValueType() == Op.getValueType() &&
|
|
|
|
"Bad legalization!");
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-01-28 15:39:30 +08:00
|
|
|
// Make sure that the generated code is itself legal.
|
|
|
|
if (Result != Op)
|
|
|
|
Result = LegalizeOp(Result);
|
2005-01-07 15:47:09 +08:00
|
|
|
|
2005-05-13 00:53:42 +08:00
|
|
|
// Note that LegalizeOp may be reentered even from single-use nodes, which
|
|
|
|
// means that we always must cache transformed nodes.
|
|
|
|
AddLegalizedOperand(Op, Result);
|
2005-01-07 15:47:09 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-05-24 06:37:25 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) {
|
|
|
|
SDValue Vec = Op.getOperand(0);
|
|
|
|
SDValue Idx = Op.getOperand(1);
|
|
|
|
DebugLoc dl = Op.getDebugLoc();
|
|
|
|
// Store the value to a temporary stack slot, then LOAD the returned part.
|
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType());
|
|
|
|
SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0);
|
|
|
|
|
|
|
|
// Add the offset to the index.
|
2009-05-24 07:03:28 +08:00
|
|
|
unsigned EltSize =
|
|
|
|
Vec.getValueType().getVectorElementType().getSizeInBits()/8;
|
2009-05-24 06:37:25 +08:00
|
|
|
Idx = DAG.getNode(ISD::MUL, dl, Idx.getValueType(), Idx,
|
|
|
|
DAG.getConstant(EltSize, Idx.getValueType()));
|
|
|
|
|
|
|
|
if (Idx.getValueType().bitsGT(TLI.getPointerTy()))
|
|
|
|
Idx = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Idx);
|
|
|
|
else
|
|
|
|
Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx);
|
|
|
|
|
|
|
|
StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr);
|
|
|
|
|
|
|
|
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2009-05-27 20:20:41 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) {
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
|
|
|
SDValue Tmp1 = Node->getOperand(0);
|
|
|
|
SDValue Tmp2 = Node->getOperand(1);
|
|
|
|
assert((Tmp2.getValueType() == MVT::f32 ||
|
|
|
|
Tmp2.getValueType() == MVT::f64) &&
|
|
|
|
"Ugly special-cased code!");
|
|
|
|
// Get the sign bit of the RHS.
|
|
|
|
SDValue SignBit;
|
|
|
|
MVT IVT = Tmp2.getValueType() == MVT::f64 ? MVT::i64 : MVT::i32;
|
|
|
|
if (isTypeLegal(IVT)) {
|
|
|
|
SignBit = DAG.getNode(ISD::BIT_CONVERT, dl, IVT, Tmp2);
|
|
|
|
} else {
|
|
|
|
assert(isTypeLegal(TLI.getPointerTy()) &&
|
|
|
|
(TLI.getPointerTy() == MVT::i32 ||
|
|
|
|
TLI.getPointerTy() == MVT::i64) &&
|
|
|
|
"Legal type for load?!");
|
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType());
|
|
|
|
SDValue StorePtr = StackPtr, LoadPtr = StackPtr;
|
|
|
|
SDValue Ch =
|
|
|
|
DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0);
|
|
|
|
if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian())
|
|
|
|
LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(),
|
|
|
|
LoadPtr, DAG.getIntPtrConstant(4));
|
|
|
|
SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(),
|
|
|
|
Ch, LoadPtr, NULL, 0, MVT::i32);
|
|
|
|
}
|
|
|
|
SignBit =
|
|
|
|
DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()),
|
|
|
|
SignBit, DAG.getConstant(0, SignBit.getValueType()),
|
|
|
|
ISD::SETLT);
|
|
|
|
// Get the absolute value of the result.
|
|
|
|
SDValue AbsVal = DAG.getNode(ISD::FABS, dl, Tmp1.getValueType(), Tmp1);
|
|
|
|
// Select between the nabs and abs value based on the sign bit of
|
|
|
|
// the input.
|
|
|
|
return DAG.getNode(ISD::SELECT, dl, AbsVal.getValueType(), SignBit,
|
|
|
|
DAG.getNode(ISD::FNEG, dl, AbsVal.getValueType(), AbsVal),
|
|
|
|
AbsVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue SelectionDAGLegalize::ExpandDBG_STOPPOINT(SDNode* Node) {
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
|
|
|
DwarfWriter *DW = DAG.getDwarfWriter();
|
|
|
|
bool useDEBUG_LOC = TLI.isOperationLegalOrCustom(ISD::DEBUG_LOC,
|
|
|
|
MVT::Other);
|
|
|
|
bool useLABEL = TLI.isOperationLegalOrCustom(ISD::DBG_LABEL, MVT::Other);
|
|
|
|
|
|
|
|
const DbgStopPointSDNode *DSP = cast<DbgStopPointSDNode>(Node);
|
|
|
|
GlobalVariable *CU_GV = cast<GlobalVariable>(DSP->getCompileUnit());
|
|
|
|
if (DW && (useDEBUG_LOC || useLABEL) && !CU_GV->isDeclaration()) {
|
|
|
|
DICompileUnit CU(cast<GlobalVariable>(DSP->getCompileUnit()));
|
|
|
|
|
|
|
|
unsigned Line = DSP->getLine();
|
|
|
|
unsigned Col = DSP->getColumn();
|
|
|
|
|
|
|
|
if (OptLevel == CodeGenOpt::None) {
|
|
|
|
// A bit self-referential to have DebugLoc on Debug_Loc nodes, but it
|
|
|
|
// won't hurt anything.
|
|
|
|
if (useDEBUG_LOC) {
|
|
|
|
return DAG.getNode(ISD::DEBUG_LOC, dl, MVT::Other, Node->getOperand(0),
|
|
|
|
DAG.getConstant(Line, MVT::i32),
|
|
|
|
DAG.getConstant(Col, MVT::i32),
|
|
|
|
DAG.getSrcValue(CU.getGV()));
|
|
|
|
} else {
|
|
|
|
unsigned ID = DW->RecordSourceLine(Line, Col, CU);
|
|
|
|
return DAG.getLabel(ISD::DBG_LABEL, dl, Node->getOperand(0), ID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Node->getOperand(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
|
|
|
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
|
|
|
|
assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
|
|
|
|
" not tell us which reg is the stack pointer!");
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
SDValue Tmp1 = SDValue(Node, 0);
|
|
|
|
SDValue Tmp2 = SDValue(Node, 1);
|
|
|
|
SDValue Tmp3 = Node->getOperand(2);
|
|
|
|
SDValue Chain = Tmp1.getOperand(0);
|
|
|
|
|
|
|
|
// Chain the dynamic stack allocation so that it doesn't modify the stack
|
|
|
|
// pointer when other instructions are using the stack.
|
|
|
|
Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true));
|
|
|
|
|
|
|
|
SDValue Size = Tmp2.getOperand(1);
|
|
|
|
SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
|
|
|
|
Chain = SP.getValue(1);
|
|
|
|
unsigned Align = cast<ConstantSDNode>(Tmp3)->getZExtValue();
|
|
|
|
unsigned StackAlign =
|
|
|
|
TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
|
|
|
|
if (Align > StackAlign)
|
|
|
|
SP = DAG.getNode(ISD::AND, dl, VT, SP,
|
|
|
|
DAG.getConstant(-(uint64_t)Align, VT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
|
|
|
|
Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain
|
|
|
|
|
|
|
|
Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true),
|
|
|
|
DAG.getIntPtrConstant(0, true), SDValue());
|
|
|
|
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
Results.push_back(Tmp2);
|
|
|
|
}
|
|
|
|
|
2006-02-01 15:19:44 +08:00
|
|
|
/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC
|
|
|
|
/// with condition CC on the current target. This usually involves legalizing
|
|
|
|
/// or promoting the arguments. In the case where LHS and RHS must be expanded,
|
|
|
|
/// there may be no choice but to create a new SetCC node to represent the
|
|
|
|
/// legalized value of setcc lhs, rhs. In this case, the value is returned in
|
2008-07-28 05:46:04 +08:00
|
|
|
/// LHS, and the SDValue returned in RHS has a nil SDNode value.
|
|
|
|
void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS,
|
|
|
|
SDValue &RHS,
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue &CC,
|
|
|
|
DebugLoc dl) {
|
2009-05-26 16:55:52 +08:00
|
|
|
LHS = LegalizeOp(LHS);
|
|
|
|
RHS = LegalizeOp(RHS);
|
|
|
|
}
|
2006-02-01 15:19:44 +08:00
|
|
|
|
2008-10-15 10:05:31 +08:00
|
|
|
/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and
|
|
|
|
/// condition code CC on the current target. This routine assumes LHS and rHS
|
|
|
|
/// have already been legalized by LegalizeSetCCOperands. It expands SETCC with
|
|
|
|
/// illegal condition code into AND / OR of multiple SETCC values.
|
|
|
|
void SelectionDAGLegalize::LegalizeSetCCCondCode(MVT VT,
|
|
|
|
SDValue &LHS, SDValue &RHS,
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue &CC,
|
|
|
|
DebugLoc dl) {
|
2008-10-15 10:05:31 +08:00
|
|
|
MVT OpVT = LHS.getValueType();
|
|
|
|
ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
|
|
|
|
switch (TLI.getCondCodeAction(CCCode, OpVT)) {
|
|
|
|
default: assert(0 && "Unknown condition code action!");
|
|
|
|
case TargetLowering::Legal:
|
|
|
|
// Nothing to do.
|
|
|
|
break;
|
|
|
|
case TargetLowering::Expand: {
|
|
|
|
ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID;
|
|
|
|
unsigned Opc = 0;
|
|
|
|
switch (CCCode) {
|
|
|
|
default: assert(0 && "Don't know how to expand this condition!"); abort();
|
2008-10-21 11:12:54 +08:00
|
|
|
case ISD::SETOEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETOGT: CC1 = ISD::SETGT; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETOGE: CC1 = ISD::SETGE; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETOLT: CC1 = ISD::SETLT; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETOLE: CC1 = ISD::SETLE; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETONE: CC1 = ISD::SETNE; CC2 = ISD::SETO; Opc = ISD::AND; break;
|
|
|
|
case ISD::SETUEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
|
|
|
case ISD::SETUGT: CC1 = ISD::SETGT; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
|
|
|
case ISD::SETUGE: CC1 = ISD::SETGE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
|
|
|
case ISD::SETULT: CC1 = ISD::SETLT; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
|
|
|
case ISD::SETULE: CC1 = ISD::SETLE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
|
|
|
case ISD::SETUNE: CC1 = ISD::SETNE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
|
2008-10-15 10:05:31 +08:00
|
|
|
// FIXME: Implement more expansions.
|
|
|
|
}
|
|
|
|
|
2009-02-03 04:41:04 +08:00
|
|
|
SDValue SetCC1 = DAG.getSetCC(dl, VT, LHS, RHS, CC1);
|
|
|
|
SDValue SetCC2 = DAG.getSetCC(dl, VT, LHS, RHS, CC2);
|
|
|
|
LHS = DAG.getNode(Opc, dl, VT, SetCC1, SetCC2);
|
2008-10-15 10:05:31 +08:00
|
|
|
RHS = SDValue();
|
|
|
|
CC = SDValue();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-16 15:45:30 +08:00
|
|
|
/// EmitStackConvert - Emit a store/load combination to the stack. This stores
|
|
|
|
/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does
|
|
|
|
/// a load from the stack slot to DestVT, extending it if needed.
|
|
|
|
/// The resultant code need not be legal.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp,
|
|
|
|
MVT SlotVT,
|
2009-02-03 06:12:50 +08:00
|
|
|
MVT DestVT,
|
|
|
|
DebugLoc dl) {
|
2005-12-23 08:16:34 +08:00
|
|
|
// Create the stack frame object.
|
2009-04-11 02:48:47 +08:00
|
|
|
unsigned SrcAlign =
|
|
|
|
TLI.getTargetData()->getPrefTypeAlignment(SrcOp.getValueType().
|
|
|
|
getTypeForMVT());
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue FIPtr = DAG.CreateStackTemporary(SlotVT, SrcAlign);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-02-12 02:58:42 +08:00
|
|
|
FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(FIPtr);
|
2008-02-07 06:27:42 +08:00
|
|
|
int SPFI = StackPtrFI->getIndex();
|
2009-01-30 05:02:43 +08:00
|
|
|
const Value *SV = PseudoSourceValue::getFixedStack(SPFI);
|
|
|
|
|
2008-06-06 20:08:01 +08:00
|
|
|
unsigned SrcSize = SrcOp.getValueType().getSizeInBits();
|
|
|
|
unsigned SlotSize = SlotVT.getSizeInBits();
|
|
|
|
unsigned DestSize = DestVT.getSizeInBits();
|
2009-04-11 02:48:47 +08:00
|
|
|
unsigned DestAlign =
|
|
|
|
TLI.getTargetData()->getPrefTypeAlignment(DestVT.getTypeForMVT());
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-01-16 15:45:30 +08:00
|
|
|
// Emit a store to the stack slot. Use a truncstore if the input value is
|
|
|
|
// later than DestVT.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Store;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-01-16 15:45:30 +08:00
|
|
|
if (SrcSize > SlotSize)
|
2009-02-03 06:12:50 +08:00
|
|
|
Store = DAG.getTruncStore(DAG.getEntryNode(), dl, SrcOp, FIPtr,
|
2009-01-30 05:02:43 +08:00
|
|
|
SV, 0, SlotVT, false, SrcAlign);
|
2008-01-16 15:45:30 +08:00
|
|
|
else {
|
|
|
|
assert(SrcSize == SlotSize && "Invalid store");
|
2009-02-03 06:12:50 +08:00
|
|
|
Store = DAG.getStore(DAG.getEntryNode(), dl, SrcOp, FIPtr,
|
2009-01-30 05:02:43 +08:00
|
|
|
SV, 0, false, SrcAlign);
|
2008-01-16 15:45:30 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-12-23 08:16:34 +08:00
|
|
|
// Result is a load from the stack slot.
|
2008-01-16 15:45:30 +08:00
|
|
|
if (SlotSize == DestSize)
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, DestAlign);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-01-16 15:45:30 +08:00
|
|
|
assert(SlotSize < DestSize && "Unknown extension!");
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, Store, FIPtr, SV, 0, SlotVT,
|
2008-07-06 04:40:31 +08:00
|
|
|
false, DestAlign);
|
2005-12-23 08:16:34 +08:00
|
|
|
}
|
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) {
|
2009-02-03 06:12:50 +08:00
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
2006-04-05 01:23:26 +08:00
|
|
|
// Create a vector sized/aligned stack slot, store the value to element #0,
|
|
|
|
// then load the whole vector back out.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(Node->getValueType(0));
|
2008-02-07 06:27:42 +08:00
|
|
|
|
2008-02-12 02:58:42 +08:00
|
|
|
FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr);
|
2008-02-07 06:27:42 +08:00
|
|
|
int SPFI = StackPtrFI->getIndex();
|
|
|
|
|
2009-04-19 04:16:54 +08:00
|
|
|
SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0),
|
|
|
|
StackPtr,
|
|
|
|
PseudoSourceValue::getFixedStack(SPFI), 0,
|
|
|
|
Node->getValueType(0).getVectorElementType());
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr,
|
2008-07-12 06:44:52 +08:00
|
|
|
PseudoSourceValue::getFixedStack(SPFI), 0);
|
2006-04-05 01:23:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-19 14:31:19 +08:00
|
|
|
/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
|
2007-07-16 22:29:03 +08:00
|
|
|
/// support the operation, but do support the resultant vector type.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
2009-04-14 04:20:30 +08:00
|
|
|
unsigned NumElems = Node->getNumOperands();
|
|
|
|
SDValue SplatValue = Node->getOperand(0);
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
MVT OpVT = SplatValue.getValueType();
|
|
|
|
MVT EltVT = VT.getVectorElementType();
|
2009-02-18 06:15:04 +08:00
|
|
|
|
|
|
|
// If the only non-undef value is the low element, turn this into a
|
2006-03-20 09:52:29 +08:00
|
|
|
// SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X.
|
2006-03-19 14:31:19 +08:00
|
|
|
bool isOnlyLowElement = true;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
// FIXME: it would be far nicer to change this into map<SDValue,uint64_t>
|
2008-03-09 08:29:42 +08:00
|
|
|
// and use a bitmask instead of a list of elements.
|
2009-04-28 02:41:29 +08:00
|
|
|
// FIXME: this doesn't treat <0, u, 0, u> for example, as a splat.
|
2008-07-28 05:46:04 +08:00
|
|
|
std::map<SDValue, std::vector<unsigned> > Values;
|
2006-03-24 09:17:21 +08:00
|
|
|
Values[SplatValue].push_back(0);
|
2006-03-24 15:29:17 +08:00
|
|
|
bool isConstant = true;
|
|
|
|
if (!isa<ConstantFPSDNode>(SplatValue) && !isa<ConstantSDNode>(SplatValue) &&
|
|
|
|
SplatValue.getOpcode() != ISD::UNDEF)
|
|
|
|
isConstant = false;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-24 09:17:21 +08:00
|
|
|
for (unsigned i = 1; i < NumElems; ++i) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue V = Node->getOperand(i);
|
2006-04-20 07:17:50 +08:00
|
|
|
Values[V].push_back(i);
|
2006-03-24 09:17:21 +08:00
|
|
|
if (V.getOpcode() != ISD::UNDEF)
|
2006-03-19 14:31:19 +08:00
|
|
|
isOnlyLowElement = false;
|
2006-03-24 09:17:21 +08:00
|
|
|
if (SplatValue != V)
|
2009-04-11 02:48:47 +08:00
|
|
|
SplatValue = SDValue(0, 0);
|
2006-03-24 15:29:17 +08:00
|
|
|
|
|
|
|
// If this isn't a constant element or an undef, we can't use a constant
|
|
|
|
// pool load.
|
|
|
|
if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V) &&
|
|
|
|
V.getOpcode() != ISD::UNDEF)
|
|
|
|
isConstant = false;
|
2006-03-19 14:31:19 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-19 14:31:19 +08:00
|
|
|
if (isOnlyLowElement) {
|
|
|
|
// If the low element is an undef too, then this whole things is an undef.
|
|
|
|
if (Node->getOperand(0).getOpcode() == ISD::UNDEF)
|
2009-04-14 04:20:30 +08:00
|
|
|
return DAG.getUNDEF(VT);
|
2006-03-19 14:31:19 +08:00
|
|
|
// Otherwise, turn this into a scalar_to_vector node.
|
2009-04-14 04:20:30 +08:00
|
|
|
return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Node->getOperand(0));
|
2006-03-19 14:31:19 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-24 15:29:17 +08:00
|
|
|
// If all elements are constants, create a load from the constant pool.
|
2006-03-19 14:31:19 +08:00
|
|
|
if (isConstant) {
|
|
|
|
std::vector<Constant*> CV;
|
2006-03-24 09:17:21 +08:00
|
|
|
for (unsigned i = 0, e = NumElems; i != e; ++i) {
|
2009-02-18 06:15:04 +08:00
|
|
|
if (ConstantFPSDNode *V =
|
2006-03-19 14:31:19 +08:00
|
|
|
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
|
2008-09-13 02:08:03 +08:00
|
|
|
CV.push_back(const_cast<ConstantFP *>(V->getConstantFPValue()));
|
2009-02-18 06:15:04 +08:00
|
|
|
} else if (ConstantSDNode *V =
|
2009-04-11 02:48:47 +08:00
|
|
|
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
|
2008-09-13 02:08:03 +08:00
|
|
|
CV.push_back(const_cast<ConstantInt *>(V->getConstantIntValue()));
|
2006-03-19 14:31:19 +08:00
|
|
|
} else {
|
|
|
|
assert(Node->getOperand(i).getOpcode() == ISD::UNDEF);
|
2009-04-14 04:20:30 +08:00
|
|
|
const Type *OpNTy = OpVT.getTypeForMVT();
|
2006-03-19 14:31:19 +08:00
|
|
|
CV.push_back(UndefValue::get(OpNTy));
|
|
|
|
}
|
|
|
|
}
|
2007-02-15 10:26:10 +08:00
|
|
|
Constant *CP = ConstantVector::get(CV);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy());
|
2009-03-13 15:51:59 +08:00
|
|
|
unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx,
|
2008-09-17 06:05:41 +08:00
|
|
|
PseudoSourceValue::getConstantPool(), 0,
|
|
|
|
false, Alignment);
|
2006-03-19 14:31:19 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-08-29 05:40:38 +08:00
|
|
|
if (SplatValue.getNode()) { // Splat of one value?
|
2006-03-24 15:29:17 +08:00
|
|
|
// Build the shuffle constant vector: <0, 0, 0, 0>
|
2009-04-28 02:41:29 +08:00
|
|
|
SmallVector<int, 8> ZeroVec(NumElems, 0);
|
2006-03-24 09:17:21 +08:00
|
|
|
|
2006-03-24 15:29:17 +08:00
|
|
|
// If the target supports VECTOR_SHUFFLE and this shuffle mask, use it.
|
2009-04-28 02:41:29 +08:00
|
|
|
if (TLI.isShuffleMaskLegal(ZeroVec, Node->getValueType(0))) {
|
2006-03-24 15:29:17 +08:00
|
|
|
// Get the splatted value into the low element of a vector register.
|
2009-02-18 06:15:04 +08:00
|
|
|
SDValue LowValVec =
|
2009-04-14 04:20:30 +08:00
|
|
|
DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, SplatValue);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-24 15:29:17 +08:00
|
|
|
// Return shuffle(LowValVec, undef, <0,0,0,0>)
|
2009-04-28 02:41:29 +08:00
|
|
|
return DAG.getVectorShuffle(VT, dl, LowValVec, DAG.getUNDEF(VT),
|
|
|
|
&ZeroVec[0]);
|
2006-03-24 15:29:17 +08:00
|
|
|
}
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-24 09:17:21 +08:00
|
|
|
// If there are only two unique elements, we may be able to turn this into a
|
|
|
|
// vector shuffle.
|
|
|
|
if (Values.size() == 2) {
|
2008-03-09 08:29:42 +08:00
|
|
|
// Get the two values in deterministic order.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Val1 = Node->getOperand(1);
|
|
|
|
SDValue Val2;
|
|
|
|
std::map<SDValue, std::vector<unsigned> >::iterator MI = Values.begin();
|
2008-03-09 08:29:42 +08:00
|
|
|
if (MI->first != Val1)
|
|
|
|
Val2 = MI->first;
|
|
|
|
else
|
|
|
|
Val2 = (++MI)->first;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2009-04-11 02:48:47 +08:00
|
|
|
// If Val1 is an undef, make sure it ends up as Val2, to ensure that our
|
2008-03-09 08:29:42 +08:00
|
|
|
// vector shuffle has the undef vector on the RHS.
|
|
|
|
if (Val1.getOpcode() == ISD::UNDEF)
|
|
|
|
std::swap(Val1, Val2);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-24 09:17:21 +08:00
|
|
|
// Build the shuffle constant vector: e.g. <0, 4, 0, 4>
|
2009-04-28 02:41:29 +08:00
|
|
|
SmallVector<int, 8> ShuffleMask(NumElems, -1);
|
2008-03-09 08:29:42 +08:00
|
|
|
|
|
|
|
// Set elements of the shuffle mask for Val1.
|
|
|
|
std::vector<unsigned> &Val1Elts = Values[Val1];
|
|
|
|
for (unsigned i = 0, e = Val1Elts.size(); i != e; ++i)
|
2009-04-28 02:41:29 +08:00
|
|
|
ShuffleMask[Val1Elts[i]] = 0;
|
2008-03-09 08:29:42 +08:00
|
|
|
|
|
|
|
// Set elements of the shuffle mask for Val2.
|
|
|
|
std::vector<unsigned> &Val2Elts = Values[Val2];
|
|
|
|
for (unsigned i = 0, e = Val2Elts.size(); i != e; ++i)
|
|
|
|
if (Val2.getOpcode() != ISD::UNDEF)
|
2009-04-28 02:41:29 +08:00
|
|
|
ShuffleMask[Val2Elts[i]] = NumElems;
|
2006-03-24 09:17:21 +08:00
|
|
|
|
2008-03-09 08:29:42 +08:00
|
|
|
// If the target supports SCALAR_TO_VECTOR and this shuffle mask, use it.
|
2009-04-14 04:20:30 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::SCALAR_TO_VECTOR, VT) &&
|
2009-04-28 02:41:29 +08:00
|
|
|
TLI.isShuffleMaskLegal(ShuffleMask, VT)) {
|
2009-04-14 04:20:30 +08:00
|
|
|
Val1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val1);
|
|
|
|
Val2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val2);
|
2009-04-28 02:41:29 +08:00
|
|
|
return DAG.getVectorShuffle(VT, dl, Val1, Val2, &ShuffleMask[0]);
|
2006-03-24 09:17:21 +08:00
|
|
|
}
|
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-19 14:31:19 +08:00
|
|
|
// Otherwise, we can't handle this case efficiently. Allocate a sufficiently
|
|
|
|
// aligned object on the stack, store each element into it, then load
|
|
|
|
// the result as a vector.
|
|
|
|
// Create the stack frame object.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue FIPtr = DAG.CreateStackTemporary(VT);
|
2009-01-30 05:02:43 +08:00
|
|
|
int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
|
|
|
const Value *SV = PseudoSourceValue::getFixedStack(FI);
|
|
|
|
|
2006-03-19 14:31:19 +08:00
|
|
|
// Emit a store of each element to the stack slot.
|
2008-07-28 05:46:04 +08:00
|
|
|
SmallVector<SDValue, 8> Stores;
|
2009-04-14 04:20:30 +08:00
|
|
|
unsigned TypeByteSize = OpVT.getSizeInBits() / 8;
|
2006-03-19 14:31:19 +08:00
|
|
|
// Store (in the right endianness) the elements to memory.
|
|
|
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
|
|
|
// Ignore undef elements.
|
|
|
|
if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-22 09:46:54 +08:00
|
|
|
unsigned Offset = TypeByteSize*i;
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType());
|
2009-02-03 06:12:50 +08:00
|
|
|
Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2009-02-03 06:12:50 +08:00
|
|
|
Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, Node->getOperand(i),
|
|
|
|
Idx, SV, Offset));
|
2006-03-19 14:31:19 +08:00
|
|
|
}
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue StoreChain;
|
2006-03-19 14:31:19 +08:00
|
|
|
if (!Stores.empty()) // Not all undef elements?
|
2009-02-03 06:12:50 +08:00
|
|
|
StoreChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
2006-08-08 10:23:42 +08:00
|
|
|
&Stores[0], Stores.size());
|
2006-03-19 14:31:19 +08:00
|
|
|
else
|
|
|
|
StoreChain = DAG.getEntryNode();
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-03-19 14:31:19 +08:00
|
|
|
// Result is a load from the stack slot.
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0);
|
2006-03-19 14:31:19 +08:00
|
|
|
}
|
|
|
|
|
2005-01-21 14:05:23 +08:00
|
|
|
// ExpandLibCall - Expand a node into a call to a libcall. If the result value
|
|
|
|
// does not fit into a register, return the lo part and set the hi part to the
|
|
|
|
// by-reg argument. If it does fit into a single register, return the result
|
|
|
|
// and leave the Hi part unset.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node,
|
2009-05-27 10:21:29 +08:00
|
|
|
bool isSigned) {
|
2006-02-13 17:18:02 +08:00
|
|
|
assert(!IsLegalizingCall && "Cannot overlap legalization of calls!");
|
2009-02-18 06:15:04 +08:00
|
|
|
// The input chain to this libcall is the entry node of the function.
|
2006-02-13 17:18:02 +08:00
|
|
|
// Legalizing the call will automatically add the previous call to the
|
|
|
|
// dependence.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue InChain = DAG.getEntryNode();
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2005-01-21 14:05:23 +08:00
|
|
|
TargetLowering::ArgListTy Args;
|
2006-12-31 13:55:36 +08:00
|
|
|
TargetLowering::ArgListEntry Entry;
|
2005-01-21 14:05:23 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT ArgVT = Node->getOperand(i).getValueType();
|
|
|
|
const Type *ArgTy = ArgVT.getTypeForMVT();
|
2009-02-18 06:15:04 +08:00
|
|
|
Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy;
|
2007-03-08 00:25:09 +08:00
|
|
|
Entry.isSExt = isSigned;
|
2008-02-15 01:28:50 +08:00
|
|
|
Entry.isZExt = !isSigned;
|
2006-12-31 13:55:36 +08:00
|
|
|
Args.push_back(Entry);
|
2005-01-21 14:05:23 +08:00
|
|
|
}
|
2008-09-17 05:48:12 +08:00
|
|
|
SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
|
2008-10-30 16:01:45 +08:00
|
|
|
TLI.getPointerTy());
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2005-05-12 03:02:11 +08:00
|
|
|
// Splice the libcall in wherever FindInputOutputChains tells us to.
|
2008-06-06 20:08:01 +08:00
|
|
|
const Type *RetTy = Node->getValueType(0).getTypeForMVT();
|
2009-04-11 02:48:47 +08:00
|
|
|
std::pair<SDValue, SDValue> CallInfo =
|
2008-09-27 03:31:26 +08:00
|
|
|
TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
|
2009-01-31 07:10:59 +08:00
|
|
|
CallingConv::C, false, Callee, Args, DAG,
|
|
|
|
Node->getDebugLoc());
|
2005-05-12 03:02:11 +08:00
|
|
|
|
2006-02-13 17:18:02 +08:00
|
|
|
// Legalize the call sequence, starting with the chain. This will advance
|
|
|
|
// the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that
|
|
|
|
// was added by LowerCallTo (guaranteeing proper serialization of calls).
|
|
|
|
LegalizeOp(CallInfo.second);
|
2009-05-26 16:55:52 +08:00
|
|
|
return CallInfo.first;
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
|
2009-05-27 11:33:44 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
|
|
|
|
RTLIB::Libcall Call_F32,
|
|
|
|
RTLIB::Libcall Call_F64,
|
|
|
|
RTLIB::Libcall Call_F80,
|
|
|
|
RTLIB::Libcall Call_PPCF128) {
|
|
|
|
RTLIB::Libcall LC;
|
|
|
|
switch (Node->getValueType(0).getSimpleVT()) {
|
|
|
|
default: assert(0 && "Unexpected request for libcall!");
|
|
|
|
case MVT::f32: LC = Call_F32; break;
|
|
|
|
case MVT::f64: LC = Call_F64; break;
|
|
|
|
case MVT::f80: LC = Call_F80; break;
|
|
|
|
case MVT::ppcf128: LC = Call_PPCF128; break;
|
|
|
|
}
|
|
|
|
return ExpandLibCall(LC, Node, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned,
|
|
|
|
RTLIB::Libcall Call_I16,
|
|
|
|
RTLIB::Libcall Call_I32,
|
|
|
|
RTLIB::Libcall Call_I64,
|
|
|
|
RTLIB::Libcall Call_I128) {
|
|
|
|
RTLIB::Libcall LC;
|
|
|
|
switch (Node->getValueType(0).getSimpleVT()) {
|
|
|
|
default: assert(0 && "Unexpected request for libcall!");
|
|
|
|
case MVT::i16: LC = Call_I16; break;
|
|
|
|
case MVT::i32: LC = Call_I32; break;
|
|
|
|
case MVT::i64: LC = Call_I64; break;
|
|
|
|
case MVT::i128: LC = Call_I128; break;
|
|
|
|
}
|
|
|
|
return ExpandLibCall(LC, Node, isSigned);
|
|
|
|
}
|
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a
|
|
|
|
/// INT_TO_FP operation of the specified operand when the target requests that
|
|
|
|
/// we expand it. At this point, we know that the result and operand types are
|
|
|
|
/// legal for the target.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
|
|
|
SDValue Op0,
|
2009-02-03 03:03:57 +08:00
|
|
|
MVT DestVT,
|
|
|
|
DebugLoc dl) {
|
2006-01-28 16:25:58 +08:00
|
|
|
if (Op0.getValueType() == MVT::i32) {
|
|
|
|
// simple 32-bit [signed|unsigned] integer to float/double expansion
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2008-01-16 15:03:22 +08:00
|
|
|
// Get the stack frame index of a 8 byte buffer.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue StackSlot = DAG.CreateStackTemporary(MVT::f64);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
// word offset constant for Hi/Lo address computation
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy());
|
2006-01-28 16:25:58 +08:00
|
|
|
// set up Hi and Lo (into buffer) address based on endian
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Hi = StackSlot;
|
2009-02-18 06:15:04 +08:00
|
|
|
SDValue Lo = DAG.getNode(ISD::ADD, dl,
|
2009-04-11 02:48:47 +08:00
|
|
|
TLI.getPointerTy(), StackSlot, WordOff);
|
2006-03-23 13:29:04 +08:00
|
|
|
if (TLI.isLittleEndian())
|
|
|
|
std::swap(Hi, Lo);
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
// if signed map to unsigned space
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Op0Mapped;
|
2006-01-28 16:25:58 +08:00
|
|
|
if (isSigned) {
|
|
|
|
// constant used to invert sign bit (signed to unsigned mapping)
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SignBit = DAG.getConstant(0x80000000u, MVT::i32);
|
2009-02-03 03:03:57 +08:00
|
|
|
Op0Mapped = DAG.getNode(ISD::XOR, dl, MVT::i32, Op0, SignBit);
|
2006-01-28 16:25:58 +08:00
|
|
|
} else {
|
|
|
|
Op0Mapped = Op0;
|
|
|
|
}
|
|
|
|
// store the lo of the constructed double - based on integer input
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl,
|
2009-04-11 02:48:47 +08:00
|
|
|
Op0Mapped, Lo, NULL, 0);
|
2006-01-28 16:25:58 +08:00
|
|
|
// initial hi portion of constructed double
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue InitialHi = DAG.getConstant(0x43300000u, MVT::i32);
|
2006-01-28 16:25:58 +08:00
|
|
|
// store the hi of the constructed double - biased exponent
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0);
|
2006-01-28 16:25:58 +08:00
|
|
|
// load the constructed double
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0);
|
2006-01-28 16:25:58 +08:00
|
|
|
// FP constant to bias correct the final result
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Bias = DAG.getConstantFP(isSigned ?
|
2009-04-11 02:48:47 +08:00
|
|
|
BitsToDouble(0x4330000080000000ULL) :
|
|
|
|
BitsToDouble(0x4330000000000000ULL),
|
2006-01-28 16:25:58 +08:00
|
|
|
MVT::f64);
|
|
|
|
// subtract the bias
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Load, Bias);
|
2006-01-28 16:25:58 +08:00
|
|
|
// final result
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Result;
|
2006-01-28 16:25:58 +08:00
|
|
|
// handle final rounding
|
|
|
|
if (DestVT == MVT::f64) {
|
|
|
|
// do nothing
|
|
|
|
Result = Sub;
|
2008-06-09 04:54:56 +08:00
|
|
|
} else if (DestVT.bitsLT(MVT::f64)) {
|
2009-02-03 03:03:57 +08:00
|
|
|
Result = DAG.getNode(ISD::FP_ROUND, dl, DestVT, Sub,
|
2008-01-17 15:00:52 +08:00
|
|
|
DAG.getIntPtrConstant(0));
|
2008-06-09 04:54:56 +08:00
|
|
|
} else if (DestVT.bitsGT(MVT::f64)) {
|
2009-02-03 03:03:57 +08:00
|
|
|
Result = DAG.getNode(ISD::FP_EXTEND, dl, DestVT, Sub);
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0);
|
2006-01-28 16:25:58 +08:00
|
|
|
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue SignSet = DAG.getSetCC(dl, TLI.getSetCCResultType(Op0.getValueType()),
|
2009-01-01 23:52:00 +08:00
|
|
|
Op0, DAG.getConstant(0, Op0.getValueType()),
|
|
|
|
ISD::SETLT);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue CstOffset = DAG.getNode(ISD::SELECT, dl, Zero.getValueType(),
|
2006-01-28 16:25:58 +08:00
|
|
|
SignSet, Four, Zero);
|
|
|
|
|
|
|
|
// If the sign bit of the integer is set, the large number will be treated
|
|
|
|
// as a negative number. To counteract this, the dynamic code adds an
|
|
|
|
// offset depending on the data type.
|
|
|
|
uint64_t FF;
|
2008-06-06 20:08:01 +08:00
|
|
|
switch (Op0.getValueType().getSimpleVT()) {
|
2006-01-28 16:25:58 +08:00
|
|
|
default: assert(0 && "Unsupported integer type!");
|
|
|
|
case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float)
|
|
|
|
case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float)
|
|
|
|
case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float)
|
|
|
|
case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float)
|
|
|
|
}
|
|
|
|
if (TLI.isLittleEndian()) FF <<= 32;
|
2009-03-08 09:47:41 +08:00
|
|
|
Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF);
|
2006-01-28 16:25:58 +08:00
|
|
|
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
|
2009-03-13 15:51:59 +08:00
|
|
|
unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
|
2009-02-03 03:03:57 +08:00
|
|
|
CPIdx = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), CPIdx, CstOffset);
|
2008-09-23 06:40:08 +08:00
|
|
|
Alignment = std::min(Alignment, 4u);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue FudgeInReg;
|
2006-01-28 16:25:58 +08:00
|
|
|
if (DestVT == MVT::f32)
|
2009-02-03 03:03:57 +08:00
|
|
|
FudgeInReg = DAG.getLoad(MVT::f32, dl, DAG.getEntryNode(), CPIdx,
|
2008-09-17 06:05:41 +08:00
|
|
|
PseudoSourceValue::getConstantPool(), 0,
|
|
|
|
false, Alignment);
|
2006-01-28 16:25:58 +08:00
|
|
|
else {
|
2008-02-07 06:27:42 +08:00
|
|
|
FudgeInReg =
|
2009-02-03 03:03:57 +08:00
|
|
|
LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT,
|
2008-02-07 06:27:42 +08:00
|
|
|
DAG.getEntryNode(), CPIdx,
|
2008-02-08 02:41:25 +08:00
|
|
|
PseudoSourceValue::getConstantPool(), 0,
|
2008-09-17 06:05:41 +08:00
|
|
|
MVT::f32, false, Alignment));
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
|
2009-02-03 03:03:57 +08:00
|
|
|
return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg);
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a
|
|
|
|
/// *INT_TO_FP operation of the specified operand when the target requests that
|
|
|
|
/// we promote it. At this point, we know that the result and operand types are
|
|
|
|
/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP
|
|
|
|
/// operation that takes a larger input.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp,
|
|
|
|
MVT DestVT,
|
2009-02-03 03:03:57 +08:00
|
|
|
bool isSigned,
|
|
|
|
DebugLoc dl) {
|
2006-01-28 16:25:58 +08:00
|
|
|
// First step, figure out the appropriate *INT_TO_FP operation to use.
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NewInTy = LegalOp.getValueType();
|
2006-01-28 16:25:58 +08:00
|
|
|
|
|
|
|
unsigned OpToUse = 0;
|
|
|
|
|
|
|
|
// Scan for the appropriate larger type to use.
|
|
|
|
while (1) {
|
2008-06-06 20:08:01 +08:00
|
|
|
NewInTy = (MVT::SimpleValueType)(NewInTy.getSimpleVT()+1);
|
|
|
|
assert(NewInTy.isInteger() && "Ran out of possibilities!");
|
2006-01-28 16:25:58 +08:00
|
|
|
|
|
|
|
// If the target supports SINT_TO_FP of this type, use it.
|
2009-05-28 11:06:16 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, NewInTy)) {
|
|
|
|
OpToUse = ISD::SINT_TO_FP;
|
|
|
|
break;
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
if (isSigned) continue;
|
|
|
|
|
|
|
|
// If the target supports UINT_TO_FP of this type, use it.
|
2009-05-28 11:06:16 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, NewInTy)) {
|
|
|
|
OpToUse = ISD::UINT_TO_FP;
|
|
|
|
break;
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, try a larger type.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, we found the operation and type to use. Zero extend our input to the
|
|
|
|
// desired type then run the operation on it.
|
2009-02-03 03:03:57 +08:00
|
|
|
return DAG.getNode(OpToUse, dl, DestVT,
|
2006-01-28 16:25:58 +08:00
|
|
|
DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
|
2009-02-03 03:03:57 +08:00
|
|
|
dl, NewInTy, LegalOp));
|
2005-01-21 14:05:23 +08:00
|
|
|
}
|
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a
|
|
|
|
/// FP_TO_*INT operation of the specified operand when the target requests that
|
|
|
|
/// we promote it. At this point, we know that the result and operand types are
|
|
|
|
/// legal for the target, and that there is a legal FP_TO_UINT or FP_TO_SINT
|
|
|
|
/// operation that returns a larger result.
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp,
|
|
|
|
MVT DestVT,
|
2009-02-03 03:03:57 +08:00
|
|
|
bool isSigned,
|
|
|
|
DebugLoc dl) {
|
2006-01-28 16:25:58 +08:00
|
|
|
// First step, figure out the appropriate FP_TO*INT operation to use.
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT NewOutTy = DestVT;
|
2005-01-23 12:42:50 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
unsigned OpToUse = 0;
|
2005-04-13 13:09:42 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
// Scan for the appropriate larger type to use.
|
|
|
|
while (1) {
|
2008-06-06 20:08:01 +08:00
|
|
|
NewOutTy = (MVT::SimpleValueType)(NewOutTy.getSimpleVT()+1);
|
|
|
|
assert(NewOutTy.isInteger() && "Ran out of possibilities!");
|
2005-05-13 12:45:13 +08:00
|
|
|
|
2009-05-28 11:06:16 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NewOutTy)) {
|
2006-01-28 16:25:58 +08:00
|
|
|
OpToUse = ISD::FP_TO_SINT;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-13 13:09:42 +08:00
|
|
|
|
2009-05-28 11:06:16 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NewOutTy)) {
|
2006-01-28 16:25:58 +08:00
|
|
|
OpToUse = ISD::FP_TO_UINT;
|
|
|
|
break;
|
2005-04-13 13:09:42 +08:00
|
|
|
}
|
2005-05-12 03:02:11 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
// Otherwise, try a larger type.
|
2005-05-14 13:33:54 +08:00
|
|
|
}
|
|
|
|
|
2009-02-18 06:15:04 +08:00
|
|
|
|
2007-11-24 15:07:01 +08:00
|
|
|
// Okay, we found the operation and type to use.
|
2009-02-03 03:03:57 +08:00
|
|
|
SDValue Operation = DAG.getNode(OpToUse, dl, NewOutTy, LegalOp);
|
2008-07-04 19:47:58 +08:00
|
|
|
|
2007-11-24 15:07:01 +08:00
|
|
|
// Truncate the result of the extended FP_TO_*INT operation to the desired
|
|
|
|
// size.
|
2009-02-03 03:03:57 +08:00
|
|
|
return DAG.getNode(ISD::TRUNCATE, dl, DestVT, Operation);
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
2005-05-12 15:00:44 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation.
|
|
|
|
///
|
2009-02-03 06:12:50 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) {
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Op.getValueType();
|
|
|
|
MVT SHVT = TLI.getShiftAmountTy();
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8;
|
2008-06-06 20:08:01 +08:00
|
|
|
switch (VT.getSimpleVT()) {
|
2006-01-28 16:25:58 +08:00
|
|
|
default: assert(0 && "Unhandled Expand type in BSWAP!"); abort();
|
|
|
|
case MVT::i16:
|
2009-02-03 06:12:50 +08:00
|
|
|
Tmp2 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
return DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2);
|
2006-01-28 16:25:58 +08:00
|
|
|
case MVT::i32:
|
2009-02-03 06:12:50 +08:00
|
|
|
Tmp4 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT));
|
|
|
|
Tmp3 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT));
|
|
|
|
Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(0xFF0000, VT));
|
|
|
|
Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(0xFF00, VT));
|
|
|
|
Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3);
|
|
|
|
Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1);
|
|
|
|
return DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2);
|
2006-01-28 16:25:58 +08:00
|
|
|
case MVT::i64:
|
2009-02-03 06:12:50 +08:00
|
|
|
Tmp8 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(56, SHVT));
|
|
|
|
Tmp7 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(40, SHVT));
|
|
|
|
Tmp6 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT));
|
|
|
|
Tmp5 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
Tmp4 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT));
|
|
|
|
Tmp3 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT));
|
|
|
|
Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(40, SHVT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(56, SHVT));
|
|
|
|
Tmp7 = DAG.getNode(ISD::AND, dl, VT, Tmp7, DAG.getConstant(255ULL<<48, VT));
|
|
|
|
Tmp6 = DAG.getNode(ISD::AND, dl, VT, Tmp6, DAG.getConstant(255ULL<<40, VT));
|
|
|
|
Tmp5 = DAG.getNode(ISD::AND, dl, VT, Tmp5, DAG.getConstant(255ULL<<32, VT));
|
|
|
|
Tmp4 = DAG.getNode(ISD::AND, dl, VT, Tmp4, DAG.getConstant(255ULL<<24, VT));
|
|
|
|
Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(255ULL<<16, VT));
|
|
|
|
Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT));
|
|
|
|
Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp7);
|
|
|
|
Tmp6 = DAG.getNode(ISD::OR, dl, VT, Tmp6, Tmp5);
|
|
|
|
Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3);
|
|
|
|
Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1);
|
|
|
|
Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp6);
|
|
|
|
Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2);
|
|
|
|
return DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp4);
|
2005-05-12 03:02:11 +08:00
|
|
|
}
|
2005-01-21 14:05:23 +08:00
|
|
|
}
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2006-01-28 16:25:58 +08:00
|
|
|
/// ExpandBitCount - Expand the specified bitcount instruction into operations.
|
|
|
|
///
|
2009-02-18 06:15:04 +08:00
|
|
|
SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
|
2009-02-03 06:12:50 +08:00
|
|
|
DebugLoc dl) {
|
2006-01-28 16:25:58 +08:00
|
|
|
switch (Opc) {
|
|
|
|
default: assert(0 && "Cannot expand this yet!");
|
|
|
|
case ISD::CTPOP: {
|
|
|
|
static const uint64_t mask[6] = {
|
|
|
|
0x5555555555555555ULL, 0x3333333333333333ULL,
|
|
|
|
0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
|
|
|
|
0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
|
|
|
|
};
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Op.getValueType();
|
|
|
|
MVT ShVT = TLI.getShiftAmountTy();
|
|
|
|
unsigned len = VT.getSizeInBits();
|
2006-01-28 16:25:58 +08:00
|
|
|
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
|
|
|
|
//x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8])
|
2009-02-02 02:06:53 +08:00
|
|
|
unsigned EltSize = VT.isVector() ?
|
|
|
|
VT.getVectorElementType().getSizeInBits() : len;
|
|
|
|
SDValue Tmp2 = DAG.getConstant(APInt(EltSize, mask[i]), VT);
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT);
|
2009-02-18 06:15:04 +08:00
|
|
|
Op = DAG.getNode(ISD::ADD, dl, VT,
|
2009-02-07 05:55:48 +08:00
|
|
|
DAG.getNode(ISD::AND, dl, VT, Op, Tmp2),
|
2009-02-03 06:12:50 +08:00
|
|
|
DAG.getNode(ISD::AND, dl, VT,
|
|
|
|
DAG.getNode(ISD::SRL, dl, VT, Op, Tmp3),
|
|
|
|
Tmp2));
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
case ISD::CTLZ: {
|
|
|
|
// for now, we do this:
|
|
|
|
// x = x | (x >> 1);
|
|
|
|
// x = x | (x >> 2);
|
|
|
|
// ...
|
|
|
|
// x = x | (x >>16);
|
|
|
|
// x = x | (x >>32); // for 64-bit input
|
|
|
|
// return popcount(~x);
|
|
|
|
//
|
|
|
|
// but see also: http://www.hackersdelight.org/HDcode/nlz.cc
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Op.getValueType();
|
|
|
|
MVT ShVT = TLI.getShiftAmountTy();
|
|
|
|
unsigned len = VT.getSizeInBits();
|
2006-01-28 16:25:58 +08:00
|
|
|
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
|
2008-07-28 05:46:04 +08:00
|
|
|
SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT);
|
2009-02-18 06:15:04 +08:00
|
|
|
Op = DAG.getNode(ISD::OR, dl, VT, Op,
|
2009-02-07 05:55:48 +08:00
|
|
|
DAG.getNode(ISD::SRL, dl, VT, Op, Tmp3));
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
2009-02-03 06:12:50 +08:00
|
|
|
Op = DAG.getNOT(dl, Op, VT);
|
|
|
|
return DAG.getNode(ISD::CTPOP, dl, VT, Op);
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
case ISD::CTTZ: {
|
|
|
|
// for now, we use: { return popcount(~x & (x - 1)); }
|
|
|
|
// unless the target has ctlz but not ctpop, in which case we use:
|
|
|
|
// { return 32 - nlz(~x & (x-1)); }
|
|
|
|
// see also http://www.hackersdelight.org/HDcode/ntz.cc
|
2008-06-06 20:08:01 +08:00
|
|
|
MVT VT = Op.getValueType();
|
2009-02-03 06:12:50 +08:00
|
|
|
SDValue Tmp3 = DAG.getNode(ISD::AND, dl, VT,
|
|
|
|
DAG.getNOT(dl, Op, VT),
|
|
|
|
DAG.getNode(ISD::SUB, dl, VT, Op,
|
2009-01-31 07:03:19 +08:00
|
|
|
DAG.getConstant(1, VT)));
|
2006-01-28 16:25:58 +08:00
|
|
|
// If ISD::CTLZ is legal and CTPOP isn't, then do that instead.
|
2009-01-29 01:46:25 +08:00
|
|
|
if (!TLI.isOperationLegalOrCustom(ISD::CTPOP, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::CTLZ, VT))
|
2009-02-03 06:12:50 +08:00
|
|
|
return DAG.getNode(ISD::SUB, dl, VT,
|
2008-06-06 20:08:01 +08:00
|
|
|
DAG.getConstant(VT.getSizeInBits(), VT),
|
2009-02-03 06:12:50 +08:00
|
|
|
DAG.getNode(ISD::CTLZ, dl, VT, Tmp3));
|
|
|
|
return DAG.getNode(ISD::CTPOP, dl, VT, Tmp3);
|
2006-01-28 16:25:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-01-19 12:19:40 +08:00
|
|
|
|
2009-05-27 09:25:56 +08:00
|
|
|
void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
2009-05-27 11:33:44 +08:00
|
|
|
SDValue Tmp1, Tmp2, Tmp3;
|
2009-05-27 09:25:56 +08:00
|
|
|
switch (Node->getOpcode()) {
|
|
|
|
case ISD::CTPOP:
|
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTTZ:
|
|
|
|
Tmp1 = ExpandBitCount(Node->getOpcode(), Node->getOperand(0), dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::BSWAP:
|
|
|
|
Results.push_back(ExpandBSWAP(Node->getOperand(0), dl));
|
|
|
|
break;
|
|
|
|
case ISD::FRAMEADDR:
|
|
|
|
case ISD::RETURNADDR:
|
|
|
|
case ISD::FRAME_TO_ARGS_OFFSET:
|
|
|
|
Results.push_back(DAG.getConstant(0, Node->getValueType(0)));
|
|
|
|
break;
|
|
|
|
case ISD::FLT_ROUNDS_:
|
|
|
|
Results.push_back(DAG.getConstant(1, Node->getValueType(0)));
|
|
|
|
break;
|
|
|
|
case ISD::EH_RETURN:
|
|
|
|
case ISD::DECLARE:
|
|
|
|
case ISD::DBG_LABEL:
|
|
|
|
case ISD::EH_LABEL:
|
|
|
|
case ISD::PREFETCH:
|
|
|
|
case ISD::MEMBARRIER:
|
|
|
|
case ISD::VAEND:
|
|
|
|
Results.push_back(Node->getOperand(0));
|
|
|
|
break;
|
2009-05-27 20:20:41 +08:00
|
|
|
case ISD::DBG_STOPPOINT:
|
|
|
|
Results.push_back(ExpandDBG_STOPPOINT(Node));
|
|
|
|
break;
|
|
|
|
case ISD::DYNAMIC_STACKALLOC:
|
|
|
|
ExpandDYNAMIC_STACKALLOC(Node, Results);
|
|
|
|
break;
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::MERGE_VALUES:
|
|
|
|
for (unsigned i = 0; i < Node->getNumValues(); i++)
|
|
|
|
Results.push_back(Node->getOperand(i));
|
|
|
|
break;
|
|
|
|
case ISD::UNDEF: {
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
if (VT.isInteger())
|
|
|
|
Results.push_back(DAG.getConstant(0, VT));
|
|
|
|
else if (VT.isFloatingPoint())
|
|
|
|
Results.push_back(DAG.getConstantFP(0, VT));
|
|
|
|
else
|
|
|
|
assert(0 && "Unknown value type!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::TRAP: {
|
|
|
|
// If this operation is not supported, lower it to 'abort()' call
|
|
|
|
TargetLowering::ArgListTy Args;
|
|
|
|
std::pair<SDValue, SDValue> CallResult =
|
|
|
|
TLI.LowerCallTo(Node->getOperand(0), Type::VoidTy,
|
|
|
|
false, false, false, false, CallingConv::C, false,
|
|
|
|
DAG.getExternalSymbol("abort", TLI.getPointerTy()),
|
|
|
|
Args, DAG, dl);
|
|
|
|
Results.push_back(CallResult.second);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::FP_ROUND:
|
|
|
|
case ISD::BIT_CONVERT:
|
|
|
|
Tmp1 = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
|
|
|
|
Node->getValueType(0), dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::FP_EXTEND:
|
|
|
|
Tmp1 = EmitStackConvert(Node->getOperand(0),
|
|
|
|
Node->getOperand(0).getValueType(),
|
|
|
|
Node->getValueType(0), dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::SIGN_EXTEND_INREG: {
|
|
|
|
// NOTE: we could fall back on load/store here too for targets without
|
|
|
|
// SAR. However, it is doubtful that any exist.
|
|
|
|
MVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
|
|
|
|
unsigned BitsDiff = Node->getValueType(0).getSizeInBits() -
|
|
|
|
ExtraVT.getSizeInBits();
|
|
|
|
SDValue ShiftCst = DAG.getConstant(BitsDiff, TLI.getShiftAmountTy());
|
|
|
|
Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0),
|
|
|
|
Node->getOperand(0), ShiftCst);
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, ShiftCst);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::FP_ROUND_INREG: {
|
|
|
|
// The only way we can lower this is to turn it into a TRUNCSTORE,
|
|
|
|
// EXTLOAD pair, targetting a temporary location (a stack slot).
|
|
|
|
|
|
|
|
// NOTE: there is a choice here between constantly creating new stack
|
|
|
|
// slots and always reusing the same one. We currently always create
|
|
|
|
// new ones, as reuse may inhibit scheduling.
|
|
|
|
MVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
|
|
|
|
Tmp1 = EmitStackConvert(Node->getOperand(0), ExtraVT,
|
|
|
|
Node->getValueType(0), dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
case ISD::UINT_TO_FP:
|
|
|
|
Tmp1 = ExpandLegalINT_TO_FP(Node->getOpcode() == ISD::SINT_TO_FP,
|
|
|
|
Node->getOperand(0), Node->getValueType(0), dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::FP_TO_UINT: {
|
|
|
|
SDValue True, False;
|
|
|
|
MVT VT = Node->getOperand(0).getValueType();
|
|
|
|
MVT NVT = Node->getValueType(0);
|
|
|
|
const uint64_t zero[] = {0, 0};
|
|
|
|
APFloat apf = APFloat(APInt(VT.getSizeInBits(), 2, zero));
|
|
|
|
APInt x = APInt::getSignBit(NVT.getSizeInBits());
|
|
|
|
(void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven);
|
|
|
|
Tmp1 = DAG.getConstantFP(apf, VT);
|
|
|
|
Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(VT),
|
|
|
|
Node->getOperand(0),
|
|
|
|
Tmp1, ISD::SETLT);
|
|
|
|
True = DAG.getNode(ISD::FP_TO_SINT, dl, NVT, Node->getOperand(0));
|
|
|
|
False = DAG.getNode(ISD::FP_TO_SINT, dl, NVT,
|
|
|
|
DAG.getNode(ISD::FSUB, dl, VT,
|
|
|
|
Node->getOperand(0), Tmp1));
|
|
|
|
False = DAG.getNode(ISD::XOR, dl, NVT, False,
|
|
|
|
DAG.getConstant(x, NVT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2, True, False);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:58:35 +08:00
|
|
|
case ISD::VAARG: {
|
|
|
|
const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
Tmp2 = Node->getOperand(1);
|
|
|
|
SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0);
|
|
|
|
// Increment the pointer, VAList, to the next vaarg
|
|
|
|
Tmp3 = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList,
|
|
|
|
DAG.getConstant(TLI.getTargetData()->
|
|
|
|
getTypeAllocSize(VT.getTypeForMVT()),
|
|
|
|
TLI.getPointerTy()));
|
|
|
|
// Store the incremented VAList to the legalized pointer
|
|
|
|
Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0);
|
|
|
|
// Load the actual argument out of the pointer VAList
|
|
|
|
Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0));
|
|
|
|
Results.push_back(Results[0].getValue(1));
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::VACOPY: {
|
|
|
|
// This defaults to loading a pointer from the input and storing it to the
|
|
|
|
// output, returning the chain.
|
|
|
|
const Value *VD = cast<SrcValueSDNode>(Node->getOperand(3))->getValue();
|
|
|
|
const Value *VS = cast<SrcValueSDNode>(Node->getOperand(4))->getValue();
|
|
|
|
Tmp1 = DAG.getLoad(TLI.getPointerTy(), dl, Node->getOperand(0),
|
|
|
|
Node->getOperand(2), VS, 0);
|
|
|
|
Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::EXTRACT_VECTOR_ELT:
|
|
|
|
if (Node->getOperand(0).getValueType().getVectorNumElements() == 1)
|
|
|
|
// This must be an access of the only element. Return it.
|
|
|
|
Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, Node->getValueType(0),
|
|
|
|
Node->getOperand(0));
|
|
|
|
else
|
|
|
|
Tmp1 = ExpandExtractFromVectorThroughStack(SDValue(Node, 0));
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::EXTRACT_SUBVECTOR:
|
|
|
|
Results.push_back(ExpandExtractFromVectorThroughStack(SDValue(Node, 0)));
|
|
|
|
break;
|
2009-05-27 15:58:35 +08:00
|
|
|
case ISD::CONCAT_VECTORS: {
|
|
|
|
// Use extract/insert/build vector for now. We might try to be
|
|
|
|
// more clever later.
|
|
|
|
SmallVector<SDValue, 8> Ops;
|
|
|
|
unsigned NumOperands = Node->getNumOperands();
|
|
|
|
for (unsigned i=0; i < NumOperands; ++i) {
|
|
|
|
SDValue SubOp = Node->getOperand(i);
|
|
|
|
MVT VVT = SubOp.getNode()->getValueType(0);
|
|
|
|
MVT EltVT = VVT.getVectorElementType();
|
|
|
|
unsigned NumSubElem = VVT.getVectorNumElements();
|
|
|
|
for (unsigned j=0; j < NumSubElem; ++j) {
|
|
|
|
Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, SubOp,
|
|
|
|
DAG.getIntPtrConstant(j)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Tmp1 = DAG.getNode(ISD::BUILD_VECTOR, dl, Node->getValueType(0),
|
|
|
|
&Ops[0], Ops.size());
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::SCALAR_TO_VECTOR:
|
|
|
|
Results.push_back(ExpandSCALAR_TO_VECTOR(Node));
|
|
|
|
break;
|
2009-05-27 10:16:40 +08:00
|
|
|
case ISD::INSERT_VECTOR_ELT:
|
|
|
|
Results.push_back(ExpandINSERT_VECTOR_ELT(Node->getOperand(0),
|
|
|
|
Node->getOperand(1),
|
|
|
|
Node->getOperand(2), dl));
|
|
|
|
break;
|
2009-05-27 15:58:35 +08:00
|
|
|
case ISD::VECTOR_SHUFFLE: {
|
|
|
|
SmallVector<int, 8> Mask;
|
|
|
|
cast<ShuffleVectorSDNode>(Node)->getMask(Mask);
|
|
|
|
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
MVT EltVT = VT.getVectorElementType();
|
|
|
|
unsigned NumElems = VT.getVectorNumElements();
|
|
|
|
SmallVector<SDValue, 8> Ops;
|
|
|
|
for (unsigned i = 0; i != NumElems; ++i) {
|
|
|
|
if (Mask[i] < 0) {
|
|
|
|
Ops.push_back(DAG.getUNDEF(EltVT));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
unsigned Idx = Mask[i];
|
|
|
|
if (Idx < NumElems)
|
|
|
|
Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT,
|
|
|
|
Node->getOperand(0),
|
|
|
|
DAG.getIntPtrConstant(Idx)));
|
|
|
|
else
|
|
|
|
Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT,
|
|
|
|
Node->getOperand(1),
|
|
|
|
DAG.getIntPtrConstant(Idx - NumElems)));
|
|
|
|
}
|
|
|
|
Tmp1 = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size());
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
case ISD::EXTRACT_ELEMENT: {
|
|
|
|
MVT OpTy = Node->getOperand(0).getValueType();
|
|
|
|
if (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue()) {
|
|
|
|
// 1 -> Hi
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0),
|
|
|
|
DAG.getConstant(OpTy.getSizeInBits()/2,
|
|
|
|
TLI.getShiftAmountTy()));
|
|
|
|
Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1);
|
|
|
|
} else {
|
|
|
|
// 0 -> Lo
|
|
|
|
Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0),
|
|
|
|
Node->getOperand(0));
|
|
|
|
}
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 10:16:40 +08:00
|
|
|
case ISD::STACKSAVE:
|
|
|
|
// Expand to CopyFromReg if the target set
|
|
|
|
// StackPointerRegisterToSaveRestore.
|
|
|
|
if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) {
|
|
|
|
Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, SP,
|
|
|
|
Node->getValueType(0)));
|
|
|
|
Results.push_back(Results[0].getValue(1));
|
|
|
|
} else {
|
|
|
|
Results.push_back(DAG.getUNDEF(Node->getValueType(0)));
|
|
|
|
Results.push_back(Node->getOperand(0));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::STACKRESTORE:
|
|
|
|
// Expand to CopyToReg if the target set
|
|
|
|
// StackPointerRegisterToSaveRestore.
|
|
|
|
if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) {
|
|
|
|
Results.push_back(DAG.getCopyToReg(Node->getOperand(0), dl, SP,
|
|
|
|
Node->getOperand(1)));
|
|
|
|
} else {
|
|
|
|
Results.push_back(Node->getOperand(0));
|
|
|
|
}
|
|
|
|
break;
|
2009-05-27 20:20:41 +08:00
|
|
|
case ISD::FCOPYSIGN:
|
|
|
|
Results.push_back(ExpandFCOPYSIGN(Node));
|
|
|
|
break;
|
2009-05-27 11:33:44 +08:00
|
|
|
case ISD::FNEG:
|
|
|
|
// Expand Y = FNEG(X) -> Y = SUB -0.0, X
|
|
|
|
Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0));
|
|
|
|
Tmp1 = DAG.getNode(ISD::FSUB, dl, Node->getValueType(0), Tmp1,
|
|
|
|
Node->getOperand(0));
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::FABS: {
|
|
|
|
// Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X).
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
Tmp2 = DAG.getConstantFP(0.0, VT);
|
|
|
|
Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(Tmp1.getValueType()),
|
|
|
|
Tmp1, Tmp2, ISD::SETUGT);
|
|
|
|
Tmp3 = DAG.getNode(ISD::FNEG, dl, VT, Tmp1);
|
|
|
|
Tmp1 = DAG.getNode(ISD::SELECT, dl, VT, Tmp2, Tmp1, Tmp3);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::FSQRT:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
|
|
|
|
RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FSIN:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::SIN_F32, RTLIB::SIN_F64,
|
|
|
|
RTLIB::SIN_F80, RTLIB::SIN_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FCOS:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::COS_F32, RTLIB::COS_F64,
|
|
|
|
RTLIB::COS_F80, RTLIB::COS_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FLOG:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
|
|
|
|
RTLIB::LOG_F80, RTLIB::LOG_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FLOG2:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
|
|
|
|
RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FLOG10:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
|
|
|
|
RTLIB::LOG10_F80, RTLIB::LOG10_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FEXP:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
|
|
|
|
RTLIB::EXP_F80, RTLIB::EXP_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FEXP2:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
|
|
|
|
RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FTRUNC:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
|
|
|
|
RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FFLOOR:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64,
|
|
|
|
RTLIB::FLOOR_F80, RTLIB::FLOOR_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FCEIL:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::CEIL_F32, RTLIB::CEIL_F64,
|
|
|
|
RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FRINT:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::RINT_F32, RTLIB::RINT_F64,
|
|
|
|
RTLIB::RINT_F80, RTLIB::RINT_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FNEARBYINT:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::NEARBYINT_F32,
|
|
|
|
RTLIB::NEARBYINT_F64,
|
|
|
|
RTLIB::NEARBYINT_F80,
|
|
|
|
RTLIB::NEARBYINT_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FPOWI:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::POWI_F32, RTLIB::POWI_F64,
|
|
|
|
RTLIB::POWI_F80, RTLIB::POWI_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FPOW:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
|
|
|
|
RTLIB::POW_F80, RTLIB::POW_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FDIV:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
|
|
|
|
RTLIB::DIV_F80, RTLIB::DIV_PPCF128));
|
|
|
|
break;
|
|
|
|
case ISD::FREM:
|
|
|
|
Results.push_back(ExpandFPLibCall(Node, RTLIB::REM_F32, RTLIB::REM_F64,
|
|
|
|
RTLIB::REM_F80, RTLIB::REM_PPCF128));
|
|
|
|
break;
|
2009-05-27 15:32:27 +08:00
|
|
|
case ISD::ConstantFP: {
|
|
|
|
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
|
|
|
|
// Check to see if this FP immediate is already legal.
|
|
|
|
bool isLegal = false;
|
|
|
|
for (TargetLowering::legal_fpimm_iterator I = TLI.legal_fpimm_begin(),
|
|
|
|
E = TLI.legal_fpimm_end(); I != E; ++I) {
|
|
|
|
if (CFP->isExactlyValue(*I)) {
|
|
|
|
isLegal = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If this is a legal constant, turn it into a TargetConstantFP node.
|
|
|
|
if (isLegal)
|
|
|
|
Results.push_back(SDValue(Node, 0));
|
|
|
|
else
|
|
|
|
Results.push_back(ExpandConstantFP(CFP, true, DAG, TLI));
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:05:37 +08:00
|
|
|
case ISD::EHSELECTION: {
|
|
|
|
unsigned Reg = TLI.getExceptionSelectorRegister();
|
|
|
|
assert(Reg && "Can't expand to unknown register!");
|
|
|
|
Results.push_back(DAG.getCopyFromReg(Node->getOperand(1), dl, Reg,
|
|
|
|
Node->getValueType(0)));
|
|
|
|
Results.push_back(Results[0].getValue(1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::EXCEPTIONADDR: {
|
|
|
|
unsigned Reg = TLI.getExceptionAddressRegister();
|
|
|
|
assert(Reg && "Can't expand to unknown register!");
|
|
|
|
Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, Reg,
|
|
|
|
Node->getValueType(0)));
|
|
|
|
Results.push_back(Results[0].getValue(1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::SUB: {
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
assert(TLI.isOperationLegalOrCustom(ISD::ADD, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::XOR, VT) &&
|
|
|
|
"Don't know how to expand this subtraction!");
|
|
|
|
Tmp1 = DAG.getNode(ISD::XOR, dl, VT, Node->getOperand(1),
|
|
|
|
DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT));
|
|
|
|
Tmp1 = DAG.getNode(ISD::ADD, dl, VT, Tmp2, DAG.getConstant(1, VT));
|
|
|
|
Results.push_back(DAG.getNode(ISD::ADD, dl, VT, Node->getOperand(0), Tmp1));
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:32:27 +08:00
|
|
|
case ISD::UREM:
|
|
|
|
case ISD::SREM: {
|
2009-05-27 15:05:37 +08:00
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
SDVTList VTs = DAG.getVTList(VT, VT);
|
2009-05-27 15:32:27 +08:00
|
|
|
bool isSigned = Node->getOpcode() == ISD::SREM;
|
|
|
|
unsigned DivOpc = isSigned ? ISD::SDIV : ISD::UDIV;
|
|
|
|
unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
|
|
|
|
Tmp2 = Node->getOperand(0);
|
|
|
|
Tmp3 = Node->getOperand(1);
|
2009-05-28 11:06:16 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) {
|
|
|
|
Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue(1);
|
|
|
|
} else if (TLI.isOperationLegalOrCustom(DivOpc, VT)) {
|
2009-05-27 15:32:27 +08:00
|
|
|
// X % Y -> X-X/Y*Y
|
|
|
|
Tmp1 = DAG.getNode(DivOpc, dl, VT, Tmp2, Tmp3);
|
|
|
|
Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Tmp3);
|
|
|
|
Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Tmp2, Tmp1);
|
|
|
|
} else if (isSigned) {
|
|
|
|
Tmp1 = ExpandIntLibCall(Node, true, RTLIB::SREM_I16, RTLIB::SREM_I32,
|
|
|
|
RTLIB::SREM_I64, RTLIB::SREM_I128);
|
|
|
|
} else {
|
2009-05-27 15:05:37 +08:00
|
|
|
Tmp1 = ExpandIntLibCall(Node, false, RTLIB::UREM_I16, RTLIB::UREM_I32,
|
|
|
|
RTLIB::UREM_I64, RTLIB::UREM_I128);
|
2009-05-27 15:32:27 +08:00
|
|
|
}
|
2009-05-27 15:05:37 +08:00
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:32:27 +08:00
|
|
|
case ISD::UDIV:
|
|
|
|
case ISD::SDIV: {
|
|
|
|
bool isSigned = Node->getOpcode() == ISD::SDIV;
|
|
|
|
unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
|
2009-05-27 15:05:37 +08:00
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
SDVTList VTs = DAG.getVTList(VT, VT);
|
2009-05-27 15:32:27 +08:00
|
|
|
if (TLI.isOperationLegalOrCustom(DivRemOpc, VT))
|
|
|
|
Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Node->getOperand(0),
|
|
|
|
Node->getOperand(1));
|
|
|
|
else if (isSigned)
|
2009-05-27 15:05:37 +08:00
|
|
|
Tmp1 = ExpandIntLibCall(Node, true, RTLIB::SDIV_I16, RTLIB::SDIV_I32,
|
|
|
|
RTLIB::SDIV_I64, RTLIB::SDIV_I128);
|
2009-05-27 15:32:27 +08:00
|
|
|
else
|
|
|
|
Tmp1 = ExpandIntLibCall(Node, false, RTLIB::UDIV_I16, RTLIB::UDIV_I32,
|
|
|
|
RTLIB::UDIV_I64, RTLIB::UDIV_I128);
|
2009-05-27 15:05:37 +08:00
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::MULHU:
|
|
|
|
case ISD::MULHS: {
|
|
|
|
unsigned ExpandOpcode = Node->getOpcode() == ISD::MULHU ? ISD::UMUL_LOHI :
|
|
|
|
ISD::SMUL_LOHI;
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
SDVTList VTs = DAG.getVTList(VT, VT);
|
|
|
|
assert(TLI.isOperationLegalOrCustom(ExpandOpcode, VT) &&
|
|
|
|
"If this wasn't legal, it shouldn't have been created!");
|
|
|
|
Tmp1 = DAG.getNode(ExpandOpcode, dl, VTs, Node->getOperand(0),
|
|
|
|
Node->getOperand(1));
|
|
|
|
Results.push_back(Tmp1.getValue(1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::MUL: {
|
|
|
|
MVT VT = Node->getValueType(0);
|
|
|
|
SDVTList VTs = DAG.getVTList(VT, VT);
|
|
|
|
// See if multiply or divide can be lowered using two-result operations.
|
|
|
|
// We just need the low half of the multiply; try both the signed
|
|
|
|
// and unsigned forms. If the target supports both SMUL_LOHI and
|
|
|
|
// UMUL_LOHI, form a preference by checking which forms of plain
|
|
|
|
// MULH it supports.
|
|
|
|
bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, VT);
|
|
|
|
bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, VT);
|
|
|
|
bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, VT);
|
|
|
|
bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, VT);
|
|
|
|
unsigned OpToUse = 0;
|
|
|
|
if (HasSMUL_LOHI && !HasMULHS) {
|
|
|
|
OpToUse = ISD::SMUL_LOHI;
|
|
|
|
} else if (HasUMUL_LOHI && !HasMULHU) {
|
|
|
|
OpToUse = ISD::UMUL_LOHI;
|
|
|
|
} else if (HasSMUL_LOHI) {
|
|
|
|
OpToUse = ISD::SMUL_LOHI;
|
|
|
|
} else if (HasUMUL_LOHI) {
|
|
|
|
OpToUse = ISD::UMUL_LOHI;
|
|
|
|
}
|
|
|
|
if (OpToUse) {
|
2009-05-27 15:32:27 +08:00
|
|
|
Results.push_back(DAG.getNode(OpToUse, dl, VTs, Node->getOperand(0),
|
|
|
|
Node->getOperand(1)));
|
2009-05-27 15:05:37 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
Tmp1 = ExpandIntLibCall(Node, false, RTLIB::MUL_I16, RTLIB::MUL_I32,
|
|
|
|
RTLIB::MUL_I64, RTLIB::MUL_I128);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 20:20:41 +08:00
|
|
|
case ISD::SADDO:
|
|
|
|
case ISD::SSUBO: {
|
|
|
|
SDValue LHS = Node->getOperand(0);
|
|
|
|
SDValue RHS = Node->getOperand(1);
|
|
|
|
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ?
|
|
|
|
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
|
|
|
|
LHS, RHS);
|
|
|
|
Results.push_back(Sum);
|
|
|
|
MVT OType = Node->getValueType(1);
|
|
|
|
|
|
|
|
SDValue Zero = DAG.getConstant(0, LHS.getValueType());
|
|
|
|
|
|
|
|
// LHSSign -> LHS >= 0
|
|
|
|
// RHSSign -> RHS >= 0
|
|
|
|
// SumSign -> Sum >= 0
|
|
|
|
//
|
|
|
|
// Add:
|
|
|
|
// Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign)
|
|
|
|
// Sub:
|
|
|
|
// Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign)
|
|
|
|
//
|
|
|
|
SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE);
|
|
|
|
SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE);
|
|
|
|
SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign,
|
|
|
|
Node->getOpcode() == ISD::SADDO ?
|
|
|
|
ISD::SETEQ : ISD::SETNE);
|
|
|
|
|
|
|
|
SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE);
|
|
|
|
SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE);
|
|
|
|
|
|
|
|
SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE);
|
|
|
|
Results.push_back(Cmp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::UADDO:
|
|
|
|
case ISD::USUBO: {
|
|
|
|
SDValue LHS = Node->getOperand(0);
|
|
|
|
SDValue RHS = Node->getOperand(1);
|
|
|
|
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::UADDO ?
|
|
|
|
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
|
|
|
|
LHS, RHS);
|
|
|
|
Results.push_back(Sum);
|
|
|
|
Results.push_back(DAG.getSetCC(dl, Node->getValueType(1), Sum, LHS,
|
|
|
|
Node->getOpcode () == ISD::UADDO ?
|
|
|
|
ISD::SETULT : ISD::SETUGT));
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:32:27 +08:00
|
|
|
case ISD::BUILD_PAIR: {
|
|
|
|
MVT PairTy = Node->getValueType(0);
|
|
|
|
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0));
|
|
|
|
Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1));
|
|
|
|
Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2,
|
|
|
|
DAG.getConstant(PairTy.getSizeInBits()/2,
|
|
|
|
TLI.getShiftAmountTy()));
|
|
|
|
Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2));
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:58:35 +08:00
|
|
|
case ISD::SELECT:
|
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
Tmp2 = Node->getOperand(1);
|
|
|
|
Tmp3 = Node->getOperand(2);
|
|
|
|
if (Tmp1.getOpcode() == ISD::SETCC) {
|
|
|
|
Tmp1 = DAG.getSelectCC(dl, Tmp1.getOperand(0), Tmp1.getOperand(1),
|
|
|
|
Tmp2, Tmp3,
|
|
|
|
cast<CondCodeSDNode>(Tmp1.getOperand(2))->get());
|
|
|
|
} else {
|
|
|
|
Tmp1 = DAG.getSelectCC(dl, Tmp1,
|
|
|
|
DAG.getConstant(0, Tmp1.getValueType()),
|
|
|
|
Tmp2, Tmp3, ISD::SETNE);
|
|
|
|
}
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
2009-05-27 20:20:41 +08:00
|
|
|
case ISD::BR_JT: {
|
|
|
|
SDValue Chain = Node->getOperand(0);
|
|
|
|
SDValue Table = Node->getOperand(1);
|
|
|
|
SDValue Index = Node->getOperand(2);
|
|
|
|
|
|
|
|
MVT PTy = TLI.getPointerTy();
|
|
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
|
|
unsigned EntrySize = MF.getJumpTableInfo()->getEntrySize();
|
|
|
|
Index= DAG.getNode(ISD::MUL, dl, PTy,
|
|
|
|
Index, DAG.getConstant(EntrySize, PTy));
|
|
|
|
SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
|
|
|
|
|
|
|
|
MVT MemVT = MVT::getIntegerVT(EntrySize * 8);
|
|
|
|
SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr,
|
|
|
|
PseudoSourceValue::getJumpTable(), 0, MemVT);
|
|
|
|
Addr = LD;
|
|
|
|
if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
|
|
|
|
// For PIC, the sequence is:
|
|
|
|
// BRIND(load(Jumptable + index) + RelocBase)
|
|
|
|
// RelocBase can be JumpTable, GOT or some sort of global base.
|
|
|
|
Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr,
|
|
|
|
TLI.getPICJumpTableRelocBase(Table, DAG));
|
|
|
|
}
|
|
|
|
Tmp1 = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 15:32:27 +08:00
|
|
|
case ISD::BRCOND:
|
|
|
|
// Expand brcond's setcc into its constituent parts and create a BR_CC
|
|
|
|
// Node.
|
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
Tmp2 = Node->getOperand(1);
|
|
|
|
if (Tmp2.getOpcode() == ISD::SETCC) {
|
|
|
|
Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other,
|
|
|
|
Tmp1, Tmp2.getOperand(2),
|
|
|
|
Tmp2.getOperand(0), Tmp2.getOperand(1),
|
|
|
|
Node->getOperand(2));
|
|
|
|
} else {
|
|
|
|
Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other, Tmp1,
|
|
|
|
DAG.getCondCode(ISD::SETNE), Tmp2,
|
|
|
|
DAG.getConstant(0, Tmp2.getValueType()),
|
|
|
|
Node->getOperand(2));
|
|
|
|
}
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
2009-05-27 10:16:40 +08:00
|
|
|
case ISD::GLOBAL_OFFSET_TABLE:
|
|
|
|
case ISD::GlobalAddress:
|
|
|
|
case ISD::GlobalTLSAddress:
|
|
|
|
case ISD::ExternalSymbol:
|
|
|
|
case ISD::ConstantPool:
|
|
|
|
case ISD::JumpTable:
|
|
|
|
case ISD::INTRINSIC_W_CHAIN:
|
|
|
|
case ISD::INTRINSIC_WO_CHAIN:
|
|
|
|
case ISD::INTRINSIC_VOID:
|
|
|
|
// FIXME: Custom lowering for these operations shouldn't return null!
|
|
|
|
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
|
|
|
|
Results.push_back(SDValue(Node, i));
|
|
|
|
break;
|
2009-05-27 09:25:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void SelectionDAGLegalize::PromoteNode(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
|
|
|
MVT OVT = Node->getValueType(0);
|
|
|
|
if (Node->getOpcode() == ISD::UINT_TO_FP ||
|
|
|
|
Node->getOpcode() == ISD::SINT_TO_FP) {
|
|
|
|
OVT = Node->getOperand(0).getValueType();
|
|
|
|
}
|
|
|
|
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT);
|
|
|
|
DebugLoc dl = Node->getDebugLoc();
|
2009-05-27 15:58:35 +08:00
|
|
|
SDValue Tmp1, Tmp2, Tmp3;
|
2009-05-27 09:25:56 +08:00
|
|
|
switch (Node->getOpcode()) {
|
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTPOP:
|
|
|
|
// Zero extend the argument.
|
|
|
|
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0));
|
|
|
|
// Perform the larger operation.
|
|
|
|
Tmp1 = DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Tmp1);
|
|
|
|
if (Node->getOpcode() == ISD::CTTZ) {
|
|
|
|
//if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT)
|
|
|
|
Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(Tmp1.getValueType()),
|
|
|
|
Tmp1, DAG.getConstant(NVT.getSizeInBits(), NVT),
|
|
|
|
ISD::SETEQ);
|
|
|
|
Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2,
|
|
|
|
DAG.getConstant(OVT.getSizeInBits(), NVT), Tmp1);
|
|
|
|
} else if (Node->getOpcode() == ISD::CTLZ) {
|
|
|
|
// Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
|
|
|
|
Tmp1 = DAG.getNode(ISD::SUB, dl, NVT, Tmp1,
|
|
|
|
DAG.getConstant(NVT.getSizeInBits() -
|
|
|
|
OVT.getSizeInBits(), NVT));
|
|
|
|
}
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::BSWAP: {
|
|
|
|
unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits();
|
|
|
|
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Tmp1);
|
|
|
|
Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1);
|
|
|
|
Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1,
|
|
|
|
DAG.getConstant(DiffBits, TLI.getShiftAmountTy()));
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ISD::FP_TO_UINT:
|
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
Tmp1 = PromoteLegalFP_TO_INT(Node->getOperand(0), Node->getValueType(0),
|
|
|
|
Node->getOpcode() == ISD::FP_TO_SINT, dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::UINT_TO_FP:
|
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
Tmp1 = PromoteLegalINT_TO_FP(Node->getOperand(0), Node->getValueType(0),
|
|
|
|
Node->getOpcode() == ISD::SINT_TO_FP, dl);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
2009-05-27 11:33:44 +08:00
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR:
|
|
|
|
assert(OVT.isVector() && "Don't know how to promote scalar logic ops");
|
|
|
|
// Bit convert each of the values to the new type.
|
|
|
|
Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(0));
|
|
|
|
Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(1));
|
|
|
|
Tmp1 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1, Tmp2);
|
|
|
|
// Bit convert the result back the original type.
|
|
|
|
Results.push_back(DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Tmp1));
|
|
|
|
break;
|
2009-05-27 15:58:35 +08:00
|
|
|
case ISD::SELECT:
|
|
|
|
unsigned ExtOp, TruncOp;
|
2009-05-27 20:20:41 +08:00
|
|
|
if (Node->getValueType(0).isVector()) {
|
2009-05-27 15:58:35 +08:00
|
|
|
ExtOp = ISD::BIT_CONVERT;
|
|
|
|
TruncOp = ISD::BIT_CONVERT;
|
2009-05-27 20:20:41 +08:00
|
|
|
} else if (Node->getValueType(0).isInteger()) {
|
2009-05-27 15:58:35 +08:00
|
|
|
ExtOp = ISD::ANY_EXTEND;
|
|
|
|
TruncOp = ISD::TRUNCATE;
|
|
|
|
} else {
|
|
|
|
ExtOp = ISD::FP_EXTEND;
|
|
|
|
TruncOp = ISD::FP_ROUND;
|
|
|
|
}
|
|
|
|
Tmp1 = Node->getOperand(0);
|
|
|
|
// Promote each of the values to the new type.
|
|
|
|
Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1));
|
|
|
|
Tmp3 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(2));
|
|
|
|
// Perform the larger operation, then round down.
|
|
|
|
Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp1, Tmp2, Tmp3);
|
|
|
|
if (TruncOp != ISD::FP_ROUND)
|
|
|
|
Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1);
|
|
|
|
else
|
|
|
|
Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1,
|
|
|
|
DAG.getIntPtrConstant(0));
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
case ISD::VECTOR_SHUFFLE: {
|
|
|
|
SmallVector<int, 8> Mask;
|
|
|
|
cast<ShuffleVectorSDNode>(Node)->getMask(Mask);
|
|
|
|
|
|
|
|
// Cast the two input vectors.
|
|
|
|
Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(0));
|
|
|
|
Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Node->getOperand(1));
|
|
|
|
|
|
|
|
// Convert the shuffle mask to the right # elements.
|
|
|
|
Tmp1 = ShuffleWithNarrowerEltType(NVT, OVT, dl, Tmp1, Tmp2, Mask);
|
|
|
|
Tmp1 = DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Tmp1);
|
|
|
|
Results.push_back(Tmp1);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-27 09:25:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-07 15:47:09 +08:00
|
|
|
// SelectionDAG::Legalize - This is the entry point for the file.
|
|
|
|
//
|
2009-04-30 07:29:43 +08:00
|
|
|
void SelectionDAG::Legalize(bool TypesNeedLegalizing,
|
|
|
|
CodeGenOpt::Level OptLevel) {
|
2005-01-07 15:47:09 +08:00
|
|
|
/// run - This is the main entry point to this class.
|
|
|
|
///
|
2009-05-24 10:46:31 +08:00
|
|
|
SelectionDAGLegalize(*this, OptLevel).LegalizeDAG();
|
2005-01-07 15:47:09 +08:00
|
|
|
}
|
|
|
|
|