[llvm] r219703 - Finish getting Mips fast-isel to match up with AArch64 fast-isel

Reed Kotler rkotler at mips.com
Tue Oct 14 11:27:58 PDT 2014


Author: rkotler
Date: Tue Oct 14 13:27:58 2014
New Revision: 219703

URL: http://llvm.org/viewvc/llvm-project?rev=219703&view=rev
Log:
Finish getting Mips fast-isel to match up with AArch64 fast-isel

Summary:
In order to facilitate use of common code, checking by reviewers of other fast-isel ports, and hopefully to eventually move most of Mips and other fast-isel ports into target independent code, I've tried to get the two implementations to line up.

There is no functional code change. Just methods moved in the file to be in the same order as in AArch64.

Test Plan: No functional change.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits, aemerson, rfuhler

Differential Revision: http://reviews.llvm.org/D5692

Modified:
    llvm/trunk/lib/Target/Mips/MipsFastISel.cpp

Modified: llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsFastISel.cpp?rev=219703&r1=219702&r2=219703&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsFastISel.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsFastISel.cpp Tue Oct 14 13:27:58 2014
@@ -166,6 +166,124 @@ public:
 };
 } // end anonymous namespace.
 
+unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) {
+  if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
+    return 0;
+  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
+  const ConstantInt *CI = cast<ConstantInt>(C);
+  int64_t Imm;
+  if ((VT != MVT::i1) && CI->isNegative())
+    Imm = CI->getSExtValue();
+  else
+    Imm = CI->getZExtValue();
+  return materialize32BitInt(Imm, RC);
+}
+
+unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
+                                           const TargetRegisterClass *RC) {
+  unsigned ResultReg = createResultReg(RC);
+
+  if (isInt<16>(Imm)) {
+    unsigned Opc = Mips::ADDiu;
+    emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
+    return ResultReg;
+  } else if (isUInt<16>(Imm)) {
+    emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
+    return ResultReg;
+  }
+  unsigned Lo = Imm & 0xFFFF;
+  unsigned Hi = (Imm >> 16) & 0xFFFF;
+  if (Lo) {
+    // Both Lo and Hi have nonzero bits.
+    unsigned TmpReg = createResultReg(RC);
+    emitInst(Mips::LUi, TmpReg).addImm(Hi);
+    emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
+  } else {
+    emitInst(Mips::LUi, ResultReg).addImm(Hi);
+  }
+  return ResultReg;
+}
+
+unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
+  if (UnsupportedFPMode)
+    return 0;
+  int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
+  if (VT == MVT::f32) {
+    const TargetRegisterClass *RC = &Mips::FGR32RegClass;
+    unsigned DestReg = createResultReg(RC);
+    unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass);
+    emitInst(Mips::MTC1, DestReg).addReg(TempReg);
+    return DestReg;
+  } else if (VT == MVT::f64) {
+    const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
+    unsigned DestReg = createResultReg(RC);
+    unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
+    unsigned TempReg2 =
+        materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
+    emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
+    return DestReg;
+  }
+  return 0;
+}
+
+unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) {
+  // For now 32-bit only.
+  if (VT != MVT::i32)
+    return 0;
+  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
+  unsigned DestReg = createResultReg(RC);
+  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
+  bool IsThreadLocal = GVar && GVar->isThreadLocal();
+  // TLS not supported at this time.
+  if (IsThreadLocal)
+    return 0;
+  emitInst(Mips::LW, DestReg)
+      .addReg(MFI->getGlobalBaseReg())
+      .addGlobalAddress(GV, 0, MipsII::MO_GOT);
+  if ((GV->hasInternalLinkage() ||
+       (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
+    unsigned TempReg = createResultReg(RC);
+    emitInst(Mips::ADDiu, TempReg)
+        .addReg(DestReg)
+        .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
+    DestReg = TempReg;
+  }
+  return DestReg;
+}
+
+// Materialize a constant into a register, and return the register
+// number (or zero if we failed to handle it).
+unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
+  EVT CEVT = TLI.getValueType(C->getType(), true);
+
+  // Only handle simple types.
+  if (!CEVT.isSimple())
+    return 0;
+  MVT VT = CEVT.getSimpleVT();
+
+  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
+    return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
+  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+    return materializeGV(GV, VT);
+  else if (isa<ConstantInt>(C))
+    return materializeInt(C, VT);
+
+  return 0;
+}
+
+bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
+  // This construct looks a big awkward but it is how other ports handle this
+  // and as this function is more fully completed, these cases which
+  // return false will have additional code in them.
+  //
+  if (isa<Instruction>(Obj))
+    return false;
+  else if (isa<ConstantExpr>(Obj))
+    return false;
+  Addr.setReg(getRegForValue(Obj));
+  return Addr.getReg() != 0;
+}
+
 bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
   EVT evt = TLI.getValueType(Ty, true);
   // Only handle simple types.
