Fix typos in comments, NFC
[oota-llvm.git] / lib / Target / AArch64 / AArch64FastISel.cpp
index aa959d19e16ce3e32abb9341b83d384e3be9ab1d..7ee8c47930a8186dd687685dfcfa6a756963ed12 100644 (file)
@@ -134,11 +134,8 @@ private:
   // Utility helper routines.
   bool isTypeLegal(Type *Ty, MVT &VT);
   bool isLoadStoreTypeLegal(Type *Ty, MVT &VT);
-  bool isLegalToFoldAddress(const Value *Obj);
-  bool computeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);
-  bool computeAddressRecursively(const Value *Obj, Address &Addr, Type *Ty);
-  bool computeAddressBase(const Value *Obj, Address &Addr);
-
+  bool isValueAvailable(const Value *V) const;
+  bool ComputeAddress(const Value *Obj, Address &Addr, Type *Ty = nullptr);
   bool ComputeCallAddress(const Value *V, Address &Addr);
   bool SimplifyAddress(Address &Addr, MVT VT);
   void AddLoadStoreOperands(Address &Addr, const MachineInstrBuilder &MIB,
@@ -420,68 +417,9 @@ unsigned AArch64FastISel::TargetMaterializeFloatZero(const ConstantFP* CFP) {
   return FastEmitInst_r(Opc, TLI.getRegClassFor(VT), ZReg, /*IsKill=*/true);
 }
 
-bool AArch64FastISel::isLegalToFoldAddress(const Value *Obj) {
-  // Look through BitCast, IntToPtr, and PtrToInt.
-  const User *U = nullptr;
-  unsigned Opcode = Instruction::UserOp1;
-  if (const auto *I = dyn_cast<Instruction>(Obj)) {
-    // Bail out if the result is used in a different basic block.
-    if (FuncInfo.isExportedInst(I))
-      return false;
-
-    Opcode = I->getOpcode();
-    U = I;
-  } else if (const auto *CE = dyn_cast<ConstantExpr>(Obj)) {
-    Opcode = CE->getOpcode();
-    U = CE;
-  }
-
-  switch (Opcode) {
-  default:
-    break;
-  case Instruction::BitCast:
-    return isLegalToFoldAddress(U->getOperand(0));
-  case Instruction::IntToPtr:
-    if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
-      return isLegalToFoldAddress(U->getOperand(0));
-    break;
-  case Instruction::PtrToInt:
-    if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
-      return isLegalToFoldAddress(U->getOperand(0));
-    break;
-  }
-
-  // Allocas never kill their operands, so it is safe to fold it.
-  if (isa<AllocaInst>(Obj) || !isa<Instruction>(Obj))
-    return true;
-
-  const auto *I = cast<Instruction>(Obj);
-  // Trivial case - the memory instruction is the only user.
-  if (I->hasOneUse())
-    return true;
-
-  // Check all users - if all of them are memory instructions that FastISel
-  // can handle, then it is safe to fold the instruction.
-  for (auto *U : I->users())
-    if (!isa<LoadInst>(U) && !isa<StoreInst>(U))
-      return false;
-
-  return true;
-}
-
 // Computes the address to get to an object.
-bool AArch64FastISel::computeAddress(const Value *Obj, Address &Addr,
-                                     Type *Ty) {
-  // Don't fold instructions into the memory operation if their result is
-  // exported to another basic block or has more than one use - except if all
-  // uses are memory operations.
-  if (isLegalToFoldAddress(Obj))
-    return computeAddressRecursively(Obj, Addr, Ty);
-  return computeAddressBase(Obj, Addr);
-}
-
-bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
-                                                Type *Ty) {
+bool AArch64FastISel::ComputeAddress(const Value *Obj, Address &Addr, Type *Ty)
+{
   const User *U = nullptr;
   unsigned Opcode = Instruction::UserOp1;
   if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
@@ -508,18 +446,18 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
     break;
   case Instruction::BitCast: {
     // Look through bitcasts.
-    return computeAddressRecursively(U->getOperand(0), Addr, Ty);
+    return ComputeAddress(U->getOperand(0), Addr, Ty);
   }
   case Instruction::IntToPtr: {
     // Look past no-op inttoptrs.
     if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy())
-      return computeAddressRecursively(U->getOperand(0), Addr, Ty);
+      return ComputeAddress(U->getOperand(0), Addr, Ty);
     break;
   }
   case Instruction::PtrToInt: {
-    // Look past no-op ptrtoints. Don't increment recursion level.
+    // Look past no-op ptrtoints.
     if (TLI.getValueType(U->getType()) == TLI.getPointerTy())
-      return computeAddressRecursively(U->getOperand(0), Addr, Ty);
+      return ComputeAddress(U->getOperand(0), Addr, Ty);
     break;
   }
   case Instruction::GetElementPtr: {
@@ -561,7 +499,7 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
 
     // Try to grab the base operand now.
     Addr.setOffset(TmpOffset);
-    if (computeAddressRecursively(U->getOperand(0), Addr, Ty))
+    if (ComputeAddress(U->getOperand(0), Addr, Ty))
       return true;
 
     // We failed, restore everything and try the other options.
@@ -582,9 +520,6 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
     break;
   }
   case Instruction::Add: {
-    if (!U->hasOneUse())
-      break;
-
     // Adds of constants are common and easy enough.
     const Value *LHS = U->getOperand(0);
     const Value *RHS = U->getOperand(1);
@@ -594,21 +529,17 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
 
     if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
       Addr.setOffset(Addr.getOffset() + (uint64_t)CI->getSExtValue());
-      return computeAddressRecursively(LHS, Addr, Ty);
+      return ComputeAddress(LHS, Addr, Ty);
     }
 
     Address Backup = Addr;
-    if (computeAddressRecursively(LHS, Addr, Ty) &&
-        computeAddressRecursively(RHS, Addr, Ty))
+    if (ComputeAddress(LHS, Addr, Ty) && ComputeAddress(RHS, Addr, Ty))
       return true;
     Addr = Backup;
 
     break;
   }
   case Instruction::Shl:
