[llvm] bc76dad - [CodeGen] Move ARMCodegenPrepare to TypePromotion

Sam Parker via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 3 03:13:22 PST 2019


Author: Sam Parker
Date: 2019-12-03T11:12:52Z
New Revision: bc76dadb3cf16c38564ccb1cc54206279b7c54bc

URL: https://github.com/llvm/llvm-project/commit/bc76dadb3cf16c38564ccb1cc54206279b7c54bc
DIFF: https://github.com/llvm/llvm-project/commit/bc76dadb3cf16c38564ccb1cc54206279b7c54bc.diff

LOG: [CodeGen] Move ARMCodegenPrepare to TypePromotion

Convert ARMCodeGenPrepare into a generic type promotion pass by:
- Removing the insertion of arm specific intrinsics to handle narrow
  types as we weren't using this.
- Removing ARMSubtarget references.
- Now query a generic TLI object to know which types should be
  promoted and what they should be promoted to.
- Move all codegen tests into Transforms folder and testing using opt
  and not llc, which is how they should have been written in the
  first place...

The pass searches up from icmp operands in an attempt to safely
promote types so we can avoid generating unnecessary unsigned extends
during DAG ISel.

Differential Revision: https://reviews.llvm.org/D69556

Added: 
    llvm/lib/CodeGen/TypePromotion.cpp
    llvm/test/Transforms/TypePromotion/ARM/calls.ll
    llvm/test/Transforms/TypePromotion/ARM/casts.ll
    llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
    llvm/test/Transforms/TypePromotion/ARM/icmps.ll
    llvm/test/Transforms/TypePromotion/ARM/lit.local.cfg
    llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
    llvm/test/Transforms/TypePromotion/ARM/pointers.ll
    llvm/test/Transforms/TypePromotion/ARM/signed-icmps.ll
    llvm/test/Transforms/TypePromotion/ARM/signed.ll
    llvm/test/Transforms/TypePromotion/ARM/switch.ll
    llvm/test/Transforms/TypePromotion/ARM/wrapping.ll

Modified: 
    llvm/include/llvm/CodeGen/Passes.h
    llvm/include/llvm/InitializePasses.h
    llvm/lib/CodeGen/CMakeLists.txt
    llvm/lib/CodeGen/CodeGen.cpp
    llvm/lib/Target/ARM/ARM.h
    llvm/lib/Target/ARM/ARMTargetMachine.cpp
    llvm/lib/Target/ARM/CMakeLists.txt
    llvm/test/CodeGen/ARM/O3-pipeline.ll
    llvm/tools/opt/opt.cpp

Removed: 
    llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
    llvm/test/CodeGen/ARM/CGP/arm-cgp-calls.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-casts.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-signed.ll
    llvm/test/CodeGen/ARM/CGP/arm-cgp-switch.ll
    llvm/test/CodeGen/ARM/CGP/clear-structures.ll


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index c21414760ce9..4e3451d80572 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -463,6 +463,9 @@ namespace llvm {
   /// Create Hardware Loop pass. \see HardwareLoops.cpp
   FunctionPass *createHardwareLoopsPass();
 
+  /// Create IR Type Promotion pass. \see TypePromotion.cpp
+  FunctionPass *createTypePromotionPass();
+
 } // End llvm namespace
 
 #endif

diff  --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index dbae32e84393..574cb69360ac 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -408,6 +408,7 @@ void initializeTargetTransformInfoWrapperPassPass(PassRegistry&);
 void initializeThreadSanitizerLegacyPassPass(PassRegistry&);
 void initializeTwoAddressInstructionPassPass(PassRegistry&);
 void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
+void initializeTypePromotionPass(PassRegistry&);
 void initializeUnifyFunctionExitNodesPass(PassRegistry&);
 void initializeUnpackMachineBundlesPass(PassRegistry&);
 void initializeUnreachableBlockElimLegacyPassPass(PassRegistry&);

diff  --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 8875568c5938..c10c3f4d7863 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -163,6 +163,7 @@ add_llvm_component_library(LLVMCodeGen
   TargetRegisterInfo.cpp
   TargetSchedule.cpp
   TargetSubtargetInfo.cpp
+  TypePromotion.cpp
   TwoAddressInstructionPass.cpp
   UnreachableBlockElim.cpp
   ValueTypes.cpp

diff  --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 85696ccc482a..20fc67cc66ae 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -105,6 +105,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
   initializeTailDuplicatePass(Registry);
   initializeTargetPassConfigPass(Registry);
   initializeTwoAddressInstructionPassPass(Registry);
+  initializeTypePromotionPass(Registry);
   initializeUnpackMachineBundlesPass(Registry);
   initializeUnreachableBlockElimLegacyPassPass(Registry);
   initializeUnreachableMachineBlockElimPass(Registry);

diff  --git a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp b/llvm/lib/CodeGen/TypePromotion.cpp
similarity index 78%
rename from llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
rename to llvm/lib/CodeGen/TypePromotion.cpp
index 1c2c8aef55bb..94fe7d2c7030 100644
--- a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/TypePromotion.cpp
@@ -1,4 +1,4 @@
-//===----- ARMCodeGenPrepare.cpp ------------------------------------------===//
+//===----- TypePromotion.cpp ----------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,23 +7,25 @@
 //===----------------------------------------------------------------------===//
 //
 /// \file
-/// This pass inserts intrinsics to handle small types that would otherwise be
-/// promoted during legalization. Here we can manually promote types or insert
-/// intrinsics which can handle narrow types that aren't supported by the
-/// register classes.
-//
+/// This is an opcode based type promotion pass for small types that would
+/// otherwise be promoted during legalisation. This works around the limitations
+/// of selection dag for cyclic regions. The search begins from icmp
+/// instructions operands where a tree, consisting of non-wrapping or safe
+/// wrapping instructions, is built, checked and promoted if possible.
+///
 //===----------------------------------------------------------------------===//
 
-#include "ARM.h"
-#include "ARMSubtarget.h"
-#include "ARMTargetMachine.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -32,26 +34,19 @@
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/InitializePasses.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 
-#define DEBUG_TYPE "arm-codegenprepare"
+#define DEBUG_TYPE "type-promotion"
+#define PASS_NAME "Type Promotion"
 
 using namespace llvm;
 
 static cl::opt<bool>
-DisableCGP("arm-disable-cgp", cl::Hidden, cl::init(true),
-           cl::desc("Disable ARM specific CodeGenPrepare pass"));
-
-static cl::opt<bool>
-EnableDSP("arm-enable-scalar-dsp", cl::Hidden, cl::init(false),
-          cl::desc("Use DSP instructions for scalar operations"));
-
-static cl::opt<bool>
-EnableDSPWithImms("arm-enable-scalar-dsp-imms", cl::Hidden, cl::init(false),
-                   cl::desc("Use DSP instructions for scalar operations\
-                            with immediate operands"));
+DisablePromotion("disable-type-promotion", cl::Hidden, cl::init(true),
+                 cl::desc("Disable type promotion pass"));
 
 // The goal of this pass is to enable more efficient code generation for
 // operations on narrow types (i.e. types with < 32-bits) and this is a
@@ -111,7 +106,6 @@ class IRPromoter {
   SmallPtrSet<Instruction*, 4> InstsToRemove;
   DenseMap<Value*, SmallVector<Type*, 4>> TruncTysMap;
   SmallPtrSet<Value*, 8> Promoted;
-  Module *M = nullptr;
   LLVMContext &Ctx;
   // The type we promote to: always i32
   IntegerType *ExtTy = nullptr;
@@ -134,11 +128,10 @@ class IRPromoter {
   void Cleanup(void);
 
 public:
-  IRPromoter(Module *M) : M(M), Ctx(M->getContext()),
-                          ExtTy(Type::getInt32Ty(Ctx)) { }
+  IRPromoter(Module *M) : Ctx(M->getContext()) { }
 
 
-  void Mutate(Type *OrigTy,
+  void Mutate(Type *OrigTy, unsigned PromotedWidth,
               SetVector<Value*> &Visited,
               SmallPtrSetImpl<Value*> &Sources,
               SmallPtrSetImpl<Instruction*> &Sinks,
@@ -146,30 +139,29 @@ class IRPromoter {
               SmallPtrSetImpl<Instruction*> &SafeWrap);
 };
 
-class ARMCodeGenPrepare : public FunctionPass {
-  const ARMSubtarget *ST = nullptr;
+class TypePromotion : public FunctionPass {
   IRPromoter *Promoter = nullptr;
-  std::set<Value*> AllVisited;
+  SmallPtrSet<Value*, 16> AllVisited;
   SmallPtrSet<Instruction*, 8> SafeToPromote;
   SmallPtrSet<Instruction*, 4> SafeWrap;
 
   bool isSafeWrap(Instruction *I);
   bool isSupportedValue(Value *V);
   bool isLegalToPromote(Value *V);
-  bool TryToPromote(Value *V);
+  bool TryToPromote(Value *V, unsigned PromotedWidth);
 
 public:
   static char ID;
   static unsigned TypeSize;
   Type *OrigTy = nullptr;
 
-  ARMCodeGenPrepare() : FunctionPass(ID) {}
+  TypePromotion() : FunctionPass(ID) {}
 
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.addRequired<TargetPassConfig>();
   }
 
-  StringRef getPassName() const override { return "ARM IR optimizations"; }
+  StringRef getPassName() const override { return PASS_NAME; }
 
   bool doInitialization(Module &M) override;
   bool runOnFunction(Function &F) override;
@@ -188,19 +180,19 @@ static bool GenerateSignBits(Value *V) {
 }
 
 static bool EqualTypeSize(Value *V) {
-  return V->getType()->getScalarSizeInBits() == ARMCodeGenPrepare::TypeSize;
+  return V->getType()->getScalarSizeInBits() == TypePromotion::TypeSize;
 }
 
 static bool LessOrEqualTypeSize(Value *V) {
-  return V->getType()->getScalarSizeInBits() <= ARMCodeGenPrepare::TypeSize;
+  return V->getType()->getScalarSizeInBits() <= TypePromotion::TypeSize;
 }
 
 static bool GreaterThanTypeSize(Value *V) {
-  return V->getType()->getScalarSizeInBits() > ARMCodeGenPrepare::TypeSize;
+  return V->getType()->getScalarSizeInBits() > TypePromotion::TypeSize;
 }
 
 static bool LessThanTypeSize(Value *V) {
-  return V->getType()->getScalarSizeInBits() < ARMCodeGenPrepare::TypeSize;
+  return V->getType()->getScalarSizeInBits() < TypePromotion::TypeSize;
 }
 
 /// Some instructions can use 8- and 16-bit operands, and we don't need to
@@ -278,7 +270,7 @@ static bool isSink(Value *V) {
 }
 
 /// Return whether this instruction can safely wrap.
-bool ARMCodeGenPrepare::isSafeWrap(Instruction *I) {
+bool TypePromotion::isSafeWrap(Instruction *I) {
   // We can support a, potentially, wrapping instruction (I) if:
   // - It is only used by an unsigned icmp.
   // - The icmp uses a constant.
@@ -374,7 +366,7 @@ bool ARMCodeGenPrepare::isSafeWrap(Instruction *I) {
   Total += OverflowConst->getValue().getBitWidth() < 32 ?
     OverflowConst->getValue().abs().zext(32) : OverflowConst->getValue().abs();
 
-  APInt Max = APInt::getAllOnesValue(ARMCodeGenPrepare::TypeSize);
+  APInt Max = APInt::getAllOnesValue(TypePromotion::TypeSize);
 
   if (Total.getBitWidth() > Max.getBitWidth()) {
     if (Total.ugt(Max.zext(Total.getBitWidth())))
@@ -385,7 +377,7 @@ bool ARMCodeGenPrepare::isSafeWrap(Instruction *I) {
   } else if (Total.ugt(Max))
     return false;
 
-  LLVM_DEBUG(dbgs() << "ARM CGP: Allowing safe overflow for " << *I << "\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for " << *I << "\n");
   SafeWrap.insert(I);
   return true;
 }
@@ -422,32 +414,12 @@ static bool isPromotedResultSafe(Value *V) {
   return cast<Instruction>(V)->hasNoUnsignedWrap();
 }
 
-/// Return the intrinsic for the instruction that can perform the same
-/// operation but on a narrow type. This is using the parallel dsp intrinsics
-/// on scalar values.
-static Intrinsic::ID getNarrowIntrinsic(Instruction *I) {
-  // Whether we use the signed or unsigned versions of these intrinsics
-  // doesn't matter because we're not using the GE bits that they set in
-  // the APSR.
-  switch(I->getOpcode()) {
-  default:
-    break;
-  case Instruction::Add:
-    return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_uadd16 :
-      Intrinsic::arm_uadd8;
-  case Instruction::Sub:
-    return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_usub16 :
-      Intrinsic::arm_usub8;
-  }
-  llvm_unreachable("unhandled opcode for narrow intrinsic");
-}
-
 void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
   SmallVector<Instruction*, 4> Users;
   Instruction *InstTo = dyn_cast<Instruction>(To);
   bool ReplacedAll = true;
 
-  LLVM_DEBUG(dbgs() << "ARM CGP: Replacing " << *From << " with " << *To
+  LLVM_DEBUG(dbgs() << "IR Promotion: Replacing " << *From << " with " << *To
              << "\n");
 
   for (Use &U : From->uses()) {
@@ -468,7 +440,7 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
 }
 
 void IRPromoter::PrepareWrappingAdds() {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Prepare underflowing adds.\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Prepare wrapping adds.\n");
   IRBuilder<> Builder{Ctx};
 
   // For adds that safely wrap and use a negative immediate as operand 1, we
@@ -479,7 +451,7 @@ void IRPromoter::PrepareWrappingAdds() {
     if (I->getOpcode() != Instruction::Add)
       continue;
 
-    LLVM_DEBUG(dbgs() << "ARM CGP: Adjusting " << *I << "\n");
+    LLVM_DEBUG(dbgs() << "IR Promotion: Adjusting " << *I << "\n");
     assert((isa<ConstantInt>(I->getOperand(1)) &&
             cast<ConstantInt>(I->getOperand(1))->isNegative()) &&
            "Wrapping should have a negative immediate as the second operand");
@@ -494,7 +466,7 @@ void IRPromoter::PrepareWrappingAdds() {
     }
     InstsToRemove.insert(I);
     I->replaceAllUsesWith(NewVal);
-    LLVM_DEBUG(dbgs() << "ARM CGP: New equivalent: " << *NewVal << "\n");
+    LLVM_DEBUG(dbgs() << "IR Promotion: New equivalent: " << *NewVal << "\n");
   }
   for (auto *I : NewInsts)
     Visited->insert(I);
@@ -505,7 +477,7 @@ void IRPromoter::ExtendSources() {
 
   auto InsertZExt = [&](Value *V, Instruction *InsertPt) {
     assert(V->getType() != ExtTy && "zext already extends to i32");
-    LLVM_DEBUG(dbgs() << "ARM CGP: Inserting ZExt for " << *V << "\n");
+    LLVM_DEBUG(dbgs() << "IR Promotion: Inserting ZExt for " << *V << "\n");
     Builder.SetInsertPoint(InsertPt);
     if (auto *I = dyn_cast<Instruction>(V))
       Builder.SetCurrentDebugLocation(I->getDebugLoc());
@@ -523,7 +495,7 @@ void IRPromoter::ExtendSources() {
   };
 
   // Now, insert extending instructions between the sources and their users.
-  LLVM_DEBUG(dbgs() << "ARM CGP: Promoting sources:\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Promoting sources:\n");
   for (auto V : *Sources) {
     LLVM_DEBUG(dbgs() << " - " << *V << "\n");
     if (auto *I = dyn_cast<Instruction>(V))
@@ -539,7 +511,7 @@ void IRPromoter::ExtendSources() {
 }
 
 void IRPromoter::PromoteTree() {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Mutating the tree..\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Mutating the tree..\n");
 
   IRBuilder<> Builder{Ctx};
 
@@ -570,38 +542,10 @@ void IRPromoter::PromoteTree() {
       Promoted.insert(I);
     }
   }
-
-  // Finally, any instructions that should be promoted but haven't yet been,
-  // need to be handled using intrinsics.
-  for (auto *V : *Visited) {
-    auto *I = dyn_cast<Instruction>(V);
-    if (!I)
-      continue;
-
-    if (Sources->count(I) || Sinks->count(I))
-      continue;
-
-    if (!shouldPromote(I) || SafeToPromote->count(I) || NewInsts.count(I))
-      continue;
-
-    assert(EnableDSP && "DSP intrinisc insertion not enabled!");
-
-    // Replace unsafe instructions with appropriate intrinsic calls.
-    LLVM_DEBUG(dbgs() << "ARM CGP: Inserting DSP intrinsic for "
-               << *I << "\n");
-    Function *DSPInst =
-      Intrinsic::getDeclaration(M, getNarrowIntrinsic(I));
-    Builder.SetInsertPoint(I);
-    Builder.SetCurrentDebugLocation(I->getDebugLoc());
-    Value *Args[] = { I->getOperand(0), I->getOperand(1) };
-    CallInst *Call = Builder.CreateCall(DSPInst, Args);
-    NewInsts.insert(Call);
-    ReplaceAllUsersOfWith(I, Call);
-  }
 }
 
 void IRPromoter::TruncateSinks() {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Fixing up the sinks:\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Fixing up the sinks:\n");
 
   IRBuilder<> Builder{Ctx};
 
@@ -612,7 +556,7 @@ void IRPromoter::TruncateSinks() {
     if ((!Promoted.count(V) && !NewInsts.count(V)) || Sources->count(V))
       return nullptr;
 
-    LLVM_DEBUG(dbgs() << "ARM CGP: Creating " << *TruncTy << " Trunc for "
+    LLVM_DEBUG(dbgs() << "IR Promotion: Creating " << *TruncTy << " Trunc for "
                << *V << "\n");
     Builder.SetInsertPoint(cast<Instruction>(V));
     auto *Trunc = dyn_cast<Instruction>(Builder.CreateTrunc(V, TruncTy));
@@ -624,7 +568,7 @@ void IRPromoter::TruncateSinks() {
   // Fix up any stores or returns that use the results of the promoted
   // chain.
   for (auto I : *Sinks) {
-    LLVM_DEBUG(dbgs() << "ARM CGP: For Sink: " << *I << "\n");
+    LLVM_DEBUG(dbgs() << "IR Promotion: For Sink: " << *I << "\n");
 
     // Handle calls separately as we need to iterate over arg operands.
     if (auto *Call = dyn_cast<CallInst>(I)) {
@@ -661,7 +605,7 @@ void IRPromoter::TruncateSinks() {
 }
 
 void IRPromoter::Cleanup() {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Cleanup..\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Cleanup..\n");
   // Some zexts will now have become redundant, along with their trunc
   // operands, so remove them
   for (auto V : *Visited) {
@@ -674,7 +618,7 @@ void IRPromoter::Cleanup() {
 
     Value *Src = ZExt->getOperand(0);
     if (ZExt->getSrcTy() == ZExt->getDestTy()) {
-      LLVM_DEBUG(dbgs() << "ARM CGP: Removing unnecessary cast: " << *ZExt
+      LLVM_DEBUG(dbgs() << "IR Promotion: Removing unnecessary cast: " << *ZExt
                  << "\n");
       ReplaceAllUsersOfWith(ZExt, Src);
       continue;
@@ -693,7 +637,7 @@ void IRPromoter::Cleanup() {
   }
 
   for (auto *I : InstsToRemove) {
-    LLVM_DEBUG(dbgs() << "ARM CGP: Removing " << *I << "\n");
+    LLVM_DEBUG(dbgs() << "IR Promotion: Removing " << *I << "\n");
     I->dropAllReferences();
     I->eraseFromParent();
   }
@@ -707,7 +651,7 @@ void IRPromoter::Cleanup() {
 }
 
 void IRPromoter::ConvertTruncs() {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Converting truncs..\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Converting truncs..\n");
   IRBuilder<> Builder{Ctx};
 
   for (auto *V : *Visited) {
@@ -731,17 +675,18 @@ void IRPromoter::ConvertTruncs() {
   }
 }
 
-void IRPromoter::Mutate(Type *OrigTy,
+void IRPromoter::Mutate(Type *OrigTy, unsigned PromotedWidth,
                         SetVector<Value*> &Visited,
                         SmallPtrSetImpl<Value*> &Sources,
                         SmallPtrSetImpl<Instruction*> &Sinks,
                         SmallPtrSetImpl<Instruction*> &SafeToPromote,
                         SmallPtrSetImpl<Instruction*> &SafeWrap) {
-  LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
-             << ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Promoting use-def chains to from "
+             << TypePromotion::TypeSize << " to 32-bits\n");
 
   assert(isa<IntegerType>(OrigTy) && "expected integer type");
   this->OrigTy = cast<IntegerType>(OrigTy);
+  ExtTy = IntegerType::get(Ctx, PromotedWidth);
   assert(OrigTy->getPrimitiveSizeInBits() < ExtTy->getPrimitiveSizeInBits() &&
          "original type not smaller than extended type");
 
@@ -779,9 +724,7 @@ void IRPromoter::Mutate(Type *OrigTy,
   // Insert zext instructions between sources and their users.
   ExtendSources();
 
-  // Promote visited instructions, mutating their types in place. Also insert
-  // DSP intrinsics, if enabled, for adds and subs which would be unsafe to
-  // promote.
+  // Promote visited instructions, mutating their types in place.
   PromoteTree();
 
   // Convert any truncs, that aren't sources, into AND masks.
@@ -794,14 +737,14 @@ void IRPromoter::Mutate(Type *OrigTy,
   // clear the data structures.
   Cleanup();
 
-  LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: Mutation complete\n");
 }
 
 /// We accept most instructions, as well as Arguments and ConstantInsts. We
 /// Disallow casts other than zext and truncs and only allow calls if their
 /// return value is zeroext. We don't allow opcodes that can introduce sign
 /// bits.
-bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
+bool TypePromotion::isSupportedValue(Value *V) {
   if (auto *I = dyn_cast<Instruction>(V)) {
     switch (I->getOpcode()) {
     default:
@@ -849,7 +792,7 @@ bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
 /// Check that the type of V would be promoted and that the original type is
 /// smaller than the targeted promoted type. Check that we're not trying to
 /// promote something larger than our base 'TypeSize' type.
-bool ARMCodeGenPrepare::isLegalToPromote(Value *V) {
+bool TypePromotion::isLegalToPromote(Value *V) {
 
   auto *I = dyn_cast<Instruction>(V);
   if (!I)
@@ -862,47 +805,20 @@ bool ARMCodeGenPrepare::isLegalToPromote(Value *V) {
     SafeToPromote.insert(I);
     return true;
   }
-
-  if (I->getOpcode() != Instruction::Add && I->getOpcode() != Instruction::Sub)
-    return false;
-
-  // If promotion is not safe, can we use a DSP instruction to natively
-  // handle the narrow type?
-  if (!ST->hasDSP() || !EnableDSP || !isSupportedType(I))
-    return false;
-
-  if (ST->isThumb() && !ST->hasThumb2())
-    return false;
-
-  // TODO
-  // Would it be profitable? For Thumb code, these parallel DSP instructions
-  // are only Thumb-2, so we wouldn't be able to dual issue on Cortex-M33. For
-  // Cortex-A, specifically Cortex-A72, the latency is double and throughput is
-  // halved. They also do not take immediates as operands.
-  for (auto &Op : I->operands()) {
-    if (isa<Constant>(Op)) {
-      if (!EnableDSPWithImms)
-        return false;
-    }
-  }
-  LLVM_DEBUG(dbgs() << "ARM CGP: Will use an intrinsic for: " << *I << "\n");
-  return true;
+  return false;
 }
 
-bool ARMCodeGenPrepare::TryToPromote(Value *V) {
+bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) {
   OrigTy = V->getType();
   TypeSize = OrigTy->getPrimitiveSizeInBits();
-  if (TypeSize > 16 || TypeSize < 8)
-    return false;
-
   SafeToPromote.clear();
   SafeWrap.clear();
 
   if (!isSupportedValue(V) || !shouldPromote(V) || !isLegalToPromote(V))
     return false;
 
-  LLVM_DEBUG(dbgs() << "ARM CGP: TryToPromote: " << *V << ", TypeSize = "
-             << TypeSize << "\n");
+  LLVM_DEBUG(dbgs() << "IR Promotion: TryToPromote: " << *V << ", from "
+             << TypeSize << " bits to " << PromotedWidth << "\n");
 
   SetVector<Value*> WorkList;
   SmallPtrSet<Value*, 8> Sources;
@@ -923,7 +839,7 @@ bool ARMCodeGenPrepare::TryToPromote(Value *V) {
       return true;
 
     if (!isSupportedValue(V) || (shouldPromote(V) && !isLegalToPromote(V))) {
-      LLVM_DEBUG(dbgs() << "ARM CGP: Can't handle: " << *V << "\n");
+      LLVM_DEBUG(dbgs() << "IR Promotion: Can't handle: " << *V << "\n");
       return false;
     }
 
@@ -979,7 +895,7 @@ bool ARMCodeGenPrepare::TryToPromote(Value *V) {
     }
   }
 
-  LLVM_DEBUG(dbgs() << "ARM CGP: Visited nodes:\n";
+  LLVM_DEBUG(dbgs() << "IR Promotion: Visited nodes:\n";
              for (auto *I : CurrentVisited)
                I->dump();
              );
@@ -995,28 +911,31 @@ bool ARMCodeGenPrepare::TryToPromote(Value *V) {
   if (ToPromote < 2)
     return false;
 
-  Promoter->Mutate(OrigTy, CurrentVisited, Sources, Sinks, SafeToPromote,
-                   SafeWrap);
+  Promoter->Mutate(OrigTy, PromotedWidth, CurrentVisited, Sources, Sinks,
+                   SafeToPromote, SafeWrap);
   return true;
 }
 
-bool ARMCodeGenPrepare::doInitialization(Module &M) {
+bool TypePromotion::doInitialization(Module &M) {
   Promoter = new IRPromoter(&M);
   return false;
 }
 
-bool ARMCodeGenPrepare::runOnFunction(Function &F) {
-  if (skipFunction(F) || DisableCGP)
+bool TypePromotion::runOnFunction(Function &F) {
+  if (skipFunction(F) || DisablePromotion)
     return false;
 
-  auto *TPC = &getAnalysis<TargetPassConfig>();
+  LLVM_DEBUG(dbgs() << "IR Promotion: Running on " << F.getName() << "\n");
+
+  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
   if (!TPC)
     return false;
 
-  const TargetMachine &TM = TPC->getTM<TargetMachine>();
-  ST = &TM.getSubtarget<ARMSubtarget>(F);
   bool MadeChange = false;
-  LLVM_DEBUG(dbgs() << "ARM CGP: Running on " << F.getName() << "\n");
+  const DataLayout &DL = F.getParent()->getDataLayout();
+  const TargetMachine &TM = TPC->getTM<TargetMachine>();
+  const TargetSubtargetInfo *SubtargetInfo = TM.getSubtargetImpl(F);
+  const TargetLowering *TLI = SubtargetInfo->getTargetLowering();
 
   // Search up from icmps to try to promote their operands.
   for (BasicBlock &BB : F) {
@@ -1025,18 +944,30 @@ bool ARMCodeGenPrepare::runOnFunction(Function &F) {
       if (AllVisited.count(&I))
         continue;
 
-      if (isa<ICmpInst>(I)) {
-        auto &CI = cast<ICmpInst>(I);
+      if (!isa<ICmpInst>(&I))
+        continue;
+
+      auto *ICmp = cast<ICmpInst>(&I);
+      // Skip signed or pointer compares
+      if (ICmp->isSigned() ||
+          !isa<IntegerType>(ICmp->getOperand(0)->getType()))
+        continue;
+
+      LLVM_DEBUG(dbgs() << "IR Promotion: Searching from: " << *ICmp << "\n");
 
-        // Skip signed or pointer compares
-        if (CI.isSigned() || !isa<IntegerType>(CI.getOperand(0)->getType()))
-          continue;
+      for (auto &Op : ICmp->operands()) {
+        if (auto *I = dyn_cast<Instruction>(Op)) {
+          EVT SrcVT = TLI->getValueType(DL, I->getType());
+          if (SrcVT.isSimple() && TLI->isTypeLegal(SrcVT.getSimpleVT()))
+            break;
 
-        LLVM_DEBUG(dbgs() << "ARM CGP: Searching from: " << CI << "\n");
+          if (TLI->getTypeAction(ICmp->getContext(), SrcVT) !=
+              TargetLowering::TypePromoteInteger)
+            break;
 
-        for (auto &Op : CI.operands()) {
-          if (auto *I = dyn_cast<Instruction>(Op))
-            MadeChange |= TryToPromote(I);
+          EVT PromotedVT = TLI->getTypeToTransformTo(ICmp->getContext(), SrcVT);
+          MadeChange |= TryToPromote(I, PromotedVT.getSizeInBits());
+          break;
         }
       }
     }
@@ -1046,24 +977,22 @@ bool ARMCodeGenPrepare::runOnFunction(Function &F) {
                });
   }
   if (MadeChange)
-    LLVM_DEBUG(dbgs() << "After ARMCodeGenPrepare: " << F << "\n");
+    LLVM_DEBUG(dbgs() << "After TypePromotion: " << F << "\n");
 
   return MadeChange;
 }
 
-bool ARMCodeGenPrepare::doFinalization(Module &M) {
+bool TypePromotion::doFinalization(Module &M) {
   delete Promoter;
   return false;
 }
 
-INITIALIZE_PASS_BEGIN(ARMCodeGenPrepare, DEBUG_TYPE,
-                      "ARM IR optimizations", false, false)
-INITIALIZE_PASS_END(ARMCodeGenPrepare, DEBUG_TYPE, "ARM IR optimizations",
-                    false, false)
+INITIALIZE_PASS_BEGIN(TypePromotion, DEBUG_TYPE, PASS_NAME, false, false)
+INITIALIZE_PASS_END(TypePromotion, DEBUG_TYPE, PASS_NAME, false, false)
 
-char ARMCodeGenPrepare::ID = 0;
-unsigned ARMCodeGenPrepare::TypeSize = 0;
+char TypePromotion::ID = 0;
+unsigned TypePromotion::TypeSize = 0;
 
-FunctionPass *llvm::createARMCodeGenPreparePass() {
-  return new ARMCodeGenPrepare();
+FunctionPass *llvm::createTypePromotionPass() {
+  return new TypePromotion();
 }

diff  --git a/llvm/lib/Target/ARM/ARM.h b/llvm/lib/Target/ARM/ARM.h
index 2e6f756d522c..9076c191d839 100644
--- a/llvm/lib/Target/ARM/ARM.h
+++ b/llvm/lib/Target/ARM/ARM.h
@@ -43,7 +43,6 @@ FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM,
 FunctionPass *createA15SDOptimizerPass();
 FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
 FunctionPass *createARMExpandPseudoPass();
-FunctionPass *createARMCodeGenPreparePass();
 FunctionPass *createARMConstantIslandPass();
 FunctionPass *createMLxExpansionPass();
 FunctionPass *createThumb2ITBlockPass();
@@ -61,7 +60,6 @@ void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
 void initializeARMParallelDSPPass(PassRegistry &);
 void initializeARMLoadStoreOptPass(PassRegistry &);
 void initializeARMPreAllocLoadStoreOptPass(PassRegistry &);
-void initializeARMCodeGenPreparePass(PassRegistry &);
 void initializeARMConstantIslandsPass(PassRegistry &);
 void initializeARMExpandPseudoPass(PassRegistry &);
 void initializeThumb2SizeReducePass(PassRegistry &);

diff  --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 10f68542e7e1..018ce3903c2d 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -91,7 +91,6 @@ extern "C" void LLVMInitializeARMTarget() {
   initializeARMLoadStoreOptPass(Registry);
   initializeARMPreAllocLoadStoreOptPass(Registry);
   initializeARMParallelDSPPass(Registry);
-  initializeARMCodeGenPreparePass(Registry);
   initializeARMConstantIslandsPass(Registry);
   initializeARMExecutionDomainFixPass(Registry);
   initializeARMExpandPseudoPass(Registry);
@@ -422,7 +421,7 @@ void ARMPassConfig::addIRPasses() {
 
 void ARMPassConfig::addCodeGenPrepare() {
   if (getOptLevel() != CodeGenOpt::None)
-    addPass(createARMCodeGenPreparePass());
+    addPass(createTypePromotionPass());
   TargetPassConfig::addCodeGenPrepare();
 }
 

diff  --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt
index 5ce28f29defb..b94a78ea9404 100644
--- a/llvm/lib/Target/ARM/CMakeLists.txt
+++ b/llvm/lib/Target/ARM/CMakeLists.txt
@@ -25,7 +25,6 @@ add_llvm_target(ARMCodeGen
   ARMBasicBlockInfo.cpp
   ARMCallingConv.cpp
   ARMCallLowering.cpp
-  ARMCodeGenPrepare.cpp
   ARMConstantIslandPass.cpp
   ARMConstantPoolValue.cpp
   ARMExpandPseudoInsts.cpp

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-calls.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-calls.ll
deleted file mode 100644
index 8d58c8e69a55..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-calls.ll
+++ /dev/null
@@ -1,230 +0,0 @@
-; RUN: llc -mtriple=thumbv8 -arm-disable-cgp=false %s -o - | FileCheck %s
-; RUN: llc -mtriple=armv8 -arm-disable-cgp=false %s -o - | FileCheck %s
-
-; Check that the pass doesn't try to promote the immediate parameters.
-; CHECK-LABEL: call_with_imms
-; CHECK-NOT:   uxt
-define i8 @call_with_imms(i8* %arg) {
-  %call = tail call arm_aapcs_vfpcc zeroext i8 @dummy2(i8* nonnull %arg, i8 zeroext 0, i8 zeroext 0)
-  %cmp = icmp eq i8 %call, 0
-  %res = select i1 %cmp, i8 %call, i8 1
-  ret i8 %res
-}
-
-; Test that the call result is still extended.
-; CHECK-LABEL: test_call:
-; CHECK: bl
-; CHECK-NEXT: sxtb r1, r0
-define i16 @test_call(i8 zeroext %arg) {
-  %call = call i8 @dummy_i8(i8 %arg)
-  %cmp = icmp ult i8 %call, 128
-  %conv = zext i1 %cmp to i16
-  ret i16 %conv
-}
-
-; CHECK-LABEL: promote_i8_sink_i16_1
-; CHECK: bl dummy_i8
-; CHECK: add{{.*}} r0, #1
-; CHECK-NOT: uxt
-; CHECK: cmp r0
-define i16 @promote_i8_sink_i16_1(i8 zeroext %arg0, i16 zeroext %arg1, i16 zeroext %arg2) {
-  %call = tail call zeroext i8 @dummy_i8(i8 %arg0)
-  %add = add nuw i8 %call, 1
-  %conv = zext i8 %add to i16
-  %cmp = icmp ne i16 %conv, %arg1
-  %sel = select i1 %cmp, i16 %arg1, i16 %arg2
-  %res = tail call zeroext i16 @dummy3(i16 %sel)
-  ret i16 %res
-}
-
-; CHECK-LABEL: promote_i8_sink_i16_2
-; CHECK: bl dummy_i8
-; CHECK: add{{.*}} r0, #1
-; CHECK-NOT: uxt
-; CHECK: cmp r0
-define i16 @promote_i8_sink_i16_2(i8 zeroext %arg0, i8 zeroext %arg1, i16 zeroext %arg2) {
-  %call = tail call zeroext i8 @dummy_i8(i8 %arg0)
-  %add = add nuw i8 %call, 1
-  %cmp = icmp ne i8 %add, %arg1
-  %conv = zext i8 %arg1 to i16
-  %sel = select i1 %cmp, i16 %conv, i16 %arg2
-  %res = tail call zeroext i16 @dummy3(i16 %sel)
-  ret i16 %res
-}
-
- at uc = global i8 42, align 1
- at LL = global i64 0, align 8
-
-; CHECK-LABEL: zext_i64
-; CHECK: ldrb
-; CHECK: strd
-define void @zext_i64() {
-entry:
-  %0 = load i8, i8* @uc, align 1
-  %conv = zext i8 %0 to i64
-  store i64 %conv, i64* @LL, align 8
-  %cmp = icmp eq i8 %0, 42
-  %conv1 = zext i1 %cmp to i32
-  %call = tail call i32 bitcast (i32 (...)* @assert to i32 (i32)*)(i32 %conv1)
-  ret void
-}
-
- at a = global i16* null, align 4
- at b = global i32 0, align 4
-
-; CHECK-LABEL: constexpr
-; CHECK: uxth
-define i32 @constexpr() {
-entry:
-  store i32 ptrtoint (i32* @b to i32), i32* @b, align 4
-  %0 = load i16*, i16** @a, align 4
-  %1 = load i16, i16* %0, align 2
-  %or = or i16 %1, ptrtoint (i32* @b to i16)
-  store i16 %or, i16* %0, align 2
-  %cmp = icmp ne i16 %or, 4
-  %conv3 = zext i1 %cmp to i32
-  %call = tail call i32 bitcast (i32 (...)* @e to i32 (i32)*)(i32 %conv3) #2
-  ret i32 undef
-}
-
-; The call to safe_lshift_func takes two parameters, but they're the same value
-; just one is zext. We do support zext now, so the transformation should
-; trigger and we don't want see uxtb here.
-; CHECK-LABEL: call_zext_i8_i32
-; CHECK-NOT: uxt
-define fastcc i32 @call_zext_i8_i32(i32 %p_45, i8 zeroext %p_46) {
-for.cond8.preheader:
-  %call217 = call fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 zeroext undef)
-  %tobool219 = icmp eq i8 %call217, 0
-  br i1 %tobool219, label %for.end411, label %for.cond273.preheader
-
-for.cond273.preheader:                            ; preds = %for.cond8.preheader
-  %call217.lcssa = phi i8 [ %call217, %for.cond8.preheader ]
-  %conv218.le = zext i8 %call217.lcssa to i32
-  %call346 = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext %call217.lcssa, i32 %conv218.le)
-  unreachable
-
-for.end411:                                       ; preds = %for.cond8.preheader
-  %call452 = call fastcc i64 @safe_sub_func_int64_t_s_s(i64 undef, i64 4)
-  unreachable
-}
-
-%struct.anon = type { i32 }
-
- at g_57 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4
- at g_893 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4
- at g_82 = hidden local_unnamed_addr global i32 0, align 4
-
-; Test that the transform bails on finding %conv4, a trunc
-; CHECK-LABEL: call_return_pointer
-; CHECK: sxth
-; CHECK: uxt
-define hidden i32 @call_return_pointer(i8 zeroext %p_13) local_unnamed_addr #0 {
-entry:
-  %conv1 = zext i8 %p_13 to i16
-  %call = tail call i16** @func_62(i8 zeroext undef, i32 undef, i16 signext %conv1, i32* undef)
-  %0 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @g_893, i32 0, i32 0), align 4
-  %conv2 = trunc i32 %0 to i16
-  br label %for.cond
-
-for.cond:                                         ; preds = %for.cond.backedge, %entry
-  %p_13.addr.0 = phi i8 [ %p_13, %entry ], [ %p_13.addr.0.be, %for.cond.backedge ]
-  %tobool = icmp eq i8 %p_13.addr.0, 0
-  br i1 %tobool, label %for.cond.backedge, label %if.then
-
-for.cond.backedge:                                ; preds = %for.cond, %if.then
-  %p_13.addr.0.be = phi i8 [ %conv4, %if.then ], [ 0, %for.cond ]
-  br label %for.cond
-
-if.then:                                          ; preds = %for.cond
-  %call3 = tail call fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %conv2)
-  %conv4 = trunc i16 %call3 to i8
-  br label %for.cond.backedge
-}
-
-; Check that d.sroa.0.0.be is promoted passed directly into the tail call.
-; CHECK-LABEL: check_zext_phi_call_arg
-; CHECK-NOT: uxt
-define i32 @check_zext_phi_call_arg() {
-entry:
-  br label %for.cond
-
-for.cond:                                         ; preds = %for.cond.backedge, %entry
-  %d.sroa.0.0 = phi i16 [ 30, %entry ], [ %d.sroa.0.0.be, %for.cond.backedge ]
-  %tobool = icmp eq i16 %d.sroa.0.0, 0
-  br i1 %tobool, label %for.cond.backedge, label %if.then
-
-for.cond.backedge:                                ; preds = %for.cond, %if.then
-  %d.sroa.0.0.be = phi i16 [ %call, %if.then ], [ 0, %for.cond ]
-  br label %for.cond
-
-if.then:                                          ; preds = %for.cond
-  %d.sroa.0.0.insert.ext = zext i16 %d.sroa.0.0 to i32
-  %call = tail call zeroext i16 bitcast (i16 (...)* @f to i16 (i32)*)(i32 %d.sroa.0.0.insert.ext) #2
-  br label %for.cond.backedge
-}
-
-%struct.atomic_flag = type { i8 }
-
-; CHECK-LABEL: atomic_flag_test_and_set
-; CHECK-NOT: uxt
-define zeroext i1 @atomic_flag_test_and_set(%struct.atomic_flag* %object) {
-entry:
-  %_Value = getelementptr inbounds %struct.atomic_flag, %struct.atomic_flag* %object, i32 0, i32 0
-  %call = tail call arm_aapcscc zeroext i8 @__atomic_exchange_1(i8* %_Value, i8 zeroext 1, i32 5) #1
-  %0 = and i8 %call, 1
-  %tobool = icmp ne i8 %0, 0
-  ret i1 %tobool
-}
-
-; CHECK-LABEL: i1_zeroext_call
-; CHECK: uxt
-define i1 @i1_zeroext_call(i16* %ts, i32 %a, i16* %b, i8* %c) {
-entry:
-  %0 = load i16, i16* %ts, align 2
-  %conv.i860 = trunc i32 %a to i16
-  store i16 %conv.i860, i16* %b, align 2
-  %call.i848 = call zeroext i1 @i1_zeroext(i8* %c, i32 64, i16 zeroext %conv.i860)
-  br i1 %call.i848, label %if.then223, label %if.else227
-
-if.then223:
-  %cmp235 = icmp eq i16 %0, %conv.i860
-  br label %exit
-
-if.else227:
-  %cmp236 = icmp ult i16 %0, %conv.i860
-  br label %exit
-
-exit:
-  %retval = phi i1 [ %cmp235, %if.then223 ], [ %cmp236, %if.else227 ]
-  ret i1 %retval
-}
-
-; CHECK-LABEL: promote_arg_pass_to_call
-; CHECK: uxtb
-define i16 @promote_arg_pass_to_call(i16 zeroext %arg1, i16 zeroext %arg2) {
-  %conv = add nuw i16 %arg1, 15
-  %mul = mul nuw nsw i16 %conv, 3
-  %cmp = icmp ult i16 %mul, %arg2
-  %trunc = trunc i16 %arg1 to i8
-  %res = call zeroext i16 @dummy4(i1 %cmp, i8 %trunc, i16 %arg1)
-  ret i16 %res
-}
-
-
-declare i32 @assert(...)
-declare i8 @dummy_i8(i8)
-declare i8 @dummy2(i8*, i8, i8)
-declare i16 @dummy3(i16)
-declare i16 @dummy4(i1, i8, i16)
-
-declare dso_local i32 @e(...) local_unnamed_addr #1
-declare dso_local zeroext i16 @f(...) local_unnamed_addr #1
-declare dso_local arm_aapcscc i8 @__atomic_exchange_1(i8*, i8, i32) local_unnamed_addr
-
-declare noalias i16** @func_62(i8 zeroext %p_63, i32 %p_64, i16 signext %p_65, i32* nocapture readnone %p_66)
-declare fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %si2)
-declare dso_local fastcc i64 @safe_sub_func_int64_t_s_s(i64, i64)
-declare dso_local fastcc zeroext i8 @safe_lshift_func(i8 zeroext, i32)
-declare dso_local fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 returned zeroext)
-declare i1 @i1_zeroext(i8*, i32, i16 zeroext)

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-casts.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-casts.ll
deleted file mode 100644
index 538f110ffd76..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-casts.ll
+++ /dev/null
@@ -1,2243 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NODSP --check-prefix=CHECK-NODSP-V8
-; RUN: llc -mtriple=thumbv7-linux-android %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NODSP --check-prefix=CHECK-NODSP-V7
-; RUN: llc -mtriple=thumbv7em -mcpu=cortex-m7 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DSP
-; RUN: llc -mtriple=thumbv8 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DSP-IMM
-
-; Transform will fail because the trunc is not a sink.
-
-define i16 @dsp_trunc(i32 %arg0, i32 %arg1, i16* %gep0, i16* %gep1) {
-; CHECK-NODSP-V8-LABEL: dsp_trunc:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    add r1, r0
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r2]
-; CHECK-NODSP-V8-NEXT:    ldrh r2, [r3]
-; CHECK-NODSP-V8-NEXT:    add r0, r1
-; CHECK-NODSP-V8-NEXT:    subs r1, r2, r1
-; CHECK-NODSP-V8-NEXT:    uxth r3, r0
-; CHECK-NODSP-V8-NEXT:    uxth r2, r1
-; CHECK-NODSP-V8-NEXT:    cmp r3, r2
-; CHECK-NODSP-V8-NEXT:    it lo
-; CHECK-NODSP-V8-NEXT:    movlo r0, r1
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: dsp_trunc:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrh r2, [r2]
-; CHECK-NODSP-V7-NEXT:    add r1, r0
-; CHECK-NODSP-V7-NEXT:    ldrh r3, [r3]
-; CHECK-NODSP-V7-NEXT:    adds r0, r2, r1
-; CHECK-NODSP-V7-NEXT:    subs r1, r3, r1
-; CHECK-NODSP-V7-NEXT:    uxth r3, r0
-; CHECK-NODSP-V7-NEXT:    uxth r2, r1
-; CHECK-NODSP-V7-NEXT:    cmp r3, r2
-; CHECK-NODSP-V7-NEXT:    it lo
-; CHECK-NODSP-V7-NEXT:    movlo r0, r1
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: dsp_trunc:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    add r0, r1
-; CHECK-DSP-NEXT:    ldrh r1, [r3]
-; CHECK-DSP-NEXT:    ldrh r2, [r2]
-; CHECK-DSP-NEXT:    subs r1, r1, r0
-; CHECK-DSP-NEXT:    add r0, r2
-; CHECK-DSP-NEXT:    uxth r3, r1
-; CHECK-DSP-NEXT:    uxth r2, r0
-; CHECK-DSP-NEXT:    cmp r2, r3
-; CHECK-DSP-NEXT:    it lo
-; CHECK-DSP-NEXT:    movlo r0, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: dsp_trunc:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    add r0, r1
-; CHECK-DSP-IMM-NEXT:    movs r1, #0
-; CHECK-DSP-IMM-NEXT:    uxth r0, r0
-; CHECK-DSP-IMM-NEXT:    usub16 r1, r1, r0
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r2]
-; CHECK-DSP-IMM-NEXT:    ldrh r3, [r3]
-; CHECK-DSP-IMM-NEXT:    usub16 r0, r0, r1
-; CHECK-DSP-IMM-NEXT:    uadd16 r1, r3, r1
-; CHECK-DSP-IMM-NEXT:    cmp r0, r1
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %add0 = add i32 %arg0, %arg1
-  %conv0 = trunc i32 %add0 to i16
-  %sub0 = sub i16 0, %conv0
-  %load0 = load i16, i16* %gep0, align 2
-  %load1 = load i16, i16* %gep1, align 2
-  %sub1 = sub i16 %load0, %sub0
-  %add1 = add i16 %load1, %sub0
-  %cmp = icmp ult i16 %sub1, %add1
-  %res = select i1 %cmp, i16 %add1, i16 %sub1
-  ret i16 %res
-}
-
-define i8 @trunc_i16_i8(i16* %ptr, i16 zeroext %arg0, i8 zeroext %arg1) {
-; CHECK-LABEL: trunc_i16_i8:
-; CHECK:       @ %bb.0: @ %entry
-; CHECK-NEXT:    ldrh r0, [r0]
-; CHECK-NEXT:    add r0, r1
-; CHECK-NEXT:    uxtb r0, r0
-; CHECK-NEXT:    cmp r0, r2
-; CHECK-NEXT:    it ls
-; CHECK-NEXT:    movls r0, r2
-; CHECK-NEXT:    bx lr
-entry:
-  %0 = load i16, i16* %ptr
-  %1 = add i16 %0, %arg0
-  %2 = trunc i16 %1 to i8
-  %3 = icmp ugt i8 %2, %arg1
-  %4 = select i1 %3, i8 %2, i8 %arg1
-  ret i8 %4
-}
-
-; The pass perform the transform, but a uxtb will still be inserted to handle
-; the zext to the icmp.
-define i8 @icmp_i32_zext(i8* %ptr) {
-; CHECK-NODSP-V8-LABEL: icmp_i32_zext:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrb r2, [r0], #1
-; CHECK-NODSP-V8-NEXT:    subs r1, r2, #1
-; CHECK-NODSP-V8-NEXT:    .p2align 2
-; CHECK-NODSP-V8-NEXT:  .LBB2_1: @ %body
-; CHECK-NODSP-V8-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V8-NEXT:    uxtb r3, r1
-; CHECK-NODSP-V8-NEXT:    cmp r2, r3
-; CHECK-NODSP-V8-NEXT:    itt ne
-; CHECK-NODSP-V8-NEXT:    movne r0, r1
-; CHECK-NODSP-V8-NEXT:    bxne lr
-; CHECK-NODSP-V8-NEXT:    ldrb r1, [r0, r2]
-; CHECK-NODSP-V8-NEXT:    adds r2, #1
-; CHECK-NODSP-V8-NEXT:    b .LBB2_1
-;
-; CHECK-NODSP-V7-LABEL: icmp_i32_zext:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrb r2, [r0], #1
-; CHECK-NODSP-V7-NEXT:    subs r1, r2, #1
-; CHECK-NODSP-V7-NEXT:  .LBB2_1: @ %body
-; CHECK-NODSP-V7-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V7-NEXT:    uxtb r3, r1
-; CHECK-NODSP-V7-NEXT:    cmp r2, r3
-; CHECK-NODSP-V7-NEXT:    itt ne
-; CHECK-NODSP-V7-NEXT:    movne r0, r1
-; CHECK-NODSP-V7-NEXT:    bxne lr
-; CHECK-NODSP-V7-NEXT:    ldrb r1, [r0, r2]
-; CHECK-NODSP-V7-NEXT:    adds r2, #1
-; CHECK-NODSP-V7-NEXT:    b .LBB2_1
-;
-; CHECK-DSP-LABEL: icmp_i32_zext:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrb r2, [r0], #1
-; CHECK-DSP-NEXT:    subs r1, r2, #1
-; CHECK-DSP-NEXT:  .LBB2_1: @ %body
-; CHECK-DSP-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-NEXT:    uxtb r3, r1
-; CHECK-DSP-NEXT:    cmp r2, r3
-; CHECK-DSP-NEXT:    itt ne
-; CHECK-DSP-NEXT:    movne r0, r1
-; CHECK-DSP-NEXT:    bxne lr
-; CHECK-DSP-NEXT:    ldrb r1, [r0, r2]
-; CHECK-DSP-NEXT:    adds r2, #1
-; CHECK-DSP-NEXT:    b .LBB2_1
-;
-; CHECK-DSP-IMM-LABEL: icmp_i32_zext:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrb r2, [r0], #1
-; CHECK-DSP-IMM-NEXT:    subs r1, r2, #1
-; CHECK-DSP-IMM-NEXT:  .LBB2_1: @ %body
-; CHECK-DSP-IMM-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-IMM-NEXT:    uxtb r3, r1
-; CHECK-DSP-IMM-NEXT:    cmp r2, r3
-; CHECK-DSP-IMM-NEXT:    bne .LBB2_3
-; CHECK-DSP-IMM-NEXT:  @ %bb.2: @ %if.end
-; CHECK-DSP-IMM-NEXT:    @ in Loop: Header=BB2_1 Depth=1
-; CHECK-DSP-IMM-NEXT:    ldrb r1, [r0, r2]
-; CHECK-DSP-IMM-NEXT:    adds r2, #1
-; CHECK-DSP-IMM-NEXT:    b .LBB2_1
-; CHECK-DSP-IMM-NEXT:  .LBB2_3: @ %exit
-; CHECK-DSP-IMM-NEXT:    mov r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %gep = getelementptr inbounds i8, i8* %ptr, i32 0
-  %0 = load i8, i8* %gep, align 1
-  %1 = sub nuw nsw i8 %0, 1
-  %conv44 = zext i8 %0 to i32
-  br label %preheader
-
-preheader:
-  br label %body
-
-body:
-  %2 = phi i8 [ %1, %preheader ], [ %3, %if.end ]
-  %si.0274 = phi i32 [ %conv44, %preheader ], [ %inc, %if.end ]
-  %conv51266 = zext i8 %2 to i32
-  %cmp52267 = icmp eq i32 %si.0274, %conv51266
-  br i1 %cmp52267, label %if.end, label %exit
-
-if.end:
-  %inc = add i32 %si.0274, 1
-  %gep1 = getelementptr inbounds i8, i8* %ptr, i32 %inc
-  %3 = load i8, i8* %gep1, align 1
-  br label %body
-
-exit:
-  ret i8 %2
-}
-
-; Won't don't handle sext
-define i32 @icmp_sext_zext_store_i8_i16() {
-; CHECK-NODSP-V8-LABEL: icmp_sext_zext_store_i8_i16:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    movw r0, :lower16:d_uch
-; CHECK-NODSP-V8-NEXT:    movt r0, :upper16:d_uch
-; CHECK-NODSP-V8-NEXT:    ldrb r1, [r0, #2]
-; CHECK-NODSP-V8-NEXT:    movw r0, :lower16:d_sh
-; CHECK-NODSP-V8-NEXT:    movt r0, :upper16:d_sh
-; CHECK-NODSP-V8-NEXT:    ldrsh.w r0, [r0, #4]
-; CHECK-NODSP-V8-NEXT:    movw r2, :lower16:sh1
-; CHECK-NODSP-V8-NEXT:    subs r0, r1, r0
-; CHECK-NODSP-V8-NEXT:    clz r0, r0
-; CHECK-NODSP-V8-NEXT:    movt r2, :upper16:sh1
-; CHECK-NODSP-V8-NEXT:    lsrs r0, r0, #5
-; CHECK-NODSP-V8-NEXT:    strh r1, [r2]
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: icmp_sext_zext_store_i8_i16:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    movw r0, :lower16:d_sh
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:d_uch
-; CHECK-NODSP-V7-NEXT:    movt r0, :upper16:d_sh
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:d_uch
-; CHECK-NODSP-V7-NEXT:    ldrb r1, [r1, #2]
-; CHECK-NODSP-V7-NEXT:    movw r2, :lower16:sh1
-; CHECK-NODSP-V7-NEXT:    ldrsh.w r0, [r0, #4]
-; CHECK-NODSP-V7-NEXT:    movt r2, :upper16:sh1
-; CHECK-NODSP-V7-NEXT:    strh r1, [r2]
-; CHECK-NODSP-V7-NEXT:    subs r0, r1, r0
-; CHECK-NODSP-V7-NEXT:    clz r0, r0
-; CHECK-NODSP-V7-NEXT:    lsrs r0, r0, #5
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: icmp_sext_zext_store_i8_i16:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    movw r0, :lower16:d_uch
-; CHECK-DSP-NEXT:    movw r1, :lower16:sh1
-; CHECK-DSP-NEXT:    movt r0, :upper16:d_uch
-; CHECK-DSP-NEXT:    movt r1, :upper16:sh1
-; CHECK-DSP-NEXT:    ldrb r0, [r0, #2]
-; CHECK-DSP-NEXT:    strh r0, [r1]
-; CHECK-DSP-NEXT:    movw r1, :lower16:d_sh
-; CHECK-DSP-NEXT:    movt r1, :upper16:d_sh
-; CHECK-DSP-NEXT:    ldrsh.w r1, [r1, #4]
-; CHECK-DSP-NEXT:    subs r0, r0, r1
-; CHECK-DSP-NEXT:    clz r0, r0
-; CHECK-DSP-NEXT:    lsrs r0, r0, #5
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: icmp_sext_zext_store_i8_i16:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    movw r0, :lower16:d_sh
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:d_uch
-; CHECK-DSP-IMM-NEXT:    movt r0, :upper16:d_sh
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:d_uch
-; CHECK-DSP-IMM-NEXT:    ldrb r1, [r1, #2]
-; CHECK-DSP-IMM-NEXT:    movw r2, :lower16:sh1
-; CHECK-DSP-IMM-NEXT:    ldrsh.w r0, [r0, #4]
-; CHECK-DSP-IMM-NEXT:    movt r2, :upper16:sh1
-; CHECK-DSP-IMM-NEXT:    strh r1, [r2]
-; CHECK-DSP-IMM-NEXT:    subs r0, r1, r0
-; CHECK-DSP-IMM-NEXT:    clz r0, r0
-; CHECK-DSP-IMM-NEXT:    lsrs r0, r0, #5
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i8, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @d_uch, i32 0, i32 2), align 1
-  %conv = zext i8 %0 to i16
-  store i16 %conv, i16* @sh1, align 2
-  %conv1 = zext i8 %0 to i32
-  %1 = load i16, i16* getelementptr inbounds ([16 x i16], [16 x i16]* @d_sh, i32 0, i32 2), align 2
-  %conv2 = sext i16 %1 to i32
-  %cmp = icmp eq i32 %conv1, %conv2
-  %conv3 = zext i1 %cmp to i32
-  ret i32 %conv3
-}
-
-define i1 @or_icmp_ugt(i32 %arg, i8* %ptr) {
-; CHECK-NODSP-V8-LABEL: or_icmp_ugt:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrb r1, [r1]
-; CHECK-NODSP-V8-NEXT:    adds r2, r1, #3
-; CHECK-NODSP-V8-NEXT:    subs.w r0, r0, r2, lsl #1
-; CHECK-NODSP-V8-NEXT:    it ne
-; CHECK-NODSP-V8-NEXT:    movne r0, #1
-; CHECK-NODSP-V8-NEXT:    subs r1, #1
-; CHECK-NODSP-V8-NEXT:    movs r2, #0
-; CHECK-NODSP-V8-NEXT:    cmp r1, #3
-; CHECK-NODSP-V8-NEXT:    it hi
-; CHECK-NODSP-V8-NEXT:    movhi r2, #1
-; CHECK-NODSP-V8-NEXT:    orrs r0, r2
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: or_icmp_ugt:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrb r1, [r1]
-; CHECK-NODSP-V7-NEXT:    adds r2, r1, #3
-; CHECK-NODSP-V7-NEXT:    subs r1, #1
-; CHECK-NODSP-V7-NEXT:    subs.w r0, r0, r2, lsl #1
-; CHECK-NODSP-V7-NEXT:    mov.w r2, #0
-; CHECK-NODSP-V7-NEXT:    it ne
-; CHECK-NODSP-V7-NEXT:    movne r0, #1
-; CHECK-NODSP-V7-NEXT:    cmp r1, #3
-; CHECK-NODSP-V7-NEXT:    it hi
-; CHECK-NODSP-V7-NEXT:    movhi r2, #1
-; CHECK-NODSP-V7-NEXT:    orrs r0, r2
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: or_icmp_ugt:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrb r1, [r1]
-; CHECK-DSP-NEXT:    adds r2, r1, #3
-; CHECK-DSP-NEXT:    subs r1, #1
-; CHECK-DSP-NEXT:    subs.w r0, r0, r2, lsl #1
-; CHECK-DSP-NEXT:    mov.w r2, #0
-; CHECK-DSP-NEXT:    it ne
-; CHECK-DSP-NEXT:    movne r0, #1
-; CHECK-DSP-NEXT:    cmp r1, #3
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movhi r2, #1
-; CHECK-DSP-NEXT:    orrs r0, r2
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: or_icmp_ugt:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrb r1, [r1]
-; CHECK-DSP-IMM-NEXT:    adds r2, r1, #3
-; CHECK-DSP-IMM-NEXT:    subs.w r0, r0, r2, lsl #1
-; CHECK-DSP-IMM-NEXT:    it ne
-; CHECK-DSP-IMM-NEXT:    movne r0, #1
-; CHECK-DSP-IMM-NEXT:    subs r1, #1
-; CHECK-DSP-IMM-NEXT:    movs r2, #0
-; CHECK-DSP-IMM-NEXT:    cmp r1, #3
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r2, #1
-; CHECK-DSP-IMM-NEXT:    orrs r0, r2
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i8, i8* %ptr
-  %1 = zext i8 %0 to i32
-  %mul = shl nuw nsw i32 %1, 1
-  %add0 = add nuw nsw i32 %mul, 6
-  %cmp0 = icmp ne i32 %arg, %add0
-  %add1 = add i8 %0, -1
-  %cmp1 = icmp ugt i8 %add1, 3
-  %or = or i1 %cmp0, %cmp1
-  ret i1 %or
-}
-
-; We currently only handle truncs as sinks, so a uxt will still be needed for
-; the icmp ugt instruction.
-define void @urem_trunc_icmps(i16** %in, i32* %g, i32* %k) {
-; CHECK-NODSP-V8-LABEL: urem_trunc_icmps:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldr r0, [r0]
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    cbz r0, .LBB5_3
-; CHECK-NODSP-V8-NEXT:  @ %bb.1: @ %cond.false.i
-; CHECK-NODSP-V8-NEXT:    movs r3, #5
-; CHECK-NODSP-V8-NEXT:    udiv r3, r3, r0
-; CHECK-NODSP-V8-NEXT:    muls r0, r3, r0
-; CHECK-NODSP-V8-NEXT:    rsb.w r0, r0, #5
-; CHECK-NODSP-V8-NEXT:    .p2align 2
-; CHECK-NODSP-V8-NEXT:  .LBB5_2: @ %body
-; CHECK-NODSP-V8-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V8-NEXT:    uxtb r3, r0
-; CHECK-NODSP-V8-NEXT:    cmp r3, #7
-; CHECK-NODSP-V8-NEXT:    mov.w r3, #0
-; CHECK-NODSP-V8-NEXT:    it hi
-; CHECK-NODSP-V8-NEXT:    movhi r3, #1
-; CHECK-NODSP-V8-NEXT:    str r3, [r1]
-; CHECK-NODSP-V8-NEXT:    ldr r3, [r2]
-; CHECK-NODSP-V8-NEXT:    cmp r3, #0
-; CHECK-NODSP-V8-NEXT:    it ne
-; CHECK-NODSP-V8-NEXT:    bxne lr
-; CHECK-NODSP-V8-NEXT:    adds r0, #1
-; CHECK-NODSP-V8-NEXT:    b .LBB5_2
-; CHECK-NODSP-V8-NEXT:  .LBB5_3: @ %exit
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: urem_trunc_icmps:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r4, r5, r7, lr}
-; CHECK-NODSP-V7-NEXT:    push {r4, r5, r7, lr}
-; CHECK-NODSP-V7-NEXT:    ldr r0, [r0]
-; CHECK-NODSP-V7-NEXT:    mov r5, r1
-; CHECK-NODSP-V7-NEXT:    ldrh r1, [r0]
-; CHECK-NODSP-V7-NEXT:    cbz r1, .LBB5_4
-; CHECK-NODSP-V7-NEXT:  @ %bb.1: @ %cond.false.i
-; CHECK-NODSP-V7-NEXT:    movs r0, #5
-; CHECK-NODSP-V7-NEXT:    mov r4, r2
-; CHECK-NODSP-V7-NEXT:    bl __aeabi_uidivmod
-; CHECK-NODSP-V7-NEXT:  .LBB5_2: @ %body
-; CHECK-NODSP-V7-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r1
-; CHECK-NODSP-V7-NEXT:    cmp r0, #7
-; CHECK-NODSP-V7-NEXT:    mov.w r0, #0
-; CHECK-NODSP-V7-NEXT:    it hi
-; CHECK-NODSP-V7-NEXT:    movhi r0, #1
-; CHECK-NODSP-V7-NEXT:    str r0, [r5]
-; CHECK-NODSP-V7-NEXT:    ldr r0, [r4]
-; CHECK-NODSP-V7-NEXT:    cbnz r0, .LBB5_4
-; CHECK-NODSP-V7-NEXT:  @ %bb.3: @ %for.inc
-; CHECK-NODSP-V7-NEXT:    @ in Loop: Header=BB5_2 Depth=1
-; CHECK-NODSP-V7-NEXT:    adds r1, #1
-; CHECK-NODSP-V7-NEXT:    b .LBB5_2
-; CHECK-NODSP-V7-NEXT:  .LBB5_4: @ %exit
-; CHECK-NODSP-V7-NEXT:    pop {r4, r5, r7, pc}
-;
-; CHECK-DSP-LABEL: urem_trunc_icmps:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldr r0, [r0]
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    cbz r0, .LBB5_3
-; CHECK-DSP-NEXT:  @ %bb.1: @ %cond.false.i
-; CHECK-DSP-NEXT:    movs r3, #5
-; CHECK-DSP-NEXT:    udiv r3, r3, r0
-; CHECK-DSP-NEXT:    muls r0, r3, r0
-; CHECK-DSP-NEXT:    rsb.w r0, r0, #5
-; CHECK-DSP-NEXT:  .LBB5_2: @ %body
-; CHECK-DSP-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-NEXT:    uxtb r3, r0
-; CHECK-DSP-NEXT:    cmp r3, #7
-; CHECK-DSP-NEXT:    mov.w r3, #0
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movhi r3, #1
-; CHECK-DSP-NEXT:    str r3, [r1]
-; CHECK-DSP-NEXT:    ldr r3, [r2]
-; CHECK-DSP-NEXT:    cmp r3, #0
-; CHECK-DSP-NEXT:    it ne
-; CHECK-DSP-NEXT:    bxne lr
-; CHECK-DSP-NEXT:    adds r0, #1
-; CHECK-DSP-NEXT:    b .LBB5_2
-; CHECK-DSP-NEXT:  .LBB5_3: @ %exit
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: urem_trunc_icmps:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldr r0, [r0]
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    cbz r0, .LBB5_4
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %cond.false.i
-; CHECK-DSP-IMM-NEXT:    movs r3, #5
-; CHECK-DSP-IMM-NEXT:    udiv r3, r3, r0
-; CHECK-DSP-IMM-NEXT:    muls r0, r3, r0
-; CHECK-DSP-IMM-NEXT:    rsb.w r0, r0, #5
-; CHECK-DSP-IMM-NEXT:  .LBB5_2: @ %body
-; CHECK-DSP-IMM-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-IMM-NEXT:    uxtb r3, r0
-; CHECK-DSP-IMM-NEXT:    cmp r3, #7
-; CHECK-DSP-IMM-NEXT:    mov.w r3, #0
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r3, #1
-; CHECK-DSP-IMM-NEXT:    str r3, [r1]
-; CHECK-DSP-IMM-NEXT:    ldr r3, [r2]
-; CHECK-DSP-IMM-NEXT:    cbnz r3, .LBB5_4
-; CHECK-DSP-IMM-NEXT:  @ %bb.3: @ %for.inc
-; CHECK-DSP-IMM-NEXT:    @ in Loop: Header=BB5_2 Depth=1
-; CHECK-DSP-IMM-NEXT:    adds r0, #1
-; CHECK-DSP-IMM-NEXT:    b .LBB5_2
-; CHECK-DSP-IMM-NEXT:  .LBB5_4: @ %exit
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %ptr = load i16*, i16** %in, align 4
-  %ld = load i16, i16* %ptr, align 2
-  %cmp.i = icmp eq i16 %ld, 0
-  br i1 %cmp.i, label %exit, label %cond.false.i
-
-cond.false.i:
-  %rem = urem i16 5, %ld
-  %extract.t = trunc i16 %rem to i8
-  br label %body
-
-body:
-  %cond.in.i.off0 = phi i8 [ %extract.t, %cond.false.i ], [ %add, %for.inc ]
-  %cmp = icmp ugt i8 %cond.in.i.off0, 7
-  %conv5 = zext i1 %cmp to i32
-  store i32 %conv5, i32* %g, align 4
-  %.pr = load i32, i32* %k, align 4
-  %tobool13150 = icmp eq i32 %.pr, 0
-  br i1 %tobool13150, label %for.inc, label %exit
-
-for.inc:
-  %add = add nuw i8 %cond.in.i.off0, 1
-  br label %body
-
-exit:
-  ret void
-}
-
-; Check that %exp requires uxth in all cases, and will also be required to
-; promote %1 for the call - unless we can generate a uadd16.
-define i32 @zext_load_sink_call(i16* %ptr, i16 %exp) {
-; CHECK-NODSP-LABEL: zext_load_sink_call:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-NEXT:    uxth r2, r1
-; CHECK-NODSP-NEXT:    cmp r0, r2
-; CHECK-NODSP-NEXT:    itt eq
-; CHECK-NODSP-NEXT:    moveq r0, #0
-; CHECK-NODSP-NEXT:    bxeq lr
-; CHECK-NODSP-NEXT:    adds r1, #3
-; CHECK-NODSP-NEXT:    uxth r1, r1
-; CHECK-NODSP-NEXT:    b dummy
-;
-; CHECK-DSP-LABEL: zext_load_sink_call:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    uxth r2, r1
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    itt eq
-; CHECK-DSP-NEXT:    moveq r0, #0
-; CHECK-DSP-NEXT:    bxeq lr
-; CHECK-DSP-NEXT:    adds r1, #3
-; CHECK-DSP-NEXT:    uxth r1, r1
-; CHECK-DSP-NEXT:    b dummy
-;
-; CHECK-DSP-IMM-LABEL: zext_load_sink_call:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    uxth r2, r1
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    movs r1, #3
-; CHECK-DSP-IMM-NEXT:    uadd16 r1, r2, r1
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    bne .LBB6_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %exit
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB6_2: @ %if.then
-; CHECK-DSP-IMM-NEXT:    b dummy
-entry:
-  %0 = load i16, i16* %ptr, align 4
-  %1 = add i16 %exp, 3
-  %cmp = icmp eq i16 %0, %exp
-  br i1 %cmp, label %exit, label %if.then
-
-if.then:
-  %conv0 = zext i16 %0 to i32
-  %conv1 = zext i16 %1 to i32
-  %call = tail call arm_aapcs_vfpcc i32 @dummy(i32 %conv0, i32 %conv1)
-  br label %exit
-
-exit:
-  %exitval = phi i32 [ %call, %if.then ], [ 0, %entry  ]
-  ret i32 %exitval
-}
-
-define i16 @bitcast_i16(i16 zeroext %arg0, i16 zeroext %arg1) {
-; CHECK-NODSP-LABEL: bitcast_i16:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    adds r0, #1
-; CHECK-NODSP-NEXT:    movw r2, #12345
-; CHECK-NODSP-NEXT:    cmp r0, r2
-; CHECK-NODSP-NEXT:    it hi
-; CHECK-NODSP-NEXT:    movwhi r1, #32657
-; CHECK-NODSP-NEXT:    mov r0, r1
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: bitcast_i16:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    adds r0, #1
-; CHECK-DSP-NEXT:    movw r2, #12345
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movwhi r1, #32657
-; CHECK-DSP-NEXT:    mov r0, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: bitcast_i16:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    adds r2, r0, #1
-; CHECK-DSP-IMM-NEXT:    movw r0, #32657
-; CHECK-DSP-IMM-NEXT:    movw r3, #12345
-; CHECK-DSP-IMM-NEXT:    cmp r2, r3
-; CHECK-DSP-IMM-NEXT:    it ls
-; CHECK-DSP-IMM-NEXT:    movls r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %cast = bitcast i16 12345 to i16
-  %add = add nuw i16 %arg0, 1
-  %cmp = icmp ule i16 %add, %cast
-  %res = select i1 %cmp, i16 %arg1, i16 32657
-  ret i16 %res
-}
-
-define i8 @bitcast_i8(i8 zeroext %arg0, i8 zeroext %arg1) {
-; CHECK-LABEL: bitcast_i8:
-; CHECK:       @ %bb.0: @ %entry
-; CHECK-NEXT:    mvn r2, #127
-; CHECK-NEXT:    cmp.w r1, r0, lsl #1
-; CHECK-NEXT:    it ls
-; CHECK-NEXT:    movls r2, #127
-; CHECK-NEXT:    mov r0, r2
-; CHECK-NEXT:    bx lr
-entry:
-  %cast = bitcast i8 127 to i8
-  %mul = shl nuw i8 %arg0, 1
-  %cmp = icmp uge i8 %mul, %arg1
-  %res = select i1 %cmp, i8 %cast, i8 128
-  ret i8 %res
-}
-
-define i16 @bitcast_i16_minus(i16 zeroext %arg0, i16 zeroext %arg1) {
-; CHECK-NODSP-LABEL: bitcast_i16_minus:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    eor r2, r0, #7
-; CHECK-NODSP-NEXT:    movw r0, #32657
-; CHECK-NODSP-NEXT:    cmp r2, r1
-; CHECK-NODSP-NEXT:    itt eq
-; CHECK-NODSP-NEXT:    movweq r0, #53191
-; CHECK-NODSP-NEXT:    movteq r0, #65535
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: bitcast_i16_minus:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    eor r2, r0, #7
-; CHECK-DSP-NEXT:    movw r0, #32657
-; CHECK-DSP-NEXT:    cmp r2, r1
-; CHECK-DSP-NEXT:    itt eq
-; CHECK-DSP-NEXT:    movweq r0, #53191
-; CHECK-DSP-NEXT:    movteq r0, #65535
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: bitcast_i16_minus:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    eor r2, r0, #7
-; CHECK-DSP-IMM-NEXT:    movw r0, #32657
-; CHECK-DSP-IMM-NEXT:    cmp r2, r1
-; CHECK-DSP-IMM-NEXT:    it eq
-; CHECK-DSP-IMM-NEXT:    movweq r0, #53191
-; CHECK-DSP-IMM-NEXT:    it eq
-; CHECK-DSP-IMM-NEXT:    movteq r0, #65535
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %cast = bitcast i16 -12345 to i16
-  %xor = xor i16 %arg0, 7
-  %cmp = icmp eq i16 %xor, %arg1
-  %res = select i1 %cmp, i16 %cast, i16 32657
-  ret i16 %res
-}
-
-define i8 @bitcast_i8_minus(i8 zeroext %arg0, i8 zeroext %arg1) {
-; CHECK-LABEL: bitcast_i8_minus:
-; CHECK:       @ %bb.0: @ %entry
-; CHECK-NEXT:    and r2, r0, #3
-; CHECK-NEXT:    mvn r0, #127
-; CHECK-NEXT:    cmp r2, r1
-; CHECK-NEXT:    it ne
-; CHECK-NEXT:    mvnne r0, #126
-; CHECK-NEXT:    bx lr
-entry:
-  %cast = bitcast i8 -127 to i8
-  %and = and i8 %arg0, 3
-  %cmp = icmp ne i8 %and, %arg1
-  %res = select i1 %cmp, i8 %cast, i8 128
-  ret i8 %res
-}
-
-declare i32 @dummy(i32, i32)
-
- at d_uch = hidden local_unnamed_addr global [16 x i8] zeroinitializer, align 1
- at sh1 = hidden local_unnamed_addr global i16 0, align 2
- at d_sh = hidden local_unnamed_addr global [16 x i16] zeroinitializer, align 2
-
-define i8* @two_stage_zext_trunc_mix(i32* %this, i32 %__pos1, i32 %__n1, i32** %__str, i32 %__pos2, i32 %__n2) {
-; CHECK-NODSP-V8-LABEL: two_stage_zext_trunc_mix:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldr.w r12, [sp]
-; CHECK-NODSP-V8-NEXT:    ldrb r2, [r0]
-; CHECK-NODSP-V8-NEXT:    add.w r0, r3, r12
-; CHECK-NODSP-V8-NEXT:    lsls r2, r2, #31
-; CHECK-NODSP-V8-NEXT:    it eq
-; CHECK-NODSP-V8-NEXT:    addeq r0, r3, r1
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: two_stage_zext_trunc_mix:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrb r2, [r0]
-; CHECK-NODSP-V7-NEXT:    ldr.w r12, [sp]
-; CHECK-NODSP-V7-NEXT:    add.w r0, r3, r12
-; CHECK-NODSP-V7-NEXT:    lsls r2, r2, #31
-; CHECK-NODSP-V7-NEXT:    it eq
-; CHECK-NODSP-V7-NEXT:    addeq r0, r3, r1
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: two_stage_zext_trunc_mix:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldr r2, [sp]
-; CHECK-DSP-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-NEXT:    add r2, r3
-; CHECK-DSP-NEXT:    lsls r0, r0, #31
-; CHECK-DSP-NEXT:    it eq
-; CHECK-DSP-NEXT:    addeq r2, r3, r1
-; CHECK-DSP-NEXT:    mov r0, r2
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: two_stage_zext_trunc_mix:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldr.w r12, [sp]
-; CHECK-DSP-IMM-NEXT:    ldrb r2, [r0]
-; CHECK-DSP-IMM-NEXT:    adds r0, r3, r1
-; CHECK-DSP-IMM-NEXT:    add r12, r3
-; CHECK-DSP-IMM-NEXT:    lsls r1, r2, #31
-; CHECK-DSP-IMM-NEXT:    it ne
-; CHECK-DSP-IMM-NEXT:    movne r0, r12
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %__size_.i.i.i.i = bitcast i32** %__str to i8*
-  %0 = load i8, i8* %__size_.i.i.i.i, align 4
-  %1 = and i8 %0, 1
-  %tobool.i.i.i.i = icmp eq i8 %1, 0
-  %__size_.i5.i.i = getelementptr inbounds i32*, i32** %__str, i32 %__n1
-  %cast = bitcast i32** %__size_.i5.i.i to i32*
-  %2 = load i32, i32* %cast, align 4
-  %3 = lshr i8 %0, 1
-  %4 = zext i8 %3 to i32
-  %cond.i.i = select i1 %tobool.i.i.i.i, i32 %4, i32 %2
-  %__size_.i.i.i.i.i = bitcast i32* %this to i8*
-  %5 = load i8, i8* %__size_.i.i.i.i.i, align 4
-  %6 = and i8 %5, 1
-  %tobool.i.i.i.i.i = icmp eq i8 %6, 0
-  %7 = getelementptr inbounds i8, i8* %__size_.i.i.i.i, i32 %__pos1
-  %8 = getelementptr inbounds i8, i8* %__size_.i.i.i.i, i32 %__pos2
-  %res = select i1 %tobool.i.i.i.i.i,  i8* %7, i8* %8
-  ret i8* %res
-}
-
-define i8 @search_through_zext_1(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c) {
-; CHECK-NODSP-V8-LABEL: search_through_zext_1:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    subs r3, r1, r0
-; CHECK-NODSP-V8-NEXT:    add.w r12, r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp r3, r2
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp r12, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: search_through_zext_1:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    subs r3, r1, r0
-; CHECK-NODSP-V7-NEXT:    cmp r3, r2
-; CHECK-NODSP-V7-NEXT:    mov r3, r1
-; CHECK-NODSP-V7-NEXT:    it hi
-; CHECK-NODSP-V7-NEXT:    movhi r3, r0
-; CHECK-NODSP-V7-NEXT:    add r0, r1
-; CHECK-NODSP-V7-NEXT:    cmp r0, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r3, #0
-; CHECK-NODSP-V7-NEXT:    mov r0, r3
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: search_through_zext_1:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    subs r3, r1, r0
-; CHECK-DSP-NEXT:    cmp r3, r2
-; CHECK-DSP-NEXT:    mov r3, r1
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movhi r3, r0
-; CHECK-DSP-NEXT:    add r0, r1
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r3, #0
-; CHECK-DSP-NEXT:    mov r0, r3
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: search_through_zext_1:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    subs r3, r1, r0
-; CHECK-DSP-IMM-NEXT:    cmp r3, r2
-; CHECK-DSP-IMM-NEXT:    mov r3, r1
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r3, r0
-; CHECK-DSP-IMM-NEXT:    add r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    cmp r1, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r3
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %add = add nuw i8 %a, %b
-  %conv = zext i8 %add to i16
-  %cmp = icmp ult i16 %conv, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %sub = sub nuw i8 %b, %a
-  %conv2 = zext i8 %sub to i16
-  %cmp2 = icmp ugt i16 %conv2, %c
-  %res = select i1 %cmp2, i8 %a, i8 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
-  ret i8 %retval
-}
-
-; TODO: We should be able to remove the uxtb here. The transform fails because
-; the icmp ugt uses an i32, which is too large... but this doesn't matter
-; because it won't be writing a large value to a register as a result.
-define i8 @search_through_zext_2(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c, i32 %d) {
-; CHECK-NODSP-V8-LABEL: search_through_zext_2:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    push {r7, lr}
-; CHECK-NODSP-V8-NEXT:    sub.w lr, r1, r0
-; CHECK-NODSP-V8-NEXT:    add.w r12, r0, r1
-; CHECK-NODSP-V8-NEXT:    uxtb.w lr, lr
-; CHECK-NODSP-V8-NEXT:    uxtb.w r12, r12
-; CHECK-NODSP-V8-NEXT:    cmp lr, r3
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp r12, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    pop {r7, pc}
-;
-; CHECK-NODSP-V7-LABEL: search_through_zext_2:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    sub.w r12, r1, r0
-; CHECK-NODSP-V7-NEXT:    uxtb.w r12, r12
-; CHECK-NODSP-V7-NEXT:    cmp r12, r3
-; CHECK-NODSP-V7-NEXT:    mov r3, r1
-; CHECK-NODSP-V7-NEXT:    it hi
-; CHECK-NODSP-V7-NEXT:    movhi r3, r0
-; CHECK-NODSP-V7-NEXT:    add r0, r1
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r0
-; CHECK-NODSP-V7-NEXT:    cmp r0, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r3, #0
-; CHECK-NODSP-V7-NEXT:    mov r0, r3
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: search_through_zext_2:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    sub.w r12, r1, r0
-; CHECK-DSP-NEXT:    uxtb.w r12, r12
-; CHECK-DSP-NEXT:    cmp r12, r3
-; CHECK-DSP-NEXT:    mov r3, r1
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movhi r3, r0
-; CHECK-DSP-NEXT:    add r0, r1
-; CHECK-DSP-NEXT:    uxtb r0, r0
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r3, #0
-; CHECK-DSP-NEXT:    mov r0, r3
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: search_through_zext_2:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    sub.w r12, r1, r0
-; CHECK-DSP-IMM-NEXT:    uxtb.w r12, r12
-; CHECK-DSP-IMM-NEXT:    cmp r12, r3
-; CHECK-DSP-IMM-NEXT:    mov r3, r1
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r3, r0
-; CHECK-DSP-IMM-NEXT:    add r0, r1
-; CHECK-DSP-IMM-NEXT:    uxtb r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    cmp r1, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r3
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %add = add nuw i8 %a, %b
-  %conv = zext i8 %add to i16
-  %cmp = icmp ult i16 %conv, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %sub = sub nuw i8 %b, %a
-  %conv2 = zext i8 %sub to i32
-  %cmp2 = icmp ugt i32 %conv2, %d
-  %res = select i1 %cmp2, i8 %a, i8 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
-  ret i8 %retval
-}
-
-; TODO: We should be able to remove the uxtb here as all the calculations are
-; performed on i8s. The promotion of i8 to i16 and then the later truncation
-; results in the uxtb.
-define i8 @search_through_zext_3(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c, i32 %d) {
-; CHECK-NODSP-LABEL: search_through_zext_3:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    add.w r12, r0, r1
-; CHECK-NODSP-NEXT:    uxtb.w r12, r12
-; CHECK-NODSP-NEXT:    cmp r12, r2
-; CHECK-NODSP-NEXT:    itt hs
-; CHECK-NODSP-NEXT:    movhs r0, #0
-; CHECK-NODSP-NEXT:    bxhs lr
-; CHECK-NODSP-NEXT:    sub.w r2, r1, r12
-; CHECK-NODSP-NEXT:    uxtb r2, r2
-; CHECK-NODSP-NEXT:    cmp r2, r3
-; CHECK-NODSP-NEXT:    it ls
-; CHECK-NODSP-NEXT:    movls r0, r1
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: search_through_zext_3:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    add.w r12, r0, r1
-; CHECK-DSP-NEXT:    uxtb.w r12, r12
-; CHECK-DSP-NEXT:    cmp r12, r2
-; CHECK-DSP-NEXT:    itt hs
-; CHECK-DSP-NEXT:    movhs r0, #0
-; CHECK-DSP-NEXT:    bxhs lr
-; CHECK-DSP-NEXT:    sub.w r2, r1, r12
-; CHECK-DSP-NEXT:    uxtb r2, r2
-; CHECK-DSP-NEXT:    cmp r2, r3
-; CHECK-DSP-NEXT:    it ls
-; CHECK-DSP-NEXT:    movls r0, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: search_through_zext_3:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    add.w r12, r0, r1
-; CHECK-DSP-IMM-NEXT:    uxtb.w r12, r12
-; CHECK-DSP-IMM-NEXT:    cmp r12, r2
-; CHECK-DSP-IMM-NEXT:    bhs .LBB14_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %if.then
-; CHECK-DSP-IMM-NEXT:    sub.w r2, r1, r12
-; CHECK-DSP-IMM-NEXT:    uxtb r2, r2
-; CHECK-DSP-IMM-NEXT:    cmp r2, r3
-; CHECK-DSP-IMM-NEXT:    it ls
-; CHECK-DSP-IMM-NEXT:    movls r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB14_2:
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %add = add nuw i8 %a, %b
-  %conv = zext i8 %add to i16
-  %cmp = icmp ult i16 %conv, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %conv to i8
-  %sub = sub nuw i8 %b, %trunc
-  %conv2 = zext i8 %sub to i32
-  %cmp2 = icmp ugt i32 %conv2, %d
-  %res = select i1 %cmp2, i8 %a, i8 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
-  ret i8 %retval
-}
-
-; TODO: We should be able to remove the uxt that gets introduced for %conv2
-define i8 @search_through_zext_cmp(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c) {
-; CHECK-NODSP-V8-LABEL: search_through_zext_cmp:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    subs r3, r1, r0
-; CHECK-NODSP-V8-NEXT:    subs.w r12, r1, r0
-; CHECK-NODSP-V8-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V8-NEXT:    it ne
-; CHECK-NODSP-V8-NEXT:    movne.w r12, #1
-; CHECK-NODSP-V8-NEXT:    cmp r3, r2
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp r12, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: search_through_zext_cmp:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    subs r3, r1, r0
-; CHECK-NODSP-V7-NEXT:    subs.w r12, r1, r0
-; CHECK-NODSP-V7-NEXT:    it ne
-; CHECK-NODSP-V7-NEXT:    movne.w r12, #1
-; CHECK-NODSP-V7-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V7-NEXT:    cmp r3, r2
-; CHECK-NODSP-V7-NEXT:    it ls
-; CHECK-NODSP-V7-NEXT:    movls r0, r1
-; CHECK-NODSP-V7-NEXT:    cmp r12, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r0, #0
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: search_through_zext_cmp:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    subs r3, r1, r0
-; CHECK-DSP-NEXT:    subs.w r12, r1, r0
-; CHECK-DSP-NEXT:    uxtb r3, r3
-; CHECK-DSP-NEXT:    it ne
-; CHECK-DSP-NEXT:    movne.w r12, #1
-; CHECK-DSP-NEXT:    cmp r3, r2
-; CHECK-DSP-NEXT:    it ls
-; CHECK-DSP-NEXT:    movls r0, r1
-; CHECK-DSP-NEXT:    cmp r12, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r0, #0
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: search_through_zext_cmp:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    subs.w r12, r1, r0
-; CHECK-DSP-IMM-NEXT:    it ne
-; CHECK-DSP-IMM-NEXT:    movne.w r12, #1
-; CHECK-DSP-IMM-NEXT:    subs r3, r1, r0
-; CHECK-DSP-IMM-NEXT:    uxtb r3, r3
-; CHECK-DSP-IMM-NEXT:    cmp r3, r2
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    cmp r12, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %cmp = icmp ne i8 %a, %b
-  %conv = zext i1 %cmp to i16
-  %cmp1 = icmp ult i16 %conv, %c
-  br i1 %cmp1, label %if.then, label %if.end
-
-if.then:
-  %sub = sub nuw i8 %b, %a
-  %conv2 = zext i8 %sub to i16
-  %cmp3 = icmp ugt i16 %conv2, %c
-  %res = select i1 %cmp3, i8 %a, i8 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
-  ret i8 %retval
-}
-
-define i8 @search_through_zext_load(i8* %a, i8 zeroext %b, i16 zeroext %c) {
-; CHECK-NODSP-V8-LABEL: search_through_zext_load:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrb r3, [r0]
-; CHECK-NODSP-V8-NEXT:    mov r0, r1
-; CHECK-NODSP-V8-NEXT:    subs r1, r1, r3
-; CHECK-NODSP-V8-NEXT:    cmp r1, r2
-; CHECK-NODSP-V8-NEXT:    it hi
-; CHECK-NODSP-V8-NEXT:    movhi r0, r3
-; CHECK-NODSP-V8-NEXT:    cmp r3, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: search_through_zext_load:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V7-NEXT:    subs r3, r1, r0
-; CHECK-NODSP-V7-NEXT:    cmp r3, r2
-; CHECK-NODSP-V7-NEXT:    it hi
-; CHECK-NODSP-V7-NEXT:    movhi r1, r0
-; CHECK-NODSP-V7-NEXT:    cmp r0, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r1, #0
-; CHECK-NODSP-V7-NEXT:    mov r0, r1
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: search_through_zext_load:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-NEXT:    subs r3, r1, r0
-; CHECK-DSP-NEXT:    cmp r3, r2
-; CHECK-DSP-NEXT:    it hi
-; CHECK-DSP-NEXT:    movhi r1, r0
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r1, #0
-; CHECK-DSP-NEXT:    mov r0, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: search_through_zext_load:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrb r3, [r0]
-; CHECK-DSP-IMM-NEXT:    subs r0, r1, r3
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r1, r3
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    cmp r3, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r1
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %load = load i8, i8* %a
-  %conv = zext i8 %load to i16
-  %cmp1 = icmp ult i16 %conv, %c
-  br i1 %cmp1, label %if.then, label %if.end
-
-if.then:
-  %sub = sub nuw i8 %b, %load
-  %conv2 = zext i8 %sub to i16
-  %cmp3 = icmp ugt i16 %conv2, %c
-  %res = select i1 %cmp3, i8 %load, i8 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
-  ret i8 %retval
-}
-
-define i16 @trunc_sink_less_than_cmp(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d) {
-; CHECK-NODSP-V8-LABEL: trunc_sink_less_than_cmp:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    push {r7, lr}
-; CHECK-NODSP-V8-NEXT:    sub.w r12, r1, r0
-; CHECK-NODSP-V8-NEXT:    adds r3, #1
-; CHECK-NODSP-V8-NEXT:    uxth.w lr, r12
-; CHECK-NODSP-V8-NEXT:    uxtb.w r12, r12
-; CHECK-NODSP-V8-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V8-NEXT:    cmp r12, r3
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp lr, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    pop {r7, pc}
-;
-; CHECK-NODSP-V7-LABEL: trunc_sink_less_than_cmp:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r7, lr}
-; CHECK-NODSP-V7-NEXT:    push {r7, lr}
-; CHECK-NODSP-V7-NEXT:    adds r3, #1
-; CHECK-NODSP-V7-NEXT:    sub.w r12, r1, r0
-; CHECK-NODSP-V7-NEXT:    uxtb.w lr, r12
-; CHECK-NODSP-V7-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V7-NEXT:    cmp lr, r3
-; CHECK-NODSP-V7-NEXT:    it ls
-; CHECK-NODSP-V7-NEXT:    movls r0, r1
-; CHECK-NODSP-V7-NEXT:    uxth.w r1, r12
-; CHECK-NODSP-V7-NEXT:    cmp r1, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r0, #0
-; CHECK-NODSP-V7-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-LABEL: trunc_sink_less_than_cmp:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    push {r7, lr}
-; CHECK-DSP-NEXT:    adds r3, #1
-; CHECK-DSP-NEXT:    sub.w r12, r1, r0
-; CHECK-DSP-NEXT:    uxtb.w lr, r12
-; CHECK-DSP-NEXT:    uxtb r3, r3
-; CHECK-DSP-NEXT:    cmp lr, r3
-; CHECK-DSP-NEXT:    it ls
-; CHECK-DSP-NEXT:    movls r0, r1
-; CHECK-DSP-NEXT:    uxth.w r1, r12
-; CHECK-DSP-NEXT:    cmp r1, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r0, #0
-; CHECK-DSP-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-IMM-LABEL: trunc_sink_less_than_cmp:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    push {r7, lr}
-; CHECK-DSP-IMM-NEXT:    adds r3, #1
-; CHECK-DSP-IMM-NEXT:    sub.w r12, r1, r0
-; CHECK-DSP-IMM-NEXT:    uxtb r3, r3
-; CHECK-DSP-IMM-NEXT:    uxtb.w lr, r12
-; CHECK-DSP-IMM-NEXT:    cmp lr, r3
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    uxth.w r3, r12
-; CHECK-DSP-IMM-NEXT:    cmp r3, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r1
-; CHECK-DSP-IMM-NEXT:    pop {r7, pc}
-entry:
-  %sub = sub nuw i16 %b, %a
-  %cmp = icmp ult i16 %sub, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %sub to i8
-  %add = add nuw i8 %d, 1
-  %cmp2 = icmp ugt i8 %trunc, %add
-  %res = select i1 %cmp2, i16 %a, i16 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i16 [ 0, %entry ], [ %res, %if.then ]
-  ret i16 %retval
-}
-
-; TODO: We should be able to remove the uxth introduced to handle %sub
-define i16 @trunc_sink_less_than_arith(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
-; CHECK-NODSP-V8-LABEL: trunc_sink_less_than_arith:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    push {r4, lr}
-; CHECK-NODSP-V8-NEXT:    sub.w lr, r1, r0
-; CHECK-NODSP-V8-NEXT:    ldr.w r12, [sp, #8]
-; CHECK-NODSP-V8-NEXT:    add r3, lr
-; CHECK-NODSP-V8-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V8-NEXT:    uxth.w r4, lr
-; CHECK-NODSP-V8-NEXT:    cmp r12, r3
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, r1
-; CHECK-NODSP-V8-NEXT:    cmp r4, r2
-; CHECK-NODSP-V8-NEXT:    it hs
-; CHECK-NODSP-V8-NEXT:    movhs r0, #0
-; CHECK-NODSP-V8-NEXT:    pop {r4, pc}
-;
-; CHECK-NODSP-V7-LABEL: trunc_sink_less_than_arith:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r7, lr}
-; CHECK-NODSP-V7-NEXT:    push {r7, lr}
-; CHECK-NODSP-V7-NEXT:    sub.w lr, r1, r0
-; CHECK-NODSP-V7-NEXT:    ldr.w r12, [sp, #8]
-; CHECK-NODSP-V7-NEXT:    add r3, lr
-; CHECK-NODSP-V7-NEXT:    uxtb r3, r3
-; CHECK-NODSP-V7-NEXT:    cmp r12, r3
-; CHECK-NODSP-V7-NEXT:    it ls
-; CHECK-NODSP-V7-NEXT:    movls r0, r1
-; CHECK-NODSP-V7-NEXT:    uxth.w r1, lr
-; CHECK-NODSP-V7-NEXT:    cmp r1, r2
-; CHECK-NODSP-V7-NEXT:    it hs
-; CHECK-NODSP-V7-NEXT:    movhs r0, #0
-; CHECK-NODSP-V7-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-LABEL: trunc_sink_less_than_arith:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    push {r7, lr}
-; CHECK-DSP-NEXT:    sub.w r12, r1, r0
-; CHECK-DSP-NEXT:    add r3, r12
-; CHECK-DSP-NEXT:    uxtb.w lr, r3
-; CHECK-DSP-NEXT:    ldr r3, [sp, #8]
-; CHECK-DSP-NEXT:    cmp r3, lr
-; CHECK-DSP-NEXT:    it ls
-; CHECK-DSP-NEXT:    movls r0, r1
-; CHECK-DSP-NEXT:    uxth.w r1, r12
-; CHECK-DSP-NEXT:    cmp r1, r2
-; CHECK-DSP-NEXT:    it hs
-; CHECK-DSP-NEXT:    movhs r0, #0
-; CHECK-DSP-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-IMM-LABEL: trunc_sink_less_than_arith:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    push {r7, lr}
-; CHECK-DSP-IMM-NEXT:    sub.w lr, r1, r0
-; CHECK-DSP-IMM-NEXT:    ldr.w r12, [sp, #8]
-; CHECK-DSP-IMM-NEXT:    add r3, lr
-; CHECK-DSP-IMM-NEXT:    uxtb r3, r3
-; CHECK-DSP-IMM-NEXT:    cmp r12, r3
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    uxth.w r3, lr
-; CHECK-DSP-IMM-NEXT:    cmp r3, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r1
-; CHECK-DSP-IMM-NEXT:    pop {r7, pc}
-entry:
-  %sub = sub nuw i16 %b, %a
-  %cmp = icmp ult i16 %sub, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %sub to i8
-  %add = add nuw i8 %d, %trunc
-  %cmp2 = icmp ugt i8 %e, %add
-  %res = select i1 %cmp2, i16 %a, i16 %b
-  br label %if.end
-
-if.end:
-  %retval = phi i16 [ 0, %entry ], [ %res, %if.then ]
-  ret i16 %retval
-}
-
-define i16 @trunc_sink_less_than_store(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8* %e) {
-; CHECK-NODSP-LABEL: trunc_sink_less_than_store:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    subs r0, r1, r0
-; CHECK-NODSP-NEXT:    cmp r0, r2
-; CHECK-NODSP-NEXT:    iteee hs
-; CHECK-NODSP-NEXT:    movhs r0, #0
-; CHECK-NODSP-NEXT:    ldrlo r1, [sp]
-; CHECK-NODSP-NEXT:    addlo r2, r3, r0
-; CHECK-NODSP-NEXT:    strblo r2, [r1]
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: trunc_sink_less_than_store:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    subs r0, r1, r0
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    iteee hs
-; CHECK-DSP-NEXT:    movhs r0, #0
-; CHECK-DSP-NEXT:    ldrlo r1, [sp]
-; CHECK-DSP-NEXT:    addlo r2, r3, r0
-; CHECK-DSP-NEXT:    strblo r2, [r1]
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: trunc_sink_less_than_store:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    subs r0, r1, r0
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    bhs .LBB19_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %if.then
-; CHECK-DSP-IMM-NEXT:    ldr r1, [sp]
-; CHECK-DSP-IMM-NEXT:    adds r2, r3, r0
-; CHECK-DSP-IMM-NEXT:    strb r2, [r1]
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB19_2:
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %sub = sub nuw i16 %b, %a
-  %cmp = icmp ult i16 %sub, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %sub to i8
-  %add = add nuw i8 %d, %trunc
-  store i8 %add, i8* %e
-  br label %if.end
-
-if.end:
-  %retval = phi i16 [ 0, %entry ], [ %sub, %if.then ]
-  ret i16 %retval
-}
-
-define i8 @trunc_sink_less_than_ret(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
-; CHECK-NODSP-LABEL: trunc_sink_less_than_ret:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    subs r1, r1, r0
-; CHECK-NODSP-NEXT:    movs r0, #0
-; CHECK-NODSP-NEXT:    cmp r1, r2
-; CHECK-NODSP-NEXT:    it lo
-; CHECK-NODSP-NEXT:    uxtablo r0, r3, r1
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: trunc_sink_less_than_ret:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    subs r1, r1, r0
-; CHECK-DSP-NEXT:    movs r0, #0
-; CHECK-DSP-NEXT:    cmp r1, r2
-; CHECK-DSP-NEXT:    it lo
-; CHECK-DSP-NEXT:    uxtablo r0, r3, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: trunc_sink_less_than_ret:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    subs r1, r1, r0
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    cmp r1, r2
-; CHECK-DSP-IMM-NEXT:    uxtab r3, r3, r1
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r0, r3
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %sub = sub nuw i16 %b, %a
-  %cmp = icmp ult i16 %sub, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %sub to i8
-  %add = add nuw i8 %d, %trunc
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %add, %if.then ]
-  ret i8 %retval
-}
-
-define zeroext i8 @trunc_sink_less_than_zext_ret(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
-; CHECK-NODSP-LABEL: trunc_sink_less_than_zext_ret:
-; CHECK-NODSP:       @ %bb.0: @ %entry
-; CHECK-NODSP-NEXT:    subs r0, r1, r0
-; CHECK-NODSP-NEXT:    movs r1, #0
-; CHECK-NODSP-NEXT:    cmp r0, r2
-; CHECK-NODSP-NEXT:    it lo
-; CHECK-NODSP-NEXT:    addlo r1, r3, r0
-; CHECK-NODSP-NEXT:    uxtb r0, r1
-; CHECK-NODSP-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: trunc_sink_less_than_zext_ret:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    subs r0, r1, r0
-; CHECK-DSP-NEXT:    movs r1, #0
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    it lo
-; CHECK-DSP-NEXT:    addlo r1, r3, r0
-; CHECK-DSP-NEXT:    uxtb r0, r1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: trunc_sink_less_than_zext_ret:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    subs r0, r1, r0
-; CHECK-DSP-IMM-NEXT:    adds r1, r3, r0
-; CHECK-DSP-IMM-NEXT:    movs r3, #0
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    it lo
-; CHECK-DSP-IMM-NEXT:    movlo r3, r1
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r3
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %sub = sub nuw i16 %b, %a
-  %cmp = icmp ult i16 %sub, %c
-  br i1 %cmp, label %if.then, label %if.end
-
-if.then:
-  %trunc = trunc i16 %sub to i8
-  %add = add nuw i8 %d, %trunc
-  br label %if.end
-
-if.end:
-  %retval = phi i8 [ 0, %entry ], [ %add, %if.then ]
-  ret i8 %retval
-}
-
-define i32 @bitcast_i1(i16 zeroext %a, i32 %b, i32 %c) {
-; CHECK-LABEL: bitcast_i1:
-; CHECK:       @ %bb.0: @ %entry
-; CHECK-NEXT:    ands r0, r0, #1
-; CHECK-NEXT:    it ne
-; CHECK-NEXT:    movne r0, r1
-; CHECK-NEXT:    bx lr
-entry:
-  %0 = bitcast i1 1 to i1
-  %1 = trunc i16 %a to i1
-  %cmp = icmp eq i1 %1, %0
-  br i1 %cmp, label %if.then, label %exit
-
-if.then:
-  %conv = zext i1 %0 to i16
-  %conv1 = zext i1 %1 to i16
-  %cmp1 = icmp uge i16 %conv, %conv1
-  %select = select i1 %cmp1, i32 %b, i32 %c
-  br label %exit
-
-exit:
-  %retval = phi i32 [ %select, %if.then ], [ 0, %entry ]
-  ret i32 %retval
-}
-
-define void @search_back_through_trunc(i8* %a, i8* %b, i8* %c, i8* %d, i16* %e) {
-; CHECK-NODSP-V8-LABEL: search_back_through_trunc:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    push {r7, lr}
-; CHECK-NODSP-V8-NEXT:    ldrb.w r12, [r0]
-; CHECK-NODSP-V8-NEXT:    ldrb.w lr, [r1]
-; CHECK-NODSP-V8-NEXT:    ldrb r1, [r2]
-; CHECK-NODSP-V8-NEXT:    ldrb r0, [r3]
-; CHECK-NODSP-V8-NEXT:    orr.w r12, lr, r12, lsl #8
-; CHECK-NODSP-V8-NEXT:    orr.w r0, r0, r1, lsl #8
-; CHECK-NODSP-V8-NEXT:    cmp r12, r0
-; CHECK-NODSP-V8-NEXT:    beq .LBB23_2
-; CHECK-NODSP-V8-NEXT:  @ %bb.1: @ %if.else136
-; CHECK-NODSP-V8-NEXT:    ldr r0, [sp, #8]
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    uxtb.w lr, r0
-; CHECK-NODSP-V8-NEXT:    lsrs r1, r0, #8
-; CHECK-NODSP-V8-NEXT:  .LBB23_2: @ %if.end183
-; CHECK-NODSP-V8-NEXT:    strb r1, [r2]
-; CHECK-NODSP-V8-NEXT:    strb.w lr, [r3]
-; CHECK-NODSP-V8-NEXT:    pop {r7, pc}
-;
-; CHECK-NODSP-V7-LABEL: search_back_through_trunc:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r4, lr}
-; CHECK-NODSP-V7-NEXT:    push {r4, lr}
-; CHECK-NODSP-V7-NEXT:    ldrb r4, [r0]
-; CHECK-NODSP-V7-NEXT:    ldrb.w r12, [r2]
-; CHECK-NODSP-V7-NEXT:    ldrb r0, [r1]
-; CHECK-NODSP-V7-NEXT:    ldrb.w lr, [r3]
-; CHECK-NODSP-V7-NEXT:    orr.w r4, r0, r4, lsl #8
-; CHECK-NODSP-V7-NEXT:    orr.w r1, lr, r12, lsl #8
-; CHECK-NODSP-V7-NEXT:    cmp r4, r1
-; CHECK-NODSP-V7-NEXT:    itttt ne
-; CHECK-NODSP-V7-NEXT:    ldrne r0, [sp, #8]
-; CHECK-NODSP-V7-NEXT:    ldrhne r0, [r0]
-; CHECK-NODSP-V7-NEXT:    lsrne.w r12, r0, #8
-; CHECK-NODSP-V7-NEXT:    uxtbne r0, r0
-; CHECK-NODSP-V7-NEXT:    strb.w r12, [r2]
-; CHECK-NODSP-V7-NEXT:    strb r0, [r3]
-; CHECK-NODSP-V7-NEXT:    pop {r4, pc}
-;
-; CHECK-DSP-LABEL: search_back_through_trunc:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    push {r4, lr}
-; CHECK-DSP-NEXT:    ldrb r4, [r0]
-; CHECK-DSP-NEXT:    ldrb r0, [r1]
-; CHECK-DSP-NEXT:    ldrb.w r12, [r2]
-; CHECK-DSP-NEXT:    ldrb.w lr, [r3]
-; CHECK-DSP-NEXT:    orr.w lr, lr, r12, lsl #8
-; CHECK-DSP-NEXT:    orr.w r1, r0, r4, lsl #8
-; CHECK-DSP-NEXT:    cmp r1, lr
-; CHECK-DSP-NEXT:    itttt ne
-; CHECK-DSP-NEXT:    ldrne r0, [sp, #8]
-; CHECK-DSP-NEXT:    ldrhne r0, [r0]
-; CHECK-DSP-NEXT:    lsrne.w r12, r0, #8
-; CHECK-DSP-NEXT:    uxtbne r0, r0
-; CHECK-DSP-NEXT:    strb.w r12, [r2]
-; CHECK-DSP-NEXT:    strb r0, [r3]
-; CHECK-DSP-NEXT:    pop {r4, pc}
-;
-; CHECK-DSP-IMM-LABEL: search_back_through_trunc:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    push {r4, lr}
-; CHECK-DSP-IMM-NEXT:    ldrb r4, [r0]
-; CHECK-DSP-IMM-NEXT:    ldrb.w r12, [r2]
-; CHECK-DSP-IMM-NEXT:    ldrb r0, [r1]
-; CHECK-DSP-IMM-NEXT:    ldrb.w lr, [r3]
-; CHECK-DSP-IMM-NEXT:    orr.w r4, r0, r4, lsl #8
-; CHECK-DSP-IMM-NEXT:    orr.w r1, lr, r12, lsl #8
-; CHECK-DSP-IMM-NEXT:    cmp r4, r1
-; CHECK-DSP-IMM-NEXT:    beq .LBB23_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %if.else136
-; CHECK-DSP-IMM-NEXT:    ldr r0, [sp, #8]
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    lsr.w r12, r0, #8
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r0
-; CHECK-DSP-IMM-NEXT:  .LBB23_2: @ %if.end183
-; CHECK-DSP-IMM-NEXT:    strb.w r12, [r2]
-; CHECK-DSP-IMM-NEXT:    strb r0, [r3]
-; CHECK-DSP-IMM-NEXT:    pop {r4, pc}
-entry:
-  %0 = load i8, i8* %a, align 1
-  %conv106 = zext i8 %0 to i16
-  %shl = shl nuw i16 %conv106, 8
-  %1 = load i8, i8* %b, align 1
-  %conv108 = zext i8 %1 to i16
-  %or109 = or i16 %shl, %conv108
-  %2 = load i8, i8* %c, align 1
-  %conv119 = zext i8 %2 to i16
-  %shl120 = shl nuw i16 %conv119, 8
-  %3 = load i8, i8* %d, align 1
-  %conv122 = zext i8 %3 to i16
-  %or123 = or i16 %shl120, %conv122
-  %cmp133 = icmp eq i16 %or109, %or123
-  br i1 %cmp133, label %if.end183, label %if.else136
-
-if.else136:
-  %4 = load i16, i16* %e, align 2
-  %extract.t854 = trunc i16 %4 to i8
-  %extract856 = lshr i16 %4, 8
-  %extract.t857 = trunc i16 %extract856 to i8
-  br label %if.end183
-
-if.end183:
-  %w.0.off0 = phi i8 [ %extract.t854, %if.else136 ], [ %1, %entry ]
-  %w.0.off8 = phi i8 [ %extract.t857, %if.else136 ], [ %2, %entry ]
-  store i8 %w.0.off8, i8* %c, align 1
-  store i8 %w.0.off0, i8* %d, align 1
-  ret void
-}
-
- at c = common dso_local local_unnamed_addr global i16 0, align 2
- at b = common dso_local local_unnamed_addr global i16 0, align 2
- at f = common dso_local local_unnamed_addr global i32 0, align 4
- at e = common dso_local local_unnamed_addr global i8 0, align 1
- at a = common dso_local local_unnamed_addr global i8 0, align 1
- at d = common dso_local local_unnamed_addr global i32 0, align 4
-
-define void @and_trunc_two_zext() {
-; CHECK-NODSP-V8-LABEL: and_trunc_two_zext:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    movw r1, :lower16:b
-; CHECK-NODSP-V8-NEXT:    movt r1, :upper16:b
-; CHECK-NODSP-V8-NEXT:    ldrh r1, [r1]
-; CHECK-NODSP-V8-NEXT:    movw r3, :lower16:f
-; CHECK-NODSP-V8-NEXT:    sxth r2, r1
-; CHECK-NODSP-V8-NEXT:    movt r3, :upper16:f
-; CHECK-NODSP-V8-NEXT:    str r2, [r3]
-; CHECK-NODSP-V8-NEXT:    movw r3, :lower16:a
-; CHECK-NODSP-V8-NEXT:    movt r3, :upper16:a
-; CHECK-NODSP-V8-NEXT:    movw r0, :lower16:c
-; CHECK-NODSP-V8-NEXT:    movw r2, :lower16:e
-; CHECK-NODSP-V8-NEXT:    ldrb r3, [r3]
-; CHECK-NODSP-V8-NEXT:    movt r0, :upper16:c
-; CHECK-NODSP-V8-NEXT:    and r1, r1, #1
-; CHECK-NODSP-V8-NEXT:    movt r2, :upper16:e
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    strb r1, [r2]
-; CHECK-NODSP-V8-NEXT:    muls r1, r3, r1
-; CHECK-NODSP-V8-NEXT:    uxtb r1, r1
-; CHECK-NODSP-V8-NEXT:    movw r2, :lower16:d
-; CHECK-NODSP-V8-NEXT:    orrs r0, r1
-; CHECK-NODSP-V8-NEXT:    movt r2, :upper16:d
-; CHECK-NODSP-V8-NEXT:    lsls r0, r0, #16
-; CHECK-NODSP-V8-NEXT:    str r1, [r2]
-; CHECK-NODSP-V8-NEXT:    it eq
-; CHECK-NODSP-V8-NEXT:    bxeq lr
-; CHECK-NODSP-V8-NEXT:    .p2align 2
-; CHECK-NODSP-V8-NEXT:  .LBB24_1: @ %for.cond
-; CHECK-NODSP-V8-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V8-NEXT:    b .LBB24_1
-;
-; CHECK-NODSP-V7-LABEL: and_trunc_two_zext:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:b
-; CHECK-NODSP-V7-NEXT:    movw r2, :lower16:a
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:b
-; CHECK-NODSP-V7-NEXT:    movt r2, :upper16:a
-; CHECK-NODSP-V7-NEXT:    ldrh r1, [r1]
-; CHECK-NODSP-V7-NEXT:    movw r0, :lower16:c
-; CHECK-NODSP-V7-NEXT:    ldrb r2, [r2]
-; CHECK-NODSP-V7-NEXT:    movt r0, :upper16:c
-; CHECK-NODSP-V7-NEXT:    and r3, r1, #1
-; CHECK-NODSP-V7-NEXT:    ldrh.w r12, [r0]
-; CHECK-NODSP-V7-NEXT:    movw r0, :lower16:e
-; CHECK-NODSP-V7-NEXT:    muls r2, r3, r2
-; CHECK-NODSP-V7-NEXT:    movt r0, :upper16:e
-; CHECK-NODSP-V7-NEXT:    strb r3, [r0]
-; CHECK-NODSP-V7-NEXT:    sxth r0, r1
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:f
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:f
-; CHECK-NODSP-V7-NEXT:    str r0, [r1]
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:d
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:d
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r2
-; CHECK-NODSP-V7-NEXT:    str r0, [r1]
-; CHECK-NODSP-V7-NEXT:    orr.w r0, r0, r12
-; CHECK-NODSP-V7-NEXT:    lsls r0, r0, #16
-; CHECK-NODSP-V7-NEXT:    it eq
-; CHECK-NODSP-V7-NEXT:    bxeq lr
-; CHECK-NODSP-V7-NEXT:  .LBB24_1: @ %for.cond
-; CHECK-NODSP-V7-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-NODSP-V7-NEXT:    b .LBB24_1
-;
-; CHECK-DSP-LABEL: and_trunc_two_zext:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    movw r0, :lower16:b
-; CHECK-DSP-NEXT:    movw r2, :lower16:f
-; CHECK-DSP-NEXT:    movt r0, :upper16:b
-; CHECK-DSP-NEXT:    movt r2, :upper16:f
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    sxth r1, r0
-; CHECK-DSP-NEXT:    and r0, r0, #1
-; CHECK-DSP-NEXT:    str r1, [r2]
-; CHECK-DSP-NEXT:    movw r1, :lower16:e
-; CHECK-DSP-NEXT:    movt r1, :upper16:e
-; CHECK-DSP-NEXT:    strb r0, [r1]
-; CHECK-DSP-NEXT:    movw r1, :lower16:a
-; CHECK-DSP-NEXT:    movt r1, :upper16:a
-; CHECK-DSP-NEXT:    ldrb r1, [r1]
-; CHECK-DSP-NEXT:    muls r0, r1, r0
-; CHECK-DSP-NEXT:    movw r1, :lower16:d
-; CHECK-DSP-NEXT:    uxtb r0, r0
-; CHECK-DSP-NEXT:    movt r1, :upper16:d
-; CHECK-DSP-NEXT:    str r0, [r1]
-; CHECK-DSP-NEXT:    movw r1, :lower16:c
-; CHECK-DSP-NEXT:    movt r1, :upper16:c
-; CHECK-DSP-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-NEXT:    orrs r0, r1
-; CHECK-DSP-NEXT:    lsls r0, r0, #16
-; CHECK-DSP-NEXT:    it eq
-; CHECK-DSP-NEXT:    bxeq lr
-; CHECK-DSP-NEXT:  .LBB24_1: @ %for.cond
-; CHECK-DSP-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-NEXT:    b .LBB24_1
-;
-; CHECK-DSP-IMM-LABEL: and_trunc_two_zext:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:b
-; CHECK-DSP-IMM-NEXT:    movw r2, :lower16:a
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:b
-; CHECK-DSP-IMM-NEXT:    movt r2, :upper16:a
-; CHECK-DSP-IMM-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-IMM-NEXT:    movw r0, :lower16:c
-; CHECK-DSP-IMM-NEXT:    ldrb r2, [r2]
-; CHECK-DSP-IMM-NEXT:    movt r0, :upper16:c
-; CHECK-DSP-IMM-NEXT:    and r3, r1, #1
-; CHECK-DSP-IMM-NEXT:    ldrh.w r12, [r0]
-; CHECK-DSP-IMM-NEXT:    movw r0, :lower16:e
-; CHECK-DSP-IMM-NEXT:    muls r2, r3, r2
-; CHECK-DSP-IMM-NEXT:    movt r0, :upper16:e
-; CHECK-DSP-IMM-NEXT:    strb r3, [r0]
-; CHECK-DSP-IMM-NEXT:    sxth r0, r1
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:f
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:f
-; CHECK-DSP-IMM-NEXT:    str r0, [r1]
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:d
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r2
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:d
-; CHECK-DSP-IMM-NEXT:    str r0, [r1]
-; CHECK-DSP-IMM-NEXT:    orr.w r0, r0, r12
-; CHECK-DSP-IMM-NEXT:    lsls r0, r0, #16
-; CHECK-DSP-IMM-NEXT:    beq .LBB24_2
-; CHECK-DSP-IMM-NEXT:  .LBB24_1: @ %for.cond
-; CHECK-DSP-IMM-NEXT:    @ =>This Inner Loop Header: Depth=1
-; CHECK-DSP-IMM-NEXT:    b .LBB24_1
-; CHECK-DSP-IMM-NEXT:  .LBB24_2: @ %if.end
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i16, i16* @c, align 2
-  %1 = load i16, i16* @b, align 2
-  %conv = sext i16 %1 to i32
-  store i32 %conv, i32* @f, align 4
-  %2 = trunc i16 %1 to i8
-  %conv1 = and i8 %2, 1
-  store i8 %conv1, i8* @e, align 1
-  %3 = load i8, i8* @a, align 1
-  %narrow = mul nuw i8 %3, %conv1
-  %mul = zext i8 %narrow to i32
-  store i32 %mul, i32* @d, align 4
-  %4 = zext i8 %narrow to i16
-  %conv5 = or i16 %0, %4
-  %tobool = icmp eq i16 %conv5, 0
-  br i1 %tobool, label %if.end, label %for.cond
-
-for.cond:
-  br label %for.cond
-
-if.end:
-  ret void
-}
-
-define void @zext_urem_trunc() {
-; CHECK-NODSP-V8-LABEL: zext_urem_trunc:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    movw r0, :lower16:c
-; CHECK-NODSP-V8-NEXT:    movt r0, :upper16:c
-; CHECK-NODSP-V8-NEXT:    ldrh r1, [r0]
-; CHECK-NODSP-V8-NEXT:    movw r0, :lower16:e
-; CHECK-NODSP-V8-NEXT:    movt r0, :upper16:e
-; CHECK-NODSP-V8-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V8-NEXT:    cbz r1, .LBB25_2
-; CHECK-NODSP-V8-NEXT:  @ %bb.1: @ %cond.false
-; CHECK-NODSP-V8-NEXT:    udiv r2, r0, r1
-; CHECK-NODSP-V8-NEXT:    mls r0, r2, r1, r0
-; CHECK-NODSP-V8-NEXT:  .LBB25_2: @ %cond.end
-; CHECK-NODSP-V8-NEXT:    movw r1, :lower16:a
-; CHECK-NODSP-V8-NEXT:    movt r1, :upper16:a
-; CHECK-NODSP-V8-NEXT:    strb r0, [r1]
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: zext_urem_trunc:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r7, lr}
-; CHECK-NODSP-V7-NEXT:    push {r7, lr}
-; CHECK-NODSP-V7-NEXT:    movw r0, :lower16:e
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:c
-; CHECK-NODSP-V7-NEXT:    movt r0, :upper16:e
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:c
-; CHECK-NODSP-V7-NEXT:    ldrh r1, [r1]
-; CHECK-NODSP-V7-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V7-NEXT:    cbz r1, .LBB25_2
-; CHECK-NODSP-V7-NEXT:  @ %bb.1: @ %cond.false
-; CHECK-NODSP-V7-NEXT:    bl __aeabi_uidivmod
-; CHECK-NODSP-V7-NEXT:    mov r0, r1
-; CHECK-NODSP-V7-NEXT:  .LBB25_2: @ %cond.end
-; CHECK-NODSP-V7-NEXT:    movw r1, :lower16:a
-; CHECK-NODSP-V7-NEXT:    movt r1, :upper16:a
-; CHECK-NODSP-V7-NEXT:    strb r0, [r1]
-; CHECK-NODSP-V7-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-LABEL: zext_urem_trunc:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    movw r1, :lower16:c
-; CHECK-DSP-NEXT:    movw r0, :lower16:e
-; CHECK-DSP-NEXT:    movt r1, :upper16:c
-; CHECK-DSP-NEXT:    movt r0, :upper16:e
-; CHECK-DSP-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-NEXT:    cmp r1, #0
-; CHECK-DSP-NEXT:    itt ne
-; CHECK-DSP-NEXT:    udivne r2, r0, r1
-; CHECK-DSP-NEXT:    mlsne r0, r2, r1, r0
-; CHECK-DSP-NEXT:    movw r1, :lower16:a
-; CHECK-DSP-NEXT:    movt r1, :upper16:a
-; CHECK-DSP-NEXT:    strb r0, [r1]
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: zext_urem_trunc:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    movw r0, :lower16:e
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:c
-; CHECK-DSP-IMM-NEXT:    movt r0, :upper16:e
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:c
-; CHECK-DSP-IMM-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-IMM-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-IMM-NEXT:    cbz r1, .LBB25_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %cond.false
-; CHECK-DSP-IMM-NEXT:    udiv r2, r0, r1
-; CHECK-DSP-IMM-NEXT:    mls r0, r2, r1, r0
-; CHECK-DSP-IMM-NEXT:  .LBB25_2: @ %cond.end
-; CHECK-DSP-IMM-NEXT:    movw r1, :lower16:a
-; CHECK-DSP-IMM-NEXT:    movt r1, :upper16:a
-; CHECK-DSP-IMM-NEXT:    strb r0, [r1]
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i16, i16* @c, align 2
-  %cmp = icmp eq i16 %0, 0
-  %1 = load i8, i8* @e, align 1
-  br i1 %cmp, label %cond.end, label %cond.false
-
-cond.false:
-  %rem.lhs.trunc = zext i8 %1 to i16
-  %rem7 = urem i16 %rem.lhs.trunc, %0
-  %rem.zext = trunc i16 %rem7 to i8
-  br label %cond.end
-
-cond.end:
-  %cond = phi i8 [ %rem.zext, %cond.false ], [ %1, %entry ]
-  store i8 %cond, i8* @a, align 1
-  ret void
-}
-
-define i1 @dont_replace_trunc_1(i8* %a, i16* %b, i16* %c, i32* %d, i8* %e, i32* %f) {
-; CHECK-NODSP-V8-LABEL: dont_replace_trunc_1:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    push {r4, lr}
-; CHECK-NODSP-V8-NEXT:    ldrh r1, [r1]
-; CHECK-NODSP-V8-NEXT:    ldrd r12, lr, [sp, #8]
-; CHECK-NODSP-V8-NEXT:    sxth r4, r1
-; CHECK-NODSP-V8-NEXT:    and r1, r1, #1
-; CHECK-NODSP-V8-NEXT:    ldrh r2, [r2]
-; CHECK-NODSP-V8-NEXT:    str.w r4, [lr]
-; CHECK-NODSP-V8-NEXT:    strb.w r1, [r12]
-; CHECK-NODSP-V8-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V8-NEXT:    muls r0, r1, r0
-; CHECK-NODSP-V8-NEXT:    uxtb r1, r0
-; CHECK-NODSP-V8-NEXT:    orr.w r0, r2, r1
-; CHECK-NODSP-V8-NEXT:    uxth r0, r0
-; CHECK-NODSP-V8-NEXT:    clz r0, r0
-; CHECK-NODSP-V8-NEXT:    lsrs r0, r0, #5
-; CHECK-NODSP-V8-NEXT:    str r1, [r3]
-; CHECK-NODSP-V8-NEXT:    pop {r4, pc}
-;
-; CHECK-NODSP-V7-LABEL: dont_replace_trunc_1:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r4, lr}
-; CHECK-NODSP-V7-NEXT:    push {r4, lr}
-; CHECK-NODSP-V7-NEXT:    ldrh r1, [r1]
-; CHECK-NODSP-V7-NEXT:    ldrd lr, r12, [sp, #8]
-; CHECK-NODSP-V7-NEXT:    ldrh r2, [r2]
-; CHECK-NODSP-V7-NEXT:    sxth r4, r1
-; CHECK-NODSP-V7-NEXT:    and r1, r1, #1
-; CHECK-NODSP-V7-NEXT:    str.w r4, [r12]
-; CHECK-NODSP-V7-NEXT:    strb.w r1, [lr]
-; CHECK-NODSP-V7-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V7-NEXT:    muls r0, r1, r0
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r0
-; CHECK-NODSP-V7-NEXT:    str r0, [r3]
-; CHECK-NODSP-V7-NEXT:    orrs r0, r2
-; CHECK-NODSP-V7-NEXT:    uxth r0, r0
-; CHECK-NODSP-V7-NEXT:    clz r0, r0
-; CHECK-NODSP-V7-NEXT:    lsrs r0, r0, #5
-; CHECK-NODSP-V7-NEXT:    pop {r4, pc}
-;
-; CHECK-DSP-LABEL: dont_replace_trunc_1:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    push {r7, lr}
-; CHECK-DSP-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-NEXT:    ldrh.w r12, [r2]
-; CHECK-DSP-NEXT:    ldr r2, [sp, #12]
-; CHECK-DSP-NEXT:    sxth.w lr, r1
-; CHECK-DSP-NEXT:    and r1, r1, #1
-; CHECK-DSP-NEXT:    str.w lr, [r2]
-; CHECK-DSP-NEXT:    ldr r2, [sp, #8]
-; CHECK-DSP-NEXT:    strb r1, [r2]
-; CHECK-DSP-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-NEXT:    muls r0, r1, r0
-; CHECK-DSP-NEXT:    uxtb r0, r0
-; CHECK-DSP-NEXT:    str r0, [r3]
-; CHECK-DSP-NEXT:    orr.w r0, r0, r12
-; CHECK-DSP-NEXT:    uxth r0, r0
-; CHECK-DSP-NEXT:    clz r0, r0
-; CHECK-DSP-NEXT:    lsrs r0, r0, #5
-; CHECK-DSP-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-IMM-LABEL: dont_replace_trunc_1:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    push {r4, lr}
-; CHECK-DSP-IMM-NEXT:    ldrd lr, r12, [sp, #8]
-; CHECK-DSP-IMM-NEXT:    ldrh r1, [r1]
-; CHECK-DSP-IMM-NEXT:    ldrh r2, [r2]
-; CHECK-DSP-IMM-NEXT:    sxth r4, r1
-; CHECK-DSP-IMM-NEXT:    str.w r4, [r12]
-; CHECK-DSP-IMM-NEXT:    and r1, r1, #1
-; CHECK-DSP-IMM-NEXT:    strb.w r1, [lr]
-; CHECK-DSP-IMM-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-IMM-NEXT:    muls r0, r1, r0
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r0
-; CHECK-DSP-IMM-NEXT:    str r0, [r3]
-; CHECK-DSP-IMM-NEXT:    orrs r0, r2
-; CHECK-DSP-IMM-NEXT:    uxth r0, r0
-; CHECK-DSP-IMM-NEXT:    clz r0, r0
-; CHECK-DSP-IMM-NEXT:    lsrs r0, r0, #5
-; CHECK-DSP-IMM-NEXT:    pop {r4, pc}
-entry:
-  %0 = load i16, i16* %c, align 2
-  %1 = load i16, i16* %b, align 2
-  %conv = sext i16 %1 to i32
-  store i32 %conv, i32* %f, align 4
-  %2 = trunc i16 %1 to i8
-  %conv1 = and i8 %2, 1
-  store i8 %conv1, i8* %e, align 1
-  %3 = load i8, i8* %a, align 1
-  %narrow = mul nuw i8 %3, %conv1
-  %mul = zext i8 %narrow to i32
-  store i32 %mul, i32* %d, align 4
-  %4 = zext i8 %narrow to i16
-  %conv5 = or i16 %0, %4
-  %tobool = icmp eq i16 %conv5, 0
-  ret i1 %tobool
-}
-
-define i32 @dont_replace_trunc_2(i16* %a, i8* %b) {
-; CHECK-NODSP-V8-LABEL: dont_replace_trunc_2:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    cmp r0, #8
-; CHECK-NODSP-V8-NEXT:    it ls
-; CHECK-NODSP-V8-NEXT:    movls r0, #0
-; CHECK-NODSP-V8-NEXT:    ldrb r2, [r1]
-; CHECK-NODSP-V8-NEXT:    uxtb r0, r0
-; CHECK-NODSP-V8-NEXT:    orrs r0, r2
-; CHECK-NODSP-V8-NEXT:    strb r0, [r1]
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: dont_replace_trunc_2:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V7-NEXT:    ldrb r2, [r1]
-; CHECK-NODSP-V7-NEXT:    cmp r0, #8
-; CHECK-NODSP-V7-NEXT:    it ls
-; CHECK-NODSP-V7-NEXT:    movls r0, #0
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r0
-; CHECK-NODSP-V7-NEXT:    orrs r0, r2
-; CHECK-NODSP-V7-NEXT:    strb r0, [r1]
-; CHECK-NODSP-V7-NEXT:    bx lr
-;
-; CHECK-DSP-LABEL: dont_replace_trunc_2:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    cmp r0, #8
-; CHECK-DSP-NEXT:    it ls
-; CHECK-DSP-NEXT:    movls r0, #0
-; CHECK-DSP-NEXT:    ldrb r2, [r1]
-; CHECK-DSP-NEXT:    uxtb r0, r0
-; CHECK-DSP-NEXT:    orrs r0, r2
-; CHECK-DSP-NEXT:    strb r0, [r1]
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: dont_replace_trunc_2:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    movs r2, #0
-; CHECK-DSP-IMM-NEXT:    ldrb r3, [r1]
-; CHECK-DSP-IMM-NEXT:    cmp r0, #8
-; CHECK-DSP-IMM-NEXT:    it hi
-; CHECK-DSP-IMM-NEXT:    movhi r2, r0
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r2
-; CHECK-DSP-IMM-NEXT:    orrs r0, r3
-; CHECK-DSP-IMM-NEXT:    strb r0, [r1]
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i16, i16* %a, align 2
-  %cmp = icmp ugt i16 %0, 8
-  %narrow = select i1 %cmp, i16 %0, i16 0
-  %cond = trunc i16 %narrow to i8
-  %1 = load i8, i8* %b, align 1
-  %or = or i8 %1, %cond
-  store i8 %or, i8* %b, align 1
-  %conv5 = zext i8 %or to i32
-  ret i32 %conv5
-}
-
-define i32 @replace_trunk_with_mask(i16* %a) {
-; CHECK-NODSP-V8-LABEL: replace_trunk_with_mask:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    cmp r0, #0
-; CHECK-NODSP-V8-NEXT:    itt eq
-; CHECK-NODSP-V8-NEXT:    moveq r0, #0
-; CHECK-NODSP-V8-NEXT:    bxeq lr
-; CHECK-NODSP-V8-NEXT:    movw r1, #535
-; CHECK-NODSP-V8-NEXT:    udiv r2, r1, r0
-; CHECK-NODSP-V8-NEXT:    mls r0, r2, r0, r1
-; CHECK-NODSP-V8-NEXT:    movw r1, #43691
-; CHECK-NODSP-V8-NEXT:    uxtb r0, r0
-; CHECK-NODSP-V8-NEXT:    movt r1, #43690
-; CHECK-NODSP-V8-NEXT:    umull r0, r1, r0, r1
-; CHECK-NODSP-V8-NEXT:    lsrs r0, r1, #1
-; CHECK-NODSP-V8-NEXT:    bx lr
-;
-; CHECK-NODSP-V7-LABEL: replace_trunk_with_mask:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    .save {r7, lr}
-; CHECK-NODSP-V7-NEXT:    push {r7, lr}
-; CHECK-NODSP-V7-NEXT:    ldrh r1, [r0]
-; CHECK-NODSP-V7-NEXT:    cbz r1, .LBB28_2
-; CHECK-NODSP-V7-NEXT:  @ %bb.1: @ %cond.false
-; CHECK-NODSP-V7-NEXT:    movw r0, #535
-; CHECK-NODSP-V7-NEXT:    bl __aeabi_uidivmod
-; CHECK-NODSP-V7-NEXT:    uxtb r0, r1
-; CHECK-NODSP-V7-NEXT:    movw r1, #43691
-; CHECK-NODSP-V7-NEXT:    movt r1, #43690
-; CHECK-NODSP-V7-NEXT:    umull r0, r1, r0, r1
-; CHECK-NODSP-V7-NEXT:    lsrs r0, r1, #1
-; CHECK-NODSP-V7-NEXT:    pop {r7, pc}
-; CHECK-NODSP-V7-NEXT:  .LBB28_2:
-; CHECK-NODSP-V7-NEXT:    movs r0, #0
-; CHECK-NODSP-V7-NEXT:    pop {r7, pc}
-;
-; CHECK-DSP-LABEL: replace_trunk_with_mask:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    cmp r0, #0
-; CHECK-DSP-NEXT:    itt eq
-; CHECK-DSP-NEXT:    moveq r0, #0
-; CHECK-DSP-NEXT:    bxeq lr
-; CHECK-DSP-NEXT:    movw r1, #535
-; CHECK-DSP-NEXT:    udiv r2, r1, r0
-; CHECK-DSP-NEXT:    mls r0, r2, r0, r1
-; CHECK-DSP-NEXT:    movw r1, #43691
-; CHECK-DSP-NEXT:    uxtb r0, r0
-; CHECK-DSP-NEXT:    movt r1, #43690
-; CHECK-DSP-NEXT:    umull r0, r1, r0, r1
-; CHECK-DSP-NEXT:    lsrs r0, r1, #1
-; CHECK-DSP-NEXT:    bx lr
-;
-; CHECK-DSP-IMM-LABEL: replace_trunk_with_mask:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    cbz r0, .LBB28_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1: @ %cond.false
-; CHECK-DSP-IMM-NEXT:    movw r1, #535
-; CHECK-DSP-IMM-NEXT:    udiv r2, r1, r0
-; CHECK-DSP-IMM-NEXT:    mls r0, r2, r0, r1
-; CHECK-DSP-IMM-NEXT:    movw r1, #43691
-; CHECK-DSP-IMM-NEXT:    movt r1, #43690
-; CHECK-DSP-IMM-NEXT:    uxtb r0, r0
-; CHECK-DSP-IMM-NEXT:    umull r0, r1, r0, r1
-; CHECK-DSP-IMM-NEXT:    lsrs r0, r1, #1
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB28_2:
-; CHECK-DSP-IMM-NEXT:    movs r0, #0
-; CHECK-DSP-IMM-NEXT:    bx lr
-entry:
-  %0 = load i16, i16* %a
-  %cmp = icmp eq i16 %0, 0
-  br i1 %cmp, label %cond.end, label %cond.false
-
-cond.false:
-  %1 = urem i16 535, %0
-  %.lhs.trunc = trunc i16 %1 to i8
-  %2 = udiv i8 %.lhs.trunc, 3
-  %phitmp = zext i8 %2 to i32
-  br label %cond.end
-
-cond.end:
-  %cond = phi i32 [ %phitmp, %cond.false ], [ 0, %entry ]
-  ret i32 %cond
-}
-
-define float @test_i8_sitofp(i8* %ptr, i8 %arg) {
-; CHECK-NODSP-V8-LABEL: test_i8_sitofp:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V8-NEXT:    uxtb r2, r1
-; CHECK-NODSP-V8-NEXT:    cmp r0, r2
-; CHECK-NODSP-V8-NEXT:    bne .LBB29_2
-; CHECK-NODSP-V8-NEXT:  @ %bb.1:
-; CHECK-NODSP-V8-NEXT:    vldr s0, .LCPI29_0
-; CHECK-NODSP-V8-NEXT:    vmov r0, s0
-; CHECK-NODSP-V8-NEXT:    bx lr
-; CHECK-NODSP-V8-NEXT:  .LBB29_2: @ %if.end
-; CHECK-NODSP-V8-NEXT:    sxtb r0, r1
-; CHECK-NODSP-V8-NEXT:    vmov s0, r0
-; CHECK-NODSP-V8-NEXT:    vcvt.f32.s32 s0, s0
-; CHECK-NODSP-V8-NEXT:    vmov.f32 s2, #2.000000e+01
-; CHECK-NODSP-V8-NEXT:    vdiv.f32 s0, s0, s2
-; CHECK-NODSP-V8-NEXT:    vmov r0, s0
-; CHECK-NODSP-V8-NEXT:    bx lr
-; CHECK-NODSP-V8-NEXT:    .p2align 2
-; CHECK-NODSP-V8-NEXT:  @ %bb.3:
-; CHECK-NODSP-V8-NEXT:  .LCPI29_0:
-; CHECK-NODSP-V8-NEXT:    .long 0 @ float 0
-;
-; CHECK-NODSP-V7-LABEL: test_i8_sitofp:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrb r0, [r0]
-; CHECK-NODSP-V7-NEXT:    uxtb r2, r1
-; CHECK-NODSP-V7-NEXT:    cmp r0, r2
-; CHECK-NODSP-V7-NEXT:    ittt eq
-; CHECK-NODSP-V7-NEXT:    vldreq s0, .LCPI29_0
-; CHECK-NODSP-V7-NEXT:    vmoveq r0, s0
-; CHECK-NODSP-V7-NEXT:    bxeq lr
-; CHECK-NODSP-V7-NEXT:    sxtb r0, r1
-; CHECK-NODSP-V7-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-NODSP-V7-NEXT:    vmov s2, r0
-; CHECK-NODSP-V7-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-NODSP-V7-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-NODSP-V7-NEXT:    vmov r0, s0
-; CHECK-NODSP-V7-NEXT:    bx lr
-; CHECK-NODSP-V7-NEXT:    .p2align 2
-; CHECK-NODSP-V7-NEXT:  @ %bb.1:
-; CHECK-NODSP-V7-NEXT:  .LCPI29_0:
-; CHECK-NODSP-V7-NEXT:    .long 0 @ float 0
-;
-; CHECK-DSP-LABEL: test_i8_sitofp:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-NEXT:    uxtb r2, r1
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    ittt eq
-; CHECK-DSP-NEXT:    vldreq s0, .LCPI29_0
-; CHECK-DSP-NEXT:    vmoveq r0, s0
-; CHECK-DSP-NEXT:    bxeq lr
-; CHECK-DSP-NEXT:    sxtb r0, r1
-; CHECK-DSP-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-DSP-NEXT:    vmov s2, r0
-; CHECK-DSP-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-DSP-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-DSP-NEXT:    vmov r0, s0
-; CHECK-DSP-NEXT:    bx lr
-; CHECK-DSP-NEXT:    .p2align 2
-; CHECK-DSP-NEXT:  @ %bb.1:
-; CHECK-DSP-NEXT:  .LCPI29_0:
-; CHECK-DSP-NEXT:    .long 0 @ float 0
-;
-; CHECK-DSP-IMM-LABEL: test_i8_sitofp:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrb r0, [r0]
-; CHECK-DSP-IMM-NEXT:    uxtb r2, r1
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    bne .LBB29_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1:
-; CHECK-DSP-IMM-NEXT:    vldr s0, .LCPI29_0
-; CHECK-DSP-IMM-NEXT:    vmov r0, s0
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB29_2: @ %if.end
-; CHECK-DSP-IMM-NEXT:    sxtb r0, r1
-; CHECK-DSP-IMM-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-DSP-IMM-NEXT:    vmov s2, r0
-; CHECK-DSP-IMM-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-DSP-IMM-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-DSP-IMM-NEXT:    vmov r0, s0
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:    .p2align 2
-; CHECK-DSP-IMM-NEXT:  @ %bb.3:
-; CHECK-DSP-IMM-NEXT:  .LCPI29_0:
-; CHECK-DSP-IMM-NEXT:    .long 0 @ float 0
-entry:
-  %0 = load i8, i8* %ptr, align 1
-   %cmp = icmp eq i8 %0, %arg
-   br i1 %cmp, label %exit, label %if.end
-
-if.end:
-  %conv = sitofp i8 %arg to float
-  %div = fdiv float %conv, 2.000000e+01
-  br label %exit
-
-exit:
-  %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
-  ret float %res
-}
-
-define float @test_i16_sitofp(i16* %ptr, i16 %arg) {
-; CHECK-NODSP-V8-LABEL: test_i16_sitofp:
-; CHECK-NODSP-V8:       @ %bb.0: @ %entry
-; CHECK-NODSP-V8-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V8-NEXT:    uxth r2, r1
-; CHECK-NODSP-V8-NEXT:    cmp r0, r2
-; CHECK-NODSP-V8-NEXT:    bne .LBB30_2
-; CHECK-NODSP-V8-NEXT:  @ %bb.1:
-; CHECK-NODSP-V8-NEXT:    vldr s0, .LCPI30_0
-; CHECK-NODSP-V8-NEXT:    vmov r0, s0
-; CHECK-NODSP-V8-NEXT:    bx lr
-; CHECK-NODSP-V8-NEXT:  .LBB30_2: @ %if.end
-; CHECK-NODSP-V8-NEXT:    sxth r0, r1
-; CHECK-NODSP-V8-NEXT:    vmov s0, r0
-; CHECK-NODSP-V8-NEXT:    vcvt.f32.s32 s0, s0
-; CHECK-NODSP-V8-NEXT:    vmov.f32 s2, #2.000000e+01
-; CHECK-NODSP-V8-NEXT:    vdiv.f32 s0, s0, s2
-; CHECK-NODSP-V8-NEXT:    vmov r0, s0
-; CHECK-NODSP-V8-NEXT:    bx lr
-; CHECK-NODSP-V8-NEXT:    .p2align 2
-; CHECK-NODSP-V8-NEXT:  @ %bb.3:
-; CHECK-NODSP-V8-NEXT:  .LCPI30_0:
-; CHECK-NODSP-V8-NEXT:    .long 0 @ float 0
-;
-; CHECK-NODSP-V7-LABEL: test_i16_sitofp:
-; CHECK-NODSP-V7:       @ %bb.0: @ %entry
-; CHECK-NODSP-V7-NEXT:    ldrh r0, [r0]
-; CHECK-NODSP-V7-NEXT:    uxth r2, r1
-; CHECK-NODSP-V7-NEXT:    cmp r0, r2
-; CHECK-NODSP-V7-NEXT:    ittt eq
-; CHECK-NODSP-V7-NEXT:    vldreq s0, .LCPI30_0
-; CHECK-NODSP-V7-NEXT:    vmoveq r0, s0
-; CHECK-NODSP-V7-NEXT:    bxeq lr
-; CHECK-NODSP-V7-NEXT:    sxth r0, r1
-; CHECK-NODSP-V7-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-NODSP-V7-NEXT:    vmov s2, r0
-; CHECK-NODSP-V7-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-NODSP-V7-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-NODSP-V7-NEXT:    vmov r0, s0
-; CHECK-NODSP-V7-NEXT:    bx lr
-; CHECK-NODSP-V7-NEXT:    .p2align 2
-; CHECK-NODSP-V7-NEXT:  @ %bb.1:
-; CHECK-NODSP-V7-NEXT:  .LCPI30_0:
-; CHECK-NODSP-V7-NEXT:    .long 0 @ float 0
-;
-; CHECK-DSP-LABEL: test_i16_sitofp:
-; CHECK-DSP:       @ %bb.0: @ %entry
-; CHECK-DSP-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-NEXT:    uxth r2, r1
-; CHECK-DSP-NEXT:    cmp r0, r2
-; CHECK-DSP-NEXT:    ittt eq
-; CHECK-DSP-NEXT:    vldreq s0, .LCPI30_0
-; CHECK-DSP-NEXT:    vmoveq r0, s0
-; CHECK-DSP-NEXT:    bxeq lr
-; CHECK-DSP-NEXT:    sxth r0, r1
-; CHECK-DSP-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-DSP-NEXT:    vmov s2, r0
-; CHECK-DSP-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-DSP-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-DSP-NEXT:    vmov r0, s0
-; CHECK-DSP-NEXT:    bx lr
-; CHECK-DSP-NEXT:    .p2align 2
-; CHECK-DSP-NEXT:  @ %bb.1:
-; CHECK-DSP-NEXT:  .LCPI30_0:
-; CHECK-DSP-NEXT:    .long 0 @ float 0
-;
-; CHECK-DSP-IMM-LABEL: test_i16_sitofp:
-; CHECK-DSP-IMM:       @ %bb.0: @ %entry
-; CHECK-DSP-IMM-NEXT:    ldrh r0, [r0]
-; CHECK-DSP-IMM-NEXT:    uxth r2, r1
-; CHECK-DSP-IMM-NEXT:    cmp r0, r2
-; CHECK-DSP-IMM-NEXT:    bne .LBB30_2
-; CHECK-DSP-IMM-NEXT:  @ %bb.1:
-; CHECK-DSP-IMM-NEXT:    vldr s0, .LCPI30_0
-; CHECK-DSP-IMM-NEXT:    vmov r0, s0
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:  .LBB30_2: @ %if.end
-; CHECK-DSP-IMM-NEXT:    sxth r0, r1
-; CHECK-DSP-IMM-NEXT:    vmov.f32 s0, #2.000000e+01
-; CHECK-DSP-IMM-NEXT:    vmov s2, r0
-; CHECK-DSP-IMM-NEXT:    vcvt.f32.s32 s2, s2
-; CHECK-DSP-IMM-NEXT:    vdiv.f32 s0, s2, s0
-; CHECK-DSP-IMM-NEXT:    vmov r0, s0
-; CHECK-DSP-IMM-NEXT:    bx lr
-; CHECK-DSP-IMM-NEXT:    .p2align 2
-; CHECK-DSP-IMM-NEXT:  @ %bb.3:
-; CHECK-DSP-IMM-NEXT:  .LCPI30_0:
-; CHECK-DSP-IMM-NEXT:    .long 0 @ float 0
-entry:
-  %0 = load i16, i16* %ptr, align 1
-   %cmp = icmp eq i16 %0, %arg
-   br i1 %cmp, label %exit, label %if.end
-
-if.end:
-  %conv = sitofp i16 %arg to float
-  %div = fdiv float %conv, 2.000000e+01
-  br label %exit
-
-exit:
-  %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
-  ret float %res
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll
deleted file mode 100644
index 76c9746c3556..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll
+++ /dev/null
@@ -1,332 +0,0 @@
-; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
-; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP
-; RUN: llc -mtriple=thumbv8 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP-IMM
-
-; CHECK-COMMON-LABEL: test_ult_254_inc_imm:
-; CHECK-DSP:        adds    r0, #1
-; CHECK-DSP-NEXT:   uxtb    r1, r0
-; CHECK-DSP-NEXT:   movs    r0, #47
-; CHECK-DSP-NEXT:   cmp     r1, #254
-; CHECK-DSP-NEXT:   it      lo
-; CHECK-DSP-NEXT:   movlo   r0, #35
-
-; CHECK-DSP-IMM:      movs r1, #1
-; CHECK-DSP-IMM-NEXT: uadd8 r1, r0, r1
-; CHECK-DSP-IMM-NEXT: movs  r0, #47
-; CHECK-DSP-IMM-NEXT: cmp r1, #254
-; CHECK-DSP-IMM-NEXT: it  lo
-; CHECK-DSP-IMM-NEXT: movlo r0, #35
-define i32 @test_ult_254_inc_imm(i8 zeroext %x) {
-entry:
-  %add = add i8 %x, 1
-  %cmp = icmp ult i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_slt_254_inc_imm
-; CHECK-COMMON: adds
-; CHECK-COMMON: sxtb
-define i32 @test_slt_254_inc_imm(i8 signext %x) {
-entry:
-  %add = add i8 %x, 1
-  %cmp = icmp slt i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_ult_254_inc_var:
-; CHECK-NODSP:      add     r0, r1
-; CHECK-NODSP-NEXT: uxtb    r1, r0
-; CHECK-NODSP-NEXT: movs    r0, #47
-; CHECK-NODSP-NEXT: cmp     r1, #254
-; CHECK-NODSP-NEXT: it      lo
-; CHECK-NODSP-NEXT: movlo   r0, #35
-
-; CHECK-DSP:        uadd8   r1, r0, r1
-; CHECK-DSP-NEXT:   movs    r0, #47
-; CHECK-DSP-NEXT:   cmp     r1, #254
-; CHECK-DSP-NEXT:   it      lo
-; CHECK-DSP-NEXT:   movlo   r0, #35
-define i32 @test_ult_254_inc_var(i8 zeroext %x, i8 zeroext %y) {
-entry:
-  %add = add i8 %x, %y
-  %cmp = icmp ult i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_sle_254_inc_var
-; CHECK-COMMON: add
-; CHECK-COMMON: sxtb
-; CHECK-COMMON: cmp
-define i32 @test_sle_254_inc_var(i8 %x, i8 %y) {
-entry:
-  %add = add i8 %x, %y
-  %cmp = icmp sle i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_ugt_1_dec_imm:
-; CHECK-COMMON:      subs    r1, r0, #1
-; CHECK-COMMON-NEXT: movs    r0, #47
-; CHECK-COMMON-NEXT: cmp     r1, #1
-; CHECK-COMMON-NEXT: it      hi
-; CHECK-COMMON-NEXT: movhi   r0, #35
-define i32 @test_ugt_1_dec_imm(i8 zeroext %x) {
-entry:
-  %add = add i8 %x, -1
-  %cmp = icmp ugt i8 %add, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_sgt_1_dec_imm
-; CHECK-COMMON: subs
-; CHECK-COMMON: sxtb
-; CHECK-COMMON: cmp
-define i32 @test_sgt_1_dec_imm(i8 %x) {
-entry:
-  %add = add i8 %x, -1
-  %cmp = icmp sgt i8 %add, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_ugt_1_dec_var:
-; CHECK-NODSP:      subs    r0, r0, r1
-; CHECK-NODSP-NEXT: uxtb    r1, r0
-; CHECK-NODSP-NEXT: movs    r0, #47
-; CHECK-NODSP-NEXT: cmp     r1, #1
-; CHECK-NODSP-NEXT: it      hi
-; CHECK-NODSP-NEXT: movhi   r0, #35
-
-; CHECK-DSP:      usub8   r1, r0, r1
-; CHECK-DSP-NEXT: movs    r0, #47
-; CHECK-DSP-NEXT: cmp     r1, #1
-; CHECK-DSP-NEXT: it      hi
-; CHECK-DSP-NEXT: movhi   r0, #35
-define i32 @test_ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
-entry:
-  %sub = sub i8 %x, %y
-  %cmp = icmp ugt i8 %sub, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: test_sge_1_dec_var
-; CHECK-COMMON: sub
-; CHECK-COMMON: sxtb
-; CHECK-COMMON: cmp
-define i32 @test_sge_1_dec_var(i8 %x, i8 %y) {
-entry:
-  %sub = sub i8 %x, %y
-  %cmp = icmp sge i8 %sub, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: dsp_imm1:
-; CHECK-DSP:      eors    r1, r0
-; CHECK-DSP-NEXT: and     r0, r0, #7
-; CHECK-DSP-NEXT: subs    r0, r0, r1
-; CHECK-DSP-NEXT: adds    r0, #1
-; CHECK-DSP-NEXT: uxtb    r1, r0
-; CHECK-DSP-NEXT: movs    r0, #47
-; CHECK-DSP-NEXT: cmp     r1, #254
-; CHECK-DSP-NEXT: it      lo
-; CHECK-DSP-NEXT: movlo   r0, #35
-
-; CHECK-DSP-IMM:      eors    r1, r0
-; CHECK-DSP-IMM-NEXT: and     r0, r0, #7
-; CHECK-DSP-IMM-NEXT: usub8   r0, r0, r1
-; CHECK-DSP-IMM-NEXT: movs    r1, #1
-; CHECK-DSP-IMM-NEXT: uadd8   r1, r0, r1
-; CHECK-DSP-IMM-NEXT: movs    r0, #47
-; CHECK-DSP-IMM-NEXT: cmp     r1, #254
-; CHECK-DSP-IMM-NEXT: it      lo
-; CHECK-DSP-IMM-NEXT: movlo   r0, #35
-define i32 @dsp_imm1(i8 zeroext %x, i8 zeroext %y) {
-entry:
-  %xor = xor i8 %x, %y
-  %and = and i8 %x, 7
-  %sub = sub i8 %and, %xor
-  %add = add i8 %sub, 1
-  %cmp = icmp ult i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: dsp_var:
-; CHECK-COMMON:   eors    r1, r0
-; CHECK-COMMON:   and     r2, r0, #7
-; CHECK-NODSP:    subs    r1, r2, r1
-; CHECK-NODSP:    add.w   r0, r1, r0, lsl #1
-; CHECK-NODSP:    uxtb    r1, r0
-; CHECK-DSP:      usub8   r1, r2, r1
-; CHECK-DSP:      lsls    r0, r0, #1
-; CHECK-DSP:      uadd8   r1, r1, r0
-; CHECK-DSP-NOT:  uxt
-; CHECK-COMMON:   movs    r0, #47
-; CHECK-COMMON:   cmp     r1, #254
-; CHECK-COMMON:   it      lo
-; CHECK-COMMON:   movlo   r0, #35
-define i32 @dsp_var(i8 zeroext %x, i8 zeroext %y) {
-  %xor = xor i8 %x, %y
-  %and = and i8 %x, 7
-  %sub = sub i8 %and, %xor
-  %mul = shl nuw i8 %x, 1
-  %add = add i8 %sub, %mul
-  %cmp = icmp ult i8 %add, 254
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: store_dsp_res
-; CHECK-DSP: usub8 
-; CHECK-DSP: strb
-define void @store_dsp_res(i8* %in, i8* %out, i8 %compare) {
-  %first = getelementptr inbounds i8, i8* %in, i32 0
-  %second = getelementptr inbounds i8, i8* %in, i32 1
-  %ld0 = load i8, i8* %first
-  %ld1 = load i8, i8* %second
-  %xor = xor i8 %ld0, -1
-  %cmp = icmp ult i8 %compare, %ld1
-  %select = select i1 %cmp, i8 %compare, i8 %xor
-  %sub = sub i8 %ld0, %select
-  store i8 %sub, i8* %out, align 1
-  ret void
-}
-
-; CHECK-COMMON-LABEL: ugt_1_dec_imm:
-; CHECK-COMMON:      subs    r1, r0, #1
-; CHECK-COMMON-NEXT: movs    r0, #47
-; CHECK-COMMON-NEXT: cmp     r1, #1
-; CHECK-COMMON-NEXT: it      hi
-; CHECK-COMMON-NEXT: movhi   r0, #35
-define i32 @ugt_1_dec_imm(i8 zeroext %x) {
-entry:
-  %add = add i8 %x, -1
-  %cmp = icmp ugt i8 %add, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: ugt_1_dec_var:
-; CHECK-NODSP:      subs    r0, r0, r1
-; CHECK-NODSP-NEXT: uxtb    r1, r0
-; CHECK-NODSP-NEXT: movs    r0, #47
-; CHECK-NODSP-NEXT: cmp     r1, #1
-; CHECK-NODSP-NEXT: it      hi
-; CHECK-NODSP-NEXT: movhi   r0, #35
-
-; CHECK-DSP:      usub8   r1, r0, r1
-; CHECK-DSP-NEXT: movs    r0, #47
-; CHECK-DSP-NEXT: cmp     r1, #1
-; CHECK-DSP-NEXT: it      hi
-; CHECK-DSP-NEXT: movhi   r0, #35
-define i32 @ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
-entry:
-  %sub = sub i8 %x, %y
-  %cmp = icmp ugt i8 %sub, 1
-  %res = select i1 %cmp, i32 35, i32 47
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: icmp_eq_minus_one
-; CHECK-COMMON: cmp {{r[0-9]+}}, #255
-define i32 @icmp_eq_minus_one(i8* %ptr) {
-  %load = load i8, i8* %ptr, align 1
-  %conv = zext i8 %load to i32
-  %cmp = icmp eq i8 %load, -1
-  %ret = select i1 %cmp, i32 %conv, i32 -1
-  ret i32 %ret
-}
-
-; CHECK-COMMON-LABEL: icmp_not
-; CHECK-COMMON: movw r2, #65535
-; CHECK-COMMON: eors r2, r0
-; CHECK-COMMON: movs r0, #32
-; CHECK-COMMON: cmp r2, r1
-define i32 @icmp_not(i16 zeroext %arg0, i16 zeroext %arg1) {
-  %not = xor i16 %arg0, -1
-  %cmp = icmp eq i16 %not, %arg1
-  %res = select i1 %cmp, i32 16, i32 32
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: icmp_i1
-; CHECK-NOT: uxt
-define i32 @icmp_i1(i1* %arg0, i1 zeroext %arg1, i32 %a, i32 %b) {
-entry:
-  %load = load i1, i1* %arg0
-  %not = xor i1 %load, 1
-  %cmp = icmp eq i1 %arg1, %not
-  %res = select i1 %cmp, i32 %a, i32 %b
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: icmp_i7
-; CHECK-COMMON: ldrb
-; CHECK-COMMON: cmp
-define i32 @icmp_i7(i7* %arg0, i7 zeroext %arg1, i32 %a, i32 %b) {
-entry:
-  %load = load i7, i7* %arg0
-  %add = add nuw i7 %load, 1
-  %cmp = icmp ult i7 %arg1, %add
-  %res = select i1 %cmp, i32 %a, i32 %b
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: icmp_i15
-; CHECK-COMMON: movw [[MINUS_ONE:r[0-9]+]], #32767
-define i32 @icmp_i15(i15 zeroext %arg0, i15 zeroext %arg1) {
-  %xor = xor i15 %arg0, -1
-  %cmp = icmp eq i15 %xor, %arg1
-  %res = select i1 %cmp, i32 21, i32 42
-  ret i32 %res
-}
-
-; CHECK-COMMON-LABEL: icmp_minus_imm
-; CHECK-NODSP: subs [[SUB:r[0-9]+]],
-; CHECK-NODSP: uxtb [[UXT:r[0-9]+]],
-; CHECK-NODSP: cmp [[UXT]], #251
-
-; CHECK-DSP: subs [[SUB:r[0-9]+]],
-; CHECK-DSP: uxtb [[UXT:r[0-9]+]],
-; CHECK-DSP: cmp [[UXT]], #251
-
-; CHECK-DSP-IMM: ldrb [[A:r[0-9]+]],
-; CHECK-DSP-IMM: movs  [[MINUS_7:r[0-9]+]], #249
-; CHECK-DSP-IMM: uadd8 [[RES:r[0-9]+]], [[A]], [[MINUS_7]]
-; CHECK-DSP-IMM: cmp [[RES]], #251
-define i32 @icmp_minus_imm(i8* %a) {
-entry:
-  %0 = load i8, i8* %a, align 1
-  %add.i = add i8 %0, -7
-  %cmp = icmp ugt i8 %add.i, -5
-  %conv1 = zext i1 %cmp to i32
-  ret i32 %conv1
-}
-
-; CHECK-COMMON-LABEL: mul_with_neg_imm
-; CHECK-COMMON-NOT: uxtb
-; CHECK-COMMON:     and [[BIT0:r[0-9]+]], r0, #1
-; CHECK-COMMON:     add.w [[MUL32:r[0-9]+]], [[BIT0]], [[BIT0]], lsl #5
-; CHECK-COMMON:     cmp.w r0, [[MUL32]], lsl #2
-define void @mul_with_neg_imm(i32, i32* %b) {
-entry:
-  %1 = trunc i32 %0 to i8
-  %2 = and i8 %1, 1
-  %conv.i = mul nuw i8 %2, -124
-  %tobool = icmp eq i8 %conv.i, 0
-  br i1 %tobool, label %if.end, label %if.then
-
-if.then:
-  store i32 0, i32* %b, align 4
-  br label %if.end
-
-if.end:
-  ret void
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll
deleted file mode 100644
index c446ddbdd07a..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll
+++ /dev/null
@@ -1,279 +0,0 @@
-; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 -mattr=-use-misched %s -arm-disable-cgp=false -o - | FileCheck %s
-
-; CHECK: overflow_add
-; CHECK: add
-; CHECK: uxth
-; CHECK: cmp
-define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) {
-  %add = add i16 %a, %b
-  %or = or i16 %add, 1
-  %cmp = icmp ugt i16 %or, 1024
-  %res = select i1 %cmp, i16 2, i16 5
-  ret i16 %res
-}
-
-; CHECK-LABEL: overflow_sub
-; CHECK: sub
-; CHECK: uxth
-; CHECK: cmp
-define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
-  %add = sub i16 %a, %b
-  %or = or i16 %add, 1
-  %cmp = icmp ugt i16 %or, 1024
-  %res = select i1 %cmp, i16 2, i16 5
-  ret i16 %res
-}
-
-; CHECK-LABEL: overflow_mul
-; CHECK: mul
-; CHECK: uxth
-; CHECK: cmp
-define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
-  %add = mul i16 %a, %b
-  %or = or i16 %add, 1
-  %cmp = icmp ugt i16 %or, 1024
-  %res = select i1 %cmp, i16 2, i16 5
-  ret i16 %res
-}
-
-; CHECK-LABEL: overflow_shl
-; CHECK-COMMON: lsl
-; CHECK-COMMON: uxth
-; CHECK-COMMON: cmp
-define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
-  %add = shl i16 %a, %b
-  %or = or i16 %add, 1
-  %cmp = icmp ugt i16 %or, 1024
-  %res = select i1 %cmp, i16 2, i16 5
-  ret i16 %res
-}
-
-; CHECK-LABEL: overflow_add_no_consts:
-; CHECK:  add r0, r1
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], r2
-; CHECK:  movhi r0, #8
-define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
-  %add = add i8 %a, %b
-  %cmp = icmp ugt i8 %add, %limit
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: overflow_add_const_limit:
-; CHECK:  add r0, r1
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], #128
-; CHECK:  movhi r0, #8
-define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
-  %add = add i8 %a, %b
-  %cmp = icmp ugt i8 %add, 128
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: overflow_add_positive_const_limit:
-; CHECK:  adds r0, #1
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], #128
-; CHECK:  movhi r0, #8
-define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
-  %add = add i8 %a, 1
-  %cmp = icmp ugt i8 %add, 128
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: unsafe_add_underflow:
-; CHECK: movs	r1, #16
-; CHECK: cmp	r0, #1
-; CHECK: it	eq
-; CHECK: moveq	r1, #8
-; CHECK: mov	r0, r1
-define i32 @unsafe_add_underflow(i8 zeroext %a) {
-  %add = add i8 %a, -2
-  %cmp = icmp ugt i8 %add, 254
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: safe_add_underflow:
-; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #1
-; CHECK-NOT:  uxtb
-; CHECK:      cmp [[MINUS_1]], #254
-; CHECK:      movhi r0, #8
-define i32 @safe_add_underflow(i8 zeroext %a) {
-  %add = add i8 %a, -1
-  %cmp = icmp ugt i8 %add, 254
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: safe_add_underflow_neg:
-; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #2
-; CHECK-NOT:  uxtb
-; CHECK:      cmp [[MINUS_1]], #251
-; CHECK:      movlo r0, #8
-define i32 @safe_add_underflow_neg(i8 zeroext %a) {
-  %add = add i8 %a, -2
-  %cmp = icmp ule i8 %add, -6
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: overflow_sub_negative_const_limit:
-; CHECK:  adds r0, #1
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], #128
-; CHECK:  movhi r0, #8
-define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
-  %sub = sub i8 %a, -1
-  %cmp = icmp ugt i8 %sub, 128
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: unsafe_sub_underflow:
-; CHECK:  subs r0, #6
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], #250
-; CHECK:  movhi r0, #8
-define i32 @unsafe_sub_underflow(i8 zeroext %a) {
-  %sub = sub i8 %a, 6
-  %cmp = icmp ugt i8 %sub, 250
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: safe_sub_underflow:
-; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #1
-; CHECK-NOT:  uxtb
-; CHECK:      cmp [[MINUS_1]], #255
-; CHECK:      movlo r0, #8
-define i32 @safe_sub_underflow(i8 zeroext %a) {
-  %sub = sub i8 %a, 1
-  %cmp = icmp ule i8 %sub, 254
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: safe_sub_underflow_neg
-; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #4
-; CHECK-NOT:  uxtb
-; CHECK:      cmp [[MINUS_1]], #250
-; CHECK:      movhi r0, #8
-define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
-  %sub = sub i8 %a, 4
-  %cmp = icmp uge i8 %sub, -5
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK-LABEL: unsafe_sub_underflow_neg
-; CHECK:  subs r0, #4
-; CHECK:  uxtb [[EXT:r[0-9]+]], r0
-; CHECK:  cmp [[EXT]], #253
-; CHECK:  movlo r0, #8
-define i32 @unsafe_sub_underflow_neg(i8 zeroext %a) {
-  %sub = sub i8 %a, 4
-  %cmp = icmp ult i8 %sub, -3
-  %res = select i1 %cmp, i32 8, i32 16
-  ret i32 %res
-}
-
-; CHECK:      rsb.w [[RSUB:r[0-9]+]], r0, #248
-; CHECK-NOT:  uxt
-; CHECK:      cmp [[RSUB]], #252
-define i32 @safe_sub_imm_var(i8* %b) {
-entry:
-  %0 = load i8, i8* %b, align 1
-  %sub = sub nuw nsw i8 -8, %0
-  %cmp = icmp ugt i8 %sub, 252
-  %conv4 = zext i1 %cmp to i32
-  ret i32 %conv4
-}
-
-; CHECK-LABEL: safe_sub_var_imm
-; CHECK:      sub.w [[ADD:r[0-9]+]], r0, #248
-; CHECK-NOT:  uxt
-; CHECK:      cmp [[ADD]], #252
-define i32 @safe_sub_var_imm(i8* %b) {
-entry:
-  %0 = load i8, i8* %b, align 1
-  %sub = sub nuw nsw i8 %0, -8
-  %cmp = icmp ugt i8 %sub, 252
-  %conv4 = zext i1 %cmp to i32
-  ret i32 %conv4
-}
-
-; CHECK-LABEL: safe_add_imm_var
-; CHECK:      add.w [[ADD:r[0-9]+]], r0, #129
-; CHECK-NOT:  uxt
-; CHECK:      cmp [[ADD]], #127
-define i32 @safe_add_imm_var(i8* %b) {
-entry:
-  %0 = load i8, i8* %b, align 1
-  %add = add nuw nsw i8 -127, %0
-  %cmp = icmp ugt i8 %add, 127
-  %conv4 = zext i1 %cmp to i32
-  ret i32 %conv4
-}
-
-; CHECK-LABEL: safe_add_var_imm
-; CHECK:      add.w [[SUB:r[0-9]+]], r0, #129
-; CHECK-NOT:  uxt
-; CHECK:      cmp [[SUB]], #127
-define i32 @safe_add_var_imm(i8* %b) {
-entry:
-  %0 = load i8, i8* %b, align 1
-  %add = add nuw nsw i8 %0, -127
-  %cmp = icmp ugt i8 %add, 127
-  %conv4 = zext i1 %cmp to i32
-  ret i32 %conv4
-}
-
-; CHECK-LABEL: convert_add_order
-; CHECK: orr{{.*}}, #1
-; CHECK: sub{{.*}}, #40
-; CHECK-NOT: uxt
-define i8 @convert_add_order(i8 zeroext %arg) {
-  %mask.0 = and i8 %arg, 1
-  %mask.1 = and i8 %arg, 2
-  %shl = or i8 %arg, 1
-  %add = add nuw i8 %shl, 10
-  %cmp.0 = icmp ult i8 %add, 60
-  %sub = add nsw i8 %shl, -40
-  %cmp.1 = icmp ult i8 %sub, 20
-  %mask.sel = select i1 %cmp.1, i8 %mask.0, i8 %mask.1
-  %res = select i1 %cmp.0, i8 %mask.sel, i8 %arg
-  ret i8 %res
-}
-
-; CHECK-LABEL: underflow_if_sub
-; CHECK: add{{.}} [[ADD:r[0-9]+]], #245
-; CHECK: cmp [[ADD]], r1
-define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
-  %cmp = icmp sgt i32 %arg, 0
-  %conv = zext i1 %cmp to i32
-  %and = and i32 %arg, %conv
-  %trunc = trunc i32 %and to i8
-  %conv1 = add nuw nsw i8 %trunc, -11
-  %cmp.1 = icmp ult i8 %conv1, %arg1
-  %res = select i1 %cmp.1, i8 %conv1, i8 100
-  ret i8 %res
-}
-
-; CHECK-LABEL: underflow_if_sub_signext
-; CHECK:      cmp r0, #0
-; CHECK-NEXT: uxtb  r1, r1
-; CHECK-NOT:  xtb
-define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
-  %cmp = icmp sgt i32 %arg, 0
-  %conv = zext i1 %cmp to i32
-  %and = and i32 %arg, %conv
-  %trunc = trunc i32 %and to i8
-  %conv1 = add nuw nsw i8 %trunc, -11
-  %cmp.1 = icmp ugt i8 %arg1, %conv1
-  %res = select i1 %cmp.1, i8 %conv1, i8 100
-  ret i8 %res
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll
deleted file mode 100644
index 9b07a80e9a1c..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll
+++ /dev/null
@@ -1,218 +0,0 @@
-; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON
-; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON
-; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false -arm-enable-scalar-dsp=true -mcpu=cortex-m33 %s -o - | FileCheck %s --check-prefix=CHECK-COMMON
-; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK-COMMON
-
-; Test that ARMCodeGenPrepare can handle:
-; - loops
-; - call operands
-; - call return values
-; - ret instructions
-; We use nuw on the arithmetic instructions to avoid complications.
-
-; Check that the arguments are extended but then nothing else is.
-; This also ensures that the pass can handle loops.
-; CHECK-COMMON-LABEL: phi_feeding_phi_args
-; CHECK-COMMON: uxtb
-; CHECK-COMMON: uxtb
-; CHECK-NOT: uxtb
-define void @phi_feeding_phi_args(i8 %a, i8 %b) {
-entry:
-  %0 = icmp ugt i8 %a, %b
-  br i1 %0, label %preheader, label %empty
-
-empty:
-  br label %preheader
-
-preheader:
-  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
-  br label %loop
-
-loop:
-  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
-  %cmp = icmp ult i8 %val, 254
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %inc = sub nuw i8 %val, 2
-  br label %if.end
-
-if.else:
-  %inc1 = shl nuw i8 %val, 1
-  br label %if.end
-
-if.end:
-  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
-  %cmp1 = icmp eq i8 %inc2, 255
-  br i1 %cmp1, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-; Same as above, but as the args are zeroext, we shouldn't see any uxts.
-; CHECK-COMMON-LABEL: phi_feeding_phi_zeroext_args
-; CHECK-COMMON-NOT: uxt
-define void @phi_feeding_phi_zeroext_args(i8 zeroext %a, i8 zeroext %b) {
-entry:
-  %0 = icmp ugt i8 %a, %b
-  br i1 %0, label %preheader, label %empty
-
-empty:
-  br label %preheader
-
-preheader:
-  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
-  br label %loop
-
-loop:
-  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
-  %cmp = icmp ult i8 %val, 254
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %inc = sub nuw i8 %val, 2
-  br label %if.end
-
-if.else:
-  %inc1 = shl nuw i8 %val, 1
-  br label %if.end
-
-if.end:
-  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
-  %cmp1 = icmp eq i8 %inc2, 255
-  br i1 %cmp1, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-; Just check that phis also work with i16s.
-; CHECK-COMMON-LABEL: phi_i16:
-; CHECK-COMMON-NOT:   uxt
-define void @phi_i16() {
-entry:
-  br label %loop
-
-loop:
-  %val = phi i16 [ 0, %entry ], [ %inc2, %if.end ]
-  %cmp = icmp ult i16 %val, 128
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %inc = add nuw i16 %val, 2
-  br label %if.end
-
-if.else:
-  %inc1 = add nuw i16 %val, 1
-  br label %if.end
-
-if.end:
-  %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ]
-  %cmp1 = icmp ult i16 %inc2, 253
-  br i1 %cmp1, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-; CHECK-COMMON-LABEL: ret_i8
-; CHECK-COMMON-NOT:   uxt
-define i8 @ret_i8() {
-entry:
-  br label %loop
-
-loop:
-  %val = phi i8 [ 0, %entry ], [ %inc2, %if.end ]
-  %cmp = icmp ult i8 %val, 128
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %inc = add nuw i8 %val, 2
-  br label %if.end
-
-if.else:
-  %inc1 = add nuw i8 %val, 1
-  br label %if.end
-
-if.end:
-  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
-  %cmp1 = icmp ult i8 %inc2, 253
-  br i1 %cmp1, label %exit, label %loop
-
-exit:
-  ret i8 %inc2
-}
-
-; CHECK-COMMON-LABEL: phi_multiple_undefs
-; CHECK-COMMON-NOT:   uxt
-define i16 @phi_multiple_undefs(i16 zeroext %arg) {
-entry:
-  br label %loop
-
-loop:
-  %val = phi i16 [ undef, %entry ], [ %inc2, %if.end ]
-  %cmp = icmp ult i16 %val, 128
-  br i1 %cmp, label %if.then, label %if.else
-
-if.then:
-  %inc = add nuw i16 %val, 2
-  br label %if.end
-
-if.else:
-  %inc1 = add nuw i16 %val, 1
-  br label %if.end
-
-if.end:
-  %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ]
-  %unrelated = phi i16 [ undef, %if.then ], [ %arg, %if.else ]
-  %cmp1 = icmp ult i16 %inc2, 253
-  br i1 %cmp1, label %loop, label %exit
-
-exit:
-  ret i16 %unrelated
-}
-
-; CHECK-COMMON-LABEL: promote_arg_return
-; CHECK-COMMON-NOT: uxt
-; CHECK-COMMON: strb
-define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, i8* %res) {
-  %add = add nuw i16 %arg1, 15
-  %mul = mul nuw nsw i16 %add, 3
-  %cmp = icmp ult i16 %mul, %arg2
-  %conv = zext i1 %cmp to i8
-  store i8 %conv, i8* %res
-  ret i16 %arg1
-}
-
-; CHECK-COMMON-LABEL: signext_bitcast_phi_select
-; CHECK: uxth [[UXT:r[0-9]+]], r0
-; CHECK: sxth [[SXT:r[0-9]+]], [[UXT]]
-; CHECK: cmp [[SXT]],
-; CHECK-NOT: xth
-define i16 @signext_bitcast_phi_select(i16 signext %start, i16* %in) {
-entry:
-  %const = bitcast i16 -1 to i16
-  br label %for.body
-
-for.body:
-  %idx = phi i16 [ %select, %if.else ], [ %start, %entry ]
-  %cmp.i = icmp sgt i16 %idx, %const
-  br i1 %cmp.i, label %exit, label %if.then
-
-if.then:
-  %idx.next = getelementptr i16, i16* %in, i16 %idx
-  %ld = load i16, i16* %idx.next, align 2
-  %cmp1.i = icmp eq i16 %ld, %idx
-  br i1 %cmp1.i, label %exit, label %if.else
-
-if.else:
-  %lobit = lshr i16 %idx, 15
-  %lobit.not = xor i16 %lobit, 1
-  %select = add nuw i16 %lobit.not, %idx
-  br label %for.body
-
-exit:
-  %res = phi i16 [ %ld, %if.then ], [ 0, %for.body ]
-  ret i16 %res
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll
deleted file mode 100644
index e7f800232d45..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll
+++ /dev/null
@@ -1,135 +0,0 @@
-; RUN: llc -mtriple=thumbv8 -arm-disable-cgp=false %s -o - | FileCheck %s
-; RUN: llc -mtriple=armv8 -arm-disable-cgp=false %s -o - | FileCheck %s
-
-; CHECK-LABEL: phi_pointers
-; CHECK-NOT: uxt
-define void @phi_pointers(i16* %a, i16* %b, i8 zeroext %M, i8 zeroext %N) {
-entry:
-  %add = add nuw i8 %M, 1
-  %and = and i8 %add, 1
-  %cmp = icmp ugt i8 %add, %N
-  %base = select i1 %cmp, i16* %a, i16* %b
-  %other = select i1 %cmp, i16* %b, i16* %b
-  br label %loop
-
-loop:
-  %ptr = phi i16* [ %base, %entry ], [ %gep, %loop ]
-  %idx = phi i8 [ %and, %entry ], [ %inc, %loop ]
-  %load = load i16, i16* %ptr, align 2
-  %inc = add nuw nsw i8 %idx, 1
-  %gep = getelementptr inbounds i16, i16* %ptr, i8 %inc
-  %cond = icmp eq i16* %gep, %other
-  br i1 %cond, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-; CHECK-LABEL: phi_pointers_null
-; CHECK-NOT: uxt
-define void @phi_pointers_null(i16* %a, i16* %b, i8 zeroext %M, i8 zeroext %N) {
-entry:
-  %add = add nuw i8 %M, 1
-  %and = and i8 %add, 1
-  %cmp = icmp ugt i8 %add, %N
-  %base = select i1 %cmp, i16* %a, i16* %b
-  %other = select i1 %cmp, i16* %b, i16* %b
-  %cmp.1 = icmp eq i16* %base, %other
-  br i1 %cmp.1, label %fail, label %loop
-
-fail:
-  br label %loop
-
-loop:
-  %ptr = phi i16* [ %base, %entry ], [ null, %fail ], [ %gep, %if.then ]
-  %idx = phi i8 [ %and, %entry ], [ 0, %fail ], [ %inc, %if.then ]
-  %undef = icmp eq i16* %ptr, undef
-  br i1 %undef, label %exit, label %if.then
-
-if.then:
-  %load = load i16, i16* %ptr, align 2
-  %inc = add nuw nsw i8 %idx, 1
-  %gep = getelementptr inbounds i16, i16* %ptr, i8 %inc
-  %cond = icmp eq i16* %gep, %other
-  br i1 %cond, label %exit, label %loop
-
-exit:
-  ret void
-}
-
-declare i8 @do_something_with_ptr(i8, i16*)
-
-; CHECK-LABEL: call_pointer
-; CHECK-NOT: uxt
-define i8 @call_pointer(i8 zeroext %x, i8 zeroext %y, i16* %a, i16* %b) {
-  %or = or i8 %x, %y
-  %shr = lshr i8 %or, 1
-  %add = add nuw i8 %shr, 2
-  %cmp = icmp ne i8 %add, 0
-  %ptr = select i1 %cmp, i16* %a, i16* %b
-  %call = tail call zeroext i8 @do_something_with_ptr(i8 %shr, i16* %ptr)
-  ret i8 %call
-}
-
-; CHECK-LABEL: pointer_to_pointer
-; CHECK-NOT: uxt
-define i16 @pointer_to_pointer(i16** %arg, i16 zeroext %limit) {
-entry:
-  %addr = load i16*, i16** %arg
-  %val = load i16, i16* %addr
-  %add = add nuw i16 %val, 7
-  %cmp = icmp ult i16 %add, 256
-  %res = select i1 %cmp, i16 128, i16 255
-  ret i16 %res
-}
-
-; CHECK-LABEL: gep_2d_array
-; CHECK-NOT: uxt
-define i8 @gep_2d_array(i8** %a, i8 zeroext %arg) {
-entry:
-  %arrayidx.us = getelementptr inbounds i8*, i8** %a, i32 0
-  %0 = load i8*, i8** %arrayidx.us, align 4
-  %1 = load i8, i8* %0, align 1
-  %sub = sub nuw i8 %1, 1
-  %cmp = icmp ult i8 %sub, %arg
-  %res = select i1 %cmp, i8 27, i8 54
-  ret i8 %res
-}
-
-; CHECK-LABEL: gep_2d_array_loop
-; CHECK-NOT: uxt
-define void @gep_2d_array_loop(i16** nocapture readonly %a, i16** nocapture readonly %b, i32 %N) {
-entry:
-  %cmp30 = icmp eq i32 %N, 0
-  br i1 %cmp30, label %for.cond.cleanup, label %for.cond1.preheader.us
-
-for.cond1.preheader.us:
-  %y.031.us = phi i32 [ %inc13.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %entry ]
-  br label %for.body4.us
-
-for.body4.us:
-  %x.029.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
-  %arrayidx.us = getelementptr inbounds i16*, i16** %a, i32 %x.029.us
-  %0 = load i16*, i16** %arrayidx.us, align 4
-  %arrayidx5.us = getelementptr inbounds i16, i16* %0, i32 %y.031.us
-  %1 = load i16, i16* %arrayidx5.us, align 2
-  %dec.us = add nuw i16 %1, -1
-  %cmp6.us = icmp ult i16 %dec.us, 16383
-  %shl.us = shl nuw i16 %dec.us, 2
-  %spec.select.us = select i1 %cmp6.us, i16 %shl.us, i16 %dec.us
-  %arrayidx10.us = getelementptr inbounds i16*, i16** %b, i32 %x.029.us
-  %2 = load i16*, i16** %arrayidx10.us, align 4
-  %arrayidx11.us = getelementptr inbounds i16, i16* %2, i32 %y.031.us
-  store i16 %spec.select.us, i16* %arrayidx11.us, align 2
-  %inc.us = add nuw i32 %x.029.us, 1
-  %exitcond = icmp eq i32 %inc.us, %N
-  br i1 %exitcond, label %for.cond1.for.cond.cleanup3_crit_edge.us, label %for.body4.us
-
-for.cond1.for.cond.cleanup3_crit_edge.us:
-  %inc13.us = add nuw i32 %y.031.us, 1
-  %exitcond32 = icmp eq i32 %inc13.us, %N
-  br i1 %exitcond32, label %for.cond.cleanup, label %for.cond1.preheader.us
-
-for.cond.cleanup:
-  ret void
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll
deleted file mode 100644
index 15030bd38660..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll
+++ /dev/null
@@ -1,108 +0,0 @@
-; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 -arm-disable-cgp=false -mattr=-use-misched %s -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
-; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP
-; RUN: llc -mtriple=thumbv8 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-DSP-IMM
-
-; CHECK-COMMON-LABEL: eq_sgt
-; CHECK-NODSP: add
-; CHECK-NODSP: uxtb
-; CHECK-NODSP: sxtb
-; CHECK-NODSP: cmp
-; CHECK-NODSP: sub
-; CHECK-NODSP: sxtb
-; CHECK-NODSP: cmp
-
-; CHECK-DSP: uadd8
-; CHECK-DSP: sub
-; CHECK-DSP: cmp
-; CHECK-DSP: sxtb
-; CHECK-DSP: sxtb
-; CHECK-DSP: cmp
-
-; CHECK-DSP-IMM: uadd8 [[ADD:r[0-9]+]],
-; CHECK-DSP-IMM: cmp [[ADD]],
-; CHECK-DSP-IMM: subs [[SUB:r[0-9]+]],
-; CHECK-DSP-IMM: sxtb [[SEXT0:r[0-9]+]], [[ADD]]
-; CHECK-DSP-IMM: sxtb [[SEXT1:r[0-9]+]], [[SUB]]
-; CHECK-DSP-IMM: cmp [[SEXT1]], [[SEXT0]]
-define i8 @eq_sgt(i8* %x, i8 *%y, i8 zeroext %z) {
-entry:
-  %load0 = load i8, i8* %x, align 1
-  %load1 = load i8, i8* %y, align 1
-  %add = add i8 %load0, %z
-  %sub = sub i8 %load1, 1
-  %cmp = icmp eq i8 %add, 200
-  %cmp1 = icmp sgt i8 %sub, %add
-  %res0 = select i1 %cmp, i8 35, i8 47
-  %res1 = select i1 %cmp1, i8 %res0, i8 %sub
-  ret i8 %res1
-}
-
-; CHECK-COMMON-LABEL: ugt_slt
-; CHECK-NODSP: sub
-; CHECK-NODSP: sxth
-; CHECK-NODSP: uxth
-; CHECK-NODSP: add
-; CHECK-NODSP: sxth
-; CHECK-NODSP: cmp
-; CHECK-NODSP: cmp
-
-; CHECK-DSP: sub
-; CHECK-DSP: sxth
-; CHECK-DSP: add
-; CHECK-DSP: uxth
-; CHECK-DSP: sxth
-; CHECK-DSP: cmp
-; CHECK-DSP: cmp
-
-; CHECK-DSP-IMM: uadd16 [[ADD:r[0-9]+]],
-; CHECK-DSP-IMM: sxth.w [[SEXT:r[0-9]+]], [[ADD]]
-; CHECK-DSP-IMM: sxth [[ARG:r[0-9]+]], r2
-; CHECK-DSP-IMM: cmp [[SEXT]], [[ARG]]
-; CHECK-DSP-IMM-NOT: uxt
-; CHECK-DSP-IMM: movs [[ONE:r[0-9]+]], #1
-; CHECK-DSP-IMM: usub16 [[SUB:r[0-9]+]], r1, [[ONE]]
-; CHECK-DSP-IMM: cmp [[SUB]], r2
-define i16 @ugt_slt(i16 *%x, i16 zeroext %y, i16 zeroext %z) {
-entry:
-  %load0 = load i16, i16* %x, align 1
-  %add = add i16 %load0, %z
-  %sub = sub i16 %y, 1
-  %cmp = icmp slt i16 %add, %z
-  %cmp1 = icmp ugt i16 %sub, %z
-  %res0 = select i1 %cmp, i16 35, i16 -1
-  %res1 = select i1 %cmp1, i16 %res0, i16 0
-  ret i16 %res1
-}
-
-; CHECK-COMMON-LABEL: urem_trunc_icmps
-; CHECK-COMMON-NOT: uxt
-; CHECK-COMMON: sxtb [[SEXT:r[0-9]+]],
-; CHECK-COMMON: cmp [[SEXT]], #7
-define void @urem_trunc_icmps(i16** %in, i32* %g, i32* %k) {
-entry:
-  %ptr = load i16*, i16** %in, align 4
-  %ld = load i16, i16* %ptr, align 2
-  %cmp.i = icmp eq i16 %ld, 0
-  br i1 %cmp.i, label %exit, label %cond.false.i
-
-cond.false.i:
-  %rem = urem i16 5, %ld
-  %extract.t = trunc i16 %rem to i8
-  br label %body
-
-body:
-  %cond.in.i.off0 = phi i8 [ %extract.t, %cond.false.i ], [ %add, %for.inc ]
-  %cmp = icmp sgt i8 %cond.in.i.off0, 7
-  %conv5 = zext i1 %cmp to i32
-  store i32 %conv5, i32* %g, align 4
-  %.pr = load i32, i32* %k, align 4
-  %tobool13150 = icmp eq i32 %.pr, 0
-  br i1 %tobool13150, label %for.inc, label %exit
-
-for.inc:
-  %add = add nuw i8 %cond.in.i.off0, 1
-  br label %body
-
-exit:
-  ret void
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed.ll
deleted file mode 100644
index 596893724d20..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-signed.ll
+++ /dev/null
@@ -1,89 +0,0 @@
-; RUN: llc -mtriple=thumbv7em -arm-disable-cgp=false %s -o - | FileCheck %s
-; RUN: llc -mtriple=thumbv8m.main -mattr=+dsp -arm-disable-cgp=false %s -o - | FileCheck %s
-; RUN: llc -mtriple=thumbv7 %s -arm-disable-cgp=false -o - | FileCheck %s
-; RUN: llc -mtriple=armv8 %s -arm-disable-cgp=false -o - | FileCheck %s
-
-; Test to check that ARMCodeGenPrepare doesn't optimised away sign extends.
-; CHECK-LABEL: test_signed_load:
-; CHECK: uxth
-define i16 @test_signed_load(i16* %ptr) {
-  %load = load i16, i16* %ptr
-  %conv0 = zext i16 %load to i32
-  %conv1 = sext i16 %load to i32
-  %cmp = icmp eq i32 %conv0, %conv1
-  %conv2 = zext i1 %cmp to i16
-  ret i16 %conv2
-}
-
-; Don't allow sign bit generating opcodes.
-; CHECK-LABEL: test_ashr:
-; CHECK: sxth
-define i16 @test_ashr(i16 zeroext %arg) {
-  %ashr = ashr i16 %arg, 1
-  %cmp = icmp eq i16 %ashr, 0
-  %conv = zext i1 %cmp to i16
-  ret i16 %conv 
-}
-
-; CHECK-LABEL: test_sdiv:
-; CHECK: sxth
-define i16 @test_sdiv(i16 zeroext %arg) {
-  %sdiv = sdiv i16 %arg, 2
-  %cmp = icmp ne i16 %sdiv, 0
-  %conv = zext i1 %cmp to i16
-  ret i16 %conv 
-}
-
-; CHECK-LABEL: test_srem
-; CHECK: sxth
-define i16 @test_srem(i16 zeroext %arg) {
-  %srem = srem i16 %arg, 4
-  %cmp = icmp ne i16 %srem, 0
-  %conv = zext i1 %cmp to i16
-  ret i16 %conv 
-}
-
-; CHECK-LABEL: test_signext_b
-; CHECK: ldrb [[LDR:r[0-9]+]], [r0]
-; CHECK: uxtab [[UXT:r[0-9]+]], [[LDR]], r1
-; CHECK: cm{{.*}} [[UXT]], #128
-define i32 @test_signext_b(i8* %ptr, i8 signext %arg) {
-entry:
-  %0 = load i8, i8* %ptr, align 1
-  %1 = add nuw nsw i8 %0, %arg
-  %cmp = icmp ult i8 %1, 128
-  %res = select i1 %cmp, i32 42, i32 20894
-  ret i32 %res
-}
-
-; CHECK-LABEL: test_signext_b_ult_slt
-; CHECK: ldrb [[LDR:r[0-9]+]], [r0]
-; CHECK: uxtab [[ADD:r[0-9]+]], [[LDR]], r1
-; CHECK: uxtb [[UXT:r[0-9]+]], r1
-; CHECK: cmp [[ADD]], [[UXT]]
-; CHECK: uxtb [[TRUNC:r[0-9]+]], [[ADD]]
-; CHECK: cmp [[TRUNC]], #127
-define i32 @test_signext_b_ult_slt(i8* %ptr, i8 signext %arg) {
-entry:
-  %0 = load i8, i8* %ptr, align 1
-  %1 = add nuw nsw i8 %0, %arg
-  %cmp = icmp sle i8 %1, 126
-  %cmp.1 = icmp ule i8 %1, %arg
-  %or = and i1 %cmp, %cmp.1
-  %res = select i1 %or, i32 42, i32 57
-  ret i32 %res
-}
-
-; CHECK-LABEL: test_signext_h
-; CHECK: ldrh [[LDR:r[0-9]+]], [r0]
-; CHECK: uxtah [[ADD:r[0-9]+]], [[LDR]], r1
-; CHECK: cm{{.*}} [[ADD]],
-define i32 @test_signext_h(i16* %ptr, i16 signext %arg) {
-entry:
-  %0 = load i16, i16* %ptr, align 1
-  %1 = add nuw nsw i16 %0, %arg
-  %cmp = icmp ult i16 %1, 32768
-  %res = select i1 %cmp, i32 42, i32 20894
-  ret i32 %res
-}
-

diff  --git a/llvm/test/CodeGen/ARM/CGP/arm-cgp-switch.ll b/llvm/test/CodeGen/ARM/CGP/arm-cgp-switch.ll
deleted file mode 100644
index 29c35fbc96e0..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/arm-cgp-switch.ll
+++ /dev/null
@@ -1,168 +0,0 @@
-; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -o - | FileCheck %s
-; RUN: llc -mtriple=thumbv7-linux-android %s -arm-disable-cgp=false -o - | FileCheck %s
-
-; CHECK-LABEL: truncate_source_phi_switch
-; CHECK: ldrb
-; CHECK: uxtb
-define void @truncate_source_phi_switch(i8* %memblock, i8* %store, i16 %arg) {
-entry:
-  %pre = load i8, i8* %memblock, align 1
-  %conv = trunc i16 %arg to i8
-  br label %header
-
-header:
-  %phi.0 = phi i8 [ %pre, %entry ], [ %count, %latch ]
-  %phi.1 = phi i8 [ %conv, %entry ], [ %phi.3, %latch ]
-  %phi.2 = phi i8 [ 0, %entry], [ %count, %latch ]
-  switch i8 %phi.0, label %default [
-    i8 43, label %for.inc.i
-    i8 45, label %for.inc.i.i
-  ]
-
-for.inc.i:
-  %xor = xor i8 %phi.1, 1
-  br label %latch
-
-for.inc.i.i:
-  %and = and i8 %phi.1, 3
-  br label %latch
-
-default:
-  %sub = sub i8 %phi.0, 1
-  %cmp2 = icmp ugt i8 %sub, 4
-  br i1 %cmp2, label %latch, label %exit
-
-latch:
-  %phi.3 = phi i8 [ %xor, %for.inc.i ], [ %and, %for.inc.i.i ], [ %phi.2, %default ]
-  %count = add nuw i8 %phi.2, 1
-  store i8 %count, i8* %store, align 1
-  br label %header
-
-exit:
-  ret void
-}
-
-; CHECK-LABEL: icmp_switch_source:
-; CHECK-NOT: uxt
-define i16 @icmp_switch_source(i16 zeroext %arg) {
-entry:
-  %conv = add nuw i16 %arg, 15
-  %mul = mul nuw nsw i16 %conv, 3
-  switch i16 %arg, label %default [
-    i16 0, label %sw.bb
-    i16 1, label %sw.bb.i
-  ]
-
-sw.bb:
-  %cmp0 = icmp ult i16 %mul, 127
-  %select = select i1 %cmp0, i16 %mul, i16 127
-  br label %exit
-
-sw.bb.i:
-  %cmp1 = icmp ugt i16 %mul, 34
-  %select.i = select i1 %cmp1, i16 %mul, i16 34
-  br label %exit
-
-default:
-  br label %exit
-
-exit:
-  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
-  ret i16 %res
-}
-
-; CHECK-LABEL: icmp_switch_narrow_source:
-; CHECK-NOT: uxt
-define i16 @icmp_switch_narrow_source(i8 zeroext %arg) {
-entry:
-  %conv = zext i8 %arg to i16
-  %add = add nuw i16 %conv, 15
-  %mul = mul nuw nsw i16 %add, 3
-  switch i8 %arg, label %default [
-    i8 0, label %sw.bb
-    i8 1, label %sw.bb.i
-  ]
-
-sw.bb:
-  %cmp0 = icmp ult i16 %mul, 127
-  %select = select i1 %cmp0, i16 %mul, i16 127
-  br label %exit
-
-sw.bb.i:
-  %cmp1 = icmp ugt i16 %mul, 34
-  %select.i = select i1 %cmp1, i16 %mul, i16 34
-  br label %exit
-
-default:
-  br label %exit
-
-exit:
-  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
-  ret i16 %res
-}
-
-; CHECK-LABEL: icmp_switch_trunc:
-; CHECK-NOT: uxt
-define i16 @icmp_switch_trunc(i16 zeroext %arg) {
-entry:
-  %conv = add nuw i16 %arg, 15
-  %mul = mul nuw nsw i16 %conv, 3
-  %trunc = trunc i16 %arg to i3
-  switch i3 %trunc, label %default [
-    i3 0, label %sw.bb
-    i3 1, label %sw.bb.i
-  ]
-
-sw.bb:
-  %cmp0 = icmp ult i16 %mul, 127
-  %select = select i1 %cmp0, i16 %mul, i16 127
-  br label %exit
-
-sw.bb.i:
-  %cmp1 = icmp ugt i16 %mul, 34
-  %select.i = select i1 %cmp1, i16 %mul, i16 34
-  br label %exit
-
-default:
-  br label %exit
-
-exit:
-  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
-  ret i16 %res
-}
-
-%class.ae = type { i8 }
-%class.x = type { i8 }
-%class.v = type { %class.q }
-%class.q = type { i16 }
-declare %class.x* @_ZNK2ae2afEv(%class.ae*) local_unnamed_addr
-declare %class.v* @_ZN1x2acEv(%class.x*) local_unnamed_addr
-
-; CHECK-LABEL: trunc_i16_i9_switch
-; CHECK-NOT: uxt
-define i32 @trunc_i16_i9_switch(%class.ae* %this) {
-entry:
-  %call = tail call %class.x* @_ZNK2ae2afEv(%class.ae* %this)
-  %call2 = tail call %class.v* @_ZN1x2acEv(%class.x* %call)
-  %0 = getelementptr inbounds %class.v, %class.v* %call2, i32 0, i32 0, i32 0
-  %1 = load i16, i16* %0, align 2
-  %2 = trunc i16 %1 to i9
-  %trunc = and i9 %2, -64
-  switch i9 %trunc, label %cleanup.fold.split [
-    i9 0, label %cleanup
-    i9 -256, label %if.then7
-  ]
-
-if.then7:
-  %3 = and i16 %1, 7
-  %tobool = icmp eq i16 %3, 0
-  %cond = select i1 %tobool, i32 2, i32 1
-  br label %cleanup
-
-cleanup.fold.split:
-  br label %cleanup
-
-cleanup:
-  %retval.0 = phi i32 [ %cond, %if.then7 ], [ 0, %entry ], [ 2, %cleanup.fold.split ]
-  ret i32 %retval.0
-}

diff  --git a/llvm/test/CodeGen/ARM/CGP/clear-structures.ll b/llvm/test/CodeGen/ARM/CGP/clear-structures.ll
deleted file mode 100644
index 86459c35dd60..000000000000
--- a/llvm/test/CodeGen/ARM/CGP/clear-structures.ll
+++ /dev/null
@@ -1,75 +0,0 @@
-; RUN: opt -arm-codegenprepare -arm-disable-cgp=false -mtriple=armv8 -verify %s -S -o - | FileCheck %s
-
-; CHECK: clear_structures
-define i32 @clear_structures(i8* nocapture readonly %fmt, [1 x i32] %ap.coerce, i8* %out, void (i32, i8*)* nocapture %write) {
-entry:
-  br label %while.cond.outer
-
-while.cond.outer:
-  %fmt.addr.0.ph = phi i8* [ %fmt, %entry ], [ %fmt.addr.3, %while.cond.outer.backedge ]
-  %0 = load i8, i8* %fmt.addr.0.ph, align 1
-  br label %while.cond
-
-while.cond:
-  switch i8 %0, label %while.cond [
-    i8 0, label %while.end48
-    i8 37, label %while.cond2
-  ]
-
-while.cond2:
-  %flags.0 = phi i32 [ %or, %while.cond2 ], [ 0, %while.cond ]
-  %fmt.addr.0.pn = phi i8* [ %fmt.addr.1, %while.cond2 ], [ %fmt.addr.0.ph, %while.cond ]
-  %fmt.addr.1 = getelementptr inbounds i8, i8* %fmt.addr.0.pn, i32 1
-  %1 = load i8, i8* %fmt.addr.1, align 1
-  ; CHECK: add i8 [[LOAD:%[^ ]+]], -32
-  %sub = add i8 %1, -32
-  %conv6 = zext i8 %sub to i32
-  %shl = shl i32 1, %conv6
-  %and = and i32 %shl, 75785
-  %tobool7 = icmp eq i32 %and, 0
-  %or = or i32 %shl, %flags.0
-  br i1 %tobool7, label %while.cond10.preheader, label %while.cond2
-
-while.cond10.preheader:
-  ; CHECK: [[ADD:%[^ ]+]] = add i8 [[LOAD]], -48
-  ; CHECK: icmp ult i8 [[ADD]], 10
-  %.off = add i8 %1, -48
-  %2 = icmp ult i8 %.off, 10
-  br i1 %2, label %while.cond10, label %while.end18.split
-
-while.cond10:
-  br label %while.cond10
-
-while.end18.split:
-  %cmp20 = icmp eq i8 %1, 46
-  br i1 %cmp20, label %if.then22, label %cond.end
-
-if.then22:
-  %incdec.ptr23 = getelementptr inbounds i8, i8* %fmt.addr.0.pn, i32 2
-  %.pr74 = load i8, i8* %incdec.ptr23, align 1
-  ; CHECK: [[LOAD2:[^ ]+]] = load i8, i8*
-  ; CHECK: [[ZEXT:[^ ]+]] = zext i8 [[LOAD2]] to i32
-  ; CHECK: sub i32 [[ZEXT]], 48
-  %.pr74.off = add i8 %.pr74, -48
-  %3 = icmp ult i8 %.pr74.off, 10
-  br i1 %3, label %while.cond24, label %cond.end
-
-while.cond24:
-  br label %while.cond24
-
-cond.end:
-  %fmt.addr.3 = phi i8* [ %fmt.addr.1, %while.end18.split ], [ %incdec.ptr23, %if.then22 ]
-  %and39 = and i32 %flags.0, 2048
-  %tobool40 = icmp eq i32 %and39, 0
-  br i1 %tobool40, label %while.cond.outer.backedge, label %if.then43
-
-while.cond.outer.backedge:
-  br label %while.cond.outer
-
-if.then43:
-  tail call void %write(i32 43, i8* %out) #1
-  br label %while.cond.outer.backedge
-
-while.end48:
-  ret i32 undef
-}

diff  --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll
index f45302fbc1b3..bfe60c4b53ac 100644
--- a/llvm/test/CodeGen/ARM/O3-pipeline.ll
+++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll
@@ -40,7 +40,7 @@
 ; CHECK-NEXT:      Function Alias Analysis Results
 ; CHECK-NEXT:      Transform functions to use DSP intrinsics
 ; CHECK-NEXT:      Interleaved Access Pass
-; CHECK-NEXT:      ARM IR optimizations
+; CHECK-NEXT:      IR Type Promotion
 ; CHECK-NEXT:      Dominator Tree Construction
 ; CHECK-NEXT:      Natural Loop Information
 ; CHECK-NEXT:      CodeGen Prepare

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/calls.ll b/llvm/test/Transforms/TypePromotion/ARM/calls.ll
new file mode 100644
index 000000000000..cd273c06150f
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/calls.ll
@@ -0,0 +1,342 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define i8 @call_with_imms(i8* %arg) {
+; CHECK-LABEL: @call_with_imms(
+; CHECK-NEXT:    [[CALL:%.*]] = tail call arm_aapcs_vfpcc zeroext i8 @dummy2(i8* nonnull [[ARG:%.*]], i8 zeroext 0, i8 zeroext 0)
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[CALL]], 0
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i8 [[CALL]], i8 1
+; CHECK-NEXT:    ret i8 [[RES]]
+;
+  %call = tail call arm_aapcs_vfpcc zeroext i8 @dummy2(i8* nonnull %arg, i8 zeroext 0, i8 zeroext 0)
+  %cmp = icmp eq i8 %call, 0
+  %res = select i1 %cmp, i8 %call, i8 1
+  ret i8 %res
+}
+
+define i16 @test_call(i8 zeroext %arg) {
+; CHECK-LABEL: @test_call(
+; CHECK-NEXT:    [[CALL:%.*]] = call i8 @dummy_i8(i8 [[ARG:%.*]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[CALL]], -128
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+  %call = call i8 @dummy_i8(i8 %arg)
+  %cmp = icmp ult i8 %call, 128
+  %conv = zext i1 %cmp to i16
+  ret i16 %conv
+}
+
+define i16 @promote_i8_sink_i16_1(i8 zeroext %arg0, i16 zeroext %arg1, i16 zeroext %arg2) {
+; CHECK-LABEL: @promote_i8_sink_i16_1(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[ARG2:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CALL:%.*]] = tail call zeroext i8 @dummy_i8(i8 [[ARG0:%.*]])
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[CALL]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP3]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD]], [[TMP2]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[SEL]] to i16
+; CHECK-NEXT:    [[RES:%.*]] = tail call zeroext i16 @dummy3(i16 [[TMP4]])
+; CHECK-NEXT:    [[TMP5:%.*]] = zext i16 [[RES]] to i32
+; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
+; CHECK-NEXT:    ret i16 [[TMP6]]
+;
+  %call = tail call zeroext i8 @dummy_i8(i8 %arg0)
+  %add = add nuw i8 %call, 1
+  %conv = zext i8 %add to i16
+  %cmp = icmp ne i16 %conv, %arg1
+  %sel = select i1 %cmp, i16 %arg1, i16 %arg2
+  %res = tail call zeroext i16 @dummy3(i16 %sel)
+  ret i16 %res
+}
+
+define i16 @promote_i8_sink_i16_2(i8 zeroext %arg0, i8 zeroext %arg1, i16 zeroext %arg2) {
+; CHECK-LABEL: @promote_i8_sink_i16_2(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CALL:%.*]] = tail call zeroext i8 @dummy_i8(i8 [[ARG0:%.*]])
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[CALL]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP2]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD]], [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP1]] to i8
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[TMP3]] to i16
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i16 [[CONV]], i16 [[ARG2:%.*]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call zeroext i16 @dummy3(i16 [[SEL]])
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+  %call = tail call zeroext i8 @dummy_i8(i8 %arg0)
+  %add = add nuw i8 %call, 1
+  %cmp = icmp ne i8 %add, %arg1
+  %conv = zext i8 %arg1 to i16
+  %sel = select i1 %cmp, i16 %conv, i16 %arg2
+  %res = tail call zeroext i16 @dummy3(i16 %sel)
+  ret i16 %res
+}
+
+ at uc = global i8 42, align 1
+ at LL = global i64 0, align 8
+
+define void @zext_i64() {
+; CHECK-LABEL: @zext_i64(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* @uc, align 1
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[TMP0]] to i64
+; CHECK-NEXT:    store i64 [[CONV]], i64* @LL, align 8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP0]], 42
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 bitcast (i32 (...)* @assert to i32 (i32)*)(i32 [[CONV1]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i8, i8* @uc, align 1
+  %conv = zext i8 %0 to i64
+  store i64 %conv, i64* @LL, align 8
+  %cmp = icmp eq i8 %0, 42
+  %conv1 = zext i1 %cmp to i32
+  %call = tail call i32 bitcast (i32 (...)* @assert to i32 (i32)*)(i32 %conv1)
+  ret void
+}
+
+ at a = global i16* null, align 4
+ at b = global i32 0, align 4
+
+define i32 @constexpr() {
+; CHECK-LABEL: @constexpr(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    store i32 ptrtoint (i32* @b to i32), i32* @b, align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16*, i16** @a, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[TMP0]], align 2
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[TMP1]], ptrtoint (i32* @b to i16)
+; CHECK-NEXT:    store i16 [[OR]], i16* [[TMP0]], align 2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[OR]], 4
+; CHECK-NEXT:    [[CONV3:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 bitcast (i32 (...)* @e to i32 (i32)*)(i32 [[CONV3]])
+; CHECK-NEXT:    ret i32 undef
+;
+entry:
+  store i32 ptrtoint (i32* @b to i32), i32* @b, align 4
+  %0 = load i16*, i16** @a, align 4
+  %1 = load i16, i16* %0, align 2
+  %or = or i16 %1, ptrtoint (i32* @b to i16)
+  store i16 %or, i16* %0, align 2
+  %cmp = icmp ne i16 %or, 4
+  %conv3 = zext i1 %cmp to i32
+  %call = tail call i32 bitcast (i32 (...)* @e to i32 (i32)*)(i32 %conv3) #2
+  ret i32 undef
+}
+
+define fastcc i32 @call_zext_i8_i32(i32 %p_45, i8 zeroext %p_46) {
+; CHECK-LABEL: @call_zext_i8_i32(
+; CHECK-NEXT:  for.cond8.preheader:
+; CHECK-NEXT:    [[CALL217:%.*]] = call fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 zeroext undef)
+; CHECK-NEXT:    [[TOBOOL219:%.*]] = icmp eq i8 [[CALL217]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL219]], label [[FOR_END411:%.*]], label [[FOR_COND273_PREHEADER:%.*]]
+; CHECK:       for.cond273.preheader:
+; CHECK-NEXT:    [[CALL217_LCSSA:%.*]] = phi i8 [ [[CALL217]], [[FOR_COND8_PREHEADER:%.*]] ]
+; CHECK-NEXT:    [[CONV218_LE:%.*]] = zext i8 [[CALL217_LCSSA]] to i32
+; CHECK-NEXT:    [[CALL346:%.*]] = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext [[CALL217_LCSSA]], i32 [[CONV218_LE]])
+; CHECK-NEXT:    unreachable
+; CHECK:       for.end411:
+; CHECK-NEXT:    [[CALL452:%.*]] = call fastcc i64 @safe_sub_func_int64_t_s_s(i64 undef, i64 4)
+; CHECK-NEXT:    unreachable
+;
+for.cond8.preheader:
+  %call217 = call fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 zeroext undef)
+  %tobool219 = icmp eq i8 %call217, 0
+  br i1 %tobool219, label %for.end411, label %for.cond273.preheader
+
+for.cond273.preheader:                            ; preds = %for.cond8.preheader
+  %call217.lcssa = phi i8 [ %call217, %for.cond8.preheader ]
+  %conv218.le = zext i8 %call217.lcssa to i32
+  %call346 = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext %call217.lcssa, i32 %conv218.le)
+  unreachable
+
+for.end411:                                       ; preds = %for.cond8.preheader
+  %call452 = call fastcc i64 @safe_sub_func_int64_t_s_s(i64 undef, i64 4)
+  unreachable
+}
+
+%struct.anon = type { i32 }
+
+ at g_57 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4
+ at g_893 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4
+ at g_82 = hidden local_unnamed_addr global i32 0, align 4
+
+define hidden i32 @call_return_pointer(i8 zeroext %p_13) local_unnamed_addr #0 {
+; CHECK-LABEL: @call_return_pointer(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[P_13:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i8 [[TMP1]] to i16
+; CHECK-NEXT:    [[CALL:%.*]] = tail call i16** @func_62(i8 zeroext undef, i32 undef, i16 signext [[CONV1]], i32* undef)
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @g_893, i32 0, i32 0), align 4
+; CHECK-NEXT:    [[CONV2:%.*]] = trunc i32 [[TMP2]] to i16
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[P_13_ADDR_0:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[P_13_ADDR_0_BE:%.*]], [[FOR_COND_BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[P_13_ADDR_0]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[FOR_COND_BACKEDGE]], label [[IF_THEN:%.*]]
+; CHECK:       for.cond.backedge:
+; CHECK-NEXT:    [[P_13_ADDR_0_BE]] = phi i32 [ [[TMP3:%.*]], [[IF_THEN]] ], [ 0, [[FOR_COND]] ]
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[CALL3:%.*]] = tail call fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext [[CONV2]])
+; CHECK-NEXT:    [[CONV4:%.*]] = trunc i16 [[CALL3]] to i8
+; CHECK-NEXT:    [[TMP3]] = zext i8 [[CONV4]] to i32
+; CHECK-NEXT:    br label [[FOR_COND_BACKEDGE]]
+;
+entry:
+  %conv1 = zext i8 %p_13 to i16
+  %call = tail call i16** @func_62(i8 zeroext undef, i32 undef, i16 signext %conv1, i32* undef)
+  %0 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @g_893, i32 0, i32 0), align 4
+  %conv2 = trunc i32 %0 to i16
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond.backedge, %entry
+  %p_13.addr.0 = phi i8 [ %p_13, %entry ], [ %p_13.addr.0.be, %for.cond.backedge ]
+  %tobool = icmp eq i8 %p_13.addr.0, 0
+  br i1 %tobool, label %for.cond.backedge, label %if.then
+
+for.cond.backedge:                                ; preds = %for.cond, %if.then
+  %p_13.addr.0.be = phi i8 [ %conv4, %if.then ], [ 0, %for.cond ]
+  br label %for.cond
+
+if.then:                                          ; preds = %for.cond
+  %call3 = tail call fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %conv2)
+  %conv4 = trunc i16 %call3 to i8
+  br label %for.cond.backedge
+}
+
+define i32 @check_zext_phi_call_arg() {
+; CHECK-LABEL: @check_zext_phi_call_arg(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[D_SROA_0_0:%.*]] = phi i32 [ 30, [[ENTRY:%.*]] ], [ [[D_SROA_0_0_BE:%.*]], [[FOR_COND_BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[D_SROA_0_0]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[FOR_COND_BACKEDGE]], label [[IF_THEN:%.*]]
+; CHECK:       for.cond.backedge:
+; CHECK-NEXT:    [[D_SROA_0_0_BE]] = phi i32 [ [[TMP1:%.*]], [[IF_THEN]] ], [ 0, [[FOR_COND]] ]
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[D_SROA_0_0]] to i16
+; CHECK-NEXT:    [[CALL:%.*]] = tail call zeroext i16 bitcast (i16 (...)* @f to i16 (i32)*)(i32 [[D_SROA_0_0]])
+; CHECK-NEXT:    [[TMP1]] = zext i16 [[CALL]] to i32
+; CHECK-NEXT:    br label [[FOR_COND_BACKEDGE]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond.backedge, %entry
+  %d.sroa.0.0 = phi i16 [ 30, %entry ], [ %d.sroa.0.0.be, %for.cond.backedge ]
+  %tobool = icmp eq i16 %d.sroa.0.0, 0
+  br i1 %tobool, label %for.cond.backedge, label %if.then
+
+for.cond.backedge:                                ; preds = %for.cond, %if.then
+  %d.sroa.0.0.be = phi i16 [ %call, %if.then ], [ 0, %for.cond ]
+  br label %for.cond
+
+if.then:                                          ; preds = %for.cond
+  %d.sroa.0.0.insert.ext = zext i16 %d.sroa.0.0 to i32
+  %call = tail call zeroext i16 bitcast (i16 (...)* @f to i16 (i32)*)(i32 %d.sroa.0.0.insert.ext) #2
+  br label %for.cond.backedge
+}
+
+%struct.atomic_flag = type { i8 }
+
+define zeroext i1 @atomic_flag_test_and_set(%struct.atomic_flag* %object) {
+; CHECK-LABEL: @atomic_flag_test_and_set(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[_VALUE:%.*]] = getelementptr inbounds [[STRUCT_ATOMIC_FLAG:%.*]], %struct.atomic_flag* [[OBJECT:%.*]], i32 0, i32 0
+; CHECK-NEXT:    [[CALL:%.*]] = tail call arm_aapcscc zeroext i8 @__atomic_exchange_1(i8* [[_VALUE]], i8 zeroext 1, i32 5)
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[CALL]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[TOBOOL]]
+;
+entry:
+  %_Value = getelementptr inbounds %struct.atomic_flag, %struct.atomic_flag* %object, i32 0, i32 0
+  %call = tail call arm_aapcscc zeroext i8 @__atomic_exchange_1(i8* %_Value, i8 zeroext 1, i32 5) #1
+  %0 = and i8 %call, 1
+  %tobool = icmp ne i8 %0, 0
+  ret i1 %tobool
+}
+
+define i1 @i1_zeroext_call(i16* %ts, i32 %a, i16* %b, i8* %c) {
+; CHECK-LABEL: @i1_zeroext_call(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[TS:%.*]], align 2
+; CHECK-NEXT:    [[CONV_I860:%.*]] = trunc i32 [[A:%.*]] to i16
+; CHECK-NEXT:    store i16 [[CONV_I860]], i16* [[B:%.*]], align 2
+; CHECK-NEXT:    [[CALL_I848:%.*]] = call zeroext i1 @i1_zeroext(i8* [[C:%.*]], i32 64, i16 zeroext [[CONV_I860]])
+; CHECK-NEXT:    br i1 [[CALL_I848]], label [[IF_THEN223:%.*]], label [[IF_ELSE227:%.*]]
+; CHECK:       if.then223:
+; CHECK-NEXT:    [[CMP235:%.*]] = icmp eq i16 [[TMP0]], [[CONV_I860]]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       if.else227:
+; CHECK-NEXT:    [[CMP236:%.*]] = icmp ult i16 [[TMP0]], [[CONV_I860]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i1 [ [[CMP235]], [[IF_THEN223]] ], [ [[CMP236]], [[IF_ELSE227]] ]
+; CHECK-NEXT:    ret i1 [[RETVAL]]
+;
+entry:
+  %0 = load i16, i16* %ts, align 2
+  %conv.i860 = trunc i32 %a to i16
+  store i16 %conv.i860, i16* %b, align 2
+  %call.i848 = call zeroext i1 @i1_zeroext(i8* %c, i32 64, i16 zeroext %conv.i860)
+  br i1 %call.i848, label %if.then223, label %if.else227
+
+if.then223:
+  %cmp235 = icmp eq i16 %0, %conv.i860
+  br label %exit
+
+if.else227:
+  %cmp236 = icmp ult i16 %0, %conv.i860
+  br label %exit
+
+exit:
+  %retval = phi i1 [ %cmp235, %if.then223 ], [ %cmp236, %if.else227 ]
+  ret i1 %retval
+}
+
+define i16 @promote_arg_pass_to_call(i16 zeroext %arg1, i16 zeroext %arg2) {
+; CHECK-LABEL: @promote_arg_pass_to_call(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[ARG2:%.*]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = add nuw i32 [[TMP1]], 15
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[MUL]], [[TMP2]]
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP1]], 255
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[TMP3]] to i8
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT:    [[RES:%.*]] = call zeroext i16 @dummy4(i1 [[CMP]], i8 [[TMP4]], i16 [[TMP5]])
+; CHECK-NEXT:    [[TMP6:%.*]] = zext i16 [[RES]] to i32
+; CHECK-NEXT:    [[TMP7:%.*]] = trunc i32 [[TMP6]] to i16
+; CHECK-NEXT:    ret i16 [[TMP7]]
+;
+  %conv = add nuw i16 %arg1, 15
+  %mul = mul nuw nsw i16 %conv, 3
+  %cmp = icmp ult i16 %mul, %arg2
+  %trunc = trunc i16 %arg1 to i8
+  %res = call zeroext i16 @dummy4(i1 %cmp, i8 %trunc, i16 %arg1)
+  ret i16 %res
+}
+
+
+declare i32 @assert(...)
+declare i8 @dummy_i8(i8)
+declare i8 @dummy2(i8*, i8, i8)
+declare i16 @dummy3(i16)
+declare i16 @dummy4(i1, i8, i16)
+
+declare dso_local i32 @e(...) local_unnamed_addr #1
+declare dso_local zeroext i16 @f(...) local_unnamed_addr #1
+declare dso_local arm_aapcscc i8 @__atomic_exchange_1(i8*, i8, i32) local_unnamed_addr
+
+declare noalias i16** @func_62(i8 zeroext %p_63, i32 %p_64, i16 signext %p_65, i32* nocapture readnone %p_66)
+declare fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %si2)
+declare dso_local fastcc i64 @safe_sub_func_int64_t_s_s(i64, i64)
+declare dso_local fastcc zeroext i8 @safe_lshift_func(i8 zeroext, i32)
+declare dso_local fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 returned zeroext)
+declare i1 @i1_zeroext(i8*, i32, i16 zeroext)

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/casts.ll b/llvm/test/Transforms/TypePromotion/ARM/casts.ll
new file mode 100644
index 000000000000..70fa617115e8
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/casts.ll
@@ -0,0 +1,1072 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define i16 @dsp_trunc(i32 %arg0, i32 %arg1, i16* %gep0, i16* %gep1) {
+; CHECK-LABEL: @dsp_trunc(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD0:%.*]] = add i32 [[ARG0:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[CONV0:%.*]] = trunc i32 [[ADD0]] to i16
+; CHECK-NEXT:    [[SUB0:%.*]] = sub i16 0, [[CONV0]]
+; CHECK-NEXT:    [[LOAD0:%.*]] = load i16, i16* [[GEP0:%.*]], align 2
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i16, i16* [[GEP1:%.*]], align 2
+; CHECK-NEXT:    [[SUB1:%.*]] = sub i16 [[LOAD0]], [[SUB0]]
+; CHECK-NEXT:    [[ADD1:%.*]] = add i16 [[LOAD1]], [[SUB0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[SUB1]], [[ADD1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 [[ADD1]], i16 [[SUB1]]
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+entry:
+  %add0 = add i32 %arg0, %arg1
+  %conv0 = trunc i32 %add0 to i16
+  %sub0 = sub i16 0, %conv0
+  %load0 = load i16, i16* %gep0, align 2
+  %load1 = load i16, i16* %gep1, align 2
+  %sub1 = sub i16 %load0, %sub0
+  %add1 = add i16 %load1, %sub0
+  %cmp = icmp ult i16 %sub1, %add1
+  %res = select i1 %cmp, i16 %add1, i16 %sub1
+  ret i16 %res
+}
+
+define i8 @trunc_i16_i8(i16* %ptr, i16 zeroext %arg0, i8 zeroext %arg1) {
+; CHECK-LABEL: @trunc_i16_i8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[PTR:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add i16 [[TMP1]], [[ARG0:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i16 [[TMP2]] to i8
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ugt i32 [[TMP4]], [[TMP0]]
+; CHECK-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 [[TMP0]]
+; CHECK-NEXT:    [[TMP7:%.*]] = trunc i32 [[TMP6]] to i8
+; CHECK-NEXT:    ret i8 [[TMP7]]
+;
+entry:
+  %0 = load i16, i16* %ptr
+  %1 = add i16 %0, %arg0
+  %2 = trunc i16 %1 to i8
+  %3 = icmp ugt i8 %2, %arg1
+  %4 = select i1 %3, i8 %2, i8 %arg1
+  ret i8 %4
+}
+
+; The pass perform the transform, but a uxtb will still be inserted to handle
+; the zext to the icmp.
+define i8 @icmp_i32_zext(i8* %ptr) {
+; CHECK-LABEL: @icmp_i32_zext(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, i8* [[PTR:%.*]], i32 0
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[GEP]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub nuw nsw i8 [[TMP0]], 1
+; CHECK-NEXT:    [[CONV44:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    br label [[PREHEADER:%.*]]
+; CHECK:       preheader:
+; CHECK-NEXT:    br label [[BODY:%.*]]
+; CHECK:       body:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i8 [ [[TMP1]], [[PREHEADER]] ], [ [[TMP3:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[SI_0274:%.*]] = phi i32 [ [[CONV44]], [[PREHEADER]] ], [ [[INC:%.*]], [[IF_END]] ]
+; CHECK-NEXT:    [[CONV51266:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT:    [[CMP52267:%.*]] = icmp eq i32 [[SI_0274]], [[CONV51266]]
+; CHECK-NEXT:    br i1 [[CMP52267]], label [[IF_END]], label [[EXIT:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC]] = add i32 [[SI_0274]], 1
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP3]] = load i8, i8* [[GEP1]], align 1
+; CHECK-NEXT:    br label [[BODY]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i8 [[TMP2]]
+;
+entry:
+  %gep = getelementptr inbounds i8, i8* %ptr, i32 0
+  %0 = load i8, i8* %gep, align 1
+  %1 = sub nuw nsw i8 %0, 1
+  %conv44 = zext i8 %0 to i32
+  br label %preheader
+
+preheader:
+  br label %body
+
+body:
+  %2 = phi i8 [ %1, %preheader ], [ %3, %if.end ]
+  %si.0274 = phi i32 [ %conv44, %preheader ], [ %inc, %if.end ]
+  %conv51266 = zext i8 %2 to i32
+  %cmp52267 = icmp eq i32 %si.0274, %conv51266
+  br i1 %cmp52267, label %if.end, label %exit
+
+if.end:
+  %inc = add i32 %si.0274, 1
+  %gep1 = getelementptr inbounds i8, i8* %ptr, i32 %inc
+  %3 = load i8, i8* %gep1, align 1
+  br label %body
+
+exit:
+  ret i8 %2
+}
+
+; Won't don't handle sext
+define i32 @icmp_sext_zext_store_i8_i16() {
+; CHECK-LABEL: @icmp_sext_zext_store_i8_i16(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @d_uch, i32 0, i32 2), align 1
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[TMP0]] to i16
+; CHECK-NEXT:    store i16 [[CONV]], i16* @sh1, align 2
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* getelementptr inbounds ([16 x i16], [16 x i16]* @d_sh, i32 0, i32 2), align 2
+; CHECK-NEXT:    [[CONV2:%.*]] = sext i16 [[TMP1]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CONV1]], [[CONV2]]
+; CHECK-NEXT:    [[CONV3:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV3]]
+;
+entry:
+  %0 = load i8, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @d_uch, i32 0, i32 2), align 1
+  %conv = zext i8 %0 to i16
+  store i16 %conv, i16* @sh1, align 2
+  %conv1 = zext i8 %0 to i32
+  %1 = load i16, i16* getelementptr inbounds ([16 x i16], [16 x i16]* @d_sh, i32 0, i32 2), align 2
+  %conv2 = sext i16 %1 to i32
+  %cmp = icmp eq i32 %conv1, %conv2
+  %conv3 = zext i1 %cmp to i32
+  ret i32 %conv3
+}
+
+define i1 @or_icmp_ugt(i32 %arg, i8* %ptr) {
+; CHECK-LABEL: @or_icmp_ugt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[PTR:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw nsw i32 [[TMP2]], 1
+; CHECK-NEXT:    [[ADD0:%.*]] = add nuw nsw i32 [[MUL]], 6
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ne i32 [[ARG:%.*]], [[ADD0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP1]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[TMP3]], 3
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP0]], [[CMP1]]
+; CHECK-NEXT:    ret i1 [[OR]]
+;
+entry:
+  %0 = load i8, i8* %ptr
+  %1 = zext i8 %0 to i32
+  %mul = shl nuw nsw i32 %1, 1
+  %add0 = add nuw nsw i32 %mul, 6
+  %cmp0 = icmp ne i32 %arg, %add0
+  %add1 = add i8 %0, -1
+  %cmp1 = icmp ugt i8 %add1, 3
+  %or = or i1 %cmp0, %cmp1
+  ret i1 %or
+}
+
+; We currently only handle truncs as sinks, so a uxt will still be needed for
+; the icmp ugt instruction.
+define void @urem_trunc_icmps(i16** %in, i32* %g, i32* %k) {
+; CHECK-LABEL: @urem_trunc_icmps(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PTR:%.*]] = load i16*, i16** [[IN:%.*]], align 4
+; CHECK-NEXT:    [[LD:%.*]] = load i16, i16* [[PTR]], align 2
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i16 [[LD]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label [[EXIT:%.*]], label [[COND_FALSE_I:%.*]]
+; CHECK:       cond.false.i:
+; CHECK-NEXT:    [[REM:%.*]] = urem i16 5, [[LD]]
+; CHECK-NEXT:    [[EXTRACT_T:%.*]] = trunc i16 [[REM]] to i8
+; CHECK-NEXT:    br label [[BODY:%.*]]
+; CHECK:       body:
+; CHECK-NEXT:    [[COND_IN_I_OFF0:%.*]] = phi i8 [ [[EXTRACT_T]], [[COND_FALSE_I]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[COND_IN_I_OFF0]], 7
+; CHECK-NEXT:    [[CONV5:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    store i32 [[CONV5]], i32* [[G:%.*]], align 4
+; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, i32* [[K:%.*]], align 4
+; CHECK-NEXT:    [[TOBOOL13150:%.*]] = icmp eq i32 [[DOTPR]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL13150]], label [[FOR_INC]], label [[EXIT]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[ADD]] = add nuw i8 [[COND_IN_I_OFF0]], 1
+; CHECK-NEXT:    br label [[BODY]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %ptr = load i16*, i16** %in, align 4
+  %ld = load i16, i16* %ptr, align 2
+  %cmp.i = icmp eq i16 %ld, 0
+  br i1 %cmp.i, label %exit, label %cond.false.i
+
+cond.false.i:
+  %rem = urem i16 5, %ld
+  %extract.t = trunc i16 %rem to i8
+  br label %body
+
+body:
+  %cond.in.i.off0 = phi i8 [ %extract.t, %cond.false.i ], [ %add, %for.inc ]
+  %cmp = icmp ugt i8 %cond.in.i.off0, 7
+  %conv5 = zext i1 %cmp to i32
+  store i32 %conv5, i32* %g, align 4
+  %.pr = load i32, i32* %k, align 4
+  %tobool13150 = icmp eq i32 %.pr, 0
+  br i1 %tobool13150, label %for.inc, label %exit
+
+for.inc:
+  %add = add nuw i8 %cond.in.i.off0, 1
+  br label %body
+
+exit:
+  ret void
+}
+
+; Check that %exp requires uxth in all cases, and will also be required to
+; promote %1 for the call - unless we can generate a uadd16.
+define i32 @zext_load_sink_call(i16* %ptr, i16 %exp) {
+; CHECK-LABEL: @zext_load_sink_call(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[PTR:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[EXP:%.*]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[TMP0]], [[EXP]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[CONV0:%.*]] = zext i16 [[TMP0]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[TMP1]] to i32
+; CHECK-NEXT:    [[CALL:%.*]] = tail call arm_aapcs_vfpcc i32 @dummy(i32 [[CONV0]], i32 [[CONV1]])
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[EXITVAL:%.*]] = phi i32 [ [[CALL]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[EXITVAL]]
+;
+entry:
+  %0 = load i16, i16* %ptr, align 4
+  %1 = add i16 %exp, 3
+  %cmp = icmp eq i16 %0, %exp
+  br i1 %cmp, label %exit, label %if.then
+
+if.then:
+  %conv0 = zext i16 %0 to i32
+  %conv1 = zext i16 %1 to i32
+  %call = tail call arm_aapcs_vfpcc i32 @dummy(i32 %conv0, i32 %conv1)
+  br label %exit
+
+exit:
+  %exitval = phi i32 [ %call, %if.then ], [ 0, %entry  ]
+  ret i32 %exitval
+}
+
+define i16 @bitcast_i16(i16 zeroext %arg0, i16 zeroext %arg1) {
+entry:
+  %cast = bitcast i16 12345 to i16
+  %add = add nuw i16 %arg0, 1
+  %cmp = icmp ule i16 %add, %cast
+  %res = select i1 %cmp, i16 %arg1, i16 32657
+  ret i16 %res
+}
+
+define i8 @bitcast_i8(i8 zeroext %arg0, i8 zeroext %arg1) {
+; CHECK-LABEL: @bitcast_i8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG0:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast i8 127 to i8
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i32 [[TMP0]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[MUL]], [[TMP1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i8 [[CAST]], i8 -128
+; CHECK-NEXT:    ret i8 [[RES]]
+;
+entry:
+  %cast = bitcast i8 127 to i8
+  %mul = shl nuw i8 %arg0, 1
+  %cmp = icmp uge i8 %mul, %arg1
+  %res = select i1 %cmp, i8 %cast, i8 128
+  ret i8 %res
+}
+
+define i16 @bitcast_i16_minus(i16 zeroext %arg0, i16 zeroext %arg1) {
+; CHECK-LABEL: @bitcast_i16_minus(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[ARG0:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast i16 -12345 to i16
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP0]], 7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[XOR]], [[TMP1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 [[CAST]], i16 32657
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+entry:
+  %cast = bitcast i16 -12345 to i16
+  %xor = xor i16 %arg0, 7
+  %cmp = icmp eq i16 %xor, %arg1
+  %res = select i1 %cmp, i16 %cast, i16 32657
+  ret i16 %res
+}
+
+define i8 @bitcast_i8_minus(i8 zeroext %arg0, i8 zeroext %arg1) {
+; CHECK-LABEL: @bitcast_i8_minus(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG0:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast i8 -127 to i8
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], [[TMP1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i8 [[CAST]], i8 -128
+; CHECK-NEXT:    ret i8 [[RES]]
+;
+entry:
+  %cast = bitcast i8 -127 to i8
+  %and = and i8 %arg0, 3
+  %cmp = icmp ne i8 %and, %arg1
+  %res = select i1 %cmp, i8 %cast, i8 128
+  ret i8 %res
+}
+
+declare i32 @dummy(i32, i32)
+
+ at d_uch = hidden local_unnamed_addr global [16 x i8] zeroinitializer, align 1
+ at sh1 = hidden local_unnamed_addr global i16 0, align 2
+ at d_sh = hidden local_unnamed_addr global [16 x i16] zeroinitializer, align 2
+
+define i8* @two_stage_zext_trunc_mix(i32* %this, i32 %__pos1, i32 %__n1, i32** %__str, i32 %__pos2, i32 %__n2) {
+; CHECK-LABEL: @two_stage_zext_trunc_mix(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[__SIZE__I_I_I_I:%.*]] = bitcast i32** [[__STR:%.*]] to i8*
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[__SIZE__I_I_I_I]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 1
+; CHECK-NEXT:    [[TOBOOL_I_I_I_I:%.*]] = icmp eq i32 [[TMP2]], 0
+; CHECK-NEXT:    [[__SIZE__I5_I_I:%.*]] = getelementptr inbounds i32*, i32** [[__STR]], i32 [[__N1:%.*]]
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast i32** [[__SIZE__I5_I_I]] to i32*
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[CAST]], align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = lshr i32 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[TMP4]] to i8
+; CHECK-NEXT:    [[COND_I_I:%.*]] = select i1 [[TOBOOL_I_I_I_I]], i32 [[TMP4]], i32 [[TMP3]]
+; CHECK-NEXT:    [[__SIZE__I_I_I_I_I:%.*]] = bitcast i32* [[THIS:%.*]] to i8*
+; CHECK-NEXT:    [[TMP6:%.*]] = load i8, i8* [[__SIZE__I_I_I_I_I]], align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = zext i8 [[TMP6]] to i32
+; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], 1
+; CHECK-NEXT:    [[TOBOOL_I_I_I_I_I:%.*]] = icmp eq i32 [[TMP8]], 0
+; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i8, i8* [[__SIZE__I_I_I_I]], i32 [[__POS1:%.*]]
+; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds i8, i8* [[__SIZE__I_I_I_I]], i32 [[__POS2:%.*]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[TOBOOL_I_I_I_I_I]], i8* [[TMP9]], i8* [[TMP10]]
+; CHECK-NEXT:    ret i8* [[RES]]
+;
+entry:
+  %__size_.i.i.i.i = bitcast i32** %__str to i8*
+  %0 = load i8, i8* %__size_.i.i.i.i, align 4
+  %1 = and i8 %0, 1
+  %tobool.i.i.i.i = icmp eq i8 %1, 0
+  %__size_.i5.i.i = getelementptr inbounds i32*, i32** %__str, i32 %__n1
+  %cast = bitcast i32** %__size_.i5.i.i to i32*
+  %2 = load i32, i32* %cast, align 4
+  %3 = lshr i8 %0, 1
+  %4 = zext i8 %3 to i32
+  %cond.i.i = select i1 %tobool.i.i.i.i, i32 %4, i32 %2
+  %__size_.i.i.i.i.i = bitcast i32* %this to i8*
+  %5 = load i8, i8* %__size_.i.i.i.i.i, align 4
+  %6 = and i8 %5, 1
+  %tobool.i.i.i.i.i = icmp eq i8 %6, 0
+  %7 = getelementptr inbounds i8, i8* %__size_.i.i.i.i, i32 %__pos1
+  %8 = getelementptr inbounds i8, i8* %__size_.i.i.i.i, i32 %__pos2
+  %res = select i1 %tobool.i.i.i.i.i,  i8* %7, i8* %8
+  ret i8* %res
+}
+
+define i8 @search_through_zext_1(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c) {
+; CHECK-LABEL: @search_through_zext_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[C:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], [[TMP2]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[SUB]], [[TMP2]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP2]], i32 [[TMP1]], i32 [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RETVAL]] to i8
+; CHECK-NEXT:    ret i8 [[TMP3]]
+;
+entry:
+  %add = add nuw i8 %a, %b
+  %conv = zext i8 %add to i16
+  %cmp = icmp ult i16 %conv, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %sub = sub nuw i8 %b, %a
+  %conv2 = zext i8 %sub to i16
+  %cmp2 = icmp ugt i16 %conv2, %c
+  %res = select i1 %cmp2, i8 %a, i8 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
+  ret i8 %retval
+}
+
+; TODO: We should be able to remove the uxtb here. The transform fails because
+; the icmp ugt uses an i32, which is too large... but this doesn't matter
+; because it won't be writing a large value to a register as a result.
+define i8 @search_through_zext_2(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c, i32 %d) {
+; CHECK-LABEL: @search_through_zext_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[ADD]] to i16
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[CONV]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[CONV2:%.*]] = zext i8 [[SUB]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[CONV2]], [[D:%.*]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP2]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret i8 [[RETVAL]]
+;
+entry:
+  %add = add nuw i8 %a, %b
+  %conv = zext i8 %add to i16
+  %cmp = icmp ult i16 %conv, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %sub = sub nuw i8 %b, %a
+  %conv2 = zext i8 %sub to i32
+  %cmp2 = icmp ugt i32 %conv2, %d
+  %res = select i1 %cmp2, i8 %a, i8 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
+  ret i8 %retval
+}
+
+; TODO: We should be able to remove the uxtb here as all the calculations are
+; performed on i8s. The promotion of i8 to i16 and then the later truncation
+; results in the uxtb.
+define i8 @search_through_zext_3(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c, i32 %d) {
+; CHECK-LABEL: @search_through_zext_3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[ADD]] to i16
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[CONV]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i16 [[CONV]] to i8
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i8 [[B]], [[TRUNC]]
+; CHECK-NEXT:    [[CONV2:%.*]] = zext i8 [[SUB]] to i32
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[CONV2]], [[D:%.*]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP2]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret i8 [[RETVAL]]
+;
+entry:
+  %add = add nuw i8 %a, %b
+  %conv = zext i8 %add to i16
+  %cmp = icmp ult i16 %conv, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %conv to i8
+  %sub = sub nuw i8 %b, %trunc
+  %conv2 = zext i8 %sub to i32
+  %cmp2 = icmp ugt i32 %conv2, %d
+  %res = select i1 %cmp2, i8 %a, i8 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
+  ret i8 %retval
+}
+
+; TODO: We should be able to remove the uxt that gets introduced for %conv2
+define i8 @search_through_zext_cmp(i8 zeroext %a, i8 zeroext %b, i16 zeroext %c) {
+; CHECK-LABEL: @search_through_zext_cmp(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i16 [[CONV]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[CONV2:%.*]] = zext i8 [[SUB]] to i16
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp ugt i16 [[CONV2]], [[C]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP3]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret i8 [[RETVAL]]
+;
+entry:
+  %cmp = icmp ne i8 %a, %b
+  %conv = zext i1 %cmp to i16
+  %cmp1 = icmp ult i16 %conv, %c
+  br i1 %cmp1, label %if.then, label %if.end
+
+if.then:
+  %sub = sub nuw i8 %b, %a
+  %conv2 = zext i8 %sub to i16
+  %cmp3 = icmp ugt i16 %conv2, %c
+  %res = select i1 %cmp3, i8 %a, i8 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
+  ret i8 %retval
+}
+
+define i8 @search_through_zext_load(i8* %a, i8 zeroext %b, i16 zeroext %c) {
+; CHECK-LABEL: @search_through_zext_load(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[C:%.*]] to i32
+; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[A:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[LOAD]] to i32
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP0]], [[TMP2]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp ugt i32 [[SUB]], [[TMP1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP3]], i32 [[TMP2]], i32 [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RETVAL]] to i8
+; CHECK-NEXT:    ret i8 [[TMP3]]
+;
+entry:
+  %load = load i8, i8* %a
+  %conv = zext i8 %load to i16
+  %cmp1 = icmp ult i16 %conv, %c
+  br i1 %cmp1, label %if.then, label %if.end
+
+if.then:
+  %sub = sub nuw i8 %b, %load
+  %conv2 = zext i8 %sub to i16
+  %cmp3 = icmp ugt i16 %conv2, %c
+  %res = select i1 %cmp3, i8 %load, i8 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %res, %if.then ]
+  ret i8 %retval
+}
+
+define i16 @trunc_sink_less_than_cmp(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d) {
+; CHECK-LABEL: @trunc_sink_less_than_cmp(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i16 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[SUB]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i16 [[SUB]] to i8
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[D:%.*]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[TRUNC]], [[ADD]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP2]], i16 [[A]], i16 [[B]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret i16 [[RETVAL]]
+;
+entry:
+  %sub = sub nuw i16 %b, %a
+  %cmp = icmp ult i16 %sub, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %sub to i8
+  %add = add nuw i8 %d, 1
+  %cmp2 = icmp ugt i8 %trunc, %add
+  %res = select i1 %cmp2, i16 %a, i16 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i16 [ 0, %entry ], [ %res, %if.then ]
+  ret i16 %retval
+}
+
+; TODO: We should be able to remove the uxth introduced to handle %sub
+define i16 @trunc_sink_less_than_arith(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
+; CHECK-LABEL: @trunc_sink_less_than_arith(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i16 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[SUB]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i16 [[SUB]] to i8
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i8 [[D:%.*]], [[TRUNC]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[E:%.*]], [[ADD]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP2]], i16 [[A]], i16 [[B]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret i16 [[RETVAL]]
+;
+entry:
+  %sub = sub nuw i16 %b, %a
+  %cmp = icmp ult i16 %sub, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %sub to i8
+  %add = add nuw i8 %d, %trunc
+  %cmp2 = icmp ugt i8 %e, %add
+  %res = select i1 %cmp2, i16 %a, i16 %b
+  br label %if.end
+
+if.end:
+  %retval = phi i16 [ 0, %entry ], [ %res, %if.then ]
+  ret i16 %retval
+}
+
+define i16 @trunc_sink_less_than_store(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8* %e) {
+; CHECK-LABEL: @trunc_sink_less_than_store(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[D:%.*]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[C:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], [[TMP3]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[SUB]], 255
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP2]], [[TMP4]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[ADD]] to i8
+; CHECK-NEXT:    store i8 [[TMP5]], i8* [[E:%.*]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUB]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[RETVAL]] to i16
+; CHECK-NEXT:    ret i16 [[TMP6]]
+;
+entry:
+  %sub = sub nuw i16 %b, %a
+  %cmp = icmp ult i16 %sub, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %sub to i8
+  %add = add nuw i8 %d, %trunc
+  store i8 %add, i8* %e
+  br label %if.end
+
+if.end:
+  %retval = phi i16 [ 0, %entry ], [ %sub, %if.then ]
+  ret i16 %retval
+}
+
+define i8 @trunc_sink_less_than_ret(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
+; CHECK-LABEL: @trunc_sink_less_than_ret(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[D:%.*]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[C:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], [[TMP3]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[SUB]], 255
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP2]], [[TMP4]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[RETVAL]] to i8
+; CHECK-NEXT:    ret i8 [[TMP5]]
+;
+entry:
+  %sub = sub nuw i16 %b, %a
+  %cmp = icmp ult i16 %sub, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %sub to i8
+  %add = add nuw i8 %d, %trunc
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %add, %if.then ]
+  ret i8 %retval
+}
+
+define zeroext i8 @trunc_sink_less_than_zext_ret(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i8 zeroext %d, i8 zeroext %e) {
+; CHECK-LABEL: @trunc_sink_less_than_zext_ret(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[D:%.*]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i16 [[C:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], [[TMP3]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[SUB]], 255
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP2]], [[TMP4]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[RETVAL]] to i8
+; CHECK-NEXT:    ret i8 [[TMP5]]
+;
+entry:
+  %sub = sub nuw i16 %b, %a
+  %cmp = icmp ult i16 %sub, %c
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %trunc = trunc i16 %sub to i8
+  %add = add nuw i8 %d, %trunc
+  br label %if.end
+
+if.end:
+  %retval = phi i8 [ 0, %entry ], [ %add, %if.then ]
+  ret i8 %retval
+}
+
+define i32 @bitcast_i1(i16 zeroext %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @bitcast_i1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i1 true to i1
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i16 [[A:%.*]] to i1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i1 [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[EXIT:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[TMP0]] to i16
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i1 [[TMP1]] to i16
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp uge i16 [[CONV]], [[CONV1]]
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP1]], i32 [[B:%.*]], i32 [[C:%.*]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi i32 [ [[SELECT]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[RETVAL]]
+;
+entry:
+  %0 = bitcast i1 1 to i1
+  %1 = trunc i16 %a to i1
+  %cmp = icmp eq i1 %1, %0
+  br i1 %cmp, label %if.then, label %exit
+
+if.then:
+  %conv = zext i1 %0 to i16
+  %conv1 = zext i1 %1 to i16
+  %cmp1 = icmp uge i16 %conv, %conv1
+  %select = select i1 %cmp1, i32 %b, i32 %c
+  br label %exit
+
+exit:
+  %retval = phi i32 [ %select, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+}
+
+define void @search_back_through_trunc(i8* %a, i8* %b, i8* %c, i8* %d, i16* %e) {
+; CHECK-LABEL: @search_back_through_trunc(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[A:%.*]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i32 [[TMP1]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT:    [[OR109:%.*]] = or i32 [[SHL]], [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = load i8, i8* [[C:%.*]], align 1
+; CHECK-NEXT:    [[TMP5:%.*]] = zext i8 [[TMP4]] to i32
+; CHECK-NEXT:    [[SHL120:%.*]] = shl nuw i32 [[TMP5]], 8
+; CHECK-NEXT:    [[TMP6:%.*]] = load i8, i8* [[D:%.*]], align 1
+; CHECK-NEXT:    [[TMP7:%.*]] = zext i8 [[TMP6]] to i32
+; CHECK-NEXT:    [[OR123:%.*]] = or i32 [[SHL120]], [[TMP7]]
+; CHECK-NEXT:    [[CMP133:%.*]] = icmp eq i32 [[OR109]], [[OR123]]
+; CHECK-NEXT:    br i1 [[CMP133]], label [[IF_END183:%.*]], label [[IF_ELSE136:%.*]]
+; CHECK:       if.else136:
+; CHECK-NEXT:    [[TMP8:%.*]] = load i16, i16* [[E:%.*]], align 2
+; CHECK-NEXT:    [[TMP9:%.*]] = zext i16 [[TMP8]] to i32
+; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP9]], 255
+; CHECK-NEXT:    [[EXTRACT856:%.*]] = lshr i32 [[TMP9]], 8
+; CHECK-NEXT:    [[TMP11:%.*]] = and i32 [[EXTRACT856]], 255
+; CHECK-NEXT:    br label [[IF_END183]]
+; CHECK:       if.end183:
+; CHECK-NEXT:    [[W_0_OFF0:%.*]] = phi i32 [ [[TMP10]], [[IF_ELSE136]] ], [ [[TMP3]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[W_0_OFF8:%.*]] = phi i32 [ [[TMP11]], [[IF_ELSE136]] ], [ [[TMP5]], [[ENTRY]] ]
+; CHECK-NEXT:    [[TMP12:%.*]] = trunc i32 [[W_0_OFF8]] to i8
+; CHECK-NEXT:    store i8 [[TMP12]], i8* [[C]], align 1
+; CHECK-NEXT:    [[TMP13:%.*]] = trunc i32 [[W_0_OFF0]] to i8
+; CHECK-NEXT:    store i8 [[TMP13]], i8* [[D]], align 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i8, i8* %a, align 1
+  %conv106 = zext i8 %0 to i16
+  %shl = shl nuw i16 %conv106, 8
+  %1 = load i8, i8* %b, align 1
+  %conv108 = zext i8 %1 to i16
+  %or109 = or i16 %shl, %conv108
+  %2 = load i8, i8* %c, align 1
+  %conv119 = zext i8 %2 to i16
+  %shl120 = shl nuw i16 %conv119, 8
+  %3 = load i8, i8* %d, align 1
+  %conv122 = zext i8 %3 to i16
+  %or123 = or i16 %shl120, %conv122
+  %cmp133 = icmp eq i16 %or109, %or123
+  br i1 %cmp133, label %if.end183, label %if.else136
+
+if.else136:
+  %4 = load i16, i16* %e, align 2
+  %extract.t854 = trunc i16 %4 to i8
+  %extract856 = lshr i16 %4, 8
+  %extract.t857 = trunc i16 %extract856 to i8
+  br label %if.end183
+
+if.end183:
+  %w.0.off0 = phi i8 [ %extract.t854, %if.else136 ], [ %1, %entry ]
+  %w.0.off8 = phi i8 [ %extract.t857, %if.else136 ], [ %2, %entry ]
+  store i8 %w.0.off8, i8* %c, align 1
+  store i8 %w.0.off0, i8* %d, align 1
+  ret void
+}
+
+ at c = common dso_local local_unnamed_addr global i16 0, align 2
+ at b = common dso_local local_unnamed_addr global i16 0, align 2
+ at f = common dso_local local_unnamed_addr global i32 0, align 4
+ at e = common dso_local local_unnamed_addr global i8 0, align 1
+ at a = common dso_local local_unnamed_addr global i8 0, align 1
+ at d = common dso_local local_unnamed_addr global i32 0, align 4
+
+define void @and_trunc_two_zext() {
+; CHECK-LABEL: @and_trunc_two_zext(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @c, align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* @b, align 2
+; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP1]] to i32
+; CHECK-NEXT:    store i32 [[CONV]], i32* @f, align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i16 [[TMP1]] to i8
+; CHECK-NEXT:    [[CONV1:%.*]] = and i8 [[TMP2]], 1
+; CHECK-NEXT:    store i8 [[CONV1]], i8* @e, align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = load i8, i8* @a, align 1
+; CHECK-NEXT:    [[NARROW:%.*]] = mul nuw i8 [[TMP3]], [[CONV1]]
+; CHECK-NEXT:    [[MUL:%.*]] = zext i8 [[NARROW]] to i32
+; CHECK-NEXT:    store i32 [[MUL]], i32* @d, align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[NARROW]] to i16
+; CHECK-NEXT:    [[CONV5:%.*]] = or i16 [[TMP0]], [[TMP4]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[CONV5]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       if.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i16, i16* @c, align 2
+  %1 = load i16, i16* @b, align 2
+  %conv = sext i16 %1 to i32
+  store i32 %conv, i32* @f, align 4
+  %2 = trunc i16 %1 to i8
+  %conv1 = and i8 %2, 1
+  store i8 %conv1, i8* @e, align 1
+  %3 = load i8, i8* @a, align 1
+  %narrow = mul nuw i8 %3, %conv1
+  %mul = zext i8 %narrow to i32
+  store i32 %mul, i32* @d, align 4
+  %4 = zext i8 %narrow to i16
+  %conv5 = or i16 %0, %4
+  %tobool = icmp eq i16 %conv5, 0
+  br i1 %tobool, label %if.end, label %for.cond
+
+for.cond:
+  br label %for.cond
+
+if.end:
+  ret void
+}
+
+define void @zext_urem_trunc() {
+; CHECK-LABEL: @zext_urem_trunc(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @c, align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[TMP0]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8, i8* @e, align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    [[REM7:%.*]] = urem i32 [[TMP3]], [[TMP1]]
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[REM7]], 255
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[TMP4]], [[COND_FALSE]] ], [ [[TMP3]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[COND]] to i8
+; CHECK-NEXT:    store i8 [[TMP5]], i8* @a, align 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i16, i16* @c, align 2
+  %cmp = icmp eq i16 %0, 0
+  %1 = load i8, i8* @e, align 1
+  br i1 %cmp, label %cond.end, label %cond.false
+
+cond.false:
+  %rem.lhs.trunc = zext i8 %1 to i16
+  %rem7 = urem i16 %rem.lhs.trunc, %0
+  %rem.zext = trunc i16 %rem7 to i8
+  br label %cond.end
+
+cond.end:
+  %cond = phi i8 [ %rem.zext, %cond.false ], [ %1, %entry ]
+  store i8 %cond, i8* @a, align 1
+  ret void
+}
+
+define i1 @dont_replace_trunc_1(i8* %a, i16* %b, i16* %c, i32* %d, i8* %e, i32* %f) {
+; CHECK-LABEL: @dont_replace_trunc_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[C:%.*]], align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[B:%.*]], align 2
+; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP1]] to i32
+; CHECK-NEXT:    store i32 [[CONV]], i32* [[F:%.*]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i16 [[TMP1]] to i8
+; CHECK-NEXT:    [[CONV1:%.*]] = and i8 [[TMP2]], 1
+; CHECK-NEXT:    store i8 [[CONV1]], i8* [[E:%.*]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = load i8, i8* [[A:%.*]], align 1
+; CHECK-NEXT:    [[NARROW:%.*]] = mul nuw i8 [[TMP3]], [[CONV1]]
+; CHECK-NEXT:    [[MUL:%.*]] = zext i8 [[NARROW]] to i32
+; CHECK-NEXT:    store i32 [[MUL]], i32* [[D:%.*]], align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[NARROW]] to i16
+; CHECK-NEXT:    [[CONV5:%.*]] = or i16 [[TMP0]], [[TMP4]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[CONV5]], 0
+; CHECK-NEXT:    ret i1 [[TOBOOL]]
+;
+entry:
+  %0 = load i16, i16* %c, align 2
+  %1 = load i16, i16* %b, align 2
+  %conv = sext i16 %1 to i32
+  store i32 %conv, i32* %f, align 4
+  %2 = trunc i16 %1 to i8
+  %conv1 = and i8 %2, 1
+  store i8 %conv1, i8* %e, align 1
+  %3 = load i8, i8* %a, align 1
+  %narrow = mul nuw i8 %3, %conv1
+  %mul = zext i8 %narrow to i32
+  store i32 %mul, i32* %d, align 4
+  %4 = zext i8 %narrow to i16
+  %conv5 = or i16 %0, %4
+  %tobool = icmp eq i16 %conv5, 0
+  ret i1 %tobool
+}
+
+define i32 @dont_replace_trunc_2(i16* %a, i8* %b) {
+; CHECK-LABEL: @dont_replace_trunc_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[A:%.*]], align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[TMP0]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 8
+; CHECK-NEXT:    [[NARROW:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 0
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[NARROW]], 255
+; CHECK-NEXT:    [[TMP3:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[TMP4]], [[TMP2]]
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[OR]] to i8
+; CHECK-NEXT:    store i8 [[TMP5]], i8* [[B]], align 1
+; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[OR]] to i8
+; CHECK-NEXT:    [[CONV5:%.*]] = zext i8 [[TMP6]] to i32
+; CHECK-NEXT:    ret i32 [[CONV5]]
+;
+entry:
+  %0 = load i16, i16* %a, align 2
+  %cmp = icmp ugt i16 %0, 8
+  %narrow = select i1 %cmp, i16 %0, i16 0
+  %cond = trunc i16 %narrow to i8
+  %1 = load i8, i8* %b, align 1
+  %or = or i8 %1, %cond
+  store i8 %or, i8* %b, align 1
+  %conv5 = zext i8 %or to i32
+  ret i32 %conv5
+}
+
+define i32 @replace_trunk_with_mask(i16* %a) {
+; CHECK-LABEL: @replace_trunk_with_mask(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[A:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[TMP0]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond.false:
+; CHECK-NEXT:    [[TMP2:%.*]] = urem i32 535, [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], 255
+; CHECK-NEXT:    [[TMP4:%.*]] = udiv i32 [[TMP3]], 3
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[TMP4]] to i8
+; CHECK-NEXT:    [[PHITMP:%.*]] = zext i8 [[TMP5]] to i32
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[PHITMP]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+entry:
+  %0 = load i16, i16* %a
+  %cmp = icmp eq i16 %0, 0
+  br i1 %cmp, label %cond.end, label %cond.false
+
+cond.false:
+  %1 = urem i16 535, %0
+  %.lhs.trunc = trunc i16 %1 to i8
+  %2 = udiv i8 %.lhs.trunc, 3
+  %phitmp = zext i8 %2 to i32
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %phitmp, %cond.false ], [ 0, %entry ]
+  ret i32 %cond
+}
+
+define float @test_i8_sitofp(i8* %ptr, i8 %arg) {
+; CHECK-LABEL: @test_i8_sitofp(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CONV:%.*]] = sitofp i8 [[ARG]] to float
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[CONV]], 2.000000e+01
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[DIV]], [[IF_END]] ]
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %0 = load i8, i8* %ptr, align 1
+  %cmp = icmp eq i8 %0, %arg
+  br i1 %cmp, label %exit, label %if.end
+
+if.end:
+  %conv = sitofp i8 %arg to float
+  %div = fdiv float %conv, 2.000000e+01
+  br label %exit
+
+exit:
+  %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
+  ret float %res
+}
+
+define float @test_i16_sitofp(i16* %ptr, i16 %arg) {
+; CHECK-LABEL: @test_i16_sitofp(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CONV:%.*]] = sitofp i16 [[ARG]] to float
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv float [[CONV]], 2.000000e+01
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[DIV]], [[IF_END]] ]
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %0 = load i16, i16* %ptr, align 1
+  %cmp = icmp eq i16 %0, %arg
+  br i1 %cmp, label %exit, label %if.end
+
+if.end:
+  %conv = sitofp i16 %arg to float
+  %div = fdiv float %conv, 2.000000e+01
+  br label %exit
+
+exit:
+  %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
+  ret float %res
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll b/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
new file mode 100644
index 000000000000..117c4c0d5c8a
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/clear-structures.ll
@@ -0,0 +1,124 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define i32 @clear_structures(i8* nocapture readonly %fmt, [1 x i32] %ap.coerce, i8* %out, void (i32, i8*)* nocapture %write) {
+; CHECK-LABEL: @clear_structures(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND_OUTER:%.*]]
+; CHECK:       while.cond.outer:
+; CHECK-NEXT:    [[FMT_ADDR_0_PH:%.*]] = phi i8* [ [[FMT:%.*]], [[ENTRY:%.*]] ], [ [[FMT_ADDR_3:%.*]], [[WHILE_COND_OUTER_BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[FMT_ADDR_0_PH]], align 1
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    switch i8 [[TMP0]], label [[WHILE_COND]] [
+; CHECK-NEXT:    i8 0, label [[WHILE_END48:%.*]]
+; CHECK-NEXT:    i8 37, label [[WHILE_COND2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.cond2:
+; CHECK-NEXT:    [[FLAGS_0:%.*]] = phi i32 [ [[OR:%.*]], [[WHILE_COND2]] ], [ 0, [[WHILE_COND]] ]
+; CHECK-NEXT:    [[FMT_ADDR_0_PN:%.*]] = phi i8* [ [[FMT_ADDR_1:%.*]], [[WHILE_COND2]] ], [ [[FMT_ADDR_0_PH]], [[WHILE_COND]] ]
+; CHECK-NEXT:    [[FMT_ADDR_1]] = getelementptr inbounds i8, i8* [[FMT_ADDR_0_PN]], i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[FMT_ADDR_1]], align 1
+; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[TMP1]], -32
+; CHECK-NEXT:    [[CONV6:%.*]] = zext i8 [[SUB]] to i32
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 1, [[CONV6]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SHL]], 75785
+; CHECK-NEXT:    [[TOBOOL7:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[OR]] = or i32 [[SHL]], [[FLAGS_0]]
+; CHECK-NEXT:    br i1 [[TOBOOL7]], label [[WHILE_COND10_PREHEADER:%.*]], label [[WHILE_COND2]]
+; CHECK:       while.cond10.preheader:
+; CHECK-NEXT:    [[DOTOFF:%.*]] = add i8 [[TMP1]], -48
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[DOTOFF]], 10
+; CHECK-NEXT:    br i1 [[TMP2]], label [[WHILE_COND10:%.*]], label [[WHILE_END18_SPLIT:%.*]]
+; CHECK:       while.cond10:
+; CHECK-NEXT:    br label [[WHILE_COND10]]
+; CHECK:       while.end18.split:
+; CHECK-NEXT:    [[CMP20:%.*]] = icmp eq i8 [[TMP1]], 46
+; CHECK-NEXT:    br i1 [[CMP20]], label [[IF_THEN22:%.*]], label [[COND_END:%.*]]
+; CHECK:       if.then22:
+; CHECK-NEXT:    [[INCDEC_PTR23:%.*]] = getelementptr inbounds i8, i8* [[FMT_ADDR_0_PN]], i32 2
+; CHECK-NEXT:    [[DOTPR74:%.*]] = load i8, i8* [[INCDEC_PTR23]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[DOTPR74]] to i32
+; CHECK-NEXT:    [[TMP4:%.*]] = sub i32 [[TMP3]], 48
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 10
+; CHECK-NEXT:    br i1 [[TMP5]], label [[WHILE_COND24:%.*]], label [[COND_END]]
+; CHECK:       while.cond24:
+; CHECK-NEXT:    br label [[WHILE_COND24]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[FMT_ADDR_3]] = phi i8* [ [[FMT_ADDR_1]], [[WHILE_END18_SPLIT]] ], [ [[INCDEC_PTR23]], [[IF_THEN22]] ]
+; CHECK-NEXT:    [[AND39:%.*]] = and i32 [[FLAGS_0]], 2048
+; CHECK-NEXT:    [[TOBOOL40:%.*]] = icmp eq i32 [[AND39]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL40]], label [[WHILE_COND_OUTER_BACKEDGE]], label [[IF_THEN43:%.*]]
+; CHECK:       while.cond.outer.backedge:
+; CHECK-NEXT:    br label [[WHILE_COND_OUTER]]
+; CHECK:       if.then43:
+; CHECK-NEXT:    tail call void [[WRITE:%.*]](i32 43, i8* [[OUT:%.*]])
+; CHECK-NEXT:    br label [[WHILE_COND_OUTER_BACKEDGE]]
+; CHECK:       while.end48:
+; CHECK-NEXT:    ret i32 undef
+;
+entry:
+  br label %while.cond.outer
+
+while.cond.outer:
+  %fmt.addr.0.ph = phi i8* [ %fmt, %entry ], [ %fmt.addr.3, %while.cond.outer.backedge ]
+  %0 = load i8, i8* %fmt.addr.0.ph, align 1
+  br label %while.cond
+
+while.cond:
+  switch i8 %0, label %while.cond [
+  i8 0, label %while.end48
+  i8 37, label %while.cond2
+  ]
+
+while.cond2:
+  %flags.0 = phi i32 [ %or, %while.cond2 ], [ 0, %while.cond ]
+  %fmt.addr.0.pn = phi i8* [ %fmt.addr.1, %while.cond2 ], [ %fmt.addr.0.ph, %while.cond ]
+  %fmt.addr.1 = getelementptr inbounds i8, i8* %fmt.addr.0.pn, i32 1
+  %1 = load i8, i8* %fmt.addr.1, align 1
+  %sub = add i8 %1, -32
+  %conv6 = zext i8 %sub to i32
+  %shl = shl i32 1, %conv6
+  %and = and i32 %shl, 75785
+  %tobool7 = icmp eq i32 %and, 0
+  %or = or i32 %shl, %flags.0
+  br i1 %tobool7, label %while.cond10.preheader, label %while.cond2
+
+while.cond10.preheader:
+  %.off = add i8 %1, -48
+  %2 = icmp ult i8 %.off, 10
+  br i1 %2, label %while.cond10, label %while.end18.split
+
+while.cond10:
+  br label %while.cond10
+
+while.end18.split:
+  %cmp20 = icmp eq i8 %1, 46
+  br i1 %cmp20, label %if.then22, label %cond.end
+
+if.then22:
+  %incdec.ptr23 = getelementptr inbounds i8, i8* %fmt.addr.0.pn, i32 2
+  %.pr74 = load i8, i8* %incdec.ptr23, align 1
+  %.pr74.off = add i8 %.pr74, -48
+  %3 = icmp ult i8 %.pr74.off, 10
+  br i1 %3, label %while.cond24, label %cond.end
+
+while.cond24:
+  br label %while.cond24
+
+cond.end:
+  %fmt.addr.3 = phi i8* [ %fmt.addr.1, %while.end18.split ], [ %incdec.ptr23, %if.then22 ]
+  %and39 = and i32 %flags.0, 2048
+  %tobool40 = icmp eq i32 %and39, 0
+  br i1 %tobool40, label %while.cond.outer.backedge, label %if.then43
+
+while.cond.outer.backedge:
+  br label %while.cond.outer
+
+if.then43:
+  tail call void %write(i32 43, i8* %out) #1
+  br label %while.cond.outer.backedge
+
+while.end48:
+  ret i32 undef
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll
new file mode 100644
index 000000000000..6dda15c309b4
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll
@@ -0,0 +1,349 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define i32 @test_ult_254_inc_imm(i8 zeroext %x) {
+; CHECK-LABEL: @test_ult_254_inc_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, 1
+  %cmp = icmp ult i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_slt_254_inc_imm(i8 signext %x) {
+; CHECK-LABEL: @test_slt_254_inc_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, 1
+  %cmp = icmp slt i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_ult_254_inc_var(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: @test_ult_254_inc_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, %y
+  %cmp = icmp ult i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_sle_254_inc_var(i8 %x, i8 %y) {
+; CHECK-LABEL: @test_sle_254_inc_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, %y
+  %cmp = icmp sle i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_ugt_1_dec_imm(i8 zeroext %x) {
+; CHECK-LABEL: @test_ugt_1_dec_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, -1
+  %cmp = icmp ugt i8 %add, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_sgt_1_dec_imm(i8 %x) {
+; CHECK-LABEL: @test_sgt_1_dec_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[ADD]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, -1
+  %cmp = icmp sgt i8 %add, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: @test_ugt_1_dec_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SUB]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %sub = sub i8 %x, %y
+  %cmp = icmp ugt i8 %sub, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @test_sge_1_dec_var(i8 %x, i8 %y) {
+; CHECK-LABEL: @test_sge_1_dec_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[SUB]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %sub = sub i8 %x, %y
+  %cmp = icmp sge i8 %sub, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @dsp_imm1(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: @dsp_imm1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], 7
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[AND]], [[XOR]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[SUB]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %xor = xor i8 %x, %y
+  %and = and i8 %x, 7
+  %sub = sub i8 %and, %xor
+  %add = add i8 %sub, 1
+  %cmp = icmp ult i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @dsp_var(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: @dsp_var(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], 7
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[AND]], [[XOR]]
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i8 [[X]], 1
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[SUB]], [[MUL]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %xor = xor i8 %x, %y
+  %and = and i8 %x, 7
+  %sub = sub i8 %and, %xor
+  %mul = shl nuw i8 %x, 1
+  %add = add i8 %sub, %mul
+  %cmp = icmp ult i8 %add, 254
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define void @store_dsp_res(i8* %in, i8* %out, i8 %compare) {
+; CHECK-LABEL: @store_dsp_res(
+; CHECK-NEXT:    [[FIRST:%.*]] = getelementptr inbounds i8, i8* [[IN:%.*]], i32 0
+; CHECK-NEXT:    [[SECOND:%.*]] = getelementptr inbounds i8, i8* [[IN]], i32 1
+; CHECK-NEXT:    [[LD0:%.*]] = load i8, i8* [[FIRST]]
+; CHECK-NEXT:    [[LD1:%.*]] = load i8, i8* [[SECOND]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[LD0]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[COMPARE:%.*]], [[LD1]]
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], i8 [[COMPARE]], i8 [[XOR]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[LD0]], [[SELECT]]
+; CHECK-NEXT:    store i8 [[SUB]], i8* [[OUT:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+  %first = getelementptr inbounds i8, i8* %in, i32 0
+  %second = getelementptr inbounds i8, i8* %in, i32 1
+  %ld0 = load i8, i8* %first
+  %ld1 = load i8, i8* %second
+  %xor = xor i8 %ld0, -1
+  %cmp = icmp ult i8 %compare, %ld1
+  %select = select i1 %cmp, i8 %compare, i8 %xor
+  %sub = sub i8 %ld0, %select
+  store i8 %sub, i8* %out, align 1
+  ret void
+}
+
+define i32 @ugt_1_dec_imm(i8 zeroext %x) {
+; CHECK-LABEL: @ugt_1_dec_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %add = add i8 %x, -1
+  %cmp = icmp ugt i8 %add, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
+; CHECK-LABEL: @ugt_1_dec_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SUB]], 1
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %sub = sub i8 %x, %y
+  %cmp = icmp ugt i8 %sub, 1
+  %res = select i1 %cmp, i32 35, i32 47
+  ret i32 %res
+}
+
+define i32 @icmp_eq_minus_one(i8* %ptr) {
+; CHECK-LABEL: @icmp_eq_minus_one(
+; CHECK-NEXT:    [[LOAD:%.*]] = load i8, i8* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[LOAD]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[LOAD]], -1
+; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[CONV]], i32 -1
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+  %load = load i8, i8* %ptr, align 1
+  %conv = zext i8 %load to i32
+  %cmp = icmp eq i8 %load, -1
+  %ret = select i1 %cmp, i32 %conv, i32 -1
+  ret i32 %ret
+}
+
+define i32 @icmp_not(i16 zeroext %arg0, i16 zeroext %arg1) {
+; CHECK-LABEL: @icmp_not(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[ARG0:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[TMP1]], 65535
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[NOT]], [[TMP2]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 16, i32 32
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %not = xor i16 %arg0, -1
+  %cmp = icmp eq i16 %not, %arg1
+  %res = select i1 %cmp, i32 16, i32 32
+  ret i32 %res
+}
+
+define i32 @icmp_i1(i1* %arg0, i1 zeroext %arg1, i32 %a, i32 %b) {
+; CHECK-LABEL: @icmp_i1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOAD:%.*]] = load i1, i1* [[ARG0:%.*]]
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[LOAD]], true
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i1 [[ARG1:%.*]], [[NOT]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 [[A:%.*]], i32 [[B:%.*]]
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %load = load i1, i1* %arg0
+  %not = xor i1 %load, 1
+  %cmp = icmp eq i1 %arg1, %not
+  %res = select i1 %cmp, i32 %a, i32 %b
+  ret i32 %res
+}
+
+define i32 @icmp_i7(i7* %arg0, i7 zeroext %arg1, i32 %a, i32 %b) {
+; CHECK-LABEL: @icmp_i7(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i7 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[LOAD:%.*]] = load i7, i7* [[ARG0:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i7 [[LOAD]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP0]], [[ADD]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 [[A:%.*]], i32 [[B:%.*]]
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %load = load i7, i7* %arg0
+  %add = add nuw i7 %load, 1
+  %cmp = icmp ult i7 %arg1, %add
+  %res = select i1 %cmp, i32 %a, i32 %b
+  ret i32 %res
+}
+
+define i32 @icmp_i15(i15 zeroext %arg0, i15 zeroext %arg1) {
+; CHECK-LABEL: @icmp_i15(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i15 [[ARG0:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i15 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], 32767
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[XOR]], [[TMP2]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 21, i32 42
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %xor = xor i15 %arg0, -1
+  %cmp = icmp eq i15 %xor, %arg1
+  %res = select i1 %cmp, i32 21, i32 42
+  ret i32 %res
+}
+
+define i32 @icmp_minus_imm(i8* %a) {
+; CHECK-LABEL: @icmp_minus_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[A:%.*]], align 1
+; CHECK-NEXT:    [[ADD_I:%.*]] = add i8 [[TMP0]], -7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[ADD_I]], -5
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV1]]
+;
+entry:
+  %0 = load i8, i8* %a, align 1
+  %add.i = add i8 %0, -7
+  %cmp = icmp ugt i8 %add.i, -5
+  %conv1 = zext i1 %cmp to i32
+  ret i32 %conv1
+}
+
+define void @mul_with_neg_imm(i32, i32* %b) {
+; CHECK-LABEL: @mul_with_neg_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0:%.*]] to i8
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], 1
+; CHECK-NEXT:    [[CONV_I:%.*]] = mul nuw i32 [[TMP3]], 132
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[CONV_I]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    store i32 0, i32* [[B:%.*]], align 4
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %1 = trunc i32 %0 to i8
+  %2 = and i8 %1, 1
+  %conv.i = mul nuw i8 %2, -124
+  %tobool = icmp eq i8 %conv.i, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:
+  store i32 0, i32* %b, align 4
+  br label %if.end
+
+if.end:
+  ret void
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/lit.local.cfg b/llvm/test/Transforms/TypePromotion/ARM/lit.local.cfg
new file mode 100644
index 000000000000..236e1d344166
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'ARM' in config.root.targets:
+    config.unsupported = True

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll b/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
new file mode 100644
index 000000000000..e79e4ff1bdb2
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/phis-ret.ll
@@ -0,0 +1,344 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+; Check that the arguments are extended but then nothing else is.
+; This also ensures that the pass can handle loops.
+define void @phi_feeding_phi_args(i8 %a, i8 %b) {
+; CHECK-LABEL: @phi_feeding_phi_args(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[TMP2]], label [[PREHEADER:%.*]], label [[EMPTY:%.*]]
+; CHECK:       empty:
+; CHECK-NEXT:    br label [[PREHEADER]]
+; CHECK:       preheader:
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP1]], [[EMPTY]] ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ [[TMP3]], [[PREHEADER]] ], [ [[INC2:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[VAL]], 254
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[INC:%.*]] = sub nuw i32 [[VAL]], 2
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[INC1:%.*]] = shl nuw i32 [[VAL]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[INC2]], 255
+; CHECK-NEXT:    br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = icmp ugt i8 %a, %b
+  br i1 %0, label %preheader, label %empty
+
+empty:
+  br label %preheader
+
+preheader:
+  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
+  br label %loop
+
+loop:
+  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
+  %cmp = icmp ult i8 %val, 254
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %inc = sub nuw i8 %val, 2
+  br label %if.end
+
+if.else:
+  %inc1 = shl nuw i8 %val, 1
+  br label %if.end
+
+if.end:
+  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
+  %cmp1 = icmp eq i8 %inc2, 255
+  br i1 %cmp1, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; Same as above, but as the args are zeroext, we shouldn't see any uxts.
+define void @phi_feeding_phi_zeroext_args(i8 zeroext %a, i8 zeroext %b) {
+; CHECK-LABEL: @phi_feeding_phi_zeroext_args(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[B:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[TMP2]], label [[PREHEADER:%.*]], label [[EMPTY:%.*]]
+; CHECK:       empty:
+; CHECK-NEXT:    br label [[PREHEADER]]
+; CHECK:       preheader:
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[TMP1]], [[EMPTY]] ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ [[TMP3]], [[PREHEADER]] ], [ [[INC2:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[VAL]], 254
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[INC:%.*]] = sub nuw i32 [[VAL]], 2
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[INC1:%.*]] = shl nuw i32 [[VAL]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[INC2]], 255
+; CHECK-NEXT:    br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = icmp ugt i8 %a, %b
+  br i1 %0, label %preheader, label %empty
+
+empty:
+  br label %preheader
+
+preheader:
+  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
+  br label %loop
+
+loop:
+  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
+  %cmp = icmp ult i8 %val, 254
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %inc = sub nuw i8 %val, 2
+  br label %if.end
+
+if.else:
+  %inc1 = shl nuw i8 %val, 1
+  br label %if.end
+
+if.end:
+  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
+  %cmp1 = icmp eq i8 %inc2, 255
+  br i1 %cmp1, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; Just check that phis also work with i16s.
+define void @phi_i16() {
+; CHECK-LABEL: @phi_i16(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[VAL]], 128
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[INC:%.*]] = add nuw i32 [[VAL]], 2
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[INC1:%.*]] = add nuw i32 [[VAL]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INC2]], 253
+; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %val = phi i16 [ 0, %entry ], [ %inc2, %if.end ]
+  %cmp = icmp ult i16 %val, 128
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %inc = add nuw i16 %val, 2
+  br label %if.end
+
+if.else:
+  %inc1 = add nuw i16 %val, 1
+  br label %if.end
+
+if.end:
+  %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ]
+  %cmp1 = icmp ult i16 %inc2, 253
+  br i1 %cmp1, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+define i8 @ret_i8() {
+; CHECK-LABEL: @ret_i8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[VAL]], 128
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[INC:%.*]] = add nuw i32 [[VAL]], 2
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[INC1:%.*]] = add nuw i32 [[VAL]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INC2]], 253
+; CHECK-NEXT:    br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i32 [[INC2]] to i8
+; CHECK-NEXT:    ret i8 [[TMP0]]
+;
+entry:
+  br label %loop
+
+loop:
+  %val = phi i8 [ 0, %entry ], [ %inc2, %if.end ]
+  %cmp = icmp ult i8 %val, 128
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %inc = add nuw i8 %val, 2
+  br label %if.end
+
+if.else:
+  %inc1 = add nuw i8 %val, 1
+  br label %if.end
+
+if.end:
+  %inc2 = phi i8 [ %inc, %if.then], [ %inc1, %if.else ]
+  %cmp1 = icmp ult i8 %inc2, 253
+  br i1 %cmp1, label %exit, label %loop
+
+exit:
+  ret i8 %inc2
+}
+
+define i16 @phi_multiple_undefs(i16 zeroext %arg) {
+; CHECK-LABEL: @phi_multiple_undefs(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[IF_END:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[VAL]], 128
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[INC:%.*]] = add nuw i32 [[VAL]], 2
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[INC1:%.*]] = add nuw i32 [[VAL]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[INC2]] = phi i32 [ [[INC]], [[IF_THEN]] ], [ [[INC1]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[UNRELATED:%.*]] = phi i16 [ undef, [[IF_THEN]] ], [ [[ARG:%.*]], [[IF_ELSE]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INC2]], 253
+; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i16 [[UNRELATED]]
+;
+entry:
+  br label %loop
+
+loop:
+  %val = phi i16 [ undef, %entry ], [ %inc2, %if.end ]
+  %cmp = icmp ult i16 %val, 128
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %inc = add nuw i16 %val, 2
+  br label %if.end
+
+if.else:
+  %inc1 = add nuw i16 %val, 1
+  br label %if.end
+
+if.end:
+  %inc2 = phi i16 [ %inc, %if.then], [ %inc1, %if.else ]
+  %unrelated = phi i16 [ undef, %if.then ], [ %arg, %if.else ]
+  %cmp1 = icmp ult i16 %inc2, 253
+  br i1 %cmp1, label %loop, label %exit
+
+exit:
+  ret i16 %unrelated
+}
+
+define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, i8* %res) {
+; CHECK-LABEL: @promote_arg_return(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i16 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[ARG2:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP1]], 15
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[ADD]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[MUL]], [[TMP2]]
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i8
+; CHECK-NEXT:    store i8 [[CONV]], i8* [[RES:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP1]] to i16
+; CHECK-NEXT:    ret i16 [[TMP3]]
+;
+  %add = add nuw i16 %arg1, 15
+  %mul = mul nuw nsw i16 %add, 3
+  %cmp = icmp ult i16 %mul, %arg2
+  %conv = zext i1 %cmp to i8
+  store i8 %conv, i8* %res
+  ret i16 %arg1
+}
+
+define i16 @signext_bitcast_phi_select(i16 signext %start, i16* %in) {
+; CHECK-LABEL: @signext_bitcast_phi_select(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[START:%.*]] to i32
+; CHECK-NEXT:    [[CONST:%.*]] = bitcast i16 -1 to i16
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[SELECT:%.*]], [[IF_ELSE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[IDX]] to i16
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp sgt i16 [[TMP1]], [[CONST]]
+; CHECK-NEXT:    br i1 [[CMP_I]], label [[EXIT:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[IDX_NEXT:%.*]] = getelementptr i16, i16* [[IN:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    [[LD:%.*]] = load i16, i16* [[IDX_NEXT]], align 2
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[LD]] to i32
+; CHECK-NEXT:    [[CMP1_I:%.*]] = icmp eq i32 [[TMP2]], [[IDX]]
+; CHECK-NEXT:    br i1 [[CMP1_I]], label [[EXIT]], label [[IF_ELSE]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[LOBIT:%.*]] = lshr i32 [[IDX]], 15
+; CHECK-NEXT:    [[LOBIT_NOT:%.*]] = xor i32 [[LOBIT]], 1
+; CHECK-NEXT:    [[SELECT]] = add nuw i32 [[LOBIT_NOT]], [[IDX]]
+; CHECK-NEXT:    br label [[FOR_BODY]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RES]] to i16
+; CHECK-NEXT:    ret i16 [[TMP3]]
+;
+entry:
+  %const = bitcast i16 -1 to i16
+  br label %for.body
+
+for.body:
+  %idx = phi i16 [ %select, %if.else ], [ %start, %entry ]
+  %cmp.i = icmp sgt i16 %idx, %const
+  br i1 %cmp.i, label %exit, label %if.then
+
+if.then:
+  %idx.next = getelementptr i16, i16* %in, i16 %idx
+  %ld = load i16, i16* %idx.next, align 2
+  %cmp1.i = icmp eq i16 %ld, %idx
+  br i1 %cmp1.i, label %exit, label %if.else
+
+if.else:
+  %lobit = lshr i16 %idx, 15
+  %lobit.not = xor i16 %lobit, 1
+  %select = add nuw i16 %lobit.not, %idx
+  br label %for.body
+
+exit:
+  %res = phi i16 [ %ld, %if.then ], [ 0, %for.body ]
+  ret i16 %res
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/pointers.ll b/llvm/test/Transforms/TypePromotion/ARM/pointers.ll
new file mode 100644
index 000000000000..3c5f097b1b92
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/pointers.ll
@@ -0,0 +1,240 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define void @phi_pointers(i16* %a, i16* %b, i8 zeroext %M, i8 zeroext %N) {
+; CHECK-LABEL: @phi_pointers(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[M:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[N:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP0]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[ADD]], [[TMP1]]
+; CHECK-NEXT:    [[BASE:%.*]] = select i1 [[CMP]], i16* [[A:%.*]], i16* [[B:%.*]]
+; CHECK-NEXT:    [[OTHER:%.*]] = select i1 [[CMP]], i16* [[B]], i16* [[B]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[PTR:%.*]] = phi i16* [ [[BASE]], [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[AND]], [[ENTRY]] ], [ [[INC:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[LOAD:%.*]] = load i16, i16* [[PTR]], align 2
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[IDX]], 1
+; CHECK-NEXT:    [[GEP]] = getelementptr inbounds i16, i16* [[PTR]], i32 [[INC]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16* [[GEP]], [[OTHER]]
+; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %add = add nuw i8 %M, 1
+  %and = and i8 %add, 1
+  %cmp = icmp ugt i8 %add, %N
+  %base = select i1 %cmp, i16* %a, i16* %b
+  %other = select i1 %cmp, i16* %b, i16* %b
+  br label %loop
+
+loop:
+  %ptr = phi i16* [ %base, %entry ], [ %gep, %loop ]
+  %idx = phi i8 [ %and, %entry ], [ %inc, %loop ]
+  %load = load i16, i16* %ptr, align 2
+  %inc = add nuw nsw i8 %idx, 1
+  %gep = getelementptr inbounds i16, i16* %ptr, i8 %inc
+  %cond = icmp eq i16* %gep, %other
+  br i1 %cond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+define void @phi_pointers_null(i16* %a, i16* %b, i8 zeroext %M, i8 zeroext %N) {
+; CHECK-LABEL: @phi_pointers_null(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[M:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[N:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP0]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[ADD]], [[TMP1]]
+; CHECK-NEXT:    [[BASE:%.*]] = select i1 [[CMP]], i16* [[A:%.*]], i16* [[B:%.*]]
+; CHECK-NEXT:    [[OTHER:%.*]] = select i1 [[CMP]], i16* [[B]], i16* [[B]]
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i16* [[BASE]], [[OTHER]]
+; CHECK-NEXT:    br i1 [[CMP_1]], label [[FAIL:%.*]], label [[LOOP:%.*]]
+; CHECK:       fail:
+; CHECK-NEXT:    br label [[LOOP]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[PTR:%.*]] = phi i16* [ [[BASE]], [[ENTRY:%.*]] ], [ null, [[FAIL]] ], [ [[GEP:%.*]], [[IF_THEN:%.*]] ]
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[AND]], [[ENTRY]] ], [ 0, [[FAIL]] ], [ [[INC:%.*]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[UNDEF:%.*]] = icmp eq i16* [[PTR]], undef
+; CHECK-NEXT:    br i1 [[UNDEF]], label [[EXIT:%.*]], label [[IF_THEN]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[LOAD:%.*]] = load i16, i16* [[PTR]], align 2
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[IDX]], 1
+; CHECK-NEXT:    [[GEP]] = getelementptr inbounds i16, i16* [[PTR]], i32 [[INC]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i16* [[GEP]], [[OTHER]]
+; CHECK-NEXT:    br i1 [[COND]], label [[EXIT]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %add = add nuw i8 %M, 1
+  %and = and i8 %add, 1
+  %cmp = icmp ugt i8 %add, %N
+  %base = select i1 %cmp, i16* %a, i16* %b
+  %other = select i1 %cmp, i16* %b, i16* %b
+  %cmp.1 = icmp eq i16* %base, %other
+  br i1 %cmp.1, label %fail, label %loop
+
+fail:
+  br label %loop
+
+loop:
+  %ptr = phi i16* [ %base, %entry ], [ null, %fail ], [ %gep, %if.then ]
+  %idx = phi i8 [ %and, %entry ], [ 0, %fail ], [ %inc, %if.then ]
+  %undef = icmp eq i16* %ptr, undef
+  br i1 %undef, label %exit, label %if.then
+
+if.then:
+  %load = load i16, i16* %ptr, align 2
+  %inc = add nuw nsw i8 %idx, 1
+  %gep = getelementptr inbounds i16, i16* %ptr, i8 %inc
+  %cond = icmp eq i16* %gep, %other
+  br i1 %cond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+declare i8 @do_something_with_ptr(i8, i16*)
+
+define i8 @call_pointer(i8 zeroext %x, i8 zeroext %y, i16* %a, i16* %b) {
+; CHECK-LABEL: @call_pointer(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[X:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[Y:%.*]] to i32
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[OR]], 1
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[SHR]], 2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD]], 0
+; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[CMP]], i16* [[A:%.*]], i16* [[B:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[SHR]] to i8
+; CHECK-NEXT:    [[CALL:%.*]] = tail call zeroext i8 @do_something_with_ptr(i8 [[TMP3]], i16* [[PTR]])
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[CALL]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = trunc i32 [[TMP4]] to i8
+; CHECK-NEXT:    ret i8 [[TMP5]]
+;
+  %or = or i8 %x, %y
+  %shr = lshr i8 %or, 1
+  %add = add nuw i8 %shr, 2
+  %cmp = icmp ne i8 %add, 0
+  %ptr = select i1 %cmp, i16* %a, i16* %b
+  %call = tail call zeroext i8 @do_something_with_ptr(i8 %shr, i16* %ptr)
+  ret i8 %call
+}
+
+define i16 @pointer_to_pointer(i16** %arg, i16 zeroext %limit) {
+; CHECK-LABEL: @pointer_to_pointer(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ADDR:%.*]] = load i16*, i16** [[ARG:%.*]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i16, i16* [[ADDR]]
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[VAL]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP0]], 7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 256
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 128, i16 255
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+entry:
+  %addr = load i16*, i16** %arg
+  %val = load i16, i16* %addr
+  %add = add nuw i16 %val, 7
+  %cmp = icmp ult i16 %add, 256
+  %res = select i1 %cmp, i16 128, i16 255
+  ret i16 %res
+}
+
+define i8 @gep_2d_array(i8** %a, i8 zeroext %arg) {
+; CHECK-LABEL: @gep_2d_array(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i8*, i8** [[A:%.*]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8*, i8** [[ARRAYIDX_US]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8, i8* [[TMP1]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[TMP3]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], [[TMP0]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i8 27, i8 54
+; CHECK-NEXT:    ret i8 [[RES]]
+;
+entry:
+  %arrayidx.us = getelementptr inbounds i8*, i8** %a, i32 0
+  %0 = load i8*, i8** %arrayidx.us, align 4
+  %1 = load i8, i8* %0, align 1
+  %sub = sub nuw i8 %1, 1
+  %cmp = icmp ult i8 %sub, %arg
+  %res = select i1 %cmp, i8 27, i8 54
+  ret i8 %res
+}
+
+define void @gep_2d_array_loop(i16** nocapture readonly %a, i16** nocapture readonly %b, i32 %N) {
+; CHECK-LABEL: @gep_2d_array_loop(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP30:%.*]] = icmp eq i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[CMP30]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND1_PREHEADER_US:%.*]]
+; CHECK:       for.cond1.preheader.us:
+; CHECK-NEXT:    [[Y_031_US:%.*]] = phi i32 [ [[INC13_US:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    br label [[FOR_BODY4_US:%.*]]
+; CHECK:       for.body4.us:
+; CHECK-NEXT:    [[X_029_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[FOR_BODY4_US]] ]
+; CHECK-NEXT:    [[ARRAYIDX_US:%.*]] = getelementptr inbounds i16*, i16** [[A:%.*]], i32 [[X_029_US]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16*, i16** [[ARRAYIDX_US]], align 4
+; CHECK-NEXT:    [[ARRAYIDX5_US:%.*]] = getelementptr inbounds i16, i16* [[TMP0]], i32 [[Y_031_US]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[ARRAYIDX5_US]], align 2
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
+; CHECK-NEXT:    [[DEC_US:%.*]] = add nuw i32 [[TMP2]], 65535
+; CHECK-NEXT:    [[CMP6_US:%.*]] = icmp ult i32 [[DEC_US]], 16383
+; CHECK-NEXT:    [[SHL_US:%.*]] = shl nuw i32 [[DEC_US]], 2
+; CHECK-NEXT:    [[SPEC_SELECT_US:%.*]] = select i1 [[CMP6_US]], i32 [[SHL_US]], i32 [[DEC_US]]
+; CHECK-NEXT:    [[ARRAYIDX10_US:%.*]] = getelementptr inbounds i16*, i16** [[B:%.*]], i32 [[X_029_US]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load i16*, i16** [[ARRAYIDX10_US]], align 4
+; CHECK-NEXT:    [[ARRAYIDX11_US:%.*]] = getelementptr inbounds i16, i16* [[TMP3]], i32 [[Y_031_US]]
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[SPEC_SELECT_US]] to i16
+; CHECK-NEXT:    store i16 [[TMP4]], i16* [[ARRAYIDX11_US]], align 2
+; CHECK-NEXT:    [[INC_US]] = add nuw i32 [[X_029_US]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC_US]], [[N]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]], label [[FOR_BODY4_US]]
+; CHECK:       for.cond1.for.cond.cleanup3_crit_edge.us:
+; CHECK-NEXT:    [[INC13_US]] = add nuw i32 [[Y_031_US]], 1
+; CHECK-NEXT:    [[EXITCOND32:%.*]] = icmp eq i32 [[INC13_US]], [[N]]
+; CHECK-NEXT:    br i1 [[EXITCOND32]], label [[FOR_COND_CLEANUP]], label [[FOR_COND1_PREHEADER_US]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp30 = icmp eq i32 %N, 0
+  br i1 %cmp30, label %for.cond.cleanup, label %for.cond1.preheader.us
+
+for.cond1.preheader.us:
+  %y.031.us = phi i32 [ %inc13.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %entry ]
+  br label %for.body4.us
+
+for.body4.us:
+  %x.029.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
+  %arrayidx.us = getelementptr inbounds i16*, i16** %a, i32 %x.029.us
+  %0 = load i16*, i16** %arrayidx.us, align 4
+  %arrayidx5.us = getelementptr inbounds i16, i16* %0, i32 %y.031.us
+  %1 = load i16, i16* %arrayidx5.us, align 2
+  %dec.us = add nuw i16 %1, -1
+  %cmp6.us = icmp ult i16 %dec.us, 16383
+  %shl.us = shl nuw i16 %dec.us, 2
+  %spec.select.us = select i1 %cmp6.us, i16 %shl.us, i16 %dec.us
+  %arrayidx10.us = getelementptr inbounds i16*, i16** %b, i32 %x.029.us
+  %2 = load i16*, i16** %arrayidx10.us, align 4
+  %arrayidx11.us = getelementptr inbounds i16, i16* %2, i32 %y.031.us
+  store i16 %spec.select.us, i16* %arrayidx11.us, align 2
+  %inc.us = add nuw i32 %x.029.us, 1
+  %exitcond = icmp eq i32 %inc.us, %N
+  br i1 %exitcond, label %for.cond1.for.cond.cleanup3_crit_edge.us, label %for.body4.us
+
+for.cond1.for.cond.cleanup3_crit_edge.us:
+  %inc13.us = add nuw i32 %y.031.us, 1
+  %exitcond32 = icmp eq i32 %inc13.us, %N
+  br i1 %exitcond32, label %for.cond.cleanup, label %for.cond1.preheader.us
+
+for.cond.cleanup:
+  ret void
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/signed-icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/signed-icmps.ll
new file mode 100644
index 000000000000..dfdd4c10ae87
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/signed-icmps.ll
@@ -0,0 +1,103 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define i8 @eq_sgt(i8* %x, i8 *%y, i8 zeroext %z) {
+; CHECK-LABEL: @eq_sgt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOAD0:%.*]] = load i8, i8* [[X:%.*]], align 1
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i8, i8* [[Y:%.*]], align 1
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[LOAD0]], [[Z:%.*]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[LOAD1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[ADD]], -56
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[SUB]], [[ADD]]
+; CHECK-NEXT:    [[RES0:%.*]] = select i1 [[CMP]], i8 35, i8 47
+; CHECK-NEXT:    [[RES1:%.*]] = select i1 [[CMP1]], i8 [[RES0]], i8 [[SUB]]
+; CHECK-NEXT:    ret i8 [[RES1]]
+;
+entry:
+  %load0 = load i8, i8* %x, align 1
+  %load1 = load i8, i8* %y, align 1
+  %add = add i8 %load0, %z
+  %sub = sub i8 %load1, 1
+  %cmp = icmp eq i8 %add, 200
+  %cmp1 = icmp sgt i8 %sub, %add
+  %res0 = select i1 %cmp, i8 35, i8 47
+  %res1 = select i1 %cmp1, i8 %res0, i8 %sub
+  ret i8 %res1
+}
+
+define i16 @ugt_slt(i16 *%x, i16 zeroext %y, i16 zeroext %z) {
+; CHECK-LABEL: @ugt_slt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOAD0:%.*]] = load i16, i16* [[X:%.*]], align 1
+; CHECK-NEXT:    [[ADD:%.*]] = add i16 [[LOAD0]], [[Z:%.*]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub i16 [[Y:%.*]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[ADD]], [[Z]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i16 [[SUB]], [[Z]]
+; CHECK-NEXT:    [[RES0:%.*]] = select i1 [[CMP]], i16 35, i16 -1
+; CHECK-NEXT:    [[RES1:%.*]] = select i1 [[CMP1]], i16 [[RES0]], i16 0
+; CHECK-NEXT:    ret i16 [[RES1]]
+;
+entry:
+  %load0 = load i16, i16* %x, align 1
+  %add = add i16 %load0, %z
+  %sub = sub i16 %y, 1
+  %cmp = icmp slt i16 %add, %z
+  %cmp1 = icmp ugt i16 %sub, %z
+  %res0 = select i1 %cmp, i16 35, i16 -1
+  %res1 = select i1 %cmp1, i16 %res0, i16 0
+  ret i16 %res1
+}
+
+define void @urem_trunc_icmps(i16** %in, i32* %g, i32* %k) {
+; CHECK-LABEL: @urem_trunc_icmps(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PTR:%.*]] = load i16*, i16** [[IN:%.*]], align 4
+; CHECK-NEXT:    [[LD:%.*]] = load i16, i16* [[PTR]], align 2
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i16 [[LD]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label [[EXIT:%.*]], label [[COND_FALSE_I:%.*]]
+; CHECK:       cond.false.i:
+; CHECK-NEXT:    [[REM:%.*]] = urem i16 5, [[LD]]
+; CHECK-NEXT:    [[EXTRACT_T:%.*]] = trunc i16 [[REM]] to i8
+; CHECK-NEXT:    br label [[BODY:%.*]]
+; CHECK:       body:
+; CHECK-NEXT:    [[COND_IN_I_OFF0:%.*]] = phi i8 [ [[EXTRACT_T]], [[COND_FALSE_I]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[COND_IN_I_OFF0]], 7
+; CHECK-NEXT:    [[CONV5:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    store i32 [[CONV5]], i32* [[G:%.*]], align 4
+; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, i32* [[K:%.*]], align 4
+; CHECK-NEXT:    [[TOBOOL13150:%.*]] = icmp eq i32 [[DOTPR]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL13150]], label [[FOR_INC]], label [[EXIT]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[ADD]] = add nuw i8 [[COND_IN_I_OFF0]], 1
+; CHECK-NEXT:    br label [[BODY]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %ptr = load i16*, i16** %in, align 4
+  %ld = load i16, i16* %ptr, align 2
+  %cmp.i = icmp eq i16 %ld, 0
+  br i1 %cmp.i, label %exit, label %cond.false.i
+
+cond.false.i:
+  %rem = urem i16 5, %ld
+  %extract.t = trunc i16 %rem to i8
+  br label %body
+
+body:
+  %cond.in.i.off0 = phi i8 [ %extract.t, %cond.false.i ], [ %add, %for.inc ]
+  %cmp = icmp sgt i8 %cond.in.i.off0, 7
+  %conv5 = zext i1 %cmp to i32
+  store i32 %conv5, i32* %g, align 4
+  %.pr = load i32, i32* %k, align 4
+  %tobool13150 = icmp eq i32 %.pr, 0
+  br i1 %tobool13150, label %for.inc, label %exit
+
+for.inc:
+  %add = add nuw i8 %cond.in.i.off0, 1
+  br label %body
+
+exit:
+  ret void
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/signed.ll b/llvm/test/Transforms/TypePromotion/ARM/signed.ll
new file mode 100644
index 000000000000..143220a53b5c
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/signed.ll
@@ -0,0 +1,123 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+; Test to check that ARMCodeGenPrepare doesn't optimised away sign extends.
+define i16 @test_signed_load(i16* %ptr) {
+; CHECK-LABEL: @test_signed_load(
+; CHECK-NEXT:    [[LOAD:%.*]] = load i16, i16* [[PTR:%.*]]
+; CHECK-NEXT:    [[CONV0:%.*]] = zext i16 [[LOAD]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = sext i16 [[LOAD]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CONV0]], [[CONV1]]
+; CHECK-NEXT:    [[CONV2:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    ret i16 [[CONV2]]
+;
+  %load = load i16, i16* %ptr
+  %conv0 = zext i16 %load to i32
+  %conv1 = sext i16 %load to i32
+  %cmp = icmp eq i32 %conv0, %conv1
+  %conv2 = zext i1 %cmp to i16
+  ret i16 %conv2
+}
+
+; Don't allow sign bit generating opcodes.
+define i16 @test_ashr(i16 zeroext %arg) {
+; CHECK-LABEL: @test_ashr(
+; CHECK-NEXT:    [[ASHR:%.*]] = ashr i16 [[ARG:%.*]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[ASHR]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+  %ashr = ashr i16 %arg, 1
+  %cmp = icmp eq i16 %ashr, 0
+  %conv = zext i1 %cmp to i16
+  ret i16 %conv
+}
+
+define i16 @test_sdiv(i16 zeroext %arg) {
+; CHECK-LABEL: @test_sdiv(
+; CHECK-NEXT:    [[SDIV:%.*]] = sdiv i16 [[ARG:%.*]], 2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[SDIV]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+  %sdiv = sdiv i16 %arg, 2
+  %cmp = icmp ne i16 %sdiv, 0
+  %conv = zext i1 %cmp to i16
+  ret i16 %conv
+}
+
+define i16 @test_srem(i16 zeroext %arg) {
+; CHECK-LABEL: @test_srem(
+; CHECK-NEXT:    [[SREM:%.*]] = srem i16 [[ARG:%.*]], 4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i16 [[SREM]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i16
+; CHECK-NEXT:    ret i16 [[CONV]]
+;
+  %srem = srem i16 %arg, 4
+  %cmp = icmp ne i16 %srem, 0
+  %conv = zext i1 %cmp to i16
+  ret i16 %conv
+}
+
+define i32 @test_signext_b(i8* %ptr, i8 signext %arg) {
+; CHECK-LABEL: @test_signext_b(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP3]], 128
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 42, i32 20894
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %0 = load i8, i8* %ptr, align 1
+  %1 = add nuw nsw i8 %0, %arg
+  %cmp = icmp ult i8 %1, 128
+  %res = select i1 %cmp, i32 42, i32 20894
+  ret i32 %res
+}
+
+define i32 @test_signext_b_ult_slt(i8* %ptr, i8 signext %arg) {
+; CHECK-LABEL: @test_signext_b_ult_slt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[TMP3]] to i8
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i8 [[TMP4]], 126
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ule i32 [[TMP3]], [[TMP0]]
+; CHECK-NEXT:    [[OR:%.*]] = and i1 [[CMP]], [[CMP_1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[OR]], i32 42, i32 57
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %0 = load i8, i8* %ptr, align 1
+  %1 = add nuw nsw i8 %0, %arg
+  %cmp = icmp sle i8 %1, 126
+  %cmp.1 = icmp ule i8 %1, %arg
+  %or = and i1 %cmp, %cmp.1
+  %res = select i1 %or, i32 42, i32 57
+  ret i32 %res
+}
+
+define i32 @test_signext_h(i16* %ptr, i16 signext %arg) {
+; CHECK-LABEL: @test_signext_h(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP3]], 32768
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 42, i32 20894
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+entry:
+  %0 = load i16, i16* %ptr, align 1
+  %1 = add nuw nsw i16 %0, %arg
+  %cmp = icmp ult i16 %1, 32768
+  %res = select i1 %cmp, i32 42, i32 20894
+  ret i32 %res
+}
+

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/switch.ll b/llvm/test/Transforms/TypePromotion/ARM/switch.ll
new file mode 100644
index 000000000000..6736ebeea4c4
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/switch.ll
@@ -0,0 +1,291 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define void @truncate_source_phi_switch(i8* %memblock, i8* %store, i16 %arg) {
+; CHECK-LABEL: @truncate_source_phi_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRE:%.*]] = load i8, i8* [[MEMBLOCK:%.*]], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[PRE]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = trunc i16 [[ARG:%.*]] to i8
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[CONV]] to i32
+; CHECK-NEXT:    br label [[HEADER:%.*]]
+; CHECK:       header:
+; CHECK-NEXT:    [[PHI_0:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[COUNT:%.*]], [[LATCH:%.*]] ]
+; CHECK-NEXT:    [[PHI_1:%.*]] = phi i32 [ [[TMP1]], [[ENTRY]] ], [ [[PHI_3:%.*]], [[LATCH]] ]
+; CHECK-NEXT:    [[PHI_2:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[COUNT]], [[LATCH]] ]
+; CHECK-NEXT:    switch i32 [[PHI_0]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 43, label [[FOR_INC_I:%.*]]
+; CHECK-NEXT:    i32 45, label [[FOR_INC_I_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       for.inc.i:
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[PHI_1]], 1
+; CHECK-NEXT:    br label [[LATCH]]
+; CHECK:       for.inc.i.i:
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[PHI_1]], 3
+; CHECK-NEXT:    br label [[LATCH]]
+; CHECK:       default:
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[PHI_0]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[SUB]], 4
+; CHECK-NEXT:    br i1 [[CMP2]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK:       latch:
+; CHECK-NEXT:    [[PHI_3]] = phi i32 [ [[XOR]], [[FOR_INC_I]] ], [ [[AND]], [[FOR_INC_I_I]] ], [ [[PHI_2]], [[DEFAULT]] ]
+; CHECK-NEXT:    [[COUNT]] = add nuw i32 [[PHI_2]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[COUNT]] to i8
+; CHECK-NEXT:    store i8 [[TMP2]], i8* [[STORE:%.*]], align 1
+; CHECK-NEXT:    br label [[HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %pre = load i8, i8* %memblock, align 1
+  %conv = trunc i16 %arg to i8
+  br label %header
+
+header:
+  %phi.0 = phi i8 [ %pre, %entry ], [ %count, %latch ]
+  %phi.1 = phi i8 [ %conv, %entry ], [ %phi.3, %latch ]
+  %phi.2 = phi i8 [ 0, %entry], [ %count, %latch ]
+  switch i8 %phi.0, label %default [
+  i8 43, label %for.inc.i
+  i8 45, label %for.inc.i.i
+  ]
+
+for.inc.i:
+  %xor = xor i8 %phi.1, 1
+  br label %latch
+
+for.inc.i.i:
+  %and = and i8 %phi.1, 3
+  br label %latch
+
+default:
+  %sub = sub i8 %phi.0, 1
+  %cmp2 = icmp ugt i8 %sub, 4
+  br i1 %cmp2, label %latch, label %exit
+
+latch:
+  %phi.3 = phi i8 [ %xor, %for.inc.i ], [ %and, %for.inc.i.i ], [ %phi.2, %default ]
+  %count = add nuw i8 %phi.2, 1
+  store i8 %count, i8* %store, align 1
+  br label %header
+
+exit:
+  ret void
+}
+
+define i16 @icmp_switch_source(i16 zeroext %arg) {
+; CHECK-LABEL: @icmp_switch_source(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = add nuw i32 [[TMP0]], 15
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], 3
+; CHECK-NEXT:    switch i32 [[TMP0]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 0, label [[SW_BB:%.*]]
+; CHECK-NEXT:    i32 1, label [[SW_BB_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb:
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ult i32 [[MUL]], 127
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP0]], i32 [[MUL]], i32 127
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       sw.bb.i:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[MUL]], 34
+; CHECK-NEXT:    [[SELECT_I:%.*]] = select i1 [[CMP1]], i32 [[MUL]], i32 34
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       default:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SELECT]], [[SW_BB]] ], [ [[SELECT_I]], [[SW_BB_I]] ], [ [[MUL]], [[DEFAULT]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[RES]] to i16
+; CHECK-NEXT:    ret i16 [[TMP1]]
+;
+entry:
+  %conv = add nuw i16 %arg, 15
+  %mul = mul nuw nsw i16 %conv, 3
+  switch i16 %arg, label %default [
+  i16 0, label %sw.bb
+  i16 1, label %sw.bb.i
+  ]
+
+sw.bb:
+  %cmp0 = icmp ult i16 %mul, 127
+  %select = select i1 %cmp0, i16 %mul, i16 127
+  br label %exit
+
+sw.bb.i:
+  %cmp1 = icmp ugt i16 %mul, 34
+  %select.i = select i1 %cmp1, i16 %mul, i16 34
+  br label %exit
+
+default:
+  br label %exit
+
+exit:
+  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
+  ret i16 %res
+}
+
+define i16 @icmp_switch_narrow_source(i8 zeroext %arg) {
+; CHECK-LABEL: @icmp_switch_narrow_source(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[TMP0]], 15
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[ADD]], 3
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
+; CHECK-NEXT:    switch i8 [[TMP1]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT:    i8 0, label [[SW_BB:%.*]]
+; CHECK-NEXT:    i8 1, label [[SW_BB_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb:
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ult i32 [[MUL]], 127
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP0]], i32 [[MUL]], i32 127
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       sw.bb.i:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[MUL]], 34
+; CHECK-NEXT:    [[SELECT_I:%.*]] = select i1 [[CMP1]], i32 [[MUL]], i32 34
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       default:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SELECT]], [[SW_BB]] ], [ [[SELECT_I]], [[SW_BB_I]] ], [ [[MUL]], [[DEFAULT]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[RES]] to i16
+; CHECK-NEXT:    ret i16 [[TMP2]]
+;
+entry:
+  %conv = zext i8 %arg to i16
+  %add = add nuw i16 %conv, 15
+  %mul = mul nuw nsw i16 %add, 3
+  switch i8 %arg, label %default [
+  i8 0, label %sw.bb
+  i8 1, label %sw.bb.i
+  ]
+
+sw.bb:
+  %cmp0 = icmp ult i16 %mul, 127
+  %select = select i1 %cmp0, i16 %mul, i16 127
+  br label %exit
+
+sw.bb.i:
+  %cmp1 = icmp ugt i16 %mul, 34
+  %select.i = select i1 %cmp1, i16 %mul, i16 34
+  br label %exit
+
+default:
+  br label %exit
+
+exit:
+  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
+  ret i16 %res
+}
+
+define i16 @icmp_switch_trunc(i16 zeroext %arg) {
+; CHECK-LABEL: @icmp_switch_trunc(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[CONV:%.*]] = add nuw i32 [[TMP0]], 15
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], 3
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 7
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i3
+; CHECK-NEXT:    switch i3 [[TMP2]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT:    i3 0, label [[SW_BB:%.*]]
+; CHECK-NEXT:    i3 1, label [[SW_BB_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb:
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ult i32 [[MUL]], 127
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP0]], i32 [[MUL]], i32 127
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       sw.bb.i:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[MUL]], 34
+; CHECK-NEXT:    [[SELECT_I:%.*]] = select i1 [[CMP1]], i32 [[MUL]], i32 34
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       default:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SELECT]], [[SW_BB]] ], [ [[SELECT_I]], [[SW_BB_I]] ], [ [[MUL]], [[DEFAULT]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RES]] to i16
+; CHECK-NEXT:    ret i16 [[TMP3]]
+;
+entry:
+  %conv = add nuw i16 %arg, 15
+  %mul = mul nuw nsw i16 %conv, 3
+  %trunc = trunc i16 %arg to i3
+  switch i3 %trunc, label %default [
+  i3 0, label %sw.bb
+  i3 1, label %sw.bb.i
+  ]
+
+sw.bb:
+  %cmp0 = icmp ult i16 %mul, 127
+  %select = select i1 %cmp0, i16 %mul, i16 127
+  br label %exit
+
+sw.bb.i:
+  %cmp1 = icmp ugt i16 %mul, 34
+  %select.i = select i1 %cmp1, i16 %mul, i16 34
+  br label %exit
+
+default:
+  br label %exit
+
+exit:
+  %res = phi i16 [ %select, %sw.bb ], [ %select.i, %sw.bb.i ], [ %mul, %default ]
+  ret i16 %res
+}
+
+%class.ae = type { i8 }
+%class.x = type { i8 }
+%class.v = type { %class.q }
+%class.q = type { i16 }
+declare %class.x* @_ZNK2ae2afEv(%class.ae*) local_unnamed_addr
+declare %class.v* @_ZN1x2acEv(%class.x*) local_unnamed_addr
+
+define i32 @trunc_i16_i9_switch(%class.ae* %this) {
+; CHECK-LABEL: @trunc_i16_i9_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call %class.x* @_ZNK2ae2afEv(%class.ae* [[THIS:%.*]])
+; CHECK-NEXT:    [[CALL2:%.*]] = tail call %class.v* @_ZN1x2acEv(%class.x* [[CALL]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_V:%.*]], %class.v* [[CALL2]], i32 0, i32 0, i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = load i16, i16* [[TMP0]], align 2
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i16 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], 511
+; CHECK-NEXT:    [[TRUNC:%.*]] = and i32 [[TMP3]], 448
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[TRUNC]] to i9
+; CHECK-NEXT:    switch i9 [[TMP4]], label [[CLEANUP_FOLD_SPLIT:%.*]] [
+; CHECK-NEXT:    i9 0, label [[CLEANUP:%.*]]
+; CHECK-NEXT:    i9 -256, label [[IF_THEN7:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.then7:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP2]], 7
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 2, i32 1
+; CHECK-NEXT:    br label [[CLEANUP]]
+; CHECK:       cleanup.fold.split:
+; CHECK-NEXT:    br label [[CLEANUP]]
+; CHECK:       cleanup:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[COND]], [[IF_THEN7]] ], [ 0, [[ENTRY:%.*]] ], [ 2, [[CLEANUP_FOLD_SPLIT]] ]
+; CHECK-NEXT:    ret i32 [[RETVAL_0]]
+;
+entry:
+  %call = tail call %class.x* @_ZNK2ae2afEv(%class.ae* %this)
+  %call2 = tail call %class.v* @_ZN1x2acEv(%class.x* %call)
+  %0 = getelementptr inbounds %class.v, %class.v* %call2, i32 0, i32 0, i32 0
+  %1 = load i16, i16* %0, align 2
+  %2 = trunc i16 %1 to i9
+  %trunc = and i9 %2, -64
+  switch i9 %trunc, label %cleanup.fold.split [
+  i9 0, label %cleanup
+  i9 -256, label %if.then7
+  ]
+
+if.then7:
+  %3 = and i16 %1, 7
+  %tobool = icmp eq i16 %3, 0
+  %cond = select i1 %tobool, i32 2, i32 1
+  br label %cleanup
+
+cleanup.fold.split:
+  br label %cleanup
+
+cleanup:
+  %retval.0 = phi i32 [ %cond, %if.then7 ], [ 0, %entry ], [ 2, %cleanup.fold.split ]
+  ret i32 %retval.0
+}

diff  --git a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
new file mode 100644
index 000000000000..23e50dec0ca1
--- /dev/null
+++ b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll
@@ -0,0 +1,356 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+
+define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) {
+; CHECK-LABEL: @overflow_add(
+; CHECK-NEXT:    [[ADD:%.*]] = add i16 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[OR]], 1024
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 2, i16 5
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+  %add = add i16 %a, %b
+  %or = or i16 %add, 1
+  %cmp = icmp ugt i16 %or, 1024
+  %res = select i1 %cmp, i16 2, i16 5
+  ret i16 %res
+}
+
+define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
+; CHECK-LABEL: @overflow_sub(
+; CHECK-NEXT:    [[ADD:%.*]] = sub i16 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[OR]], 1024
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 2, i16 5
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+  %add = sub i16 %a, %b
+  %or = or i16 %add, 1
+  %cmp = icmp ugt i16 %or, 1024
+  %res = select i1 %cmp, i16 2, i16 5
+  ret i16 %res
+}
+
+define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
+; CHECK-LABEL: @overflow_mul(
+; CHECK-NEXT:    [[ADD:%.*]] = mul i16 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[OR]], 1024
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 2, i16 5
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+  %add = mul i16 %a, %b
+  %or = or i16 %add, 1
+  %cmp = icmp ugt i16 %or, 1024
+  %res = select i1 %cmp, i16 2, i16 5
+  ret i16 %res
+}
+
+define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
+; CHECK-LABEL: @overflow_shl(
+; CHECK-NEXT:    [[ADD:%.*]] = shl i16 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[ADD]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i16 [[OR]], 1024
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i16 2, i16 5
+; CHECK-NEXT:    ret i16 [[RES]]
+;
+  %add = shl i16 %a, %b
+  %or = or i16 %add, 1
+  %cmp = icmp ugt i16 %or, 1024
+  %res = select i1 %cmp, i16 2, i16 5
+  ret i16 %res
+}
+
+define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
+; CHECK-LABEL: @overflow_add_no_consts(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[ADD]], [[LIMIT:%.*]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, %b
+  %cmp = icmp ugt i8 %add, %limit
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
+; CHECK-LABEL: @overflow_add_const_limit(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[ADD]], -128
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, %b
+  %cmp = icmp ugt i8 %add, 128
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
+; CHECK-LABEL: @overflow_add_positive_const_limit(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[ADD]], -128
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, 1
+  %cmp = icmp ugt i8 %add, 128
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @unsafe_add_underflow(i8 zeroext %a) {
+; CHECK-LABEL: @unsafe_add_underflow(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[A:%.*]], -2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[ADD]], -2
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, -2
+  %cmp = icmp ugt i8 %add, 254
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @safe_add_underflow(i8 zeroext %a) {
+; CHECK-LABEL: @safe_add_underflow(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[TMP2]], 254
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, -1
+  %cmp = icmp ugt i8 %add, 254
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @safe_add_underflow_neg(i8 zeroext %a) {
+; CHECK-LABEL: @safe_add_underflow_neg(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[TMP1]], 2
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[TMP2]], 250
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %add = add i8 %a, -2
+  %cmp = icmp ule i8 %add, -6
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
+; CHECK-LABEL: @overflow_sub_negative_const_limit(
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SUB]], -128
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %sub = sub i8 %a, -1
+  %cmp = icmp ugt i8 %sub, 128
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @unsafe_sub_underflow(i8 zeroext %a) {
+; CHECK-LABEL: @unsafe_sub_underflow(
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A:%.*]], 6
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[SUB]], -6
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %sub = sub i8 %a, 6
+  %cmp = icmp ugt i8 %sub, 250
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @safe_sub_underflow(i8 zeroext %a) {
+; CHECK-LABEL: @safe_sub_underflow(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[SUB]], 254
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %sub = sub i8 %a, 1
+  %cmp = icmp ule i8 %sub, 254
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
+; CHECK-LABEL: @safe_sub_underflow_neg(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP1]], 4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[SUB]], 251
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %sub = sub i8 %a, 4
+  %cmp = icmp uge i8 %sub, -5
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @unsafe_sub_underflow_neg(i8 zeroext %a) {
+; CHECK-LABEL: @unsafe_sub_underflow_neg(
+; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[A:%.*]], 4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[SUB]], -3
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %sub = sub i8 %a, 4
+  %cmp = icmp ult i8 %sub, -3
+  %res = select i1 %cmp, i32 8, i32 16
+  ret i32 %res
+}
+
+define i32 @safe_sub_imm_var(i8* %b) {
+; CHECK-LABEL: @safe_sub_imm_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 248, [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SUB]], 252
+; CHECK-NEXT:    [[CONV4:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV4]]
+;
+entry:
+  %0 = load i8, i8* %b, align 1
+  %sub = sub nuw nsw i8 -8, %0
+  %cmp = icmp ugt i8 %sub, 252
+  %conv4 = zext i1 %cmp to i32
+  ret i32 %conv4
+}
+
+define i32 @safe_sub_var_imm(i8* %b) {
+; CHECK-LABEL: @safe_sub_var_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[TMP1]], 248
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SUB]], 252
+; CHECK-NEXT:    [[CONV4:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV4]]
+;
+entry:
+  %0 = load i8, i8* %b, align 1
+  %sub = sub nuw nsw i8 %0, -8
+  %cmp = icmp ugt i8 %sub, 252
+  %conv4 = zext i1 %cmp to i32
+  ret i32 %conv4
+}
+
+define i32 @safe_add_imm_var(i8* %b) {
+; CHECK-LABEL: @safe_add_imm_var(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 129, [[TMP1]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[ADD]], 127
+; CHECK-NEXT:    [[CONV4:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV4]]
+;
+entry:
+  %0 = load i8, i8* %b, align 1
+  %add = add nuw nsw i8 -127, %0
+  %cmp = icmp ugt i8 %add, 127
+  %conv4 = zext i1 %cmp to i32
+  ret i32 %conv4
+}
+
+define i32 @safe_add_var_imm(i8* %b) {
+; CHECK-LABEL: @safe_add_var_imm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[B:%.*]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[TMP1]], 129
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[ADD]], 127
+; CHECK-NEXT:    [[CONV4:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    ret i32 [[CONV4]]
+;
+entry:
+  %0 = load i8, i8* %b, align 1
+  %add = add nuw nsw i8 %0, -127
+  %cmp = icmp ugt i8 %add, 127
+  %conv4 = zext i1 %cmp to i32
+  ret i32 %conv4
+}
+
+define i8 @convert_add_order(i8 zeroext %arg) {
+; CHECK-LABEL: @convert_add_order(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[MASK_0:%.*]] = and i32 [[TMP1]], 1
+; CHECK-NEXT:    [[MASK_1:%.*]] = and i32 [[TMP1]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = or i32 [[TMP1]], 1
+; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[SHL]], 10
+; CHECK-NEXT:    [[CMP_0:%.*]] = icmp ult i32 [[ADD]], 60
+; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 [[SHL]], 40
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[TMP2]], 20
+; CHECK-NEXT:    [[MASK_SEL:%.*]] = select i1 [[CMP_1]], i32 [[MASK_0]], i32 [[MASK_1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_0]], i32 [[MASK_SEL]], i32 [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RES]] to i8
+; CHECK-NEXT:    ret i8 [[TMP3]]
+;
+  %mask.0 = and i8 %arg, 1
+  %mask.1 = and i8 %arg, 2
+  %shl = or i8 %arg, 1
+  %add = add nuw i8 %shl, 10
+  %cmp.0 = icmp ult i8 %add, 60
+  %sub = add nsw i8 %shl, -40
+  %cmp.1 = icmp ult i8 %sub, 20
+  %mask.sel = select i1 %cmp.1, i8 %mask.0, i8 %mask.1
+  %res = select i1 %cmp.0, i8 %mask.sel, i8 %arg
+  ret i8 %res
+}
+
+define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
+; CHECK-LABEL: @underflow_if_sub(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARG]], [[CONV]]
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[AND]] to i8
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TRUNC]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = add nuw nsw i32 [[TMP2]], 245
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[CONV1]], [[TMP1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_1]], i32 [[CONV1]], i32 100
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RES]] to i8
+; CHECK-NEXT:    ret i8 [[TMP3]]
+;
+  %cmp = icmp sgt i32 %arg, 0
+  %conv = zext i1 %cmp to i32
+  %and = and i32 %arg, %conv
+  %trunc = trunc i32 %and to i8
+  %conv1 = add nuw nsw i8 %trunc, -11
+  %cmp.1 = icmp ult i8 %conv1, %arg1
+  %res = select i1 %cmp.1, i8 %conv1, i8 100
+  ret i8 %res
+}
+
+define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
+; CHECK-LABEL: @underflow_if_sub_signext(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARG]], [[CONV]]
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[AND]] to i8
+; CHECK-NEXT:    [[TMP2:%.*]] = zext i8 [[TRUNC]] to i32
+; CHECK-NEXT:    [[CONV1:%.*]] = add nuw nsw i32 [[TMP2]], 245
+; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ugt i32 [[TMP1]], [[CONV1]]
+; CHECK-NEXT:    [[RES:%.*]] = select i1 [[CMP_1]], i32 [[CONV1]], i32 100
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[RES]] to i8
+; CHECK-NEXT:    ret i8 [[TMP3]]
+;
+  %cmp = icmp sgt i32 %arg, 0
+  %conv = zext i1 %cmp to i32
+  %and = and i32 %arg, %conv
+  %trunc = trunc i32 %and to i8
+  %conv1 = add nuw nsw i8 %trunc, -11
+  %cmp.1 = icmp ugt i8 %arg1, %conv1
+  %res = select i1 %cmp.1, i8 %conv1, i8 100
+  ret i8 %res
+}

diff  --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp
index 07eedfc659fe..e701000f6974 100644
--- a/llvm/tools/opt/opt.cpp
+++ b/llvm/tools/opt/opt.cpp
@@ -562,6 +562,7 @@ int main(int argc, char **argv) {
   initializeWasmEHPreparePass(Registry);
   initializeWriteBitcodePassPass(Registry);
   initializeHardwareLoopsPass(Registry);
+  initializeTypePromotionPass(Registry);
 
 #ifdef LINK_POLLY_INTO_TOOLS
   polly::initializePollyPasses(Registry);


        


More information about the llvm-commits mailing list