diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 35 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZ.h | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp | 30 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h | 5 | 
6 files changed, 80 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 6feca81dad2..77a3c51169c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5647,6 +5647,37 @@ bool SelectionDAGBuilder::visitMemCmpCall(const CallInst &I) {    return false;  } +/// visitMemChrCall -- See if we can lower a memchr call into an optimized +/// form.  If so, return true and lower it, otherwise return false and it +/// will be lowered like a normal call. +bool SelectionDAGBuilder::visitMemChrCall(const CallInst &I) { +  // Verify that the prototype makes sense.  void *memchr(void *, int, size_t) +  if (I.getNumArgOperands() != 3) +    return false; + +  const Value *Src = I.getArgOperand(0); +  const Value *Char = I.getArgOperand(1); +  const Value *Length = I.getArgOperand(2); +  if (!Src->getType()->isPointerTy() || +      !Char->getType()->isIntegerTy() || +      !Length->getType()->isIntegerTy() || +      !I.getType()->isPointerTy()) +    return false; + +  const TargetSelectionDAGInfo &TSI = DAG.getSelectionDAGInfo(); +  std::pair<SDValue, SDValue> Res = +    TSI.EmitTargetCodeForMemchr(DAG, getCurSDLoc(), DAG.getRoot(), +                                getValue(Src), getValue(Char), getValue(Length), +                                MachinePointerInfo(Src)); +  if (Res.first.getNode()) { +    setValue(&I, Res.first); +    PendingLoads.push_back(Res.second); +    return true; +  } + +  return false; +} +  /// visitStrCpyCall -- See if we can lower a strcpy or stpcpy call into an  /// optimized form.  If so, return true and lower it, otherwise return false  /// and it will be lowered like a normal call. @@ -5904,6 +5935,10 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {          if (visitMemCmpCall(I))            return;          break; +      case LibFunc::memchr: +        if (visitMemChrCall(I)) +          return; +        break;        case LibFunc::strcpy:          if (visitStrCpyCall(I, false))            return; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 1fe00e090f1..e995424527d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -724,6 +724,7 @@ private:    void visitPHI(const PHINode &I);    void visitCall(const CallInst &I);    bool visitMemCmpCall(const CallInst &I); +  bool visitMemChrCall(const CallInst &I);    bool visitStrCpyCall(const CallInst &I, bool isStpcpy);    bool visitStrCmpCall(const CallInst &I);    bool visitStrLenCall(const CallInst &I); diff --git a/llvm/lib/Target/SystemZ/SystemZ.h b/llvm/lib/Target/SystemZ/SystemZ.h index eccc2aa4d52..bb6ceac83b6 100644 --- a/llvm/lib/Target/SystemZ/SystemZ.h +++ b/llvm/lib/Target/SystemZ/SystemZ.h @@ -52,6 +52,11 @@ namespace llvm {      const unsigned CCMASK_CS_NE = CCMASK_1;      const unsigned CCMASK_CS    = CCMASK_0 | CCMASK_1; +    // Condition-code mask assignments for a completed SRST loop. +    const unsigned CCMASK_SRST_FOUND    = CCMASK_1; +    const unsigned CCMASK_SRST_NOTFOUND = CCMASK_2; +    const unsigned CCMASK_SRST          = CCMASK_1 | CCMASK_2; +      // Return true if Val fits an LLILL operand.      static inline bool isImmLL(uint64_t Val) {        return (Val & ~0x000000000000ffffULL) == 0; diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 0000485f2d0..6710f89a1a4 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2345,19 +2345,19 @@ SystemZTargetLowering::emitStringWrapper(MachineInstr *MI,    MachineBasicBlock *LoopMBB = emitBlockAfter(StartMBB);    //  StartMBB: -  //   R0W = %CharReg    //   # fall through to LoopMMB -  BuildMI(MBB, DL, TII->get(TargetOpcode::COPY), SystemZ::R0W).addReg(CharReg);    MBB->addSuccessor(LoopMBB);    //  LoopMBB:    //   %This1Reg = phi [ %Start1Reg, StartMBB ], [ %End1Reg, LoopMBB ]    //   %This2Reg = phi [ %Start2Reg, StartMBB ], [ %End2Reg, LoopMBB ] +  //   R0W = %CharReg    //   %End1Reg, %End2Reg = CLST %This1Reg, %This2Reg -- uses R0W    //   JO LoopMBB    //   # fall through to DoneMMB +  // +  // The load of R0W can be hoisted by post-RA LICM.    MBB = LoopMBB; -  MBB->addLiveIn(SystemZ::R0W);    BuildMI(MBB, DL, TII->get(SystemZ::PHI), This1Reg)      .addReg(Start1Reg).addMBB(StartMBB) @@ -2365,6 +2365,7 @@ SystemZTargetLowering::emitStringWrapper(MachineInstr *MI,    BuildMI(MBB, DL, TII->get(SystemZ::PHI), This2Reg)      .addReg(Start2Reg).addMBB(StartMBB)      .addReg(End2Reg).addMBB(LoopMBB); +  BuildMI(MBB, DL, TII->get(TargetOpcode::COPY), SystemZ::R0W).addReg(CharReg);    BuildMI(MBB, DL, TII->get(Opcode))      .addReg(End1Reg, RegState::Define).addReg(End2Reg, RegState::Define)      .addReg(This1Reg).addReg(This2Reg); diff --git a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp index 73bd4808fe8..638c3ee6f6f 100644 --- a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp @@ -159,6 +159,36 @@ EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain,  }  std::pair<SDValue, SDValue> SystemZSelectionDAGInfo:: +EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc DL, SDValue Chain, +                        SDValue Src, SDValue Char, SDValue Length, +                        MachinePointerInfo SrcPtrInfo) const { +  // Use SRST to find the character.  End is its address on success. +  EVT PtrVT = Src.getValueType(); +  SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other, MVT::Glue); +  Length = DAG.getZExtOrTrunc(Length, DL, PtrVT); +  Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32); +  Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char, +                     DAG.getConstant(255, MVT::i32)); +  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length); +  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain, +                            Limit, Src, Char); +  Chain = End.getValue(1); +  SDValue Glue = End.getValue(2); + +  // Now select between End and null, depending on whether the character +  // was found. +  SmallVector<SDValue, 5> Ops; +  Ops.push_back(End); +  Ops.push_back(DAG.getConstant(0, PtrVT)); +  Ops.push_back(DAG.getConstant(SystemZ::CCMASK_SRST, MVT::i32)); +  Ops.push_back(DAG.getConstant(SystemZ::CCMASK_SRST_FOUND, MVT::i32)); +  Ops.push_back(Glue); +  VTs = DAG.getVTList(PtrVT, MVT::Glue); +  End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, VTs, &Ops[0], Ops.size()); +  return std::make_pair(End, Chain); +} + +std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::  EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,                          SDValue Dest, SDValue Src,                          MachinePointerInfo DestPtrInfo, diff --git a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h index 26d648893ea..281d1e291dc 100644 --- a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h @@ -47,6 +47,11 @@ public:                            MachinePointerInfo Op2PtrInfo) const LLVM_OVERRIDE;    virtual std::pair<SDValue, SDValue> +  EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc DL, SDValue Chain, +                          SDValue Src, SDValue Char, SDValue Length, +                          MachinePointerInfo SrcPtrInfo) const LLVM_OVERRIDE; + +  virtual std::pair<SDValue, SDValue>    EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,                            SDValue Dest, SDValue Src,                            MachinePointerInfo DestPtrInfo,  | 