-    if (!U->hasOneUse())
-      break;
-
     if (Addr.getOffsetReg())
       break;
 
@@ -631,10 +562,8 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
       Addr.setShift(Val);
       Addr.setExtendType(AArch64_AM::LSL);
 
-      // Only try to fold the operand if it has one use.
       if (const auto *I = dyn_cast<Instruction>(U->getOperand(0)))
-        if (I->hasOneUse() &&
-            (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB))
+        if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB)
           U = I;
 
       if (const auto *ZE = dyn_cast<ZExtInst>(U))
@@ -654,10 +583,6 @@ bool AArch64FastISel::computeAddressRecursively(const Value *Obj, Address &Addr,
     break;
   }
 
-  return computeAddressBase(Obj, Addr);
-}
-
-bool AArch64FastISel::computeAddressBase(const Value *Obj, Address &Addr) {
   if (Addr.getReg()) {
     if (!Addr.getOffsetReg()) {
       unsigned Reg = getRegForValue(Obj);
@@ -755,6 +680,17 @@ bool AArch64FastISel::isLoadStoreTypeLegal(Type *Ty, MVT &VT) {
   return false;
 }
 
+bool AArch64FastISel::isValueAvailable(const Value *V) const {
+  if (!isa<Instruction>(V))
+    return true;
+
+  const auto *I = cast<Instruction>(V);
+  if (FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB)
+    return true;
+
+  return false;
+}
+
 bool AArch64FastISel::SimplifyAddress(Address &Addr, MVT VT) {
   unsigned ScaleFactor;
   switch (VT.SimpleTy) {
@@ -929,7 +865,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
     std::swap(LHS, RHS);
 
   // Canonicalize shift immediate to the RHS.
-  if (UseAdds)
+  if (UseAdds && isValueAvailable(LHS))
     if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
       if (isa<ConstantInt>(SI->getOperand(1)))
         if (SI->getOpcode() == Instruction::Shl  ||
@@ -959,7 +895,7 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
     return ResultReg;
 
   // Only extend the RHS within the instruction if there is a valid extend type.
-  if (ExtendType != AArch64_AM::InvalidShiftExtend) {
+  if (ExtendType != AArch64_AM::InvalidShiftExtend && isValueAvailable(RHS)) {
     if (const auto *SI = dyn_cast<BinaryOperator>(RHS))
       if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1)))
         if ((SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) {
@@ -980,26 +916,27 @@ unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
   }
 
   // Check if the shift can be folded into the instruction.
-  if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
-    if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
-      AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;
-      switch (SI->getOpcode()) {
-      default: break;
-      case Instruction::Shl:  ShiftType = AArch64_AM::LSL; break;
-      case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;
-      case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;
-      }
-      uint64_t ShiftVal = C->getZExtValue();
-      if (ShiftType != AArch64_AM::InvalidShiftExtend) {
-        unsigned RHSReg = getRegForValue(SI->getOperand(0));
-        if (!RHSReg)
-          return 0;
-        bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
-        return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
-                               RHSIsKill, ShiftType, ShiftVal, WantResult);
+  if (isValueAvailable(RHS))
+    if (const auto *SI = dyn_cast<BinaryOperator>(RHS)) {
+      if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1))) {
+        AArch64_AM::ShiftExtendType ShiftType = AArch64_AM::InvalidShiftExtend;
+        switch (SI->getOpcode()) {
+        default: break;
+        case Instruction::Shl:  ShiftType = AArch64_AM::LSL; break;
+        case Instruction::LShr: ShiftType = AArch64_AM::LSR; break;
+        case Instruction::AShr: ShiftType = AArch64_AM::ASR; break;
+        }
+        uint64_t ShiftVal = C->getZExtValue();
+        if (ShiftType != AArch64_AM::InvalidShiftExtend) {
+          unsigned RHSReg = getRegForValue(SI->getOperand(0));
+          if (!RHSReg)
+            return 0;
+          bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
+          return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
+                                 RHSIsKill, ShiftType, ShiftVal, WantResult);
+        }
       }
     }
-  }
 
   unsigned RHSReg = getRegForValue(RHS);
   if (!RHSReg)
@@ -1428,7 +1365,7 @@ bool AArch64FastISel::SelectLoad(const Instruction *I) {
 
   // See if we can handle this address.
   Address Addr;
-  if (!computeAddress(I->getOperand(0), Addr, I->getType()))
+  if (!ComputeAddress(I->getOperand(0), Addr, I->getType()))
     return false;
 
   unsigned ResultReg;
@@ -1545,7 +1482,7 @@ bool AArch64FastISel::SelectStore(const Instruction *I) {
 
   // See if we can handle this address.
   Address Addr;
-  if (!computeAddress(I->getOperand(1), Addr, I->getOperand(0)->getType()))
+  if (!ComputeAddress(I->getOperand(1), Addr, I->getOperand(0)->getType()))
     return false;
 
   if (!EmitStore(VT, SrcReg, Addr, createMachineMemOperandFor(I)))
@@ -2453,7 +2390,7 @@ bool AArch64FastISel::FastLowerIntrinsicCall(const IntrinsicInst *II) {
     if (MTI->isVolatile())
       return false;
 
-    // Disable inlining for memmove before calls to computeAddress.  Otherwise,
+    // Disable inlining for memmove before calls to ComputeAddress.  Otherwise,
     // we would emit dead code because we don't currently handle memmoves.
     bool IsMemCpy = (II->getIntrinsicID() == Intrinsic::memcpy);
     if (isa<ConstantInt>(MTI->getLength()) && IsMemCpy) {
@@ -2463,8 +2400,8 @@ bool AArch64FastISel::FastLowerIntrinsicCall(const IntrinsicInst *II) {
       unsigned Alignment = MTI->getAlignment();
       if (IsMemCpySmall(Len, Alignment)) {
         Address Dest, Src;
-        if (!computeAddress(MTI->getRawDest(), Dest) ||
-            !computeAddress(MTI->getRawSource(), Src))
+        if (!ComputeAddress(MTI->getRawDest(), Dest) ||
+            !ComputeAddress(MTI->getRawSource(), Src))
           return false;
         if (TryEmitSmallMemCpy(Dest, Src, Len, Alignment))
           return true;
@@ -2757,8 +2694,11 @@ bool AArch64FastISel::SelectTrunc(const Instruction *I) {
   bool SrcIsKill = hasTrivialKill(Op);
 
   // If we're truncating from i64 to a smaller non-legal type then generate an
-  // AND.  Otherwise, we know the high bits are undefined and a truncate doesn't
-  // generate any code.
+  // AND. Otherwise, we know the high bits are undefined and a truncate only
+  // generate a COPY. We cannot mark the source register also as result
+  // register, because this can incorrectly transfer the kill flag onto the
+  // source register.
+  unsigned ResultReg;
   if (SrcVT == MVT::i64) {
     uint64_t Mask = 0;
     switch (DestVT.SimpleTy) {
@@ -2779,12 +2719,16 @@ bool AArch64FastISel::SelectTrunc(const Instruction *I) {
     unsigned Reg32 = FastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,
                                                 AArch64::sub_32);
     // Create the AND instruction which performs the actual truncation.
-    unsigned ANDReg = emitAND_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask);
-    assert(ANDReg && "Unexpected AND instruction emission failure.");
-    SrcReg = ANDReg;
+    ResultReg = emitAND_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask);
+    assert(ResultReg && "Unexpected AND instruction emission failure.");
+  } else {
+    ResultReg = createResultReg(&AArch64::GPR32RegClass);
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+            TII.get(TargetOpcode::COPY), ResultReg)
+        .addReg(SrcReg, getKillRegState(SrcIsKill));
   }
 
-  UpdateValueMap(I, SrcReg);
+  UpdateValueMap(I, ResultReg);
   return true;
 }
 
@@ -3357,17 +3301,19 @@ bool AArch64FastISel::SelectShift(const Instruction *I) {
     uint64_t ShiftVal = C->getZExtValue();
     MVT SrcVT = RetVT;
     bool IsZExt = (I->getOpcode() == Instruction::AShr) ? false : true;
-    const Value * Op0 = I->getOperand(0);
+    const Value *Op0 = I->getOperand(0);
     if (const auto *ZExt = dyn_cast<ZExtInst>(Op0)) {
       MVT TmpVT;
-      if (isLoadStoreTypeLegal(ZExt->getSrcTy(), TmpVT)) {
+      if (isValueAvailable(ZExt) &&
+          isLoadStoreTypeLegal(ZExt->getSrcTy(), TmpVT)) {
         SrcVT = TmpVT;
         IsZExt = true;
         Op0 = ZExt->getOperand(0);
       }
     } else if (const auto *SExt = dyn_cast<SExtInst>(Op0)) {
       MVT TmpVT;
-      if (isLoadStoreTypeLegal(SExt->getSrcTy(), TmpVT)) {
+      if (isValueAvailable(SExt) &&
+          isLoadStoreTypeLegal(SExt->getSrcTy(), TmpVT)) {
         SrcVT = TmpVT;
         IsZExt = false;
         Op0 = SExt->getOperand(0);