@@ -188,229 +306,207 @@ bool MipsFastISel::isLoadTypeLegal(Type
     return true;
   return false;
 }
-
-bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
-  // This construct looks a big awkward but it is how other ports handle this
-  // and as this function is more fully completed, these cases which
-  // return false will have additional code in them.
-  //
-  if (isa<Instruction>(Obj))
+// Because of how EmitCmp is called with fast-isel, you can
+// end up with redundant "andi" instructions after the sequences emitted below.
+// We should try and solve this issue in the future.
+//
+bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
+  const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1);
+  bool IsUnsigned = CI->isUnsigned();
+  unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
+  if (LeftReg == 0)
     return false;
-  else if (isa<ConstantExpr>(Obj))
+  unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
+  if (RightReg == 0)
     return false;
-  Addr.setReg(getRegForValue(Obj));
-  return Addr.getReg() != 0;
-}
+  CmpInst::Predicate P = CI->getPredicate();
 
-unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
-                                                           bool IsUnsigned) {
-  unsigned VReg = getRegForValue(V);
-  if (VReg == 0)
-    return 0;
-  MVT VMVT = TLI.getValueType(V->getType(), true).getSimpleVT();
-  if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) {
+  switch (P) {
+  default:
+    return false;
+  case CmpInst::ICMP_EQ: {
     unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned))
-      return 0;
-    VReg = TempReg;
+    emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
+    emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
+    break;
   }
