diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/FastISel.cpp')
| -rw-r--r-- | lib/CodeGen/SelectionDAG/FastISel.cpp | 299 | 
1 files changed, 179 insertions, 120 deletions
diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 490b857b0e9c8..3af948288daff 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -43,6 +43,7 @@  #include "llvm/GlobalVariable.h"  #include "llvm/Instructions.h"  #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h"  #include "llvm/CodeGen/FastISel.h"  #include "llvm/CodeGen/FunctionLoweringInfo.h"  #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -121,10 +122,9 @@ unsigned FastISel::getRegForValue(const Value *V) {    // only locally. This is because Instructions already have the SSA    // def-dominates-use requirement enforced.    DenseMap<const Value *, unsigned>::iterator I = FuncInfo.ValueMap.find(V); -  if (I != FuncInfo.ValueMap.end()) { -    unsigned Reg = I->second; -    return Reg; -  } +  if (I != FuncInfo.ValueMap.end()) +    return I->second; +    unsigned Reg = LocalValueMap[V];    if (Reg != 0)      return Reg; @@ -164,8 +164,12 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {      Reg =        getRegForValue(Constant::getNullValue(TD.getIntPtrType(V->getContext())));    } else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) { -    // Try to emit the constant directly. -    Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); +    if (CF->isNullValue()) { +      Reg = TargetMaterializeFloatZero(CF); +    } else { +      // Try to emit the constant directly. +      Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); +    }      if (!Reg) {        // Try to emit the constant by using an integer constant with a cast. @@ -330,23 +334,51 @@ bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) {        return false;    } +  // Check if the first operand is a constant, and handle it as "ri".  At -O0, +  // we don't have anything that canonicalizes operand order. +  if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(0))) +    if (isa<Instruction>(I) && cast<Instruction>(I)->isCommutative()) { +      unsigned Op1 = getRegForValue(I->getOperand(1)); +      if (Op1 == 0) return false; + +      bool Op1IsKill = hasTrivialKill(I->getOperand(1)); + +      unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op1, +                                        Op1IsKill, CI->getZExtValue(), +                                        VT.getSimpleVT()); +      if (ResultReg == 0) return false; + +      // We successfully emitted code for the given LLVM Instruction. +      UpdateValueMap(I, ResultReg); +      return true; +    } + +    unsigned Op0 = getRegForValue(I->getOperand(0)); -  if (Op0 == 0) -    // Unhandled operand. Halt "fast" selection and bail. +  if (Op0 == 0)   // Unhandled operand. Halt "fast" selection and bail.      return false;    bool Op0IsKill = hasTrivialKill(I->getOperand(0));    // Check if the second operand is a constant and handle it appropriately.    if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { -    unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(), -                                     ISDOpcode, Op0, Op0IsKill, -                                     CI->getZExtValue()); -    if (ResultReg != 0) { -      // We successfully emitted code for the given LLVM Instruction. -      UpdateValueMap(I, ResultReg); -      return true; +    uint64_t Imm = CI->getZExtValue(); + +    // Transform "sdiv exact X, 8" -> "sra X, 3". +    if (ISDOpcode == ISD::SDIV && isa<BinaryOperator>(I) && +        cast<BinaryOperator>(I)->isExact() && +        isPowerOf2_64(Imm)) { +      Imm = Log2_64(Imm); +      ISDOpcode = ISD::SRA;      } + +    unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0, +                                      Op0IsKill, Imm, VT.getSimpleVT()); +    if (ResultReg == 0) return false; + +    // We successfully emitted code for the given LLVM Instruction. +    UpdateValueMap(I, ResultReg); +    return true;    }    // Check if the second operand is a constant float. @@ -454,15 +486,35 @@ bool FastISel::SelectGetElementPtr(const User *I) {  }  bool FastISel::SelectCall(const User *I) { -  const Function *F = cast<CallInst>(I)->getCalledFunction(); +  const CallInst *Call = cast<CallInst>(I); + +  // Handle simple inline asms. +  if (const InlineAsm *IA = dyn_cast<InlineAsm>(Call->getArgOperand(0))) { +    // Don't attempt to handle constraints. +    if (!IA->getConstraintString().empty()) +      return false; + +    unsigned ExtraInfo = 0; +    if (IA->hasSideEffects()) +      ExtraInfo |= InlineAsm::Extra_HasSideEffects; +    if (IA->isAlignStack()) +      ExtraInfo |= InlineAsm::Extra_IsAlignStack; + +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, +            TII.get(TargetOpcode::INLINEASM)) +      .addExternalSymbol(IA->getAsmString().c_str()) +      .addImm(ExtraInfo); +    return true; +  } + +  const Function *F = Call->getCalledFunction();    if (!F) return false;    // Handle selected intrinsic function calls. -  unsigned IID = F->getIntrinsicID(); -  switch (IID) { +  switch (F->getIntrinsicID()) {    default: break;    case Intrinsic::dbg_declare: { -    const DbgDeclareInst *DI = cast<DbgDeclareInst>(I); +    const DbgDeclareInst *DI = cast<DbgDeclareInst>(Call);      if (!DIVariable(DI->getVariable()).Verify() ||          !FuncInfo.MF->getMMI().hasDebugInfo())        return true; @@ -494,7 +546,7 @@ bool FastISel::SelectCall(const User *I) {    }    case Intrinsic::dbg_value: {      // This form of DBG_VALUE is target-independent. -    const DbgValueInst *DI = cast<DbgValueInst>(I); +    const DbgValueInst *DI = cast<DbgValueInst>(Call);      const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);      const Value *V = DI->getValue();      if (!V) { @@ -523,65 +575,58 @@ bool FastISel::SelectCall(const User *I) {      return true;    }    case Intrinsic::eh_exception: { -    EVT VT = TLI.getValueType(I->getType()); -    switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { -    default: break; -    case TargetLowering::Expand: { -      assert(FuncInfo.MBB->isLandingPad() && -             "Call to eh.exception not in landing pad!"); -      unsigned Reg = TLI.getExceptionAddressRegister(); -      const TargetRegisterClass *RC = TLI.getRegClassFor(VT); -      unsigned ResultReg = createResultReg(RC); -      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), -              ResultReg).addReg(Reg); -      UpdateValueMap(I, ResultReg); -      return true; -    } -    } -    break; +    EVT VT = TLI.getValueType(Call->getType()); +    if (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)!=TargetLowering::Expand) +      break; + +    assert(FuncInfo.MBB->isLandingPad() && +           "Call to eh.exception not in landing pad!"); +    unsigned Reg = TLI.getExceptionAddressRegister(); +    const TargetRegisterClass *RC = TLI.getRegClassFor(VT); +    unsigned ResultReg = createResultReg(RC); +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), +            ResultReg).addReg(Reg); +    UpdateValueMap(Call, ResultReg); +    return true;    }    case Intrinsic::eh_selector: { -    EVT VT = TLI.getValueType(I->getType()); -    switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { -    default: break; -    case TargetLowering::Expand: { -      if (FuncInfo.MBB->isLandingPad()) -        AddCatchInfo(*cast<CallInst>(I), &FuncInfo.MF->getMMI(), FuncInfo.MBB); -      else { +    EVT VT = TLI.getValueType(Call->getType()); +    if (TLI.getOperationAction(ISD::EHSELECTION, VT) != TargetLowering::Expand) +      break; +    if (FuncInfo.MBB->isLandingPad()) +      AddCatchInfo(*Call, &FuncInfo.MF->getMMI(), FuncInfo.MBB); +    else {  #ifndef NDEBUG -        FuncInfo.CatchInfoLost.insert(cast<CallInst>(I)); +      FuncInfo.CatchInfoLost.insert(Call);  #endif -        // FIXME: Mark exception selector register as live in.  Hack for PR1508. -        unsigned Reg = TLI.getExceptionSelectorRegister(); -        if (Reg) FuncInfo.MBB->addLiveIn(Reg); -      } - +      // FIXME: Mark exception selector register as live in.  Hack for PR1508.        unsigned Reg = TLI.getExceptionSelectorRegister(); -      EVT SrcVT = TLI.getPointerTy(); -      const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); -      unsigned ResultReg = createResultReg(RC); -      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), -              ResultReg).addReg(Reg); - -      bool ResultRegIsKill = hasTrivialKill(I); - -      // Cast the register to the type of the selector. -      if (SrcVT.bitsGT(MVT::i32)) -        ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, -                               ResultReg, ResultRegIsKill); -      else if (SrcVT.bitsLT(MVT::i32)) -        ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, -                               ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill); -      if (ResultReg == 0) -        // Unhandled operand. Halt "fast" selection and bail. -        return false; +      if (Reg) FuncInfo.MBB->addLiveIn(Reg); +    } -      UpdateValueMap(I, ResultReg); +    unsigned Reg = TLI.getExceptionSelectorRegister(); +    EVT SrcVT = TLI.getPointerTy(); +    const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); +    unsigned ResultReg = createResultReg(RC); +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), +            ResultReg).addReg(Reg); + +    bool ResultRegIsKill = hasTrivialKill(Call); + +    // Cast the register to the type of the selector. +    if (SrcVT.bitsGT(MVT::i32)) +      ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, +                             ResultReg, ResultRegIsKill); +    else if (SrcVT.bitsLT(MVT::i32)) +      ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, +                             ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill); +    if (ResultReg == 0) +      // Unhandled operand. Halt "fast" selection and bail. +      return false; -      return true; -    } -    } -    break; +    UpdateValueMap(Call, ResultReg); + +    return true;    }    } @@ -966,59 +1011,33 @@ unsigned FastISel::FastEmit_rri(MVT, MVT,  unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode,                                  unsigned Op0, bool Op0IsKill,                                  uint64_t Imm, MVT ImmType) { +  // If this is a multiply by a power of two, emit this as a shift left. +  if (Opcode == ISD::MUL && isPowerOf2_64(Imm)) { +    Opcode = ISD::SHL; +    Imm = Log2_64(Imm); +  } else if (Opcode == ISD::UDIV && isPowerOf2_64(Imm)) { +    // div x, 8 -> srl x, 3 +    Opcode = ISD::SRL; +    Imm = Log2_64(Imm); +  } + +  // Horrible hack (to be removed), check to make sure shift amounts are +  // in-range. +  if ((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) && +      Imm >= VT.getSizeInBits()) +    return 0; +    // First check if immediate type is legal. If not, we can't use the ri form.    unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm);    if (ResultReg != 0)      return ResultReg;    unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm); -  if (MaterialReg == 0) -    return 0; -  return FastEmit_rr(VT, VT, Opcode, -                     Op0, Op0IsKill, -                     MaterialReg, /*Kill=*/true); -} - -/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries -/// to emit an instruction with a floating-point immediate operand using -/// FastEmit_rf. If that fails, it materializes the immediate into a register -/// and try FastEmit_rr instead. -unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode, -                                unsigned Op0, bool Op0IsKill, -                                const ConstantFP *FPImm, MVT ImmType) { -  // First check if immediate type is legal. If not, we can't use the rf form. -  unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm); -  if (ResultReg != 0) -    return ResultReg; - -  // Materialize the constant in a register. -  unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm);    if (MaterialReg == 0) { -    // If the target doesn't have a way to directly enter a floating-point -    // value into a register, use an alternate approach. -    // TODO: The current approach only supports floating-point constants -    // that can be constructed by conversion from integer values. This should -    // be replaced by code that creates a load from a constant-pool entry, -    // which will require some target-specific work. -    const APFloat &Flt = FPImm->getValueAPF(); -    EVT IntVT = TLI.getPointerTy(); - -    uint64_t x[2]; -    uint32_t IntBitWidth = IntVT.getSizeInBits(); -    bool isExact; -    (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, -                             APFloat::rmTowardZero, &isExact); -    if (!isExact) -      return 0; -    APInt IntVal(IntBitWidth, 2, x); - -    unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), -                                     ISD::Constant, IntVal.getZExtValue()); -    if (IntegerReg == 0) -      return 0; -    MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, -                             ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true); -    if (MaterialReg == 0) -      return 0; +    // This is a bit ugly/slow, but failing here means falling out of +    // fast-isel, which would be very slow. +    const IntegerType *ITy = IntegerType::get(FuncInfo.Fn->getContext(), +                                              VT.getSizeInBits()); +    MaterialReg = getRegForValue(ConstantInt::get(ITy, Imm));    }    return FastEmit_rr(VT, VT, Opcode,                       Op0, Op0IsKill, @@ -1099,6 +1118,29 @@ unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,    return ResultReg;  } +unsigned FastISel::FastEmitInst_rii(unsigned MachineInstOpcode, +                                   const TargetRegisterClass *RC, +                                   unsigned Op0, bool Op0IsKill, +                                   uint64_t Imm1, uint64_t Imm2) { +  unsigned ResultReg = createResultReg(RC); +  const TargetInstrDesc &II = TII.get(MachineInstOpcode); + +  if (II.getNumDefs() >= 1) +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) +      .addReg(Op0, Op0IsKill * RegState::Kill) +      .addImm(Imm1) +      .addImm(Imm2); +  else { +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) +      .addReg(Op0, Op0IsKill * RegState::Kill) +      .addImm(Imm1) +      .addImm(Imm2); +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), +            ResultReg).addReg(II.ImplicitDefs[0]); +  } +  return ResultReg; +} +  unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,                                     const TargetRegisterClass *RC,                                     unsigned Op0, bool Op0IsKill, @@ -1160,6 +1202,23 @@ unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode,    return ResultReg;  } +unsigned FastISel::FastEmitInst_ii(unsigned MachineInstOpcode, +                                  const TargetRegisterClass *RC, +                                  uint64_t Imm1, uint64_t Imm2) { +  unsigned ResultReg = createResultReg(RC); +  const TargetInstrDesc &II = TII.get(MachineInstOpcode); + +  if (II.getNumDefs() >= 1) +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) +      .addImm(Imm1).addImm(Imm2); +  else { +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II).addImm(Imm1).addImm(Imm2); +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), +            ResultReg).addReg(II.ImplicitDefs[0]); +  } +  return ResultReg; +} +  unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT,                                                unsigned Op0, bool Op0IsKill,                                                uint32_t Idx) { @@ -1215,7 +1274,7 @@ bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {        // Only handle legal types. Two interesting things to note here. First,        // by bailing out early, we may leave behind some dead instructions,        // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its -      // own moves. Second, this check is necessary becuase FastISel doesn't +      // own moves. Second, this check is necessary because FastISel doesn't        // use CreateRegs to create registers, so it always creates        // exactly one register for each non-void instruction.        EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);  | 
