diff options
author | vporpo <vporpodas@google.com> | 2024-07-11 21:52:11 -0700 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2024-07-11 21:52:11 -0700 |
commit | c86c98e21b7e48b95bfc40790250e270add23fcd (patch) | |
tree | e95a05be99cf7f951d36524ebd17f93a651cdd98 | |
parent | 8ed26eae8785da1b96fde4b6b290b18c859980a1 (diff) | |
parent | ecd2bf73cb212452951b3010bbf06e4d96330a92 (diff) | |
download | llvm-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]
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. |