-  return VReg;
-}
-
-bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
-                            unsigned Alignment) {
-  //
-  // more cases will be handled here in following patches.
-  //
-  unsigned Opc;
-  switch (VT.SimpleTy) {
-  case MVT::i32: {
-    ResultReg = createResultReg(&Mips::GPR32RegClass);
-    Opc = Mips::LW;
+  case CmpInst::ICMP_NE: {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
+    emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
     break;
   }
-  case MVT::i16: {
-    ResultReg = createResultReg(&Mips::GPR32RegClass);
-    Opc = Mips::LHu;
+  case CmpInst::ICMP_UGT: {
+    emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
     break;
   }
-  case MVT::i8: {
-    ResultReg = createResultReg(&Mips::GPR32RegClass);
-    Opc = Mips::LBu;
+  case CmpInst::ICMP_ULT: {
+    emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
     break;
   }
-  case MVT::f32: {
-    if (UnsupportedFPMode)
-      return false;
-    ResultReg = createResultReg(&Mips::FGR32RegClass);
-    Opc = Mips::LWC1;
+  case CmpInst::ICMP_UGE: {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
+    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
     break;
   }
-  case MVT::f64: {
+  case CmpInst::ICMP_ULE: {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
+    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
+    break;
+  }
+  case CmpInst::ICMP_SGT: {
+    emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
+    break;
+  }
+  case CmpInst::ICMP_SLT: {
+    emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
+    break;
+  }
+  case CmpInst::ICMP_SGE: {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
+    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
+    break;
+  }
+  case CmpInst::ICMP_SLE: {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
+    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
+    break;
+  }
+  case CmpInst::FCMP_OEQ:
+  case CmpInst::FCMP_UNE:
+  case CmpInst::FCMP_OLT:
+  case CmpInst::FCMP_OLE:
+  case CmpInst::FCMP_OGT:
+  case CmpInst::FCMP_OGE: {
     if (UnsupportedFPMode)
       return false;
-    ResultReg = createResultReg(&Mips::AFGR64RegClass);
-    Opc = Mips::LDC1;
+    bool IsFloat = Left->getType()->isFloatTy();
+    bool IsDouble = Left->getType()->isDoubleTy();
+    if (!IsFloat && !IsDouble)
+      return false;
+    unsigned Opc, CondMovOpc;
+    switch (P) {
+    case CmpInst::FCMP_OEQ:
+      Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
+      CondMovOpc = Mips::MOVT_I;
+      break;
+    case CmpInst::FCMP_UNE:
+      Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
+      CondMovOpc = Mips::MOVF_I;
+      break;
+    case CmpInst::FCMP_OLT:
+      Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
+      CondMovOpc = Mips::MOVT_I;
+      break;
+    case CmpInst::FCMP_OLE:
+      Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
+      CondMovOpc = Mips::MOVT_I;
+      break;
+    case CmpInst::FCMP_OGT:
+      Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
+      CondMovOpc = Mips::MOVF_I;
+      break;
+    case CmpInst::FCMP_OGE:
+      Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
+      CondMovOpc = Mips::MOVF_I;
+      break;
+    default:
+      llvm_unreachable("Only switching of a subset of CCs.");
+    }
+    unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
+    unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
+    emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
+    emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
+    emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
+        Mips::FCC0, RegState::ImplicitDefine);
+    MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg)
+                                 .addReg(RegWithOne)
+                                 .addReg(Mips::FCC0)
+                                 .addReg(RegWithZero, RegState::Implicit);
+    MI->tieOperands(0, 3);
     break;
   }
-  default:
-    return false;
   }
-  emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
   return true;
 }
-
-// Materialize a constant into a register, and return the register
-// number (or zero if we failed to handle it).
-unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
-  EVT CEVT = TLI.getValueType(C->getType(), true);
-
-  // Only handle simple types.
-  if (!CEVT.isSimple())
-    return 0;
-  MVT VT = CEVT.getSimpleVT();
-
-  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
-    return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
-  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
-    return materializeGV(GV, VT);
-  else if (isa<ConstantInt>(C))
-    return materializeInt(C, VT);
-
-  return 0;
-}
-
-bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
-                             unsigned Alignment) {
+bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
+                            unsigned Alignment) {
   //
   // more cases will be handled here in following patches.
   //
   unsigned Opc;
   switch (VT.SimpleTy) {
-  case MVT::i8:
-    Opc = Mips::SB;
-    break;
-  case MVT::i16:
-    Opc = Mips::SH;
-    break;
-  case MVT::i32:
-    Opc = Mips::SW;
-    break;
-  case MVT::f32:
-    if (UnsupportedFPMode)
-      return false;
-    Opc = Mips::SWC1;
-    break;
-  case MVT::f64:
-    if (UnsupportedFPMode)
-      return false;
-    Opc = Mips::SDC1;
+  case MVT::i32: {
+    ResultReg = createResultReg(&Mips::GPR32RegClass);
+    Opc = Mips::LW;
     break;
-  default:
-    return false;
   }
-  emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
-  return true;
-}
-
-bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
-                                   unsigned DestReg) {
-  unsigned ShiftAmt;
-  switch (SrcVT.SimpleTy) {
-  default:
-    return false;
-  case MVT::i8:
-    ShiftAmt = 24;
+  case MVT::i16: {
+    ResultReg = createResultReg(&Mips::GPR32RegClass);
+    Opc = Mips::LHu;
     break;
-  case MVT::i16:
-    ShiftAmt = 16;
+  }
+  case MVT::i8: {
+    ResultReg = createResultReg(&Mips::GPR32RegClass);
+    Opc = Mips::LBu;
     break;
   }
-  unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-  emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
-  emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
-  return true;
-}
-
-bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
-                                   unsigned DestReg) {
-  switch (SrcVT.SimpleTy) {
-  default:
-    return false;
-  case MVT::i8:
-    emitInst(Mips::SEB, DestReg).addReg(SrcReg);
+  case MVT::f32: {
+    if (UnsupportedFPMode)
+      return false;
+    ResultReg = createResultReg(&Mips::FGR32RegClass);
+    Opc = Mips::LWC1;
     break;
-  case MVT::i16:
-    emitInst(Mips::SEH, DestReg).addReg(SrcReg);
+  }
+  case MVT::f64: {
+    if (UnsupportedFPMode)
+      return false;
+    ResultReg = createResultReg(&Mips::AFGR64RegClass);
+    Opc = Mips::LDC1;
     break;
   }
-  return true;
-}
-
-bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
-                              unsigned DestReg, bool IsZExt) {
-  if (IsZExt)
-    return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
-  return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
-}
-
-bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
-                               unsigned DestReg) {
-  if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
-    return false;
-  if (Subtarget->hasMips32r2())
-    return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
-  return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
-}
-
-bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
-                               unsigned DestReg) {
-  switch (SrcVT.SimpleTy) {
   default:
     return false;
-  case MVT::i1:
-    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
-    break;
-  case MVT::i8:
-    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
-    break;
-  case MVT::i16:
-    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
-    break;
   }
+  emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
   return true;
 }
 
