#endif
assert(0 && "Do not know how to legalize this operator!");
abort();
+ case ISD::JumpTableRelocBase:
+ switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+ case TargetLowering::Custom:
+ Tmp1 = TLI.LowerOperation(Op, DAG);
+ if (Tmp1.Val) Result = Tmp1;
+ break;
+ default:
+ Result = LegalizeOp(Node->getOperand(0));
+ break;
+ }
+ break;
case ISD::GlobalAddress:
case ISD::ExternalSymbol:
case ISD::ConstantPool:
if (isDouble && CFP->isExactlyValue((float)CFP->getValue()) &&
// Only do this if the target has a native EXTLOAD instruction from
// f32.
- TLI.isOperationLegal(ISD::EXTLOAD, MVT::f32)) {
+ TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
LLVMC = cast<ConstantFP>(ConstantExpr::getCast(LLVMC, Type::FloatTy));
VT = MVT::f32;
Extend = true;
AddLegalizedOperand(SDOperand(Node, 1), Tmp4);
return Op.ResNo ? Tmp4 : Tmp3;
}
- case ISD::EXTLOAD:
- case ISD::SEXTLOAD:
- case ISD::ZEXTLOAD: {
+ case ISD::LOADX: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
MVT::ValueType SrcVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
- switch (TLI.getOperationAction(Node->getOpcode(), SrcVT)) {
+ unsigned LType = cast<ConstantSDNode>(Node->getOperand(4))->getValue();
+ switch (TLI.getLoadXAction(LType, SrcVT)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Promote:
- assert(SrcVT == MVT::i1 && "Can only promote EXTLOAD from i1 -> i8!");
+ assert(SrcVT == MVT::i1 && "Can only promote LOADX from i1 -> i8!");
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2),
- DAG.getValueType(MVT::i8));
+ DAG.getValueType(MVT::i8),
+ Node->getOperand(4));
Tmp1 = Result.getValue(0);
Tmp2 = Result.getValue(1);
break;
// FALLTHROUGH
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2),
- Node->getOperand(3));
+ Node->getOperand(3), Node->getOperand(4));
Tmp1 = Result.getValue(0);
Tmp2 = Result.getValue(1);
if (isCustom) {
- Tmp3 = TLI.LowerOperation(Tmp3, DAG);
+ Tmp3 = TLI.LowerOperation(Result, DAG);
if (Tmp3.Val) {
Tmp1 = LegalizeOp(Tmp3);
Tmp2 = LegalizeOp(Tmp3.getValue(1));
Tmp2 = LegalizeOp(Load.getValue(1));
break;
}
- assert(Node->getOpcode() != ISD::EXTLOAD &&
- "EXTLOAD should always be supported!");
+ assert(LType != ISD::EXTLOAD && "EXTLOAD should always be supported!");
// Turn the unsupported load into an EXTLOAD followed by an explicit
// zero/sign extend inreg.
Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0),
Tmp1, Tmp2, Node->getOperand(2), SrcVT);
SDOperand ValRes;
- if (Node->getOpcode() == ISD::SEXTLOAD)
+ if (LType == ISD::SEXTLOAD)
ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
Result, DAG.getValueType(SrcVT));
else
if (Tmp1.Val) Result = Tmp1;
break;
case TargetLowering::Expand: {
+ if (Node->getValueType(0) == MVT::i32) {
+ switch (Node->getOpcode()) {
+ default: assert(0 && "Do not know how to expand this integer BinOp!");
+ case ISD::UDIV:
+ case ISD::SDIV:
+ const char *FnName = Node->getOpcode() == ISD::UDIV
+ ? "__udivsi3" : "__divsi3";
+ SDOperand Dummy;
+ Result = ExpandLibCall(FnName, Node, Dummy);
+ };
+ break;
+ }
+
assert(MVT::isVector(Node->getValueType(0)) &&
"Cannot expand this binary operator!");
// Expand the operation into a bunch of nasty scalar code.
}
break;
case TargetLowering::Expand:
+ unsigned DivOpc= (Node->getOpcode() == ISD::UREM) ? ISD::UDIV : ISD::SDIV;
if (MVT::isInteger(Node->getValueType(0))) {
- // X % Y -> X-X/Y*Y
- MVT::ValueType VT = Node->getValueType(0);
- unsigned Opc = Node->getOpcode() == ISD::UREM ? ISD::UDIV : ISD::SDIV;
- Result = DAG.getNode(Opc, VT, Tmp1, Tmp2);
- Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
- Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
+ if (TLI.getOperationAction(DivOpc, Node->getValueType(0)) ==
+ TargetLowering::Legal) {
+ // X % Y -> X-X/Y*Y
+ MVT::ValueType VT = Node->getValueType(0);
+ Result = DAG.getNode(DivOpc, VT, Tmp1, Tmp2);
+ Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
+ Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
+ } else {
+ assert(Node->getValueType(0) == MVT::i32 &&
+ "Cannot expand this binary operator!");
+ const char *FnName = Node->getOpcode() == ISD::UREM
+ ? "__umodsi3" : "__modsi3";
+ SDOperand Dummy;
+ Result = ExpandLibCall(FnName, Node, Dummy);
+ }
} else {
// Floating point mod -> fmod libcall.
const char *FnName = Node->getValueType(0) == MVT::f32 ? "fmodf":"fmod";
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
break;
- case ISD::SEXTLOAD:
- case ISD::ZEXTLOAD:
- case ISD::EXTLOAD:
- Result = DAG.getExtLoad(Node->getOpcode(), NVT, Node->getOperand(0),
- Node->getOperand(1), Node->getOperand(2),
- cast<VTSDNode>(Node->getOperand(3))->getVT());
+ case ISD::LOADX:
+ Result =
+ DAG.getExtLoad((ISD::LoadExtType)Node->getConstantOperandVal(4),
+ NVT, Node->getOperand(0), Node->getOperand(1),
+ Node->getOperand(2),
+ cast<VTSDNode>(Node->getOperand(3))->getVT());
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
break;
return true;
}
}
+
+ // Okay, the shift amount isn't constant. However, if we can tell that it is
+ // >= 32 or < 32, we can still simplify it, without knowing the actual value.
+ uint64_t Mask = NVTBits, KnownZero, KnownOne;
+ TLI.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
+
+ // If we know that the high bit of the shift amount is one, then we can do
+ // this as a couple of simple shifts.
+ if (KnownOne & Mask) {
+ // Mask out the high bit, which we know is set.
+ Amt = DAG.getNode(ISD::AND, Amt.getValueType(), Amt,
+ DAG.getConstant(NVTBits-1, Amt.getValueType()));
+
+ // Expand the incoming operand to be shifted, so that we have its parts
+ SDOperand InL, InH;
+ ExpandOp(Op, InL, InH);
+ switch(Opc) {
+ case ISD::SHL:
+ Lo = DAG.getConstant(0, NVT); // Low part is zero.
+ Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part.
+ return true;
+ case ISD::SRL:
+ Hi = DAG.getConstant(0, NVT); // Hi part is zero.
+ Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ case ISD::SRA:
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part.
+ DAG.getConstant(NVTBits-1, Amt.getValueType()));
+ Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ }
+ }
+
+ // If we know that the high bit of the shift amount is zero, then we can do
+ // this as a couple of simple shifts.
+ if (KnownZero & Mask) {
+ // Compute 32-amt.
+ SDOperand Amt2 = DAG.getNode(ISD::SUB, Amt.getValueType(),
+ DAG.getConstant(NVTBits, Amt.getValueType()),
+ Amt);
+
+ // Expand the incoming operand to be shifted, so that we have its parts
+ SDOperand InL, InH;
+ ExpandOp(Op, InL, InH);
+ switch(Opc) {
+ case ISD::SHL:
+ Lo = DAG.getNode(ISD::SHL, NVT, InL, Amt);
+ Hi = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SHL, NVT, InH, Amt),
+ DAG.getNode(ISD::SRL, NVT, InL, Amt2));
+ return true;
+ case ISD::SRL:
+ Hi = DAG.getNode(ISD::SRL, NVT, InH, Amt);
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL, Amt),
+ DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+ return true;
+ case ISD::SRA:
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, Amt);
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL, Amt),
+ DAG.getNode(ISD::SHL, NVT, InH, Amt2));
+ return true;
+ }
+ }
+
return false;
}
Node->getOperand(1), TH, FH, Node->getOperand(4));
break;
}
- case ISD::SEXTLOAD: {
+ case ISD::LOADX: {
SDOperand Chain = Node->getOperand(0);
SDOperand Ptr = Node->getOperand(1);
MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
+ unsigned LType = Node->getConstantOperandVal(4);
if (EVT == NVT)
Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
// Remember that we legalized the chain.
AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
-
- // The high part is obtained by SRA'ing all but one of the bits of the lo
- // part.
- unsigned LoSize = MVT::getSizeInBits(Lo.getValueType());
- Hi = DAG.getNode(ISD::SRA, NVT, Lo, DAG.getConstant(LoSize-1,
- TLI.getShiftAmountTy()));
- break;
- }
- case ISD::ZEXTLOAD: {
- SDOperand Chain = Node->getOperand(0);
- SDOperand Ptr = Node->getOperand(1);
- MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
-
- if (EVT == NVT)
- Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
- else
- Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Chain, Ptr, Node->getOperand(2),
- EVT);
-
- // Remember that we legalized the chain.
- AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
- // The high part is just a zero.
- Hi = DAG.getConstant(0, NVT);
- break;
- }
- case ISD::EXTLOAD: {
- SDOperand Chain = Node->getOperand(0);
- SDOperand Ptr = Node->getOperand(1);
- MVT::ValueType EVT = cast<VTSDNode>(Node->getOperand(3))->getVT();
-
- if (EVT == NVT)
- Lo = DAG.getLoad(NVT, Chain, Ptr, Node->getOperand(2));
- else
- Lo = DAG.getExtLoad(ISD::EXTLOAD, NVT, Chain, Ptr, Node->getOperand(2),
- EVT);
-
- // Remember that we legalized the chain.
- AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
-
- // The high part is undefined.
- Hi = DAG.getNode(ISD::UNDEF, NVT);
+ if (LType == ISD::SEXTLOAD) {
+ // The high part is obtained by SRA'ing all but one of the bits of the lo
+ // part.
+ unsigned LoSize = MVT::getSizeInBits(Lo.getValueType());
+ Hi = DAG.getNode(ISD::SRA, NVT, Lo, DAG.getConstant(LoSize-1,
+ TLI.getShiftAmountTy()));
+ } else if (LType == ISD::ZEXTLOAD) {
+ // The high part is just a zero.
+ Hi = DAG.getConstant(0, NVT);
+ } else /* if (LType == ISD::EXTLOAD) */ {
+ // The high part is undefined.
+ Hi = DAG.getNode(ISD::UNDEF, NVT);
+ }
break;
}
case ISD::ANY_EXTEND:
}
}
+ // If ADDC/ADDE are supported and if the shift amount is a constant 1, emit
+ // this X << 1 as X+X.
+ if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(ShiftAmt)) {
+ if (ShAmt->getValue() == 1 && TLI.isOperationLegal(ISD::ADDC, NVT) &&
+ TLI.isOperationLegal(ISD::ADDE, NVT)) {
+ SDOperand LoOps[2], HiOps[3];
+ ExpandOp(Node->getOperand(0), LoOps[0], HiOps[0]);
+ SDVTList VTList = DAG.getVTList(LoOps[0].getValueType(), MVT::Flag);
+ LoOps[1] = LoOps[0];
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+
+ HiOps[1] = HiOps[0];
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+ break;
+ }
+ }
+
// If we can emit an efficient shift operation, do so now.
if (ExpandShift(ISD::SHL, Node->getOperand(0), ShiftAmt, Lo, Hi))
break;
SDOperand LHSL, LHSH, RHSL, RHSH;
ExpandOp(Node->getOperand(0), LHSL, LHSH);
ExpandOp(Node->getOperand(1), RHSL, RHSH);
- const MVT::ValueType *VTs =
- DAG.getNodeValueTypes(LHSL.getValueType(),MVT::Flag);
- SDOperand LoOps[2], HiOps[2];
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[2], HiOps[3];
LoOps[0] = LHSL;
LoOps[1] = RHSL;
HiOps[0] = LHSH;
HiOps[1] = RHSH;
if (Node->getOpcode() == ISD::ADD) {
- Lo = DAG.getNode(ISD::ADDC, VTs, 2, LoOps, 2);
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::ADDE, VTs, 2, HiOps, 3);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
} else {
- Lo = DAG.getNode(ISD::SUBC, VTs, 2, LoOps, 2);
+ Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::SUBE, VTs, 2, HiOps, 3);
+ Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
}
break;
}
case ISD::MUL: {
+ // If the target wants to custom expand this, let them.
+ if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) {
+ SDOperand New = TLI.LowerOperation(Op, DAG);
+ if (New.Val) {
+ ExpandOp(New, Lo, Hi);
+ break;
+ }
+ }
+
bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
bool UseLibCall = true;
LH.getOpcode() == ISD::SRA && LH.getOperand(0) == LL &&
LH.getOperand(1).getOpcode() == ISD::Constant &&
cast<ConstantSDNode>(LH.getOperand(1))->getValue() == SH) {
+ // FIXME: Move this to the dag combiner.
+
+ // Low part:
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ // High part:
Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
- UseLibCall = false;
+ break;
} else if (HasMULHU) {
+ // Low part:
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+
+ // High part:
Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
- UseLibCall = false;
+ break;
}
- if (!UseLibCall)
- Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
}
- if (UseLibCall)
- Lo = ExpandLibCall("__muldi3" , Node, Hi);
+ Lo = ExpandLibCall("__muldi3" , Node, Hi);
break;
}
case ISD::SDIV: Lo = ExpandLibCall("__divdi3" , Node, Hi); break;