mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-04 02:24:29 +00:00
Move the rest of the PPCTargetLowering::LowerOperation cases out into
separate functions, for simplicity and code clarity. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27693 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -258,6 +258,10 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Node matching predicates, for use by the tblgen matching code.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// isFloatingPointZero - Return true if this is 0.0 or -0.0.
|
/// isFloatingPointZero - Return true if this is 0.0 or -0.0.
|
||||||
static bool isFloatingPointZero(SDOperand Op) {
|
static bool isFloatingPointZero(SDOperand Op) {
|
||||||
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op))
|
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op))
|
||||||
@ -544,6 +548,388 @@ SDOperand PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) {
|
|||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// LowerOperation implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
|
||||||
|
Constant *C = CP->get();
|
||||||
|
SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i32, CP->getAlignment());
|
||||||
|
SDOperand Zero = DAG.getConstant(0, MVT::i32);
|
||||||
|
|
||||||
|
const TargetMachine &TM = DAG.getTarget();
|
||||||
|
|
||||||
|
// If this is a non-darwin platform, we don't support non-static relo models
|
||||||
|
// yet.
|
||||||
|
if (TM.getRelocationModel() == Reloc::Static ||
|
||||||
|
!TM.getSubtarget<PPCSubtarget>().isDarwin()) {
|
||||||
|
// Generate non-pic code that has direct accesses to the constant pool.
|
||||||
|
// The address of the global is just (hi(&g)+lo(&g)).
|
||||||
|
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero);
|
||||||
|
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero);
|
||||||
|
return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero);
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC) {
|
||||||
|
// With PIC, the first instruction is actually "GR+hi(&G)".
|
||||||
|
Hi = DAG.getNode(ISD::ADD, MVT::i32,
|
||||||
|
DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero);
|
||||||
|
Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
||||||
|
return Lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
|
||||||
|
GlobalValue *GV = GSDN->getGlobal();
|
||||||
|
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32, GSDN->getOffset());
|
||||||
|
SDOperand Zero = DAG.getConstant(0, MVT::i32);
|
||||||
|
|
||||||
|
const TargetMachine &TM = DAG.getTarget();
|
||||||
|
|
||||||
|
// If this is a non-darwin platform, we don't support non-static relo models
|
||||||
|
// yet.
|
||||||
|
if (TM.getRelocationModel() == Reloc::Static ||
|
||||||
|
!TM.getSubtarget<PPCSubtarget>().isDarwin()) {
|
||||||
|
// Generate non-pic code that has direct accesses to globals.
|
||||||
|
// The address of the global is just (hi(&g)+lo(&g)).
|
||||||
|
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero);
|
||||||
|
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero);
|
||||||
|
return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero);
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC) {
|
||||||
|
// With PIC, the first instruction is actually "GR+hi(&G)".
|
||||||
|
Hi = DAG.getNode(ISD::ADD, MVT::i32,
|
||||||
|
DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero);
|
||||||
|
Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
||||||
|
|
||||||
|
if (!GV->hasWeakLinkage() && !GV->hasLinkOnceLinkage() &&
|
||||||
|
(!GV->isExternal() || GV->hasNotBeenReadFromBytecode()))
|
||||||
|
return Lo;
|
||||||
|
|
||||||
|
// If the global is weak or external, we have to go through the lazy
|
||||||
|
// resolution stub.
|
||||||
|
return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Lo, DAG.getSrcValue(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
||||||
|
|
||||||
|
// If we're comparing for equality to zero, expose the fact that this is
|
||||||
|
// implented as a ctlz/srl pair on ppc, so that the dag combiner can
|
||||||
|
// fold the new nodes.
|
||||||
|
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
||||||
|
if (C->isNullValue() && CC == ISD::SETEQ) {
|
||||||
|
MVT::ValueType VT = Op.getOperand(0).getValueType();
|
||||||
|
SDOperand Zext = Op.getOperand(0);
|
||||||
|
if (VT < MVT::i32) {
|
||||||
|
VT = MVT::i32;
|
||||||
|
Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0));
|
||||||
|
}
|
||||||
|
unsigned Log2b = Log2_32(MVT::getSizeInBits(VT));
|
||||||
|
SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext);
|
||||||
|
SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz,
|
||||||
|
DAG.getConstant(Log2b, MVT::i32));
|
||||||
|
return DAG.getNode(ISD::TRUNCATE, MVT::i32, Scc);
|
||||||
|
}
|
||||||
|
// Leave comparisons against 0 and -1 alone for now, since they're usually
|
||||||
|
// optimized. FIXME: revisit this when we can custom lower all setcc
|
||||||
|
// optimizations.
|
||||||
|
if (C->isAllOnesValue() || C->isNullValue())
|
||||||
|
return SDOperand();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have an integer seteq/setne, turn it into a compare against zero
|
||||||
|
// by subtracting the rhs from the lhs, which is faster than setting a
|
||||||
|
// condition register, reading it back out, and masking the correct bit.
|
||||||
|
MVT::ValueType LHSVT = Op.getOperand(0).getValueType();
|
||||||
|
if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
|
||||||
|
MVT::ValueType VT = Op.getValueType();
|
||||||
|
SDOperand Sub = DAG.getNode(ISD::SUB, LHSVT, Op.getOperand(0),
|
||||||
|
Op.getOperand(1));
|
||||||
|
return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC);
|
||||||
|
}
|
||||||
|
return SDOperand();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
|
||||||
|
unsigned VarArgsFrameIndex) {
|
||||||
|
// vastart just stores the address of the VarArgsFrameIndex slot into the
|
||||||
|
// memory location argument.
|
||||||
|
SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
|
||||||
|
return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR,
|
||||||
|
Op.getOperand(1), Op.getOperand(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
SDOperand Copy;
|
||||||
|
switch(Op.getNumOperands()) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Do not know how to return this many arguments!");
|
||||||
|
abort();
|
||||||
|
case 1:
|
||||||
|
return SDOperand(); // ret void is legal
|
||||||
|
case 2: {
|
||||||
|
MVT::ValueType ArgVT = Op.getOperand(1).getValueType();
|
||||||
|
unsigned ArgReg;
|
||||||
|
if (MVT::isVector(ArgVT))
|
||||||
|
ArgReg = PPC::V2;
|
||||||
|
else if (MVT::isInteger(ArgVT))
|
||||||
|
ArgReg = PPC::R3;
|
||||||
|
else {
|
||||||
|
assert(MVT::isFloatingPoint(ArgVT));
|
||||||
|
ArgReg = PPC::F1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1),
|
||||||
|
SDOperand());
|
||||||
|
|
||||||
|
// If we haven't noted the R3/F1 are live out, do so now.
|
||||||
|
if (DAG.getMachineFunction().liveout_empty())
|
||||||
|
DAG.getMachineFunction().addLiveOut(ArgReg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
Copy = DAG.getCopyToReg(Op.getOperand(0), PPC::R3, Op.getOperand(2),
|
||||||
|
SDOperand());
|
||||||
|
Copy = DAG.getCopyToReg(Copy, PPC::R4, Op.getOperand(1),Copy.getValue(1));
|
||||||
|
// If we haven't noted the R3+R4 are live out, do so now.
|
||||||
|
if (DAG.getMachineFunction().liveout_empty()) {
|
||||||
|
DAG.getMachineFunction().addLiveOut(PPC::R3);
|
||||||
|
DAG.getMachineFunction().addLiveOut(PPC::R4);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when
|
||||||
|
/// possible.
|
||||||
|
static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
// Not FP? Not a fsel.
|
||||||
|
if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) ||
|
||||||
|
!MVT::isFloatingPoint(Op.getOperand(2).getValueType()))
|
||||||
|
return SDOperand();
|
||||||
|
|
||||||
|
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
|
||||||
|
|
||||||
|
// Cannot handle SETEQ/SETNE.
|
||||||
|
if (CC == ISD::SETEQ || CC == ISD::SETNE) return SDOperand();
|
||||||
|
|
||||||
|
MVT::ValueType ResVT = Op.getValueType();
|
||||||
|
MVT::ValueType CmpVT = Op.getOperand(0).getValueType();
|
||||||
|
SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);
|
||||||
|
SDOperand TV = Op.getOperand(2), FV = Op.getOperand(3);
|
||||||
|
|
||||||
|
// If the RHS of the comparison is a 0.0, we don't need to do the
|
||||||
|
// subtraction at all.
|
||||||
|
if (isFloatingPointZero(RHS))
|
||||||
|
switch (CC) {
|
||||||
|
default: break; // SETUO etc aren't handled by fsel.
|
||||||
|
case ISD::SETULT:
|
||||||
|
case ISD::SETLT:
|
||||||
|
std::swap(TV, FV); // fsel is natively setge, swap operands for setlt
|
||||||
|
case ISD::SETUGE:
|
||||||
|
case ISD::SETGE:
|
||||||
|
if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT, LHS, TV, FV);
|
||||||
|
case ISD::SETUGT:
|
||||||
|
case ISD::SETGT:
|
||||||
|
std::swap(TV, FV); // fsel is natively setge, swap operands for setlt
|
||||||
|
case ISD::SETULE:
|
||||||
|
case ISD::SETLE:
|
||||||
|
if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT,
|
||||||
|
DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand Cmp;
|
||||||
|
switch (CC) {
|
||||||
|
default: break; // SETUO etc aren't handled by fsel.
|
||||||
|
case ISD::SETULT:
|
||||||
|
case ISD::SETLT:
|
||||||
|
Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
|
||||||
|
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
|
||||||
|
case ISD::SETUGE:
|
||||||
|
case ISD::SETGE:
|
||||||
|
Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
|
||||||
|
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
|
||||||
|
case ISD::SETUGT:
|
||||||
|
case ISD::SETGT:
|
||||||
|
Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
|
||||||
|
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
|
||||||
|
case ISD::SETULE:
|
||||||
|
case ISD::SETLE:
|
||||||
|
Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
|
||||||
|
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
||||||
|
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
||||||
|
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
|
||||||
|
}
|
||||||
|
return SDOperand();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
|
||||||
|
SDOperand Src = Op.getOperand(0);
|
||||||
|
if (Src.getValueType() == MVT::f32)
|
||||||
|
Src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Src);
|
||||||
|
|
||||||
|
SDOperand Tmp;
|
||||||
|
switch (Op.getValueType()) {
|
||||||
|
default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!");
|
||||||
|
case MVT::i32:
|
||||||
|
Tmp = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Src);
|
||||||
|
break;
|
||||||
|
case MVT::i64:
|
||||||
|
Tmp = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Src);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the FP value to an int value through memory.
|
||||||
|
SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Tmp);
|
||||||
|
if (Op.getValueType() == MVT::i32)
|
||||||
|
Bits = DAG.getNode(ISD::TRUNCATE, MVT::i32, Bits);
|
||||||
|
return Bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
if (Op.getOperand(0).getValueType() == MVT::i64) {
|
||||||
|
SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0));
|
||||||
|
SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits);
|
||||||
|
if (Op.getValueType() == MVT::f32)
|
||||||
|
FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
|
||||||
|
return FP;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(Op.getOperand(0).getValueType() == MVT::i32 &&
|
||||||
|
"Unhandled SINT_TO_FP type in custom expander!");
|
||||||
|
// Since we only generate this in 64-bit mode, we can take advantage of
|
||||||
|
// 64-bit registers. In particular, sign extend the input value into the
|
||||||
|
// 64-bit register with extsw, store the WHOLE 64-bit value into the stack
|
||||||
|
// then lfd it and fcfid it.
|
||||||
|
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
||||||
|
int FrameIdx = FrameInfo->CreateStackObject(8, 8);
|
||||||
|
SDOperand FIdx = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
|
||||||
|
SDOperand Ext64 = DAG.getNode(PPCISD::EXTSW_32, MVT::i32,
|
||||||
|
Op.getOperand(0));
|
||||||
|
|
||||||
|
// STD the extended value into the stack slot.
|
||||||
|
SDOperand Store = DAG.getNode(PPCISD::STD_32, MVT::Other,
|
||||||
|
DAG.getEntryNode(), Ext64, FIdx,
|
||||||
|
DAG.getSrcValue(NULL));
|
||||||
|
// Load the value as a double.
|
||||||
|
SDOperand Ld = DAG.getLoad(MVT::f64, Store, FIdx, DAG.getSrcValue(NULL));
|
||||||
|
|
||||||
|
// FCFID it and return it.
|
||||||
|
SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Ld);
|
||||||
|
if (Op.getValueType() == MVT::f32)
|
||||||
|
FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
|
||||||
|
return FP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSHL(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
assert(Op.getValueType() == MVT::i64 &&
|
||||||
|
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
|
||||||
|
// The generic code does a fine job expanding shift by a constant.
|
||||||
|
if (isa<ConstantSDNode>(Op.getOperand(1))) return SDOperand();
|
||||||
|
|
||||||
|
// Otherwise, expand into a bunch of logical ops. Note that these ops
|
||||||
|
// depend on the PPC behavior for oversized shift amounts.
|
||||||
|
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(0, MVT::i32));
|
||||||
|
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(1, MVT::i32));
|
||||||
|
SDOperand Amt = Op.getOperand(1);
|
||||||
|
|
||||||
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
||||||
|
DAG.getConstant(32, MVT::i32), Amt);
|
||||||
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt);
|
||||||
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1);
|
||||||
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
||||||
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
||||||
|
DAG.getConstant(-32U, MVT::i32));
|
||||||
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5);
|
||||||
|
SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
||||||
|
SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSRL(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
assert(Op.getValueType() == MVT::i64 &&
|
||||||
|
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
|
||||||
|
// The generic code does a fine job expanding shift by a constant.
|
||||||
|
if (isa<ConstantSDNode>(Op.getOperand(1))) return SDOperand();
|
||||||
|
|
||||||
|
// Otherwise, expand into a bunch of logical ops. Note that these ops
|
||||||
|
// depend on the PPC behavior for oversized shift amounts.
|
||||||
|
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(0, MVT::i32));
|
||||||
|
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(1, MVT::i32));
|
||||||
|
SDOperand Amt = Op.getOperand(1);
|
||||||
|
|
||||||
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
||||||
|
DAG.getConstant(32, MVT::i32), Amt);
|
||||||
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
||||||
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
||||||
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
||||||
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
||||||
|
DAG.getConstant(-32U, MVT::i32));
|
||||||
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5);
|
||||||
|
SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
||||||
|
SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSRA(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
assert(Op.getValueType() == MVT::i64 &&
|
||||||
|
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
|
||||||
|
// The generic code does a fine job expanding shift by a constant.
|
||||||
|
if (isa<ConstantSDNode>(Op.getOperand(1))) return SDOperand();
|
||||||
|
|
||||||
|
// Otherwise, expand into a bunch of logical ops, followed by a select_cc.
|
||||||
|
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(0, MVT::i32));
|
||||||
|
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
||||||
|
DAG.getConstant(1, MVT::i32));
|
||||||
|
SDOperand Amt = Op.getOperand(1);
|
||||||
|
|
||||||
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
||||||
|
DAG.getConstant(32, MVT::i32), Amt);
|
||||||
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
||||||
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
||||||
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
||||||
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
||||||
|
DAG.getConstant(-32U, MVT::i32));
|
||||||
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5);
|
||||||
|
SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt);
|
||||||
|
SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32),
|
||||||
|
Tmp4, Tmp6, ISD::SETLE);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Vector related lowering.
|
||||||
|
//
|
||||||
|
|
||||||
// If this is a vector of constants or undefs, get the bits. A bit in
|
// If this is a vector of constants or undefs, get the bits. A bit in
|
||||||
// UndefBits is set if the corresponding element of the vector is an
|
// UndefBits is set if the corresponding element of the vector is an
|
||||||
// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
|
// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
|
||||||
@ -740,385 +1126,9 @@ static SDOperand LowerVECTOR_SHUFFLE(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
|
return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom
|
||||||
///
|
/// lower, do it, otherwise return null.
|
||||||
SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
static SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
|
||||||
switch (Op.getOpcode()) {
|
|
||||||
default: assert(0 && "Wasn't expecting to be able to lower this!");
|
|
||||||
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
|
||||||
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
|
||||||
case ISD::FP_TO_SINT: {
|
|
||||||
assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType()));
|
|
||||||
SDOperand Src = Op.getOperand(0);
|
|
||||||
if (Src.getValueType() == MVT::f32)
|
|
||||||
Src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Src);
|
|
||||||
|
|
||||||
SDOperand Tmp;
|
|
||||||
switch (Op.getValueType()) {
|
|
||||||
default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!");
|
|
||||||
case MVT::i32:
|
|
||||||
Tmp = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Src);
|
|
||||||
break;
|
|
||||||
case MVT::i64:
|
|
||||||
Tmp = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Src);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the FP value to an int value through memory.
|
|
||||||
SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Tmp);
|
|
||||||
if (Op.getValueType() == MVT::i32)
|
|
||||||
Bits = DAG.getNode(ISD::TRUNCATE, MVT::i32, Bits);
|
|
||||||
return Bits;
|
|
||||||
}
|
|
||||||
case ISD::SINT_TO_FP:
|
|
||||||
if (Op.getOperand(0).getValueType() == MVT::i64) {
|
|
||||||
SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0));
|
|
||||||
SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits);
|
|
||||||
if (Op.getValueType() == MVT::f32)
|
|
||||||
FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
|
|
||||||
return FP;
|
|
||||||
} else {
|
|
||||||
assert(Op.getOperand(0).getValueType() == MVT::i32 &&
|
|
||||||
"Unhandled SINT_TO_FP type in custom expander!");
|
|
||||||
// Since we only generate this in 64-bit mode, we can take advantage of
|
|
||||||
// 64-bit registers. In particular, sign extend the input value into the
|
|
||||||
// 64-bit register with extsw, store the WHOLE 64-bit value into the stack
|
|
||||||
// then lfd it and fcfid it.
|
|
||||||
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
|
||||||
int FrameIdx = FrameInfo->CreateStackObject(8, 8);
|
|
||||||
SDOperand FIdx = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
|
||||||
|
|
||||||
SDOperand Ext64 = DAG.getNode(PPCISD::EXTSW_32, MVT::i32,
|
|
||||||
Op.getOperand(0));
|
|
||||||
|
|
||||||
// STD the extended value into the stack slot.
|
|
||||||
SDOperand Store = DAG.getNode(PPCISD::STD_32, MVT::Other,
|
|
||||||
DAG.getEntryNode(), Ext64, FIdx,
|
|
||||||
DAG.getSrcValue(NULL));
|
|
||||||
// Load the value as a double.
|
|
||||||
SDOperand Ld = DAG.getLoad(MVT::f64, Store, FIdx, DAG.getSrcValue(NULL));
|
|
||||||
|
|
||||||
// FCFID it and return it.
|
|
||||||
SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Ld);
|
|
||||||
if (Op.getValueType() == MVT::f32)
|
|
||||||
FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP);
|
|
||||||
return FP;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ISD::SELECT_CC: {
|
|
||||||
// Turn FP only select_cc's into fsel instructions.
|
|
||||||
if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) ||
|
|
||||||
!MVT::isFloatingPoint(Op.getOperand(2).getValueType()))
|
|
||||||
break;
|
|
||||||
|
|
||||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
|
|
||||||
|
|
||||||
// Cannot handle SETEQ/SETNE.
|
|
||||||
if (CC == ISD::SETEQ || CC == ISD::SETNE) break;
|
|
||||||
|
|
||||||
MVT::ValueType ResVT = Op.getValueType();
|
|
||||||
MVT::ValueType CmpVT = Op.getOperand(0).getValueType();
|
|
||||||
SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);
|
|
||||||
SDOperand TV = Op.getOperand(2), FV = Op.getOperand(3);
|
|
||||||
|
|
||||||
// If the RHS of the comparison is a 0.0, we don't need to do the
|
|
||||||
// subtraction at all.
|
|
||||||
if (isFloatingPointZero(RHS))
|
|
||||||
switch (CC) {
|
|
||||||
default: break; // SETUO etc aren't handled by fsel.
|
|
||||||
case ISD::SETULT:
|
|
||||||
case ISD::SETLT:
|
|
||||||
std::swap(TV, FV); // fsel is natively setge, swap operands for setlt
|
|
||||||
case ISD::SETUGE:
|
|
||||||
case ISD::SETGE:
|
|
||||||
if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT, LHS, TV, FV);
|
|
||||||
case ISD::SETUGT:
|
|
||||||
case ISD::SETGT:
|
|
||||||
std::swap(TV, FV); // fsel is natively setge, swap operands for setlt
|
|
||||||
case ISD::SETULE:
|
|
||||||
case ISD::SETLE:
|
|
||||||
if (LHS.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT,
|
|
||||||
DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand Cmp;
|
|
||||||
switch (CC) {
|
|
||||||
default: break; // SETUO etc aren't handled by fsel.
|
|
||||||
case ISD::SETULT:
|
|
||||||
case ISD::SETLT:
|
|
||||||
Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
|
|
||||||
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
|
|
||||||
case ISD::SETUGE:
|
|
||||||
case ISD::SETGE:
|
|
||||||
Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS);
|
|
||||||
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
|
|
||||||
case ISD::SETUGT:
|
|
||||||
case ISD::SETGT:
|
|
||||||
Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
|
|
||||||
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV);
|
|
||||||
case ISD::SETULE:
|
|
||||||
case ISD::SETLE:
|
|
||||||
Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS);
|
|
||||||
if (Cmp.getValueType() == MVT::f32) // Comparison is always 64-bits
|
|
||||||
Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp);
|
|
||||||
return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ISD::SHL: {
|
|
||||||
assert(Op.getValueType() == MVT::i64 &&
|
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
|
|
||||||
// The generic code does a fine job expanding shift by a constant.
|
|
||||||
if (isa<ConstantSDNode>(Op.getOperand(1))) break;
|
|
||||||
|
|
||||||
// Otherwise, expand into a bunch of logical ops. Note that these ops
|
|
||||||
// depend on the PPC behavior for oversized shift amounts.
|
|
||||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(0, MVT::i32));
|
|
||||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(1, MVT::i32));
|
|
||||||
SDOperand Amt = Op.getOperand(1);
|
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt);
|
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1);
|
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5);
|
|
||||||
SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
|
||||||
SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt);
|
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
|
||||||
}
|
|
||||||
case ISD::SRL: {
|
|
||||||
assert(Op.getValueType() == MVT::i64 &&
|
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
|
|
||||||
// The generic code does a fine job expanding shift by a constant.
|
|
||||||
if (isa<ConstantSDNode>(Op.getOperand(1))) break;
|
|
||||||
|
|
||||||
// Otherwise, expand into a bunch of logical ops. Note that these ops
|
|
||||||
// depend on the PPC behavior for oversized shift amounts.
|
|
||||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(0, MVT::i32));
|
|
||||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(1, MVT::i32));
|
|
||||||
SDOperand Amt = Op.getOperand(1);
|
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5);
|
|
||||||
SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
|
||||||
SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt);
|
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
|
||||||
}
|
|
||||||
case ISD::SRA: {
|
|
||||||
assert(Op.getValueType() == MVT::i64 &&
|
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
|
|
||||||
// The generic code does a fine job expanding shift by a constant.
|
|
||||||
if (isa<ConstantSDNode>(Op.getOperand(1))) break;
|
|
||||||
|
|
||||||
// Otherwise, expand into a bunch of logical ops, followed by a select_cc.
|
|
||||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(0, MVT::i32));
|
|
||||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0),
|
|
||||||
DAG.getConstant(1, MVT::i32));
|
|
||||||
SDOperand Amt = Op.getOperand(1);
|
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5);
|
|
||||||
SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt);
|
|
||||||
SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32),
|
|
||||||
Tmp4, Tmp6, ISD::SETLE);
|
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi);
|
|
||||||
}
|
|
||||||
case ISD::ConstantPool: {
|
|
||||||
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
|
|
||||||
Constant *C = CP->get();
|
|
||||||
SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i32, CP->getAlignment());
|
|
||||||
SDOperand Zero = DAG.getConstant(0, MVT::i32);
|
|
||||||
|
|
||||||
// If this is a non-darwin platform, we don't support non-static relo models
|
|
||||||
// yet.
|
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::Static ||
|
|
||||||
!getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) {
|
|
||||||
// Generate non-pic code that has direct accesses to the constant pool.
|
|
||||||
// The address of the global is just (hi(&g)+lo(&g)).
|
|
||||||
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero);
|
|
||||||
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero);
|
|
||||||
return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero);
|
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC) {
|
|
||||||
// With PIC, the first instruction is actually "GR+hi(&G)".
|
|
||||||
Hi = DAG.getNode(ISD::ADD, MVT::i32,
|
|
||||||
DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero);
|
|
||||||
Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
|
||||||
return Lo;
|
|
||||||
}
|
|
||||||
case ISD::GlobalAddress: {
|
|
||||||
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
|
|
||||||
GlobalValue *GV = GSDN->getGlobal();
|
|
||||||
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32, GSDN->getOffset());
|
|
||||||
SDOperand Zero = DAG.getConstant(0, MVT::i32);
|
|
||||||
|
|
||||||
// If this is a non-darwin platform, we don't support non-static relo models
|
|
||||||
// yet.
|
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::Static ||
|
|
||||||
!getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) {
|
|
||||||
// Generate non-pic code that has direct accesses to globals.
|
|
||||||
// The address of the global is just (hi(&g)+lo(&g)).
|
|
||||||
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero);
|
|
||||||
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero);
|
|
||||||
return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero);
|
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC) {
|
|
||||||
// With PIC, the first instruction is actually "GR+hi(&G)".
|
|
||||||
Hi = DAG.getNode(ISD::ADD, MVT::i32,
|
|
||||||
DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero);
|
|
||||||
Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
|
|
||||||
|
|
||||||
if (!GV->hasWeakLinkage() && !GV->hasLinkOnceLinkage() &&
|
|
||||||
(!GV->isExternal() || GV->hasNotBeenReadFromBytecode()))
|
|
||||||
return Lo;
|
|
||||||
|
|
||||||
// If the global is weak or external, we have to go through the lazy
|
|
||||||
// resolution stub.
|
|
||||||
return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Lo, DAG.getSrcValue(0));
|
|
||||||
}
|
|
||||||
case ISD::SETCC: {
|
|
||||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
|
||||||
|
|
||||||
// If we're comparing for equality to zero, expose the fact that this is
|
|
||||||
// implented as a ctlz/srl pair on ppc, so that the dag combiner can
|
|
||||||
// fold the new nodes.
|
|
||||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
|
||||||
if (C->isNullValue() && CC == ISD::SETEQ) {
|
|
||||||
MVT::ValueType VT = Op.getOperand(0).getValueType();
|
|
||||||
SDOperand Zext = Op.getOperand(0);
|
|
||||||
if (VT < MVT::i32) {
|
|
||||||
VT = MVT::i32;
|
|
||||||
Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0));
|
|
||||||
}
|
|
||||||
unsigned Log2b = Log2_32(MVT::getSizeInBits(VT));
|
|
||||||
SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext);
|
|
||||||
SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz,
|
|
||||||
DAG.getConstant(Log2b, getShiftAmountTy()));
|
|
||||||
return DAG.getNode(ISD::TRUNCATE, getSetCCResultTy(), Scc);
|
|
||||||
}
|
|
||||||
// Leave comparisons against 0 and -1 alone for now, since they're usually
|
|
||||||
// optimized. FIXME: revisit this when we can custom lower all setcc
|
|
||||||
// optimizations.
|
|
||||||
if (C->isAllOnesValue() || C->isNullValue())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have an integer seteq/setne, turn it into a compare against zero
|
|
||||||
// by subtracting the rhs from the lhs, which is faster than setting a
|
|
||||||
// condition register, reading it back out, and masking the correct bit.
|
|
||||||
MVT::ValueType LHSVT = Op.getOperand(0).getValueType();
|
|
||||||
if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
|
|
||||||
MVT::ValueType VT = Op.getValueType();
|
|
||||||
SDOperand Sub = DAG.getNode(ISD::SUB, LHSVT, Op.getOperand(0),
|
|
||||||
Op.getOperand(1));
|
|
||||||
return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ISD::VASTART: {
|
|
||||||
// vastart just stores the address of the VarArgsFrameIndex slot into the
|
|
||||||
// memory location argument.
|
|
||||||
// FIXME: Replace MVT::i32 with PointerTy
|
|
||||||
SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
|
|
||||||
return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR,
|
|
||||||
Op.getOperand(1), Op.getOperand(2));
|
|
||||||
}
|
|
||||||
case ISD::RET: {
|
|
||||||
SDOperand Copy;
|
|
||||||
|
|
||||||
switch(Op.getNumOperands()) {
|
|
||||||
default:
|
|
||||||
assert(0 && "Do not know how to return this many arguments!");
|
|
||||||
abort();
|
|
||||||
case 1:
|
|
||||||
return SDOperand(); // ret void is legal
|
|
||||||
case 2: {
|
|
||||||
MVT::ValueType ArgVT = Op.getOperand(1).getValueType();
|
|
||||||
unsigned ArgReg;
|
|
||||||
if (MVT::isVector(ArgVT))
|
|
||||||
ArgReg = PPC::V2;
|
|
||||||
else if (MVT::isInteger(ArgVT))
|
|
||||||
ArgReg = PPC::R3;
|
|
||||||
else {
|
|
||||||
assert(MVT::isFloatingPoint(ArgVT));
|
|
||||||
ArgReg = PPC::F1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1),
|
|
||||||
SDOperand());
|
|
||||||
|
|
||||||
// If we haven't noted the R3/F1 are live out, do so now.
|
|
||||||
if (DAG.getMachineFunction().liveout_empty())
|
|
||||||
DAG.getMachineFunction().addLiveOut(ArgReg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
Copy = DAG.getCopyToReg(Op.getOperand(0), PPC::R3, Op.getOperand(2),
|
|
||||||
SDOperand());
|
|
||||||
Copy = DAG.getCopyToReg(Copy, PPC::R4, Op.getOperand(1),Copy.getValue(1));
|
|
||||||
// If we haven't noted the R3+R4 are live out, do so now.
|
|
||||||
if (DAG.getMachineFunction().liveout_empty()) {
|
|
||||||
DAG.getMachineFunction().addLiveOut(PPC::R3);
|
|
||||||
DAG.getMachineFunction().addLiveOut(PPC::R4);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
|
|
||||||
}
|
|
||||||
case ISD::SCALAR_TO_VECTOR: {
|
|
||||||
// Create a stack slot that is 16-byte aligned.
|
|
||||||
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
|
||||||
int FrameIdx = FrameInfo->CreateStackObject(16, 16);
|
|
||||||
SDOperand FIdx = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
|
||||||
|
|
||||||
// Store the input value into Value#0 of the stack slot.
|
|
||||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
|
||||||
Op.getOperand(0), FIdx,DAG.getSrcValue(NULL));
|
|
||||||
// Load it out.
|
|
||||||
return DAG.getLoad(Op.getValueType(), Store, FIdx, DAG.getSrcValue(NULL));
|
|
||||||
}
|
|
||||||
case ISD::INTRINSIC_WO_CHAIN: {
|
|
||||||
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
|
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
|
||||||
|
|
||||||
// If this is a lowered altivec predicate compare, CompareOpc is set to the
|
// If this is a lowered altivec predicate compare, CompareOpc is set to the
|
||||||
@ -1215,11 +1225,54 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
Flags = DAG.getNode(ISD::XOR, MVT::i32, Flags,
|
Flags = DAG.getNode(ISD::XOR, MVT::i32, Flags,
|
||||||
DAG.getConstant(1, MVT::i32));
|
DAG.getConstant(1, MVT::i32));
|
||||||
return Flags;
|
return Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
// Create a stack slot that is 16-byte aligned.
|
||||||
|
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
||||||
|
int FrameIdx = FrameInfo->CreateStackObject(16, 16);
|
||||||
|
SDOperand FIdx = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
|
||||||
|
// Store the input value into Value#0 of the stack slot.
|
||||||
|
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||||
|
Op.getOperand(0), FIdx,DAG.getSrcValue(NULL));
|
||||||
|
// Load it out.
|
||||||
|
return DAG.getLoad(Op.getValueType(), Store, FIdx, DAG.getSrcValue(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
|
///
|
||||||
|
SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||||
|
switch (Op.getOpcode()) {
|
||||||
|
default: assert(0 && "Wasn't expecting to be able to lower this!");
|
||||||
|
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||||
|
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||||
|
case ISD::SETCC: return LowerSETCC(Op, DAG);
|
||||||
|
case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex);
|
||||||
|
case ISD::RET: return LowerRET(Op, DAG);
|
||||||
|
|
||||||
|
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||||
|
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
|
||||||
|
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
|
||||||
|
|
||||||
|
// Lower 64-bit shifts.
|
||||||
|
case ISD::SHL: return LowerSHL(Op, DAG);
|
||||||
|
case ISD::SRL: return LowerSRL(Op, DAG);
|
||||||
|
case ISD::SRA: return LowerSRA(Op, DAG);
|
||||||
|
|
||||||
|
// Vector-related lowering.
|
||||||
|
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
||||||
|
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
||||||
|
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||||
|
case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG);
|
||||||
}
|
}
|
||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Other Lowering Code
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
std::vector<SDOperand>
|
std::vector<SDOperand>
|
||||||
PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||||
//
|
//
|
||||||
@ -1663,6 +1716,10 @@ PPCTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
|
|||||||
return BB;
|
return BB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Target Optimization Hooks
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
|
SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
|
||||||
DAGCombinerInfo &DCI) const {
|
DAGCombinerInfo &DCI) const {
|
||||||
TargetMachine &TM = getTargetMachine();
|
TargetMachine &TM = getTargetMachine();
|
||||||
@ -1751,6 +1808,10 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
|
|||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Inline Assembly Support
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
|
void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
|
||||||
uint64_t Mask,
|
uint64_t Mask,
|
||||||
uint64_t &KnownZero,
|
uint64_t &KnownZero,
|
||||||
|
Reference in New Issue
Block a user