コード例 #1
0
static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
  SDNode *Node = Op.getNode();
  EVT VT = Node->getValueType(0);
  SDValue InChain = Node->getOperand(0);
  SDValue VAListPtr = Node->getOperand(1);
  const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
  DebugLoc dl = Node->getDebugLoc();
  SDValue VAList = DAG.getLoad(MVT::i32, dl, InChain, VAListPtr, SV, 0,
                               false, false, 0);
  // Increment the pointer, VAList, to the next vaarg
  SDValue NextPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, VAList,
                                  DAG.getConstant(VT.getSizeInBits()/8,
                                                  MVT::i32));
  // Store the incremented VAList to the legalized pointer
  InChain = DAG.getStore(VAList.getValue(1), dl, NextPtr,
                         VAListPtr, SV, 0, false, false, 0);
  // Load the actual argument out of the pointer VAList, unless this is an
  // f64 load.
  if (VT != MVT::f64)
    return DAG.getLoad(VT, dl, InChain, VAList, NULL, 0, false, false, 0);

  // Otherwise, load it as i64, then do a bitconvert.
  SDValue V = DAG.getLoad(MVT::i64, dl, InChain, VAList, NULL, 0,
                          false, false, 0);

  // Bit-Convert the value to f64.
  SDValue Ops[2] = {
    DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, V),
    V.getValue(1)
  };
  return DAG.getMergeValues(Ops, 2, dl);
}
コード例 #2
0
SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
        SelectionDAG &DAG) {
    unsigned Opc = Op.getOpcode();
    SDNode* N = Op.getNode();
    MVT VT = Op.getValueType();
    DebugLoc dl = N->getDebugLoc();

    // We currently only lower shifts of constant argument.
    if (!isa<ConstantSDNode>(N->getOperand(1)))
        return SDValue();

    uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();

    // Expand the stuff into sequence of shifts.
    // FIXME: for some shift amounts this might be done better!
    // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
    SDValue Victim = N->getOperand(0);

    if (Opc == ISD::SRL && ShiftAmount) {
        // Emit a special goodness here:
        // srl A, 1 => clrc; rrc A
        Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim);
        ShiftAmount -= 1;
    }

    while (ShiftAmount--)
        Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA),
                             dl, VT, Victim);

    return Victim;
}
コード例 #3
0
ファイル: SparcISelDAGToDAG.cpp プロジェクト: aaasz/SHP
SDNode *SparcDAGToDAGISel::Select(SDValue Op) {
  SDNode *N = Op.getNode();
  DebugLoc dl = N->getDebugLoc();
  if (N->isMachineOpcode())
    return NULL;   // Already selected.

  switch (N->getOpcode()) {
  default: break;
  case SPISD::GLOBAL_BASE_REG:
    return getGlobalBaseReg();

  case ISD::SDIV:
  case ISD::UDIV: {
    // FIXME: should use a custom expander to expose the SRA to the dag.
    SDValue DivLHS = N->getOperand(0);
    SDValue DivRHS = N->getOperand(1);

    // Set the Y register to the high-part.
    SDValue TopPart;
    if (N->getOpcode() == ISD::SDIV) {
      TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
                                   CurDAG->getTargetConstant(31, MVT::i32)), 0);
    } else {
      TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
    }
    TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Flag, TopPart,
                                     CurDAG->getRegister(SP::G0, MVT::i32)), 0);

    // FIXME: Handle div by immediate.
    unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
    return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS,
                                TopPart);
  }
  case ISD::MULHU:
  case ISD::MULHS: {
    // FIXME: Handle mul by immediate.
    SDValue MulLHS = N->getOperand(0);
    SDValue MulRHS = N->getOperand(1);
    unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
    SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Flag,
                                         MulLHS, MulRHS);
    // The high part is in the Y register.
    return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1));
    return NULL;
  }
  }

  return SelectCode(Op);
}
コード例 #4
0
SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
                                          SelectionDAG &DAG) const {
  unsigned Opc = Op.getOpcode();
  SDNode* N = Op.getNode();
  EVT VT = Op.getValueType();
  DebugLoc dl = N->getDebugLoc();

  // Expand non-constant shifts to loops:
  if (!isa<ConstantSDNode>(N->getOperand(1)))
    switch (Opc) {
    default:
      assert(0 && "Invalid shift opcode!");
    case ISD::SHL:
      return DAG.getNode(MSP430ISD::SHL, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    case ISD::SRA:
      return DAG.getNode(MSP430ISD::SRA, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    case ISD::SRL:
      return DAG.getNode(MSP430ISD::SRL, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    }

  uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();

  // Expand the stuff into sequence of shifts.
  // FIXME: for some shift amounts this might be done better!
  // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
  SDValue Victim = N->getOperand(0);

  if (Opc == ISD::SRL && ShiftAmount) {
    // Emit a special goodness here:
    // srl A, 1 => clrc; rrc A
    Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim);
    ShiftAmount -= 1;
  }

  while (ShiftAmount--)
    Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA),
                         dl, VT, Victim);

  return Victim;
}
コード例 #5
0
// By default CONCAT_VECTORS is lowered by ExpandVectorBuildThroughStack()
// (see LegalizeDAG.cpp). This is slow and uses local memory.
// We use extract/insert/build vector just as what LegalizeOp() does in llvm 2.5
SDValue NVPTXTargetLowering::
LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const {
  SDNode *Node = Op.getNode();
  DebugLoc dl = Node->getDebugLoc();
  SmallVector<SDValue, 8> Ops;
  unsigned NumOperands = Node->getNumOperands();
  for (unsigned i=0; i < NumOperands; ++i) {
    SDValue SubOp = Node->getOperand(i);
    EVT VVT = SubOp.getNode()->getValueType(0);
    EVT 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)));
    }
  }
  return DAG.getNode(ISD::BUILD_VECTOR, dl, Node->getValueType(0),
                     &Ops[0], Ops.size());
}
コード例 #6
0
ファイル: AVRISelLowering.cpp プロジェクト: saaadhu/AVR
SDValue AVRTargetLowering::LowerShifts(SDValue Op,
                                          SelectionDAG &DAG) const {
  unsigned Opc = Op.getOpcode();
  SDNode* N = Op.getNode();
  EVT VT = Op.getValueType();
  DebugLoc dl = N->getDebugLoc();

  // Expand non-constant shifts to loops:
  if (!isa<ConstantSDNode>(N->getOperand(1)))
    switch (Opc) {
    default:
      assert(0 && "Invalid shift opcode!");
    case ISD::SHL:
      return DAG.getNode(AVRISD::SHL, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    case ISD::SRA:
      return DAG.getNode(AVRISD::SRA, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    case ISD::SRL:
      return DAG.getNode(AVRISD::SRL, dl,
                         VT, N->getOperand(0), N->getOperand(1));
    }

  uint64_t ShiftAmount = N->getConstantOperandVal(1);

  // Expand the stuff into sequence of shifts.
  // FIXME: for some shift amounts this might be done better!
  // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
  SDValue Victim = N->getOperand(0);

  unsigned int TargetOpcode = 0;
  switch(Opc) {
    case ISD::SHL: TargetOpcode = AVRISD::SHLC; break;
    case ISD::SRA: TargetOpcode = AVRISD::SRAC; break;
    case ISD::SRL: TargetOpcode = AVRISD::SRLC; break;
  }

  while (ShiftAmount--)
    Victim = DAG.getNode(TargetOpcode, dl, VT, Victim);

  return Victim;
}
コード例 #7
0
SDNode *IA64DAGToDAGISel::SelectDIV(SDValue Op) {
    SDNode *N = Op.getNode();
    SDValue Chain = N->getOperand(0);
    SDValue Tmp1 = N->getOperand(0);
    SDValue Tmp2 = N->getOperand(1);
    DebugLoc dl = N->getDebugLoc();

    bool isFP=false;

    if(Tmp1.getValueType().isFloatingPoint())
        isFP=true;

    bool isModulus=false; // is it a division or a modulus?
    bool isSigned=false;

    switch(N->getOpcode()) {
    case ISD::FDIV:
    case ISD::SDIV:
        isModulus=false;
        isSigned=true;
        break;
    case ISD::UDIV:
        isModulus=false;
        isSigned=false;
        break;
    case ISD::FREM:
    case ISD::SREM:
        isModulus=true;
        isSigned=true;
        break;
    case ISD::UREM:
        isModulus=true;
        isSigned=false;
        break;
    }

    // TODO: check for integer divides by powers of 2 (or other simple patterns?)

    SDValue TmpPR, TmpPR2;
    SDValue TmpF1, TmpF2, TmpF3, TmpF4, TmpF5, TmpF6, TmpF7, TmpF8;
    SDValue TmpF9, TmpF10,TmpF11,TmpF12,TmpF13,TmpF14,TmpF15;
    SDNode *Result;

    // we'll need copies of F0 and F1
    SDValue F0 = CurDAG->getRegister(IA64::F0, MVT::f64);
    SDValue F1 = CurDAG->getRegister(IA64::F1, MVT::f64);

    // OK, emit some code:

    if(!isFP) {
        // first, load the inputs into FP regs.
        TmpF1 =
            SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp1), 0);
        Chain = TmpF1.getValue(1);
        TmpF2 =
            SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp2), 0);
        Chain = TmpF2.getValue(1);

        // next, convert the inputs to FP
        if(isSigned) {
            TmpF3 =
                SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF1), 0);
            Chain = TmpF3.getValue(1);
            TmpF4 =
                SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF2), 0);
            Chain = TmpF4.getValue(1);
        } else { // is unsigned
            TmpF3 =
                SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF1),
                        0);
            Chain = TmpF3.getValue(1);
            TmpF4 =
                SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF2),
                        0);
            Chain = TmpF4.getValue(1);
        }

    } else { // this is an FP divide/remainder, so we 'leak' some temp
        // regs and assign TmpF3=Tmp1, TmpF4=Tmp2
        TmpF3=Tmp1;
        TmpF4=Tmp2;
    }

    // we start by computing an approximate reciprocal (good to 9 bits?)
    // note, this instruction writes _both_ TmpF5 (answer) and TmpPR (predicate)
    if(isFP)
        TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS0, dl, MVT::f64,
                                              MVT::i1, TmpF3, TmpF4), 0);
    else
        TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS1, dl, MVT::f64,
                                              MVT::i1, TmpF3, TmpF4), 0);

    TmpPR = TmpF5.getValue(1);
    Chain = TmpF5.getValue(2);

    SDValue minusB;
    if(isModulus) { // for remainders, it'll be handy to have
        // copies of -input_b
        minusB = SDValue(CurDAG->getTargetNode(IA64::SUB, dl, MVT::i64,
                                               CurDAG->getRegister(IA64::r0, MVT::i64), Tmp2), 0);
        Chain = minusB.getValue(1);
    }

    SDValue TmpE0, TmpY1, TmpE1, TmpY2;

    SDValue OpsE0[] = { TmpF4, TmpF5, F1, TmpPR };
    TmpE0 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
                                          OpsE0, 4), 0);
    Chain = TmpE0.getValue(1);
    SDValue OpsY1[] = { TmpF5, TmpE0, TmpF5, TmpPR };
    TmpY1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                          OpsY1, 4), 0);
    Chain = TmpY1.getValue(1);
    SDValue OpsE1[] = { TmpE0, TmpE0, F0, TmpPR };
    TmpE1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                          OpsE1, 4), 0);
    Chain = TmpE1.getValue(1);
    SDValue OpsY2[] = { TmpY1, TmpE1, TmpY1, TmpPR };
    TmpY2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                          OpsY2, 4), 0);
    Chain = TmpY2.getValue(1);

    if(isFP) { // if this is an FP divide, we finish up here and exit early
        if(isModulus)
            assert(0 && "Sorry, try another FORTRAN compiler.");

        SDValue TmpE2, TmpY3, TmpQ0, TmpR0;

        SDValue OpsE2[] = { TmpE1, TmpE1, F0, TmpPR };
        TmpE2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                              OpsE2, 4), 0);
        Chain = TmpE2.getValue(1);
        SDValue OpsY3[] = { TmpY2, TmpE2, TmpY2, TmpPR };
        TmpY3 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                              OpsY3, 4), 0);
        Chain = TmpY3.getValue(1);
        SDValue OpsQ0[] = { Tmp1, TmpY3, F0, TmpPR };
        TmpQ0 =
            SDValue(CurDAG->getTargetNode(IA64::CFMADS1, dl,  // double prec!
                                          MVT::f64, OpsQ0, 4), 0);
        Chain = TmpQ0.getValue(1);
        SDValue OpsR0[] = { Tmp2, TmpQ0, Tmp1, TmpPR };
        TmpR0 =
            SDValue(CurDAG->getTargetNode(IA64::CFNMADS1, dl, // double prec!
                                          MVT::f64, OpsR0, 4), 0);
        Chain = TmpR0.getValue(1);

