[llvm] r345840 - [ARM][CGP] Negative constant operand handling
Sam Parker via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 1 08:23:42 PDT 2018
Author: sam_parker
Date: Thu Nov 1 08:23:42 2018
New Revision: 345840
URL: http://llvm.org/viewvc/llvm-project?rev=345840&view=rev
Log:
[ARM][CGP] Negative constant operand handling
While mutating instructions, we sign extended negative constant
operands for binary operators that can safely overflow. This was to
allow instructions, such as add nuw i8 %a, -2, to still be able to
perform a subtraction. However, the code to handle constants doesn't
take into consideration that instructions, such as sub nuw i8 -2, %a,
require the i8 -2 to be converted into i32 254.
This is a relatively simple fix, but I've taken the time to
reorganise the code a bit - mainly that instructions that can be
promoted are cached and splitting up the Mutate function.
Differential Revision: https://reviews.llvm.org/D53972
Added:
llvm/trunk/test/CodeGen/ARM/CGP/
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-calls.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-casts.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll
llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed.ll
Removed:
llvm/trunk/test/CodeGen/ARM/arm-cgp-calls.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-casts.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-icmps.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-overflow.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-phis-ret.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-pointers.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-signed-icmps.ll
llvm/trunk/test/CodeGen/ARM/arm-cgp-signed.ll
Modified:
llvm/trunk/lib/Target/ARM/ARMCodeGenPrepare.cpp
Modified: llvm/trunk/lib/Target/ARM/ARMCodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCodeGenPrepare.cpp?rev=345840&r1=345839&r2=345840&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMCodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMCodeGenPrepare.cpp Thu Nov 1 08:23:42 2018
@@ -110,11 +110,26 @@ namespace {
class IRPromoter {
SmallPtrSet<Value*, 8> NewInsts;
SmallVector<Instruction*, 4> InstsToRemove;
+ DenseMap<Value*, Type*> TruncTysMap;
+ SmallPtrSet<Value*, 8> Promoted;
Module *M = nullptr;
LLVMContext &Ctx;
+ Type *ExtTy = nullptr;
+ Type *OrigTy = nullptr;
+
+ void PrepareConstants(SmallPtrSetImpl<Value*> &Visited,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote);
+ void ExtendSources(SmallPtrSetImpl<Value*> &Sources);
+ void PromoteTree(SmallPtrSetImpl<Value*> &Visited,
+ SmallPtrSetImpl<Value*> &Sources,
+ SmallPtrSetImpl<Instruction*> &Sinks,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote);
+ void TruncateSinks(SmallPtrSetImpl<Value*> &Sources,
+ SmallPtrSetImpl<Instruction*> &Sinks);
public:
- IRPromoter(Module *M) : M(M), Ctx(M->getContext()) { }
+ IRPromoter(Module *M) : M(M), Ctx(M->getContext()),
+ ExtTy(Type::getInt32Ty(Ctx)) { }
void Cleanup() {
for (auto *I : InstsToRemove) {
@@ -129,14 +144,17 @@ public:
void Mutate(Type *OrigTy,
SmallPtrSetImpl<Value*> &Visited,
SmallPtrSetImpl<Value*> &Sources,
- SmallPtrSetImpl<Instruction*> &Sinks);
+ SmallPtrSetImpl<Instruction*> &Sinks,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote);
};
class ARMCodeGenPrepare : public FunctionPass {
const ARMSubtarget *ST = nullptr;
IRPromoter *Promoter = nullptr;
std::set<Value*> AllVisited;
+ SmallPtrSet<Instruction*, 8> SafeToPromote;
+ bool isSafeOverflow(Instruction *I);
bool isSupportedValue(Value *V);
bool isLegalToPromote(Value *V);
bool TryToPromote(Value *V);
@@ -241,8 +259,8 @@ static bool isSink(Value *V) {
}
/// Return whether the instruction can be promoted within any modifications to
-/// it's operands or result.
-static bool isSafeOverflow(Instruction *I) {
+/// its operands or result.
+bool ARMCodeGenPrepare::isSafeOverflow(Instruction *I) {
// FIXME Do we need NSW too?
if (isa<OverflowingBinaryOperator>(I) && I->hasNoUnsignedWrap())
return true;
@@ -386,11 +404,13 @@ static bool isPromotedResultSafe(Value *
// If I is only being used by something that will require its value to be
// truncated, then we don't care about the promoted result.
auto *I = cast<Instruction>(V);
- if (I->hasOneUse() && isSink(*I->use_begin()))
+ if (I->hasOneUse() && isSink(*I->use_begin())) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Only use is a sink: " << *V << "\n");
return true;
+ }
if (isa<OverflowingBinaryOperator>(I))
- return isSafeOverflow(I);
+ return false;
return true;
}
@@ -414,56 +434,84 @@ static Intrinsic::ID getNarrowIntrinsic(
llvm_unreachable("unhandled opcode for narrow intrinsic");
}
-void IRPromoter::Mutate(Type *OrigTy,
- SmallPtrSetImpl<Value*> &Visited,
- SmallPtrSetImpl<Value*> &Sources,
- SmallPtrSetImpl<Instruction*> &Sinks) {
+static void ReplaceAllUsersOfWith(Value *From, Value *To) {
+ SmallVector<Instruction*, 4> Users;
+ Instruction *InstTo = dyn_cast<Instruction>(To);
+ for (Use &U : From->uses()) {
+ auto *User = cast<Instruction>(U.getUser());
+ if (InstTo && User->isIdenticalTo(InstTo))
+ continue;
+ Users.push_back(User);
+ }
+
+ for (auto *U : Users)
+ U->replaceUsesOfWith(From, To);
+}
+
+void
+IRPromoter::PrepareConstants(SmallPtrSetImpl<Value*> &Visited,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote) {
IRBuilder<> Builder{Ctx};
- Type *ExtTy = Type::getInt32Ty(M->getContext());
- SmallPtrSet<Value*, 8> Promoted;
- LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
- << ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
+ // First step is to prepare the instructions for mutation. Most constants
+ // just need to be zero extended into their new type, but complications arise
+ // because:
+ // - For nuw binary operators, negative immediates would need sign extending;
+ // however, instead we'll change them to positive and zext them. We can do
+ // this because:
+ // > The operators that can wrap are: add, sub, mul and shl.
+ // > shl interprets its second operand as unsigned and if the first operand
+ // is an immediate, it will need zext to be nuw.
+ // > I'm assuming mul cannot be nuw while using a negative immediate...
+ // > Which leaves the nuw add and sub to be handled; as with shl, if an
+ // immediate is used as operand 0, it will need zext to be nuw.
+ // - We also allow add and sub to safely overflow in certain circumstances
+ // and only when the value (operand 0) is being decreased.
+ //
+ // For adds and subs, that are either nuw or safely wrap and use a negative
+ // immediate as operand 1, we create an equivalent instruction using a
+ // positive immediate. That positive immediate can then be zext along with
+ // all the other immediates later.
+ for (auto *V : Visited) {
+ if (!isa<Instruction>(V))
+ continue;
- // Cache original types.
- DenseMap<Value*, Type*> TruncTysMap;
- for (auto *V : Visited)
- TruncTysMap[V] = V->getType();
+ auto *I = cast<Instruction>(V);
+ if (SafeToPromote.count(I)) {
- auto ReplaceAllUsersOfWith = [&](Value *From, Value *To) {
- SmallVector<Instruction*, 4> Users;
- Instruction *InstTo = dyn_cast<Instruction>(To);
- for (Use &U : From->uses()) {
- auto *User = cast<Instruction>(U.getUser());
- if (InstTo && User->isIdenticalTo(InstTo))
+ if (!isa<OverflowingBinaryOperator>(I))
continue;
- Users.push_back(User);
- }
- for (auto *U : Users)
- U->replaceUsesOfWith(From, To);
- };
-
- auto FixConst = [&](ConstantInt *Const, Instruction *I) {
- Constant *NewConst = isSafeOverflow(I) && Const->isNegative() ?
- ConstantExpr::getSExt(Const, ExtTy) :
- ConstantExpr::getZExt(Const, ExtTy);
- I->replaceUsesOfWith(Const, NewConst);
- };
+ if (auto *Const = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ if (!Const->isNegative())
+ break;
+
+ unsigned Opc = I->getOpcode();
+ assert((Opc == Instruction::Add || Opc == Instruction::Sub) &&
+ "expected only an add or sub to use a negative imm");
+
+ LLVM_DEBUG(dbgs() << "ARM CGP: Adjusting " << *I << "\n");
+ auto *NewConst = ConstantInt::get(Ctx, Const->getValue().abs());
+ Builder.SetInsertPoint(I);
+ Value *NewVal = Opc == Instruction::Sub ?
+ Builder.CreateAdd(I->getOperand(0), NewConst) :
+ Builder.CreateSub(I->getOperand(0), NewConst);
+ LLVM_DEBUG(dbgs() << "ARM CGP: New equivalent: " << *NewVal << "\n");
+
+ if (auto *NewInst = dyn_cast<Instruction>(NewVal)) {
+ NewInst->copyIRFlags(I);
+ NewInsts.insert(NewInst);
+ }
+ InstsToRemove.push_back(I);
+ I->replaceAllUsesWith(NewVal);
+ }
+ }
+ }
+ for (auto *I : NewInsts)
+ Visited.insert(I);
+}
- auto InsertDSPIntrinsic = [&](Instruction *I) {
- 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);
- ReplaceAllUsersOfWith(I, Call);
- InstsToRemove.push_back(I);
- NewInsts.insert(Call);
- TruncTysMap[Call] = OrigTy;
- };
+void IRPromoter::ExtendSources(SmallPtrSetImpl<Value*> &Sources) {
+ IRBuilder<> Builder{Ctx};
auto InsertZExt = [&](Value *V, Instruction *InsertPt) {
LLVM_DEBUG(dbgs() << "ARM CGP: Inserting ZExt for " << *V << "\n");
@@ -480,7 +528,8 @@ void IRPromoter::Mutate(Type *OrigTy,
TruncTysMap[ZExt] = TruncTysMap[V];
};
- // First, insert extending instructions between the sources and their users.
+
+ // Now, insert extending instructions between the sources and their users.
LLVM_DEBUG(dbgs() << "ARM CGP: Promoting sources:\n");
for (auto V : Sources) {
LLVM_DEBUG(dbgs() << " - " << *V << "\n");
@@ -494,9 +543,17 @@ void IRPromoter::Mutate(Type *OrigTy,
}
Promoted.insert(V);
}
+}
+void IRPromoter::PromoteTree(SmallPtrSetImpl<Value*> &Visited,
+ SmallPtrSetImpl<Value*> &Sources,
+ SmallPtrSetImpl<Instruction*> &Sinks,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote) {
LLVM_DEBUG(dbgs() << "ARM CGP: Mutating the tree..\n");
- // Then mutate the types of the instructions within the tree. Here we handle
+
+ IRBuilder<> Builder{Ctx};
+
+ // Mutate the types of the instructions within the tree. Here we handle
// constant operands.
for (auto *V : Visited) {
if (Sources.count(V))
@@ -511,9 +568,10 @@ void IRPromoter::Mutate(Type *OrigTy,
if ((Op->getType() == ExtTy) || !isa<IntegerType>(Op->getType()))
continue;
- if (auto *Const = dyn_cast<ConstantInt>(Op))
- FixConst(Const, I);
- else if (isa<UndefValue>(Op))
+ if (auto *Const = dyn_cast<ConstantInt>(Op)) {
+ Constant *NewConst = ConstantExpr::getZExt(Const, ExtTy);
+ I->setOperand(i, NewConst);
+ } else if (isa<UndefValue>(Op))
I->setOperand(i, UndefValue::get(ExtTy));
}
@@ -523,20 +581,42 @@ void IRPromoter::Mutate(Type *OrigTy,
}
}
- // Now we need to remove any zexts that have become unnecessary, as well
- // as insert any intrinsics.
+ // Finally, any instructions that should be promoted but haven't yet been,
+ // need to be handled using intrinsics.
for (auto *V : Visited) {
- if (Sources.count(V))
+ auto *I = dyn_cast<Instruction>(V);
+ if (!I)
continue;
- if (!shouldPromote(V) || isPromotedResultSafe(V))
+ 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.
- InsertDSPIntrinsic(cast<Instruction>(V));
+ 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);
+ ReplaceAllUsersOfWith(I, Call);
+ InstsToRemove.push_back(I);
+ NewInsts.insert(Call);
+ TruncTysMap[Call] = OrigTy;
}
+}
+
+void IRPromoter::TruncateSinks(SmallPtrSetImpl<Value*> &Sources,
+ SmallPtrSetImpl<Instruction*> &Sinks) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Fixing up the sinks:\n");
+
+ IRBuilder<> Builder{Ctx};
auto InsertTrunc = [&](Value *V) -> Instruction* {
if (!isa<Instruction>(V) || !isa<IntegerType>(V->getType()))
@@ -558,7 +638,6 @@ void IRPromoter::Mutate(Type *OrigTy,
return Trunc;
};
- LLVM_DEBUG(dbgs() << "ARM CGP: Fixing up the sinks:\n");
// Fix up any stores or returns that use the results of the promoted
// chain.
for (auto I : Sinks) {
@@ -584,6 +663,36 @@ void IRPromoter::Mutate(Type *OrigTy,
}
}
}
+}
+
+void IRPromoter::Mutate(Type *OrigTy,
+ SmallPtrSetImpl<Value*> &Visited,
+ SmallPtrSetImpl<Value*> &Sources,
+ SmallPtrSetImpl<Instruction*> &Sinks,
+ SmallPtrSetImpl<Instruction*> &SafeToPromote) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
+ << ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
+ this->OrigTy = OrigTy;
+
+ // Cache original types.
+ for (auto *V : Visited)
+ TruncTysMap[V] = V->getType();
+
+ // Convert adds and subs using negative immediates to equivalent instructions
+ // that use positive constants.
+ PrepareConstants(Visited, SafeToPromote);
+
+ // Insert zext instructions between sources and their users.
+ ExtendSources(Sources);
+
+ // Promote visited instructions, mutating their types in place. Also insert
+ // DSP intrinsics, if enabled, for adds and subs which would be unsafe to
+ // promote.
+ PromoteTree(Visited, Sources, Sinks, SafeToPromote);
+
+ // Finally, insert trunc instructions for use by calls, stores etc...
+ TruncateSinks(Sources, Sinks);
+
LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete:\n");
LLVM_DEBUG(dbgs();
for (auto *V : Sources)
@@ -651,11 +760,20 @@ bool ARMCodeGenPrepare::isSupportedValue
/// 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) {
- if (isPromotedResultSafe(V))
- return true;
auto *I = dyn_cast<Instruction>(V);
if (!I)
+ return true;
+
+ if (SafeToPromote.count(I))
+ return true;
+
+ if (isPromotedResultSafe(V) || isSafeOverflow(I)) {
+ 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
@@ -666,9 +784,6 @@ bool ARMCodeGenPrepare::isLegalToPromote
if (ST->isThumb() && !ST->hasThumb2())
return false;
- if (I->getOpcode() != Instruction::Add && I->getOpcode() != Instruction::Sub)
- 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
@@ -680,6 +795,7 @@ bool ARMCodeGenPrepare::isLegalToPromote
return false;
}
}
+ LLVM_DEBUG(dbgs() << "ARM CGP: Will use an intrinsic for: " << *I << "\n");
return true;
}
@@ -689,6 +805,8 @@ bool ARMCodeGenPrepare::TryToPromote(Val
if (TypeSize > 16 || TypeSize < 8)
return false;
+ SafeToPromote.clear();
+
if (!isSupportedValue(V) || !shouldPromote(V) || !isLegalToPromote(V))
return false;
@@ -698,9 +816,8 @@ bool ARMCodeGenPrepare::TryToPromote(Val
SetVector<Value*> WorkList;
SmallPtrSet<Value*, 8> Sources;
SmallPtrSet<Instruction*, 4> Sinks;
- WorkList.insert(V);
SmallPtrSet<Value*, 16> CurrentVisited;
- CurrentVisited.clear();
+ WorkList.insert(V);
// Return true if V was added to the worklist as a supported instruction,
// if it was already visited, or if we don't need to explore it (e.g.
@@ -783,7 +900,7 @@ bool ARMCodeGenPrepare::TryToPromote(Val
if (ToPromote < 2)
return false;
- Promoter->Mutate(OrigTy, CurrentVisited, Sources, Sinks);
+ Promoter->Mutate(OrigTy, CurrentVisited, Sources, Sinks, SafeToPromote);
return true;
}
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-calls.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-calls.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-calls.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,182 @@
+; 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
+}
+
+; Test that the transformation bails when it finds that i16 is larger than i8.
+; TODO: We should be able to remove the uxtb in these cases.
+; CHECK-LABEL: promote_i8_sink_i16_1
+; CHECK: bl dummy_i8
+; CHECK: add{{.*}} r0, #1
+; CHECK: uxtb r0, r0
+; 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
+}
+
+; Transform will bail because of the zext
+; Check that d.sroa.0.0.be is promoted passed directly into the tail call.
+; CHECK-LABEL: check_zext_phi_call_arg
+; CHECK: 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
+}
+
+declare i32 @assert(...)
+declare i8 @dummy_i8(i8)
+declare i8 @dummy2(i8*, i8, i8)
+declare i16 @dummy3(i16)
+
+declare dso_local i32 @e(...) local_unnamed_addr #1
+declare dso_local zeroext i16 @f(...) local_unnamed_addr #1
+
+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)
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-casts.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-casts.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-casts.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,340 @@
+; RUN: llc -mtriple=thumbv8.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
+; RUN: llc -mtriple=thumbv7-linux-android %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
+
+; Transform will fail because the trunc is not a sink.
+; CHECK-COMMON-LABEL: dsp_trunc
+; CHECK-COMMON: add [[ADD:[^ ]+]],
+; CHECK-DSP-NEXT: ldrh r1, [r3]
+; CHECK-DSP-NEXT: ldrh r2, [r2]
+; CHECK-DSP-NEXT: subs r1, r1, [[ADD]]
+; CHECK-DSP-NEXT: add r0, r2
+; CHECK-DSP-NEXT: uxth r3, r1
+; CHECK-DSP-NEXT: uxth r2, r0
+; CHECK-DSP-NEXT: cmp r2, r3
+
+; With DSP-IMM, we could have:
+; movs r1, #0
+; uxth r0, r0
+; usub16 r1, r1, r0
+; ldrh r0, [r2]
+; ldrh r3, [r3]
+; usub16 r0, r0, r1
+; uadd16 r1, r3, r1
+; cmp r0, r1
+define i16 @dsp_trunc(i32 %arg0, i32 %arg1, i16* %gep0, i16* %gep1) {
+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
+}
+
+; CHECK-COMMON-LABEL: trunc_i16_i8
+; CHECK-COMMON: ldrh
+; CHECK-COMMON: uxtb
+; CHECK-COMMON: cmp
+define i8 @trunc_i16_i8(i16* %ptr, i16 zeroext %arg0, i8 zeroext %arg1) {
+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.
+; CHECK-COMMON-LABEL: icmp_i32_zext:
+; CHECK-COMMON: sub
+; CHECK-COMMON: uxtb
+; CHECK-COMMON: cmp
+define i8 @icmp_i32_zext(i8* %ptr) {
+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
+; CHECK-COMMON-LABEL: icmp_sext_zext_store_i8_i16
+; CHECK-COMMON: ldrb
+; CHECK-COMMON: ldrsh
+define i32 @icmp_sext_zext_store_i8_i16() {
+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
+}
+
+; CHECK-COMMON-LABEL: or_icmp_ugt:
+; CHECK-COMMON: ldrb
+; CHECK-COMMON: sub.w
+; CHECK-COMMON-NOT: uxt
+; CHECK-COMMON: cmp.w
+; CHECK-COMMON-NOT: uxt
+; CHECK-COMMON: cmp
+define i1 @or_icmp_ugt(i32 %arg, i8* %ptr) {
+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
+}
+
+; CHECK-COMMON-LABEL: icmp_switch_trunc:
+; CHECK-COMMON-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
+}
+
+; We currently only handle truncs as sinks, so a uxt will still be needed for
+; the icmp ugt instruction.
+; CHECK-COMMON-LABEL: urem_trunc_icmps
+; CHECK-COMMON: cmp
+; CHECK-COMMON: uxt
+; CHECK-COMMON: cmp
+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 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-COMMON-LABEL: phi_feeding_switch
+; CHECK-COMMON: ldrb
+; CHECK-COMMON: uxtb
+define void @phi_feeding_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 that %exp requires uxth in all cases, and will also be required to
+; promote %1 for the call - unless we can generate a uadd16.
+; CHECK-COMMON-LABEL: zext_load_sink_call:
+; CHECK-COMMON: uxt
+; uadd16
+; cmp
+; CHECK-COMMON: uxt
+define i32 @zext_load_sink_call(i16* %ptr, i16 %exp) {
+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
+}
+
+%class.ae = type { i8 }
+%class.x = type { i8 }
+%class.v = type { %class.q }
+%class.q = type { i16 }
+
+; CHECK-COMMON-LABEL: trunc_i16_i9_switch
+; CHECK-COMMON-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
+}
+
+; CHECK-COMMON-LABEL: bitcast_i16
+; CHECK-COMMON-NOT: uxt
+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
+}
+
+; CHECK-COMMON-LABEL: bitcast_i8
+; CHECK-COMMON-NOT: uxt
+define i8 @bitcast_i8(i8 zeroext %arg0, i8 zeroext %arg1) {
+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
+}
+
+; CHECK-COMMON-LABEL: bitcast_i16_minus
+; CHECK-COMMON-NOT: uxt
+define i16 @bitcast_i16_minus(i16 zeroext %arg0, i16 zeroext %arg1) {
+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
+}
+
+; CHECK-COMMON-LABEL: bitcast_i8_minus
+; CHECK-COMMON-NOT: uxt
+define i8 @bitcast_i8_minus(i8 zeroext %arg0, i8 zeroext %arg1) {
+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 %class.x* @_ZNK2ae2afEv(%class.ae*) local_unnamed_addr
+declare %class.v* @_ZN1x2acEv(%class.x*) local_unnamed_addr
+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
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-icmps.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,312 @@
+; 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 r0, #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
+}
+
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-overflow.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,232 @@
+; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 %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: subs r0, #2
+; CHECK: uxtb [[EXT:r[0-9]+]], r0
+; CHECK: cmp [[EXT]], #255
+; CHECK: moveq r0, #8
+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: add.w [[ADD:r[0-9]+]], r0, #8
+; 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: sub.w [[SUB:r[0-9]+]], r0, #127
+; 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
+}
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-phis-ret.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,174 @@
+; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
+; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
+; 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 --check-prefix=CHECK-DSP
+; 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 --check-prefix=CHECK-DSP-IMM
+
+; 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
+}
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-pointers.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,135 @@
+; 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
+}
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed-icmps.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,109 @@
+; 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: add
+; CHECK-DSP: uxtb
+; CHECK-DSP: cmp
+; CHECK-DSP: sxtb
+; CHECK-DSP: sub
+; CHECK-DSP: sxtb
+; CHECK-DSP: cmp
+
+; CHECK-DSP-IMM: uadd8 [[ADD:r[0-9]+]],
+; CHECK-DSP-IMM: cmp [[ADD]],
+; CHECK-DSP-IMM: sxtb [[SEXT0:r[0-9]+]], [[ADD]]
+; CHECK-DSP-IMM: usub8 [[SUB:r[0-9]+]],
+; 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: sxth [[ARG:r[0-9]+]], r2
+; CHECK-DSP-IMM: uadd16 [[ADD:r[0-9]+]],
+; CHECK-DSP-IMM: sxth.w [[SEXT:r[0-9]+]], [[ADD]]
+; 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
+}
Added: llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed.ll?rev=345840&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/CGP/arm-cgp-signed.ll Thu Nov 1 08:23:42 2018
@@ -0,0 +1,45 @@
+; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8m.main -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
+}
+
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-calls.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-calls.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-calls.ll (removed)
@@ -1,182 +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
-}
-
-; Test that the transformation bails when it finds that i16 is larger than i8.
-; TODO: We should be able to remove the uxtb in these cases.
-; CHECK-LABEL: promote_i8_sink_i16_1
-; CHECK: bl dummy_i8
-; CHECK: add{{.*}} r0, #1
-; CHECK: uxtb r0, r0
-; 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
-}
-
-; Transform will bail because of the zext
-; Check that d.sroa.0.0.be is promoted passed directly into the tail call.
-; CHECK-LABEL: check_zext_phi_call_arg
-; CHECK: 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
-}
-
-declare i32 @assert(...)
-declare i8 @dummy_i8(i8)
-declare i8 @dummy2(i8*, i8, i8)
-declare i16 @dummy3(i16)
-
-declare dso_local i32 @e(...) local_unnamed_addr #1
-declare dso_local zeroext i16 @f(...) local_unnamed_addr #1
-
-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)
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-casts.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-casts.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-casts.ll (removed)
@@ -1,340 +0,0 @@
-; RUN: llc -mtriple=thumbv8.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
-; RUN: llc -mtriple=thumbv7-linux-android %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
-
-; Transform will fail because the trunc is not a sink.
-; CHECK-COMMON-LABEL: dsp_trunc
-; CHECK-COMMON: add [[ADD:[^ ]+]],
-; CHECK-DSP-NEXT: ldrh r1, [r3]
-; CHECK-DSP-NEXT: ldrh r2, [r2]
-; CHECK-DSP-NEXT: subs r1, r1, [[ADD]]
-; CHECK-DSP-NEXT: add r0, r2
-; CHECK-DSP-NEXT: uxth r3, r1
-; CHECK-DSP-NEXT: uxth r2, r0
-; CHECK-DSP-NEXT: cmp r2, r3
-
-; With DSP-IMM, we could have:
-; movs r1, #0
-; uxth r0, r0
-; usub16 r1, r1, r0
-; ldrh r0, [r2]
-; ldrh r3, [r3]
-; usub16 r0, r0, r1
-; uadd16 r1, r3, r1
-; cmp r0, r1
-define i16 @dsp_trunc(i32 %arg0, i32 %arg1, i16* %gep0, i16* %gep1) {
-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
-}
-
-; CHECK-COMMON-LABEL: trunc_i16_i8
-; CHECK-COMMON: ldrh
-; CHECK-COMMON: uxtb
-; CHECK-COMMON: cmp
-define i8 @trunc_i16_i8(i16* %ptr, i16 zeroext %arg0, i8 zeroext %arg1) {
-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.
-; CHECK-COMMON-LABEL: icmp_i32_zext:
-; CHECK-COMMON: sub
-; CHECK-COMMON: uxtb
-; CHECK-COMMON: cmp
-define i8 @icmp_i32_zext(i8* %ptr) {
-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
-; CHECK-COMMON-LABEL: icmp_sext_zext_store_i8_i16
-; CHECK-COMMON: ldrb
-; CHECK-COMMON: ldrsh
-define i32 @icmp_sext_zext_store_i8_i16() {
-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
-}
-
-; CHECK-COMMON-LABEL: or_icmp_ugt:
-; CHECK-COMMON: ldrb
-; CHECK-COMMON: sub.w
-; CHECK-COMMON-NOT: uxt
-; CHECK-COMMON: cmp.w
-; CHECK-COMMON-NOT: uxt
-; CHECK-COMMON: cmp
-define i1 @or_icmp_ugt(i32 %arg, i8* %ptr) {
-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
-}
-
-; CHECK-COMMON-LABEL: icmp_switch_trunc:
-; CHECK-COMMON-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
-}
-
-; We currently only handle truncs as sinks, so a uxt will still be needed for
-; the icmp ugt instruction.
-; CHECK-COMMON-LABEL: urem_trunc_icmps
-; CHECK-COMMON: cmp
-; CHECK-COMMON: uxt
-; CHECK-COMMON: cmp
-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 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-COMMON-LABEL: phi_feeding_switch
-; CHECK-COMMON: ldrb
-; CHECK-COMMON: uxtb
-define void @phi_feeding_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 that %exp requires uxth in all cases, and will also be required to
-; promote %1 for the call - unless we can generate a uadd16.
-; CHECK-COMMON-LABEL: zext_load_sink_call:
-; CHECK-COMMON: uxt
-; uadd16
-; cmp
-; CHECK-COMMON: uxt
-define i32 @zext_load_sink_call(i16* %ptr, i16 %exp) {
-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
-}
-
-%class.ae = type { i8 }
-%class.x = type { i8 }
-%class.v = type { %class.q }
-%class.q = type { i16 }
-
-; CHECK-COMMON-LABEL: trunc_i16_i9_switch
-; CHECK-COMMON-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
-}
-
-; CHECK-COMMON-LABEL: bitcast_i16
-; CHECK-COMMON-NOT: uxt
-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
-}
-
-; CHECK-COMMON-LABEL: bitcast_i8
-; CHECK-COMMON-NOT: uxt
-define i8 @bitcast_i8(i8 zeroext %arg0, i8 zeroext %arg1) {
-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
-}
-
-; CHECK-COMMON-LABEL: bitcast_i16_minus
-; CHECK-COMMON-NOT: uxt
-define i16 @bitcast_i16_minus(i16 zeroext %arg0, i16 zeroext %arg1) {
-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
-}
-
-; CHECK-COMMON-LABEL: bitcast_i8_minus
-; CHECK-COMMON-NOT: uxt
-define i8 @bitcast_i8_minus(i8 zeroext %arg0, i8 zeroext %arg1) {
-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 %class.x* @_ZNK2ae2afEv(%class.ae*) local_unnamed_addr
-declare %class.v* @_ZN1x2acEv(%class.x*) local_unnamed_addr
-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
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-icmps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-icmps.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-icmps.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-icmps.ll (removed)
@@ -1,312 +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 r0, #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
-}
-
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-overflow.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-overflow.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-overflow.ll (removed)
@@ -1,180 +0,0 @@
-; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 %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: subs r0, #2
-; CHECK: uxtb [[EXT:r[0-9]+]], r0
-; CHECK: cmp [[EXT]], #255
-; CHECK: moveq r0, #8
-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: 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
-}
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-phis-ret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-phis-ret.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-phis-ret.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-phis-ret.ll (removed)
@@ -1,174 +0,0 @@
-; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
-; RUN: llc -mtriple=thumbv8m.main -arm-disable-cgp=false %s -o - | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-NODSP
-; 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 --check-prefix=CHECK-DSP
-; 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 --check-prefix=CHECK-DSP-IMM
-
-; 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
-}
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-pointers.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-pointers.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-pointers.ll (removed)
@@ -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
-}
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-signed-icmps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-signed-icmps.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-signed-icmps.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-signed-icmps.ll (removed)
@@ -1,109 +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: add
-; CHECK-DSP: uxtb
-; CHECK-DSP: cmp
-; CHECK-DSP: sxtb
-; CHECK-DSP: sub
-; CHECK-DSP: sxtb
-; CHECK-DSP: cmp
-
-; CHECK-DSP-IMM: uadd8 [[ADD:r[0-9]+]],
-; CHECK-DSP-IMM: cmp [[ADD]],
-; CHECK-DSP-IMM: sxtb [[SEXT0:r[0-9]+]], [[ADD]]
-; CHECK-DSP-IMM: usub8 [[SUB:r[0-9]+]],
-; 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: sxth [[ARG:r[0-9]+]], r2
-; CHECK-DSP-IMM: uadd16 [[ADD:r[0-9]+]],
-; CHECK-DSP-IMM: sxth.w [[SEXT:r[0-9]+]], [[ADD]]
-; 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
-}
Removed: llvm/trunk/test/CodeGen/ARM/arm-cgp-signed.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-cgp-signed.ll?rev=345839&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-cgp-signed.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/arm-cgp-signed.ll (removed)
@@ -1,45 +0,0 @@
-; RUN: llc -mtriple=thumbv7m -arm-disable-cgp=false %s -o - | FileCheck %s
-; RUN: llc -mtriple=thumbv8m.main -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
-}
-
More information about the llvm-commits
mailing list