summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwanglei <wanglei@loongson.cn>2024-05-16 15:35:28 +0800
committerwanglei <wanglei@loongson.cn>2024-05-16 15:35:28 +0800
commit4f8f5005ed7ea01b4b18da74b9d64e75d91bf7be (patch)
tree6b4ec92652f995a0d9514580e67366d4c7cb5e42
parent36cb2c4fd7dd4faf60559f0b895800e81a47f4de (diff)
parentd187005cad8c2cb7d44ba3dd6b01c5f0e4c14ae7 (diff)
Created using spr 1.3.5-bogner [skip ci]
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp10
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.h1
-rw-r--r--clang/lib/AST/Interp/Interp.cpp14
-rw-r--r--clang/lib/AST/Interp/Pointer.cpp2
-rw-r--r--clang/lib/AST/Interp/Program.cpp3
-rw-r--r--clang/lib/CodeGen/Targets/AArch64.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp131
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h9
-rw-r--r--clang/test/AST/Interp/bitfields.cpp21
-rw-r--r--clang/test/AST/Interp/c.c5
-rw-r--r--clang/test/AST/Interp/cxx98.cpp5
-rw-r--r--clang/test/Analysis/memory-model.cpp18
-rw-r--r--clang/test/CodeGen/ext-int-cc.c8
-rw-r--r--flang/lib/Optimizer/Analysis/AliasAnalysis.cpp6
-rw-r--r--flang/lib/Optimizer/Transforms/AddAliasTags.cpp1
-rw-r--r--flang/test/Transforms/tbaa.fir37
-rw-r--r--lldb/source/Target/UnwindLLDB.cpp7
-rw-r--r--lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c21
-rw-r--r--lldb/test/Shell/Unwind/unaligned-pc-sigbus.test31
-rw-r--r--llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp71
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp35
-rw-r--r--llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll8
-rw-r--r--llvm/test/Transforms/LoopVectorize/uniform-blend.ll20
-rw-r--r--llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll105
25 files changed, 370 insertions, 203 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 7b10482dff23..1da74ac7c8bd 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2488,6 +2488,16 @@ bool ByteCodeExprGen<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
return this->emitError(E);
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
+ assert(E->getType()->isVoidPointerType());
+
+ unsigned Offset = allocateLocalPrimitive(
+ E->getLabel(), PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
+
+ return this->emitGetLocal(PT_Ptr, Offset, E);
+}
+
template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
/*NewInitializing=*/false);
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 9f83d173bbae..6039a54d32a5 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -122,6 +122,7 @@ public:
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
bool VisitPackIndexingExpr(const PackIndexingExpr *E);
bool VisitRecoveryExpr(const RecoveryExpr *E);
+ bool VisitAddrLabelExpr(const AddrLabelExpr *E);
protected:
bool visitExpr(const Expr *E) override;
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 2607e0743251..3e4da487e43c 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -302,7 +302,9 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
QualType T = VD->getType();
if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
- return T->isSignedIntegerOrEnumerationType() || T->isUnsignedIntegerOrEnumerationType();
+ return (T->isSignedIntegerOrEnumerationType() ||
+ T->isUnsignedIntegerOrEnumerationType()) &&
+ T.isConstQualified();
if (T.isConstQualified())
return true;
@@ -316,12 +318,10 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
return false;
};
- if (const auto *D = Desc->asValueDecl()) {
- if (const auto *VD = dyn_cast<VarDecl>(D);
- VD && VD->hasGlobalStorage() && !IsConstType(VD)) {
- diagnoseNonConstVariable(S, OpPC, VD);
- return S.inConstantContext();
- }
+ if (const auto *D = Desc->asVarDecl();
+ D && D->hasGlobalStorage() && !IsConstType(D)) {
+ diagnoseNonConstVariable(S, OpPC, D);
+ return S.inConstantContext();
}
return true;
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index d2e34f2c7f09..ee8cedccb8d4 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -191,7 +191,7 @@ void Pointer::print(llvm::raw_ostream &OS) const {
else
OS << Offset << ", ";
- if (isBlockPointer() && PointeeStorage.BS.Pointee)
+ if (PointeeStorage.BS.Pointee)
OS << PointeeStorage.BS.Pointee->getSize();
else
OS << "nullptr";
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 31a64e13d2b1..e3d48d5a8ddb 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -152,8 +152,7 @@ std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {
if (std::optional<PrimType> T = Ctx.classify(QT))
Desc = createDescriptor(VD, *T, std::nullopt, true, false);
else
- Desc = createDescriptor(VD, VD->getType().getTypePtr(), std::nullopt, true,
- false);
+ Desc = createDescriptor(VD, QT.getTypePtr(), std::nullopt, true, false);
if (!Desc)
Desc = allocateDescriptor(VD);
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index e32b060ebeb9..0a4711fb2170 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -317,7 +317,7 @@ AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic,
if (const auto *EIT = Ty->getAs<BitIntType>())
if (EIT->getNumBits() > 128)
- return getNaturalAlignIndirect(Ty);
+ return getNaturalAlignIndirect(Ty, false);
return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
? ABIArgInfo::getExtend(Ty)
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp
index 18e718e08553..72fd6781a756 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp
@@ -205,7 +205,7 @@ void ErrnoChecker::checkPreCall(const CallEvent &Call,
// Probably 'strerror'?
if (CallF->isExternC() && CallF->isGlobal() &&
C.getSourceManager().isInSystemHeader(CallF->getLocation()) &&
- !isErrno(CallF)) {
+ !isErrnoLocationCall(Call)) {
if (getErrnoState(C.getState()) == MustBeChecked) {
std::optional<ento::Loc> ErrnoLoc = getErrnoLoc(C.getState());
assert(ErrnoLoc && "ErrnoLoc should exist if an errno state is set.");
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
index 1b34ea0e056e..6ffc05f06742 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -39,10 +39,15 @@ namespace {
// Name of the "errno" variable.
// FIXME: Is there a system where it is not called "errno" but is a variable?
const char *ErrnoVarName = "errno";
+
// Names of functions that return a location of the "errno" value.
// FIXME: Are there other similar function names?
-const char *ErrnoLocationFuncNames[] = {"__errno_location", "___errno",
- "__errno", "_errno", "__error"};
+CallDescriptionSet ErrnoLocationCalls{
+ {CDM::CLibrary, {"__errno_location"}, 0, 0},
+ {CDM::CLibrary, {"___errno"}, 0, 0},
+ {CDM::CLibrary, {"__errno"}, 0, 0},
+ {CDM::CLibrary, {"_errno"}, 0, 0},
+ {CDM::CLibrary, {"__error"}, 0, 0}};
class ErrnoModeling
: public Checker<check::ASTDecl<TranslationUnitDecl>, check::BeginFunction,
@@ -54,16 +59,10 @@ public:
void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
- // The declaration of an "errno" variable or "errno location" function.
- mutable const Decl *ErrnoDecl = nullptr;
-
private:
- // FIXME: Names from `ErrnoLocationFuncNames` are used to build this set.
- CallDescriptionSet ErrnoLocationCalls{{{"__errno_location"}, 0, 0},
- {{"___errno"}, 0, 0},
- {{"__errno"}, 0, 0},
- {{"_errno"}, 0, 0},
- {{"__error"}, 0, 0}};
+ // The declaration of an "errno" variable on systems where errno is
+ // represented by a variable (and not a function that queries its location).
+ mutable const VarDecl *ErrnoDecl = nullptr;
};
} // namespace
@@ -74,9 +73,13 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoRegion, const MemRegion *)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ErrnoState, errno_modeling::ErrnoCheckState)
-/// Search for a variable called "errno" in the AST.
-/// Return nullptr if not found.
-static const VarDecl *getErrnoVar(ASTContext &ACtx) {
+void ErrnoModeling::checkASTDecl(const TranslationUnitDecl *D,
+ AnalysisManager &Mgr, BugReporter &BR) const {
+ // Try to find the declaration of the external variable `int errno;`.
+ // There are also C library implementations, where the `errno` location is
+ // accessed via a function that returns its address; in those environments
+ // this callback has no effect.
+ ASTContext &ACtx = Mgr.getASTContext();
IdentifierInfo &II = ACtx.Idents.get(ErrnoVarName);
auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) {
@@ -86,47 +89,8 @@ static const VarDecl *getErrnoVar(ASTContext &ACtx) {
VD->getType().getCanonicalType() == ACtx.IntTy;
return false;
});
- if (Found == LookupRes.end())
- return nullptr;
-
- return cast<VarDecl>(*Found);
-}
-
-/// Search for a function with a specific name that is used to return a pointer
-/// to "errno".
-/// Return nullptr if no such function was found.
-static const FunctionDecl *getErrnoFunc(ASTContext &ACtx) {
- SmallVector<const Decl *> LookupRes;
- for (StringRef ErrnoName : ErrnoLocationFuncNames) {
- IdentifierInfo &II = ACtx.Idents.get(ErrnoName);
- llvm::append_range(LookupRes, ACtx.getTranslationUnitDecl()->lookup(&II));
- }
-
- auto Found = llvm::find_if(LookupRes, [&ACtx](const Decl *D) {
- if (auto *FD = dyn_cast<FunctionDecl>(D))
- return ACtx.getSourceManager().isInSystemHeader(FD->getLocation()) &&
- FD->isExternC() && FD->getNumParams() == 0 &&
- FD->getReturnType().getCanonicalType() ==
- ACtx.getPointerType(ACtx.IntTy);
- return false;
- });
- if (Found == LookupRes.end())
- return nullptr;
-
- return cast<FunctionDecl>(*Found);
-}
-
-void ErrnoModeling::checkASTDecl(const TranslationUnitDecl *D,
- AnalysisManager &Mgr, BugReporter &BR) const {
- // Try to find an usable `errno` value.
- // It can be an external variable called "errno" or a function that returns a
- // pointer to the "errno" value. This function can have different names.
- // The actual case is dependent on the C library implementation, we
- // can only search for a match in one of these variations.
- // We assume that exactly one of these cases might be true.
- ErrnoDecl = getErrnoVar(Mgr.getASTContext());
- if (!ErrnoDecl)
- ErrnoDecl = getErrnoFunc(Mgr.getASTContext());
+ if (Found != LookupRes.end())
+ ErrnoDecl = cast<VarDecl>(*Found);
}
void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
@@ -136,25 +100,18 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
ASTContext &ACtx = C.getASTContext();
ProgramStateRef State = C.getState();
- if (const auto *ErrnoVar = dyn_cast_or_null<VarDecl>(ErrnoDecl)) {
- // There is an external 'errno' variable.
- // Use its memory region.
- // The memory region for an 'errno'-like variable is allocated in system
- // space by MemRegionManager.
- const MemRegion *ErrnoR =
- State->getRegion(ErrnoVar, C.getLocationContext());
+ const MemRegion *ErrnoR = nullptr;
+
+ if (ErrnoDecl) {
+ // There is an external 'errno' variable, so we can simply use the memory
+ // region that's associated with it.
+ ErrnoR = State->getRegion(ErrnoDecl, C.getLocationContext());
assert(ErrnoR && "Memory region should exist for the 'errno' variable.");
- State = State->set<ErrnoRegion>(ErrnoR);
- State =
- errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant);
- C.addTransition(State);
- } else if (ErrnoDecl) {
- assert(isa<FunctionDecl>(ErrnoDecl) && "Invalid errno location function.");
- // There is a function that returns the location of 'errno'.
- // We must create a memory region for it in system space.
- // Currently a symbolic region is used with an artifical symbol.
- // FIXME: It is better to have a custom (new) kind of MemRegion for such
- // cases.
+ } else {
+ // There is no 'errno' variable, so create a new symbolic memory region
+ // that can be used to model the return value of the "get the location of
+ // errno" internal functions.
+ // NOTE: this `SVal` is created even if errno is not defined or used.
SValBuilder &SVB = C.getSValBuilder();
MemRegionManager &RMgr = C.getStateManager().getRegionManager();
@@ -162,27 +119,31 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
RMgr.getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
// Create an artifical symbol for the region.
- // It is not possible to associate a statement or expression in this case.
+ // Note that it is not possible to associate a statement or expression in
+ // this case and the `symbolTag` (opaque pointer tag) is just the address
+ // of the data member `ErrnoDecl` of the singleton `ErrnoModeling` checker
+ // object.
const SymbolConjured *Sym = SVB.conjureSymbol(
nullptr, C.getLocationContext(),
ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl);
// The symbolic region is untyped, create a typed sub-region in it.
// The ElementRegion is used to make the errno region a typed region.
- const MemRegion *ErrnoR = RMgr.getElementRegion(
+ ErrnoR = RMgr.getElementRegion(
ACtx.IntTy, SVB.makeZeroArrayIndex(),
RMgr.getSymbolicRegion(Sym, GlobalSystemSpace), C.getASTContext());
- State = State->set<ErrnoRegion>(ErrnoR);
- State =
- errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant);
- C.addTransition(State);
}
+ assert(ErrnoR);
+ State = State->set<ErrnoRegion>(ErrnoR);
+ State =
+ errno_modeling::setErrnoValue(State, C, 0, errno_modeling::Irrelevant);
+ C.addTransition(State);
}
bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const {
// Return location of "errno" at a call to an "errno address returning"
// function.
- if (ErrnoLocationCalls.contains(Call)) {
+ if (errno_modeling::isErrnoLocationCall(Call)) {
ProgramStateRef State = C.getState();
const MemRegion *ErrnoR = State->get<ErrnoRegion>();
@@ -260,14 +221,8 @@ ProgramStateRef clearErrnoState(ProgramStateRef State) {
return setErrnoState(State, Irrelevant);
}
-bool isErrno(const Decl *D) {
- if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
- if (const IdentifierInfo *II = VD->getIdentifier())
- return II->getName() == ErrnoVarName;
- if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
- if (const IdentifierInfo *II = FD->getIdentifier())
- return llvm::is_contained(ErrnoLocationFuncNames, II->getName());
- return false;
+bool isErrnoLocationCall(const CallEvent &CE) {
+ return ErrnoLocationCalls.contains(CE);
}
const NoteTag *getErrnoNoteTag(CheckerContext &C, const std::string &Message) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
index 6b53572fe5e2..95da8a28d325 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h
@@ -71,12 +71,9 @@ ProgramStateRef setErrnoState(ProgramStateRef State, ErrnoCheckState EState);
/// Clear state of errno (make it irrelevant).
ProgramStateRef clearErrnoState(ProgramStateRef State);
-/// Determine if a `Decl` node related to 'errno'.
-/// This is true if the declaration is the errno variable or a function
-/// that returns a pointer to the 'errno' value (usually the 'errno' macro is
-/// defined with this function). \p D is not required to be a canonical
-/// declaration.
-bool isErrno(const Decl *D);
+/// Determine if `Call` is a call to an internal function that returns the
+/// location of `errno` (in environments where errno is accessed this way).
+bool isErrnoLocationCall(const CallEvent &Call);
/// Create a NoteTag that displays the message if the 'errno' memory region is
/// marked as interesting, and resets the interestingness.
diff --git a/clang/test/AST/Interp/bitfields.cpp b/clang/test/AST/Interp/bitfields.cpp
index d3a8a083063a..5fc34bb1229d 100644
--- a/clang/test/AST/Interp/bitfields.cpp
+++ b/clang/test/AST/Interp/bitfields.cpp
@@ -102,3 +102,24 @@ namespace Compound {
}
static_assert(div() == 1, "");
}
+
+namespace test0 {
+ extern int int_source();
+ struct A {
+ int aField;
+ int bField;
+ };
+
+ struct B {
+ int onebit : 2;
+ int twobit : 6;
+ int intField;
+ };
+
+ struct C : A, B {
+ };
+
+ void b(C &c) {
+ c.onebit = int_source();
+ }
+}
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 2c675f4418ef..2a75457a4693 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -273,3 +273,8 @@ int test3(void) {
/// This tests that we have full type info, even for values we cannot read.
int dummyarray[5];
_Static_assert(&dummyarray[0] < &dummyarray[1], ""); // pedantic-warning {{GNU extension}}
+
+void addrlabelexpr(void) {
+ a0: ;
+ static void *ps[] = { &&a0 }; // pedantic-warning {{use of GNU address-of-label extension}}
+}
diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/Interp/cxx98.cpp
index ba6bcd97d920..be81735329db 100644
--- a/clang/test/AST/Interp/cxx98.cpp
+++ b/clang/test/AST/Interp/cxx98.cpp
@@ -45,3 +45,8 @@ struct C0 {
};
const int c0_test = C0::Data<int*>;
_Static_assert(c0_test == 0, "");
+
+
+int a = 0; // both-note {{declared here}}
+_Static_assert(a == 0, ""); // both-error {{static assertion expression is not an integral constant expression}} \
+ // both-note {{read of non-const variable 'a' is not allowed in a constant expression}}
diff --git a/clang/test/Analysis/memory-model.cpp b/clang/test/Analysis/memory-model.cpp
index fd5a286acb60..cd42e8c72b8b 100644
--- a/clang/test/Analysis/memory-model.cpp
+++ b/clang/test/Analysis/memory-model.cpp
@@ -34,9 +34,9 @@ void var_simple_ref() {
}
void var_simple_ptr(int *a) {
- clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$0<int * a>}}}
- clang_analyzer_dumpExtent(a); // expected-warning {{extent_$1{SymRegion{reg_$0<int * a>}}}}
- clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$1{SymRegion{reg_$0<int * a>}}) / 4}}
+ clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$1<int * a>}}}
+ clang_analyzer_dumpExtent(a); // expected-warning {{extent_$2{SymRegion{reg_$1<int * a>}}}}
+ clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$2{SymRegion{reg_$1<int * a>}}) / 4}}
}
void var_array() {
@@ -53,9 +53,9 @@ void string() {
}
void struct_simple_ptr(S *a) {
- clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$0<S * a>}}}
- clang_analyzer_dumpExtent(a); // expected-warning {{extent_$1{SymRegion{reg_$0<S * a>}}}}
- clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$1{SymRegion{reg_$0<S * a>}}) / 4}}
+ clang_analyzer_dump(a); // expected-warning {{SymRegion{reg_$1<S * a>}}}
+ clang_analyzer_dumpExtent(a); // expected-warning {{extent_$2{SymRegion{reg_$1<S * a>}}}}
+ clang_analyzer_dumpElementCount(a); // expected-warning {{(extent_$2{SymRegion{reg_$1<S * a>}}) / 4}}
}
void field_ref(S a) {
@@ -65,9 +65,9 @@ void field_ref(S a) {
}
void field_ptr(S *a) {
- clang_analyzer_dump(&a->f); // expected-warning {{Element{SymRegion{reg_$0<S * a>},0 S64b,struct S}.f}}
- clang_analyzer_dumpExtent(&a->f); // expected-warning {{extent_$1{SymRegion{reg_$0<S * a>}}}}
- clang_analyzer_dumpElementCount(&a->f); // expected-warning {{(extent_$1{SymRegion{reg_$0<S * a>}}) / 4U}}
+ clang_analyzer_dump(&a->f); // expected-warning {{Element{SymRegion{reg_$1<S * a>},0 S64b,struct S}.f}}
+ clang_analyzer_dumpExtent(&a->f); // expected-warning {{extent_$2{SymRegion{reg_$1<S * a>}}}}
+ clang_analyzer_dumpElementCount(&a->f); // expected-warning {{(extent_$2{SymRegion{reg_$1<S * a>}}) / 4U}}
}
void symbolic_array() {
diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c
index 001e866d34b4..508728172ab4 100644
--- a/clang/test/CodeGen/ext-int-cc.c
+++ b/clang/test/CodeGen/ext-int-cc.c
@@ -22,9 +22,9 @@
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple systemz -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=SYSTEMZ
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple ppc64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC64
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple ppc -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=PPC32
-// RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64
+// RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -O3 -disable-llvm-passes -fexperimental-max-bitint-width=1024 -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple aarch64 -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN
-// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64
+// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -O3 -disable-llvm-passes -fexperimental-max-bitint-width=1024 -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm64_32-apple-ios -target-abi darwinpcs -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=AARCH64DARWIN
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple arm -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=ARM
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple loongarch64 -O3 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s --check-prefixes=LA64
@@ -135,6 +135,7 @@ void ParamPassing4(_BitInt(129) a) {}
// WIN64: define dso_local void @ParamPassing4(ptr %{{.+}})
// LIN32: define{{.*}} void @ParamPassing4(ptr %{{.+}})
// WIN32: define dso_local void @ParamPassing4(ptr %{{.+}})
+// AARCH64: define{{.*}} void @ParamPassing4(ptr %{{.+}})
// NACL-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// NVPTX64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// NVPTX-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
@@ -155,7 +156,6 @@ void ParamPassing4(_BitInt(129) a) {}
// SYSTEMZ-NOT: define{{.*}} void @ParamPassing4(ptr %{{.+}})
// PPC64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// PPC32-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
-// AARCH64-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// AARCH64DARWIN-NOT: define{{.*}} void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// ARM-NOT: define{{.*}} arm_aapcscc void @ParamPassing4(ptr byval(i129) align 8 %{{.+}})
// LA64-NOT: define{{.*}} void @ParamPassing4(ptr %{{.+}})
@@ -294,6 +294,7 @@ _BitInt(129) ReturnPassing5(void){}
// WIN64: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// LIN32: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// WIN32: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
+// AARCH64: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// NACL-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// NVPTX64-NOT: define{{.*}} i129 @ReturnPassing5(
// NVPTX-NOT: define{{.*}} i129 @ReturnPassing5(
@@ -314,7 +315,6 @@ _BitInt(129) ReturnPassing5(void){}
// SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// PPC64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// PPC32-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
-// AARCH64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
// LA64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index f723e8f66e3e..ed1101dc5e8d 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -33,7 +33,11 @@ static bool isDummyArgument(mlir::Value v) {
if (!blockArg)
return false;
- return blockArg.getOwner()->isEntryBlock();
+ mlir::Block *owner = blockArg.getOwner();
+ if (!owner->isEntryBlock() ||
+ !mlir::isa<mlir::FunctionOpInterface>(owner->getParentOp()))
+ return false;
+ return true;
}
/// Temporary function to skip through all the no op operations
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 684aa4462915..3642a812096d 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -105,6 +105,7 @@ static std::string getFuncArgName(mlir::Value arg) {
"arg is a function argument");
mlir::FunctionOpInterface func = mlir::dyn_cast<mlir::FunctionOpInterface>(
blockArg.getOwner()->getParentOp());
+ assert(func && "This is not a function argument");
mlir::StringAttr attr = func.getArgAttrOfType<mlir::StringAttr>(
blockArg.getArgNumber(), "fir.bindc_name");
if (!attr)
diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir
index 7825ae60c71e..f94bbe4bf948 100644
--- a/flang/test/Transforms/tbaa.fir
+++ b/flang/test/Transforms/tbaa.fir
@@ -173,3 +173,40 @@
// CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] : !fir.ref<i32>
// CHECK: return
// CHECK: }
+
+// -----
+
+// Make sure we don't mistake other block arguments as dummy arguments:
+
+omp.declare_reduction @add_reduction_i32 : i32 init {
+^bb0(%arg0: i32):
+ %c0_i32 = arith.constant 0 : i32
+ omp.yield(%c0_i32 : i32)
+} combiner {
+^bb0(%arg0: i32, %arg1: i32):
+ %0 = arith.addi %arg0, %arg1 : i32
+ omp.yield(%0 : i32)
+}
+
+func.func @_QQmain() attributes {fir.bindc_name = "reduce"} {
+ %c10_i32 = arith.constant 10 : i32
+ %c6_i32 = arith.constant 6 : i32
+ %c-1_i32 = arith.constant -1 : i32
+ %0 = fir.address_of(@_QFEi) : !fir.ref<i32>
+ %1 = fir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ omp.parallel reduction(@add_reduction_i32 %1 -> %arg0 : !fir.ref<i32>) {
+// CHECK: omp.parallel reduction({{.*}}) {
+ %8 = fir.declare %arg0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: %[[DECL:.*]] = fir.declare
+ fir.store %c-1_i32 to %8 : !fir.ref<i32>
+// CHECK-NOT: fir.store %{{.*}} to %[[DECL]] {tbaa = %{{.*}}} : !fir.ref<i32>
+// CHECK: fir.store %{{.*}} to %[[DECL]] : !fir.ref<i32>
+ omp.terminator
+ }
+ return
+}
+
+fir.global internal @_QFEi : i32 {
+ %c0_i32 = arith.constant 0 : i32
+ fir.has_value %c0_i32 : i32
+}
diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp
index 1d8bf2f88ae6..f43e940492b0 100644
--- a/lldb/source/Target/UnwindLLDB.cpp
+++ b/lldb/source/Target/UnwindLLDB.cpp
@@ -261,7 +261,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
cur_idx < 100 ? cur_idx : 100, "", cur_idx);
return nullptr;
}
- if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) {
+
+ // Invalid code addresses should not appear on the stack *unless* we're
+ // directly below a trap handler frame (in this case, the invalid address is
+ // likely the cause of the trap).
+ if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc) &&
+ !prev_frame->reg_ctx_lldb_sp->IsTrapHandlerFrame()) {
// If the RegisterContextUnwind has a fallback UnwindPlan, it will switch to
// that and return true. Subsequent calls to TryFallbackUnwindPlan() will
// return false.
diff --git a/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c b/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c
new file mode 100644
index 000000000000..b4818de3b7fb
--- /dev/null
+++ b/lldb/test/Shell/Unwind/Inputs/unaligned-pc-sigbus.c
@@ -0,0 +1,21 @@
+#include <signal.h>
+#include <stdint.h>
+#include <unistd.h>
+
+void sigbus_handler(int signo) { _exit(47); }
+
+int target_function() { return 47; }
+
+int main() {
+ signal(SIGBUS, sigbus_handler);
+
+ // Generate a SIGBUS by deliverately calling through an unaligned function
+ // pointer.
+ union {
+ int (*t)();
+ uintptr_t p;
+ } u;
+ u.t = target_function;
+ u.p |= 1;
+ return u.t();
+}
diff --git a/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test
new file mode 100644
index 000000000000..49f771cae95b
--- /dev/null
+++ b/lldb/test/Shell/Unwind/unaligned-pc-sigbus.test
@@ -0,0 +1,31 @@
+# REQUIRES: target-aarch64 && native
+# UNSUPPORTED: system-windows
+# llvm.org/pr91610, rdar://128031075
+# XFAIL: system-darwin
+
+# RUN: %clang_host %S/Inputs/unaligned-pc-sigbus.c -o %t
+# RUN: %lldb -s %s -o exit %t | FileCheck %s
+
+# Convert EXC_BAD_ACCESS into SIGBUS on darwin.
+settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_ACCESS
+
+breakpoint set -n sigbus_handler
+# CHECK: Breakpoint 1: where = {{.*}}`sigbus_handler
+
+run
+# CHECK: thread #1, {{.*}} stop reason = signal SIGBUS
+
+thread backtrace
+# CHECK: (lldb) thread backtrace
+# CHECK: frame #0: [[TARGET:0x[0-9a-fA-F]*]] {{.*}}`target_function
+
+continue
+# CHECK: thread #1, {{.*}} stop reason = breakpoint 1
+
+
+thread backtrace
+# CHECK: (lldb) thread backtrace
+# CHECK: frame #0: {{.*}}`sigbus_handler
+# Unknown number of signal trampoline frames
+# CHECK: frame #{{[0-9]+}}: [[TARGET]] {{.*}}`target_function
+
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index ee39c6355c29..3ce766fc173c 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -1161,52 +1161,45 @@ void AArch64AsmPrinter::emitFunctionEntryLabel() {
TS->emitDirectiveVariantPCS(CurrentFnSym);
}
+ AsmPrinter::emitFunctionEntryLabel();
+
if (TM.getTargetTriple().isWindowsArm64EC() &&
!MF->getFunction().hasLocalLinkage()) {
// For ARM64EC targets, a function definition's name is mangled differently
- // from the normal symbol. We emit the alias from the unmangled symbol to
- // mangled symbol name here.
- if (MDNode *Unmangled =
- MF->getFunction().getMetadata("arm64ec_unmangled_name")) {
- AsmPrinter::emitFunctionEntryLabel();
-
- if (MDNode *ECMangled =
- MF->getFunction().getMetadata("arm64ec_ecmangled_name")) {
- StringRef UnmangledStr =
- cast<MDString>(Unmangled->getOperand(0))->getString();
- MCSymbol *UnmangledSym =
- MMI->getContext().getOrCreateSymbol(UnmangledStr);
- StringRef ECMangledStr =
- cast<MDString>(ECMangled->getOperand(0))->getString();
- MCSymbol *ECMangledSym =
- MMI->getContext().getOrCreateSymbol(ECMangledStr);
- OutStreamer->emitSymbolAttribute(UnmangledSym, MCSA_WeakAntiDep);
- OutStreamer->emitAssignment(
- UnmangledSym,
- MCSymbolRefExpr::create(ECMangledSym, MCSymbolRefExpr::VK_WEAKREF,
- MMI->getContext()));
- OutStreamer->emitSymbolAttribute(ECMangledSym, MCSA_WeakAntiDep);
- OutStreamer->emitAssignment(
- ECMangledSym,
- MCSymbolRefExpr::create(CurrentFnSym, MCSymbolRefExpr::VK_WEAKREF,
- MMI->getContext()));
- return;
+ // from the normal symbol, emit required aliases here.
+ auto emitFunctionAlias = [&](MCSymbol *Src, MCSymbol *Dst) {
+ OutStreamer->emitSymbolAttribute(Src, MCSA_WeakAntiDep);
+ OutStreamer->emitAssignment(
+ Src, MCSymbolRefExpr::create(Dst, MCSymbolRefExpr::VK_WEAKREF,
+ MMI->getContext()));
+ };
+
+ auto getSymbolFromMetadata = [&](StringRef Name) {
+ MCSymbol *Sym = nullptr;
+ if (MDNode *Node = MF->getFunction().getMetadata(Name)) {
+ StringRef NameStr = cast<MDString>(Node->getOperand(0))->getString();
+ Sym = MMI->getContext().getOrCreateSymbol(NameStr);
+ }
+ return Sym;
+ };
+
+ if (MCSymbol *UnmangledSym =
+ getSymbolFromMetadata("arm64ec_unmangled_name")) {
+ MCSymbol *ECMangledSym = getSymbolFromMetadata("arm64ec_ecmangled_name");
+
+ if (ECMangledSym) {
+ // An external function, emit the alias from the unmangled symbol to
+ // mangled symbol name and the alias from the mangled symbol to guest
+ // exit thunk.
+ emitFunctionAlias(UnmangledSym, ECMangledSym);
+ emitFunctionAlias(ECMangledSym, CurrentFnSym);
} else {
- StringRef UnmangledStr =
- cast<MDString>(Unmangled->getOperand(0))->getString();
- MCSymbol *UnmangledSym =
- MMI->getContext().getOrCreateSymbol(UnmangledStr);
- OutStreamer->emitSymbolAttribute(UnmangledSym, MCSA_WeakAntiDep);
- OutStreamer->emitAssignment(
- UnmangledSym,
- MCSymbolRefExpr::create(CurrentFnSym, MCSymbolRefExpr::VK_WEAKREF,
- MMI->getContext()));
- return;
+ // A function implementation, emit the alias from the unmangled symbol
+ // to mangled symbol name.
+ emitFunctionAlias(UnmangledSym, CurrentFnSym);
}
}
}
-
- return AsmPrinter::emitFunctionEntryLabel();
}
/// Small jump tables contain an unsigned byte or half, representing the offset
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index fa634e774b5c..5eb99ffd1e10 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -1506,24 +1506,25 @@ void VPBlendRecipe::execute(VPTransformState &State) {
// Note that Mask0 is never used: lanes for which no path reaches this phi and
// are essentially undef are taken from In0.
VectorParts Entry(State.UF);
- for (unsigned In = 0; In < NumIncoming; ++In) {
- for (unsigned Part = 0; Part < State.UF; ++Part) {
- // We might have single edge PHIs (blocks) - use an identity
- // 'select' for the first PHI operand.
- Value *In0 = State.get(getIncomingValue(In), Part);
- if (In == 0)
- Entry[Part] = In0; // Initialize with the first incoming value.
- else {
- // Select between the current value and the previous incoming edge
- // based on the incoming mask.
- Value *Cond = State.get(getMask(In), Part);
- Entry[Part] =
- State.Builder.CreateSelect(Cond, In0, Entry[Part], "predphi");
- }
- }
- }
+ bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
+ for (unsigned In = 0; In < NumIncoming; ++In) {
+ for (unsigned Part = 0; Part < State.UF; ++Part) {
+ // We might have single edge PHIs (blocks) - use an identity
+ // 'select' for the first PHI operand.
+ Value *In0 = State.get(getIncomingValue(In), Part, OnlyFirstLaneUsed);
+ if (In == 0)
+ Entry[Part] = In0; // Initialize with the first incoming value.
+ else {
+ // Select between the current value and the previous incoming edge
+ // based on the incoming mask.
+ Value *Cond = State.get(getMask(In), Part, OnlyFirstLaneUsed);
+ Entry[Part] =
+ State.Builder.CreateSelect(Cond, In0, Entry[Part], "predphi");
+ }
+ }
+ }
for (unsigned Part = 0; Part < State.UF; ++Part)
- State.set(this, Entry[Part], Part);
+ State.set(this, Entry[Part], Part, OnlyFirstLaneUsed);
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll
index 4e38630209b2..5f8141600371 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll
@@ -40,8 +40,6 @@ define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 8 x i64> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], 0
-; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[TMP12]], i64 0
-; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <vscale x 8 x i64> [[BROADCAST_SPLATINSERT5]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP13:%.*]] = icmp ule <vscale x 8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
; CHECK-NEXT: [[TMP14:%.*]] = icmp ule <vscale x 8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT2]]
; CHECK-NEXT: [[TMP15:%.*]] = select <vscale x 8 x i1> [[TMP13]], <vscale x 8 x i1> [[TMP14]], <vscale x 8 x i1> zeroinitializer
@@ -52,9 +50,9 @@ define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64
; CHECK-NEXT: [[TMP20:%.*]] = xor <vscale x 8 x i1> [[TMP14]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer)
; CHECK-NEXT: [[TMP21:%.*]] = select <vscale x 8 x i1> [[TMP13]], <vscale x 8 x i1> [[TMP20]], <vscale x 8 x i1> zeroinitializer
; CHECK-NEXT: [[TMP22:%.*]] = or <vscale x 8 x i1> [[TMP19]], [[TMP21]]
-; CHECK-NEXT: [[PREDPHI:%.*]] = select <vscale x 8 x i1> [[TMP19]], <vscale x 8 x i64> [[BROADCAST_SPLAT6]], <vscale x 8 x i64> shufflevector (<vscale x 8 x i64> insertelement (<vscale x 8 x i64> poison, i64 poison, i64 0), <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer)
-; CHECK-NEXT: [[TMP23:%.*]] = extractelement <vscale x 8 x i64> [[PREDPHI]], i32 0
-; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[TMP23]]
+; CHECK-NEXT: [[EXT:%.+]] = extractelement <vscale x 8 x i1> [[TMP19]], i32 0
+; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[EXT]], i64 [[TMP12]], i64 poison
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[PREDPHI]]
; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i16, ptr [[TMP24]], i32 0
; CHECK-NEXT: call void @llvm.masked.store.nxv8i16.p0(<vscale x 8 x i16> zeroinitializer, ptr [[TMP25]], i32 2, <vscale x 8 x i1> [[TMP22]])
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]]
diff --git a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll
index 71eed3b2985d..19cbcac6090c 100644
--- a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll
+++ b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll
@@ -4,19 +4,12 @@
define void @blend_uniform_iv_trunc(i1 %c) {
; CHECK-LABEL: @blend_uniform_iv_trunc(
-; CHECK: vector.ph:
-; CHECK-NEXT: [[MASK0:%.*]] = insertelement <4 x i1> poison, i1 %c, i64 0
-; CHECK-NEXT: [[MASK1:%.*]] = shufflevector <4 x i1> [[MASK0]], <4 x i1> poison, <4 x i32> zeroinitializer
-
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDEX]] to i16
; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP1]], 0
-; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i16> poison, i16 [[TMP2]], i64 0
-; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT1]], <4 x i16> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[MASK1]], <4 x i16> [[BROADCAST_SPLAT2]], <4 x i16> undef
-; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i16> [[PREDPHI]], i32 0
-; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i16 [[TMP4]]
+; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 %c, i16 [[TMP2]], i16 undef
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i16 [[PREDPHI]]
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
; CHECK-NEXT: store <4 x i16> zeroinitializer, ptr [[TMP6]], align 2
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
@@ -49,17 +42,12 @@ exit: ; preds = %loop.latch
define void @blend_uniform_iv(i1 %c) {
; CHECK-LABEL: @blend_uniform_iv(
; CHECK: vector.ph:
-; CHECK-NEXT: [[MASK0:%.*]] = insertelement <4 x i1> poison, i1 %c, i64 0
-; CHECK-NEXT: [[MASK1:%.*]] = shufflevector <4 x i1> [[MASK0]], <4 x i1> poison, <4 x i32> zeroinitializer
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0
-; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> poison, i64 [[TMP0]], i64 0
-; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT1]], <4 x i64> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[MASK1]], <4 x i64> [[BROADCAST_SPLAT2]], <4 x i64> undef
-; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i64> [[PREDPHI]], i32 0
-; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i64 [[TMP2]]
+; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 %c, i64 [[TMP0]], i64 undef
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i64 [[PREDPHI]]
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i16, ptr [[TMP3]], i32 0
; CHECK-NEXT: store <4 x i16> zeroinitializer, ptr [[TMP4]], align 2
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
diff --git a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll
index d0c74897f264..0f7bd3d71feb 100644
--- a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll
+++ b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll
@@ -16,7 +16,7 @@ define void @test_not_first_lane_only_constant(ptr %A, ptr noalias %B) {
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16
; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[OFFSET_IDX]], 0
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[TMP0]]
-; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr %B, align 2
+; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[B]], align 2
; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i16> poison, i16 [[TMP13]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT5]], <4 x i16> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
@@ -86,8 +86,6 @@ define void @test_not_first_lane_only_wide_compare(ptr %A, ptr noalias %B, i16 %
; CHECK: vector.ph:
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x ptr> poison, ptr [[B]], i64 0
-; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x ptr> [[BROADCAST_SPLATINSERT3]], <4 x ptr> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
@@ -97,8 +95,8 @@ define void @test_not_first_lane_only_wide_compare(ptr %A, ptr noalias %B, i16 %
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP2]], align 2
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT2]]
-; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP5]], <4 x ptr> poison, <4 x ptr> [[BROADCAST_SPLAT4]]
-; CHECK-NEXT: [[TMP12:%.*]] = extractelement <4 x ptr> [[PREDPHI]], i32 0
+; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0
+; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP4]], ptr poison, ptr [[B]]
; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[TMP12]], align 2
; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <4 x i16> poison, i16 [[TMP13]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT5]], <4 x i16> poison, <4 x i32> zeroinitializer
@@ -165,6 +163,101 @@ loop.latch:
exit:
ret void
}
+
+define void @test_not_first_lane_only_wide_compare_incoming_order_swapped(ptr %A, ptr noalias %B, i16 %x, i16 %y) {
+; CHECK-LABEL: define void @test_not_first_lane_only_wide_compare_incoming_order_swapped(
+; CHECK-SAME: ptr [[A:%.*]], ptr noalias [[B:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
+; CHECK: vector.ph:
+; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0
+; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i16> poison, i16 [[Y]], i64 0
+; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT1]], <4 x i16> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
+; CHECK: vector.body:
+; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
+; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16
+; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[OFFSET_IDX]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
+; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP2]], align 2
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT]]
+; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[TMP3]], <i1 true, i1 true, i1 true, i1 true>
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT2]]
+; CHECK-NEXT: [[TMP6:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP5]], <4 x i1> zeroinitializer
+; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i1> [[TMP5]], <i1 true, i1 true, i1 true, i1 true>
+; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP7]], <4 x i1> zeroinitializer
+; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP6]], i32 0
+; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP8]], i32 0
+; CHECK-NEXT: [[TMP11:%.*]] = or i1 [[TMP9]], [[TMP10]]
+; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[TMP11]], ptr [[B]], ptr poison
+; CHECK-NEXT: [[TMP12:%.*]] = load i16, ptr [[PREDPHI]], align 2
+; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x i16> poison, i16 [[TMP12]], i64 0
+; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT3]], <4 x i16> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT: store <4 x i16> [[BROADCAST_SPLAT4]], ptr [[TMP2]], align 2
+; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4
+; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1000
+; CHECK-NEXT: br i1 [[TMP13]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
+; CHECK: middle.block:
+; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
+; CHECK: scalar.ph:
+; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ 1000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
+; CHECK: loop.header:
+; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i16, ptr [[A]], i16 [[IV]]
+; CHECK-NEXT: [[L_0:%.*]] = load i16, ptr [[GEP_A]], align 2
+; CHECK-NEXT: [[C_0:%.*]] = icmp ult i16 [[L_0]], [[X]]
+; CHECK-NEXT: br i1 [[C_0]], label [[LOOP_LATCH]], label [[ELSE_1:%.*]]
+; CHECK: else.1:
+; CHECK-NEXT: [[C_1:%.*]] = icmp ult i16 [[L_0]], [[Y]]
+; CHECK-NEXT: br i1 [[C_1]], label [[THEN_2:%.*]], label [[ELSE_2:%.*]]
+; CHECK: then.2:
+; CHECK-NEXT: br label [[ELSE_2]]
+; CHECK: else.2:
+; CHECK-NEXT: br label [[LOOP_LATCH]]
+; CHECK: loop.latch:
+; CHECK-NEXT: [[MERGE:%.*]] = phi ptr [ poison, [[LOOP_HEADER]] ], [ [[B]], [[ELSE_2]] ]
+; CHECK-NEXT: [[L:%.*]] = load i16, ptr [[MERGE]], align 2
+; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1
+; CHECK-NEXT: store i16 [[L]], ptr [[GEP_A]], align 2
+; CHECK-NEXT: [[C_2:%.*]] = icmp eq i16 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[C_2]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop.latch ]
+ %gep.A = getelementptr inbounds i16, ptr %A, i16 %iv
+ %l.0 = load i16, ptr %gep.A
+ %c.0 = icmp ult i16 %l.0, %x
+ br i1 %c.0, label %loop.latch, label %else.1
+
+else.1:
+ %c.1 = icmp ult i16 %l.0, %y
+ br i1 %c.1, label %then.2, label %else.2
+
+then.2:
+ br label %else.2
+
+else.2:
+ br label %loop.latch
+
+loop.latch:
+ %merge = phi ptr [ poison, %loop.header ], [ %B, %else.2 ]
+ %l = load i16, ptr %merge, align 2
+ %iv.next = add i16 %iv, 1
+ store i16 %l, ptr %gep.A
+ %c.2 = icmp eq i16 %iv.next, 1000
+ br i1 %c.2, label %exit, label %loop.header
+
+exit:
+ ret void
+}
;.
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
@@ -172,4 +265,6 @@ exit:
; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]}
; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]}
+; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]}
+; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META1]]}
;.