X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeIntegerTypes.cpp;h=d4be998be5ed32d4d5d0db868549680059da085a;hb=ee4c619b3b28a42078fc8033e5dccd42fc6edd42;hp=9e4ff4a8a01c3999da7a9fae51c02f66013bb060;hpb=ef5b199905cee0b78eb30cd44836e5b6ca5cbd09;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 9e4ff4a8a01..d4be998be5e 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -89,13 +89,65 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { case ISD::XOR: case ISD::ADD: case ISD::SUB: - case ISD::MUL: Result = PromoteIntRes_SimpleIntBinOp(N); break; + case ISD::MUL: Result = PromoteIntRes_SimpleIntBinOp(N); break; case ISD::SDIV: - case ISD::SREM: Result = PromoteIntRes_SDIV(N); break; + case ISD::SREM: Result = PromoteIntRes_SDIV(N); break; case ISD::UDIV: - case ISD::UREM: Result = PromoteIntRes_UDIV(N); break; + case ISD::UREM: Result = PromoteIntRes_UDIV(N); break; + + case ISD::ATOMIC_LOAD_ADD_8: + case ISD::ATOMIC_LOAD_SUB_8: + case ISD::ATOMIC_LOAD_AND_8: + case ISD::ATOMIC_LOAD_OR_8: + case ISD::ATOMIC_LOAD_XOR_8: + case ISD::ATOMIC_LOAD_NAND_8: + case ISD::ATOMIC_LOAD_MIN_8: + case ISD::ATOMIC_LOAD_MAX_8: + case ISD::ATOMIC_LOAD_UMIN_8: + case ISD::ATOMIC_LOAD_UMAX_8: + case ISD::ATOMIC_SWAP_8: + case ISD::ATOMIC_LOAD_ADD_16: + case ISD::ATOMIC_LOAD_SUB_16: + case ISD::ATOMIC_LOAD_AND_16: + case ISD::ATOMIC_LOAD_OR_16: + case ISD::ATOMIC_LOAD_XOR_16: + case ISD::ATOMIC_LOAD_NAND_16: + case ISD::ATOMIC_LOAD_MIN_16: + case ISD::ATOMIC_LOAD_MAX_16: + case ISD::ATOMIC_LOAD_UMIN_16: + case ISD::ATOMIC_LOAD_UMAX_16: + case ISD::ATOMIC_SWAP_16: + case ISD::ATOMIC_LOAD_ADD_32: + case ISD::ATOMIC_LOAD_SUB_32: + case ISD::ATOMIC_LOAD_AND_32: + case ISD::ATOMIC_LOAD_OR_32: + case ISD::ATOMIC_LOAD_XOR_32: + case ISD::ATOMIC_LOAD_NAND_32: + case ISD::ATOMIC_LOAD_MIN_32: + case ISD::ATOMIC_LOAD_MAX_32: + case ISD::ATOMIC_LOAD_UMIN_32: + case ISD::ATOMIC_LOAD_UMAX_32: + case ISD::ATOMIC_SWAP_32: + case ISD::ATOMIC_LOAD_ADD_64: + case ISD::ATOMIC_LOAD_SUB_64: + case ISD::ATOMIC_LOAD_AND_64: + case ISD::ATOMIC_LOAD_OR_64: + case ISD::ATOMIC_LOAD_XOR_64: + case ISD::ATOMIC_LOAD_NAND_64: + case ISD::ATOMIC_LOAD_MIN_64: + case ISD::ATOMIC_LOAD_MAX_64: + case ISD::ATOMIC_LOAD_UMIN_64: + case ISD::ATOMIC_LOAD_UMAX_64: + case ISD::ATOMIC_SWAP_64: + Result = PromoteIntRes_Atomic1(cast(N)); break; + + case ISD::ATOMIC_CMP_SWAP_8: + case ISD::ATOMIC_CMP_SWAP_16: + case ISD::ATOMIC_CMP_SWAP_32: + case ISD::ATOMIC_CMP_SWAP_64: + Result = PromoteIntRes_Atomic2(cast(N)); break; } // If Result is null, the sub-method took care of registering the result. @@ -120,6 +172,27 @@ SDValue DAGTypeLegalizer::PromoteIntRes_AssertZext(SDNode *N) { DAG.getZeroExtendInReg(Op, OldVT), N->getOperand(1)); } +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic1(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getChain(), N->getBasePtr(), + Op2, N->getSrcValue(), N->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic2(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Op3 = GetPromotedInteger(N->getOperand(3)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getChain(), N->getBasePtr(), + Op2, Op3, N->getSrcValue(), N->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + SDValue DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) { SDValue InOp = N->getOperand(0); MVT InVT = InOp.getValueType(); @@ -364,14 +437,18 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { } SDValue DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); MVT SVT = TLI.getSetCCResultType(N->getOperand(0)); - assert(isTypeLegal(SVT) && "SetCC type not legal??"); + assert(isTypeLegal(SVT) && "Illegal SetCC type!"); + + // Get the SETCC result using the canonical SETCC type. + SDValue SetCC = DAG.getNode(ISD::SETCC, SVT, N->getOperand(0), + N->getOperand(1), N->getOperand(2)); + + // Convert to the expected type. + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); assert(NVT.getSizeInBits() <= SVT.getSizeInBits() && "Integer type overpromoted?"); - return DAG.getNode(ISD::TRUNCATE, NVT, - DAG.getNode(ISD::SETCC, SVT, N->getOperand(0), - N->getOperand(1), N->getOperand(2))); + return DAG.getNode(ISD::TRUNCATE, NVT, SetCC); } SDValue DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) { @@ -465,7 +542,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { // of zero here!). unsigned Increment = VT.getSizeInBits() / 8; SDValue Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList, - DAG.getConstant(Increment, TLI.getPointerTy())); + DAG.getIntPtrConstant(Increment)); // Store the incremented VAList to the pointer. Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0); @@ -495,7 +572,7 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) == TargetLowering::Custom) - Res = TLI.LowerOperation(SDValue(N, OpNo), DAG); + Res = TLI.LowerOperation(SDValue(N, 0), DAG); if (Res.getNode() == 0) { switch (N->getOpcode()) { @@ -731,18 +808,54 @@ SDValue DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { assert(OpNo == 0 && "Only know how to promote condition"); - SDValue Cond = GetPromotedInteger(N->getOperand(0)); // Promote condition. - - // The top bits of the promoted condition are not necessarily zero, ensure - // that the value is properly zero extended. - unsigned BitWidth = Cond.getValueSizeInBits(); - if (!DAG.MaskedValueIsZero(Cond, - APInt::getHighBitsSet(BitWidth, BitWidth-1))) - Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); + SDValue Cond = GetPromotedInteger(N->getOperand(0)); + + // Promote all the way up to SVT, the canonical SetCC type. + // FIXME: Not clear what value to pass to getSetCCResultType. + // [This only matters for CellSPU since all other targets + // ignore the argument.] We used to pass Cond, resulting in + // SVT = MVT::i8, but CellSPU has no select patterns for i8, + // causing an abort later. Passing the result type works + // around the problem. + MVT SVT = TLI.getSetCCResultType(N->getOperand(1)); + assert(isTypeLegal(SVT) && "Illegal SetCC type!"); + assert(Cond.getValueSizeInBits() <= SVT.getSizeInBits() && + "Unexpected SetCC type!"); + + // Make sure the extra bits conform to getSetCCResultContents. There are + // two sets of extra bits: those in Cond, which come from type promotion, + // and those we need to add to have the final type be SVT (for most targets + // this last set of bits is empty). + unsigned CondBits = Cond.getValueSizeInBits(); + ISD::NodeType ExtendCode; + switch (TLI.getSetCCResultContents()) { + default: + assert(false && "Unknown SetCCResultValue!"); + case TargetLowering::UndefinedSetCCResult: + // Extend to SVT by adding rubbish. + ExtendCode = ISD::ANY_EXTEND; + break; + case TargetLowering::ZeroOrOneSetCCResult: + ExtendCode = ISD::ZERO_EXTEND; + if (!DAG.MaskedValueIsZero(Cond,APInt::getHighBitsSet(CondBits,CondBits-1))) + // All extra bits need to be cleared. Do this by zero extending the + // original condition value all the way to SVT. + Cond = N->getOperand(0); + break; + case TargetLowering::ZeroOrNegativeOneSetCCResult: { + ExtendCode = ISD::SIGN_EXTEND; + unsigned SignBits = DAG.ComputeNumSignBits(Cond); + if (SignBits != CondBits) + // All extra bits need to be sign extended. Do this by sign extending the + // original condition value all the way to SVT. + Cond = N->getOperand(0); + break; + } + } + Cond = DAG.getNode(ExtendCode, SVT, Cond); - // The chain (Op#0) and basic block destination (Op#2) are always legal types. - return DAG.UpdateNodeOperands(SDValue(N, 0), Cond, N->getOperand(1), - N->getOperand(2)); + return DAG.UpdateNodeOperands(SDValue(N, 0), Cond, + N->getOperand(1), N->getOperand(2)); } SDValue DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) { @@ -1058,18 +1171,54 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, SDValue LHSL, LHSH, RHSL, RHSH; GetExpandedInteger(N->getOperand(0), LHSL, LHSH); GetExpandedInteger(N->getOperand(1), RHSL, RHSH); - SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + + MVT NVT = LHSL.getValueType(); + SDVTList VTList = DAG.getVTList(NVT, MVT::Flag); SDValue LoOps[2] = { LHSL, RHSL }; SDValue HiOps[3] = { LHSH, RHSH }; - if (N->getOpcode() == ISD::ADD) { - Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + // Do not generate ADDC/ADDE or SUBC/SUBE if the target does not support + // them. TODO: Teach operation legalization how to expand unsupported + // ADDC/ADDE/SUBC/SUBE. The problem is that these operations generate + // a carry of type MVT::Flag, but there doesn't seem to be any way to + // generate a value of this type in the expanded code sequence. + bool hasCarry = + TLI.isOperationLegal(N->getOpcode() == ISD::ADD ? ISD::ADDC : ISD::SUBC, + TLI.getTypeToExpandTo(NVT)); + + if (hasCarry) { + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + } } else { - Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADD, VTList, LoOps, 2); + Hi = DAG.getNode(ISD::ADD, VTList, HiOps, 2); + SDValue Cmp1 = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo, LoOps[0], + ISD::SETULT); + SDValue Carry1 = DAG.getNode(ISD::SELECT, NVT, Cmp1, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + SDValue Cmp2 = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo, LoOps[1], + ISD::SETULT); + SDValue Carry2 = DAG.getNode(ISD::SELECT, NVT, Cmp2, + DAG.getConstant(1, NVT), Carry1); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, Carry2); + } else { + Lo = DAG.getNode(ISD::SUB, VTList, LoOps, 2); + Hi = DAG.getNode(ISD::SUB, VTList, HiOps, 2); + SDValue Cmp = DAG.getSetCC(NVT, LoOps[0], LoOps[1], ISD::SETULT); + SDValue Borrow = DAG.getNode(ISD::SELECT, NVT, Cmp, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + Hi = DAG.getNode(ISD::SUB, NVT, Hi, Borrow); + } } } @@ -1707,7 +1856,7 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) == TargetLowering::Custom) - Res = TLI.LowerOperation(SDValue(N, OpNo), DAG); + Res = TLI.LowerOperation(SDValue(N, 0), DAG); if (Res.getNode() == 0) { switch (N->getOpcode()) { @@ -2037,7 +2186,7 @@ SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits. SDValue FudgePtr = DAG.getConstantPool(ConstantInt::get(FF.zext(64)), - TLI.getPointerTy()); + TLI.getPointerTy()); // Get a pointer to FF if the sign bit was set, or to 0 otherwise. SDValue Zero = DAG.getIntPtrConstant(0);