-//
-// This can cause a redundant sltiu to be generated.
-// FIXME: try and eliminate this in a future patch.
-//
-bool MipsFastISel::selectBranch(const Instruction *I) {
-  const BranchInst *BI = cast<BranchInst>(I);
-  MachineBasicBlock *BrBB = FuncInfo.MBB;
+bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
+                             unsigned Alignment) {
   //
-  // TBB is the basic block for the case where the comparison is true.
-  // FBB is the basic block for the case where the comparison is false.
-  // if (cond) goto TBB
-  // goto FBB
-  // TBB:
+  // more cases will be handled here in following patches.
   //
-  MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
-  MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
-  BI->getCondition();
-  // For now, just try the simplest case where it's fed by a compare.
-  if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
-    unsigned CondReg = createResultReg(&Mips::GPR32RegClass);
-    if (!emitCmp(CondReg, CI))
+  unsigned Opc;
+  switch (VT.SimpleTy) {
+  case MVT::i8:
+    Opc = Mips::SB;
+    break;
+  case MVT::i16:
+    Opc = Mips::SH;
+    break;
+  case MVT::i32:
+    Opc = Mips::SW;
+    break;
+  case MVT::f32:
+    if (UnsupportedFPMode)
       return false;
-    BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
-        .addReg(CondReg)
-        .addMBB(TBB);
-    fastEmitBranch(FBB, DbgLoc);
-    FuncInfo.MBB->addSuccessor(TBB);
-    return true;
+    Opc = Mips::SWC1;
+    break;
+  case MVT::f64:
+    if (UnsupportedFPMode)
+      return false;
+    Opc = Mips::SDC1;
+    break;
+  default:
+    return false;
   }
-  return false;
+  emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
+  return true;
 }
 
 bool MipsFastISel::selectLoad(const Instruction *I) {
@@ -463,15 +559,44 @@ bool MipsFastISel::selectStore(const Ins
   return true;
 }
 
-bool MipsFastISel::selectRet(const Instruction *I) {
-  const ReturnInst *Ret = cast<ReturnInst>(I);
+//
+// This can cause a redundant sltiu to be generated.
+// FIXME: try and eliminate this in a future patch.
+//
+bool MipsFastISel::selectBranch(const Instruction *I) {
+  const BranchInst *BI = cast<BranchInst>(I);
+  MachineBasicBlock *BrBB = FuncInfo.MBB;
+  //
+  // TBB is the basic block for the case where the comparison is true.
+  // FBB is the basic block for the case where the comparison is false.
+  // if (cond) goto TBB
+  // goto FBB
+  // TBB:
+  //
+  MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
+  MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
+  BI->getCondition();
+  // For now, just try the simplest case where it's fed by a compare.
+  if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
+    unsigned CondReg = createResultReg(&Mips::GPR32RegClass);
+    if (!emitCmp(CondReg, CI))
+      return false;
+    BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
+        .addReg(CondReg)
+        .addMBB(TBB);
+    fastEmitBranch(FBB, DbgLoc);
+    FuncInfo.MBB->addSuccessor(TBB);
+    return true;
+  }
+  return false;
+}
 
-  if (!FuncInfo.CanLowerReturn)
-    return false;
-  if (Ret->getNumOperands() > 0) {
+bool MipsFastISel::selectCmp(const Instruction *I) {
+  const CmpInst *CI = cast<CmpInst>(I);
+  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
+  if (!emitCmp(ResultReg, CI))
     return false;
-  }
-  emitInst(Mips::RetRA);
+  updateValueMap(I, ResultReg);
   return true;
 }
 
@@ -522,58 +647,6 @@ bool MipsFastISel::selectFPTrunc(const I
   return true;
 }
 
-bool MipsFastISel::selectIntExt(const Instruction *I) {
-  Type *DestTy = I->getType();
-  Value *Src = I->getOperand(0);
-  Type *SrcTy = Src->getType();
-
-  bool isZExt = isa<ZExtInst>(I);
-  unsigned SrcReg = getRegForValue(Src);
-  if (!SrcReg)
-    return false;
-
-  EVT SrcEVT, DestEVT;
-  SrcEVT = TLI.getValueType(SrcTy, true);
-  DestEVT = TLI.getValueType(DestTy, true);
-  if (!SrcEVT.isSimple())
-    return false;
-  if (!DestEVT.isSimple())
-    return false;
-
-  MVT SrcVT = SrcEVT.getSimpleVT();
-  MVT DestVT = DestEVT.getSimpleVT();
-  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
-
-  if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
-    return false;
-  updateValueMap(I, ResultReg);
-  return true;
-}
-
-bool MipsFastISel::selectTrunc(const Instruction *I) {
-  // The high bits for a type smaller than the register size are assumed to be
-  // undefined.
-  Value *Op = I->getOperand(0);
-
-  EVT SrcVT, DestVT;
-  SrcVT = TLI.getValueType(Op->getType(), true);
-  DestVT = TLI.getValueType(I->getType(), true);
-
-  if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
-    return false;
-  if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
-    return false;
-
-  unsigned SrcReg = getRegForValue(Op);
-  if (!SrcReg)
-    return false;
-
-  // Because the high bits are undefined, a truncate doesn't generate
-  // any code.
-  updateValueMap(I, SrcReg);
-  return true;
-}
-
 // Attempt to fast-select a floating-point-to-integer conversion.
 bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) {
   if (UnsupportedFPMode)
@@ -621,143 +694,134 @@ bool MipsFastISel::selectFPToInt(const I
   return true;
 }
 //
-// Because of how EmitCmp is called with fast-isel, you can
-// end up with redundant "andi" instructions after the sequences emitted below.
-// We should try and solve this issue in the future.
-//
-bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
-  const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1);
-  bool IsUnsigned = CI->isUnsigned();
-  unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
-  if (LeftReg == 0)
+bool MipsFastISel::selectRet(const Instruction *I) {
+  const ReturnInst *Ret = cast<ReturnInst>(I);
+
+  if (!FuncInfo.CanLowerReturn)
     return false;
-  unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
-  if (RightReg == 0)
+  if (Ret->getNumOperands() > 0) {
     return false;
-  CmpInst::Predicate P = CI->getPredicate();
+  }
+  emitInst(Mips::RetRA);
+  return true;
+}
+
+bool MipsFastISel::selectTrunc(const Instruction *I) {
+  // The high bits for a type smaller than the register size are assumed to be
+  // undefined.
+  Value *Op = I->getOperand(0);
+
+  EVT SrcVT, DestVT;
+  SrcVT = TLI.getValueType(Op->getType(), true);
+  DestVT = TLI.getValueType(I->getType(), true);
+
+  if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
+    return false;
+  if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
+    return false;
+
+  unsigned SrcReg = getRegForValue(Op);
+  if (!SrcReg)
+    return false;
+
+  // Because the high bits are undefined, a truncate doesn't generate
+  // any code.
+  updateValueMap(I, SrcReg);
+  return true;
+}
+bool MipsFastISel::selectIntExt(const Instruction *I) {
+  Type *DestTy = I->getType();
+  Value *Src = I->getOperand(0);
+  Type *SrcTy = Src->getType();
+
+  bool isZExt = isa<ZExtInst>(I);
+  unsigned SrcReg = getRegForValue(Src);
+  if (!SrcReg)
+    return false;
+
+  EVT SrcEVT, DestEVT;
+  SrcEVT = TLI.getValueType(SrcTy, true);
+  DestEVT = TLI.getValueType(DestTy, true);
+  if (!SrcEVT.isSimple())
+    return false;
+  if (!DestEVT.isSimple())
+    return false;
+
+  MVT SrcVT = SrcEVT.getSimpleVT();
+  MVT DestVT = DestEVT.getSimpleVT();
+  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
 
-  switch (P) {
+  if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
+    return false;
+  updateValueMap(I, ResultReg);
+  return true;
+}
+bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
+                                   unsigned DestReg) {
+  unsigned ShiftAmt;
+  switch (SrcVT.SimpleTy) {
   default:
     return false;
-  case CmpInst::ICMP_EQ: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
-    emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
-    break;
-  }
-  case CmpInst::ICMP_NE: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
-    emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
-    break;
-  }
-  case CmpInst::ICMP_UGT: {
-    emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
-    break;
-  }
-  case CmpInst::ICMP_ULT: {
-    emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
-    break;
-  }
-  case CmpInst::ICMP_UGE: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
-    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
-    break;
-  }
-  case CmpInst::ICMP_ULE: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
-    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
-    break;
-  }
-  case CmpInst::ICMP_SGT: {
-    emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
-    break;
-  }
-  case CmpInst::ICMP_SLT: {
-    emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
+  case MVT::i8:
+    ShiftAmt = 24;
     break;
-  }
-  case CmpInst::ICMP_SGE: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
-    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
+  case MVT::i16:
+    ShiftAmt = 16;
     break;
   }
