https://github.com/houngkoungting updated https://github.com/llvm/llvm-project/pull/207568
From d878643fb9129ef0e63f3137da2d0ff7d653a290 Mon Sep 17 00:00:00 2001 From: Yuan Suo <[email protected]> Date: Sun, 5 Jul 2026 11:04:44 +0000 Subject: [PATCH 1/2] [LifetimeSafety] Add multi-block support to buildOriginFlowChain (#204592) After introducing `buildOriginFlowChain` to use-after-scope diagnostics, it should support multi-block analysis. This also allows it to be reused by other diagnostics. In some loops, `UseFact` may appear before `OriginFlowFact`: ```cpp void for_loop_use_before_loop_body(MyObj safe) { MyObj* p = &safe; for (int i = 0; i < 1; ++i) { (void)*p; MyObj s; p = &s; } (void)*p; } ``` So I no longer use `StartPoint` as the initial search starting point; it is only used to locate the corresponding block. --------- Signed-off-by: Yuan Suo <[email protected]> --- .../Analysis/Analyses/LifetimeSafety/Facts.h | 1 + .../Analyses/LifetimeSafety/LoanPropagation.h | 19 +- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 6 +- clang/lib/Analysis/LifetimeSafety/Facts.cpp | 14 +- .../LifetimeSafety/LoanPropagation.cpp | 142 ++- clang/test/Sema/LifetimeSafety/safety-c.c | 4 +- clang/test/Sema/LifetimeSafety/safety.cpp | 160 +++- .../unittests/Analysis/LifetimeSafetyTest.cpp | 66 +- llvm/lib/CodeGen/CodeGenPrepare.cpp | 64 ++ llvm/test/CodeGen/ARM/aes-erratum-fix.ll | 894 ++++++++---------- .../CodeGenPrepare/X86/hoist-bitcast-i686.ll | 27 + .../X86/hoist-bitcast-integer-to-vector.ll | 63 ++ 12 files changed, 881 insertions(+), 579 deletions(-) create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-i686.ll create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-integer-to-vector.ll diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h index 8dccccc0f2257..94db2a7f311ae 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h @@ -385,6 +385,7 @@ class FactManager { /// Retrieves all the facts in the block containing Program Point P. /// \note This is intended for testing only. llvm::ArrayRef<const Fact *> getBlockContaining(ProgramPoint P) const; + size_t getBlockID(ProgramPoint P) const; unsigned getNumFacts() const { return NextFactID.Value; } diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h index 724c6eee7d3c2..838daa024c953 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h @@ -40,16 +40,21 @@ class LoanPropagationAnalysis { /// Builds the chain of origins through which a loan has propagated. /// - /// Starting from StartPoint where StartOID currently holds TargetLoan, - /// this function traces backwards through OriginFlowFacts to identify the + /// Starting from the last fact of the block containing StartPoint, this + /// function performs a DFS over CFG blocks to explore all reachable blocks. + /// Within each block, facts are processed in reverse order. + /// + /// The traversal follows OriginFlowFacts backwards to reconstruct the /// sequence of origins through which the loan flowed, ending at the origin /// where the loan was originally issued. - llvm::SmallVector<OriginID> - buildOriginFlowChain(ProgramPoint StartPoint, const OriginID StartOID, - const LoanID TargetLoan) const; + llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const; - llvm::SmallVector<OriginID> - buildOriginFlowChain(const UseFact *UF, const LoanID TargetLoan) const; + llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const; private: class Impl; diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index 746ebbfb15c39..f72f7f80abbc0 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -67,6 +67,7 @@ class LifetimeChecker { FactManager &FactMgr; LifetimeSafetySemaHelper *SemaHelper; ASTContext &AST; + const CFG *Cfg; const Decl *FD; const LifetimeSafetyOpts &LSOpts; @@ -92,7 +93,8 @@ class LifetimeChecker { const LifetimeSafetyOpts &LSOpts) : LoanPropagation(LoanPropagation), MovedLoans(MovedLoans), LiveOrigins(LiveOrigins), FactMgr(FM), SemaHelper(SemaHelper), - AST(ADC.getASTContext()), FD(ADC.getDecl()), LSOpts(LSOpts) { + AST(ADC.getASTContext()), Cfg(ADC.getCFG()), FD(ADC.getDecl()), + LSOpts(LSOpts) { for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>()) for (const Fact *F : FactMgr.getFacts(B)) if (const auto *EF = F->getAs<ExpireFact>()) @@ -272,7 +274,7 @@ class LifetimeChecker { // Scope-based expiry (use-after-scope). SemaHelper->reportUseAfterScope( IssueExpr, UF->getUseExpr(), MovedExpr, ExpiryLoc, - getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID))); + getExprChain(LoanPropagation.buildOriginFlowChain(UF, LID, Cfg))); } else if (const auto *OEF = CausingFact.dyn_cast<const OriginEscapesFact *>()) { diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp b/clang/lib/Analysis/LifetimeSafety/Facts.cpp index 15b666fbdf7ca..ec2d42e10206a 100644 --- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp @@ -171,12 +171,14 @@ void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC, llvm::ArrayRef<const Fact *> FactManager::getBlockContaining(ProgramPoint P) const { - for (const auto &BlockToFactsVec : BlockToFacts) { - for (const Fact *F : BlockToFactsVec) - if (F == P) - return BlockToFactsVec; - } - return {}; + return BlockToFacts[getBlockID(P)]; } +size_t FactManager::getBlockID(ProgramPoint P) const { + for (size_t i = 0; i < BlockToFacts.size(); ++i) + for (const Fact *F : BlockToFacts[i]) + if (F == P) + return i; + llvm_unreachable("Failed to find BlockID for given ProgramPoint"); +} } // namespace clang::lifetimes::internal diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp index a67b1b3c0f826..078892bd48c10 100644 --- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp @@ -18,6 +18,7 @@ #include "clang/Analysis/CFG.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" @@ -202,53 +203,74 @@ class AnalysisImpl return getLoans(getState(P), OID); } - llvm::SmallVector<OriginID> - buildOriginFlowChain(ProgramPoint StartPoint, const OriginID StartOID, - const LoanID TargetLoan) const { + llvm::SmallVector<OriginID> buildOriginFlowChain(ProgramPoint StartPoint, + const OriginID StartOID, + const LoanID TargetLoan, + const CFG *Cfg) const { assert(getLoans(StartOID, StartPoint).contains(TargetLoan) && "TargetLoan must be present in the StartOID at the StartPoint"); - OriginID CurrOID = StartOID; - llvm::SmallVector<OriginID> OriginFlowChain; - llvm::ArrayRef<const Fact *> Facts = FactMgr.getBlockContaining(StartPoint); - const auto *StartIt = llvm::find(Facts, StartPoint); - assert(StartIt != Facts.end()); - - for (const Fact *F : - llvm::reverse(llvm::make_range(Facts.begin(), StartIt))) { - if (const auto *IF = F->getAs<IssueFact>()) - if (IF->getLoanID() == TargetLoan) { - assert(IF->getOriginID() == CurrOID); - return OriginFlowChain; - } + // Locate the CFG block containing the StartPoint + const CFGBlock *EndBlock = nullptr; + size_t BlockID = FactMgr.getBlockID(StartPoint); + for (const CFGBlock *Block : *Cfg) + if (Block->getBlockID() == BlockID) { + EndBlock = Block; + break; + } - const auto *OFF = F->getAs<OriginFlowFact>(); - if (!OFF) - continue; - if (OFF->getDestOriginID() != CurrOID) - continue; + // Set up DFS traversal state + // SearchState tracks which block we're in and which origin we're tracing + // Each DFSNode maintains its own OriginFlowChain. + using SearchState = std::pair<const CFGBlock *, OriginID>; + struct DFSNode { + SearchState CurrState; + llvm::SmallVector<OriginID> OriginFlowChain; + }; + + llvm::SmallVector<DFSNode> PendingStates; + llvm::SmallSet<SearchState, 16> VistedStates; + PendingStates.push_back({{EndBlock, StartOID}, {}}); + + // DFS loop to trace loan backwards through CFG + while (!PendingStates.empty()) { + DFSNode CurrNode = PendingStates.pop_back_val(); + auto [CurrBlock, CurrOID] = CurrNode.CurrState; + + // Trace origins within the current block + const auto [BuildResult, Complete] = + buildOriginFlowChain(CurrBlock, CurrOID, TargetLoan); + if (!BuildResult.empty()) { + CurrNode.OriginFlowChain.append(BuildResult); + CurrOID = BuildResult.back(); + } - const OriginID SrcOriginID = OFF->getSrcOriginID(); - if (!getLoans(SrcOriginID, OFF).contains(TargetLoan)) - continue; - OriginFlowChain.push_back(SrcOriginID); - CurrOID = SrcOriginID; + // If we found the IssueFact, we're done + if (Complete) + return CurrNode.OriginFlowChain; + + // Only explore predecessor blocks where the target loan is present in the + // current origin. + for (const CFGBlock *PredBlock : CurrBlock->preds()) { + SearchState NextState = {PredBlock, CurrOID}; + if (getLoans(getOutState(PredBlock), CurrOID).contains(TargetLoan) && + VistedStates.insert(NextState).second) + PendingStates.push_back({NextState, CurrNode.OriginFlowChain}); + } } - // FIXME: Ideally, this return is unreachable and should be an assert - // because we expect to always finish at an IssueFact. But since current - // traversal is limited to a single CFG block, multi-block OriginFlowChain - // construction might miss the IssueFact. We should add llvm_unreachable - // here once multi-block support is implemented. - return {}; + llvm_unreachable( + "buildOriginFlowChain did not reach IssueFact for TargetLoan"); } - llvm::SmallVector<OriginID> - buildOriginFlowChain(const UseFact *UF, const LoanID TargetLoan) const { + llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF, + const LoanID TargetLoan, + const CFG *Cfg) const { for (const OriginList *Cur = UF->getUsedOrigins(); Cur; Cur = Cur->peelOuterOrigin()) if (getLoans(Cur->getOuterOriginID(), UF).contains(TargetLoan)) - return buildOriginFlowChain(UF, Cur->getOuterOriginID(), TargetLoan); + return buildOriginFlowChain(UF, Cur->getOuterOriginID(), TargetLoan, + Cfg); return {}; } @@ -275,6 +297,40 @@ class AnalysisImpl return LoanSetFactory.getEmptySet(); } + /// Builds the chain of origins through which a loan has propagated. + /// + /// This procedure operates strictly within a single Block. Starting from the + /// last fact of the Block, it traces backwards through OriginFlowFacts to + /// identify the sequence of origins through which the loan flowed. + /// + /// Returns (chain, true) if the target loan origin is found during the + /// traversal, otherwise returns (chain, false). + std::pair<llvm::SmallVector<OriginID>, bool> + buildOriginFlowChain(const CFGBlock *Block, const OriginID StartOID, + const LoanID TargetLoan) const { + OriginID CurrOID = StartOID; + llvm::SmallVector<OriginID> OriginFlowChain; + + for (const Fact *F : llvm::reverse(FactMgr.getFacts(Block))) { + if (const auto *IF = F->getAs<IssueFact>()) + if (IF->getLoanID() == TargetLoan && IF->getOriginID() == CurrOID) + return {OriginFlowChain, true}; + + const auto *OFF = F->getAs<OriginFlowFact>(); + if (!OFF || OFF->getDestOriginID() != CurrOID) + continue; + + const OriginID SrcOriginID = OFF->getSrcOriginID(); + if (!getLoans(SrcOriginID, OFF).contains(TargetLoan)) + continue; + + OriginFlowChain.push_back(SrcOriginID); + CurrOID = SrcOriginID; + } + + return {OriginFlowChain, false}; + } + OriginLoanMap::Factory &OriginLoanMapFactory; LoanSet::Factory &LoanSetFactory; /// Boolean vector indexed by origin ID. If true, the origin appears in @@ -303,16 +359,14 @@ LoanSet LoanPropagationAnalysis::getLoans(OriginID OID, ProgramPoint P) const { return PImpl->getLoans(OID, P); } -llvm::SmallVector<OriginID> -LoanPropagationAnalysis::buildOriginFlowChain(ProgramPoint StartPoint, - const OriginID StartOID, - const LoanID TargetLoan) const { - return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan); +llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( + ProgramPoint StartPoint, const OriginID StartOID, const LoanID TargetLoan, + const CFG *Cfg) const { + return PImpl->buildOriginFlowChain(StartPoint, StartOID, TargetLoan, Cfg); } -llvm::SmallVector<OriginID> -LoanPropagationAnalysis::buildOriginFlowChain(const UseFact *UF, - const LoanID TargetLoan) const { - return PImpl->buildOriginFlowChain(UF, TargetLoan); +llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain( + const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const { + return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg); } } // namespace clang::lifetimes::internal diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c b/clang/test/Sema/LifetimeSafety/safety-c.c index e9443899c9935..42adbbb3f0628 100644 --- a/clang/test/Sema/LifetimeSafety/safety-c.c +++ b/clang/test/Sema/LifetimeSafety/safety-c.c @@ -93,7 +93,9 @@ void conditional_operator_lifetimebound(int cond) { int *p; { int a, b; - p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} + p = identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ + // expected-note {{result of call to 'identity' aliases the storage of local variable 'a'}} \ + // expected-note {{result of call to 'identity' aliases the storage of local variable 'b'}} : &b); // expected-warning {{local variable 'b' does not live long enough}} } // expected-note {{local variable 'a' is destroyed here}} \ // expected-note {{local variable 'b' is destroyed here}} diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp index 7362ca632b2e5..3c9b58c4e4957 100644 --- a/clang/test/Sema/LifetimeSafety/safety.cpp +++ b/clang/test/Sema/LifetimeSafety/safety.cpp @@ -236,7 +236,7 @@ void overrides_potential(bool cond) { { MyObj s; q = &s; // expected-warning {{does not live long enough}} - p = q; + p = q; // expected-note {{local variable 'q' aliases the storage of local variable 's'}} } // expected-note {{local variable 's' is destroyed here}} if (cond) { @@ -448,7 +448,7 @@ void loan_from_previous_iteration(MyObj safe, bool condition) { p = &x; // expected-warning {{does not live long enough}} if (condition) - q = p; + q = p; // expected-note {{local variable 'p' aliases the storage of local variable 'x'}} (void)*p; (void)*q; // expected-note {{later used here}} } // expected-note {{local variable 'x' is destroyed here}} @@ -846,7 +846,8 @@ void lifetimebound_multiple_args_potential(bool cond) { MyObj obj1; if (cond) { MyObj obj2; - v = Choose(true, + v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj1'}} \ + // expected-note {{result of call to 'Choose' aliases the storage of local variable 'obj2'}} obj1, // expected-warning {{local variable 'obj1' does not live long enough}} obj2); // expected-warning {{local variable 'obj2' does not live long enough}} } // expected-note {{local variable 'obj2' is destroyed here}} @@ -854,6 +855,18 @@ void lifetimebound_multiple_args_potential(bool cond) { v.use(); // expected-note 2 {{later used here}} } +// FIXME: Detect this. +void func_pointer() { + View p; + View (*func_ptr)(View v [[clang::lifetimebound]]); + { + MyObj s; + View a = Identity(s); + p = func_ptr(a); + } + p.use(); +} + View SelectFirst(View a [[clang::lifetimebound]], View b); void lifetimebound_mixed_args() { View v; @@ -940,7 +953,7 @@ void lifetimebound_partial_safety(bool cond) { if (cond) { MyObj temp_obj; - v = Choose(true, + v = Choose(true, // expected-note {{result of call to 'Choose' aliases the storage of local variable 'temp_obj'}} safe_obj, temp_obj); // expected-warning {{local variable 'temp_obj' does not live long enough}} } // expected-note {{local variable 'temp_obj' is destroyed here}} @@ -1223,7 +1236,9 @@ void conditional_operator_lifetimebound(bool cond) { MyObj* p; { MyObj a, b; - p = Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} + p = Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'a'}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b'}} : &b); // expected-warning {{local variable 'b' does not live long enough}} } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}} (void)*p; // expected-note 2 {{later used here}} @@ -1233,8 +1248,11 @@ void conditional_operator_lifetimebound_nested(bool cond) { MyObj* p; { MyObj a, b; - p = Identity(cond ? Identity(&a) // expected-warning {{local variable 'a' does not live long enough}} - : Identity(&b)); // expected-warning {{local variable 'b' does not live long enough}} + p = Identity(cond ? Identity(&a) // expected-warning {{local variable 'a' does not live long enough}} \ + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a'}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b'}} + : Identity(&b)); // expected-warning {{local variable 'b' does not live long enough}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'b'}} } // expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'a' is destroyed here}} (void)*p; // expected-note 2 {{later used here}} } @@ -1243,9 +1261,15 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) { MyObj* p; { MyObj a, b, c, d; - p = Identity(cond ? Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} + p = Identity(cond ? Identity(cond ? &a // expected-warning {{local variable 'a' does not live long enough}} \ + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'a'}} \ + // expected-note 2 {{result of call to 'Identity' aliases the storage of local variable 'b'}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c'}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd'}} : &b) // expected-warning {{local variable 'b' does not live long enough}} - : Identity(cond ? &c // expected-warning {{local variable 'c' does not live long enough}} + : Identity(cond ? &c // expected-warning {{local variable 'c' does not live long enough}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'c'}} \ + // expected-note {{result of call to 'Identity' aliases the storage of local variable 'd'}} : &d)); // expected-warning {{local variable 'd' does not live long enough}} } // expected-note {{local variable 'a' is destroyed here}} expected-note {{local variable 'd' is destroyed here}} expected-note {{local variable 'b' is destroyed here}} expected-note {{local variable 'c' is destroyed here}} (void)*p; // expected-note 4 {{later used here}} @@ -1586,7 +1610,8 @@ void range_based_for_use_after_scope() { View v; { MyObjStorage s; - for (const MyObj &o : s) { // expected-warning {{local variable 's' does not live long enough}} + for (const MyObj &o : s) { // expected-warning {{local variable 's' does not live long enough}} \ + // expected-note {{local variable '__range2' aliases the storage of local variable 's'}} v = o; } } // expected-note {{local variable 's' is destroyed here}} @@ -2772,7 +2797,7 @@ void chained_defaulted_assignment_propagation() { std::string str{"abc"}; S a = getS(str); // expected-warning {{local variable 'str' does not live long enough}} \ // expected-note {{result of call to 'getS' aliases the storage of local variable 'str'}} - c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}}\ + c = b = a; // expected-note {{local variable 'a' aliases the storage of local variable 'str'}} \ // expected-note {{expression aliases the storage of local variable 'str'}} } // expected-note {{local variable 'str' is destroyed here}} use(c); // expected-note {{later used here}} @@ -4132,3 +4157,116 @@ void test_loop_cond_bind(bool cond) { consume_loop_cond_bind(cond ? &x : &y); // no-warning } } + +//===----------------------------------------------------------------------===// +// buildOriginFlowChain +//===----------------------------------------------------------------------===// + +void used_variable_reassigned() { + View p, q, r; + { + MyObj a; + p = a; // expected-warning {{local variable 'a' does not live long enough}} + q = p; // expected-note {{local variable 'p' aliases the storage of local variable 'a'}} + r = q; // expected-note {{local variable 'q' aliases the storage of local variable 'a'}} + } // expected-note {{destroyed here}} + r.use(); // expected-note {{later used here}} + + MyObj b; + r = b; + r.use(); +} + +void multi_reassigned(bool condition) { + MyObj v1, v2, v3; + View p1, p2, p3, p4; + { + MyObj v4; + + p1 = v1; + p2 = v2; + p3 = v3; + p4 = v4; // expected-warning {{local variable 'v4' does not live long enough}} + + while (condition) { + View temp = p1; + p1 = p2; // expected-note {{local variable 'p2' aliases the storage of local variable 'v4'}} + p2 = p3; // expected-note {{local variable 'p3' aliases the storage of local variable 'v4'}} + p3 = p4; // expected-note {{local variable 'p4' aliases the storage of local variable 'v4'}} + p4 = temp; + } + } // expected-note {{destroyed here}} + + p1.use(); // expected-note {{later used here}} +} + +#define BRANCH(con) \ + if (con) {} else {} + +#define BRANCH10(con) \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con); \ + BRANCH(con) + +#define BRANCH100(con) \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con); \ + BRANCH10(con) + +void test_exponential_paths(bool c) { + View v; + { + MyObj a; + View p = a; // expected-warning{{local variable 'a' does not live long enough}} + BRANCH100(c); + v = p; // expected-note {{local variable 'p' aliases the storage of local variable 'a'}} + } // expected-note {{local variable 'a' is destroyed here}} + v.use(); // expected-note {{later used here}} +} + +void test_multiple_paths(bool cond) { + View v; + { + MyObj a; + View p1, p2, p3; + p1 = a; // expected-warning {{local variable 'a' does not live long enough}} + p2 = p1; + if (cond) { + p3 = p1; // expected-note {{local variable 'p1' aliases the storage of local variable 'a'}} + } else { + p3 = p2; + } + + v = p3; // expected-note {{local variable 'p3' aliases the storage of local variable 'a'}} + } // expected-note {{local variable 'a' is destroyed here}} + v.use(); // expected-note {{later used here}} +} + +void test_cyclic_cfg(int n) { + View v; + { + MyObj a; + View p; + p = a; // expected-warning {{local variable 'a' does not live long enough}} + while (n > 0) { + p = p; + n--; + } + v = p; // expected-note {{local variable 'p' aliases the storage of local variable 'a'}} + } // expected-note {{local variable 'a' is destroyed here}} + v.use(); // expected-note {{later used here}} +} diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index 78b7449958140..57cf7068affae 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -206,16 +206,16 @@ class LifetimeTestHelper { } llvm::SmallVector<OriginID> - buildOriginFlowChainInOneBlock(llvm::StringRef StartOriginVar, - llvm::StringRef EndLoanVar, - llvm::StringRef Annotation) { + buildOriginFlowChain(llvm::StringRef StartOriginVar, + llvm::StringRef EndLoanVar, llvm::StringRef Annotation) { std::optional<OriginID> StartOriginID = getOriginForDecl(StartOriginVar); std::vector<LoanID> EndLoanIDs = getLoansForVar(EndLoanVar); for (LoanID LID : EndLoanIDs) { llvm::SmallVector<OriginID> OriginFlowChain = Runner.getAnalysis().getLoanPropagation().buildOriginFlowChain( - getProgramPoint(Annotation), *StartOriginID, LID); + getProgramPoint(Annotation), *StartOriginID, LID, + Runner.getAnalysisContext().getCFG()); if (!OriginFlowChain.empty()) return OriginFlowChain; } @@ -1975,6 +1975,52 @@ TEST_F(LifetimeAnalysisTest, LambdaInitCaptureViewByValue) { // Tests for buildOriginFlowChain // ========================================================================= // +TEST_F(LifetimeAnalysisTest, BuildOriginFlowChain) { + SetupTest(R"( + void target(bool c1, bool c2) { + int *s; + int *a, *b, *c; + + { + int tgta, tgtb, tgtc; + a = &tgta; + b = &tgtb; + c = &tgtc; + } + + if (c1) { + s = c2 ? a : b; + } else { + s = c; + } + + POINT(after_nested_merge); + (void)*s; + int reset; + s = &reset; + } + )"); + + llvm::SmallVector<OriginID> ChainForTgtA = + Helper->buildOriginFlowChain("s", "tgta", "after_nested_merge"); + llvm::SmallVector<OriginID> ChainForTgtB = + Helper->buildOriginFlowChain("s", "tgtb", "after_nested_merge"); + llvm::SmallVector<OriginID> ChainForTgtC = + Helper->buildOriginFlowChain("s", "tgtc", "after_nested_merge"); + + EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); + EXPECT_THAT(ChainForTgtA, Not(Contains(*Helper->getOriginForDecl("b")))); + EXPECT_THAT(ChainForTgtA, Not(Contains(*Helper->getOriginForDecl("c")))); + + EXPECT_THAT(ChainForTgtB, Not(Contains(*Helper->getOriginForDecl("a")))); + EXPECT_THAT(ChainForTgtB, Contains(*Helper->getOriginForDecl("b"))); + EXPECT_THAT(ChainForTgtB, Not(Contains(*Helper->getOriginForDecl("c")))); + + EXPECT_THAT(ChainForTgtC, Not(Contains(*Helper->getOriginForDecl("a")))); + EXPECT_THAT(ChainForTgtC, Not(Contains(*Helper->getOriginForDecl("b")))); + EXPECT_THAT(ChainForTgtC, Contains(*Helper->getOriginForDecl("c"))); +} + TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithErrorTargetLoan) { SetupTest(R"( void target() { @@ -1986,7 +2032,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithErrorTargetLoan) { )"); #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST - EXPECT_DEATH(Helper->buildOriginFlowChainInOneBlock("s", "a", "after_use"), + EXPECT_DEATH(Helper->buildOriginFlowChain("s", "a", "after_use"), "TargetLoan must be present in the StartOID at the StartPoint"); #endif } @@ -2005,7 +2051,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithSelfAssignment) { )"); const llvm::SmallVector<OriginID> OriginFlowChain = - Helper->buildOriginFlowChainInOneBlock("s", "tgt", "after_use"); + Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); } @@ -2022,7 +2068,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithMultiAssignInSameStmt) { )"); const llvm::SmallVector<OriginID> OriginFlowChain = - Helper->buildOriginFlowChainInOneBlock("s", "tgt", "after_use"); + Helper->buildOriginFlowChain("s", "tgt", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2043,7 +2089,7 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithOverwritingAssignments) { )"); const llvm::SmallVector<OriginID> OriginFlowChain = - Helper->buildOriginFlowChainInOneBlock("s", "tgt1", "after_use"); + Helper->buildOriginFlowChain("s", "tgt1", "after_use"); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(OriginFlowChain, Contains(*Helper->getOriginForDecl("b"))); @@ -2065,9 +2111,9 @@ TEST_F(LifetimeAnalysisTest, BuildOriginFlowChainWithLifetimeBound) { )"); llvm::SmallVector<OriginID> ChainForTgtA = - Helper->buildOriginFlowChainInOneBlock("s", "tgta", "after_use"); + Helper->buildOriginFlowChain("s", "tgta", "after_use"); llvm::SmallVector<OriginID> ChainForTgtB = - Helper->buildOriginFlowChainInOneBlock("s", "tgtb", "after_use"); + Helper->buildOriginFlowChain("s", "tgtb", "after_use"); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("a"))); EXPECT_THAT(ChainForTgtA, Contains(*Helper->getOriginForDecl("result"))); diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index aa14d2586a534..16d6a5da54e66 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -1488,6 +1488,61 @@ static bool SinkCast(CastInst *CI) { return MadeChange; } +/// Hoists bitcasts to the source block to reduce register pressure +static bool optimizeBitCast(BitCastInst *BCI, const TargetLowering &TLI, + const DataLayout &DL) { + auto *SrcInst = dyn_cast<Instruction>(BCI->getOperand(0)); + if (!SrcInst || SrcInst->getParent() == BCI->getParent() || + SrcInst->isTerminator()) + return false; + + EVT SrcVT = TLI.getValueType(DL, SrcInst->getType()); + EVT DestVT = TLI.getValueType(DL, BCI->getType()); + + // Bail out on scalable vectors and illegal destination types + if (SrcVT.isScalableVector() || DestVT.isScalableVector() || + !TLI.isTypeLegal(DestVT)) + return false; + + // Only hoist if it reduces physical register count + if (TLI.getNumRegisters(BCI->getContext(), SrcVT) <= + TLI.getNumRegisters(BCI->getContext(), DestVT)) + return false; + + // Prevent large cross-domain scalar hoists + Type *DestTy = BCI->getType(); + Type *SrcTy = SrcInst->getType(); + bool IsCrossDomain = DestTy->isFPOrFPVectorTy() != SrcTy->isFPOrFPVectorTy(); + bool IsLargeScalar = !DestTy->isVectorTy() && + DL.getTypeSizeInBits(DestTy).getFixedValue() > 64; + if (IsCrossDomain && IsLargeScalar) + return false; + + // SelectionDAG Guard to prevent breaking atomic loop layout + auto IsAtomic = [](const Value *V) { + const auto *I = dyn_cast<Instruction>(V); + return I && I->isAtomic(); + }; + + // Check upstream atomic -> [extractvalue] -> bitcast + const Value *Origin = SrcInst; + if (auto *EV = dyn_cast<ExtractValueInst>(Origin)) + Origin = EV->getAggregateOperand(); + + // Check downstream bitcast -> [phi] -> atomic + if (IsAtomic(Origin) || any_of(BCI->users(), [IsAtomic](const User *U) { + return IsAtomic(U) || (isa<PHINode>(U) && any_of(U->users(), IsAtomic)); + })) + return false; + + // Hoist the bitcast + BasicBlock *SrcBB = SrcInst->getParent(); + auto InsertPt = isa<PHINode>(SrcInst) ? SrcBB->getFirstInsertionPt() + : std::next(SrcInst->getIterator()); + BCI->moveBefore(*SrcBB, InsertPt); + return true; +} + /// If the specified cast instruction is a noop copy (e.g. it's casting from /// one pointer type to another, i32->i8 on PPC), sink it into user blocks to /// reduce the number of virtual registers that must be created and coalesced. @@ -8938,6 +8993,15 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) { // evaluation in a block other than then one that uses it (e.g. to hoist // the address of globals out of a loop). If this is the case, we don't // want to forward-subst the cast. + + if (auto *BCI = dyn_cast<BitCastInst>(CI)) { + // Hoist bitcasts of illegal types to reduce cross-block register pressure + // and prevent register splitting. + if (optimizeBitCast(BCI, *TLI, *DL)) { + return true; + } + } + if (isa<Constant>(CI->getOperand(0))) return AnyChange; diff --git a/llvm/test/CodeGen/ARM/aes-erratum-fix.ll b/llvm/test/CodeGen/ARM/aes-erratum-fix.ll index 60658444ea6d0..4959e0bdd46a8 100644 --- a/llvm/test/CodeGen/ARM/aes-erratum-fix.ll +++ b/llvm/test/CodeGen/ARM/aes-erratum-fix.ll @@ -1353,38 +1353,22 @@ define arm_aapcs_vfpcc void @aese_setf16_via_val(half %0, <16 x i8> %1, ptr %2) define arm_aapcs_vfpcc void @aese_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 x i8> %2, ptr %3) nounwind { ; CHECK-FIX-NOSCHED-LABEL: aese_setf16_cond_via_ptr: ; CHECK-FIX-NOSCHED: @ %bb.0: -; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: .pad #12 -; CHECK-FIX-NOSCHED-NEXT: sub sp, sp, #12 +; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, lr} +; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, lr} ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: beq .LBB36_3 +; CHECK-FIX-NOSCHED-NEXT: beq .LBB36_2 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.1: ; CHECK-FIX-NOSCHED-NEXT: vld1.64 {d16, d17}, [r2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d17[3] ; CHECK-FIX-NOSCHED-NEXT: ldrh r7, [r1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d17[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d16[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[1] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d17[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d17[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d17[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[2] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d16[1] -; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: bne .LBB36_4 +; CHECK-FIX-NOSCHED-NEXT: b .LBB36_3 ; CHECK-FIX-NOSCHED-NEXT: .LBB36_2: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d1[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d1[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d0[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d0[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d0[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r1, d0[0] -; CHECK-FIX-NOSCHED-NEXT: b .LBB36_5 -; CHECK-FIX-NOSCHED-NEXT: .LBB36_3: ; CHECK-FIX-NOSCHED-NEXT: add r3, r2, #8 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[0]}, [r3:32] @@ -1392,138 +1376,125 @@ define arm_aapcs_vfpcc void @aese_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[1]}, [r3:32] ; CHECK-FIX-NOSCHED-NEXT: add r3, r2, #12 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[1]}, [r3:32] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d18[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d16[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[1] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d18[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d18[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d18[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d18[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[2] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d16[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] +; CHECK-FIX-NOSCHED-NEXT: .LBB36_3: +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r7, r3, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: beq .LBB36_2 -; CHECK-FIX-NOSCHED-NEXT: .LBB36_4: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r4, r8, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r6, r5, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, lr, r12, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r3 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d1[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d1[2] +; CHECK-FIX-NOSCHED-NEXT: beq .LBB36_5 +; CHECK-FIX-NOSCHED-NEXT: @ %bb.4: +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[1] ; CHECK-FIX-NOSCHED-NEXT: ldrh r1, [r1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d1[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d1[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d0[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d0[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d0[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d0[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d0[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d0[1] +; CHECK-FIX-NOSCHED-NEXT: b .LBB36_6 ; CHECK-FIX-NOSCHED-NEXT: .LBB36_5: -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r1, r8, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r7, r3, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d0[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d0[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d0[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r1, d0[0] +; CHECK-FIX-NOSCHED-NEXT: .LBB36_6: +; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r1, r7, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r4, r0, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, lr, r12, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r3 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r11, r10, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r6, r5, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r1 -; CHECK-FIX-NOSCHED-NEXT: ldr r1, [sp] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r9, r1, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r6, r5, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r3, r12, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[1], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp, #8] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r1 -; CHECK-FIX-NOSCHED-NEXT: ldr r1, [sp, #4] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r1, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r0 ; CHECK-FIX-NOSCHED-NEXT: aese.8 q8, q9 ; CHECK-FIX-NOSCHED-NEXT: aesmc.8 q8, q8 ; CHECK-FIX-NOSCHED-NEXT: vst1.64 {d16, d17}, [r2] -; CHECK-FIX-NOSCHED-NEXT: add sp, sp, #12 -; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, pc} ; ; CHECK-CORTEX-FIX-LABEL: aese_setf16_cond_via_ptr: ; CHECK-CORTEX-FIX: @ %bb.0: -; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: .pad #16 -; CHECK-CORTEX-FIX-NEXT: sub sp, sp, #16 +; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, lr} +; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, lr} ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB36_3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB36_2 ; CHECK-CORTEX-FIX-NEXT: @ %bb.1: ; CHECK-CORTEX-FIX-NEXT: vld1.64 {d16, d17}, [r2] -; CHECK-CORTEX-FIX-NEXT: ldrh r11, [r1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d17[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d17[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d17[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[2] -; CHECK-CORTEX-FIX-NEXT: str r7, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #12] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #8] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: ldrh r4, [r1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d17[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d17[1] -; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: bne .LBB36_4 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d17[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d17[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB36_3 ; CHECK-CORTEX-FIX-NEXT: .LBB36_2: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d0[0] -; CHECK-CORTEX-FIX-NEXT: b .LBB36_5 -; CHECK-CORTEX-FIX-NEXT: .LBB36_3: -; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-CORTEX-FIX-NEXT: add r3, r2, #8 +; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-CORTEX-FIX-NEXT: add r7, r2, #4 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[0]}, [r3:32] ; CHECK-CORTEX-FIX-NEXT: add r3, r2, #12 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[1]}, [r7:32] ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[1]}, [r3:32] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d16[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d18[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d18[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d18[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[2] -; CHECK-CORTEX-FIX-NEXT: str r7, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #12] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #8] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d16[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d18[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d18[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d18[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d18[3] +; CHECK-CORTEX-FIX-NEXT: .LBB36_3: +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r7, r3, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r4, r4, r8, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r12, lr, lsl #16 ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB36_2 -; CHECK-CORTEX-FIX-NEXT: .LBB36_4: -; CHECK-CORTEX-FIX-NEXT: ldrh r4, [r1] +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r4 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r3 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r7 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB36_5 +; CHECK-CORTEX-FIX-NEXT: @ %bb.4: +; CHECK-CORTEX-FIX-NEXT: ldrh r3, [r1] +; CHECK-CORTEX-FIX-NEXT: b .LBB36_6 ; CHECK-CORTEX-FIX-NEXT: .LBB36_5: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d0[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d0[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d0[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d1[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r1, d1[1] -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d1[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d1[3] -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r8, r3, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r11, r0, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r4, r5, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r6, r6, r12, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r1, r9, r1, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d0[0] +; CHECK-CORTEX-FIX-NEXT: .LBB36_6: +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d0[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d0[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r1, d0[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d1[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d1[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d1[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d1[3] +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r3, r0, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r7, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r1, r12, r1, lsl #16 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r0 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp, #4] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r3 -; CHECK-CORTEX-FIX-NEXT: ldr r3, [sp, #12] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r7, lr, r7, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r5 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r10, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r6 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r1 -; CHECK-CORTEX-FIX-NEXT: ldr r6, [sp, #8] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r3, r6, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r3 +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r7 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r1 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[1], r0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r7 -; CHECK-CORTEX-FIX-NEXT: aese.8 q9, q8 -; CHECK-CORTEX-FIX-NEXT: aesmc.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aese.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesmc.8 q8, q8 ; CHECK-CORTEX-FIX-NEXT: vst1.64 {d16, d17}, [r2] -; CHECK-CORTEX-FIX-NEXT: add sp, sp, #16 -; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, pc} br i1 %0, label %5, label %12 5: @@ -1569,25 +1540,20 @@ define arm_aapcs_vfpcc void @aese_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 define arm_aapcs_vfpcc void @aese_setf16_cond_via_val(i1 zeroext %0, half %1, <16 x i8> %2, ptr %3) nounwind { ; CHECK-FIX-NOSCHED-LABEL: aese_setf16_cond_via_val: ; CHECK-FIX-NOSCHED: @ %bb.0: -; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: .pad #12 -; CHECK-FIX-NOSCHED-NEXT: sub sp, sp, #12 +; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r11, lr} +; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r11, lr} ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 ; CHECK-FIX-NOSCHED-NEXT: beq .LBB37_2 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.1: ; CHECK-FIX-NOSCHED-NEXT: vld1.64 {d16, d17}, [r1] ; CHECK-FIX-NOSCHED-NEXT: vmov.f32 s2, s0 -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d17[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d17[3] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d17[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d16[1] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[0] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[3] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[1] ; CHECK-FIX-NOSCHED-NEXT: b .LBB37_3 ; CHECK-FIX-NOSCHED-NEXT: .LBB37_2: ; CHECK-FIX-NOSCHED-NEXT: add r2, r1, #8 @@ -1597,100 +1563,76 @@ define arm_aapcs_vfpcc void @aese_setf16_cond_via_val(i1 zeroext %0, half %1, <1 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[1]}, [r2:32] ; CHECK-FIX-NOSCHED-NEXT: add r2, r1, #12 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[1]}, [r2:32] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d18[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d18[3] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d18[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d16[1] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[0] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[3] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[0] -; CHECK-FIX-NOSCHED-NEXT: vmov s2, r2 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[1] +; CHECK-FIX-NOSCHED-NEXT: vmov s2, r7 ; CHECK-FIX-NOSCHED-NEXT: .LBB37_3: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d3[3] +; CHECK-FIX-NOSCHED-NEXT: vmov r7, s2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, r3, r2, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d3[1] ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d3[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d3[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d3[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: pkhbt r6, r7, r6, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r6 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, r5, r4, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, lr, r12, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r2 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d3[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d3[2] ; CHECK-FIX-NOSCHED-NEXT: beq .LBB37_5 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.4: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d2[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d3[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d2[1] ; CHECK-FIX-NOSCHED-NEXT: b .LBB37_6 ; CHECK-FIX-NOSCHED-NEXT: .LBB37_5: -; CHECK-FIX-NOSCHED-NEXT: mov r0, lr -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d2[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d2[1] -; CHECK-FIX-NOSCHED-NEXT: vmov s0, lr -; CHECK-FIX-NOSCHED-NEXT: mov lr, r0 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d2[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d3[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d2[1] +; CHECK-FIX-NOSCHED-NEXT: vmov s0, r7 ; CHECK-FIX-NOSCHED-NEXT: .LBB37_6: -; CHECK-FIX-NOSCHED-NEXT: vmov r0, s0 -; CHECK-FIX-NOSCHED-NEXT: vmov r6, s2 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r0, r12, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r6, r6, r8, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r0 +; CHECK-FIX-NOSCHED-NEXT: vmov r7, s0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r0, r3, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r7, r7, r6, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r7 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 ; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r5, r4, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r6 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r11, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r3, r2, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: ldr r2, [sp, #4] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp, #8] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r2, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r10, r9, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r2, r12, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[1], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, lr, r7, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r0 ; CHECK-FIX-NOSCHED-NEXT: aese.8 q8, q9 ; CHECK-FIX-NOSCHED-NEXT: aesmc.8 q8, q8 ; CHECK-FIX-NOSCHED-NEXT: vst1.64 {d16, d17}, [r1] -; CHECK-FIX-NOSCHED-NEXT: add sp, sp, #12 -; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r11, pc} ; ; CHECK-CORTEX-FIX-LABEL: aese_setf16_cond_via_val: ; CHECK-CORTEX-FIX: @ %bb.0: -; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: .pad #8 -; CHECK-CORTEX-FIX-NEXT: sub sp, sp, #8 +; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r11, lr} +; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r11, lr} ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB37_3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB37_2 ; CHECK-CORTEX-FIX-NEXT: @ %bb.1: ; CHECK-CORTEX-FIX-NEXT: vld1.64 {d16, d17}, [r1] ; CHECK-CORTEX-FIX-NEXT: vmov.f32 s2, s0 ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d17[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d17[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d17[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d17[3] -; CHECK-CORTEX-FIX-NEXT: str r2, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d17[2] -; CHECK-CORTEX-FIX-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: bne .LBB37_4 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d17[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d17[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB37_3 ; CHECK-CORTEX-FIX-NEXT: .LBB37_2: -; CHECK-CORTEX-FIX-NEXT: mov r0, lr -; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d2[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d2[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d3[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d3[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d3[3] -; CHECK-CORTEX-FIX-NEXT: vmov s0, lr -; CHECK-CORTEX-FIX-NEXT: mov lr, r0 -; CHECK-CORTEX-FIX-NEXT: b .LBB37_5 -; CHECK-CORTEX-FIX-NEXT: .LBB37_3: ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r1:32] ; CHECK-CORTEX-FIX-NEXT: add r2, r1, #8 ; CHECK-CORTEX-FIX-NEXT: add r3, r1, #4 @@ -1698,53 +1640,60 @@ define arm_aapcs_vfpcc void @aese_setf16_cond_via_val(i1 zeroext %0, half %1, <1 ; CHECK-CORTEX-FIX-NEXT: add r2, r1, #12 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[1]}, [r3:32] ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[1]}, [r2:32] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d18[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d18[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d18[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d18[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d18[2] -; CHECK-CORTEX-FIX-NEXT: vmov s2, r2 -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #4] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d18[3] +; CHECK-CORTEX-FIX-NEXT: vmov s2, r7 +; CHECK-CORTEX-FIX-NEXT: .LBB37_3: +; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov r6, s2 ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB37_2 -; CHECK-CORTEX-FIX-NEXT: .LBB37_4: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d2[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d3[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d3[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d3[3] +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r6, r2, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r2 +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r3, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r12, lr, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r5 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r3 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r2 +; CHECK-CORTEX-FIX-NEXT: beq .LBB37_5 +; CHECK-CORTEX-FIX-NEXT: @ %bb.4: +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d2[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d3[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d3[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d3[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB37_6 ; CHECK-CORTEX-FIX-NEXT: .LBB37_5: -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r3, r4, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov r4, s2 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r5, r12, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r6, r11, r6, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r4, r4, r0, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov r0, s0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r4 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r6 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r2, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r7, lr, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r0 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp, #4] @ 4-byte Reload +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d2[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d2[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d3[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d3[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d3[3] +; CHECK-CORTEX-FIX-NEXT: vmov s0, r7 +; CHECK-CORTEX-FIX-NEXT: .LBB37_6: +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov r6, s0 +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r12, r2, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r6, r3, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r3 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r7 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r2 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r10, lsl #16 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[1], r0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r3 -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r8, r9, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r3 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r5 -; CHECK-CORTEX-FIX-NEXT: aese.8 q9, q8 -; CHECK-CORTEX-FIX-NEXT: aesmc.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aese.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesmc.8 q8, q8 ; CHECK-CORTEX-FIX-NEXT: vst1.64 {d16, d17}, [r1] -; CHECK-CORTEX-FIX-NEXT: add sp, sp, #8 -; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r11, pc} br i1 %0, label %5, label %11 5: @@ -3501,38 +3450,22 @@ define arm_aapcs_vfpcc void @aesd_setf16_via_val(half %0, <16 x i8> %1, ptr %2) define arm_aapcs_vfpcc void @aesd_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 x i8> %2, ptr %3) nounwind { ; CHECK-FIX-NOSCHED-LABEL: aesd_setf16_cond_via_ptr: ; CHECK-FIX-NOSCHED: @ %bb.0: -; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: .pad #12 -; CHECK-FIX-NOSCHED-NEXT: sub sp, sp, #12 +; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, lr} +; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, lr} ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: beq .LBB82_3 +; CHECK-FIX-NOSCHED-NEXT: beq .LBB82_2 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.1: ; CHECK-FIX-NOSCHED-NEXT: vld1.64 {d16, d17}, [r2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d17[3] ; CHECK-FIX-NOSCHED-NEXT: ldrh r7, [r1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d17[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d16[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[1] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d17[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d17[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d17[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[2] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d16[1] -; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: bne .LBB82_4 +; CHECK-FIX-NOSCHED-NEXT: b .LBB82_3 ; CHECK-FIX-NOSCHED-NEXT: .LBB82_2: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d1[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d1[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d0[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d0[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d0[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r1, d0[0] -; CHECK-FIX-NOSCHED-NEXT: b .LBB82_5 -; CHECK-FIX-NOSCHED-NEXT: .LBB82_3: ; CHECK-FIX-NOSCHED-NEXT: add r3, r2, #8 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[0]}, [r3:32] @@ -3540,138 +3473,125 @@ define arm_aapcs_vfpcc void @aesd_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[1]}, [r3:32] ; CHECK-FIX-NOSCHED-NEXT: add r3, r2, #12 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[1]}, [r3:32] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d18[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d16[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[2] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[1] -; CHECK-FIX-NOSCHED-NEXT: str r3, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d18[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d18[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d18[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d18[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[2] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d16[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] +; CHECK-FIX-NOSCHED-NEXT: .LBB82_3: +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r7, r3, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: beq .LBB82_2 -; CHECK-FIX-NOSCHED-NEXT: .LBB82_4: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r4, r8, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r6, r5, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r3 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, lr, r12, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r3 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d1[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d1[2] +; CHECK-FIX-NOSCHED-NEXT: beq .LBB82_5 +; CHECK-FIX-NOSCHED-NEXT: @ %bb.4: +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[1] ; CHECK-FIX-NOSCHED-NEXT: ldrh r1, [r1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d1[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d1[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d0[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d0[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d0[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d0[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d0[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d0[1] +; CHECK-FIX-NOSCHED-NEXT: b .LBB82_6 ; CHECK-FIX-NOSCHED-NEXT: .LBB82_5: -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r1, r8, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r3, r7, r3, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d1[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d1[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d0[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d0[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d0[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r1, d0[0] +; CHECK-FIX-NOSCHED-NEXT: .LBB82_6: +; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r1, r7, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r4, r0, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, lr, r12, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r3 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r11, r10, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r1 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r6, r5, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r1 -; CHECK-FIX-NOSCHED-NEXT: ldr r1, [sp] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r1, r9, r1, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r6, r5, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r3, r12, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[1], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp, #8] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r1 -; CHECK-FIX-NOSCHED-NEXT: ldr r1, [sp, #4] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r1, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r0 ; CHECK-FIX-NOSCHED-NEXT: aesd.8 q8, q9 ; CHECK-FIX-NOSCHED-NEXT: aesimc.8 q8, q8 ; CHECK-FIX-NOSCHED-NEXT: vst1.64 {d16, d17}, [r2] -; CHECK-FIX-NOSCHED-NEXT: add sp, sp, #12 -; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, pc} ; ; CHECK-CORTEX-FIX-LABEL: aesd_setf16_cond_via_ptr: ; CHECK-CORTEX-FIX: @ %bb.0: -; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: .pad #16 -; CHECK-CORTEX-FIX-NEXT: sub sp, sp, #16 +; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, lr} +; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, lr} ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB82_3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB82_2 ; CHECK-CORTEX-FIX-NEXT: @ %bb.1: ; CHECK-CORTEX-FIX-NEXT: vld1.64 {d16, d17}, [r2] -; CHECK-CORTEX-FIX-NEXT: ldrh r11, [r1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d17[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d17[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d17[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[2] -; CHECK-CORTEX-FIX-NEXT: str r7, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #12] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #8] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: ldrh r4, [r1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d17[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d17[1] -; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: bne .LBB82_4 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d17[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d17[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB82_3 ; CHECK-CORTEX-FIX-NEXT: .LBB82_2: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d0[0] -; CHECK-CORTEX-FIX-NEXT: b .LBB82_5 -; CHECK-CORTEX-FIX-NEXT: .LBB82_3: -; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-CORTEX-FIX-NEXT: add r3, r2, #8 +; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r2:32] ; CHECK-CORTEX-FIX-NEXT: add r7, r2, #4 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[0]}, [r3:32] ; CHECK-CORTEX-FIX-NEXT: add r3, r2, #12 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[1]}, [r7:32] ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[1]}, [r3:32] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d16[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d18[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d18[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d18[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[2] -; CHECK-CORTEX-FIX-NEXT: str r7, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #12] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #8] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d16[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d18[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d18[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d18[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d18[3] +; CHECK-CORTEX-FIX-NEXT: .LBB82_3: +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r7, r3, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r4, r4, r8, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r12, lr, lsl #16 ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB82_2 -; CHECK-CORTEX-FIX-NEXT: .LBB82_4: -; CHECK-CORTEX-FIX-NEXT: ldrh r4, [r1] +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r4 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r3 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r7 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB82_5 +; CHECK-CORTEX-FIX-NEXT: @ %bb.4: +; CHECK-CORTEX-FIX-NEXT: ldrh r3, [r1] +; CHECK-CORTEX-FIX-NEXT: b .LBB82_6 ; CHECK-CORTEX-FIX-NEXT: .LBB82_5: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d0[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d0[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d0[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d1[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r1, d1[1] -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d1[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d1[3] -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r8, r3, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r11, r0, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r4, r5, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r6, r6, r12, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r1, r9, r1, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d0[0] +; CHECK-CORTEX-FIX-NEXT: .LBB82_6: +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d0[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d0[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r1, d0[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d1[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d1[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d1[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d1[3] +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r3, r0, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r7, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r1, r12, r1, lsl #16 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r0 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp, #4] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r3 -; CHECK-CORTEX-FIX-NEXT: ldr r3, [sp, #12] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r7, lr, r7, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r5 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r10, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r6 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r1 -; CHECK-CORTEX-FIX-NEXT: ldr r6, [sp, #8] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r3, r6, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r3 +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r7 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r1 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[1], r0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r7 -; CHECK-CORTEX-FIX-NEXT: aesd.8 q9, q8 -; CHECK-CORTEX-FIX-NEXT: aesimc.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesd.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesimc.8 q8, q8 ; CHECK-CORTEX-FIX-NEXT: vst1.64 {d16, d17}, [r2] -; CHECK-CORTEX-FIX-NEXT: add sp, sp, #16 -; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, pc} br i1 %0, label %5, label %12 5: @@ -3717,25 +3637,20 @@ define arm_aapcs_vfpcc void @aesd_setf16_cond_via_ptr(i1 zeroext %0, ptr %1, <16 define arm_aapcs_vfpcc void @aesd_setf16_cond_via_val(i1 zeroext %0, half %1, <16 x i8> %2, ptr %3) nounwind { ; CHECK-FIX-NOSCHED-LABEL: aesd_setf16_cond_via_val: ; CHECK-FIX-NOSCHED: @ %bb.0: -; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-FIX-NOSCHED-NEXT: .pad #12 -; CHECK-FIX-NOSCHED-NEXT: sub sp, sp, #12 +; CHECK-FIX-NOSCHED-NEXT: .save {r4, r5, r6, r7, r11, lr} +; CHECK-FIX-NOSCHED-NEXT: push {r4, r5, r6, r7, r11, lr} ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 ; CHECK-FIX-NOSCHED-NEXT: beq .LBB83_2 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.1: ; CHECK-FIX-NOSCHED-NEXT: vld1.64 {d16, d17}, [r1] ; CHECK-FIX-NOSCHED-NEXT: vmov.f32 s2, s0 -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d17[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d17[3] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d17[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d16[1] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[0] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[3] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp] @ 4-byte Spill +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d17[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d17[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[1] ; CHECK-FIX-NOSCHED-NEXT: b .LBB83_3 ; CHECK-FIX-NOSCHED-NEXT: .LBB83_2: ; CHECK-FIX-NOSCHED-NEXT: add r2, r1, #8 @@ -3745,100 +3660,76 @@ define arm_aapcs_vfpcc void @aesd_setf16_cond_via_val(i1 zeroext %0, half %1, <1 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d16[1]}, [r2:32] ; CHECK-FIX-NOSCHED-NEXT: add r2, r1, #12 ; CHECK-FIX-NOSCHED-NEXT: vld1.32 {d18[1]}, [r2:32] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d18[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d16[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d18[3] ; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d18[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r11, d16[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r8, d16[1] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #8] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[0] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[3] -; CHECK-FIX-NOSCHED-NEXT: str r2, [sp] @ 4-byte Spill -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d16[0] -; CHECK-FIX-NOSCHED-NEXT: vmov s2, r2 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d18[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d18[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d16[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d16[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d16[1] +; CHECK-FIX-NOSCHED-NEXT: vmov s2, r7 ; CHECK-FIX-NOSCHED-NEXT: .LBB83_3: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r9, d3[3] +; CHECK-FIX-NOSCHED-NEXT: vmov r7, s2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, r3, r2, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d3[1] ; CHECK-FIX-NOSCHED-NEXT: cmp r0, #0 -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r10, d3[2] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d3[1] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r3, d3[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: pkhbt r6, r7, r6, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r6 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, r5, r4, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r2 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r2, lr, r12, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r2 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d3[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r2, d3[2] ; CHECK-FIX-NOSCHED-NEXT: beq .LBB83_5 ; CHECK-FIX-NOSCHED-NEXT: @ %bb.4: -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d2[1] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d3[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d2[1] ; CHECK-FIX-NOSCHED-NEXT: b .LBB83_6 ; CHECK-FIX-NOSCHED-NEXT: .LBB83_5: -; CHECK-FIX-NOSCHED-NEXT: mov r0, lr -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 lr, d2[0] -; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r12, d2[1] -; CHECK-FIX-NOSCHED-NEXT: vmov s0, lr -; CHECK-FIX-NOSCHED-NEXT: mov lr, r0 +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r7, d2[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r0, d3[0] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r4, d2[3] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r5, d2[2] +; CHECK-FIX-NOSCHED-NEXT: vmov.u16 r6, d2[1] +; CHECK-FIX-NOSCHED-NEXT: vmov s0, r7 ; CHECK-FIX-NOSCHED-NEXT: .LBB83_6: -; CHECK-FIX-NOSCHED-NEXT: vmov r0, s0 -; CHECK-FIX-NOSCHED-NEXT: vmov r6, s2 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r0, r12, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r6, r6, r8, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r0 +; CHECK-FIX-NOSCHED-NEXT: vmov r7, s0 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r0, r3, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r7, r7, r6, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[0], r7 +; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 ; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r5, r4, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[0], r6 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d18[1], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r11, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d16[1], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r3, r2, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: ldr r2, [sp, #4] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[0], r0 -; CHECK-FIX-NOSCHED-NEXT: ldr r0, [sp, #8] @ 4-byte Reload -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r2, r0, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[0], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r10, r9, lsl #16 +; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, r2, r12, lsl #16 ; CHECK-FIX-NOSCHED-NEXT: vmov.32 d19[1], r0 -; CHECK-FIX-NOSCHED-NEXT: pkhbt r0, lr, r7, lsl #16 -; CHECK-FIX-NOSCHED-NEXT: vmov.32 d17[1], r0 ; CHECK-FIX-NOSCHED-NEXT: aesd.8 q8, q9 ; CHECK-FIX-NOSCHED-NEXT: aesimc.8 q8, q8 ; CHECK-FIX-NOSCHED-NEXT: vst1.64 {d16, d17}, [r1] -; CHECK-FIX-NOSCHED-NEXT: add sp, sp, #12 -; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-FIX-NOSCHED-NEXT: pop {r4, r5, r6, r7, r11, pc} ; ; CHECK-CORTEX-FIX-LABEL: aesd_setf16_cond_via_val: ; CHECK-CORTEX-FIX: @ %bb.0: -; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -; CHECK-CORTEX-FIX-NEXT: .pad #8 -; CHECK-CORTEX-FIX-NEXT: sub sp, sp, #8 +; CHECK-CORTEX-FIX-NEXT: .save {r4, r5, r6, r7, r11, lr} +; CHECK-CORTEX-FIX-NEXT: push {r4, r5, r6, r7, r11, lr} ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB83_3 +; CHECK-CORTEX-FIX-NEXT: beq .LBB83_2 ; CHECK-CORTEX-FIX-NEXT: @ %bb.1: ; CHECK-CORTEX-FIX-NEXT: vld1.64 {d16, d17}, [r1] ; CHECK-CORTEX-FIX-NEXT: vmov.f32 s2, s0 ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d17[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d17[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d17[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d17[3] -; CHECK-CORTEX-FIX-NEXT: str r2, [sp] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d17[2] -; CHECK-CORTEX-FIX-NEXT: str r2, [sp, #4] @ 4-byte Spill -; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: bne .LBB83_4 +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d17[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d17[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB83_3 ; CHECK-CORTEX-FIX-NEXT: .LBB83_2: -; CHECK-CORTEX-FIX-NEXT: mov r0, lr -; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d2[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d2[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d3[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d3[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d3[3] -; CHECK-CORTEX-FIX-NEXT: vmov s0, lr -; CHECK-CORTEX-FIX-NEXT: mov lr, r0 -; CHECK-CORTEX-FIX-NEXT: b .LBB83_5 -; CHECK-CORTEX-FIX-NEXT: .LBB83_3: ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[0]}, [r1:32] ; CHECK-CORTEX-FIX-NEXT: add r2, r1, #8 ; CHECK-CORTEX-FIX-NEXT: add r3, r1, #4 @@ -3846,53 +3737,60 @@ define arm_aapcs_vfpcc void @aesd_setf16_cond_via_val(i1 zeroext %0, half %1, <1 ; CHECK-CORTEX-FIX-NEXT: add r2, r1, #12 ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d16[1]}, [r3:32] ; CHECK-CORTEX-FIX-NEXT: vld1.32 {d18[1]}, [r2:32] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d16[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d16[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d16[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d16[2] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 lr, d16[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r11, d18[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d18[0] ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d18[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r10, d18[3] -; CHECK-CORTEX-FIX-NEXT: str r3, [sp] @ 4-byte Spill ; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d18[2] -; CHECK-CORTEX-FIX-NEXT: vmov s2, r2 -; CHECK-CORTEX-FIX-NEXT: str r3, [sp, #4] @ 4-byte Spill +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d18[3] +; CHECK-CORTEX-FIX-NEXT: vmov s2, r7 +; CHECK-CORTEX-FIX-NEXT: .LBB83_3: +; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov r6, s2 ; CHECK-CORTEX-FIX-NEXT: cmp r0, #0 -; CHECK-CORTEX-FIX-NEXT: beq .LBB83_2 -; CHECK-CORTEX-FIX-NEXT: .LBB83_4: -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d2[3] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r8, d3[0] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r9, d3[1] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[2] -; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d3[3] +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r6, r2, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r2 +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r3, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r12, lr, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r5 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r3 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r2 +; CHECK-CORTEX-FIX-NEXT: beq .LBB83_5 +; CHECK-CORTEX-FIX-NEXT: @ %bb.4: +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d2[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d3[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d3[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d3[3] +; CHECK-CORTEX-FIX-NEXT: b .LBB83_6 ; CHECK-CORTEX-FIX-NEXT: .LBB83_5: -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r3, r4, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov r4, s2 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp] @ 4-byte Reload -; CHECK-CORTEX-FIX-NEXT: pkhbt r5, r5, r12, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r6, r11, r6, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r4, r4, r0, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov r0, s0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r4 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r6 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r2, lsl #16 -; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r7, lr, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[0], r0 -; CHECK-CORTEX-FIX-NEXT: ldr r0, [sp, #4] @ 4-byte Reload +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r7, d2[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r3, d2[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r12, d2[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r2, d2[3] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r5, d3[0] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r6, d3[1] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r0, d3[2] +; CHECK-CORTEX-FIX-NEXT: vmov.u16 r4, d3[3] +; CHECK-CORTEX-FIX-NEXT: vmov s0, r7 +; CHECK-CORTEX-FIX-NEXT: .LBB83_6: +; CHECK-CORTEX-FIX-NEXT: pkhbt r7, r5, r6, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov r6, s0 +; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r4, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r2, r12, r2, lsl #16 +; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r6, r3, lsl #16 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[0], r3 +; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[0], r7 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d18[1], r2 -; CHECK-CORTEX-FIX-NEXT: pkhbt r0, r0, r10, lsl #16 ; CHECK-CORTEX-FIX-NEXT: vmov.32 d19[1], r0 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d16[1], r3 -; CHECK-CORTEX-FIX-NEXT: pkhbt r3, r8, r9, lsl #16 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[0], r3 -; CHECK-CORTEX-FIX-NEXT: vmov.32 d17[1], r5 -; CHECK-CORTEX-FIX-NEXT: aesd.8 q9, q8 -; CHECK-CORTEX-FIX-NEXT: aesimc.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesd.8 q8, q9 +; CHECK-CORTEX-FIX-NEXT: aesimc.8 q8, q8 ; CHECK-CORTEX-FIX-NEXT: vst1.64 {d16, d17}, [r1] -; CHECK-CORTEX-FIX-NEXT: add sp, sp, #8 -; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} +; CHECK-CORTEX-FIX-NEXT: pop {r4, r5, r6, r7, r11, pc} br i1 %0, label %5, label %11 5: diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-i686.ll b/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-i686.ll new file mode 100644 index 0000000000000..daf3e571174e4 --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-i686.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes='require<profile-summary>,codegenprepare' -mtriple=i686-unknown-linux-gnu -mattr=+sse2 < %s | FileCheck %s + +define double @test_hoist_bitcast_i64_to_double(i1 %cond, i64 %a) { +; CHECK-LABEL: @test_hoist_bitcast_i64_to_double( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add i64 [[A:%.*]], 1 +; CHECK-NEXT: [[BC_HOISTED:%.*]] = bitcast i64 [[ADD]] to double +; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[EXIT:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RES:%.*]] = phi double [ [[BC_HOISTED]], [[IF_THEN]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RES]] +; +entry: + %add = add i64 %a, 1 + br i1 %cond, label %if.then, label %exit + +if.then: + %bc = bitcast i64 %add to double + br label %exit + +exit: + %res = phi double [ %bc, %if.then ], [ 0.0, %entry ] + ret double %res +} diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-integer-to-vector.ll b/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-integer-to-vector.ll new file mode 100644 index 0000000000000..f475b3c551b51 --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/X86/hoist-bitcast-integer-to-vector.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -codegenprepare -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 -S < %s | FileCheck %s + +define i8 @hoist_bitcast_i256_to_v32i8(ptr %a0) { +; CHECK-LABEL: @hoist_bitcast_i256_to_v32i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SRC256:%.*]] = load i256, ptr [[A0:%.*]], align 1 +; CHECK-NEXT: [[SRC256_BITCAST:%.*]] = bitcast i256 [[SRC256]] to <32 x i8> +; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i256 [[SRC256]], 0 +; CHECK-NEXT: br i1 [[ISZERO]], label [[EXIT:%.*]], label [[REDUCTION:%.*]] +; CHECK: reduction: +; CHECK-NEXT: [[RED:%.*]] = call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> [[SRC256_BITCAST]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[RED]], [[REDUCTION]] ] +; CHECK-NEXT: ret i8 [[RESULT]] +; +entry: + %src256 = load i256, ptr %a0, align 1 + %iszero = icmp eq i256 %src256, 0 + br i1 %iszero, label %exit, label %reduction + +reduction: + %src256.bitcast = bitcast i256 %src256 to <32 x i8> + %red = call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> %src256.bitcast) + br label %exit + +exit: + %result = phi i8 [ 0, %entry ], [ %red, %reduction ] + ret i8 %result +} + +define i8 @test_legal_i64(ptr %a0) { +; CHECK-LABEL: @test_legal_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SRC64:%.*]] = load i64, ptr [[A0:%.*]], align 8 +; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i64 [[SRC64]], 0 +; CHECK-NEXT: br i1 [[ISZERO]], label [[EXIT:%.*]], label [[REDUCTION:%.*]] +; CHECK: reduction: +; CHECK-NEXT: [[SRC64_BITCAST:%.*]] = bitcast i64 [[SRC64]] to <8 x i8> +; CHECK-NEXT: [[RED:%.*]] = call i8 @llvm.vector.reduce.umax.v8i8(<8 x i8> [[SRC64_BITCAST]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[RESULT:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[RED]], [[REDUCTION]] ] +; CHECK-NEXT: ret i8 [[RESULT]] +; +entry: + %src64 = load i64, ptr %a0, align 8 + %iszero = icmp eq i64 %src64, 0 + br i1 %iszero, label %exit, label %reduction + +reduction: + %src64.bitcast = bitcast i64 %src64 to <8 x i8> + %red = call i8 @llvm.vector.reduce.umax.v8i8(<8 x i8> %src64.bitcast) + br label %exit + +exit: + %result = phi i8 [ 0, %entry ], [ %red, %reduction ] + ret i8 %result +} + +declare i8 @llvm.vector.reduce.umax.v8i8(<8 x i8>) +declare i8 @llvm.vector.reduce.umax.v32i8(<32 x i8>) From 3676189440942350a30ae0c18eac7d9a0ad58ea8 Mon Sep 17 00:00:00 2001 From: william <[email protected]> Date: Sun, 5 Jul 2026 23:55:30 +0800 Subject: [PATCH 2/2] style and test: fix clang-format and update ARM test checks --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 16d6a5da54e66..e4017456e2dfe 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -8993,7 +8993,6 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) { // evaluation in a block other than then one that uses it (e.g. to hoist // the address of globals out of a loop). If this is the case, we don't // want to forward-subst the cast. - if (auto *BCI = dyn_cast<BitCastInst>(CI)) { // Hoist bitcasts of illegal types to reduce cross-block register pressure // and prevent register splitting. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
