aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvporpo <vporpodas@google.com>2024-07-11 21:52:11 -0700
committerVitaly Buka <vitalybuka@google.com>2024-07-11 21:52:11 -0700
commitc86c98e21b7e48b95bfc40790250e270add23fcd (patch)
treee95a05be99cf7f951d36524ebd17f93a651cdd98
parent8ed26eae8785da1b96fde4b6b290b18c859980a1 (diff)
parentecd2bf73cb212452951b3010bbf06e4d96330a92 (diff)
downloadllvm-users/vitalybuka/spr/main.nfcasan-use-p-to-print-addresses.zip
llvm-users/vitalybuka/spr/main.nfcasan-use-p-to-print-addresses.tar.gz
llvm-users/vitalybuka/spr/main.nfcasan-use-p-to-print-addresses.tar.bz2
[𝘀𝗽𝗿] changes introduced through rebaseusers/vitalybuka/spr/main.nfcasan-use-p-to-print-addresses
Created using spr 1.3.4 [skip ci]
-rw-r--r--clang/docs/ReleaseNotes.rst2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp44
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h3
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp2
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp21
-rw-r--r--clang/test/SemaCXX/cxx0x-noexcept-expression.cpp18
-rw-r--r--clang/unittests/Format/FormatTestComments.cpp17
-rw-r--r--compiler-rt/lib/memprof/memprof_allocator.h6
-rw-r--r--compiler-rt/lib/msan/msan_linux.cpp2
-rw-r--r--compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c4
-rw-r--r--llvm/include/llvm/SandboxIR/SandboxIR.h15
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp79
-rw-r--r--llvm/lib/SandboxIR/SandboxIR.cpp40
-rw-r--r--llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp2
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp17
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp13
-rw-r--r--llvm/lib/Target/RISCV/RISCVSystemOperands.td1
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroSplit.cpp28
-rw-r--r--llvm/test/MC/AsmParser/altmacro-arg.s22
-rw-r--r--llvm/unittests/SandboxIR/SandboxIRTest.cpp123
20 files changed, 328 insertions, 131 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index be2f067..e68398c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1011,7 +1011,7 @@ Bug Fixes to C++ Support
- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821)
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
- (#GH88081), (#GH89496), (#GH90669) and (#GH91633).
+ (#GH88081), (#GH89496), (#GH90669), (#GH91633) and (#GH97453).
- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters.
- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368).
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 5c810cd..6c10b4a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3702,6 +3702,19 @@ template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *D) {
return D->isImplicit();
}
+bool CodeGenModule::shouldEmitCUDAGlobalVar(const VarDecl *Global) const {
+ assert(LangOpts.CUDA && "Should not be called by non-CUDA languages");
+ // We need to emit host-side 'shadows' for all global
+ // device-side variables because the CUDA runtime needs their
+ // size and host-side address in order to provide access to
+ // their device-side incarnations.
+ return !LangOpts.CUDAIsDevice || Global->hasAttr<CUDADeviceAttr>() ||
+ Global->hasAttr<CUDAConstantAttr>() ||
+ Global->hasAttr<CUDASharedAttr>() ||
+ Global->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ Global->getType()->isCUDADeviceBuiltinTextureType();
+}
+
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
const auto *Global = cast<ValueDecl>(GD.getDecl());
@@ -3726,36 +3739,27 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Non-constexpr non-lambda implicit host device functions are not emitted
// unless they are used on device side.
if (LangOpts.CUDA) {
- if (LangOpts.CUDAIsDevice) {
+ assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
+ "Expected Variable or Function");
+ if (const auto *VD = dyn_cast<VarDecl>(Global)) {
+ if (!shouldEmitCUDAGlobalVar(VD))
+ return;
+ } else if (LangOpts.CUDAIsDevice) {
const auto *FD = dyn_cast<FunctionDecl>(Global);
if ((!Global->hasAttr<CUDADeviceAttr>() ||
- (LangOpts.OffloadImplicitHostDeviceTemplates && FD &&
+ (LangOpts.OffloadImplicitHostDeviceTemplates &&
hasImplicitAttr<CUDAHostAttr>(FD) &&
hasImplicitAttr<CUDADeviceAttr>(FD) && !FD->isConstexpr() &&
!isLambdaCallOperator(FD) &&
!getContext().CUDAImplicitHostDeviceFunUsedByDevice.count(FD))) &&
!Global->hasAttr<CUDAGlobalAttr>() &&
- !Global->hasAttr<CUDAConstantAttr>() &&
- !Global->hasAttr<CUDASharedAttr>() &&
- !Global->getType()->isCUDADeviceBuiltinSurfaceType() &&
- !Global->getType()->isCUDADeviceBuiltinTextureType() &&
!(LangOpts.HIPStdPar && isa<FunctionDecl>(Global) &&
!Global->hasAttr<CUDAHostAttr>()))
return;
- } else {
- // We need to emit host-side 'shadows' for all global
- // device-side variables because the CUDA runtime needs their
- // size and host-side address in order to provide access to
- // their device-side incarnations.
-
- // So device-only functions are the only things we skip.
- if (isa<FunctionDecl>(Global) && !Global->hasAttr<CUDAHostAttr>() &&
- Global->hasAttr<CUDADeviceAttr>())
- return;
-
- assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
- "Expected Variable or Function");
- }
+ // Device-only functions are the only things we skip.
+ } else if (!Global->hasAttr<CUDAHostAttr>() &&
+ Global->hasAttr<CUDADeviceAttr>())
+ return;
}
if (LangOpts.OpenMP) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 585c4ea..caa3786 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -563,6 +563,9 @@ private:
bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
+ // Whether a global variable should be emitted by CUDA/HIP host/device
+ // related attributes.
+ bool shouldEmitCUDAGlobalVar(const VarDecl *VD) const;
bool shouldOpportunisticallyEmitVTables();
/// Map used to be sure we don't emit the same CompoundLiteral twice.
llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *>
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 50531ae..a31874a 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -1116,7 +1116,7 @@ void WhitespaceManager::alignTrailingComments() {
// leave the comments.
if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
break;
- C.Spaces = OriginalSpaces;
+ C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
continue;
}
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 943ce0f..9ccbbf9 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -511,11 +511,28 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// and the end of the function-definition, member-declarator, or
// declarator.
CXXMethodDecl *Method;
+ FunctionDecl *FunctionToPush;
if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(LM.Method))
- Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ FunctionToPush = FunTmpl->getTemplatedDecl();
else
- Method = dyn_cast<CXXMethodDecl>(LM.Method);
+ FunctionToPush = cast<FunctionDecl>(LM.Method);
+ Method = dyn_cast<CXXMethodDecl>(FunctionToPush);
+
+ // Push a function scope so that tryCaptureVariable() can properly visit
+ // function scopes involving function parameters that are referenced inside
+ // the noexcept specifier e.g. through a lambda expression.
+ // Example:
+ // struct X {
+ // void ICE(int val) noexcept(noexcept([val]{}));
+ // };
+ // Setup the CurScope to match the function DeclContext - we have such
+ // assumption in IsInFnTryBlockHandler().
+ ParseScope FnScope(this, Scope::FnScope);
+ Sema::ContextRAII FnContext(Actions, FunctionToPush,
+ /*NewThisContext=*/false);
+ Sema::FunctionScopeRAII PopFnContext(Actions);
+ Actions.PushFunctionScope();
Sema::CXXThisScopeRAII ThisScope(
Actions, Method ? Method->getParent() : nullptr,
diff --git a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
index b9aeffb..a01edc7 100644
--- a/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
+++ b/clang/test/SemaCXX/cxx0x-noexcept-expression.cpp
@@ -157,3 +157,21 @@ void f5() {
// expected-error@-1 {{no member named 'non_existent' in 'typeid_::X<true>'}}
}
} // namespace typeid_
+
+namespace GH97453 {
+
+struct UnconstrainedCtor {
+ int value_;
+
+ template <typename T>
+ constexpr UnconstrainedCtor(T value) noexcept(noexcept(value_ = value))
+ : value_(static_cast<int>(value)) {}
+};
+
+UnconstrainedCtor U(42);
+
+struct X {
+ void ICE(int that) noexcept(noexcept([that]() {}));
+};
+
+} // namespace GH97453
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 3e75707..8f84d59 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -3145,6 +3145,23 @@ TEST_F(FormatTestComments, AlignTrailingCommentsLeave) {
"int bar = 1234; // This is a very long comment\n"
" // which is wrapped arround.",
Style));
+
+ Style = getLLVMStyle();
+ Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Leave;
+ Style.TabWidth = 2;
+ Style.UseTab = FormatStyle::UT_ForIndentation;
+ verifyNoChange("{\n"
+ "\t// f\n"
+ "\tf();\n"
+ "\n"
+ "\t// g\n"
+ "\tg();\n"
+ "\t{\n"
+ "\t\t// h(); // h\n"
+ "\t\tfoo(); // foo\n"
+ "\t}\n"
+ "}",
+ Style);
}
TEST_F(FormatTestComments, DontAlignNamespaceComments) {
diff --git a/compiler-rt/lib/memprof/memprof_allocator.h b/compiler-rt/lib/memprof/memprof_allocator.h
index 89e924f..6d898f0 100644
--- a/compiler-rt/lib/memprof/memprof_allocator.h
+++ b/compiler-rt/lib/memprof/memprof_allocator.h
@@ -46,11 +46,7 @@ struct MemprofMapUnmapCallback {
void OnUnmap(uptr p, uptr size) const;
};
-#if SANITIZER_APPLE
-constexpr uptr kAllocatorSpace = 0x600000000000ULL;
-#else
-constexpr uptr kAllocatorSpace = 0x500000000000ULL;
-#endif
+constexpr uptr kAllocatorSpace = ~(uptr)0;
constexpr uptr kAllocatorSize = 0x40000000000ULL; // 4T.
typedef DefaultSizeClassMap SizeClassMap;
template <typename AddressSpaceViewTy>
diff --git a/compiler-rt/lib/msan/msan_linux.cpp b/compiler-rt/lib/msan/msan_linux.cpp
index 5daf9d8..894cf17 100644
--- a/compiler-rt/lib/msan/msan_linux.cpp
+++ b/compiler-rt/lib/msan/msan_linux.cpp
@@ -74,7 +74,7 @@ static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
uptr end = beg + size - 1;
Printf(
"FATAL: MemorySanitizer: Cannot protect memory range %p-%p (%s).\n",
- (void *)beg, (void *)end);
+ (void *)beg, (void *)end, name);
return false;
}
}
diff --git a/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
index e450c10..421d2339 100644
--- a/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
+++ b/compiler-rt/test/hwasan/TestCases/Linux/fixed-shadow.c
@@ -4,7 +4,7 @@
// RUN: %clang_hwasan %s -o %t
// RUN: %run %t
// RUN: HWASAN_OPTIONS=fixed_shadow_base=263878495698944 %run %t 2>%t.out || (cat %t.out | FileCheck %s)
-// RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t 2>%t.out || (cat %t.out | FileCheck %s)
+// RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t
//
// If -hwasan-mapping-offset is set, then the fixed_shadow_base needs to match.
// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=263878495698944 -o %t
@@ -12,7 +12,7 @@
// RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 not %run %t
// RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=4398046511104 -o %t
-// RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t 2>%t.out || (cat %t.out | FileCheck %s)
+// RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t
// RUN: HWASAN_OPTIONS=fixed_shadow_base=263878495698944 not %run %t
//
// Note: if fixed_shadow_base is not set, compiler-rt will dynamically choose a
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 8e87470..317884f 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -200,6 +200,7 @@ protected:
llvm::Value *Val = nullptr;
friend class Context; // For getting `Val`.
+ friend class User; // For getting `Val`.
/// All values point to the context.
Context &Ctx;
@@ -284,6 +285,11 @@ public:
Type *getType() const { return Val->getType(); }
Context &getContext() const { return Ctx; }
+
+ void replaceUsesWithIf(Value *OtherV,
+ llvm::function_ref<bool(const Use &)> ShouldReplace);
+ void replaceAllUsesWith(Value *Other);
+
#ifndef NDEBUG
/// Should crash if there is something wrong with the instruction.
virtual void verify() const = 0;
@@ -349,6 +355,10 @@ protected:
virtual unsigned getUseOperandNo(const Use &Use) const = 0;
friend unsigned Use::getOperandNo() const; // For getUseOperandNo()
+#ifndef NDEBUG
+ void verifyUserOfLLVMUse(const llvm::Use &Use) const;
+#endif // NDEBUG
+
public:
/// For isa/dyn_cast.
static bool classof(const Value *From);
@@ -387,6 +397,11 @@ public:
return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands() : 0;
}
+ virtual void setOperand(unsigned OperandIdx, Value *Operand);
+ /// Replaces any operands that match \p FromV with \p ToV. Returns whether any
+ /// operands were replaced.
+ bool replaceUsesOfWith(Value *FromV, Value *ToV);
+
#ifndef NDEBUG
void verify() const override {
assert(isa<llvm::User>(Val) && "Expected User!");
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index f3caa90..b3d16d55 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -2504,34 +2504,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
ArrayRef<MCAsmMacroArgument> A,
bool EnableAtPseudoVariable) {
unsigned NParameters = Parameters.size();
- auto expandArg = [&](unsigned Index) {
- bool HasVararg = NParameters ? Parameters.back().Vararg : false;
- bool VarargParameter = HasVararg && Index == (NParameters - 1);
- for (const AsmToken &Token : A[Index])
- // For altmacro mode, you can write '%expr'.
- // The prefix '%' evaluates the expression 'expr'
- // and uses the result as a string (e.g. replace %(1+2) with the
- // string "3").
- // Here, we identify the integer token which is the result of the
- // absolute expression evaluation and replace it with its string
- // representation.
- if (AltMacroMode && Token.getString().front() == '%' &&
- Token.is(AsmToken::Integer))
- // Emit an integer value to the buffer.
- OS << Token.getIntVal();
- // Only Token that was validated as a string and begins with '<'
- // is considered altMacroString!!!
- else if (AltMacroMode && Token.getString().front() == '<' &&
- Token.is(AsmToken::String)) {
- OS << angleBracketString(Token.getStringContents());
- }
- // We expect no quotes around the string's contents when
- // parsing for varargs.
- else if (Token.isNot(AsmToken::String) || VarargParameter)
- OS << Token.getString();
- else
- OS << Token.getStringContents();
- };
+ bool HasVararg = NParameters ? Parameters.back().Vararg : false;
// A macro without parameters is handled differently on Darwin:
// gas accepts no arguments and does no substitutions
@@ -2565,10 +2538,36 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
for (; Index < NParameters; ++Index)
if (Parameters[Index].Name == Argument)
break;
- if (Index == NParameters)
+ if (Index == NParameters) {
OS << '\\' << Argument;
- else
- expandArg(Index);
+ } else {
+ bool VarargParameter = HasVararg && Index == (NParameters - 1);
+ for (const AsmToken &Token : A[Index]) {
+ // For altmacro mode, you can write '%expr'.
+ // The prefix '%' evaluates the expression 'expr'
+ // and uses the result as a string (e.g. replace %(1+2) with the
+ // string "3").
+ // Here, we identify the integer token which is the result of the
+ // absolute expression evaluation and replace it with its string
+ // representation.
+ if (AltMacroMode && Token.getString().front() == '%' &&
+ Token.is(AsmToken::Integer))
+ // Emit an integer value to the buffer.
+ OS << Token.getIntVal();
+ // Only Token that was validated as a string and begins with '<'
+ // is considered altMacroString!!!
+ else if (AltMacroMode && Token.getString().front() == '<' &&
+ Token.is(AsmToken::String)) {
+ OS << angleBracketString(Token.getStringContents());
+ }
+ // We expect no quotes around the string's contents when
+ // parsing for varargs.
+ else if (Token.isNot(AsmToken::String) || VarargParameter)
+ OS << Token.getString();
+ else
+ OS << Token.getStringContents();
+ }
+ }
continue;
}
@@ -2600,24 +2599,6 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,
}
}
- if (AltMacroMode && isIdentifierChar(Body[I])) {
- size_t Len = 1;
- while (I + Len != End && isIdentifierChar(Body[I + Len]))
- ++Len;
- StringRef Argument(Body.data() + I, Len);
- unsigned Index = 0;
- for (; Index != NParameters; ++Index)
- if (Parameters[Index].Name == Argument)
- break;
- if (Index != NParameters) {
- expandArg(Index);
- I += Len;
- if (I != End && Body[I] == '&')
- ++I;
- continue;
- }
- }
-
OS << Body[I];
++I;
}
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index e4a902f..41b66c0 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -103,6 +103,25 @@ Value::user_iterator Value::user_begin() {
unsigned Value::getNumUses() const { return range_size(Val->users()); }
+void Value::replaceUsesWithIf(
+ Value *OtherV, llvm::function_ref<bool(const Use &)> ShouldReplace) {
+ assert(getType() == OtherV->getType() && "Can't replace with different type");
+ llvm::Value *OtherVal = OtherV->Val;
+ Val->replaceUsesWithIf(
+ OtherVal, [&ShouldReplace, this](llvm::Use &LLVMUse) -> bool {
+ User *DstU = cast_or_null<User>(Ctx.getValue(LLVMUse.getUser()));
+ if (DstU == nullptr)
+ return false;
+ return ShouldReplace(Use(&LLVMUse, DstU, Ctx));
+ });
+}
+
+void Value::replaceAllUsesWith(Value *Other) {
+ assert(getType() == Other->getType() &&
+ "Replacing with Value of different type!");
+ Val->replaceAllUsesWith(Other->Val);
+}
+
#ifndef NDEBUG
std::string Value::getName() const {
std::stringstream SS;
@@ -165,6 +184,13 @@ Use User::getOperandUseDefault(unsigned OpIdx, bool Verify) const {
return Use(LLVMUse, const_cast<User *>(this), Ctx);
}
+#ifndef NDEBUG
+void User::verifyUserOfLLVMUse(const llvm::Use &Use) const {
+ assert(Ctx.getValue(Use.getUser()) == this &&
+ "Use not found in this SBUser's operands!");
+}
+#endif
+
bool User::classof(const Value *From) {
switch (From->getSubclassID()) {
#define DEF_VALUE(ID, CLASS)
@@ -180,6 +206,15 @@ bool User::classof(const Value *From) {
}
}
+void User::setOperand(unsigned OperandIdx, Value *Operand) {
+ assert(isa<llvm::User>(Val) && "No operands!");
+ cast<llvm::User>(Val)->setOperand(OperandIdx, Operand->Val);
+}
+
+bool User::replaceUsesOfWith(Value *FromV, Value *ToV) {
+ return cast<llvm::User>(Val)->replaceUsesOfWith(FromV->Val, ToV->Val);
+}
+
#ifndef NDEBUG
void User::dumpCommonHeader(raw_ostream &OS) const {
Value::dumpCommonHeader(OS);
@@ -325,10 +360,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
return It->second.get();
if (auto *C = dyn_cast<llvm::Constant>(LLVMV)) {
+ It->second = std::unique_ptr<Constant>(new Constant(C, *this));
+ auto *NewC = It->second.get();
for (llvm::Value *COp : C->operands())
getOrCreateValueInternal(COp, C);
- It->second = std::unique_ptr<Constant>(new Constant(C, *this));
- return It->second.get();
+ return NewC;
}
if (auto *Arg = dyn_cast<llvm::Argument>(LLVMV)) {
It->second = std::unique_ptr<Argument>(new Argument(Arg, *this));
diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
index 8d94639..4ff52eb 100644
--- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
@@ -525,7 +525,7 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) {
unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
unsigned PassthroughArgSize =
(F->isVarArg() ? 5 : Thunk->arg_size()) - ThunkArgOffset;
- assert(ArgTranslations.size() == F->isVarArg() ? 5 : PassthroughArgSize);
+ assert(ArgTranslations.size() == (F->isVarArg() ? 5 : PassthroughArgSize));
// Translate arguments to call.
SmallVector<Value *> Args;
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 333db1b..a288e7d 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1890,11 +1890,18 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
if (CE) {
int64_t Imm = CE->getValue();
if (isUInt<12>(Imm)) {
- auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
- // Accept an immediate representing a named or un-named Sys Reg
- // if the range is valid, regardless of the required features.
- Operands.push_back(
- RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
+ auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
+ // Accept an immediate representing a named Sys Reg if it satisfies the
+ // the required features.
+ for (auto &Reg : Range) {
+ if (Reg.haveRequiredFeatures(STI->getFeatureBits())) {
+ Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm));
+ return ParseStatus::Success;
+ }
+ }
+ // Accept an immediate representing an un-named Sys Reg if the range is
+ // valid, regardless of the required features.
+ Operands.push_back(RISCVOperand::createSysReg("", S, Imm));
return ParseStatus::Success;
}
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index 48b669c..d18ded2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -121,11 +121,14 @@ void RISCVInstPrinter::printCSRSystemRegister(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
unsigned Imm = MI->getOperand(OpNo).getImm();
- auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
- if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits()))
- markup(O, Markup::Register) << SysReg->Name;
- else
- markup(O, Markup::Register) << formatImm(Imm);
+ auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
+ for (auto &Reg : Range) {
+ if (Reg.haveRequiredFeatures(STI.getFeatureBits())) {
+ markup(O, Markup::Register) << Reg.Name;
+ return;
+ }
+ }
+ markup(O, Markup::Register) << formatImm(Imm);
}
void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
index db840b30..a836227 100644
--- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td
+++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
@@ -49,6 +49,7 @@ def SysRegsList : GenericTable {
let PrimaryKey = [ "Encoding" ];
let PrimaryKeyName = "lookupSysRegByEncoding";
+ let PrimaryKeyReturnRange = true;
}
def lookupSysRegByName : SearchIndex {
diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index 0b52d1e..9e4da5f 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -1248,6 +1248,7 @@ static void handleNoSuspendCoroutine(coro::Shape &Shape) {
}
CoroBegin->eraseFromParent();
+ Shape.CoroBegin = nullptr;
}
// SimplifySuspendPoint needs to check that there is no calls between
@@ -1970,9 +1971,17 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
}
/// Remove calls to llvm.coro.end in the original function.
-static void removeCoroEnds(const coro::Shape &Shape) {
- for (auto *End : Shape.CoroEnds) {
- replaceCoroEnd(End, Shape, Shape.FramePtr, /*in resume*/ false, nullptr);
+static void removeCoroEndsFromRampFunction(const coro::Shape &Shape) {
+ if (Shape.ABI != coro::ABI::Switch) {
+ for (auto *End : Shape.CoroEnds) {
+ replaceCoroEnd(End, Shape, Shape.FramePtr, /*in resume*/ false, nullptr);
+ }
+ } else {
+ for (llvm::AnyCoroEndInst *End : Shape.CoroEnds) {
+ auto &Context = End->getContext();
+ End->replaceAllUsesWith(ConstantInt::getFalse(Context));
+ End->eraseFromParent();
+ }
}
}
@@ -1981,18 +1990,6 @@ static void updateCallGraphAfterCoroutineSplit(
const SmallVectorImpl<Function *> &Clones, LazyCallGraph::SCC &C,
LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
FunctionAnalysisManager &FAM) {
- if (!Shape.CoroBegin)
- return;
-
- if (Shape.ABI != coro::ABI::Switch)
- removeCoroEnds(Shape);
- else {
- for (llvm::AnyCoroEndInst *End : Shape.CoroEnds) {
- auto &Context = End->getContext();
- End->replaceAllUsesWith(ConstantInt::getFalse(Context));
- End->eraseFromParent();
- }
- }
if (!Clones.empty()) {
switch (Shape.ABI) {
@@ -2120,6 +2117,7 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
const coro::Shape Shape =
splitCoroutine(F, Clones, FAM.getResult<TargetIRAnalysis>(F),
OptimizeFrame, MaterializableCallback);
+ removeCoroEndsFromRampFunction(Shape);
updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM);
ORE.emit([&]() {
diff --git a/llvm/test/MC/AsmParser/altmacro-arg.s b/llvm/test/MC/AsmParser/altmacro-arg.s
deleted file mode 100644
index 262c5ea..0000000
--- a/llvm/test/MC/AsmParser/altmacro-arg.s
+++ /dev/null
@@ -1,22 +0,0 @@
-## Arguments can be expanded even if they are not preceded by \
-# RUN: llvm-mc -triple=x86_64 %s | FileCheck %s
-
-# CHECK: 1 1 1a
-# CHECK-NEXT: 1 2 1a 2b
-# CHECK-NEXT: \$b \$b
-.altmacro
-.irp ._a,1
- .print "\._a \._a& ._a&a"
- .irp $b,2
- .print "\._a \$b ._a&a $b&b"
- .endr
- .print "\$b \$b&"
-.endr
-
-# CHECK: 1 1& ._a&a
-# CHECK-NEXT: \$b \$b&
-.noaltmacro
-.irp ._a,1
- .print "\._a \._a& ._a&a"
- .print "\$b \$b&"
-.endr
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 72e81bf..98c0052 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -122,6 +122,9 @@ define i32 @foo(i32 %v0, i32 %v1) {
BasicBlock *LLVMBB = &*LLVMF.begin();
auto LLVMBBIt = LLVMBB->begin();
Instruction *LLVMI0 = &*LLVMBBIt++;
+ Instruction *LLVMRet = &*LLVMBBIt++;
+ Argument *LLVMArg0 = LLVMF.getArg(0);
+ Argument *LLVMArg1 = LLVMF.getArg(1);
auto &F = *Ctx.createFunction(&LLVMF);
auto &BB = *F.begin();
@@ -203,6 +206,126 @@ OperandNo: 0
EXPECT_FALSE(I0->hasNUses(0u));
EXPECT_TRUE(I0->hasNUses(1u));
EXPECT_FALSE(I0->hasNUses(2u));
+
+ // Check User.setOperand().
+ Ret->setOperand(0, Arg0);
+ EXPECT_EQ(Ret->getOperand(0), Arg0);
+ EXPECT_EQ(Ret->getOperandUse(0).get(), Arg0);
+ EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg0);
+
+ Ret->setOperand(0, Arg1);
+ EXPECT_EQ(Ret->getOperand(0), Arg1);
+ EXPECT_EQ(Ret->getOperandUse(0).get(), Arg1);
+ EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg1);
+}
+
+TEST_F(SandboxIRTest, RUOW) {
+ parseIR(C, R"IR(
+declare void @bar0()
+declare void @bar1()
+
+@glob0 = global ptr @bar0
+@glob1 = global ptr @bar1
+
+define i32 @foo(i32 %arg0, i32 %arg1) {
+ %add0 = add i32 %arg0, %arg1
+ %gep1 = getelementptr i8, ptr @glob0, i32 1
+ %gep2 = getelementptr i8, ptr @glob1, i32 1
+ ret i32 %add0
+}
+)IR");
+ llvm::Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto &BB = *F.begin();
+ auto *Arg0 = F.getArg(0);
+ auto *Arg1 = F.getArg(1);
+ auto It = BB.begin();
+ auto *I0 = &*It++;
+ auto *I1 = &*It++;
+ auto *I2 = &*It++;
+ auto *Ret = &*It++;
+
+ bool Replaced;
+ // Try to replace an operand that doesn't match.
+ Replaced = I0->replaceUsesOfWith(Ret, Arg1);
+ EXPECT_FALSE(Replaced);
+ EXPECT_EQ(I0->getOperand(0), Arg0);
+ EXPECT_EQ(I0->getOperand(1), Arg1);
+
+ // Replace I0 operands when operands differ.
+ Replaced = I0->replaceUsesOfWith(Arg0, Arg1);
+ EXPECT_TRUE(Replaced);
+ EXPECT_EQ(I0->getOperand(0), Arg1);
+ EXPECT_EQ(I0->getOperand(1), Arg1);
+
+ // Replace I0 operands when operands are the same.
+ Replaced = I0->replaceUsesOfWith(Arg1, Arg0);
+ EXPECT_TRUE(Replaced);
+ EXPECT_EQ(I0->getOperand(0), Arg0);
+ EXPECT_EQ(I0->getOperand(1), Arg0);
+
+ // Replace Ret operand.
+ Replaced = Ret->replaceUsesOfWith(I0, Arg0);
+ EXPECT_TRUE(Replaced);
+ EXPECT_EQ(Ret->getOperand(0), Arg0);
+
+ // Check RAUW on constant.
+ auto *Glob0 = cast<sandboxir::Constant>(I1->getOperand(0));
+ auto *Glob1 = cast<sandboxir::Constant>(I2->getOperand(0));
+ auto *Glob0Op = Glob0->getOperand(0);
+ Glob0->replaceUsesOfWith(Glob0Op, Glob1);
+ EXPECT_EQ(Glob0->getOperand(0), Glob1);
+}
+
+TEST_F(SandboxIRTest, RAUW_RUWIf) {
+ parseIR(C, R"IR(
+define void @foo(ptr %ptr) {
+ %ld0 = load float, ptr %ptr
+ %ld1 = load float, ptr %ptr
+ store float %ld0, ptr %ptr
+ store float %ld0, ptr %ptr
+ ret void
+}
+)IR");
+ llvm::Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+ llvm::BasicBlock *LLVMBB = &*LLVMF.begin();
+
+ Ctx.createFunction(&LLVMF);
+ auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));
+ auto It = BB->begin();
+ sandboxir::Instruction *Ld0 = &*It++;
+ sandboxir::Instruction *Ld1 = &*It++;
+ sandboxir::Instruction *St0 = &*It++;
+ sandboxir::Instruction *St1 = &*It++;
+ // Check RUWIf when the lambda returns false.
+ Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; });
+ EXPECT_EQ(St0->getOperand(0), Ld0);
+ EXPECT_EQ(St1->getOperand(0), Ld0);
+ // Check RUWIf when the lambda returns true.
+ Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; });
+ EXPECT_EQ(St0->getOperand(0), Ld1);
+ EXPECT_EQ(St1->getOperand(0), Ld1);
+ St0->setOperand(0, Ld0);
+ St1->setOperand(0, Ld0);
+ // Check RUWIf user == St0.
+ Ld0->replaceUsesWithIf(
+ Ld1, [St0](const sandboxir::Use &Use) { return Use.getUser() == St0; });
+ EXPECT_EQ(St0->getOperand(0), Ld1);
+ EXPECT_EQ(St1->getOperand(0), Ld0);
+ St0->setOperand(0, Ld0);
+ // Check RUWIf user == St1.
+ Ld0->replaceUsesWithIf(
+ Ld1, [St1](const sandboxir::Use &Use) { return Use.getUser() == St1; });
+ EXPECT_EQ(St0->getOperand(0), Ld0);
+ EXPECT_EQ(St1->getOperand(0), Ld1);
+ St1->setOperand(0, Ld0);
+ // Check RAUW.
+ Ld1->replaceAllUsesWith(Ld0);
+ EXPECT_EQ(St0->getOperand(0), Ld0);
+ EXPECT_EQ(St1->getOperand(0), Ld0);
}
// Check that the operands/users are counted correctly.