-  case CmpInst::ICMP_SLE: {
-    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
-    emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
+  unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+  emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
+  emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
+  return true;
+}
+
+bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
+                                   unsigned DestReg) {
+  switch (SrcVT.SimpleTy) {
+  default:
+    return false;
+  case MVT::i8:
+    emitInst(Mips::SEB, DestReg).addReg(SrcReg);
     break;
-  }
-  case CmpInst::FCMP_OEQ:
-  case CmpInst::FCMP_UNE:
-  case CmpInst::FCMP_OLT:
-  case CmpInst::FCMP_OLE:
-  case CmpInst::FCMP_OGT:
-  case CmpInst::FCMP_OGE: {
-    if (UnsupportedFPMode)
-      return false;
-    bool IsFloat = Left->getType()->isFloatTy();
-    bool IsDouble = Left->getType()->isDoubleTy();
-    if (!IsFloat && !IsDouble)
-      return false;
-    unsigned Opc, CondMovOpc;
-    switch (P) {
-    case CmpInst::FCMP_OEQ:
-      Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
-      CondMovOpc = Mips::MOVT_I;
-      break;
-    case CmpInst::FCMP_UNE:
-      Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
-      CondMovOpc = Mips::MOVF_I;
-      break;
-    case CmpInst::FCMP_OLT:
-      Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
-      CondMovOpc = Mips::MOVT_I;
-      break;
-    case CmpInst::FCMP_OLE:
-      Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
-      CondMovOpc = Mips::MOVT_I;
-      break;
-    case CmpInst::FCMP_OGT:
-      Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
-      CondMovOpc = Mips::MOVF_I;
-      break;
-    case CmpInst::FCMP_OGE:
-      Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
-      CondMovOpc = Mips::MOVF_I;
-      break;
-    default:
-      llvm_unreachable("Only switching of a subset of CCs.");
-    }
-    unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass);
-    unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
-    emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
-    emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
-    emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
-        Mips::FCC0, RegState::ImplicitDefine);
-    MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg)
-                                 .addReg(RegWithOne)
-                                 .addReg(Mips::FCC0)
-                                 .addReg(RegWithZero, RegState::Implicit);
-    MI->tieOperands(0, 3);
+  case MVT::i16:
+    emitInst(Mips::SEH, DestReg).addReg(SrcReg);
     break;
   }