// we want Result to have the same target register as the frcpa, so
// we two-address hack it. See the comment "for this to work..." on
// page 48 of Intel application note #245415
        SDValue Ops[] = { TmpF5, TmpY3, TmpR0, TmpQ0, TmpPR };
        Result = CurDAG->getTargetNode(IA64::TCFMADS0, dl, // d.p. s0 rndg!
                                       MVT::f64, Ops, 5);
        Chain = SDValue(Result, 1);
        return Result; // XXX: early exit!
    } else { // this is *not* an FP divide, so there's a bit left to do:

        SDValue TmpQ2, TmpR2, TmpQ3, TmpQ;

        SDValue OpsQ2[] = { TmpF3, TmpY2, F0, TmpPR };
        TmpQ2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
                                              OpsQ2, 4), 0);
        Chain = TmpQ2.getValue(1);
        SDValue OpsR2[] = { TmpF4, TmpQ2, TmpF3, TmpPR };
        TmpR2 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
                                              OpsR2, 4), 0);
        Chain = TmpR2.getValue(1);

// we want TmpQ3 to have the same target register as the frcpa? maybe we
// should two-address hack it. See the comment "for this to work..." on page
// 48 of Intel application note #245415
        SDValue OpsQ3[] = { TmpF5, TmpR2, TmpY2, TmpQ2, TmpPR };
        TmpQ3 = SDValue(CurDAG->getTargetNode(IA64::TCFMAS1, dl, MVT::f64,
                                              OpsQ3, 5), 0);
        Chain = TmpQ3.getValue(1);

        // STORY: without these two-address instructions (TCFMAS1 and TCFMADS0)
        // the FPSWA won't be able to help out in the case of large/tiny
        // arguments. Other fun bugs may also appear, e.g. 0/x = x, not 0.

        if(isSigned)
            TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXTRUNCS1, dl,
                                                 MVT::f64, TmpQ3), 0);
        else
            TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXUTRUNCS1, dl,
                                                 MVT::f64, TmpQ3), 0);

        Chain = TmpQ.getValue(1);

        if(isModulus) {
            SDValue FPminusB =
                SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, minusB),
                        0);
            Chain = FPminusB.getValue(1);
            SDValue Remainder =
                SDValue(CurDAG->getTargetNode(IA64::XMAL, dl, MVT::f64,
                                              TmpQ, FPminusB, TmpF1), 0);
            Chain = Remainder.getValue(1);
            Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, Remainder);
            Chain = SDValue(Result, 1);
        } else { // just an integer divide
            Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, TmpQ);
            Chain = SDValue(Result, 1);
        }

        return Result;
    } // wasn't an FP divide
}
コード例 #8
0
SDNode *XCoreDAGToDAGISel::Select(SDValue Op) {
  SDNode *N = Op.getNode();
  DebugLoc dl = N->getDebugLoc();
  EVT NVT = N->getValueType(0);
  if (NVT == MVT::i32) {
    switch (N->getOpcode()) {
      default: break;
      case ISD::Constant: {
        if (Predicate_immMskBitp(N)) {
          SDValue MskSize = Transform_msksize_xform(N);
          return CurDAG->getTargetNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize);
        }
        else if (! Predicate_immU16(N)) {
          unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
          SDValue CPIdx =
            CurDAG->getTargetConstantPool(ConstantInt::get(
                                  Type::getInt32Ty(*CurDAG->getContext()), Val),
                                          TLI.getPointerTy());
          return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32, 
                                       MVT::Other, CPIdx, 
                                       CurDAG->getEntryNode());
        }
        break;
      }
      case ISD::SMUL_LOHI: {
        // FIXME fold addition into the macc instruction
        if (!Subtarget.isXS1A()) {
          SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
                                  CurDAG->getTargetConstant(0, MVT::i32)), 0);
          SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
          SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl,
                                                  MVT::i32, MVT::i32, Ops, 4);
          ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
          ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
          return NULL;
        }
        break;
      }
      case ISD::UMUL_LOHI: {
        // FIXME fold addition into the macc / lmul instruction
        SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
                                  CurDAG->getTargetConstant(0, MVT::i32)), 0);
        SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
                            Zero, Zero };
        SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32,
                                                MVT::i32, Ops, 4);
        ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
        ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
        return NULL;
      }
      case XCoreISD::LADD: {
        if (!Subtarget.isXS1A()) {
          SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
                              Op.getOperand(2) };
          return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
                                       Ops, 3);
        }
        break;
      }
      case XCoreISD::LSUB: {
        if (!Subtarget.isXS1A()) {
          SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
                              Op.getOperand(2) };
          return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
                                       Ops, 3);
        }
        break;
      }
      // Other cases are autogenerated.
    }
  }
  return SelectCode(Op);
}