diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 21:25:48 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 21:25:48 +0000 | 
| commit | d88c1a5a572cdb661c111098831fa526e933756f (patch) | |
| tree | 97b32c3372106ac47ded3d1a99f9c023a8530073 /contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | |
| parent | 715652a404ee99f10c09c0a5edbb5883961b8c25 (diff) | |
| parent | b915e9e0fc85ba6f398b3fab0db6a81a8913af94 (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp')
| -rw-r--r-- | contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 161 | 
1 files changed, 126 insertions, 35 deletions
diff --git a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 7bfa4074849b..529540ea4ed2 100644 --- a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -84,7 +84,10 @@ class WebAssemblyFastISel final : public FastISel {        return Base.FI;      } -    void setOffset(int64_t Offset_) { Offset = Offset_; } +    void setOffset(int64_t Offset_) { +      assert(Offset_ >= 0 && "Offsets must be non-negative"); +      Offset = Offset_; +    }      int64_t getOffset() const { return Offset; }      void setGlobalValue(const GlobalValue *G) { GV = G; }      const GlobalValue *getGlobalValue() const { return GV; } @@ -113,6 +116,13 @@ private:      case MVT::f32:      case MVT::f64:        return VT; +    case MVT::v16i8: +    case MVT::v8i16: +    case MVT::v4i32: +    case MVT::v4f32: +      if (Subtarget->hasSIMD128()) +        return VT; +      break;      default:        break;      } @@ -229,12 +239,15 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {    case Instruction::GetElementPtr: {      Address SavedAddr = Addr;      uint64_t TmpOffset = Addr.getOffset(); +    // Non-inbounds geps can wrap; wasm's offsets can't. +    if (!cast<GEPOperator>(U)->isInBounds()) +      goto unsupported_gep;      // Iterate through the GEP folding the constants into offsets where      // we can.      for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);           GTI != E; ++GTI) {        const Value *Op = GTI.getOperand(); -      if (StructType *STy = dyn_cast<StructType>(*GTI)) { +      if (StructType *STy = GTI.getStructTypeOrNull()) {          const StructLayout *SL = DL.getStructLayout(STy);          unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();          TmpOffset += SL->getElementOffset(Idx); @@ -265,10 +278,13 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {          }        }      } -    // Try to grab the base operand now. -    Addr.setOffset(TmpOffset); -    if (computeAddress(U->getOperand(0), Addr)) -      return true; +    // Don't fold in negative offsets. +    if (int64_t(TmpOffset) >= 0) { +      // Try to grab the base operand now. +      Addr.setOffset(TmpOffset); +      if (computeAddress(U->getOperand(0), Addr)) +        return true; +    }      // We failed, restore everything and try the other options.      Addr = SavedAddr;    unsupported_gep: @@ -294,8 +310,11 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {        std::swap(LHS, RHS);      if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { -      Addr.setOffset(Addr.getOffset() + CI->getSExtValue()); -      return computeAddress(LHS, Addr); +      uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue(); +      if (int64_t(TmpOffset) >= 0) { +        Addr.setOffset(TmpOffset); +        return computeAddress(LHS, Addr); +      }      }      Address Backup = Addr; @@ -311,8 +330,11 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {      const Value *RHS = U->getOperand(1);      if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { -      Addr.setOffset(Addr.getOffset() - CI->getSExtValue()); -      return computeAddress(LHS, Addr); +      int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue(); +      if (TmpOffset >= 0) { +        Addr.setOffset(TmpOffset); +        return computeAddress(LHS, Addr); +      }      }      break;    } @@ -341,6 +363,10 @@ void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {  void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,                                                 const MachineInstrBuilder &MIB,                                                 MachineMemOperand *MMO) { +  // Set the alignment operand (this is rewritten in SetP2AlignOperands). +  // TODO: Disable SetP2AlignOperands for FastISel and just do it here. +  MIB.addImm(0); +    if (const GlobalValue *GV = Addr.getGlobalValue())      MIB.addGlobalAddress(GV, Addr.getOffset());    else @@ -351,10 +377,6 @@ void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,    else      MIB.addFrameIndex(Addr.getFI()); -  // Set the alignment operand (this is rewritten in SetP2AlignOperands). -  // TODO: Disable SetP2AlignOperands for FastISel and just do it here. -  MIB.addImm(0); -    MIB.addMemOperand(MMO);  } @@ -381,6 +403,9 @@ unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {  unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,                                                MVT::SimpleValueType From) { +  if (Reg == 0) +    return 0; +    switch (From) {    case MVT::i1:      // If the value is naturally an i1, we don't need to mask it. @@ -415,6 +440,9 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,  unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,                                                MVT::SimpleValueType From) { +  if (Reg == 0) +    return 0; +    switch (From) {    case MVT::i1:    case MVT::i8: @@ -529,8 +557,8 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {                                           &WebAssembly::I64RegClass :                                           &WebAssembly::I32RegClass);      unsigned Opc = Subtarget->hasAddr64() ? -                   WebAssembly::COPY_LOCAL_I64 : -                   WebAssembly::COPY_LOCAL_I32; +                   WebAssembly::COPY_I64 : +                   WebAssembly::COPY_I32;      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)          .addFrameIndex(SI->second);      return ResultReg; @@ -575,7 +603,9 @@ bool WebAssemblyFastISel::fastLowerArguments() {        return false;      Type *ArgTy = Arg.getType(); -    if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) +    if (ArgTy->isStructTy() || ArgTy->isArrayTy()) +      return false; +    if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())        return false;      unsigned Opc; @@ -600,6 +630,22 @@ bool WebAssemblyFastISel::fastLowerArguments() {        Opc = WebAssembly::ARGUMENT_F64;        RC = &WebAssembly::F64RegClass;        break; +    case MVT::v16i8: +      Opc = WebAssembly::ARGUMENT_v16i8; +      RC = &WebAssembly::V128RegClass; +      break; +    case MVT::v8i16: +      Opc = WebAssembly::ARGUMENT_v8i16; +      RC = &WebAssembly::V128RegClass; +      break; +    case MVT::v4i32: +      Opc = WebAssembly::ARGUMENT_v4i32; +      RC = &WebAssembly::V128RegClass; +      break; +    case MVT::v4f32: +      Opc = WebAssembly::ARGUMENT_v4f32; +      RC = &WebAssembly::V128RegClass; +      break;      default:        return false;      } @@ -637,29 +683,52 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {    bool IsVoid = FuncTy->getReturnType()->isVoidTy();    unsigned ResultReg;    if (IsVoid) { -    Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::CALL_INDIRECT_VOID; +    Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;    } else { +    if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy()) +      return false; +      MVT::SimpleValueType RetTy = getSimpleType(Call->getType());      switch (RetTy) {      case MVT::i1:      case MVT::i8:      case MVT::i16:      case MVT::i32: -      Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::CALL_INDIRECT_I32; +      Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;        ResultReg = createResultReg(&WebAssembly::I32RegClass);        break;      case MVT::i64: -      Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::CALL_INDIRECT_I64; +      Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;        ResultReg = createResultReg(&WebAssembly::I64RegClass);        break;      case MVT::f32: -      Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::CALL_INDIRECT_F32; +      Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;        ResultReg = createResultReg(&WebAssembly::F32RegClass);        break;      case MVT::f64: -      Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::CALL_INDIRECT_F64; +      Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;        ResultReg = createResultReg(&WebAssembly::F64RegClass);        break; +    case MVT::v16i8: +      Opc = +          IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8; +      ResultReg = createResultReg(&WebAssembly::V128RegClass); +      break; +    case MVT::v8i16: +      Opc = +          IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16; +      ResultReg = createResultReg(&WebAssembly::V128RegClass); +      break; +    case MVT::v4i32: +      Opc = +          IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32; +      ResultReg = createResultReg(&WebAssembly::V128RegClass); +      break; +    case MVT::v4f32: +      Opc = +          IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32; +      ResultReg = createResultReg(&WebAssembly::V128RegClass); +      break;      default:        return false;      } @@ -972,6 +1041,8 @@ bool WebAssemblyFastISel::selectLoad(const Instruction *I) {    const LoadInst *Load = cast<LoadInst>(I);    if (Load->isAtomic())      return false; +  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy()) +    return false;    Address Addr;    if (!computeAddress(Load->getPointerOperand(), Addr)) @@ -1027,40 +1098,36 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {    const StoreInst *Store = cast<StoreInst>(I);    if (Store->isAtomic())      return false; +  if (!Subtarget->hasSIMD128() && +      Store->getValueOperand()->getType()->isVectorTy()) +    return false;    Address Addr;    if (!computeAddress(Store->getPointerOperand(), Addr))      return false;    unsigned Opc; -  const TargetRegisterClass *RC;    bool VTIsi1 = false;    switch (getSimpleType(Store->getValueOperand()->getType())) {    case MVT::i1:      VTIsi1 = true;    case MVT::i8:      Opc = WebAssembly::STORE8_I32; -    RC = &WebAssembly::I32RegClass;      break;    case MVT::i16:      Opc = WebAssembly::STORE16_I32; -    RC = &WebAssembly::I32RegClass;      break;    case MVT::i32:      Opc = WebAssembly::STORE_I32; -    RC = &WebAssembly::I32RegClass;      break;    case MVT::i64:      Opc = WebAssembly::STORE_I64; -    RC = &WebAssembly::I64RegClass;      break;    case MVT::f32:      Opc = WebAssembly::STORE_F32; -    RC = &WebAssembly::F32RegClass;      break;    case MVT::f64:      Opc = WebAssembly::STORE_F64; -    RC = &WebAssembly::F64RegClass;      break;    default: return false;    } @@ -1068,12 +1135,12 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {    materializeLoadStoreOperands(Addr);    unsigned ValueReg = getRegForValue(Store->getValueOperand()); +  if (ValueReg == 0) +    return false;    if (VTIsi1)      ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); -  unsigned ResultReg = createResultReg(RC); -  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), -                     ResultReg); +  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));    addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); @@ -1094,6 +1161,8 @@ bool WebAssemblyFastISel::selectBr(const Instruction *I) {    bool Not;    unsigned CondReg = getRegForI1Value(Br->getCondition(), Not); +  if (CondReg == 0) +    return false;    unsigned Opc = WebAssembly::BR_IF;    if (Not) @@ -1102,7 +1171,7 @@ bool WebAssemblyFastISel::selectBr(const Instruction *I) {    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))        .addMBB(TBB)        .addReg(CondReg); -   +    finishCondBranch(Br->getParent(), TBB, FBB);    return true;  } @@ -1120,6 +1189,9 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {    }    Value *RV = Ret->getOperand(0); +  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy()) +    return false; +    unsigned Opc;    switch (getSimpleType(RV->getType())) {    case MVT::i1: case MVT::i8: @@ -1129,8 +1201,24 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {    case MVT::i64:      Opc = WebAssembly::RETURN_I64;      break; -  case MVT::f32: Opc = WebAssembly::RETURN_F32; break; -  case MVT::f64: Opc = WebAssembly::RETURN_F64; break; +  case MVT::f32: +    Opc = WebAssembly::RETURN_F32; +    break; +  case MVT::f64: +    Opc = WebAssembly::RETURN_F64; +    break; +  case MVT::v16i8: +    Opc = WebAssembly::RETURN_v16i8; +    break; +  case MVT::v8i16: +    Opc = WebAssembly::RETURN_v8i16; +    break; +  case MVT::v4i32: +    Opc = WebAssembly::RETURN_v4i32; +    break; +  case MVT::v4f32: +    Opc = WebAssembly::RETURN_v4f32; +    break;    default: return false;    } @@ -1142,6 +1230,9 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {    else      Reg = getRegForValue(RV); +  if (Reg == 0) +    return false; +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);    return true;  }  | 