-  }
   return true;
 }
 
-bool MipsFastISel::selectCmp(const Instruction *I) {
-  const CmpInst *CI = cast<CmpInst>(I);
-  unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
-  if (!emitCmp(ResultReg, CI))
+bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
+                               unsigned DestReg) {
+  if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
     return false;
-  updateValueMap(I, ResultReg);
+  if (Subtarget->hasMips32r2())
+    return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
+  return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
+}
+
+bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
+                               unsigned DestReg) {
+  switch (SrcVT.SimpleTy) {
+  default:
+    return false;
+  case MVT::i1:
+    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(1);
+    break;
+  case MVT::i8:
+    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xff);
+    break;
+  case MVT::i16:
+    emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(0xffff);
+  }
   return true;
 }
 
+bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
+                              unsigned DestReg, bool IsZExt) {
+  if (IsZExt)
+    return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
+  return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
+}
 bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
   if (!TargetSupported)
     return false;
@@ -792,89 +856,19 @@ bool MipsFastISel::fastSelectInstruction
   return false;
 }
 
-unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
-  if (UnsupportedFPMode)
-    return 0;
-  int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
-  if (VT == MVT::f32) {
-    const TargetRegisterClass *RC = &Mips::FGR32RegClass;
-    unsigned DestReg = createResultReg(RC);
-    unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass);
-    emitInst(Mips::MTC1, DestReg).addReg(TempReg);
-    return DestReg;
-  } else if (VT == MVT::f64) {
-    const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
-    unsigned DestReg = createResultReg(RC);
-    unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
-    unsigned TempReg2 =
-        materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
-    emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
-    return DestReg;
-  }
-  return 0;
-}
-
-unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) {
-  // For now 32-bit only.
-  if (VT != MVT::i32)
-    return 0;
-  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
-  unsigned DestReg = createResultReg(RC);
-  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
-  bool IsThreadLocal = GVar && GVar->isThreadLocal();
-  // TLS not supported at this time.
-  if (IsThreadLocal)
-    return 0;
-  emitInst(Mips::LW, DestReg)
-      .addReg(MFI->getGlobalBaseReg())
-      .addGlobalAddress(GV, 0, MipsII::MO_GOT);
-  if ((GV->hasInternalLinkage() ||
-       (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
-    unsigned TempReg = createResultReg(RC);
-    emitInst(Mips::ADDiu, TempReg)
-        .addReg(DestReg)
-        .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
-    DestReg = TempReg;
-  }
-  return DestReg;
-}
-
-unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) {
-  if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
+unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
+                                                           bool IsUnsigned) {
+  unsigned VReg = getRegForValue(V);
+  if (VReg == 0)
     return 0;
-  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
-  const ConstantInt *CI = cast<ConstantInt>(C);
-  int64_t Imm;
-  if ((VT != MVT::i1) && CI->isNegative())
-    Imm = CI->getSExtValue();
-  else
-    Imm = CI->getZExtValue();
-  return materialize32BitInt(Imm, RC);
-}
-
-unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
-                                           const TargetRegisterClass *RC) {
-  unsigned ResultReg = createResultReg(RC);
-
-  if (isInt<16>(Imm)) {
-    unsigned Opc = Mips::ADDiu;
-    emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
-    return ResultReg;
-  } else if (isUInt<16>(Imm)) {
-    emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
-    return ResultReg;
-  }
-  unsigned Lo = Imm & 0xFFFF;
-  unsigned Hi = (Imm >> 16) & 0xFFFF;
-  if (Lo) {
-    // Both Lo and Hi have nonzero bits.
-    unsigned TmpReg = createResultReg(RC);
-    emitInst(Mips::LUi, TmpReg).addImm(Hi);
-    emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
-  } else {
-    emitInst(Mips::LUi, ResultReg).addImm(Hi);
+  MVT VMVT = TLI.getValueType(V->getType(), true).getSimpleVT();
+  if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) {
+    unsigned TempReg = createResultReg(&Mips::GPR32RegClass);
+    if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned))
+      return 0;
+    VReg = TempReg;
   }
-  return ResultReg;
+  return VReg;
 }
 
 namespace llvm {





More information about the llvm-commits mailing list