[llvm-branch-commits] [clang] [clang-tools-extra] [flang] [lld] [llvm] [ADT] Adopt SmallVectorWithFlags in padding-saving records (PR #233622)

Mehdi Amini via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Oct 19 16:08:44 PDT 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/233622

Pack boolean and small-bitfield state into SmallVectorWithFlags across 464 records in LLVM, Clang, MLIR, Flang, LLD, LLDB, BOLT, Polly, and clang-tools-extra. Preserve inline capacities, initial flag values, payload-only comparisons, and existing copy and move behavior. Remove redundant state where doing so provides the same layout improvement.

Add ordinary-vector construction and payload move assignment support. Use ArrayRef for read-only vector interfaces and explicit payload transfers where existing mutable SmallVectorImpl interfaces need ordinary vectors. Add regression tests for flag retention during vector growth, copy, move, serialization, and calling-convention lowering.

Assisted-by: Codex

>From 58fb3700094aa94e6fc0d84754402379d4c27dda Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Mon, 19 Oct 2026 15:40:16 -0700
Subject: [PATCH] [ADT] Adopt SmallVectorWithFlags in padding-saving records

Pack boolean and small-bitfield state into SmallVectorWithFlags across
464 records in LLVM, Clang, MLIR, Flang, LLD, LLDB, BOLT, Polly, and
clang-tools-extra. Preserve inline capacities, initial flag values,
payload-only comparisons, and existing copy and move behavior. Remove
redundant state where doing so provides the same layout improvement.

Add ordinary-vector construction and payload move assignment support.
Use ArrayRef for read-only vector interfaces and explicit payload transfers
where existing mutable SmallVectorImpl interfaces need ordinary vectors.
Add regression tests for flag retention during vector growth, copy, move,
serialization, and calling-convention lowering.

Leave ELFObjectFile lazy caches separate from immutable flags to preserve
independent const access. Leave generated AffineVectorizeOptions unchanged
because its public aggregate contract needs a separate generator change.

Validation: Clang unit tests, check-lld, 21 selected unit-test binaries,
all-target syntax and layout checks, and focused LLVM, Clang, MLIR, Flang,
and BOLT lit tests. The final calling-convention checks passed 336 tests.

Assisted-by: Codex
---
 bolt/include/bolt/Core/BinaryFunction.h       | 136 +++---
 bolt/include/bolt/Core/DebugData.h            |  10 +-
 bolt/include/bolt/Core/DebugNames.h           |  11 +-
 bolt/include/bolt/Profile/DataAggregator.h    |  23 +-
 bolt/lib/Core/BinaryFunction.cpp              |   4 +-
 bolt/lib/Core/DebugData.cpp                   |   7 +-
 bolt/lib/Core/DebugNames.cpp                  |  18 +-
 bolt/lib/Profile/DataAggregator.cpp           |  26 +-
 bolt/lib/Profile/DataReader.cpp               |   2 +-
 bolt/lib/Rewrite/RewriteInstance.cpp          |   2 +-
 bolt/unittests/Core/BinaryContext.cpp         |  20 +
 clang-tools-extra/clang-move/Move.cpp         |   4 +-
 clang-tools-extra/clang-move/Move.h           |   9 +-
 .../clang-move/tool/ClangMove.cpp             |   6 +-
 .../clang-tidy/boost/UseRangesCheck.cpp       |  13 +-
 .../bugprone/AssertSideEffectCheck.cpp        |  19 +-
 .../bugprone/AssertSideEffectCheck.h          |  11 +-
 .../clang-tidy/modernize/AvoidBindCheck.cpp   |  12 +-
 .../clang-tidy/modernize/LoopConvertCheck.cpp |  14 +-
 .../clang-tidy/modernize/LoopConvertCheck.h   |   7 +-
 .../clang-tidy/modernize/LoopConvertUtils.cpp |  22 +-
 .../clang-tidy/modernize/LoopConvertUtils.h   |  30 +-
 .../clang-tidy/modernize/UseNullptrCheck.cpp  |  13 +-
 .../clang-tidy/modernize/UseNullptrCheck.h    |  11 +-
 .../readability/MagicNumbersCheck.cpp         |  54 ++-
 .../readability/MagicNumbersCheck.h           |  33 +-
 .../readability/NamespaceCommentCheck.cpp     |  12 +-
 .../readability/NamespaceCommentCheck.h       |   5 +-
 .../clangd/SystemIncludeExtractor.cpp         |  42 +-
 .../modularize/ModularizeUtilities.cpp        |   2 +-
 .../modularize/PreprocessorTracker.cpp        |  29 +-
 .../unittests/clang-move/ClangMoveTests.cpp   |   4 +-
 clang/include/clang/AST/ASTConcept.h          |  10 +-
 clang/include/clang/AST/ASTContext.h          |  23 +-
 clang/include/clang/AST/ExprConcepts.h        |   2 +-
 clang/include/clang/AST/VTTBuilder.h          |  10 +-
 .../Analysis/Analyses/LifetimeSafety/Facts.h  |  13 +-
 .../Analyses/LifetimeSafety/FactsGenerator.h  |  11 +-
 clang/include/clang/Basic/Attr.td             |   4 +-
 clang/include/clang/Basic/Module.h            | 142 ++++--
 clang/include/clang/Basic/OpenMPKinds.h       |  15 +-
 clang/include/clang/Basic/Sarif.h             |   6 +-
 clang/include/clang/Basic/SourceManager.h     |  31 +-
 clang/include/clang/CodeGen/CodeGenAction.h   |   6 +-
 .../clang/CodeGen/ConstantInitBuilder.h       |  23 +-
 .../include/clang/CodeGen/SwiftCallingConv.h  |   8 +-
 .../DependencyScanning/DependencyGraph.h      |  15 +-
 clang/include/clang/Driver/Action.h           |  22 +-
 clang/include/clang/Driver/Driver.h           |  13 +-
 clang/include/clang/Driver/OffloadBundler.h   |  34 +-
 .../clang/Driver/RocmInstallationDetector.h   |  14 +-
 clang/include/clang/Driver/ToolChain.h        |   6 +-
 clang/include/clang/Edit/Commit.h             |   8 +-
 .../Serialization/SymbolGraphSerializer.h     |  23 +-
 clang/include/clang/Frontend/ASTUnit.h        |  29 +-
 clang/include/clang/Lex/Lexer.h               |   4 +-
 clang/include/clang/Lex/ModuleMap.h           |  16 +-
 clang/include/clang/Lex/ModuleMapFile.h       |  11 +-
 clang/include/clang/Lex/Preprocessor.h        | 159 +++++--
 clang/include/clang/Lex/PreprocessorLexer.h   |  24 +-
 clang/include/clang/Parse/Parser.h            |  67 ++-
 .../clang/Parse/RAIIObjectsForParser.h        |  14 +-
 clang/include/clang/Sema/DeclSpec.h           |  27 +-
 clang/include/clang/Sema/ScopeInfo.h          |  37 +-
 clang/include/clang/Sema/Sema.h               | 231 +++++++---
 clang/include/clang/Sema/SemaHLSL.h           |  10 +-
 clang/include/clang/Sema/SemaInternal.h       |  22 +-
 clang/include/clang/Sema/Template.h           |  50 ++-
 clang/include/clang/Sema/TemplateDeduction.h  |  14 +-
 clang/include/clang/Serialization/ASTReader.h |  78 +++-
 clang/include/clang/Serialization/ASTWriter.h |  51 ++-
 .../include/clang/Serialization/ModuleFile.h  |  19 +-
 .../Serialization/PCHContainerOperations.h    |   6 +-
 .../Core/BugReporter/BugReporter.h            |  10 +-
 .../StaticAnalyzer/Core/CheckerManager.h      |   8 +-
 .../clang/Tooling/Inclusions/HeaderIncludes.h |   6 +-
 .../clang/Tooling/Refactoring/ASTSelection.h  |  15 +-
 clang/lib/APINotes/APINotesManager.cpp        |  14 +-
 clang/lib/AST/ASTConcept.cpp                  |   4 +-
 clang/lib/AST/ASTContext.cpp                  |   8 +-
 clang/lib/AST/ASTImporter.cpp                 |   6 +-
 clang/lib/AST/AttrImpl.cpp                    |   2 +-
 clang/lib/AST/Availability.cpp                |  36 +-
 clang/lib/AST/ByteCode/Disasm.cpp             |  20 +-
 clang/lib/AST/ByteCode/Interp.h               |   4 +-
 clang/lib/AST/ByteCode/InterpState.cpp        |  13 +-
 clang/lib/AST/ByteCode/InterpState.h          |  13 +-
 clang/lib/AST/CommentParser.cpp               |  16 +-
 clang/lib/AST/ExprConstant.cpp                |  34 +-
 clang/lib/AST/MicrosoftMangle.cpp             |  45 +-
 clang/lib/AST/OpenMPClause.cpp                |   8 +-
 clang/lib/AST/RecordLayoutBuilder.cpp         |  77 ++--
 clang/lib/AST/VTTBuilder.cpp                  |  10 +-
 clang/lib/AST/VTableBuilder.cpp               |  34 +-
 clang/lib/Analysis/CFG.cpp                    |  26 +-
 clang/lib/Analysis/CalledOnceCheck.cpp        |  41 +-
 .../LifetimeSafety/FactsGenerator.cpp         |   9 +-
 clang/lib/Basic/Module.cpp                    |  68 +--
 clang/lib/Basic/Sarif.cpp                     |  13 +-
 clang/lib/Basic/SourceManager.cpp             |  14 +-
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp          |   8 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      |  12 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |  35 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |  12 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h          |   8 +-
 .../CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp |  74 ++--
 clang/lib/CIR/CodeGen/CIRGenVTables.cpp       |   2 +-
 .../Transforms/CallConvLoweringPass.cpp       |   4 +-
 clang/lib/CodeGen/BackendConsumer.h           |   6 +-
 clang/lib/CodeGen/CGBuiltin.cpp               |   6 +-
 clang/lib/CodeGen/CGCUDANV.cpp                |  36 +-
 clang/lib/CodeGen/CGCall.cpp                  |   6 +-
 clang/lib/CodeGen/CGClass.cpp                 |  18 +-
 clang/lib/CodeGen/CGCleanup.h                 |  10 +-
 clang/lib/CodeGen/CGCoroutine.cpp             |   2 +-
 clang/lib/CodeGen/CGDebugInfo.cpp             |   8 +-
 clang/lib/CodeGen/CGDecl.cpp                  |  14 +-
 clang/lib/CodeGen/CGDeclCXX.cpp               |   4 +-
 clang/lib/CodeGen/CGException.cpp             |   4 +-
 clang/lib/CodeGen/CGExpr.cpp                  |  12 +-
 clang/lib/CodeGen/CGExprConstant.cpp          |  22 +-
 clang/lib/CodeGen/CGExprScalar.cpp            |   2 +-
 clang/lib/CodeGen/CGObjC.cpp                  |   8 +-
 clang/lib/CodeGen/CGObjCMac.cpp               |  25 +-
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |  56 +--
 clang/lib/CodeGen/CGOpenMPRuntime.h           |  75 +++-
 clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp      |   2 +-
 clang/lib/CodeGen/CGRecordLayoutBuilder.cpp   |  67 +--
 clang/lib/CodeGen/CGStmt.cpp                  |  27 +-
 clang/lib/CodeGen/CGStmtOpenMP.cpp            |  58 +--
 clang/lib/CodeGen/CGVTables.cpp               |   4 +-
 clang/lib/CodeGen/CodeGenAction.cpp           |  62 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp         |  31 +-
 clang/lib/CodeGen/CodeGenFunction.h           |  70 ++-
 clang/lib/CodeGen/CodeGenModule.cpp           |  24 +-
 clang/lib/CodeGen/CodeGenModule.h             |  15 +-
 clang/lib/CodeGen/CodeGenPGO.cpp              |  54 +--
 clang/lib/CodeGen/ConstantEmitter.h           |  14 +-
 clang/lib/CodeGen/ConstantInitBuilder.cpp     |   2 +-
 clang/lib/CodeGen/ItaniumCXXABI.cpp           |  57 +--
 clang/lib/CodeGen/MicrosoftCXXABI.cpp         |   4 +-
 .../CodeGen/ObjectFilePCHContainerWriter.cpp  |   4 +-
 clang/lib/CodeGen/SwiftCallingConv.cpp        |  14 +-
 clang/lib/CodeGen/TargetBuiltins/ARM.cpp      |   6 +-
 clang/lib/CodeGen/Targets/Sparc.cpp           |  19 +-
 clang/lib/CodeGen/VarBypassDetector.cpp       |   6 +-
 clang/lib/CodeGen/VarBypassDetector.h         |   9 +-
 .../DependencyScanning/ModuleDepCollector.cpp |  38 +-
 clang/lib/Driver/Compilation.cpp              |  12 +-
 clang/lib/Driver/CreateASTUnitFromArgs.cpp    |   4 +-
 clang/lib/Driver/Driver.cpp                   |  36 +-
 clang/lib/Driver/OffloadBundler.cpp           |  40 +-
 clang/lib/Driver/ToolChain.cpp                |   7 +-
 clang/lib/Driver/ToolChains/AMDGPU.cpp        |  16 +-
 clang/lib/Driver/ToolChains/Hexagon.cpp       |   6 +-
 clang/lib/Driver/ToolChains/Hexagon.h         |   5 +-
 clang/lib/Edit/Commit.cpp                     |  20 +-
 .../Serialization/SymbolGraphSerializer.cpp   |  15 +-
 clang/lib/Format/AffectedRangeManager.cpp     |   8 +-
 clang/lib/Format/AffectedRangeManager.h       |   4 +-
 clang/lib/Format/ContinuationIndenter.cpp     |  22 +-
 clang/lib/Format/ContinuationIndenter.h       |  32 +-
 clang/lib/Format/Format.cpp                   |  50 ++-
 clang/lib/Format/FormatToken.cpp              |   4 +-
 clang/lib/Format/FormatToken.h                |  14 +-
 clang/lib/Format/FormatTokenLexer.cpp         |  32 +-
 clang/lib/Format/FormatTokenLexer.h           |  12 +-
 clang/lib/Format/MacroCallReconstructor.cpp   |   8 +-
 clang/lib/Format/QualifierAlignmentFixer.cpp  |   8 +-
 clang/lib/Format/QualifierAlignmentFixer.h    |   8 +-
 clang/lib/Format/SortJavaScriptImports.cpp    |  60 +--
 clang/lib/Format/TokenAnnotator.cpp           |  86 ++--
 clang/lib/Format/TokenAnnotator.h             |  36 +-
 clang/lib/Format/UnwrappedLineFormatter.cpp   |  11 +-
 clang/lib/Format/UnwrappedLineParser.cpp      |  72 ++--
 clang/lib/Format/UnwrappedLineParser.h        |  22 +-
 clang/lib/Format/WhitespaceManager.cpp        |   8 +-
 clang/lib/Format/WhitespaceManager.h          |  11 +-
 clang/lib/Frontend/ASTUnit.cpp                |  20 +-
 clang/lib/Frontend/ChainedIncludesSource.cpp  |   2 +-
 clang/lib/Frontend/CompilerInstance.cpp       |  15 +-
 clang/lib/Frontend/FrontendAction.cpp         |  19 +-
 clang/lib/Frontend/HeaderIncludeGen.cpp       |  11 +-
 clang/lib/Frontend/PrecompiledPreamble.cpp    |   2 +-
 .../Frontend/SerializedDiagnosticPrinter.cpp  |  19 +-
 clang/lib/Index/IndexTypeSourceInfo.cpp       |  21 +-
 clang/lib/Lex/DependencyDirectivesScanner.cpp |  16 +-
 clang/lib/Lex/HeaderSearch.cpp                |   5 +-
 clang/lib/Lex/Lexer.cpp                       |  91 ++--
 clang/lib/Lex/MacroArgs.cpp                   |  10 +-
 clang/lib/Lex/ModuleMap.cpp                   | 128 +++---
 clang/lib/Lex/ModuleMapFile.cpp               |  21 +-
 clang/lib/Lex/PPDirectives.cpp                |  97 +++--
 clang/lib/Lex/PPExpressions.cpp               |  10 +-
 clang/lib/Lex/PPLexerChange.cpp               |  10 +-
 clang/lib/Lex/PPMacroExpansion.cpp            |   2 +-
 clang/lib/Lex/Pragma.cpp                      |  42 +-
 clang/lib/Lex/Preprocessor.cpp                |  64 +--
 clang/lib/Lex/PreprocessorLexer.cpp           |   8 +-
 clang/lib/Parse/ParseCXXInlineMethods.cpp     |   8 +-
 clang/lib/Parse/ParseDecl.cpp                 |  11 +-
 clang/lib/Parse/ParseDeclCXX.cpp              |  23 +-
 clang/lib/Parse/ParseExpr.cpp                 |  13 +-
 clang/lib/Parse/ParseExprCXX.cpp              |  17 +-
 clang/lib/Parse/ParseObjc.cpp                 |  11 +-
 clang/lib/Parse/ParseOpenACC.cpp              |  19 +-
 clang/lib/Parse/ParseOpenMP.cpp               |  10 +-
 clang/lib/Parse/ParseStmt.cpp                 |   6 +-
 clang/lib/Parse/ParseTemplate.cpp             |   4 +-
 clang/lib/Parse/ParseTentative.cpp            |   2 +-
 clang/lib/Parse/Parser.cpp                    |  11 +-
 clang/lib/Sema/CoroutineStmtBuilder.h         |  10 +-
 clang/lib/Sema/JumpDiagnostics.cpp            |  11 +-
 clang/lib/Sema/ScopeInfo.cpp                  |   2 +-
 clang/lib/Sema/Sema.cpp                       |  28 +-
 clang/lib/Sema/SemaAccess.cpp                 |  44 +-
 clang/lib/Sema/SemaAttr.cpp                   |  12 +-
 clang/lib/Sema/SemaAvailability.cpp           |   2 +-
 clang/lib/Sema/SemaBase.cpp                   |   4 +-
 clang/lib/Sema/SemaCUDA.cpp                   |   4 +-
 clang/lib/Sema/SemaChecking.cpp               |  16 +-
 clang/lib/Sema/SemaConcept.cpp                |  83 ++--
 clang/lib/Sema/SemaCoroutine.cpp              |  41 +-
 clang/lib/Sema/SemaDecl.cpp                   |  21 +-
 clang/lib/Sema/SemaDeclCXX.cpp                |  35 +-
 clang/lib/Sema/SemaExpr.cpp                   | 117 +++--
 clang/lib/Sema/SemaExprCXX.cpp                |  60 +--
 clang/lib/Sema/SemaHLSL.cpp                   |  42 +-
 clang/lib/Sema/SemaLambda.cpp                 |  38 +-
 clang/lib/Sema/SemaLifetimeSafety.h           |  10 +-
 clang/lib/Sema/SemaLookup.cpp                 |  14 +-
 clang/lib/Sema/SemaModule.cpp                 |   8 +-
 clang/lib/Sema/SemaOpenMP.cpp                 | 107 +++--
 clang/lib/Sema/SemaOverload.cpp               |  92 ++--
 clang/lib/Sema/SemaPseudoObject.cpp           |  12 +-
 clang/lib/Sema/SemaSYCL.cpp                   |  10 +-
 clang/lib/Sema/SemaStmt.cpp                   |  12 +-
 clang/lib/Sema/SemaTemplate.cpp               | 102 +++--
 clang/lib/Sema/SemaTemplateDeduction.cpp      | 114 +++--
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |  16 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  48 ++-
 clang/lib/Sema/SemaTemplateVariadic.cpp       |   2 +-
 clang/lib/Sema/SemaType.cpp                   |  41 +-
 clang/lib/Sema/TreeTransform.h                |  62 +--
 clang/lib/Serialization/ASTReader.cpp         | 117 ++---
 clang/lib/Serialization/ASTReaderDecl.cpp     |  13 +-
 clang/lib/Serialization/ASTReaderStmt.cpp     |   6 +-
 clang/lib/Serialization/ASTWriter.cpp         | 176 ++++----
 clang/lib/Serialization/ASTWriterDecl.cpp     |   2 +-
 clang/lib/Serialization/GeneratePCH.cpp       |  12 +-
 .../Serialization/PCHContainerOperations.cpp  |   6 +-
 .../Checkers/CallAndMessageChecker.cpp        |  31 +-
 .../Checkers/LocalizationChecker.cpp          |  32 +-
 .../Checkers/StackAddrEscapeChecker.cpp       |  11 +-
 .../lib/Tooling/Inclusions/HeaderIncludes.cpp |  19 +-
 .../ClangOffloadBundler.cpp                   |  20 +-
 clang/tools/clang-scan-deps/ClangScanDeps.cpp |  11 +-
 clang/tools/driver/cc1as_main.cpp             |  22 +-
 clang/tools/driver/driver.cpp                 |   4 +-
 clang/tools/libclang/CIndex.cpp               |  38 +-
 clang/tools/libclang/CursorVisitor.h          |  26 +-
 clang/tools/libclang/Indexing.cpp             |  14 +-
 clang/utils/TableGen/ClangAttrEmitter.cpp     |  12 +-
 clang/utils/TableGen/HLSLEmitter.cpp          |  38 +-
 clang/utils/TableGen/NeonEmitter.cpp          |  48 ++-
 clang/utils/TableGen/SveEmitter.cpp           |  12 +-
 flang/include/flang/Lower/CallInterface.h     |   7 +-
 flang/include/flang/Lower/PFTBuilder.h        |  48 ++-
 .../flang/Optimizer/Analysis/AliasAnalysis.h  |  48 ++-
 .../Optimizer/Builder/TemporaryStorage.h      |  11 +-
 flang/lib/Lower/Bridge.cpp                    |  95 ++--
 flang/lib/Lower/CallInterface.cpp             |   4 +-
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  26 +-
 .../lib/Lower/OpenMP/DataSharingProcessor.cpp |  25 +-
 flang/lib/Lower/OpenMP/DataSharingProcessor.h |  36 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  62 ++-
 flang/lib/Lower/PFTBuilder.cpp                |  66 +--
 .../Lower/Support/PrivateReductionUtils.cpp   |  64 +--
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  69 +--
 .../Optimizer/Builder/TemporaryStorage.cpp    |  13 +-
 .../LowerHLFIROrderedAssignments.cpp          |  16 +-
 .../Transforms/ScheduleOrderedAssignments.cpp |  51 ++-
 .../lib/Optimizer/Transforms/FIRToMemRef.cpp  |  18 +-
 .../Optimizer/AliasAnalysisCacheTest.cpp      |  19 +
 lld/COFF/Chunks.cpp                           |   4 +-
 lld/COFF/Config.h                             |  83 +++-
 lld/COFF/DebugTypes.cpp                       |   2 +-
 lld/COFF/Driver.cpp                           |  94 ++--
 lld/COFF/DriverUtils.cpp                      |   4 +-
 lld/COFF/InputFiles.cpp                       |   4 +-
 lld/COFF/LTO.cpp                              |  14 +-
 lld/COFF/MapFile.cpp                          |   2 +-
 lld/COFF/SymbolTable.cpp                      |   2 +-
 lld/COFF/Symbols.cpp                          |   2 +-
 lld/COFF/Writer.cpp                           |   6 +-
 lld/ELF/Arch/AArch64.cpp                      |  18 +-
 lld/ELF/Arch/ARM.cpp                          |  11 +-
 lld/ELF/Arch/LoongArch.cpp                    |  44 +-
 lld/ELF/Arch/Mips.cpp                         |  30 +-
 lld/ELF/Arch/MipsArchTree.cpp                 |   4 +-
 lld/ELF/Arch/PPC.cpp                          |  16 +-
 lld/ELF/Arch/PPC64.cpp                        |  34 +-
 lld/ELF/Arch/RISCV.cpp                        |  38 +-
 lld/ELF/Arch/SPARCV9.cpp                      |   2 +-
 lld/ELF/Arch/SystemZ.cpp                      |   6 +-
 lld/ELF/Arch/X86.cpp                          |  16 +-
 lld/ELF/Arch/X86_64.cpp                       |  26 +-
 lld/ELF/Config.h                              | 385 ++++++++++++-----
 lld/ELF/DWARF.cpp                             |   2 +-
 lld/ELF/Driver.cpp                            | 404 +++++++++---------
 lld/ELF/ICF.cpp                               |   6 +-
 lld/ELF/InputFiles.cpp                        |  57 +--
 lld/ELF/InputFiles.h                          |  25 +-
 lld/ELF/InputSection.cpp                      |  35 +-
 lld/ELF/LTO.cpp                               |  36 +-
 lld/ELF/LinkerScript.cpp                      |  70 +--
 lld/ELF/LinkerScript.h                        |  33 +-
 lld/ELF/MapFile.cpp                           |   8 +-
 lld/ELF/MarkLive.cpp                          |   9 +-
 lld/ELF/OutputSections.cpp                    |  56 +--
 lld/ELF/OutputSections.h                      |  68 ++-
 lld/ELF/RelocScan.h                           |  14 +-
 lld/ELF/Relocations.cpp                       |  44 +-
 lld/ELF/ScriptParser.cpp                      |  48 ++-
 lld/ELF/SymbolTable.cpp                       |   4 +-
 lld/ELF/Symbols.cpp                           |  15 +-
 lld/ELF/SyntheticSections.cpp                 | 172 ++++----
 lld/ELF/SyntheticSections.h                   |  35 +-
 lld/ELF/Target.cpp                            |   4 +-
 lld/ELF/Thunks.cpp                            |  32 +-
 lld/ELF/Writer.cpp                            | 154 +++----
 lld/MachO/Config.h                            | 110 +++--
 lld/MachO/Driver.cpp                          | 154 ++++---
 lld/MachO/DriverUtils.cpp                     |   2 +-
 lld/MachO/InputFiles.cpp                      |  28 +-
 lld/MachO/InputFiles.h                        |  30 +-
 lld/MachO/InputSection.cpp                    |   2 +-
 lld/MachO/LTO.cpp                             |   6 +-
 lld/MachO/SectionPriorities.cpp               |  18 +-
 lld/MachO/Symbols.h                           |   2 +-
 lld/MachO/SyntheticSections.cpp               |   8 +-
 lld/MachO/Writer.cpp                          |  18 +-
 lld/wasm/Config.h                             |  62 ++-
 lld/wasm/Driver.cpp                           |  79 ++--
 lld/wasm/InputChunks.cpp                      |   8 +-
 lld/wasm/InputChunks.h                        |   5 +-
 lld/wasm/InputElement.h                       |   2 +-
 lld/wasm/InputFiles.cpp                       |   2 +-
 lld/wasm/InputFiles.h                         |   2 +-
 lld/wasm/LTO.cpp                              |   4 +-
 lld/wasm/MarkLive.cpp                         |   4 +-
 lld/wasm/OutputSections.cpp                   |   6 +-
 lld/wasm/OutputSegment.h                      |   2 +-
 lld/wasm/Relocations.cpp                      |   4 +-
 lld/wasm/SymbolTable.cpp                      |  12 +-
 lld/wasm/Symbols.cpp                          |   2 +-
 lld/wasm/Symbols.h                            |   8 +-
 lld/wasm/SyntheticSections.cpp                |  16 +-
 lld/wasm/SyntheticSections.h                  |   2 +-
 lld/wasm/Writer.cpp                           |  63 +--
 lldb/include/lldb/Core/FormatEntity.h         |  25 +-
 lldb/source/Core/Disassembler.cpp             |   2 +-
 lldb/source/Core/FormatEntity.cpp             |  16 +-
 .../Clang/ClangASTImporter.cpp                |   4 +-
 .../MacOSX/PlatformAppleSimulator.cpp         |   4 +-
 .../Platform/MacOSX/PlatformAppleSimulator.h  |  10 +-
 .../DWARF/SymbolFileDWARFDebugMap.cpp         |   4 +-
 .../DWARF/SymbolFileDWARFDebugMap.h           |  10 +-
 llvm/include/llvm/ADT/GenericUniformityImpl.h |  14 +-
 llvm/include/llvm/ADT/SmallVectorWithFlags.h  |  61 +++
 llvm/include/llvm/Analysis/AliasAnalysis.h    |  26 +-
 llvm/include/llvm/Analysis/AssumptionCache.h  |  12 +-
 .../llvm/Analysis/BasicAliasAnalysis.h        |   2 +-
 .../llvm/Analysis/BlockFrequencyInfoImpl.h    |  38 +-
 .../llvm/Analysis/GenericDomTreeUpdater.h     |   7 +-
 .../llvm/Analysis/GenericDomTreeUpdaterImpl.h |   8 +-
 .../llvm/Analysis/LoopAccessAnalysis.h        |  33 +-
 .../include/llvm/Analysis/LoopCacheAnalysis.h |   8 +-
 llvm/include/llvm/Analysis/PtrUseVisitor.h    |  15 +-
 llvm/include/llvm/Analysis/ScalarEvolution.h  |  13 +-
 .../llvm/Analysis/TargetTransformInfo.h       |  18 +-
 .../ImportedFunctionsInliningStatistics.h     |   9 +-
 llvm/include/llvm/AsmParser/LLParser.h        |  18 +-
 llvm/include/llvm/Bitstream/BitstreamWriter.h |   8 +
 llvm/include/llvm/CGData/StableFunctionMap.h  |  14 +-
 .../llvm/CGData/StableFunctionMapRecord.h     |   2 +-
 llvm/include/llvm/CodeGen/AsmPrinter.h        |  38 +-
 llvm/include/llvm/CodeGen/CallingConvLower.h  |  57 +--
 .../llvm/CodeGen/GlobalISel/CallLowering.h    |   9 +-
 .../llvm/CodeGen/GlobalISel/GISelWorkList.h   |  18 +-
 llvm/include/llvm/CodeGen/LexicalScopes.h     |  14 +-
 llvm/include/llvm/CodeGen/LiveIntervalUnion.h |  24 +-
 llvm/include/llvm/CodeGen/MachineBasicBlock.h |  29 +-
 llvm/include/llvm/CodeGen/MachineFrameInfo.h  |  17 +-
 llvm/include/llvm/CodeGen/MachineFunction.h   |  39 +-
 llvm/include/llvm/CodeGen/MachinePipeliner.h  |   5 +-
 .../llvm/CodeGen/MachineRegisterInfo.h        |  12 +-
 llvm/include/llvm/CodeGen/MachineScheduler.h  |  20 +-
 llvm/include/llvm/CodeGen/Rematerializer.h    |   6 +-
 llvm/include/llvm/CodeGen/ScheduleDAG.h       |   8 +-
 llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h |  22 +-
 llvm/include/llvm/CodeGen/SelectionDAG.h      |  19 +
 .../llvm/CodeGen/SwitchLoweringUtils.h        |  19 +-
 llvm/include/llvm/CodeGen/TargetLowering.h    | 122 +++---
 llvm/include/llvm/CodeGen/TargetSchedule.h    |   9 +-
 llvm/include/llvm/DTLTO/DTLTO.h               |  22 +-
 .../llvm/DWARFLinker/Classic/DWARFLinker.h    |  23 +-
 llvm/include/llvm/DebugInfo/DIContext.h       |  10 +-
 .../llvm/DebugInfo/DWARF/DWARFDebugMacro.h    |   6 +-
 .../DWARF/LowLevel/DWARFExpression.h          |  19 +-
 .../llvm/ExecutionEngine/ExecutionEngine.h    |  57 ++-
 .../Orc/TargetProcess/LibraryScanner.h        |   9 +-
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       |  38 +-
 llvm/include/llvm/IR/DIBuilder.h              |   5 +-
 llvm/include/llvm/IR/DataLayout.h             |  13 +-
 llvm/include/llvm/IR/DroppedVariableStats.h   |  15 +-
 llvm/include/llvm/IR/LegacyPassManagers.h     |   4 +-
 llvm/include/llvm/IR/PassTimingInfo.h         |   9 +-
 llvm/include/llvm/LTO/LTO.h                   |  33 +-
 llvm/include/llvm/MC/DXContainerInfo.h        |  13 +-
 llvm/include/llvm/MC/DXContainerPSVInfo.h     |  17 +-
 llvm/include/llvm/MC/MCAssembler.h            |  21 +-
 llvm/include/llvm/MC/MCCodeView.h             |   6 +-
 llvm/include/llvm/MC/MCContext.h              |  20 +-
 llvm/include/llvm/MC/MCDwarf.h                |  38 +-
 llvm/include/llvm/MC/MCELFStreamer.h          |  18 +-
 llvm/include/llvm/MC/MCInstPrinter.h          |  15 +-
 llvm/include/llvm/MC/MCObjectStreamer.h       |  17 +-
 llvm/include/llvm/MC/MCObjectWriter.h         |  14 +-
 llvm/include/llvm/MC/MCParser/AsmLexer.h      |   7 +-
 llvm/include/llvm/MC/MCParser/MCAsmParser.h   |  22 +-
 llvm/include/llvm/MCA/Instruction.h           |  18 +-
 llvm/include/llvm/ObjCopy/CommonConfig.h      |  67 ++-
 llvm/include/llvm/ObjCopy/ELF/ELFConfig.h     |  15 +-
 llvm/include/llvm/Object/MachO.h              |  12 +-
 llvm/include/llvm/Object/OffloadBundle.h      |  16 +-
 .../include/llvm/ObjectYAML/DXContainerYAML.h |  16 +-
 llvm/include/llvm/Option/OptTable.h           |  14 +-
 llvm/include/llvm/PassAnalysisSupport.h       |  14 +-
 .../include/llvm/ProfileData/DataAccessProf.h |  10 +-
 llvm/include/llvm/ProfileData/GCOV.h          |   8 +-
 .../llvm/ProfileData/InstrProfWriter.h        |  33 +-
 llvm/include/llvm/ProfileData/MemProfReader.h |  14 +-
 .../llvm/ProfileData/SampleProfWriter.h       |  28 +-
 llvm/include/llvm/SandboxIR/Tracker.h         |  17 +-
 llvm/include/llvm/Support/CFGDiff.h           |  11 +-
 llvm/include/llvm/Support/CFGUpdate.h         |   5 +-
 llvm/include/llvm/Support/DebugCounter.h      |  27 +-
 llvm/include/llvm/Support/GenericDomTree.h    |  27 +-
 .../llvm/Support/GenericDomTreeConstruction.h |  13 +-
 llvm/include/llvm/Support/GlobPattern.h       |  12 +-
 llvm/include/llvm/Support/LSP/Transport.h     |  16 +-
 llvm/include/llvm/Support/SuffixTree.h        |  15 +-
 llvm/include/llvm/Support/YAMLTraits.h        |  13 +
 llvm/include/llvm/Transforms/IPO/Attributor.h |  21 +-
 .../llvm/Transforms/IPO/Instrumentor.h        |   9 +-
 .../llvm/Transforms/Scalar/ConstantHoisting.h |   6 +-
 llvm/include/llvm/Transforms/Utils/Cloning.h  |  11 +-
 .../llvm/Transforms/Utils/CodeExtractor.h     |  25 +-
 .../Utils/LockstepReverseIterator.h           |  29 +-
 .../include/llvm/Transforms/Utils/LoopUtils.h |   9 +-
 .../Transforms/Utils/MemoryTaggingSupport.h   |   8 +-
 .../Utils/ScalarEvolutionExpander.h           |  32 +-
 .../Vectorize/LoopVectorizationLegality.h     |  28 +-
 llvm/lib/Analysis/AssumptionCache.cpp         |   6 +-
 llvm/lib/Analysis/BasicAliasAnalysis.cpp      |  15 +-
 llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp  |  10 +-
 .../ImportedFunctionsInliningStatistics.cpp   |  21 +-
 llvm/lib/Analysis/KernelInfo.cpp              |  15 +-
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      |  44 +-
 llvm/lib/Analysis/LoopCacheAnalysis.cpp       |  34 +-
 llvm/lib/Analysis/MemorySSAUpdater.cpp        |  25 +-
 llvm/lib/Analysis/PtrUseVisitor.cpp           |   6 +-
 llvm/lib/Analysis/ScalarEvolution.cpp         |  11 +-
 llvm/lib/AsmParser/LLParser.cpp               |  10 +-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     |  88 ++--
 llvm/lib/CAS/OnDiskGraphDB.cpp                |  14 +-
 llvm/lib/CGData/StableFunctionMap.cpp         |   6 +-
 llvm/lib/CGData/StableFunctionMapRecord.cpp   |   6 +-
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp    |  13 +-
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  22 +-
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp |   7 +-
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h   |   2 +-
 .../CodeGen/AsmPrinter/DebugHandlerBase.cpp   |   2 +-
 llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h   |  29 +-
 llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h  |  12 +-
 .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp   |   2 +-
 .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h |  16 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  26 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h      |  52 ++-
 .../CodeGen/AsmPrinter/DwarfExpression.cpp    |  20 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h |   6 +-
 llvm/lib/CodeGen/CallingConvLower.cpp         |  44 +-
 .../lib/CodeGen/ComplexDeinterleavingPass.cpp |  16 +-
 llvm/lib/CodeGen/DFAPacketizer.cpp            |   2 +-
 .../CodeGen/FixupStatepointCallerSaved.cpp    |  18 +-
 llvm/lib/CodeGen/GlobalISel/CallLowering.cpp  |   4 +-
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp  |  49 ++-
 llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp |  31 +-
 llvm/lib/CodeGen/LexicalScopes.cpp            |   4 +-
 .../LiveDebugValues/InstrRefBasedImpl.cpp     |  23 +-
 .../LiveDebugValues/InstrRefBasedImpl.h       |   8 +-
 llvm/lib/CodeGen/LiveIntervalUnion.cpp        |  13 +-
 llvm/lib/CodeGen/MachineCopyPropagation.cpp   |  23 +-
 llvm/lib/CodeGen/MachineFunction.cpp          |   4 +-
 llvm/lib/CodeGen/MachineLICM.cpp              |  53 ++-
 llvm/lib/CodeGen/MachineOutliner.cpp          |  14 +-
 llvm/lib/CodeGen/MachinePipeliner.cpp         |  33 +-
 llvm/lib/CodeGen/MachineRegisterInfo.cpp      |  19 +-
 llvm/lib/CodeGen/MachineScheduler.cpp         |  45 +-
 llvm/lib/CodeGen/MachineVerifier.cpp          |  30 +-
 llvm/lib/CodeGen/PrologEpilogInserter.cpp     |  29 +-
 llvm/lib/CodeGen/RegAllocFast.cpp             |  32 +-
 llvm/lib/CodeGen/RegAllocGreedy.cpp           |  10 +-
 llvm/lib/CodeGen/RegAllocGreedy.h             |  15 +-
 llvm/lib/CodeGen/RegisterCoalescer.cpp        |  28 +-
 llvm/lib/CodeGen/Rematerializer.cpp           |  10 +-
 llvm/lib/CodeGen/ScheduleDAG.cpp              |   8 +-
 llvm/lib/CodeGen/ScheduleDAGInstrs.cpp        |  19 +-
 .../SelectionDAG/ScheduleDAGRRList.cpp        |  18 +-
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  10 +-
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 101 +++--
 .../SelectionDAG/SelectionDAGBuilder.h        |  25 +-
 .../CodeGen/SelectionDAG/SelectionDAGISel.cpp |  27 +-
 .../SelectionDAG/StatepointLowering.cpp       |   2 +-
 llvm/lib/CodeGen/TargetSchedule.cpp           |   8 +-
 llvm/lib/DTLTO/DTLTO.cpp                      |  12 +-
 llvm/lib/DTLTO/DTLTOInputFiles.cpp            |   2 +-
 llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp  |  47 +-
 .../Parallel/DIEAttributeCloner.cpp           |  14 +-
 .../Parallel/DWARFLinkerCompileUnit.cpp       |  25 +-
 .../Parallel/DWARFLinkerCompileUnit.h         |   9 +-
 .../Parallel/DWARFLinkerGlobalData.h          |  18 +-
 .../DWARFLinker/Parallel/DWARFLinkerImpl.cpp  |  38 +-
 .../DWARFLinker/Parallel/DWARFLinkerImpl.h    |  18 +-
 .../Parallel/DependencyTracker.cpp            |   8 +-
 .../DWARFLinker/Parallel/DependencyTracker.h  |  10 +-
 .../DebugInfo/CodeView/TypeStreamMerger.cpp   |  36 +-
 llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp  |   6 +-
 .../DWARF/DWARFExpressionPrinter.cpp          |  12 +-
 llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp    |   4 +-
 llvm/lib/ExecutionEngine/ExecutionEngine.cpp  |  12 +-
 .../Orc/TargetProcess/LibraryScanner.cpp      |   4 +-
 llvm/lib/ExecutionEngine/TargetSelect.cpp     |   7 +-
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     |  12 +-
 llvm/lib/IR/AsmWriter.cpp                     |  43 +-
 llvm/lib/IR/DIBuilder.cpp                     |  10 +-
 llvm/lib/IR/DataLayout.cpp                    |  10 +-
 llvm/lib/IR/DroppedVariableStats.cpp          |   7 +-
 llvm/lib/IR/DroppedVariableStatsIR.cpp        |   2 +-
 llvm/lib/IR/LLVMContext.cpp                   |  18 +-
 llvm/lib/IR/LLVMContextImpl.h                 |  17 +-
 llvm/lib/IR/LegacyPassManager.cpp             |   2 +-
 llvm/lib/IR/PassTimingInfo.cpp                |   9 +-
 llvm/lib/IR/Verifier.cpp                      |  25 +-
 llvm/lib/LTO/LTO.cpp                          |  14 +-
 llvm/lib/MC/DXContainerInfo.cpp               |  10 +-
 llvm/lib/MC/DXContainerPSVInfo.cpp            |   2 +-
 llvm/lib/MC/MCAssembler.cpp                   |  16 +-
 llvm/lib/MC/MCCodeView.cpp                    |   4 +-
 llvm/lib/MC/MCContext.cpp                     |  16 +-
 llvm/lib/MC/MCDwarf.cpp                       |  19 +-
 llvm/lib/MC/MCELFStreamer.cpp                 |  24 +-
 llvm/lib/MC/MCObjectStreamer.cpp              |  22 +-
 llvm/lib/MC/MCObjectWriter.cpp                |   3 +-
 llvm/lib/MC/MCParser/AsmLexer.cpp             |   2 +-
 llvm/lib/MC/MCParser/AsmParser.cpp            |  25 +-
 llvm/lib/MC/MCParser/MasmParser.cpp           |  12 +-
 llvm/lib/MC/MachObjectWriter.cpp              |   4 +-
 llvm/lib/ObjCopy/Archive.cpp                  |   6 +-
 llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp         |  15 +-
 llvm/lib/ObjCopy/ConfigManager.cpp            |  44 +-
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp           |  60 +--
 llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp       |  14 +-
 llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp         |   6 +-
 llvm/lib/Object/MachOObjectFile.cpp           |  29 +-
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  21 +-
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       |   4 +-
 llvm/lib/Option/OptTable.cpp                  |  23 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  |  28 +-
 llvm/lib/ProfileData/DataAccessProf.cpp       |   2 +-
 llvm/lib/ProfileData/GCOV.cpp                 |  19 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  46 +-
 llvm/lib/ProfileData/MemProfReader.cpp        |   8 +-
 llvm/lib/ProfileData/SampleProfWriter.cpp     |  16 +-
 llvm/lib/Support/DebugCounter.cpp             |   6 +-
 llvm/lib/Support/GlobPattern.cpp              |  10 +-
 llvm/lib/Support/LSP/Transport.cpp            |  14 +-
 llvm/lib/Support/SuffixTree.cpp               |   2 +-
 llvm/lib/Support/YAMLParser.cpp               | 118 ++---
 llvm/lib/TableGen/TGParser.cpp                |  14 +-
 llvm/lib/TableGen/TGParser.h                  |  16 +-
 .../Target/AArch64/AArch64ISelLowering.cpp    |  74 ++--
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |   8 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp  |  14 +-
 .../AArch64/AArch64MachineFunctionInfo.cpp    |   8 +-
 .../AArch64/AArch64MachineFunctionInfo.h      |  74 ++--
 .../Target/AArch64/AArch64StackTagging.cpp    |   4 +-
 .../AArch64/AArch64TargetTransformInfo.cpp    |   8 +-
 .../AArch64/GISel/AArch64CallLowering.cpp     |   4 +-
 .../MCTargetDesc/AArch64InstPrinter.cpp       |   8 +-
 .../MCTargetDesc/AArch64TargetStreamer.cpp    |   8 +-
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp   |  10 +-
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h     |  10 +-
 llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp |   6 +-
 llvm/lib/Target/AMDGPU/AMDGPUIGroupLP.cpp     |  44 +-
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp |  17 +-
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h   |   7 +-
 llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp      |  11 +-
 .../AMDGPU/AMDGPUTargetTransformInfo.cpp      |   6 +-
 llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp   |   6 +-
 llvm/lib/Target/AMDGPU/GCNSchedStrategy.h     |   6 +-
 llvm/lib/Target/AMDGPU/R600ISelLowering.cpp   |   4 +-
 llvm/lib/Target/AMDGPU/R600ISelLowering.h     |   3 +-
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     |  74 ++--
 llvm/lib/Target/AMDGPU/SIISelLowering.h       |  27 +-
 .../Target/AMDGPU/SIMachineFunctionInfo.cpp   |  59 ++-
 .../lib/Target/AMDGPU/SIMachineFunctionInfo.h | 191 +++++----
 llvm/lib/Target/AMDGPU/SIModeRegister.cpp     |  18 +-
 llvm/lib/Target/ARC/ARCISelLowering.cpp       |  40 +-
 llvm/lib/Target/ARC/ARCISelLowering.h         |  11 +-
 llvm/lib/Target/ARM/ARMAsmPrinter.cpp         |  14 +-
 llvm/lib/Target/ARM/ARMAsmPrinter.h           |   7 +-
 llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp     |   6 +-
 llvm/lib/Target/ARM/ARMBasicBlockInfo.h       |  12 +-
 llvm/lib/Target/ARM/ARMCallLowering.cpp       |   2 +-
 llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 103 +++--
 llvm/lib/Target/ARM/ARMHazardRecognizer.cpp   |  12 +-
 llvm/lib/Target/ARM/ARMHazardRecognizer.h     |   6 +-
 llvm/lib/Target/ARM/ARMISelLowering.cpp       | 107 ++---
 llvm/lib/Target/ARM/ARMISelLowering.h         |  19 +-
 llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp |  95 ++--
 llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp   |  29 +-
 llvm/lib/Target/ARM/ARMParallelDSP.cpp        |  41 +-
 .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp |  18 +-
 .../ARM/MCTargetDesc/ARMELFStreamer.cpp       |  49 ++-
 .../ARM/MCTargetDesc/ARMInstPrinter.cpp       |   2 +-
 .../ARM/MCTargetDesc/ARMUnwindOpAsm.cpp       |   2 +-
 .../Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h  |  12 +-
 llvm/lib/Target/ARM/Thumb2SizeReduction.cpp   |  45 +-
 llvm/lib/Target/AVR/AVRISelLowering.cpp       |  55 ++-
 llvm/lib/Target/AVR/AVRISelLowering.h         |  12 +-
 llvm/lib/Target/BPF/BPFISelLowering.cpp       |  44 +-
 llvm/lib/Target/BPF/BPFISelLowering.h         |  12 +-
 llvm/lib/Target/BPF/BTFDebug.cpp              |   9 +-
 llvm/lib/Target/BPF/BTFDebug.h                |   9 +-
 llvm/lib/Target/CSKY/CSKYISelLowering.cpp     |  55 +--
 llvm/lib/Target/CSKY/CSKYISelLowering.h       |   8 +-
 .../CSKY/MCTargetDesc/CSKYInstPrinter.cpp     |  12 +-
 .../Target/Hexagon/HexagonCopyToCombine.cpp   |  27 +-
 .../Target/Hexagon/HexagonISelDAGToDAG.cpp    |  31 +-
 .../Target/Hexagon/HexagonISelLowering.cpp    |  67 ++-
 llvm/lib/Target/Hexagon/HexagonISelLowering.h |  34 +-
 llvm/lib/Target/Lanai/LanaiISelLowering.cpp   |  45 +-
 llvm/lib/Target/Lanai/LanaiISelLowering.h     |  22 +-
 .../LoongArch/LoongArchISelLowering.cpp       |  63 +--
 .../Target/LoongArch/LoongArchISelLowering.h  |  15 +-
 .../LoongArch/LoongArchMachineFunctionInfo.h  |  10 +-
 .../MCTargetDesc/LoongArchInstPrinter.cpp     |   2 +-
 .../Target/M68k/GISel/M68kCallLowering.cpp    |   2 +-
 llvm/lib/Target/M68k/M68kISelLowering.cpp     |  96 ++---
 llvm/lib/Target/M68k/M68kISelLowering.h       |  18 +-
 llvm/lib/Target/M68k/M68kMachineFunction.h    |  16 +-
 llvm/lib/Target/MSP430/MSP430ISelLowering.cpp |  71 ++-
 llvm/lib/Target/MSP430/MSP430ISelLowering.h   |  26 +-
 .../Mips/MCTargetDesc/MipsInstPrinter.cpp     |   4 +-
 llvm/lib/Target/Mips/MipsBranchExpansion.cpp  |  23 +-
 llvm/lib/Target/Mips/MipsCallLowering.cpp     |   2 +-
 llvm/lib/Target/Mips/MipsISelLowering.cpp     |  57 ++-
 llvm/lib/Target/Mips/MipsISelLowering.h       |  14 +-
 .../MCTargetDesc/NVPTXTargetStreamer.cpp      |   4 +-
 .../NVPTX/MCTargetDesc/NVPTXTargetStreamer.h  |   6 +-
 llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp     |  14 +-
 llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp   |  16 +-
 llvm/lib/Target/NVPTX/NVPTXISelLowering.h     |   5 +-
 llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp      |   2 +-
 .../PowerPC/MCTargetDesc/PPCInstPrinter.cpp   |   2 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     |   2 +-
 .../Target/PowerPC/PPCBranchCoalescing.cpp    |  39 +-
 llvm/lib/Target/PowerPC/PPCFrameLowering.cpp  |   4 +-
 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp   |  16 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 112 +++--
 llvm/lib/Target/PowerPC/PPCISelLowering.h     |  80 ++--
 .../Target/PowerPC/PPCMachineFunctionInfo.h   |  51 ++-
 .../Target/PowerPC/PPCTargetTransformInfo.cpp |  12 +-
 .../Target/RISCV/GISel/RISCVCallLowering.cpp  |   2 +-
 .../RISCV/MCTargetDesc/RISCVInstPrinter.cpp   |   4 +-
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  49 ++-
 llvm/lib/Target/RISCV/RISCVISelLowering.h     |   8 +-
 .../Target/RISCV/RISCVMachineFunctionInfo.cpp |   2 +-
 .../Target/RISCV/RISCVMachineFunctionInfo.h   |  35 +-
 llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp   |   2 +-
 .../SPIRV/SPIRVLegalizeZeroSizeArrays.cpp     |  24 +-
 .../Sparc/MCTargetDesc/SparcInstPrinter.cpp   |   2 +-
 llvm/lib/Target/Sparc/SparcISelLowering.cpp   |  78 ++--
 llvm/lib/Target/Sparc/SparcISelLowering.h     |  19 +-
 .../MCTargetDesc/SystemZInstPrinterCommon.cpp |   2 +-
 .../Target/SystemZ/SystemZISelLowering.cpp    |  59 ++-
 llvm/lib/Target/SystemZ/SystemZISelLowering.h |  27 +-
 llvm/lib/Target/VE/VEISelLowering.cpp         |  39 +-
 llvm/lib/Target/VE/VEISelLowering.h           |  11 +-
 .../AsmParser/WebAssemblyAsmTypeCheck.cpp     |  11 +-
 .../AsmParser/WebAssemblyAsmTypeCheck.h       |   6 +-
 .../GISel/WebAssemblyCallLowering.cpp         |   2 +-
 .../WebAssembly/WebAssemblyISelLowering.cpp   |  24 +-
 .../WebAssembly/WebAssemblyISelLowering.h     |   8 +-
 llvm/lib/Target/X86/GISel/X86CallLowering.cpp |   2 +-
 .../X86/MCTargetDesc/X86ATTInstPrinter.cpp    |   2 +-
 .../X86/MCTargetDesc/X86InstPrinterCommon.cpp |   4 +-
 .../X86/MCTargetDesc/X86IntelInstPrinter.cpp  |   2 +-
 .../Target/X86/X86CallFrameOptimization.cpp   |  19 +-
 llvm/lib/Target/X86/X86ISelLowering.h         |  19 +-
 llvm/lib/Target/X86/X86ISelLoweringCall.cpp   | 103 +++--
 llvm/lib/Target/X86/X86MachineFunctionInfo.h  |  60 +--
 llvm/lib/Target/XCore/XCoreISelLowering.cpp   |  44 +-
 llvm/lib/Target/XCore/XCoreISelLowering.h     |  19 +-
 .../Xtensa/MCTargetDesc/XtensaInstPrinter.cpp |   6 +-
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp |  26 +-
 llvm/lib/Target/Xtensa/XtensaISelLowering.h   |   8 +-
 llvm/lib/Transforms/Coroutines/SpillUtils.cpp |   2 +-
 llvm/lib/Transforms/IPO/Attributor.cpp        |  10 +-
 llvm/lib/Transforms/IPO/BlockExtractor.cpp    |  13 +-
 llvm/lib/Transforms/IPO/HotColdSplitting.cpp  |  12 +-
 llvm/lib/Transforms/IPO/Instrumentor.cpp      |  14 +-
 .../Transforms/IPO/InstrumentorConfigFile.cpp |   6 +-
 .../IPO/InstrumentorStubPrinter.cpp           |   2 +-
 llvm/lib/Transforms/IPO/OpenMPOpt.cpp         |  10 +-
 llvm/lib/Transforms/IPO/PartialInlining.cpp   |  12 +-
 llvm/lib/Transforms/IPO/SampleProfile.cpp     |   2 +-
 .../lib/Transforms/IPO/WholeProgramDevirt.cpp |  58 +--
 .../Instrumentation/AddressSanitizer.cpp      |  53 ++-
 .../ControlHeightReduction.cpp                |  40 +-
 .../Instrumentation/HWAddressSanitizer.cpp    |   2 +-
 .../Instrumentation/InstrProfiling.cpp        |  16 +-
 .../Instrumentation/MemorySanitizer.cpp       |  88 ++--
 .../Transforms/Scalar/ConstantHoisting.cpp    |  23 +-
 .../Scalar/ConstraintElimination.cpp          |  22 +-
 .../Scalar/DeadStoreElimination.cpp           |  30 +-
 llvm/lib/Transforms/Scalar/EarlyCSE.cpp       |  28 +-
 llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp   |  42 +-
 llvm/lib/Transforms/Scalar/GVN.cpp            |  18 +-
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp |  81 ++--
 llvm/lib/Transforms/Scalar/LoopDistribute.cpp |  26 +-
 llvm/lib/Transforms/Scalar/LoopFuse.cpp       |  57 +--
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  |  52 ++-
 .../lib/Transforms/Scalar/LoopSimplifyCFG.cpp |  37 +-
 .../Transforms/Scalar/LoopStrengthReduce.cpp  | 202 +++++----
 .../Scalar/LowerMatrixIntrinsics.cpp          |  25 +-
 llvm/lib/Transforms/Scalar/SROA.cpp           |  36 +-
 llvm/lib/Transforms/Scalar/Scalarizer.cpp     |  50 ++-
 .../Scalar/TailRecursionElimination.cpp       |  13 +-
 llvm/lib/Transforms/Utils/CodeExtractor.cpp   |  33 +-
 llvm/lib/Transforms/Utils/InlineFunction.cpp  |   2 +-
 llvm/lib/Transforms/Utils/LoopUtils.cpp       |  35 +-
 .../Transforms/Utils/MemoryTaggingSupport.cpp |   4 +-
 .../Utils/PromoteMemoryToRegister.cpp         |  24 +-
 .../Utils/ScalarEvolutionExpander.cpp         |  22 +-
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp  |  32 +-
 .../Vectorize/LoopVectorizationLegality.cpp   |  10 +-
 .../Vectorize/LoopVectorizationPlanner.cpp    |   2 +-
 .../Transforms/Vectorize/LoopVectorize.cpp    |   7 +-
 .../Transforms/Vectorize/SLPVectorizer.cpp    | 243 +++++++----
 llvm/tools/dsymutil/MachODebugMapParser.cpp   |  18 +-
 llvm/tools/dsymutil/Reproducer.cpp            |   9 +-
 llvm/tools/dsymutil/Reproducer.h              |   9 +-
 llvm/tools/llvm-cov/SourceCoverageView.h      |  15 +-
 llvm/tools/llvm-dwarfdump/Coverage.cpp        |  26 +-
 llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp  |   8 +-
 llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp  |  10 +-
 llvm/tools/llvm-exegesis/lib/Analysis.cpp     |   2 +-
 .../lib/SchedClassResolution.cpp              |   8 +-
 .../llvm-exegesis/lib/SchedClassResolution.h  |   8 +-
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp    |  99 ++---
 llvm/tools/llvm-objcopy/llvm-objcopy.cpp      |  18 +-
 llvm/tools/llvm-profgen/PerfReader.cpp        |   8 +-
 llvm/tools/llvm-profgen/PerfReader.h          |  15 +-
 llvm/tools/llvm-profgen/ProfileGenerator.cpp  |   2 +-
 llvm/tools/llvm-reduce/TestRunner.cpp         |  16 +-
 llvm/tools/llvm-reduce/TestRunner.h           |  21 +-
 llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp        |  12 +-
 .../ADT/SmallVectorWithFlagsTest.cpp          | 110 ++++-
 .../Bitstream/BitstreamWriterTest.cpp         |  18 +
 .../SelectionDAGNodeConstructionTest.cpp      |  42 ++
 .../MCJIT/MCJITObjectCacheTest.cpp            |  12 +-
 .../HLSLSemanticSignaturePackingTest.cpp      |  17 +-
 .../Frontend/OpenMPIRBuilderTest.cpp          |   2 +-
 llvm/unittests/IR/LegacyPassManagerTest.cpp   |  23 +
 .../LoongArch/LoongArchMCDisassemblerTest.cpp |  10 +-
 .../ProfileData/DataAccessProfTest.cpp        |   7 +-
 .../Support/OptimizedStructLayoutTest.cpp     |  10 +-
 llvm/unittests/Support/YAMLIOTest.cpp         |  33 ++
 llvm/utils/TableGen/AsmMatcherEmitter.cpp     |  43 +-
 .../TableGen/Basic/CodeGenIntrinsics.cpp      |  18 +-
 llvm/utils/TableGen/Basic/CodeGenIntrinsics.h |  71 ++-
 .../utils/TableGen/Basic/IntrinsicEmitter.cpp |  43 +-
 .../TableGen/Common/CodeGenDAGPatterns.cpp    |   5 +-
 .../TableGen/Common/CodeGenRegisters.cpp      | 158 +++----
 llvm/utils/TableGen/Common/CodeGenRegisters.h |  76 ++--
 llvm/utils/TableGen/Common/CodeGenTarget.cpp  |   3 +-
 llvm/utils/TableGen/Common/CodeGenTarget.h    |  14 +-
 .../Common/GlobalISel/MatchTable/Matchers.cpp |   9 +-
 .../Common/GlobalISel/MatchTable/Matchers.h   |  22 +-
 .../Common/GlobalISel/PatternParser.cpp       |   8 +-
 .../TableGen/Common/InstructionEncoding.cpp   |   6 +-
 .../TableGen/Common/InstructionEncoding.h     |   8 +-
 .../TableGen/Common/VarLenCodeEmitterGen.cpp  |   6 +-
 .../TableGen/Common/VarLenCodeEmitterGen.h    |  10 +-
 llvm/utils/TableGen/DecoderEmitter.cpp        |  25 +-
 llvm/utils/TableGen/GlobalISelEmitter.cpp     |   2 +-
 llvm/utils/TableGen/RegisterInfoEmitter.cpp   |  39 +-
 .../utils/TableGen/SearchableTableEmitter.cpp |  36 +-
 .../transform-opt/mlir-transform-opt.cpp      |  13 +-
 mlir/include/mlir/ABI/ABIRewriteContext.h     |   9 +-
 .../mlir/Analysis/Presburger/Simplex.h        |  12 +-
 .../IR/BufferizableOpInterface.h              |  10 +-
 .../Dialect/LLVMIR/BasicPtxBuilderInterface.h |  20 +-
 .../Dialect/Linalg/Transforms/Transforms.h    |  47 +-
 mlir/include/mlir/Dialect/Shard/IR/ShardOps.h |   4 +-
 .../Shard/Interfaces/ShardingInterface.h      |  13 +-
 .../mlir/Dialect/SparseTensor/Utils/Merger.h  |   7 +-
 .../mlir/Dialect/Tosa/Utils/ConversionUtils.h |   4 +-
 .../mlir/Dialect/Tosa/Utils/ShapeUtils.h      |  62 +--
 .../Dialect/Transform/IR/TransformDialect.h   |  10 +-
 .../mlir/ExecutionEngine/ExecutionEngine.h    |   6 +-
 .../mlir/Interfaces/InferTypeOpInterface.h    |  38 +-
 .../mlir/Support/CyclicReplacerCache.h        |  12 +-
 mlir/include/mlir/TableGen/Class.h            |   9 +-
 mlir/include/mlir/TableGen/Operator.h         |   9 +-
 mlir/include/mlir/Tools/PDLL/ODS/Operation.h  |   8 +-
 mlir/lib/Analysis/Presburger/Simplex.cpp      |  51 +--
 mlir/lib/AsmParser/AffineParser.cpp           |  14 +-
 mlir/lib/Bytecode/Reader/BytecodeReader.cpp   |  60 +--
 .../IR/BufferizableOpInterface.cpp            |   4 +-
 .../Transforms/OneShotModuleBufferize.cpp     |   2 +-
 .../LLVMIR/IR/BasicPtxBuilderInterface.cpp    |  30 +-
 .../Linalg/Transforms/BlockPackMatmul.cpp     |  26 +-
 .../Linalg/Transforms/PadTilingInterface.cpp  |   6 +-
 .../Linalg/Transforms/Vectorization.cpp       |  16 +-
 .../NVGPU/TransformOps/NVGPUTransformOps.cpp  |  16 +-
 .../Dialect/OpenACC/Transforms/ACCCGToGPU.cpp |  96 +++--
 .../Shard/Interfaces/ShardingInterface.cpp    |   4 +-
 .../Shard/Transforms/ShardingPropagation.cpp  |   9 +-
 .../SparseTensor/IR/Detail/DimLvlMap.cpp      |   5 +-
 .../SparseTensor/IR/Detail/DimLvlMap.h        |   6 +-
 .../lib/Dialect/SparseTensor/Utils/Merger.cpp |   3 +-
 .../Tosa/Transforms/TosaInferShapes.cpp       |   2 +-
 mlir/lib/ExecutionEngine/ExecutionEngine.cpp  |   6 +-
 mlir/lib/IR/MLIRContext.cpp                   |  54 ++-
 mlir/lib/Interfaces/InferTypeOpInterface.cpp  |  11 +-
 mlir/lib/TableGen/Class.cpp                   |   5 +-
 mlir/lib/TableGen/Operator.cpp                |  39 +-
 mlir/lib/Target/Cpp/TranslateToCpp.cpp        |  20 +-
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  31 +-
 mlir/lib/Tools/PDLL/ODS/Operation.cpp         |   5 +-
 .../TestOneShotModuleBufferize.cpp            |   2 +-
 mlir/unittests/Dialect/CMakeLists.txt         |   1 +
 mlir/unittests/Dialect/Tosa/CMakeLists.txt    |   9 +
 .../unittests/Dialect/Tosa/ShapeUtilsTest.cpp |  46 ++
 .../Interfaces/InferTypeOpInterfaceTest.cpp   |  32 ++
 polly/include/polly/ScopInfo.h                |  69 +--
 polly/lib/Analysis/ScopInfo.cpp               |  13 +-
 861 files changed, 12978 insertions(+), 8706 deletions(-)
 create mode 100644 mlir/unittests/Dialect/Tosa/CMakeLists.txt
 create mode 100644 mlir/unittests/Dialect/Tosa/ShapeUtilsTest.cpp

diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index c41ad06027f64..22fdf5a5beaef 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -39,6 +39,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseBitVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
@@ -236,6 +237,24 @@ class BinaryFunction {
   bool HadNegateRAState{false};
   bool InitialRAState{false};
 
+  /// False if the function is too complex to reconstruct its control
+  /// flow graph.
+  /// In relocation mode we still disassemble and re-assemble such functions.
+  bool IsSimple{true};
+
+  /// Indication that the function should be ignored for optimization purposes.
+  /// If we can skip emission of some functions, then ignored functions could
+  /// be not fully disassembled and will not be emitted.
+  bool IsIgnored{false};
+
+  /// Pseudo functions should not be disassembled or emitted.
+  bool IsPseudo{false};
+
+  /// True if the original function code has all necessary relocations to track
+  /// addresses of functions emitted to new locations. Typically set for
+  /// functions that we are not going to emit.
+  bool HasExternalRefRelocations{false};
+
   /// A list of symbols associated with the function entry point.
   ///
   /// Multiple symbols would typically result from identical code-folding
@@ -245,7 +264,7 @@ class BinaryFunction {
 
   /// The list of names this function is known under. Used for fuzzy-matching
   /// the function to its name in a profile, command line, etc.
-  SmallVector<std::string, 0> Aliases;
+  SmallVectorWithFlags<std::string, 0, 4> Aliases;
 
   /// Containing section in the input file.
   BinarySection *OriginSection = nullptr;
@@ -315,67 +334,23 @@ class BinaryFunction {
   /// is a global symbol corresponding to an external entry point.
   DenseMap<const MCSymbol *, MCSymbol *> SecondaryEntryPoints;
 
-  /// False if the function is too complex to reconstruct its control
-  /// flow graph.
-  /// In relocation mode we still disassemble and re-assemble such functions.
-  bool IsSimple{true};
-
-  /// Indication that the function should be ignored for optimization purposes.
-  /// If we can skip emission of some functions, then ignored functions could
-  /// be not fully disassembled and will not be emitted.
-  bool IsIgnored{false};
-
-  /// Pseudo functions should not be disassembled or emitted.
-  bool IsPseudo{false};
-
-  /// True if the original function code has all necessary relocations to track
-  /// addresses of functions emitted to new locations. Typically set for
-  /// functions that we are not going to emit.
-  bool HasExternalRefRelocations{false};
-
-  /// True if the function has an indirect branch with unknown destination.
-  bool HasUnknownControlFlow{false};
-
-  /// The code from inside the function references one of the code locations
-  /// from the same function as a data, i.e. it's possible the label is used
-  /// inside an address calculation or could be referenced from outside.
-  bool HasInternalLabelReference{false};
-
-  /// In AArch64, preserve nops to maintain code equal to input (assuming no
-  /// optimizations are done).
-  bool PreserveNops{false};
-
-  /// Indicate if this function has associated exception handling metadata.
-  bool HasEHRanges{false};
-
-  /// True if the function uses DW_CFA_GNU_args_size CFIs.
-  bool UsesGnuArgsSize{false};
-
-  /// True if the function might have a profile available externally.
-  /// Used to check if processing of the function is required under certain
-  /// conditions.
-  bool HasProfileAvailable{false};
-
-  bool HasMemoryProfile{false};
-
-  /// Execution halts whenever this function is entered.
-  bool TrapsOnEntry{false};
+  bool getHasMemoryProfileFlag() const { return Aliases.getFlag(0); }
+  void setHasMemoryProfileFlag(bool Value) { Aliases.setFlag(0, Value); }
 
   /// True if the function is a fragment of another function. This means that
   /// this function could only be entered via its parent or one of its sibling
   /// fragments. It could be entered at any basic block. It can also return
   /// the control to any basic block of its parent or its sibling.
-  bool IsFragment{false};
+  bool getIsFragmentFlag() const { return Aliases.getFlag(1); }
+  void setIsFragmentFlag(bool Value) { Aliases.setFlag(1, Value); }
 
   /// Indicate that the function body has SDT marker
-  bool HasSDTMarker{false};
+  bool getHasSDTMarkerFlag() const { return Aliases.getFlag(2); }
+  void setHasSDTMarkerFlag(bool Value) { Aliases.setFlag(2, Value); }
 
   /// Indicate that the function body has Pseudo Probe
-  bool HasPseudoProbe{BC.getUniqueSectionByName(".pseudo_probe_desc") &&
-                      BC.getUniqueSectionByName(".pseudo_probe")};
-
-  /// True if the function uses ORC format for stack unwinding.
-  bool HasORC{false};
+  bool getHasPseudoProbeFlag() const { return Aliases.getFlag(3); }
+  void setHasPseudoProbeFlag(bool Value) { Aliases.setFlag(3, Value); }
 
   /// True if the function contains explicit or implicit indirect branch to its
   /// split fragments, e.g., split jump table, landing pad in split fragment
@@ -450,6 +425,24 @@ class BinaryFunction {
   /// been adjusted by the profile inference algorithm.
   bool HasInferredProfile{false};
 
+  /// True if the function has an indirect branch with unknown destination.
+  bool HasUnknownControlFlow{false};
+
+  /// The code from inside the function references one of the code locations
+  /// from the same function as a data, i.e. it's possible the label is used
+  /// inside an address calculation or could be referenced from outside.
+  bool HasInternalLabelReference{false};
+
+  /// In AArch64, preserve nops to maintain code equal to input (assuming no
+  /// optimizations are done).
+  bool PreserveNops{false};
+
+  /// Indicate if this function has associated exception handling metadata.
+  bool HasEHRanges{false};
+
+  /// True if the function uses DW_CFA_GNU_args_size CFIs.
+  bool UsesGnuArgsSize{false};
+
   /// For functions with mismatched profile we store all call profile
   /// information at a function level (as opposed to tying it to
   /// specific call sites).
@@ -486,6 +479,17 @@ class BinaryFunction {
   /// Function is referenced by a non-control flow instruction.
   bool HasAddressTaken{false};
 
+  /// True if the function might have a profile available externally.
+  /// Used to check if processing of the function is required under certain
+  /// conditions.
+  bool HasProfileAvailable{false};
+
+  /// Execution halts whenever this function is entered.
+  bool TrapsOnEntry{false};
+
+  /// True if the function uses ORC format for stack unwinding.
+  bool HasORC{false};
+
   /// Get basic block index assuming it belongs to this function.
   unsigned getIndex(const BinaryBasicBlock *BB) const {
     assert(BB->getIndex() < BasicBlocks.size());
@@ -716,7 +720,8 @@ class BinaryFunction {
   /// parent fragment to \p BF.
   void addParentFragment(BinaryFunction &BF) {
     assert(this != &BF);
-    assert(IsFragment && "function must be a fragment to have a parent");
+    assert(getIsFragmentFlag() &&
+           "function must be a fragment to have a parent");
     ParentFragments.insert(&BF);
   }
 
@@ -770,7 +775,11 @@ class BinaryFunction {
   /// Creation should be handled by RewriteInstance or BinaryContext
   BinaryFunction(const std::string &Name, BinarySection &Section,
                  uint64_t Address, uint64_t Size, BinaryContext &BC)
-      : OriginSection(&Section), Address(Address), Size(Size), BC(BC),
+      : Aliases(decltype(Aliases)::withFlags(
+            (unsigned(bool(BC.getUniqueSectionByName(".pseudo_probe_desc") &&
+                           BC.getUniqueSectionByName(".pseudo_probe")))
+             << 3))),
+        OriginSection(&Section), Address(Address), Size(Size), BC(BC),
         FunctionNumber(++Count) {
     Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name));
   }
@@ -778,7 +787,12 @@ class BinaryFunction {
   /// This constructor is used to create an injected function, i.e. a function
   /// that didn't originate in the input file.
   BinaryFunction(const std::string &Name, BinaryContext &BC, bool IsSimple)
-      : Address(0), Size(0), BC(BC), IsSimple(IsSimple),
+      : IsSimple(IsSimple),
+        Aliases(decltype(Aliases)::withFlags(
+            (unsigned(bool(BC.getUniqueSectionByName(".pseudo_probe_desc") &&
+                           BC.getUniqueSectionByName(".pseudo_probe")))
+             << 3))),
+        Address(0), Size(0), BC(BC),
         CodeSectionName(BC.getInjectedCodeSectionName()),
         ColdCodeSectionName(BC.getInjectedColdCodeSectionName()),
         FunctionNumber(++Count) {
@@ -1498,7 +1512,7 @@ class BinaryFunction {
   /// but not yet populated into the function.
   bool hasProfileAvailable() const { return HasProfileAvailable; }
 
-  bool hasMemoryProfile() const { return HasMemoryProfile; }
+  bool hasMemoryProfile() const { return getHasMemoryProfileFlag(); }
 
   /// Return true if the body of the function was merged into another function.
   bool isFolded() const { return FoldedIntoFunction != nullptr; }
@@ -1525,10 +1539,10 @@ class BinaryFunction {
   bool hasJumpTables() const { return !JumpTables.empty(); }
 
   /// Return true if the function has SDT marker
-  bool hasSDTMarker() const { return HasSDTMarker; }
+  bool hasSDTMarker() const { return getHasSDTMarkerFlag(); }
 
   /// Return true if the function has Pseudo Probe
-  bool hasPseudoProbe() const { return HasPseudoProbe; }
+  bool hasPseudoProbe() const { return getHasPseudoProbeFlag(); }
 
   /// Return true if the function uses ORC format for stack unwinding.
   bool hasORC() const { return HasORC; }
@@ -1964,7 +1978,7 @@ class BinaryFunction {
     IsAnonymous = V;
   }
 
-  void setHasSDTMarker(bool V) { HasSDTMarker = V; }
+  void setHasSDTMarker(bool V) { setHasSDTMarkerFlag(V); }
 
   /// Mark the function as using ORC format for stack unwinding.
   void setHasORC(bool V) { HasORC = V; }
@@ -2032,7 +2046,7 @@ class BinaryFunction {
   }
 
   /// Return true if the function is a secondary fragment of another function.
-  bool isFragment() const { return IsFragment; }
+  bool isFragment() const { return getIsFragmentFlag(); }
 
   /// Returns if this function is a child of \p Other function.
   bool isChildOf(const BinaryFunction &Other) const {
diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h
index b06b0d90a7aee..8fa86c1ee3228 100644
--- a/bolt/include/bolt/Core/DebugData.h
+++ b/bolt/include/bolt/Core/DebugData.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/MC/MCDwarf.h"
@@ -517,7 +518,7 @@ class DebugStrOffsetsWriter {
   }
 
   bool isStrOffsetsSectionModified() const {
-    return StrOffsetSectionWasModified;
+    return getStrOffsetSectionWasModified();
   }
 
 private:
@@ -526,9 +527,12 @@ class DebugStrOffsetsWriter {
   std::map<uint32_t, uint64_t> IndexToAddressMap;
   [[maybe_unused]]
   DenseSet<uint64_t> DebugStrOffsetFinalized;
-  SmallVector<uint64_t, 5> StrOffsets;
+  llvm::SmallVectorWithFlags<uint64_t, 5> StrOffsets;
   std::unordered_map<uint64_t, uint64_t> ProcessedBaseOffsets;
-  bool StrOffsetSectionWasModified = false;
+  bool getStrOffsetSectionWasModified() const { return StrOffsets.getFlag(0); }
+  void setStrOffsetSectionWasModified(bool Value) {
+    StrOffsets.setFlag(0, Value);
+  }
   BinaryContext &BC;
 };
 
diff --git a/bolt/include/bolt/Core/DebugNames.h b/bolt/include/bolt/Core/DebugNames.h
index a87d4c3c67b2c..099816d231263 100644
--- a/bolt/include/bolt/Core/DebugNames.h
+++ b/bolt/include/bolt/Core/DebugNames.h
@@ -15,6 +15,7 @@
 #define BOLT_CORE_DEBUG_NAMES_H
 
 #include "bolt/Core/DebugData.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AccelTable.h"
 
 #include <mutex>
@@ -67,7 +68,7 @@ class DWARF5AcceleratorTable {
   /// Emit Accelerator table.
   void emitAccelTable();
   /// Returns true if the table was created.
-  bool isCreated() const { return NeedToCreate; }
+  bool isCreated() const { return getNeedToCreate(); }
   /// Returns buffer containing the accelerator table.
   std::unique_ptr<DebugBufferVector> releaseBuffer() {
     return std::move(FullTableBuffer);
@@ -89,7 +90,8 @@ class DWARF5AcceleratorTable {
 
 private:
   BinaryContext &BC;
-  bool NeedToCreate = false;
+  bool getNeedToCreate() const { return AbbreviationsVector.getFlag(0); }
+  void setNeedToCreate(bool Value) { AbbreviationsVector.setFlag(0, Value); }
   BumpPtrAllocator Allocator;
   DebugStrWriter &MainBinaryStrWriter;
   StringRef StrSection;
@@ -102,7 +104,8 @@ class DWARF5AcceleratorTable {
   /// multiple TUs with the same hash.
   DenseMap<uint64_t, uint32_t> TUHashToIndexMap;
   /// Track whether AcceleratorTable have been preallocated.
-  bool Preallocated = false;
+  bool getPreallocated() const { return AbbreviationsVector.getFlag(1); }
+  void setPreallocated(bool Value) { AbbreviationsVector.setFlag(1, Value); }
   /// Represents a group of entries with identical name (and hence, hash value).
   struct HashData {
     uint64_t StrOffset;
@@ -128,7 +131,7 @@ class DWARF5AcceleratorTable {
   /// FoldingSet that uniques the abbreviations.
   FoldingSet<DebugNamesAbbrev> AbbreviationsSet;
   /// Vector containing DebugNames abbreviations for iteration in order.
-  SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector;
+  llvm::SmallVectorWithFlags<DebugNamesAbbrev *, 5, 2> AbbreviationsVector;
   /// The bump allocator to use when creating DIEAbbrev objects in the uniqued
   /// storage container.
   BumpPtrAllocator Alloc;
diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h
index 710a61f19e340..e8b6c0443c52b 100644
--- a/bolt/include/bolt/Profile/DataAggregator.h
+++ b/bolt/include/bolt/Profile/DataAggregator.h
@@ -16,6 +16,7 @@
 
 #include "bolt/Profile/DataReader.h"
 #include "bolt/Profile/YAMLProfileWriter.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Program.h"
@@ -163,9 +164,10 @@ class DataAggregator : public DataReader {
 
   /// Perf.data or pre-aggregated inputs to aggregate and merge into this
   /// reader. The first entry is the primary profile input.
-  SmallVector<std::string, 1> InputFilenames;
+  llvm::SmallVectorWithFlags<std::string, 1> InputFilenames;
 
-  bool Parsed{false};
+  bool getParsed() const { return InputFilenames.getFlag(0); }
+  void setParsed(bool Value) { InputFilenames.setFlag(0, Value); }
 
   /// Filter pre-aggregated entries belonging to a DSO with this buildid.
   /// Set when processing a shared library, empty implies main binary.
@@ -193,11 +195,14 @@ class DataAggregator : public DataReader {
     static constexpr StringLiteral PerfProcessTypeNames[] = {
         "BUILDIDS", "MAIN", "MEM", "MMAP", "TASK"};
 
+    explicit PerfProcessInfo(PerfProcessType Type) : Type(Type) {}
+
     enum PerfProcessType Type;
-    bool IsFinished{false};
+    bool getIsFinished() const { return StderrPath.getFlag(0); }
+    void setIsFinished(bool Value) { StderrPath.setFlag(0, Value); }
     sys::ProcessInfo PI{};
     SmallVector<char, 256> StdoutPath{};
-    SmallVector<char, 256> StderrPath{};
+    llvm::SmallVectorWithFlags<char, 256> StderrPath{};
 
     /// Helper variables for parsing perfscript profile.
     /// Length: Total size of the content from \p Offset.
@@ -207,11 +212,11 @@ class DataAggregator : public DataReader {
   };
 
   /// Process info for spawned processes
-  PerfProcessInfo BuildIDProcessInfo = {PerfProcessType::BUILDIDS};
-  PerfProcessInfo MainEventsPPI = {PerfProcessType::MAIN_EVENTS};
-  PerfProcessInfo MemEventsPPI = {PerfProcessType::MEM_EVENTS};
-  PerfProcessInfo MMapEventsPPI = {PerfProcessType::MMAP_EVENTS};
-  PerfProcessInfo TaskEventsPPI = {PerfProcessType::TASK_EVENTS};
+  PerfProcessInfo BuildIDProcessInfo{PerfProcessType::BUILDIDS};
+  PerfProcessInfo MainEventsPPI{PerfProcessType::MAIN_EVENTS};
+  PerfProcessInfo MemEventsPPI{PerfProcessType::MEM_EVENTS};
+  PerfProcessInfo MMapEventsPPI{PerfProcessType::MMAP_EVENTS};
+  PerfProcessInfo TaskEventsPPI{PerfProcessType::TASK_EVENTS};
 
   /// Kernel VM starts at fixed based address
   /// https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index 8985ca30433a7..7f3941ab5c925 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -446,7 +446,7 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation) {
     OS << "\n  Unknown CF  : true";
   if (getPersonalityFunction())
     OS << "\n  Personality : " << getPersonalityFunction()->getName();
-  if (IsFragment)
+  if (getIsFragmentFlag())
     OS << "\n  IsFragment  : true";
   if (isFolded())
     OS << "\n  FoldedInto  : " << *getFoldedIntoFunction();
@@ -4605,7 +4605,7 @@ DebugAddressRangesVector BinaryFunction::getOutputAddressRanges() const {
   if (isFolded())
     return OutputRanges;
 
-  if (IsFragment)
+  if (getIsFragmentFlag())
     return OutputRanges;
 
   OutputRanges.emplace_back(getOutputAddress(),
diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp
index df8f7aa33485c..d95abf9bb968a 100644
--- a/bolt/lib/Core/DebugData.cpp
+++ b/bolt/lib/Core/DebugData.cpp
@@ -918,7 +918,7 @@ void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint64_t Address,
          "Cannot update address map since debug_str_offsets was already "
          "finalized for this CU.");
   IndexToAddressMap[Index] = Address;
-  StrOffsetSectionWasModified = true;
+  setStrOffsetSectionWasModified(true);
 }
 
 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
@@ -941,7 +941,8 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
       Die.findAttribute(dwarf::DW_AT_str_offsets_base);
   auto RetVal = ProcessedBaseOffsets.find(*Val);
   // Handling reuse of str-offsets section.
-  if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
+  if (RetVal == ProcessedBaseOffsets.end() ||
+      getStrOffsetSectionWasModified()) {
     initialize(Unit);
     // Update String Offsets that were modified.
     for (const auto &Entry : IndexToAddressMap)
@@ -974,7 +975,7 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
                          DIEInteger(RetVal->second));
   }
 
-  StrOffsetSectionWasModified = false;
+  setStrOffsetSectionWasModified(false);
   assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&
          "debug_str_offsets was already finalized for this CU.");
   clear();
diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp
index 829200e9d182c..aa3fdf956082f 100644
--- a/bolt/lib/Core/DebugNames.cpp
+++ b/bolt/lib/Core/DebugNames.cpp
@@ -23,8 +23,8 @@ DWARF5AcceleratorTable::DWARF5AcceleratorTable(
     const bool CreateDebugNames, BinaryContext &BC,
     DebugStrWriter &MainBinaryStrWriter)
     : BC(BC), MainBinaryStrWriter(MainBinaryStrWriter) {
-  NeedToCreate = CreateDebugNames || BC.getDebugNamesSection();
-  if (!NeedToCreate)
+  setNeedToCreate(CreateDebugNames || BC.getDebugNamesSection());
+  if (!getNeedToCreate())
     return;
   FullTableBuffer = std::make_unique<DebugStrBufferVector>();
   FullTableStream = std::make_unique<raw_svector_ostream>(*FullTableBuffer);
@@ -47,7 +47,7 @@ DWARF5AcceleratorTable::DWARF5AcceleratorTable(
       Error Err = Error::success();
       const char *CStr = StrData.getCStr(&Offset, &Err);
       if (Err) {
-        NeedToCreate = false;
+        setNeedToCreate(false);
         BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Could not extract "
                      "string from .debug_str section at offset: "
                   << Twine::utohexstr(StrOffset) << ".\n";
@@ -98,7 +98,7 @@ void DWARF5AcceleratorTable::preAllocateUnits(DWARFContext &DwCtx) {
       }
     }
   }
-  Preallocated = true;
+  setPreallocated(true);
 }
 
 void DWARF5AcceleratorTable::setCurrentUnit(DWARFUnit &Unit,
@@ -137,7 +137,7 @@ DWARF5AcceleratorTable::getCrossCUDie(uint64_t Offset) {
 void DWARF5AcceleratorTable::addUnit(DWARFUnit &Unit,
                                      const std::optional<uint64_t> &DWOID) {
   StrSection = Unit.getStringSection();
-  if (Preallocated) {
+  if (getPreallocated()) {
     if (!Unit.isTypeUnit() && !DWOID) {
       CUList.push_back(CurrentUnitOffset);
     }
@@ -302,7 +302,7 @@ uint32_t DWARF5AcceleratorTable::getUnitID(const DWARFUnit &Unit,
     }
     return LocalTUList.size() - 1;
   }
-  if (Preallocated && DWOID) {
+  if (getPreallocated() && DWOID) {
     auto Iter = CUOffsetsToPatch.find(*DWOID);
     assert(Iter != CUOffsetsToPatch.end() && "DWO ID not preallocated");
     return Iter->second;
@@ -450,7 +450,7 @@ DWARF5AcceleratorTable::addAccelTableEntry(
     DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID,
     const uint32_t NumberParentsInChain,
     std::optional<BOLTDWARF5AccelTableData *> &Parent) {
-  if (Unit.getVersion() < 5 || !NeedToCreate)
+  if (Unit.getVersion() < 5 || !getNeedToCreate())
     return std::nullopt;
   std::string NameToUse = "";
 
@@ -538,7 +538,7 @@ static unsigned getTypeUnitKey(const BOLTDWARF5AccelTableData *Entry) {
 
 /// Bucket code as in: AccelTableBase::finalize()
 void DWARF5AcceleratorTable::finalize() {
-  if (!NeedToCreate)
+  if (!getNeedToCreate())
     return;
   // Figure out how many buckets we need, then compute the bucket contents and
   // the final ordering. The hashes and offsets can be emitted by walking these
@@ -895,7 +895,7 @@ void DWARF5AcceleratorTable::emitAugmentationString() const {
   FullTableStream->write(AugStringBuffer->data(), AugStringBuffer->size());
 }
 void DWARF5AcceleratorTable::emitAccelTable() {
-  if (!NeedToCreate)
+  if (!getNeedToCreate())
     return;
   finalize();
   populateAbbrevsMap();
diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp
index ca1c18dcaadd3..9319ca57acda4 100644
--- a/bolt/lib/Profile/DataAggregator.cpp
+++ b/bolt/lib/Profile/DataAggregator.cpp
@@ -184,7 +184,7 @@ void DataAggregator::mergeFrom(const DataAggregator &Other) {
   NumInvalidTraces += Other.NumInvalidTraces;
   NumLongRangeTraces += Other.NumLongRangeTraces;
   NumTotalSamples += Other.NumTotalSamples;
-  Parsed = true;
+  setParsed(true);
 }
 
 void DataAggregator::markFunctionsWithProfile() {
@@ -328,14 +328,20 @@ Error DataAggregator::launchPerfProcess(StringRef Name, PerfProcessInfo &PPI,
   Argv.push_back("-i");
   Argv.push_back(Filename.c_str());
 
-  for (auto [Ext, Path] : {std::make_pair("out", &PPI.StdoutPath),
-                           std::make_pair("err", &PPI.StderrPath)}) {
+  auto CreateTempFile = [&](StringRef Ext, auto &Path) -> Error {
+    SmallVector<char, 256> TemporaryPath;
     if (std::error_code Errc =
-            sys::fs::createTemporaryFile("perf.script", Ext, *Path))
+            sys::fs::createTemporaryFile("perf.script", Ext, TemporaryPath))
       return createStringError(Errc, "failed to create temporary file %s",
-                               Path->data());
-    TempFiles.push_back(Path->data());
-  }
+                               TemporaryPath.data());
+    Path.assign(TemporaryPath.begin(), TemporaryPath.end());
+    TempFiles.push_back(Path.data());
+    return Error::success();
+  };
+  if (Error E = CreateTempFile("out", PPI.StdoutPath))
+    return E;
+  if (Error E = CreateTempFile("err", PPI.StderrPath))
+    return E;
 
   std::optional<StringRef> Redirects[] = {
       std::nullopt,                      // Stdin
@@ -893,19 +899,19 @@ Error DataAggregator::parseAllInputs(BinaryContext &BC) {
               inconvertibleErrorCode(), "%s: %s%s", Job->DA->Filename.c_str(),
               Job->DiagBuffer.c_str(), toString(std::move(E)).c_str());
         }
-        Job->DA->Parsed = true;
+        Job->DA->setParsed(true);
         return Error::success();
       });
   parallel::strategy = SavedStrategy;
 
   for (AggregatorJob *Job : Jobs) {
-    if (Job->DA->Parsed)
+    if (Job->DA->getParsed())
       mergeFrom(*Job->DA);
     delete Job->DA;
     delete Job;
   }
 
-  if (!Parsed)
+  if (!getParsed())
     return ParseErrors;
   handleAllErrors(std::move(ParseErrors), [](const ErrorInfoBase &EI) {
     errs() << "PERF2BOLT-WARNING: " << EI.message() << "\n";
diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp
index 7fcaffd763ad3..8d5719e13f839 100644
--- a/bolt/lib/Profile/DataReader.cpp
+++ b/bolt/lib/Profile/DataReader.cpp
@@ -314,7 +314,7 @@ Error DataReader::readProfilePreCFG(BinaryContext &BC) {
       else
         MemAccessProfile.NextInstrOffset = II->first;
     }
-    Function.HasMemoryProfile = true;
+    Function.setHasMemoryProfileFlag(true);
   }
 
   return Error::success();
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 829dc998d623b..964ec219fdbac 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1423,7 +1423,7 @@ void RewriteInstance::discoverFileObjects() {
           BC->errs() << '\n';
       }
       BC->HasSplitFunctions = true;
-      BF->IsFragment = true;
+      BF->setIsFragmentFlag(true);
     }
 
     if (!AlternativeName.empty())
diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp
index a436200c81e13..1cc94979439f7 100644
--- a/bolt/unittests/Core/BinaryContext.cpp
+++ b/bolt/unittests/Core/BinaryContext.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "bolt/Core/BinaryContext.h"
+#include "bolt/Core/BinaryFunction.h"
 #include "bolt/Rewrite/RewriteInstance.h"
 #include "bolt/Utils/CommandLineOpts.h"
 #include "llvm/BinaryFormat/ELF.h"
@@ -73,6 +74,25 @@ struct BinaryContextTester : public testing::TestWithParam<Triple::ArchType> {
 
 } // namespace
 
+TEST_P(BinaryContextTester, FunctionMetadataFlags) {
+  BC->registerOrUpdateSection(".pseudo_probe_desc", ELF::SHT_PROGBITS, 0);
+  BC->registerOrUpdateSection(".pseudo_probe", ELF::SHT_PROGBITS, 0);
+  BinaryFunction *Function = BC->createInjectedBinaryFunction("metadata", true);
+  ASSERT_TRUE(Function->hasPseudoProbe());
+  EXPECT_FALSE(Function->hasMemoryProfile());
+  EXPECT_FALSE(Function->isFragment());
+  Function->setHasSDTMarker(true);
+  EXPECT_TRUE(Function->hasSDTMarker());
+  EXPECT_TRUE(Function->hasPseudoProbe());
+  EXPECT_FALSE(Function->hasMemoryProfile());
+  EXPECT_FALSE(Function->isFragment());
+  EXPECT_TRUE(Function->isSimple());
+  EXPECT_TRUE(Function->hasName("metadata"));
+  Function->setHasSDTMarker(false);
+  EXPECT_FALSE(Function->hasSDTMarker());
+  EXPECT_TRUE(Function->hasPseudoProbe());
+}
+
 #ifdef X86_AVAILABLE
 
 INSTANTIATE_TEST_SUITE_P(X86, BinaryContextTester,
diff --git a/clang-tools-extra/clang-move/Move.cpp b/clang-tools-extra/clang-move/Move.cpp
index 1f966b3119620..721a55ae9f207 100644
--- a/clang-tools-extra/clang-move/Move.cpp
+++ b/clang-tools-extra/clang-move/Move.cpp
@@ -763,7 +763,7 @@ void ClangMoveTool::removeDeclsInOldFiles() {
   for (auto &FileAndReplacements : Context->FileToReplacements) {
     StringRef FilePath = FileAndReplacements.first;
     // Add #include of new header to old header.
-    if (Context->Spec.OldDependOnNew &&
+    if (Context->Spec.getOldDependOnNew() &&
         MakeAbsolutePath(SM, FilePath) ==
             makeAbsolutePath(Context->Spec.OldHeader)) {
       // FIXME: Minimize the include path like clang-include-fixer.
@@ -827,7 +827,7 @@ void ClangMoveTool::moveDeclsToNewFiles() {
 
   if (!Context->Spec.NewHeader.empty()) {
     std::string OldHeaderInclude =
-        Context->Spec.NewDependOnOld
+        Context->Spec.getNewDependOnOld()
             ? "#include \"" + Context->Spec.OldHeader + "\"\n"
             : "";
     Context->FileToReplacements[Context->Spec.NewHeader] =
diff --git a/clang-tools-extra/clang-move/Move.h b/clang-tools-extra/clang-move/Move.h
index ba613abc03e19..316a5efd8f554 100644
--- a/clang-tools-extra/clang-move/Move.h
+++ b/clang-tools-extra/clang-move/Move.h
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include <map>
@@ -59,7 +60,7 @@ class DeclarationReporter {
 // declarations.
 struct MoveDefinitionSpec {
   // The list of fully qualified names, e.g. Foo, a::Foo, b::Foo.
-  SmallVector<std::string, 4> Names;
+  llvm::SmallVectorWithFlags<std::string, 4, 2> Names;
   // The file path of old header, can be relative path and absolute path.
   std::string OldHeader;
   // The file path of old cc, can be relative path and absolute path.
@@ -70,10 +71,12 @@ struct MoveDefinitionSpec {
   std::string NewCC;
   // Whether old.h depends on new.h. If true, #include "new.h" will be added
   // in old.h.
-  bool OldDependOnNew = false;
+  bool getOldDependOnNew() const { return Names.getFlag(0); }
+  void setOldDependOnNew(bool Value) { Names.setFlag(0, Value); }
   // Whether new.h depends on old.h. If true, #include "old.h" will be added
   // in new.h.
-  bool NewDependOnOld = false;
+  bool getNewDependOnOld() const { return Names.getFlag(1); }
+  void setNewDependOnOld(bool Value) { Names.setFlag(1, Value); }
 };
 
 // A Context which contains extra options which are used in ClangMoveTool.
diff --git a/clang-tools-extra/clang-move/tool/ClangMove.cpp b/clang-tools-extra/clang-move/tool/ClangMove.cpp
index d36ce89b611f5..d239448043f68 100644
--- a/clang-tools-extra/clang-move/tool/ClangMove.cpp
+++ b/clang-tools-extra/clang-move/tool/ClangMove.cpp
@@ -117,13 +117,13 @@ int main(int argc, const char **argv) {
   Tool.appendArgumentsAdjuster(tooling::getInsertArgumentAdjuster(
       "-fparse-all-comments", tooling::ArgumentInsertPosition::BEGIN));
   move::MoveDefinitionSpec Spec;
-  Spec.Names = {Names.begin(), Names.end()};
+  Spec.Names.assign(Names.begin(), Names.end());
   Spec.OldHeader = OldHeader;
   Spec.NewHeader = NewHeader;
   Spec.OldCC = OldCC;
   Spec.NewCC = NewCC;
-  Spec.OldDependOnNew = OldDependOnNew;
-  Spec.NewDependOnOld = NewDependOnOld;
+  Spec.setOldDependOnNew(OldDependOnNew);
+  Spec.setNewDependOnOld(NewDependOnOld);
 
   llvm::SmallString<128> InitialDirectory;
   if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
diff --git a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp
index e976a7eecbfcb..525f9fc5accc0 100644
--- a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include <initializer_list>
 #include <optional>
@@ -30,7 +31,8 @@ class BoostReplacer : public UseRangesCheck::Replacer {
 public:
   BoostReplacer(ArrayRef<UseRangesCheck::Signature> Signatures,
                 bool IncludeSystem)
-      : Signatures(Signatures), IncludeSystem(IncludeSystem) {}
+      : Signatures(decltype(this->Signatures)::withFlags(
+            unsigned(IncludeSystem), Signatures)) {}
 
   ArrayRef<UseRangesCheck::Signature> getReplacementSignatures() const final {
     return Signatures;
@@ -52,15 +54,16 @@ class BoostReplacer : public UseRangesCheck::Replacer {
   std::optional<std::string>
   getHeaderInclusion(const NamedDecl &OriginalName) const final {
     auto [Path, HeaderName] = getBoostHeader(OriginalName);
-    return ((IncludeSystem ? "<boost/" : "boost/") + Path +
+    return ((getIncludeSystem() ? "<boost/" : "boost/") + Path +
             (Path.empty() ? "" : "/") + HeaderName +
-            (IncludeSystem ? ".hpp>" : ".hpp"))
+            (getIncludeSystem() ? ".hpp>" : ".hpp"))
         .str();
   }
 
 private:
-  SmallVector<UseRangesCheck::Signature> Signatures;
-  bool IncludeSystem;
+  llvm::SmallVectorWithFlags<UseRangesCheck::Signature> Signatures;
+  bool getIncludeSystem() const { return Signatures.getFlag(0); }
+  void setIncludeSystem(bool Value) { Signatures.setFlag(0, Value); }
 };
 
 /// Creates replaces where the header file lives in
diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
index f7c0024fc1fd1..0c7b608abde22 100644
--- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
@@ -14,6 +14,7 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include <string>
 
@@ -87,16 +88,22 @@ AST_MATCHER_P2(Expr, hasSideEffect, bool, CheckFunctionCalls,
 AssertSideEffectCheck::AssertSideEffectCheck(StringRef Name,
                                              ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      CheckFunctionCalls(Options.get("CheckFunctionCalls", false)),
       RawAssertList(Options.get("AssertMacros", "assert,NSAssert,NSCAssert")),
+      AssertMacros(decltype(this->AssertMacros)::withFlags([&] {
+        unsigned PackedFlags = 0;
+        PackedFlags |= unsigned(bool(Options.get("CheckFunctionCalls", false)));
+        return PackedFlags;
+      }())),
       IgnoredFunctions(utils::options::parseListPair(
           "__builtin_expect;", Options.get("IgnoredFunctions", ""))) {
-  RawAssertList.split(AssertMacros, ",", -1, false);
+  for (StringRef Macro : llvm::split(RawAssertList, ','))
+    if (!Macro.empty())
+      AssertMacros.push_back(Macro);
 }
 
 // The options are explained in AssertSideEffectCheck.h.
 void AssertSideEffectCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
-  Options.store(Opts, "CheckFunctionCalls", CheckFunctionCalls);
+  Options.store(Opts, "CheckFunctionCalls", getCheckFunctionCalls());
   Options.store(Opts, "AssertMacros", RawAssertList);
   Options.store(Opts, "IgnoredFunctions",
                 utils::options::serializeStringList(IgnoredFunctions));
@@ -106,9 +113,9 @@ void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) {
   const auto IgnoredFunctionsMatcher =
       matchers::matchesAnyListedRegexName(IgnoredFunctions);
 
-  const auto DescendantWithSideEffect =
-      traverse(TK_AsIs, hasDescendant(expr(hasSideEffect(
-                            CheckFunctionCalls, IgnoredFunctionsMatcher))));
+  const auto DescendantWithSideEffect = traverse(
+      TK_AsIs, hasDescendant(expr(hasSideEffect(getCheckFunctionCalls(),
+                                                IgnoredFunctionsMatcher))));
   const auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect);
   Finder->addMatcher(
       stmt(
diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
index b65e1a19e81ac..4b89445e98d41 100644
--- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.h
@@ -11,6 +11,7 @@
 
 #include "../ClangTidyCheck.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include <string>
 
@@ -37,10 +38,16 @@ class AssertSideEffectCheck : public ClangTidyCheck {
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 
 private:
-  const bool CheckFunctionCalls;
+  bool getCheckFunctionCalls() const { return AssertMacros.getFlag(0); }
   const StringRef RawAssertList;
-  SmallVector<StringRef, 5> AssertMacros;
+  llvm::SmallVectorWithFlags<StringRef, 5> AssertMacros;
   const std::vector<StringRef> IgnoredFunctions;
+
+public:
+  AssertSideEffectCheck(const AssertSideEffectCheck &) = default;
+  AssertSideEffectCheck(AssertSideEffectCheck &&) = default;
+  AssertSideEffectCheck &operator=(const AssertSideEffectCheck &) = delete;
+  AssertSideEffectCheck &operator=(AssertSideEffectCheck &&) = delete;
 };
 
 } // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
index 3cf0173aaa002..4702c0ec9eda0 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -98,9 +99,10 @@ struct CallableInfo {
 
 struct LambdaProperties {
   CallableInfo Callable;
-  SmallVector<BindArgument, 4> BindArguments;
+  llvm::SmallVectorWithFlags<BindArgument, 4> BindArguments;
   StringRef BindNamespace;
-  bool IsFixitSupported = false;
+  bool getIsFixitSupported() const { return BindArguments.getFlag(0); }
+  void setIsFixitSupported(bool Value) { BindArguments.setFlag(0, Value); }
 };
 
 } // end namespace
@@ -568,9 +570,9 @@ getLambdaProperties(const MatchFinder::MatchResult &Result) {
     LP.Callable.CaptureInitializer = getSourceTextForExpr(Result, CalleeExpr);
   }
 
-  LP.BindArguments = buildBindArguments(Result, LP.Callable);
+  LP.BindArguments.assign(buildBindArguments(Result, LP.Callable));
 
-  LP.IsFixitSupported = isFixitSupported(LP.Callable, LP.BindArguments);
+  LP.setIsFixitSupported(isFixitSupported(LP.Callable, LP.BindArguments));
 
   return LP;
 }
@@ -654,7 +656,7 @@ void AvoidBindCheck::check(const MatchFinder::MatchResult &Result) {
   const auto Diag =
       diag(MatchedDecl->getBeginLoc(),
            formatv("prefer a lambda to {0}::bind", LP.BindNamespace).str());
-  if (!LP.IsFixitSupported)
+  if (!LP.getIsFixitSupported())
     return;
 
   const auto *Ref = Result.Nodes.getNodeAs<Expr>("ref");
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 75bf2a7325900..1ea9b1e9abdcc 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -515,7 +515,7 @@ static bool canBeModified(ASTContext *Context, const Expr *E) {
 
 /// Returns true when it can be guaranteed that the elements of the
 /// container are not being modified.
-static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {
+static bool usagesAreConst(ASTContext *Context, ArrayRef<Usage> Usages) {
   return llvm::none_of(Usages, [&Context](const Usage &U) {
     // Lambda captures are just redeclarations (VarDecl) of the same variable,
     // not expressions. If we want to know if a variable that is captured by
@@ -530,7 +530,7 @@ static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {
 
 /// Returns true if the elements of the container are never accessed
 /// by reference.
-static bool usagesReturnRValues(const UsageResult &Usages) {
+static bool usagesReturnRValues(ArrayRef<Usage> Usages) {
   return llvm::all_of(Usages, [](const Usage &U) {
     return !U.Expression || U.Expression->isPRValue();
   });
@@ -663,7 +663,7 @@ void LoopConvertCheck::getAliasRange(SourceManager &SM, SourceRange &Range) {
 /// applies them.
 void LoopConvertCheck::doConversion(
     ASTContext *Context, const VarDecl *IndexVar,
-    const ValueDecl *MaybeContainer, const UsageResult &Usages,
+    const ValueDecl *MaybeContainer, ArrayRef<Usage> Usages,
     const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit,
     const ForStmt *Loop, RangeDescriptor Descriptor) {
   std::string VarNameOrStructuredBinding;
@@ -868,7 +868,7 @@ StringRef LoopConvertCheck::getContainerString(ASTContext *Context,
 void LoopConvertCheck::getArrayLoopQualifiers(ASTContext *Context,
                                               const BoundNodes &Nodes,
                                               const Expr *ContainerExpr,
-                                              const UsageResult &Usages,
+                                              ArrayRef<Usage> Usages,
                                               RangeDescriptor &Descriptor) {
   // On arrays and pseudoarrays, we must figure out the qualifiers from the
   // usages.
@@ -940,8 +940,8 @@ void LoopConvertCheck::getIteratorLoopQualifiers(ASTContext *Context,
 /// Determines the parameters needed to build the range replacement.
 void LoopConvertCheck::determineRangeDescriptor(
     ASTContext *Context, const BoundNodes &Nodes, const ForStmt *Loop,
-    LoopFixerKind FixerKind, const Expr *ContainerExpr,
-    const UsageResult &Usages, RangeDescriptor &Descriptor) {
+    LoopFixerKind FixerKind, const Expr *ContainerExpr, ArrayRef<Usage> Usages,
+    RangeDescriptor &Descriptor) {
   Descriptor.ContainerString =
       std::string(getContainerString(Context, Loop, ContainerExpr));
   Descriptor.NeedsReverseCall = (FixerKind == LFK_ReverseIterator);
@@ -1092,7 +1092,7 @@ void LoopConvertCheck::check(const MatchFinder::MatchResult &Result) {
 
   // Find out which qualifiers we have to use in the loop range.
   const TraversalKindScope RAII(*Context, TK_AsIs);
-  const UsageResult &Usages = Finder.getUsages();
+  ArrayRef<Usage> Usages = Finder.getUsages();
   determineRangeDescriptor(Context, Nodes, Loop, FixerKind, ContainerExpr,
                            Usages, Descriptor);
 
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h
index 958b4eb4ea2a5..cfe148334afb6 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.h
@@ -41,7 +41,7 @@ class LoopConvertCheck : public ClangTidyCheck {
   void getAliasRange(SourceManager &SM, SourceRange &DeclRange);
 
   void doConversion(ASTContext *Context, const VarDecl *IndexVar,
-                    const ValueDecl *MaybeContainer, const UsageResult &Usages,
+                    const ValueDecl *MaybeContainer, ArrayRef<Usage> Usages,
                     const DeclStmt *AliasDecl, bool AliasUseRequired,
                     bool AliasFromForInit, const ForStmt *Loop,
                     RangeDescriptor Descriptor);
@@ -51,8 +51,7 @@ class LoopConvertCheck : public ClangTidyCheck {
 
   void getArrayLoopQualifiers(ASTContext *Context,
                               const ast_matchers::BoundNodes &Nodes,
-                              const Expr *ContainerExpr,
-                              const UsageResult &Usages,
+                              const Expr *ContainerExpr, ArrayRef<Usage> Usages,
                               RangeDescriptor &Descriptor);
 
   void getIteratorLoopQualifiers(ASTContext *Context,
@@ -63,7 +62,7 @@ class LoopConvertCheck : public ClangTidyCheck {
                                 const ast_matchers::BoundNodes &Nodes,
                                 const ForStmt *Loop, LoopFixerKind FixerKind,
                                 const Expr *ContainerExpr,
-                                const UsageResult &Usages,
+                                ArrayRef<Usage> Usages,
                                 RangeDescriptor &Descriptor);
 
   bool isConvertible(ASTContext *Context, const ast_matchers::BoundNodes &Nodes,
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
index f173de2c52bc0..0ee44409c80ca 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
@@ -450,8 +450,8 @@ ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context,
                                                bool ContainerNeedsDereference)
     : Context(Context), IndexVar(IndexVar), EndVar(EndVar),
       ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
-      ContainerNeedsDereference(ContainerNeedsDereference),
-
+      Usages(decltype(this->Usages)::withFlags(
+          unsigned(ContainerNeedsDereference))),
       ConfidenceLevel(Confidence::CL_Safe) {
   if (ContainerExpr)
     addComponent(ContainerExpr);
@@ -459,7 +459,7 @@ ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context,
 
 bool ForLoopIndexUseVisitor::findAndVerifyUsages(const Stmt *Body) {
   TraverseStmt(const_cast<Stmt *>(Body));
-  return OnlyUsedAsIndex && ContainerExpr;
+  return getOnlyUsedAsIndex() && ContainerExpr;
 }
 
 void ForLoopIndexUseVisitor::addComponents(const ComponentVector &Components) {
@@ -557,7 +557,7 @@ bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
   if (Obj && exprReferencesVariable(IndexVar, Obj)) {
     // Member calls on the iterator with '.' are not allowed.
     if (!Member->isArrow()) {
-      OnlyUsedAsIndex = false;
+      setOnlyUsedAsIndex(false);
       return true;
     }
 
@@ -604,7 +604,7 @@ bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr(
   if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1 &&
       isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar,
                              Member->getBase(), ContainerExpr,
-                             ContainerNeedsDereference)) {
+                             getContainerNeedsDereference())) {
     addUsage(Usage(MemberCall));
     return true;
   }
@@ -649,7 +649,7 @@ bool ForLoopIndexUseVisitor::TraverseCXXOperatorCallExpr(
       break;
     if (isIndexInSubscriptExpr(Context, OpCall->getArg(1), IndexVar,
                                OpCall->getArg(0), ContainerExpr,
-                               ContainerNeedsDereference)) {
+                               getContainerNeedsDereference())) {
       addUsage(Usage(OpCall));
       return true;
     }
@@ -691,7 +691,7 @@ bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
                              ArrayBoundExpr)) {
     // If we have already discovered the array being indexed and this isn't it
     // or this array doesn't match, mark this loop as unconvertible.
-    OnlyUsedAsIndex = false;
+    setOnlyUsedAsIndex(false);
     return VisitorBase::TraverseArraySubscriptExpr(E);
   }
 
@@ -739,7 +739,7 @@ bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
   if (areSameVariable(IndexVar, TheDecl) ||
       exprReferencesVariable(IndexVar, E) || areSameVariable(EndVar, TheDecl) ||
       exprReferencesVariable(EndVar, E))
-    OnlyUsedAsIndex = false;
+    setOnlyUsedAsIndex(false);
   if (containsExpr(Context, &DependentExprs, E))
     ConfidenceLevel.lowerTo(Confidence::CL_Risky);
   return true;
@@ -798,13 +798,13 @@ bool ForLoopIndexUseVisitor::VisitDeclStmt(DeclStmt *S) {
     if (CurrStmtParent) {
       if (isa<IfStmt>(CurrStmtParent) || isa<WhileStmt>(CurrStmtParent) ||
           isa<SwitchStmt>(CurrStmtParent)) {
-        ReplaceWithAliasUse = true;
+        setReplaceWithAliasUse(true);
       } else if (isa<ForStmt>(CurrStmtParent)) {
         if (cast<ForStmt>(CurrStmtParent)->getConditionVariableDeclStmt() == S)
-          ReplaceWithAliasUse = true;
+          setReplaceWithAliasUse(true);
         else
           // It's assumed S came the for loop's init clause.
-          AliasFromForInit = true;
+          setAliasFromForInit(true);
       }
     }
   }
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
index 1415af6061783..f8ecd271712b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
@@ -15,6 +15,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <algorithm>
 #include <memory>
 #include <string>
@@ -304,7 +305,7 @@ class ForLoopIndexUseVisitor
   void addComponents(const ComponentVector &Components);
 
   /// Accessor for Usages.
-  const UsageResult &getUsages() const { return Usages; }
+  ArrayRef<Usage> getUsages() const { return Usages; }
 
   /// Adds the Usage if it was not added before.
   void addUsage(const Usage &U);
@@ -325,12 +326,12 @@ class ForLoopIndexUseVisitor
   /// simply be removed but rather replaced with a use of the alias variable.
   /// For example, variables declared in the condition of an if, switch, or for
   /// stmt.
-  bool aliasUseRequired() const { return ReplaceWithAliasUse; }
+  bool aliasUseRequired() const { return getReplaceWithAliasUse(); }
 
   /// Indicates if the alias declaration came from the init clause of a
   /// nested for loop. SourceRanges provided by Clang for DeclStmts in this
   /// case need to be adjusted.
-  bool aliasFromForInit() const { return AliasFromForInit; }
+  bool aliasFromForInit() const { return getAliasFromForInit(); }
 
 private:
   /// Typedef used in CRTP functions.
@@ -365,14 +366,19 @@ class ForLoopIndexUseVisitor
   const Expr *ContainerExpr;
   /// The Expr which refers to the terminating condition for array-based loops.
   const Expr *ArrayBoundExpr;
-  bool ContainerNeedsDereference;
+  bool getContainerNeedsDereference() const { return Usages.getFlag(0); }
+  void setContainerNeedsDereference(bool Value) { Usages.setFlag(0, Value); }
 
   // Output member variables:
   /// A container which holds all usages of IndexVar as the index of
   /// ArraySubscriptExpressions.
-  UsageResult Usages;
+  llvm::SmallVectorWithFlagsFor<UsageResult, 4> Usages;
   llvm::SmallSet<SourceLocation, 8> UsageLocations;
-  bool OnlyUsedAsIndex = true;
+  bool getOnlyUsedAsIndex() const { return !Usages.getFlag(1); }
+  bool setOnlyUsedAsIndex(bool Value) {
+    Usages.setFlag(1, !Value);
+    return Value;
+  }
   /// The DeclStmt for an alias to the container element.
   const DeclStmt *AliasDecl = nullptr;
   Confidence ConfidenceLevel;
@@ -392,9 +398,17 @@ class ForLoopIndexUseVisitor
   const Stmt *CurrStmtParent = nullptr;
 
   /// \see aliasUseRequired().
-  bool ReplaceWithAliasUse = false;
+  bool getReplaceWithAliasUse() const { return Usages.getFlag(2); }
+  bool setReplaceWithAliasUse(bool Value) {
+    Usages.setFlag(2, Value);
+    return Value;
+  }
   /// \see aliasFromForInit().
-  bool AliasFromForInit = false;
+  bool getAliasFromForInit() const { return Usages.getFlag(3); }
+  bool setAliasFromForInit(bool Value) {
+    Usages.setFlag(3, Value);
+    return Value;
+  }
 };
 
 struct TUTrackingInfo {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 42a16c8739808..b7f2ad7dc7462 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -13,6 +13,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringExtras.h"
 
 using namespace clang;
 using namespace clang::ast_matchers;
@@ -92,7 +93,7 @@ void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
           unless(hasAncestor(functionDecl(isDefaulted())))),
       this);
 
-  if (UseNullptrT)
+  if (getUseNullptrT())
     Finder->addMatcher(typeLoc(loc(decltypeType(decltypeTypeNullptrLiteral())))
                            .bind("matchDecltypeNullptr"),
                        this);
@@ -509,13 +510,17 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
 UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
+      NullMacros(decltype(this->NullMacros)::withFlags([&] {
+        unsigned PackedFlags = 0;
+        PackedFlags |= unsigned(bool(Options.get("UseNullptrT", true)));
+        return PackedFlags;
+      }())),
       IgnoredTypes(utils::options::parseStringList(
           Options.get("IgnoredTypes", DefaultIgnoredTypes))),
-      UseNullptrT(Options.get("UseNullptrT", true)),
       IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
                                                utils::IncludeSorter::IS_LLVM),
                       areDiagsSelfContained()) {
-  NullMacrosStr.split(NullMacros, ",");
+  llvm::append_range(NullMacros, llvm::split(NullMacrosStr, ','));
 }
 
 void UseNullptrCheck::registerPPCallbacks(const SourceManager &SM,
@@ -529,7 +534,7 @@ void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoredTypes",
                 utils::options::serializeStringList(IgnoredTypes));
   Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
-  Options.store(Opts, "UseNullptrT", UseNullptrT);
+  Options.store(Opts, "UseNullptrT", getUseNullptrT());
 }
 
 void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
index 7f3eb6e4dd18b..ef8a3a3bf790d 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
@@ -11,6 +11,7 @@
 
 #include "../ClangTidyCheck.h"
 #include "../utils/IncludeInserter.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang::tidy::modernize {
 
@@ -28,10 +29,16 @@ class UseNullptrCheck : public ClangTidyCheck {
 
 private:
   const StringRef NullMacrosStr;
-  SmallVector<StringRef, 1> NullMacros;
+  llvm::SmallVectorWithFlags<StringRef, 1> NullMacros;
   std::vector<StringRef> IgnoredTypes;
-  const bool UseNullptrT;
+  bool getUseNullptrT() const { return NullMacros.getFlag(0); }
   utils::IncludeInserter IncludeInserter;
+
+public:
+  UseNullptrCheck(const UseNullptrCheck &) = default;
+  UseNullptrCheck(UseNullptrCheck &&) = default;
+  UseNullptrCheck &operator=(const UseNullptrCheck &) = delete;
+  UseNullptrCheck &operator=(UseNullptrCheck &&) = delete;
 };
 
 } // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
index c0b11b7fc1afb..d38779d839cdb 100644
--- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp
@@ -72,18 +72,33 @@ const char DefaultIgnoredFloatingPointValues[] = "1.0;100.0;";
 
 MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      IgnoreAllFloatingPointValues(
-          Options.get("IgnoreAllFloatingPointValues", false)),
-      IgnoreBitFieldsWidths(Options.get("IgnoreBitFieldsWidths", true)),
-      IgnorePowersOf2IntegerValues(
-          Options.get("IgnorePowersOf2IntegerValues", false)),
-      IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)),
-      IgnoreUserDefinedLiterals(
-          Options.get("IgnoreUserDefinedLiterals", false)),
       RawIgnoredIntegerValues(
           Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues)),
       RawIgnoredFloatingPointValues(Options.get(
-          "IgnoredFloatingPointValues", DefaultIgnoredFloatingPointValues)) {
+          "IgnoredFloatingPointValues", DefaultIgnoredFloatingPointValues)),
+      IgnoredFloatingPointValues(
+          decltype(this->IgnoredFloatingPointValues)::withFlags([&] {
+            unsigned PackedFlags = 0;
+            PackedFlags |= unsigned(
+                bool(Options.get("IgnoreAllFloatingPointValues", false)));
+            PackedFlags |=
+                (unsigned(bool(Options.get("IgnoreBitFieldsWidths", true)))
+                 << 1);
+            PackedFlags |=
+                (unsigned(
+                     bool(Options.get("IgnorePowersOf2IntegerValues", false)))
+                 << 2);
+            PackedFlags |=
+                (unsigned(bool(Options.get("IgnoreTypeAliases", false))) << 3);
+            return PackedFlags;
+          }())),
+      IgnoredDoublePointValues(
+          decltype(this->IgnoredDoublePointValues)::withFlags([&] {
+            unsigned PackedFlags = 0;
+            PackedFlags |=
+                unsigned(bool(Options.get("IgnoreUserDefinedLiterals", false)));
+            return PackedFlags;
+          }())) {
   // Process the set of ignored integer values.
   const std::vector<StringRef> IgnoredIntegerValuesInput =
       utils::options::parseStringList(RawIgnoredIntegerValues);
@@ -96,7 +111,7 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
                   });
   llvm::sort(IgnoredIntegerValues);
 
-  if (!IgnoreAllFloatingPointValues) {
+  if (!getIgnoreAllFloatingPointValues()) {
     // Process the set of ignored floating point values.
     const std::vector<StringRef> IgnoredFloatingPointValuesInput =
         utils::options::parseStringList(RawIgnoredFloatingPointValues);
@@ -124,12 +139,13 @@ MagicNumbersCheck::MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
 
 void MagicNumbersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreAllFloatingPointValues",
-                IgnoreAllFloatingPointValues);
-  Options.store(Opts, "IgnoreBitFieldsWidths", IgnoreBitFieldsWidths);
+                getIgnoreAllFloatingPointValues());
+  Options.store(Opts, "IgnoreBitFieldsWidths", getIgnoreBitFieldsWidths());
   Options.store(Opts, "IgnorePowersOf2IntegerValues",
-                IgnorePowersOf2IntegerValues);
-  Options.store(Opts, "IgnoreTypeAliases", IgnoreTypeAliases);
-  Options.store(Opts, "IgnoreUserDefinedLiterals", IgnoreUserDefinedLiterals);
+                getIgnorePowersOf2IntegerValues());
+  Options.store(Opts, "IgnoreTypeAliases", getIgnoreTypeAliases());
+  Options.store(Opts, "IgnoreUserDefinedLiterals",
+                getIgnoreUserDefinedLiterals());
   Options.store(Opts, "IgnoredIntegerValues", RawIgnoredIntegerValues);
   Options.store(Opts, "IgnoredFloatingPointValues",
                 RawIgnoredFloatingPointValues);
@@ -137,7 +153,7 @@ void MagicNumbersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
 
 void MagicNumbersCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(integerLiteral().bind("integer"), this);
-  if (!IgnoreAllFloatingPointValues)
+  if (!getIgnoreAllFloatingPointValues())
     Finder->addMatcher(floatLiteral().bind("float"), this);
 }
 
@@ -156,7 +172,7 @@ bool MagicNumbersCheck::isConstant(const MatchFinder::MatchResult &Result,
         if (isUsedToInitializeAConstant(Result, Parent))
           return true;
 
-        if (IgnoreTypeAliases && isUsedToDefineATypeAlias(Result, Parent))
+        if (getIgnoreTypeAliases() && isUsedToDefineATypeAlias(Result, Parent))
           return true;
 
         // Ignore this instance, because this matches an
@@ -195,7 +211,7 @@ bool MagicNumbersCheck::isIgnoredValue(const IntegerLiteral *Literal) const {
   if (Value == 0)
     return true;
 
-  if (IgnorePowersOf2IntegerValues && IntValue.isPowerOf2())
+  if (getIgnorePowersOf2IntegerValues() && IntValue.isPowerOf2())
     return true;
 
   return llvm::binary_search(IgnoredIntegerValues, Value);
@@ -235,7 +251,7 @@ bool MagicNumbersCheck::isSyntheticValue(const SourceManager *SourceManager,
 bool MagicNumbersCheck::isBitFieldWidth(
     const ast_matchers::MatchFinder::MatchResult &Result,
     const IntegerLiteral &Literal) const {
-  return IgnoreBitFieldsWidths &&
+  return getIgnoreBitFieldsWidths() &&
          llvm::any_of(Result.Context->getParents(Literal),
                       [&Result](const DynTypedNode &Parent) {
                         return isUsedToDefineABitField(Result, Parent);
diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
index ca64880c030cf..330a3ca47d989 100644
--- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.h
@@ -11,6 +11,7 @@
 
 #include "../ClangTidyCheck.h"
 #include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <llvm/ADT/APFloat.h>
 #include <llvm/ADT/SmallVector.h>
 
@@ -75,7 +76,7 @@ class MagicNumbersCheck : public ClangTidyCheck {
     if (isBitFieldWidth(Result, *MatchedLiteral))
       return;
 
-    if (IgnoreUserDefinedLiterals &&
+    if (getIgnoreUserDefinedLiterals() &&
         isUserDefinedLiteral(Result, *MatchedLiteral))
       return;
 
@@ -88,11 +89,21 @@ class MagicNumbersCheck : public ClangTidyCheck {
         << LiteralSourceText;
   }
 
-  const bool IgnoreAllFloatingPointValues;
-  const bool IgnoreBitFieldsWidths;
-  const bool IgnorePowersOf2IntegerValues;
-  const bool IgnoreTypeAliases;
-  const bool IgnoreUserDefinedLiterals;
+  bool getIgnoreAllFloatingPointValues() const {
+    return IgnoredFloatingPointValues.getFlag(0);
+  }
+  bool getIgnoreBitFieldsWidths() const {
+    return IgnoredFloatingPointValues.getFlag(1);
+  }
+  bool getIgnorePowersOf2IntegerValues() const {
+    return IgnoredFloatingPointValues.getFlag(2);
+  }
+  bool getIgnoreTypeAliases() const {
+    return IgnoredFloatingPointValues.getFlag(3);
+  }
+  bool getIgnoreUserDefinedLiterals() const {
+    return IgnoredDoublePointValues.getFlag(0);
+  }
   const StringRef RawIgnoredIntegerValues;
   const StringRef RawIgnoredFloatingPointValues;
 
@@ -103,10 +114,16 @@ class MagicNumbersCheck : public ClangTidyCheck {
 
   SmallVector<int64_t, SensibleNumberOfMagicValueExceptions>
       IgnoredIntegerValues;
-  SmallVector<float, SensibleNumberOfMagicValueExceptions>
+  llvm::SmallVectorWithFlags<float, SensibleNumberOfMagicValueExceptions, 4>
       IgnoredFloatingPointValues;
-  SmallVector<double, SensibleNumberOfMagicValueExceptions>
+  llvm::SmallVectorWithFlags<double, SensibleNumberOfMagicValueExceptions>
       IgnoredDoublePointValues;
+
+public:
+  MagicNumbersCheck(const MagicNumbersCheck &) = default;
+  MagicNumbersCheck(MagicNumbersCheck &&) = default;
+  MagicNumbersCheck &operator=(const MagicNumbersCheck &) = delete;
+  MagicNumbersCheck &operator=(MagicNumbersCheck &&) = delete;
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
index 99f57374f3bda..5bcf749d17013 100644
--- a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
@@ -28,14 +28,18 @@ NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
           llvm::Regex::IgnoreCase),
       ShortNamespaceLines(Options.get("ShortNamespaceLines", 1U)),
       SpacesBeforeComments(Options.get("SpacesBeforeComments", 1U)),
-      AllowOmittingNamespaceComments(
-          Options.get("AllowOmittingNamespaceComments", false)) {}
+      Ends(decltype(this->Ends)::withFlags([&] {
+        unsigned PackedFlags = 0;
+        PackedFlags |= unsigned(
+            bool(Options.get("AllowOmittingNamespaceComments", false)));
+        return PackedFlags;
+      }())) {}
 
 void NamespaceCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "ShortNamespaceLines", ShortNamespaceLines);
   Options.store(Opts, "SpacesBeforeComments", SpacesBeforeComments);
   Options.store(Opts, "AllowOmittingNamespaceComments",
-                AllowOmittingNamespaceComments);
+                getAllowOmittingNamespaceComments());
 }
 
 void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
@@ -193,7 +197,7 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
           : ("namespace '" + *NamespaceNameAsWritten + "'");
 
   // If no namespace comment is allowed
-  if (!HasComment && AllowOmittingNamespaceComments)
+  if (!HasComment && getAllowOmittingNamespaceComments())
     return;
 
   std::string Fix(SpacesBeforeComments, ' ');
diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
index 68902428e9bab..328ff8184a112 100644
--- a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NAMESPACECOMMENTCHECK_H
 
 #include "../ClangTidyCheck.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Regex.h"
 
 namespace clang::tidy::readability {
@@ -34,8 +35,8 @@ class NamespaceCommentCheck : public ClangTidyCheck {
   llvm::Regex NamespaceCommentPattern;
   const unsigned ShortNamespaceLines;
   const unsigned SpacesBeforeComments;
-  const bool AllowOmittingNamespaceComments;
-  SmallVector<SourceLocation, 4> Ends;
+  bool getAllowOmittingNamespaceComments() const { return Ends.getFlag(0); }
+  llvm::SmallVectorWithFlags<SourceLocation, 4> Ends;
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
index 22237863ff041..4d82506c86298 100644
--- a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
+++ b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp
@@ -50,6 +50,7 @@
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -82,22 +83,35 @@ struct DriverArgs {
   // Name of the driver program to execute or absolute path to it.
   std::string Driver;
   // Whether certain includes should be part of query.
-  bool StandardIncludes = true;
-  bool StandardCXXIncludes = true;
+  bool getStandardIncludes() const { return !Specs.getFlag(0); }
+  bool setStandardIncludes(bool Value) {
+    Specs.setFlag(0, !Value);
+    return Value;
+  }
+  bool getStandardCXXIncludes() const { return !Specs.getFlag(1); }
+  bool setStandardCXXIncludes(bool Value) {
+    Specs.setFlag(1, !Value);
+    return Value;
+  }
   // Language to use while querying.
   std::string Lang;
   std::string Sysroot;
   std::string ISysroot;
   std::string Target;
   std::string Stdlib;
-  llvm::SmallVector<std::string> Specs;
+  llvm::SmallVectorWithFlags<
+      std::string,
+      llvm::CalculateSmallVectorDefaultInlinedElements<std::string>::value, 2>
+      Specs;
 
   bool operator==(const DriverArgs &RHS) const {
-    return std::tie(Driver, StandardIncludes, StandardCXXIncludes, Lang,
-                    Sysroot, ISysroot, Target, Stdlib, Specs) ==
-           std::tie(RHS.Driver, RHS.StandardIncludes, RHS.StandardCXXIncludes,
-                    RHS.Lang, RHS.Sysroot, RHS.ISysroot, RHS.Target, RHS.Stdlib,
-                    RHS.Specs);
+    return getStandardIncludes() == RHS.getStandardIncludes() &&
+           getStandardCXXIncludes() == RHS.getStandardCXXIncludes() &&
+           llvm::ArrayRef<std::string>(Specs) ==
+               llvm::ArrayRef<std::string>(RHS.Specs) &&
+           std::tie(Driver, Lang, Sysroot, ISysroot, Target, Stdlib) ==
+               std::tie(RHS.Driver, RHS.Lang, RHS.Sysroot, RHS.ISysroot,
+                        RHS.Target, RHS.Stdlib);
   }
 
   DriverArgs(const tooling::CompileCommand &Cmd, llvm::StringRef File) {
@@ -121,9 +135,9 @@ struct DriverArgs {
       }
       // Look for standard/builtin includes.
       else if (Arg == "-nostdinc" || Arg == "--no-standard-includes")
-        StandardIncludes = false;
+        setStandardIncludes(false);
       else if (Arg == "-nostdinc++")
-        StandardCXXIncludes = false;
+        setStandardCXXIncludes(false);
       // Figure out sysroot
       else if (Arg.consume_front("--sysroot")) {
         if (Arg.consume_front("="))
@@ -187,9 +201,9 @@ struct DriverArgs {
     // FIXME: Don't treat lang specially?
     assert(!Lang.empty());
     llvm::SmallVector<llvm::StringRef> Args = {"-x", Lang};
-    if (!StandardIncludes)
+    if (!getStandardIncludes())
       Args.push_back("-nostdinc");
-    if (!StandardCXXIncludes)
+    if (!getStandardCXXIncludes())
       Args.push_back("-nostdinc++");
     if (!Sysroot.empty())
       Args.append({"--sysroot", Sysroot});
@@ -218,8 +232,8 @@ template <> struct DenseMapInfo<DriverArgs> {
   static unsigned getHashValue(const DriverArgs &Val) {
     unsigned FixedFieldsHash = llvm::hash_value(std::tuple{
         Val.Driver,
-        Val.StandardIncludes,
-        Val.StandardCXXIncludes,
+        Val.getStandardIncludes(),
+        Val.getStandardCXXIncludes(),
         Val.Lang,
         Val.Sysroot,
         Val.ISysroot,
diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp
index 607b0382a2e98..01e6759e6a388 100644
--- a/clang-tools-extra/modularize/ModularizeUtilities.cpp
+++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp
@@ -335,7 +335,7 @@ bool ModularizeUtilities::collectModuleHeaders(const clang::Module &Mod) {
 
   // Ignore explicit modules because they often have dependencies
   // we can't know.
-  if (Mod.IsExplicit)
+  if (Mod.getIsExplicit())
     return true;
 
   // Treat headers in umbrella directory as dependencies.
diff --git a/clang-tools-extra/modularize/PreprocessorTracker.cpp b/clang-tools-extra/modularize/PreprocessorTracker.cpp
index 6205b97a17176..e464433c56c68 100644
--- a/clang-tools-extra/modularize/PreprocessorTracker.cpp
+++ b/clang-tools-extra/modularize/PreprocessorTracker.cpp
@@ -249,6 +249,7 @@
 #include "clang/Lex/MacroArgs.h"
 #include "clang/Lex/PPCallbacks.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -769,10 +770,10 @@ ConditionalExpansionMapIter;
 class PreprocessorTrackerImpl : public PreprocessorTracker {
 public:
   PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
-        bool DoBlockCheckHeaderListOnly)
-      : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
-        CurrentInclusionPathHandle(InclusionPathHandleInvalid),
-        InNestedHeader(false) {
+                          bool DoBlockCheckHeaderListOnly)
+      : HeaderList(decltype(HeaderList)::withFlags(
+            unsigned(DoBlockCheckHeaderListOnly))),
+        CurrentInclusionPathHandle(InclusionPathHandleInvalid) {
     // Use canonical header path representation.
     for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
       E = Headers.end();
@@ -804,7 +805,7 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
                               llvm::StringRef TargetPath) override {
     // If it's not a header in the header list, ignore it with respect to
     // the check.
-    if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
+    if (getBlockCheckHeaderListOnly() && !isHeaderListHeader(TargetPath))
       return;
     HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
     StringHandle IncludeHeaderHandle = addString(TargetPath);
@@ -876,8 +877,8 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
     if (H != getCurrentHeaderHandle())
       pushHeaderHandle(H);
     // Check for nested header.
-    if (!InNestedHeader)
-      InNestedHeader = !HeadersInThisCompile.insert(H).second;
+    if (!getInNestedHeader())
+      setInNestedHeader(!HeadersInThisCompile.insert(H).second);
   }
 
   // Handle exiting a header source file.
@@ -893,7 +894,7 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
         popHeaderHandle();
       } while ((TH != H) && (HeaderStack.size() != 0));
     }
-    InNestedHeader = false;
+    setInNestedHeader(false);
   }
 
   // Lookup/add string.
@@ -1022,7 +1023,7 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
                                  llvm::StringRef MacroUnexpanded,
                                  llvm::StringRef MacroExpanded,
                                  InclusionPathHandle InclusionPathHandle) {
-    if (InNestedHeader)
+    if (getInNestedHeader())
       return;
     StringHandle MacroName = addString(II->getName());
     PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
@@ -1071,7 +1072,7 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
                                   llvm::StringRef ConditionUnexpanded,
                                   InclusionPathHandle InclusionPathHandle) {
     // Ignore header guards, assuming the header guard is the only conditional.
-    if (InNestedHeader)
+    if (getInNestedHeader())
       return;
     StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
     PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
@@ -1222,9 +1223,10 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
   }
 
 private:
-  llvm::SmallVector<std::string, 32> HeaderList;
+  llvm::SmallVectorWithFlags<std::string, 32, 2> HeaderList;
   // Only do extern, namespace check for headers in HeaderList.
-  bool BlockCheckHeaderListOnly;
+  bool getBlockCheckHeaderListOnly() const { return HeaderList.getFlag(0); }
+  void setBlockCheckHeaderListOnly(bool Value) { HeaderList.setFlag(0, Value); }
   llvm::StringSet<> Strings;
   std::vector<StringHandle> HeaderPaths;
   std::vector<HeaderHandle> HeaderStack;
@@ -1234,7 +1236,8 @@ class PreprocessorTrackerImpl : public PreprocessorTracker {
   std::vector<PPItemKey> IncludeDirectives;
   MacroExpansionMap MacroExpansions;
   ConditionalExpansionMap ConditionalExpansions;
-  bool InNestedHeader;
+  bool getInNestedHeader() const { return HeaderList.getFlag(1); }
+  void setInNestedHeader(bool Value) { HeaderList.setFlag(1, Value); }
 };
 
 } // namespace
diff --git a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
index 082779358fbfb..471f2a289fd2a 100644
--- a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
+++ b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
@@ -527,7 +527,7 @@ TEST(ClangMove, AddDependentNewHeader) {
   Spec.OldCC = "foo.cc";
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
-  Spec.OldDependOnNew = true;
+  Spec.setOldDependOnNew(true);
   auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
   EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
   EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
@@ -552,7 +552,7 @@ TEST(ClangMove, AddDependentOldHeader) {
   Spec.OldCC = "foo.cc";
   Spec.NewHeader = "new_foo.h";
   Spec.NewCC = "new_foo.cc";
-  Spec.NewDependOnOld = true;
+  Spec.setNewDependOnOld(true);
   auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
   EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
   EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index 839146f40445b..c5190b5c2a96d 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <utility>
 
 namespace clang {
@@ -48,7 +49,8 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
   // The template-like entity that 'owns' the constraint checked here (can be a
   // constrained entity or a concept).
   const NamedDecl *ConstraintOwner = nullptr;
-  llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
+  /// Flag bits 0 and 1 record satisfaction and the presence of errors.
+  llvm::SmallVectorWithFlags<TemplateArgument, 4, 2> TemplateArgs;
 
 public:
 
@@ -58,8 +60,10 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
                          ArrayRef<TemplateArgument> TemplateArgs)
       : ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
 
-  bool IsSatisfied = false;
-  bool ContainsErrors = false;
+  bool isSatisfied() const { return TemplateArgs.getFlag(0); }
+  void setIsSatisfied(bool Value) { TemplateArgs.setFlag(0, Value); }
+  bool containsErrors() const { return TemplateArgs.getFlag(1); }
+  void setContainsErrors(bool Value) { TemplateArgs.setFlag(1, Value); }
 
   /// \brief The substituted constraint expr, if the template arguments could be
   /// substituted into them, or a diagnostic if substitution resulted in an
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 04cc2da25cecb..f0f3d2032009f 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -42,6 +42,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -245,7 +246,7 @@ struct QualTypeBoolInfo {
 class ASTContext : public RefCountedBase<ASTContext> {
   friend class NestedNameSpecifier;
 
-  mutable SmallVector<Type *, 0> Types;
+  mutable llvm::SmallVectorWithFlags<Type *, 0, 3> Types;
   mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
   mutable llvm::UniquingSet<ComplexType> ComplexTypes;
   mutable llvm::UniquingSet<PointerType> PointerTypes{GeneralTypesLog2InitSize};
@@ -838,10 +839,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   /// Address space map mangling must be used with language specific
   /// address spaces (e.g. OpenCL/CUDA)
-  bool AddrSpaceMapMangling;
+  bool getAddrSpaceMapMangling() const { return Types.getFlag(0); }
+  void setAddrSpaceMapMangling(bool Value) { Types.setFlag(0, Value); }
 
   /// For performance, track whether any function effects are in use.
-  mutable bool AnyFunctionEffects = false;
+  bool getAnyFunctionEffects() const { return Types.getFlag(1); }
+  bool setAnyFunctionEffects(bool Value) const {
+    Types.setFlag(1, Value);
+    return Value;
+  }
 
   const TargetInfo *Target = nullptr;
   const TargetInfo *AuxTarget = nullptr;
@@ -1048,7 +1054,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   RawCommentList Comments;
 
   /// True if comments are already loaded from ExternalASTSource.
-  mutable bool CommentsLoaded = false;
+  bool getCommentsLoaded() const { return Types.getFlag(2); }
+  void setCommentsLoaded(bool Value) const { Types.setFlag(2, Value); }
 
   /// Key used to look up the raw comment attached to a declaration or macro.
   using RawCommentLookupKey =
@@ -1520,7 +1527,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   ASTMutationListener *getASTMutationListener() const { return Listener; }
 
   void PrintStats() const;
-  const SmallVectorImpl<Type *>& getTypes() const { return Types; }
+  const llvm::SmallVectorWithFlagsImpl<Type *, 3> &getTypes() const {
+    return Types;
+  }
 
   BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
                                                 const IdentifierInfo *II) const;
@@ -3402,10 +3411,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   uint64_t getTargetNullPointerValue(QualType QT) const;
 
   bool addressSpaceMapManglingFor(LangAS AS) const {
-    return AddrSpaceMapMangling || isTargetAddressSpace(AS);
+    return getAddrSpaceMapMangling() || isTargetAddressSpace(AS);
   }
 
-  bool hasAnyFunctionEffects() const { return AnyFunctionEffects; }
+  bool hasAnyFunctionEffects() const { return getAnyFunctionEffects(); }
 
   // Merges two exception specifications, such that the resulting
   // exception spec is the union of both. For example, if either
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index 18ce5a94ebef3..d097e1d5d274b 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -454,7 +454,7 @@ class NestedRequirement : public Requirement {
                     const ConstraintSatisfaction &Satisfaction)
       : Requirement(RK_Nested, Constraint->isInstantiationDependent(),
                     Constraint->containsUnexpandedParameterPack(),
-                    Satisfaction.IsSatisfied),
+                    Satisfaction.isSatisfied()),
         Constraint(Constraint),
         Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {}
 
diff --git a/clang/include/clang/AST/VTTBuilder.h b/clang/include/clang/AST/VTTBuilder.h
index 3c19e61a8701c..17830367a49cf 100644
--- a/clang/include/clang/AST/VTTBuilder.h
+++ b/clang/include/clang/AST/VTTBuilder.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cstdint>
 
 namespace clang {
@@ -82,7 +83,7 @@ class VTTBuilder {
   using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>;
 
   /// The VTT components.
-  VTTComponentsVectorTy VTTComponents;
+  llvm::SmallVectorWithFlagsFor<VTTComponentsVectorTy, 1> VTTComponents;
 
   /// The AST record layout of the most derived class.
   const ASTRecordLayout &MostDerivedClassLayout;
@@ -99,7 +100,8 @@ class VTTBuilder {
   llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
 
   /// Whether the VTT builder should generate LLVM IR for the VTT.
-  bool GenerateDefinition;
+  bool getGenerateDefinition() const { return VTTComponents.getFlag(0); }
+  void setGenerateDefinition(bool Value) { VTTComponents.setFlag(0, Value); }
 
   /// Add a vtable pointer to the VTT currently being built.
   void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
@@ -138,9 +140,7 @@ class VTTBuilder {
              bool GenerateDefinition);
 
   // Returns a reference to the VTT components.
-  const VTTComponentsVectorTy &getVTTComponents() const {
-    return VTTComponents;
-  }
+  ArrayRef<VTTComponent> getVTTComponents() const { return VTTComponents; }
 
   // Returns a reference to the VTT vtables.
   const VTTVTablesVectorTy &getVTTVTables() const {
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index 16fe31a577fa1..b02033b5c086f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
@@ -402,9 +403,9 @@ class FactManager {
 
   void addCapturedField(const FieldDecl *FD) { CapturedFields.insert(FD); }
   bool isFieldCapturedByLambda(const FieldDecl *FD) const {
-    return IsThisCapturedByLambda || CapturedFields.contains(FD);
+    return BlockToFacts.getFlag(0) || CapturedFields.contains(FD);
   }
-  void setThisCapturedByLambda() { IsThisCapturedByLambda = true; }
+  void setThisCapturedByLambda() { BlockToFacts.setFlag(0, true); }
 
 private:
   /// Classifies every origin as persistent or block-local. Called by
@@ -416,8 +417,9 @@ class FactManager {
   FactID NextFactID{0};
   LoanManager LoanMgr;
   OriginManager OriginMgr;
-  /// Facts for each CFG block, indexed by block ID.
-  llvm::SmallVector<llvm::SmallVector<const Fact *>> BlockToFacts;
+  /// Facts for each CFG block, indexed by block ID. The flag tracks whether
+  /// any lambda captures the this pointer.
+  llvm::SmallVectorWithFlags<llvm::SmallVector<const Fact *>> BlockToFacts;
   llvm::BumpPtrAllocator FactAllocator;
   /// Bit vector indexed by origin ID. If set, the origin is referenced from
   /// more than one basic block and must participate in join operations. If
@@ -431,9 +433,6 @@ class FactManager {
   /// Set of field declarations that are explicitly or init-captured in any
   /// lambda within the analyzed function.
   llvm::DenseSet<const FieldDecl *> CapturedFields;
-  /// Whether the 'this' pointer is captured by any lambda within the analyzed
-  /// function. When true, any field of 'this' is considered captured.
-  bool IsThisCapturedByLambda = false;
 };
 } // namespace clang::lifetimes::internal
 
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
index f5f84f27b5035..3e56fd4934844 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h
@@ -22,6 +22,7 @@
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang::lifetimes::internal {
 
@@ -32,8 +33,9 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
   FactsGenerator(FactManager &FactMgr, AnalysisDeclContext &AC,
                  const LifetimeSafetyOpts &LSOpts)
       : FactMgr(FactMgr), AC(AC), LSOpts(LSOpts),
-        IsCMode(!AC.getASTContext().getLangOpts().CPlusPlus &&
-                !AC.getASTContext().getLangOpts().ObjC) {}
+        EscapesInCurrentBlock(decltype(this->EscapesInCurrentBlock)::withFlags(
+            unsigned(bool(!AC.getASTContext().getLangOpts().CPlusPlus &&
+                          !AC.getASTContext().getLangOpts().ObjC)))) {}
 
   void run();
 
@@ -174,9 +176,10 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
   // Collect origins that escape the function in this block (OriginEscapesFact),
   // appended at the end of CurrentBlockFacts to ensure they appear after
   // ExpireFact entries.
-  llvm::SmallVector<Fact *> EscapesInCurrentBlock;
+  llvm::SmallVectorWithFlags<Fact *> EscapesInCurrentBlock;
   const CFGBlock *CurrentBlock;
-  bool IsCMode = false;
+  bool getIsCMode() const { return EscapesInCurrentBlock.getFlag(0); }
+  void setIsCMode(bool Value) { EscapesInCurrentBlock.setFlag(0, Value); }
 };
 
 } // namespace clang::lifetimes::internal
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index f8bd097733529..922fc858309aa 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4961,9 +4961,9 @@ def OMPDeclareVariant : InheritableAttr {
     void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
         const;
     static StringRef getInteropTypeString(const OMPInteropInfo *I) {
-      if (I->IsTarget && I->IsTargetSync)
+      if (I->isTarget() && I->isTargetSync())
         return "target,targetsync";
-      if (I->IsTarget)
+      if (I->isTarget())
         return "target";
       return "targetsync";
     }
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 4d304b8f006b6..4adc8b5f707bd 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
@@ -498,7 +499,7 @@ class alignas(8) Module {
   // The begin index for a HeaderKind also acts the end index of HeaderKind - 1.
   // The extra element at the end acts as the end index of the last HeaderKind.
   unsigned HeaderKindBeginIndex[NumHeaderKinds + 1] = {};
-  SmallVector<Header, 2> HeadersStorage;
+  llvm::SmallVectorWithFlags<Header, 2, 4> HeadersStorage;
 
 public:
   ArrayRef<Header> getAllHeaders() const { return HeadersStorage; }
@@ -552,7 +553,7 @@ class alignas(8) Module {
   ///
   /// If any of these requirements are not available, the \c IsAvailable bit
   /// will be false to indicate that this (sub)module is not available.
-  SmallVector<Requirement, 2> Requirements;
+  llvm::SmallVectorWithFlags<Requirement, 2, 4> Requirements;
 
   /// A module with the same name that shadows this module.
   Module *ShadowingModule = nullptr;
@@ -560,86 +561,129 @@ class alignas(8) Module {
   /// Whether this module has declared itself unimportable, either because
   /// it's missing a requirement from \p Requirements or because it's been
   /// shadowed by another module.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsUnimportable : 1;
+  unsigned getIsUnimportable() const { return Requirements.getFlag(0); }
+  void setIsUnimportable(unsigned Value) {
+    Requirements.setFlag(0, (Value & 1));
+  }
 
   /// Whether we tried and failed to load a module file for this module.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned HasIncompatibleModuleFile : 1;
+  unsigned getHasIncompatibleModuleFile() const {
+    return Requirements.getFlag(1);
+  }
+  void setHasIncompatibleModuleFile(unsigned Value) {
+    Requirements.setFlag(1, (Value & 1));
+  }
 
   /// Whether this module is available in the current translation unit.
   ///
   /// If the module is missing headers or does not meet all requirements then
   /// this bit will be 0.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsAvailable : 1;
+  unsigned getIsAvailable() const { return Requirements.getFlag(2); }
+  void setIsAvailable(unsigned Value) { Requirements.setFlag(2, (Value & 1)); }
 
   /// Whether this module was loaded from a module file.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsFromModuleFile : 1;
+  unsigned getIsFromModuleFile() const { return Requirements.getFlag(3); }
+  void setIsFromModuleFile(unsigned Value) {
+    Requirements.setFlag(3, (Value & 1));
+  }
 
   /// Whether this is a framework module.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsFramework : 1;
+  unsigned getIsFramework() const { return HeadersStorage.getFlag(0); }
+  void setIsFramework(unsigned Value) {
+    HeadersStorage.setFlag(0, (Value & 1));
+  }
 
   /// Whether this is an explicit submodule.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsExplicit : 1;
+  unsigned getIsExplicit() const { return HeadersStorage.getFlag(1); }
+  void setIsExplicit(unsigned Value) { HeadersStorage.setFlag(1, (Value & 1)); }
 
   /// Whether this is a "system" module (which assumes that all
   /// headers in it are system headers).
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsSystem : 1;
+  unsigned getIsSystem() const { return HeadersStorage.getFlag(2); }
+  unsigned setIsSystem(unsigned Value) {
+    HeadersStorage.setFlag(2, (Value & 1));
+    return (Value & 1);
+  }
 
   /// Whether this is an 'extern "C"' module (which implicitly puts all
   /// headers in it within an 'extern "C"' block, and allows the module to be
   /// imported within such a block).
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsExternC : 1;
+  unsigned getIsExternC() const { return HeadersStorage.getFlag(3); }
+  unsigned setIsExternC(unsigned Value) {
+    HeadersStorage.setFlag(3, (Value & 1));
+    return (Value & 1);
+  }
 
   /// Whether this is an inferred submodule (module * { ... }).
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned IsInferred : 1;
+  unsigned getIsInferred() const { return LinkLibraries.getFlag(0); }
+  void setIsInferred(unsigned Value) { LinkLibraries.setFlag(0, (Value & 1)); }
 
   /// Whether we should infer submodules for this module based on
   /// the headers.
   ///
   /// Submodules can only be inferred for modules with an umbrella header.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned InferSubmodules : 1;
+  unsigned getInferSubmodules() const { return LinkLibraries.getFlag(1); }
+  void setInferSubmodules(unsigned Value) {
+    LinkLibraries.setFlag(1, (Value & 1));
+  }
 
   /// Whether, when inferring submodules, the inferred submodules
   /// should be explicit.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned InferExplicitSubmodules : 1;
+  unsigned getInferExplicitSubmodules() const {
+    return LinkLibraries.getFlag(2);
+  }
+  void setInferExplicitSubmodules(unsigned Value) {
+    LinkLibraries.setFlag(2, (Value & 1));
+  }
 
   /// Whether, when inferring submodules, the inferr submodules should
   /// export all modules they import (e.g., the equivalent of "export *").
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned InferExportWildcard : 1;
+  unsigned getInferExportWildcard() const { return LinkLibraries.getFlag(3); }
+  unsigned setInferExportWildcard(unsigned Value) {
+    LinkLibraries.setFlag(3, (Value & 1));
+    return (Value & 1);
+  }
 
   /// Whether the set of configuration macros is exhaustive.
   ///
   /// When the set of configuration macros is exhaustive, meaning
   /// that no identifier not in this list should affect how the module is
   /// built.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned ConfigMacrosExhaustive : 1;
+  unsigned getConfigMacrosExhaustive() const {
+    return UnresolvedDirectUses.getFlag(0);
+  }
+  void setConfigMacrosExhaustive(unsigned Value) {
+    UnresolvedDirectUses.setFlag(0, (Value & 1));
+  }
 
   /// Whether files in this module can only include non-modular headers
   /// and headers from used modules.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned NoUndeclaredIncludes : 1;
+  unsigned getNoUndeclaredIncludes() const {
+    return UnresolvedDirectUses.getFlag(1);
+  }
+  unsigned setNoUndeclaredIncludes(unsigned Value) {
+    UnresolvedDirectUses.setFlag(1, (Value & 1));
+    return (Value & 1);
+  }
 
   /// Whether this module came from a "private" module map, found next
   /// to a regular (public) module map.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned ModuleMapIsPrivate : 1;
+  unsigned getModuleMapIsPrivate() const {
+    return UnresolvedDirectUses.getFlag(2);
+  }
+  void setModuleMapIsPrivate(unsigned Value) {
+    UnresolvedDirectUses.setFlag(2, (Value & 1));
+  }
 
   /// Whether this C++20 named modules doesn't need an initializer.
   /// This is only meaningful for C++20 modules.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned NamedModuleHasInit : 1;
+  unsigned getNamedModuleHasInit() const {
+    return UnresolvedDirectUses.getFlag(3);
+  }
+  unsigned setNamedModuleHasInit(unsigned Value) {
+    UnresolvedDirectUses.setFlag(3, (Value & 1));
+    return (Value & 1);
+  }
 
   /// Describes the visibility of the various names within a
   /// particular module.
@@ -680,22 +724,26 @@ class alignas(8) Module {
     SourceLocation ExportLoc;
 
     /// The name of the module.
-    ModuleId Id;
+    llvm::SmallVectorWithFlagsFor<ModuleId, 1> Id;
 
     /// Whether this export declaration ends in a wildcard, indicating
     /// that all of its submodules should be exported (rather than the named
     /// module itself).
-    bool Wildcard;
+    bool getWildcard() const { return Id.getFlag(0); }
+    void setWildcard(bool Value) { Id.setFlag(0, Value); }
+
+    UnresolvedExportDecl(SourceLocation ExportLoc, ModuleId Id, bool Wildcard)
+        : ExportLoc(ExportLoc), Id(unsigned(Wildcard), std::move(Id)) {}
   };
 
   /// The set of export declarations that have yet to be resolved.
   SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
 
   /// The directly used modules.
-  SmallVector<Module *, 2> DirectUses;
+  llvm::SmallVectorWithFlags<Module *, 2> DirectUses;
 
   /// The set of use declarations that have yet to be resolved.
-  SmallVector<ModuleId, 2> UnresolvedDirectUses;
+  llvm::SmallVectorWithFlags<ModuleId, 2, 4> UnresolvedDirectUses;
 
   /// When \c NoUndeclaredIncludes is true, the set of modules this module tried
   /// to import but didn't because they are not direct uses.
@@ -720,11 +768,15 @@ class alignas(8) Module {
 
   /// The set of libraries or frameworks to link against when
   /// an entity from this module is used.
-  llvm::SmallVector<LinkLibrary, 2> LinkLibraries;
+  llvm::SmallVectorWithFlags<LinkLibrary, 2, 4> LinkLibraries;
 
   /// Autolinking uses the framework name for linking purposes
   /// when this is false and the export_as name otherwise.
-  bool UseExportAsModuleLinkName = false;
+  bool getUseExportAsModuleLinkName() const { return DirectUses.getFlag(0); }
+  bool setUseExportAsModuleLinkName(bool Value) {
+    DirectUses.setFlag(0, Value);
+    return Value;
+  }
 
   /// The set of "configuration macros", which are macros that
   /// (intentionally) change how this module is built.
@@ -763,7 +815,7 @@ class alignas(8) Module {
   ~Module();
 
   /// Determine whether this module has been declared unimportable.
-  bool isUnimportable() const { return IsUnimportable; }
+  bool isUnimportable() const { return getIsUnimportable(); }
 
   /// Determine whether this module has been declared unimportable.
   ///
@@ -786,7 +838,7 @@ class alignas(8) Module {
 
   /// Determine whether this module is available for use within the
   /// current translation unit.
-  bool isAvailable() const { return IsAvailable; }
+  bool isAvailable() const { return getIsAvailable(); }
 
   /// Determine whether this module is available for use within the
   /// current translation unit.
@@ -827,7 +879,7 @@ class alignas(8) Module {
   /// of a framework module.
   bool isPartOfFramework() const {
     for (const Module *Mod = this; Mod; Mod = Mod->Parent)
-      if (Mod->IsFramework)
+      if (Mod->getIsFramework())
         return true;
 
     return false;
@@ -836,7 +888,7 @@ class alignas(8) Module {
   /// Determine whether this module is a subframework of another
   /// framework.
   bool isSubFramework() const {
-    return IsFramework && Parent && Parent->isPartOfFramework();
+    return getIsFramework() && Parent && Parent->isPartOfFramework();
   }
 
   /// Set the parent of this module. This should only be used if the parent
@@ -902,7 +954,7 @@ class alignas(8) Module {
     return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface;
   }
 
-  bool isNamedModuleInterfaceHasInit() const { return NamedModuleHasInit; }
+  bool isNamedModuleInterfaceHasInit() const { return getNamedModuleHasInit(); }
 
   /// Get the primary module interface name from a partition.
   StringRef getPrimaryModuleInterfaceName() const {
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index 36c388668a455..68041da8263a9 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
 
@@ -318,11 +319,15 @@ struct OMPInteropPref final {
 };
 struct OMPInteropInfo final {
   OMPInteropInfo(bool IsTarget = false, bool IsTargetSync = false)
-      : IsTarget(IsTarget), IsTargetSync(IsTargetSync) {}
-  bool IsTarget;
-  bool IsTargetSync;
-  bool HasPreferAttrs = false;
-  llvm::SmallVector<OMPInteropPref, 4> Prefs;
+      : Prefs(decltype(this->Prefs)::withFlags(
+            unsigned(IsTarget) | (unsigned(IsTargetSync) << 1))) {}
+  bool isTarget() const { return Prefs.getFlag(0); }
+  void setIsTarget(bool Value) { Prefs.setFlag(0, Value); }
+  bool isTargetSync() const { return Prefs.getFlag(1); }
+  void setIsTargetSync(bool Value) { Prefs.setFlag(1, Value); }
+  bool hasPreferAttrs() const { return Prefs.getFlag(2); }
+  void setPreferAttrs(bool Value) { Prefs.setFlag(2, Value); }
+  llvm::SmallVectorWithFlags<OMPInteropPref, 4, 3> Prefs;
 };
 
 OpenMPDefaultClauseVariableCategory
diff --git a/clang/include/clang/Basic/Sarif.h b/clang/include/clang/Basic/Sarif.h
index 7651d2ac7a768..42ae11cac3a6f 100644
--- a/clang/include/clang/Basic/Sarif.h
+++ b/clang/include/clang/Basic/Sarif.h
@@ -35,6 +35,7 @@
 #include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
@@ -519,7 +520,8 @@ class SarifDocumentWriter {
   /// A closed document is one on which a new runs must be created.
   /// This could be a document that is freshly created, or has recently
   /// finished writing to a previous run.
-  bool Closed = true;
+  bool getClosed() const { return !CurrentRules.getFlag(0); }
+  void setClosed(bool Value) { CurrentRules.setFlag(0, !Value); }
 
   /// A sequence of SARIF runs.
   /// Each run object describes a single run of an analysis tool and contains
@@ -536,7 +538,7 @@ class SarifDocumentWriter {
   /// also known as "reportingDescriptor" objects in SARIF.
   ///
   /// Reference: <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317556">rules property</a>
-  llvm::SmallVector<SarifRule, 32> CurrentRules;
+  llvm::SmallVectorWithFlags<SarifRule, 32> CurrentRules;
 
   /// The list of artifacts that have been encountered on the most recent active
   /// run. An artifact is defined in SARIF as a sequence of bytes addressable
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h
index 1939d1aa4915e..5d2e710fa0bc8 100644
--- a/clang/include/clang/Basic/SourceManager.h
+++ b/clang/include/clang/Basic/SourceManager.h
@@ -46,6 +46,7 @@
 #include "llvm/ADT/PagedVector.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
@@ -678,16 +679,31 @@ class SourceManager : public RefCountedBase<SourceManager> {
 
   /// True if the ContentCache for files that are overridden by other
   /// files, should report the original file name. Defaults to true.
-  bool OverridenFilesKeepOriginalName = true;
+  bool getOverridenFilesKeepOriginalNameFlag() const {
+    return !StoredModuleBuildStack.getFlag(0);
+  }
+  void setOverridenFilesKeepOriginalNameFlag(bool Value) {
+    StoredModuleBuildStack.setFlag(0, !Value);
+  }
 
   /// True if non-system source files should be treated as volatile
   /// (likely to change while trying to use them). Defaults to false.
-  bool UserFilesAreVolatile;
+  bool getUserFilesAreVolatile() const {
+    return StoredModuleBuildStack.getFlag(1);
+  }
+  void setUserFilesAreVolatile(bool Value) {
+    StoredModuleBuildStack.setFlag(1, Value);
+  }
 
   /// True if all files read during this compilation should be treated
   /// as transient (may not be present in later compilations using a module
   /// file created from this compilation). Defaults to false.
-  bool FilesAreTransient = false;
+  bool getFilesAreTransient() const {
+    return StoredModuleBuildStack.getFlag(2);
+  }
+  void setFilesAreTransient(bool Value) {
+    StoredModuleBuildStack.setFlag(2, Value);
+  }
 
   struct OverriddenFilesInfoTy {
     /// Files that have been overridden with the contents from another
@@ -844,7 +860,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
   /// There is no way to set this value from the command line. If we ever need
   /// to do so (e.g., if on-demand module construction moves out-of-process),
   /// we can add a cc1-level option to do so.
-  SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack;
+  llvm::SmallVectorWithFlags<std::pair<std::string, FullSourceLoc>, 2, 3>
+      StoredModuleBuildStack;
 
 public:
   SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
@@ -867,12 +884,12 @@ class SourceManager : public RefCountedBase<SourceManager> {
   /// for contents of files that were overridden by other files. Defaults to
   /// true.
   void setOverridenFilesKeepOriginalName(bool value) {
-    OverridenFilesKeepOriginalName = value;
+    setOverridenFilesKeepOriginalNameFlag(value);
   }
 
   /// True if non-system source files should be treated as volatile
   /// (likely to change while trying to use them).
-  bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
+  bool userFilesAreVolatile() const { return getUserFilesAreVolatile(); }
 
   /// Retrieve the module build stack.
   ModuleBuildStack getModuleBuildStack() const {
@@ -1046,7 +1063,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
   /// Specify that all files that are read during this compilation are
   /// transient.
   void setAllFilesAreTransient(bool Transient) {
-    FilesAreTransient = Transient;
+    setFilesAreTransient(Transient);
   }
 
   //===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CodeGen/CodeGenAction.h b/clang/include/clang/CodeGen/CodeGenAction.h
index 84fa4549d5033..c222f35509891 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -11,6 +11,7 @@
 
 #include "clang/CodeGen/ModuleLinker.h"
 #include "clang/Frontend/FrontendAction.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <memory>
 
 namespace llvm {
@@ -28,9 +29,10 @@ class CodeGenAction : public ASTFrontendAction {
   std::unique_ptr<llvm::Module> TheModule;
 
   /// Bitcode modules to link in to our module.
-  SmallVector<LinkModule, 4> LinkModules;
+  llvm::SmallVectorWithFlags<LinkModule, 4> LinkModules;
   llvm::LLVMContext *VMContext;
-  bool OwnsVMContext;
+  bool getOwnsVMContext() const { return LinkModules.getFlag(0); }
+  void setOwnsVMContext(bool Value) { LinkModules.setFlag(0, Value); }
 
   std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef);
 
diff --git a/clang/include/clang/CodeGen/ConstantInitBuilder.h b/clang/include/clang/CodeGen/ConstantInitBuilder.h
index 70a6ac323ccec..8697afa978aee 100644
--- a/clang/include/clang/CodeGen/ConstantInitBuilder.h
+++ b/clang/include/clang/CodeGen/ConstantInitBuilder.h
@@ -15,12 +15,13 @@
 #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
 #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
 
+#include "clang/AST/CharUnits.h"
+#include "clang/CodeGen/ConstantInitFuture.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/GlobalValue.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/CodeGen/ConstantInitFuture.h"
 
 #include <optional>
 #include <vector>
@@ -60,9 +61,10 @@ class ConstantInitBuilderBase {
     SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
   };
   CodeGenModule &CGM;
-  llvm::SmallVector<llvm::Constant*, 16> Buffer;
+  llvm::SmallVectorWithFlags<llvm::Constant *, 16> Buffer;
   std::vector<SelfReference> SelfReferences;
-  bool Frozen = false;
+  bool getFrozen() const { return Buffer.getFlag(0); }
+  void setFrozen(bool Value) { Buffer.setFlag(0, Value); }
 
   friend class ConstantInitFuture;
   friend class ConstantAggregateBuilderBase;
@@ -108,11 +110,11 @@ class ConstantAggregateBuilderBase {
   bool Packed = false;
   mutable CharUnits CachedOffsetFromGlobal;
 
-  llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
+  llvm::SmallVectorWithFlagsImpl<llvm::Constant *> &getBuffer() {
     return Builder.Buffer;
   }
 
-  const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
+  const llvm::SmallVectorWithFlagsImpl<llvm::Constant *> &getBuffer() const {
     return Builder.Buffer;
   }
 
@@ -123,8 +125,9 @@ class ConstantAggregateBuilderBase {
       assert(!parent->Frozen && "parent already has child builder active");
       parent->Frozen = true;
     } else {
-      assert(!builder.Frozen && "builder already has child builder active");
-      builder.Frozen = true;
+      assert(!builder.getFrozen() &&
+             "builder already has child builder active");
+      builder.setFrozen(true);
     }
   }
 
@@ -141,9 +144,9 @@ class ConstantAggregateBuilderBase {
              "parent not frozen while child builder active");
       Parent->Frozen = false;
     } else {
-      assert(Builder.Frozen &&
+      assert(Builder.getFrozen() &&
              "builder not frozen while child builder active");
-      Builder.Frozen = false;
+      Builder.setFrozen(false);
     }
   }
 
diff --git a/clang/include/clang/CodeGen/SwiftCallingConv.h b/clang/include/clang/CodeGen/SwiftCallingConv.h
index d7a0c84699ab0..540749a67d682 100644
--- a/clang/include/clang/CodeGen/SwiftCallingConv.h
+++ b/clang/include/clang/CodeGen/SwiftCallingConv.h
@@ -17,6 +17,7 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Type.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/TrailingObjects.h"
 #include <cassert>
 
@@ -50,8 +51,9 @@ class SwiftAggLowering {
       return End - Begin;
     }
   };
-  SmallVector<StorageEntry, 4> Entries;
-  bool Finished = false;
+  llvm::SmallVectorWithFlags<StorageEntry, 4> Entries;
+  bool getFinished() const { return Entries.getFlag(0); }
+  void setFinished(bool Value) { Entries.setFlag(0, Value); }
 
 public:
   SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {}
@@ -71,7 +73,7 @@ class SwiftAggLowering {
 
   /// Does this lowering require passing any data?
   bool empty() const {
-    assert(Finished && "didn't finish lowering before calling empty()");
+    assert(getFinished() && "didn't finish lowering before calling empty()");
     return Entries.empty();
   }
 
diff --git a/clang/include/clang/DependencyScanning/DependencyGraph.h b/clang/include/clang/DependencyScanning/DependencyGraph.h
index f35786418fc60..23df4e4e0f499 100644
--- a/clang/include/clang/DependencyScanning/DependencyGraph.h
+++ b/clang/include/clang/DependencyScanning/DependencyGraph.h
@@ -14,6 +14,7 @@
 #include "clang/Frontend/CompilerInvocation.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include <string>
 #include <variant>
@@ -80,7 +81,8 @@ struct ModuleDeps {
   ModuleID ID;
 
   /// Whether this is a "system" module.
-  bool IsSystem;
+  bool getIsSystem() const { return LinkLibraries.getFlag(0); }
+  void setIsSystem(bool Value) { LinkLibraries.setFlag(0, Value); }
 
   /// Whether this module is fully composed of file & module inputs from
   /// locations likely to stay the same across the active development and build
@@ -88,10 +90,15 @@ struct ModuleDeps {
   ///
   /// External paths, as opposed to virtual file paths, are always used
   /// for computing this value.
-  bool IsInStableDirectories;
+  bool getIsInStableDirectories() const { return LinkLibraries.getFlag(1); }
+  bool setIsInStableDirectories(bool Value) {
+    LinkLibraries.setFlag(1, Value);
+    return Value;
+  }
 
   /// Whether current working directory is ignored.
-  bool IgnoreCWD;
+  bool getIgnoreCWD() const { return LinkLibraries.getFlag(2); }
+  void setIgnoreCWD(bool Value) { LinkLibraries.setFlag(2, Value); }
 
   /// The path to the modulemap file which defines this module.
   ///
@@ -126,7 +133,7 @@ struct ModuleDeps {
 
   /// The set of libraries or frameworks to link against when
   /// an entity from this module is used.
-  llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;
+  llvm::SmallVectorWithFlags<Module::LinkLibrary, 2, 3> LinkLibraries;
 
   /// Invokes \c Cb for all file dependencies of this module. Each provided
   /// \c StringRef is only valid within the individual callback invocation.
diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h
index b4b91e7010941..0b85f123b0aa9 100644
--- a/clang/include/clang/Driver/Action.h
+++ b/clang/include/clang/Driver/Action.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
 #include <string>
@@ -109,13 +110,18 @@ class Action {
   /// The output type of this action.
   types::ID Type;
 
-  ActionList Inputs;
+  llvm::SmallVectorWithFlagsFor<ActionList, 1> Inputs;
 
   /// Flag that is set to true if this action can be collapsed with others
   /// actions that depend on it. This is true by default and set to false when
   /// the action is used by two different tool chains, which is enabled by the
   /// offloading support implementation.
-  bool CanBeCollapsedWithNextDependentAction = true;
+  bool getCanBeCollapsedWithNextDependentAction() const {
+    return !Inputs.getFlag(0);
+  }
+  void setCanBeCollapsedWithNextDependentAction(bool Value) {
+    Inputs.setFlag(0, !Value);
+  }
 
 protected:
   ///
@@ -142,7 +148,7 @@ class Action {
   Action(ActionClass Kind, Action *Input)
       : Action(Kind, ActionList({Input}), Input->getType()) {}
   Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
-      : Kind(Kind), Type(Type), Inputs(Inputs) {}
+      : Kind(Kind), Type(Type), Inputs(Inputs.begin(), Inputs.end()) {}
 
 public:
   virtual ~Action();
@@ -152,8 +158,10 @@ class Action {
   ActionClass getKind() const { return Kind; }
   types::ID getType() const { return Type; }
 
-  ActionList &getInputs() { return Inputs; }
-  const ActionList &getInputs() const { return Inputs; }
+  llvm::SmallVectorWithFlagsFor<ActionList, 1> &getInputs() { return Inputs; }
+  const llvm::SmallVectorWithFlagsFor<ActionList, 1> &getInputs() const {
+    return Inputs;
+  }
 
   size_type size() const { return Inputs.size(); }
 
@@ -168,12 +176,12 @@ class Action {
 
   /// Mark this action as not legal to collapse.
   void setCannotBeCollapsedWithNextDependentAction() {
-    CanBeCollapsedWithNextDependentAction = false;
+    setCanBeCollapsedWithNextDependentAction(false);
   }
 
   /// Return true if this function can be collapsed with others.
   bool isCollapsingWithNextDependentActionLegal() const {
-    return CanBeCollapsedWithNextDependentAction;
+    return getCanBeCollapsedWithNextDependentAction();
   }
 
   /// Return a string containing the offload kind of the action.
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 15b6fdcb8a574..8984c93ce1995 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -23,6 +23,7 @@
 #include "clang/Options/Options.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Option/Arg.h"
@@ -187,7 +188,7 @@ class Driver {
   /// FIXME: This type of customization should be removed in favor of the
   /// universal driver when it is ready.
   typedef SmallVector<std::string, 4> prefix_list;
-  prefix_list PrefixDirs;
+  llvm::SmallVectorWithFlagsFor<prefix_list, 2> PrefixDirs;
 
   /// sysroot, if present
   std::string SysRoot;
@@ -236,13 +237,15 @@ class Driver {
   bool IsDXCMode() const { return Mode == DXCMode; }
 
   /// Only print tool bindings, don't build any jobs.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned CCCPrintBindings : 1;
+  unsigned getCCCPrintBindings() const { return PrefixDirs.getFlag(0); }
+  void setCCCPrintBindings(unsigned Value) {
+    PrefixDirs.setFlag(0, (Value & 1));
+  }
 
   /// Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to
   /// CCPrintOptionsFilename or to stderr.
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned CCPrintOptions : 1;
+  unsigned getCCPrintOptions() const { return PrefixDirs.getFlag(1); }
+  void setCCPrintOptions(unsigned Value) { PrefixDirs.setFlag(1, (Value & 1)); }
 
   /// The format of the header information that is emitted. If CC_PRINT_HEADERS
   /// is set, the format is textual. Otherwise, the format is determined by the
diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h
index 96839240543af..f15a3c9d2d2a8 100644
--- a/clang/include/clang/Driver/OffloadBundler.h
+++ b/clang/include/clang/Driver/OffloadBundler.h
@@ -18,6 +18,7 @@
 #define LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Error.h"
 #include "llvm/TargetParser/Triple.h"
@@ -30,13 +31,28 @@ class OffloadBundlerConfig {
 public:
   OffloadBundlerConfig();
 
-  bool AllowNoHost = false;
-  bool AllowMissingBundles = false;
-  bool CheckInputArchive = false;
-  bool PrintExternalCommands = false;
-  bool HipOpenmpCompatible = false;
-  bool Compress = false;
-  bool Verbose = false;
+  bool getAllowNoHost() const { return OutputFileNames.getFlag(0); }
+  void setAllowNoHost(bool Value) { OutputFileNames.setFlag(0, Value); }
+  bool getAllowMissingBundles() const { return OutputFileNames.getFlag(1); }
+  void setAllowMissingBundles(bool Value) { OutputFileNames.setFlag(1, Value); }
+  bool getCheckInputArchive() const { return OutputFileNames.getFlag(2); }
+  void setCheckInputArchive(bool Value) { OutputFileNames.setFlag(2, Value); }
+  bool getPrintExternalCommands() const { return OutputFileNames.getFlag(3); }
+  void setPrintExternalCommands(bool Value) {
+    OutputFileNames.setFlag(3, Value);
+  }
+  bool getHipOpenmpCompatible() const { return InputFileNames.getFlag(0); }
+  void setHipOpenmpCompatible(bool Value) { InputFileNames.setFlag(0, Value); }
+  bool getCompress() const { return InputFileNames.getFlag(1); }
+  bool setCompress(bool Value) {
+    InputFileNames.setFlag(1, Value);
+    return Value;
+  }
+  bool getVerbose() const { return InputFileNames.getFlag(2); }
+  bool setVerbose(bool Value) {
+    InputFileNames.setFlag(2, Value);
+    return Value;
+  }
   llvm::compression::Format CompressionFormat;
   int CompressionLevel;
   uint16_t CompressedBundleVersion;
@@ -48,8 +64,8 @@ class OffloadBundlerConfig {
   std::string ObjcopyPath;
 
   llvm::SmallVector<std::string, 4> TargetNames;
-  llvm::SmallVector<std::string, 4> InputFileNames;
-  llvm::SmallVector<std::string, 4> OutputFileNames;
+  llvm::SmallVectorWithFlags<std::string, 4, 3> InputFileNames;
+  llvm::SmallVectorWithFlags<std::string, 4, 4> OutputFileNames;
 };
 
 class OffloadBundler {
diff --git a/clang/include/clang/Driver/RocmInstallationDetector.h b/clang/include/clang/Driver/RocmInstallationDetector.h
index 6481507692b25..824b2a318e277 100644
--- a/clang/include/clang/Driver/RocmInstallationDetector.h
+++ b/clang/include/clang/Driver/RocmInstallationDetector.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H
 
 #include "clang/Driver/Driver.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 namespace driver {
@@ -120,7 +121,8 @@ class RocmInstallationDetector {
   // HIP version specified by --hip-version.
   StringRef HIPVersionArg;
   // Wheter -nogpulib is specified.
-  bool NoBuiltinLibs = false;
+  bool getNoBuiltinLibs() const { return ROCmSearchDirs.getFlag(0); }
+  void setNoBuiltinLibs(bool Value) { ROCmSearchDirs.setFlag(0, Value); }
 
   // Paths
   SmallString<0> InstallPath;
@@ -151,9 +153,11 @@ class RocmInstallationDetector {
   std::map<unsigned, std::string> ABIVersionMap;
 
   // Cache ROCm installation search paths.
-  SmallVector<Candidate, 4> ROCmSearchDirs;
-  bool PrintROCmSearchDirs;
-  bool Verbose;
+  llvm::SmallVectorWithFlags<Candidate, 4, 3> ROCmSearchDirs;
+  bool getPrintROCmSearchDirs() const { return ROCmSearchDirs.getFlag(1); }
+  void setPrintROCmSearchDirs(bool Value) { ROCmSearchDirs.setFlag(1, Value); }
+  bool getVerbose() const { return ROCmSearchDirs.getFlag(2); }
+  void setVerbose(bool Value) { ROCmSearchDirs.setFlag(2, Value); }
 
   bool allGenericLibsValid() const {
     return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() &&
@@ -162,7 +166,7 @@ class RocmInstallationDetector {
 
   void scanLibDevicePath(llvm::StringRef Path);
   bool parseHIPVersionFile(llvm::StringRef V);
-  const SmallVectorImpl<Candidate> &getInstallationPathCandidates();
+  ArrayRef<Candidate> getInstallationPathCandidates();
 
   /// Find the path to a SPACK package under the ROCm candidate installation
   /// directory if the candidate is a SPACK ROCm candidate. \returns empty
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 7304ddc43b63f..9e8f716f84f42 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -185,11 +185,9 @@ class ToolChain {
   Tool *getOffloadPackager() const;
   Tool *getLinkerWrapper() const;
 
-  /// Track if diagnostics have been emitted for sanitizer arguments already to
-  /// avoid duplicate diagnostics.
-  mutable bool SanitizerArgsChecked = false;
-
   /// Set of BoundArch values which have already had diagnostics emitted.
+  /// A nonempty set also records that common sanitizer-argument diagnostics
+  /// have already been emitted.
   mutable llvm::SmallSet<StringRef, 4> BoundArchSanitizerArgsChecked;
 
   /// The effective clang triple for the current Job.
diff --git a/clang/include/clang/Edit/Commit.h b/clang/include/clang/Edit/Commit.h
index f6c7988e28ee1..19955107e2a6b 100644
--- a/clang/include/clang/Edit/Commit.h
+++ b/clang/include/clang/Edit/Commit.h
@@ -13,6 +13,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Edit/FileOffset.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Allocator.h"
 
@@ -54,8 +55,9 @@ class Commit {
   const PPConditionalDirectiveRecord *PPRec;
   EditedSource *Editor = nullptr;
 
-  bool IsCommitable = true;
-  SmallVector<Edit, 8> CachedEdits;
+  bool getIsCommitable() const { return !CachedEdits.getFlag(0); }
+  void setIsCommitable(bool Value) { CachedEdits.setFlag(0, !Value); }
+  llvm::SmallVectorWithFlags<Edit, 8> CachedEdits;
 
   llvm::BumpPtrAllocator StrAlloc;
 
@@ -65,7 +67,7 @@ class Commit {
          const PPConditionalDirectiveRecord *PPRec = nullptr)
       : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {}
 
-  bool isCommitable() const { return IsCommitable; }
+  bool isCommitable() const { return getIsCommitable(); }
 
   bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
               bool beforePreviousInsertions = false);
diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
index f8759bf2d8f25..2e2df61ccf468 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -88,20 +89,23 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
 
   /// Indicates whether to take into account the extended module. This is only
   /// useful for \c serializeSingleSymbolSGF.
-  bool ForceEmitToMainModule;
+  bool getForceEmitToMainModule() const { return Hierarchy.getFlag(0); }
+  void setForceEmitToMainModule(bool Value) { Hierarchy.setFlag(0, Value); }
 
   // Stores the references required to construct path components for the
   // currently visited APIRecord.
-  llvm::SmallVector<SymbolReference, 8> Hierarchy;
+  llvm::SmallVectorWithFlags<SymbolReference, 8, 3> Hierarchy;
 
   /// The list of symbols to ignore.
   ///
   /// Note: This should be consulted before emitting a symbol.
   const APIIgnoresList &IgnoresList;
 
-  const bool EmitSymbolLabelsForTesting = false;
+  bool getEmitSymbolLabelsForTesting() const { return Hierarchy.getFlag(1); }
 
-  const bool SkipSymbolsInCategoriesToExternalTypes = false;
+  bool getSkipSymbolsInCategoriesToExternalTypes() const {
+    return Hierarchy.getFlag(2);
+  }
 
   /// The object instantiated by the last call to serializeAPIRecord.
   Object *CurrentSymbol = nullptr;
@@ -274,11 +278,12 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
                         bool EmitSymbolLabelsForTesting = false,
                         bool ForceEmitToMainModule = false,
                         bool SkipSymbolsInCategoriesToExternalTypes = false)
-      : Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
-        IgnoresList(IgnoresList),
-        EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting),
-        SkipSymbolsInCategoriesToExternalTypes(
-            SkipSymbolsInCategoriesToExternalTypes) {}
+      : Base(API),
+        Hierarchy(decltype(this->Hierarchy)::withFlags(
+            unsigned(ForceEmitToMainModule) |
+            (unsigned(EmitSymbolLabelsForTesting) << 1) |
+            (unsigned(SkipSymbolsInCategoriesToExternalTypes) << 2))),
+        IgnoresList(IgnoresList) {}
 };
 
 } // namespace extractapi
diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h
index 92d0bd9d03b4d..7f9afd54db68e 100644
--- a/clang/include/clang/Frontend/ASTUnit.h
+++ b/clang/include/clang/Frontend/ASTUnit.h
@@ -35,6 +35,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
@@ -106,8 +107,18 @@ class ASTUnit {
   std::unique_ptr<HeaderSearchOptions> HSOpts;
   std::shared_ptr<PreprocessorOptions>    PPOpts;
   IntrusiveRefCntPtr<ASTReader> Reader;
-  bool HadModuleLoaderFatalFailure = false;
-  bool StorePreamblesInMemory = false;
+  bool getHadModuleLoaderFatalFailure() const {
+    return PreambleDiagnostics.getFlag(0);
+  }
+  void setHadModuleLoaderFatalFailure(bool Value) {
+    PreambleDiagnostics.setFlag(0, Value);
+  }
+  bool getStorePreamblesInMemory() const {
+    return PreambleDiagnostics.getFlag(1);
+  }
+  void setStorePreamblesInMemory(bool Value) {
+    PreambleDiagnostics.setFlag(1, Value);
+  }
 
   /// Utility struct for managing ASTWriter and its associated data streams.
   struct ASTWriterData {
@@ -148,13 +159,17 @@ class ASTUnit {
   // OnlyLocalDecls - when true, walking this AST should only visit declarations
   // that come from the AST itself, not from included precompiled headers.
   // FIXME: This is temporary; eventually, CIndex will always do this.
-  bool OnlyLocalDecls = false;
+  bool getOnlyLocalDeclsFlag() const { return PreambleDiagnostics.getFlag(2); }
+  void setOnlyLocalDeclsFlag(bool Value) {
+    PreambleDiagnostics.setFlag(2, Value);
+  }
 
   /// Whether to capture any diagnostics produced.
   CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::None;
 
   /// Track whether the main file was loaded from an AST or not.
-  bool MainFileIsAST;
+  bool getMainFileIsAST() const { return PreambleDiagnostics.getFlag(3); }
+  void setMainFileIsAST(bool Value) { PreambleDiagnostics.setFlag(3, Value); }
 
   /// What kind of translation unit this AST represents.
   TranslationUnitKind TUKind = TU_Complete;
@@ -186,7 +201,7 @@ class ASTUnit {
   std::string OriginalSourceFile;
 
   /// The set of diagnostics produced when creating the preamble.
-  SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics;
+  llvm::SmallVectorWithFlags<StandaloneDiagnostic, 4, 4> PreambleDiagnostics;
 
   /// The set of diagnostics produced when creating this
   /// translation unit.
@@ -423,7 +438,7 @@ class ASTUnit {
   ASTUnit &operator=(const ASTUnit &) = delete;
   ~ASTUnit();
 
-  bool isMainFileAST() const { return MainFileIsAST; }
+  bool isMainFileAST() const { return getMainFileIsAST(); }
 
   bool isUnsafeToFree() const { return UnsafeToFree; }
   void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
@@ -509,7 +524,7 @@ class ASTUnit {
   ASTMutationListener *getASTMutationListener();
   ASTDeserializationListener *getDeserializationListener();
 
-  bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+  bool getOnlyLocalDecls() const { return getOnlyLocalDeclsFlag(); }
 
   bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }
   void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; }
diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h
index b3d8ccdd2d0e3..895170db993c4 100644
--- a/clang/include/clang/Lex/Lexer.h
+++ b/clang/include/clang/Lex/Lexer.h
@@ -234,7 +234,7 @@ class Lexer : public PreprocessorLexer {
   /// associated preprocessor object.  Return true if the 'next character to
   /// read' pointer points at the end of the lexer buffer, false otherwise.
   bool LexFromRawLexer(Token &Result) {
-    assert(LexingRawMode && "Not already in raw mode!");
+    assert(getLexingRawMode() && "Not already in raw mode!");
     Lex(Result);
     // Note that lexing to the end of the buffer doesn't implicitly delete the
     // lexer when in raw mode.
@@ -252,7 +252,7 @@ class Lexer : public PreprocessorLexer {
   /// SetKeepWhitespaceMode - This method lets clients enable or disable
   /// whitespace retention mode.
   void SetKeepWhitespaceMode(bool Val) {
-    assert((!Val || LexingRawMode || LangOpts.TraditionalCPP) &&
+    assert((!Val || getLexingRawMode() || LangOpts.TraditionalCPP) &&
            "Can only retain whitespace in raw mode or -traditional-cpp");
     ExtendedTokenMode = Val ? 2 : 0;
   }
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 18e77cc28ce4b..3e2bb664a0b3e 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -245,8 +246,10 @@ class ModuleMap {
   /// A directory for which framework modules can be inferred.
   struct InferredDirectory {
     /// Whether to infer modules from this directory.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned InferModules : 1;
+    unsigned getInferModules() const { return ExcludedModules.getFlag(0); }
+    void setInferModules(unsigned Value) {
+      ExcludedModules.setFlag(0, (Value & 1));
+    }
 
     /// The attributes to use for inferred modules.
     Attributes Attrs;
@@ -257,9 +260,9 @@ class ModuleMap {
 
     /// The names of modules that cannot be inferred within this
     /// directory.
-    SmallVector<std::string, 2> ExcludedModules;
+    llvm::SmallVectorWithFlags<std::string, 2> ExcludedModules;
 
-    InferredDirectory() : InferModules(false) {}
+    InferredDirectory() {}
   };
 
   /// A mapping from directories to information about inferring
@@ -319,7 +322,8 @@ class ModuleMap {
   ///
   /// \returns The resolved module, or null if the module-id could not be
   /// resolved.
-  Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
+  Module *resolveModuleId(llvm::ArrayRef<ModuleId::value_type> Id, Module *Mod,
+                          bool Complain) const;
 
   /// Add an unresolved header to a module.
   ///
@@ -646,7 +650,7 @@ class ModuleMap {
   /// Check whether a framework module can be inferred in the given directory.
   bool canInferFrameworkModule(const DirectoryEntry *Dir) const {
     auto It = InferredDirectories.find(Dir);
-    return It != InferredDirectories.end() && It->getSecond().InferModules;
+    return It != InferredDirectories.end() && It->getSecond().getInferModules();
   }
 
   /// Retrieve the module map file containing the definition of the given
diff --git a/clang/include/clang/Lex/ModuleMapFile.h b/clang/include/clang/Lex/ModuleMapFile.h
index 59389cd85a928..37658dc037cce 100644
--- a/clang/include/clang/Lex/ModuleMapFile.h
+++ b/clang/include/clang/Lex/ModuleMapFile.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_LEX_MODULEMAPFILE_H
 
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 // TODO: Consider moving ModuleId to another header, parsing a modulemap file is
 //   intended to not depend on anything about the clang::Module class.
 #include "clang/Basic/Module.h"
@@ -68,15 +69,15 @@ struct UmbrellaDirDecl {
 };
 
 struct ModuleDecl {
-  ModuleId Id;
+  llvm::SmallVectorWithFlagsFor<ModuleId, 2> Id;
   SourceLocation Location; /// Points to the first keyword in the decl.
   ModuleAttributes Attrs;
   std::vector<Decl> Decls;
 
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned Explicit : 1;
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned Framework : 1;
+  unsigned getExplicit() const { return Id.getFlag(0); }
+  void setExplicit(unsigned Value) { Id.setFlag(0, (Value & 1)); }
+  unsigned getFramework() const { return Id.getFlag(1); }
+  void setFramework(unsigned Value) { Id.setFlag(1, (Value & 1)); }
 };
 
 struct ExcludeDecl {
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index 31b68a0fd0670..97a04b7142c1d 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -43,6 +43,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/ADT/iterator_range.h"
@@ -297,13 +298,28 @@ class Preprocessor {
   bool PragmasEnabled : 1;
 
   /// True if the current build action is a preprocessing action.
-  bool PreprocessedOutput : 1;
+  bool getPreprocessedOutputFlag() const {
+    return PendingModuleMacroNames.getFlag(0);
+  }
+  void setPreprocessedOutputFlag(bool Value) {
+    PendingModuleMacroNames.setFlag(0, Value);
+  }
 
   /// True if we are currently preprocessing a #if or #elif directive
-  bool ParsingIfOrElifDirective;
+  bool getParsingIfOrElifDirective() const {
+    return PendingModuleMacroNames.getFlag(1);
+  }
+  void setParsingIfOrElifDirective(bool Value) {
+    PendingModuleMacroNames.setFlag(1, Value);
+  }
 
   /// True if we are pre-expanding macro arguments.
-  bool InMacroArgPreExpansion;
+  bool getInMacroArgPreExpansion() const {
+    return PendingModuleMacroNames.getFlag(2);
+  }
+  void setInMacroArgPreExpansion(bool Value) {
+    PendingModuleMacroNames.setFlag(2, Value);
+  }
 
   /// Mapping/lookup information for all identifiers in
   /// the program, including program keywords.
@@ -339,7 +355,12 @@ class Preprocessor {
   EmptylineHandler *Emptyline = nullptr;
 
   /// True to avoid tearing down the lexer etc on EOF
-  bool IncrementalProcessing = false;
+  bool getIncrementalProcessing() const {
+    return PendingModuleMacroNames.getFlag(3);
+  }
+  void setIncrementalProcessing(bool Value) {
+    PendingModuleMacroNames.setFlag(3, Value);
+  }
 
 public:
   /// The kind of translation unit we are processing.
@@ -384,10 +405,20 @@ class Preprocessor {
   unsigned CheckPointCounter = 0;
 
   /// Whether to record lexer check points for diagnostic snippet highlighting.
-  bool RecordCheckPoints = false;
+  bool getRecordCheckPoints() const {
+    return BuildingSubmoduleStack.getFlag(0);
+  }
+  void setRecordCheckPoints(bool Value) {
+    BuildingSubmoduleStack.setFlag(0, Value);
+  }
 
   /// Whether we're importing a standard C++20 named Modules.
-  bool ImportingCXXNamedModules = false;
+  bool getImportingCXXNamedModules() const {
+    return BuildingSubmoduleStack.getFlag(1);
+  }
+  void setImportingCXXNamedModules(bool Value) {
+    BuildingSubmoduleStack.setFlag(1, Value);
+  }
 
   /// Whether the last token we lexed was an 'export' keyword.
   Token LastExportKeyword;
@@ -690,7 +721,12 @@ class Preprocessor {
   SourceLocation PreambleRecordedPragmaAssumeNonNullLoc;
 
   /// True if we hit the code-completion point.
-  bool CodeCompletionReached = false;
+  bool getCodeCompletionReachedFlag() const {
+    return BuildingSubmoduleStack.getFlag(2);
+  }
+  void setCodeCompletionReachedFlag(bool Value) {
+    BuildingSubmoduleStack.setFlag(2, Value);
+  }
 
   /// The code completion token containing the information
   /// on the stem that is to be code completed.
@@ -719,11 +755,26 @@ class Preprocessor {
   FileID DeferredGMFInputsFileID;
 
   /// Whether the predefines buffer contains a synthesized GMF introducer.
-  bool HasSynthesizedGMF = false;
+  bool getHasSynthesizedGMF() const {
+    return BuildingSubmoduleStack.getFlag(3);
+  }
+  void setHasSynthesizedGMF(bool Value) {
+    BuildingSubmoduleStack.setFlag(3, Value);
+  }
 
   /// Whether setPredefines() replaced a previously initialized buffer.
-  bool PredefinesWereReplaced = false;
-  bool PredefinesInitialized = false;
+  bool getPredefinesWereReplaced() const {
+    return DelayedMacroExpandsCallbacks.getFlag(0);
+  }
+  void setPredefinesWereReplaced(bool Value) {
+    DelayedMacroExpandsCallbacks.setFlag(0, Value);
+  }
+  bool getPredefinesInitialized() const {
+    return DelayedMacroExpandsCallbacks.getFlag(1);
+  }
+  void setPredefinesInitialized(bool Value) {
+    DelayedMacroExpandsCallbacks.setFlag(1, Value);
+  }
 
   bool hasDeferredGMFInputs() const { return !DeferredGMFInputs.empty(); }
 
@@ -732,7 +783,12 @@ class Preprocessor {
 
   /// Whether we hit an error due to reaching max allowed include depth. Allows
   /// to avoid hitting the same error over and over again.
-  bool HasReachedMaxIncludeDepth = false;
+  bool getHasReachedMaxIncludeDepth() const {
+    return DelayedMacroExpandsCallbacks.getFlag(2);
+  }
+  void setHasReachedMaxIncludeDepth(bool Value) {
+    DelayedMacroExpandsCallbacks.setFlag(2, Value);
+  }
 
   /// The number of currently-active calls to Lex.
   ///
@@ -746,7 +802,12 @@ class Preprocessor {
   unsigned TokenCount = 0;
 
   /// Preprocess every token regardless of LexLevel.
-  bool PreprocessToken = false;
+  bool getPreprocessTokenFlag() const {
+    return DelayedMacroExpandsCallbacks.getFlag(3);
+  }
+  void setPreprocessTokenFlag(bool Value) {
+    DelayedMacroExpandsCallbacks.setFlag(3, Value);
+  }
 
   /// The maximum number of (LexLevel 0) tokens before issuing a -Wmax-tokens
   /// warning, or zero for unlimited.
@@ -829,7 +890,7 @@ class Preprocessor {
   /// Stack of Lexer unwinds completely (LexLevel returns to 0).
   /// This avoids use-after-free when HandleEndOfFile is called from
   /// within a Lexer method that still needs to access its members.
-  SmallVector<std::unique_ptr<Lexer>, 2> PendingDestroyLexers;
+  llvm::SmallVectorWithFlags<std::unique_ptr<Lexer>, 2, 4> PendingDestroyLexers;
 
   /// The current top of the stack that we're lexing from
   /// if not expanding a macro.
@@ -895,7 +956,8 @@ class Preprocessor {
     MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range)
         : Tok(Tok), MD(MD), Range(Range) {}
   };
-  SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
+  llvm::SmallVectorWithFlags<MacroExpandsInfo, 2, 4>
+      DelayedMacroExpandsCallbacks;
 
   /// Information about a name that has been used to define a module macro.
   struct FullModuleMacroInfo {
@@ -1061,7 +1123,8 @@ class Preprocessor {
           OuterSubmoduleState(OuterSubmoduleState),
           OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {}
   };
-  SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
+  llvm::SmallVectorWithFlags<BuildingSubmoduleInfo, 8, 4>
+      BuildingSubmoduleStack;
 
   /// Information about a submodule's preprocessor state.
   struct SubmoduleState {
@@ -1094,7 +1157,7 @@ class Preprocessor {
   llvm::UniquingSet<ModuleMacro> ModuleMacros;
 
   /// The names of potential module macros that we've not yet processed.
-  llvm::SmallVector<IdentifierInfo *, 32> PendingModuleMacroNames;
+  llvm::SmallVectorWithFlags<IdentifierInfo *, 32, 4> PendingModuleMacroNames;
 
   /// The list of module macros, for each identifier, that are not overridden by
   /// any other module macro.
@@ -1170,13 +1233,31 @@ class Preprocessor {
   FileID PCHThroughHeaderFileID;
 
   /// Whether tokens are being skipped until a #pragma hdrstop is seen.
-  bool SkippingUntilPragmaHdrStop = false;
+  bool getSkippingUntilPragmaHdrStop() const {
+    return PendingDestroyLexers.getFlag(0);
+  }
+  bool setSkippingUntilPragmaHdrStop(bool Value) {
+    PendingDestroyLexers.setFlag(0, Value);
+    return Value;
+  }
 
   /// Whether tokens are being skipped until the through header is seen.
-  bool SkippingUntilPCHThroughHeader = false;
+  bool getSkippingUntilPCHThroughHeader() const {
+    return PendingDestroyLexers.getFlag(1);
+  }
+  bool setSkippingUntilPCHThroughHeader(bool Value) {
+    PendingDestroyLexers.setFlag(1, Value);
+    return Value;
+  }
 
   /// Whether the main file is preprocessed module file.
-  bool MainFileIsPreprocessedModuleFile = false;
+  bool getMainFileIsPreprocessedModuleFile() const {
+    return PendingDestroyLexers.getFlag(2);
+  }
+  bool setMainFileIsPreprocessedModuleFile(bool Value) {
+    PendingDestroyLexers.setFlag(2, Value);
+    return Value;
+  }
 
   /// \{
   /// Cache of macro expanders to reduce malloc traffic.
@@ -1230,7 +1311,12 @@ class Preprocessor {
   /// This is used to guard against calling this function recursively.
   ///
   /// See comments at the use-site for more context about why it is needed.
-  bool SkippingExcludedConditionalBlock = false;
+  bool getSkippingExcludedConditionalBlock() const {
+    return PendingDestroyLexers.getFlag(3);
+  }
+  void setSkippingExcludedConditionalBlock(bool Value) {
+    PendingDestroyLexers.setFlag(3, Value);
+  }
 
   /// Keeps track of skipped range mappings that were recorded while skipping
   /// excluded conditional directives. It maps the source buffer pointer at
@@ -1313,7 +1399,7 @@ class Preprocessor {
 
   /// True if we are currently preprocessing a #if or #elif directive
   bool isParsingIfOrElifDirective() const {
-    return ParsingIfOrElifDirective;
+    return getParsingIfOrElifDirective();
   }
 
   /// Control whether the preprocessor retains comments in output.
@@ -1338,12 +1424,12 @@ class Preprocessor {
   /// Sets whether the preprocessor is responsible for producing output or if
   /// it is producing tokens to be consumed by Parse and Sema.
   void setPreprocessedOutput(bool IsPreprocessedOutput) {
-    PreprocessedOutput = IsPreprocessedOutput;
+    setPreprocessedOutputFlag(IsPreprocessedOutput);
   }
 
   /// Returns true if the preprocessor is responsible for generating output,
   /// false if it is producing tokens to be consumed by Parse and Sema.
-  bool isPreprocessedOutput() const { return PreprocessedOutput; }
+  bool isPreprocessedOutput() const { return getPreprocessedOutputFlag(); }
 
   /// Return true if we are lexing directly from the specified lexer.
   bool isCurrentLexer(const PreprocessorLexer *L) const {
@@ -1408,7 +1494,9 @@ class Preprocessor {
     GetDependencyDirectives = &Get;
   }
 
-  void setPreprocessToken(bool Preprocess) { PreprocessToken = Preprocess; }
+  void setPreprocessToken(bool Preprocess) {
+    setPreprocessTokenFlag(Preprocess);
+  }
 
   bool isMacroDefined(StringRef Id) {
     return isMacroDefined(&Identifiers.get(Id));
@@ -1589,8 +1677,9 @@ class Preprocessor {
   ///
   /// These predefines are automatically injected when parsing the main file.
   void setPredefines(std::string P) {
-    PredefinesWereReplaced |= PredefinesInitialized;
-    PredefinesInitialized = true;
+    setPredefinesWereReplaced(int(getPredefinesWereReplaced()) |
+                              (getPredefinesInitialized()));
+    setPredefinesInitialized(true);
     Predefines = std::move(P);
   }
 
@@ -1835,14 +1924,14 @@ class Preprocessor {
 
   /// Whether the main file is preprocessed module file.
   bool isPreprocessedModuleFile() const {
-    return MainFileIsPreprocessedModuleFile;
+    return getMainFileIsPreprocessedModuleFile();
   }
 
   /// Mark the main file as a preprocessed module file, then the 'module' and
   /// 'import' directive recognition will be suppressed. Only
   /// '__preprocessed_moduke' and '__preprocessed_import' are allowed.
   void markMainFileAsPreprocessedModuleFile() {
-    MainFileIsPreprocessedModuleFile = true;
+    setMainFileIsPreprocessedModuleFile(true);
   }
 
   bool LexModuleNameContinue(Token &Tok, SourceLocation UseLoc,
@@ -2069,11 +2158,13 @@ class Preprocessor {
   void recomputeCurLexerKind();
 
   /// Returns true if incremental processing is enabled
-  bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; }
+  bool isIncrementalProcessingEnabled() const {
+    return getIncrementalProcessing();
+  }
 
   /// Enables the incremental processing
   void enableIncrementalProcessing(bool value = true) {
-    IncrementalProcessing = value;
+    setIncrementalProcessing(value);
   }
 
   /// Specify the point at which code-completion will be performed.
@@ -2112,12 +2203,14 @@ class Preprocessor {
 
   /// Returns true if code-completion is enabled and we have hit the
   /// code-completion point.
-  bool isCodeCompletionReached() const { return CodeCompletionReached; }
+  bool isCodeCompletionReached() const {
+    return getCodeCompletionReachedFlag();
+  }
 
   /// Note that we hit the code-completion point.
   void setCodeCompletionReached() {
     assert(isCodeCompletionEnabled() && "Code-completion not enabled!");
-    CodeCompletionReached = true;
+    setCodeCompletionReachedFlag(true);
     // Silence any diagnostics that occur after we hit the code-completion.
     getDiagnostics().setSuppressAllDiagnostics(true);
   }
@@ -2571,7 +2664,7 @@ class Preprocessor {
   bool isImportingCXXNamedModules() const {
     assert(getLangOpts().CPlusPlusModules &&
            "Import C++ named modules are only valid for C++20 modules");
-    return ImportingCXXNamedModules;
+    return getImportingCXXNamedModules();
   }
 
   /// Allocate a new MacroInfo object with the provided SourceLocation.
diff --git a/clang/include/clang/Lex/PreprocessorLexer.h b/clang/include/clang/Lex/PreprocessorLexer.h
index d71fe708ab20a..1435161f9edae 100644
--- a/clang/include/clang/Lex/PreprocessorLexer.h
+++ b/clang/include/clang/Lex/PreprocessorLexer.h
@@ -20,6 +20,7 @@
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cassert>
 
 namespace clang {
@@ -47,10 +48,17 @@ class PreprocessorLexer {
   //===--------------------------------------------------------------------===//
 
   /// True when parsing \#XXX; turns '\\n' into a tok::eod token.
-  bool ParsingPreprocessorDirective = false;
+  bool getParsingPreprocessorDirectiveFlag() const {
+    return ConditionalStack.getFlag(0);
+  }
+  bool setParsingPreprocessorDirectiveFlag(bool Value) {
+    ConditionalStack.setFlag(0, Value);
+    return Value;
+  }
 
   /// True after \#include; turns \<xx> or "xxx" into a tok::header_name token.
-  bool ParsingFilename = false;
+  bool getParsingFilename() const { return ConditionalStack.getFlag(1); }
+  void setParsingFilename(bool Value) { ConditionalStack.setFlag(1, Value); }
 
   /// True if in raw mode.
   ///
@@ -65,7 +73,11 @@ class PreprocessorLexer {
   ///  5. No callbacks are made into the preprocessor.
   ///
   /// Note that in raw mode that the PP pointer may be null.
-  bool LexingRawMode = false;
+  bool getLexingRawMode() const { return ConditionalStack.getFlag(2); }
+  bool setLexingRawMode(bool Value) {
+    ConditionalStack.setFlag(2, Value);
+    return Value;
+  }
 
   /// A state machine that detects the \#ifndef-wrapping a file
   /// idiom for the multiple-include optimization.
@@ -73,7 +85,7 @@ class PreprocessorLexer {
 
   /// Information about the set of \#if/\#ifdef/\#ifndef blocks
   /// we are currently in.
-  SmallVector<PPConditionalInfo, 4> ConditionalStack;
+  llvm::SmallVectorWithFlags<PPConditionalInfo, 4, 3> ConditionalStack;
 
   PreprocessorLexer() : FID() {}
   PreprocessorLexer(Preprocessor *pp, FileID fid);
@@ -135,11 +147,11 @@ class PreprocessorLexer {
   /// Inform the lexer whether or not we are currently lexing a
   /// preprocessor directive.
   void setParsingPreprocessorDirective(bool f) {
-    ParsingPreprocessorDirective = f;
+    setParsingPreprocessorDirectiveFlag(f);
   }
 
   /// Return true if this lexer is in raw mode or not.
-  bool isLexingRawMode() const { return LexingRawMode; }
+  bool isLexingRawMode() const { return getLexingRawMode(); }
 
   /// Return the preprocessor object for this lexer.
   Preprocessor *getPP() const { return PP; }
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 9a1abd4f3872d..cf5d119118201 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -23,6 +23,7 @@
 #include "clang/Sema/SemaOpenMP.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Frontend/OpenMP/OMPContext.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include <optional>
@@ -684,7 +685,12 @@ class Parser : public CodeCompletionHandler {
   /// Gets set to true after calling ProduceSignatureHelp, it is for a
   /// workaround to make sure ProduceSignatureHelp is only called at the deepest
   /// function call.
-  bool CalledSignatureHelp = false;
+  bool getCalledSignatureHelp() const {
+    return TentativelyDeclaredIdentifiers.getFlag(0);
+  }
+  void setCalledSignatureHelp(bool Value) {
+    TentativelyDeclaredIdentifiers.setFlag(0, Value);
+  }
 
   bool isTokenSEHExcept();
 
@@ -692,7 +698,12 @@ class Parser : public CodeCompletionHandler {
   ///
   /// This option can be used, for example, to speed up searches for
   /// declarations/definitions when indexing.
-  bool SkipFunctionBodies;
+  bool getSkipFunctionBodies() const {
+    return TentativelyDeclaredIdentifiers.getFlag(1);
+  }
+  void setSkipFunctionBodies(bool Value) {
+    TentativelyDeclaredIdentifiers.setFlag(1, Value);
+  }
 
   //===--------------------------------------------------------------------===//
   // Low-Level token peeking and consumption methods.
@@ -1353,7 +1364,7 @@ class Parser : public CodeCompletionHandler {
   /// the method declarations and possibly attached inline definitions
   /// will be stored here with the tokens that will be parsed to create those
   /// entities.
-  typedef SmallVector<LateParsedDeclaration *, 2>
+  typedef llvm::SmallVectorWithFlags<LateParsedDeclaration *, 2, 2>
       LateParsedDeclarationsContainer;
 
   /// Utility to re-enter a possibly-templated scope while parsing its
@@ -2919,15 +2930,17 @@ class Parser : public CodeCompletionHandler {
   /// parsed after the corresponding top-level class is complete.
   struct ParsingClass {
     ParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface)
-        : TopLevelClass(TopLevelClass), IsInterface(IsInterface),
-          TagOrTemplate(TagOrTemplate) {}
+        : TagOrTemplate(TagOrTemplate) {
+      LateParsedDeclarations.setFlag(0, TopLevelClass);
+      LateParsedDeclarations.setFlag(1, IsInterface);
+    }
 
     /// Whether this is a "top-level" class, meaning that it is
     /// not nested within another class.
-    bool TopLevelClass : 1;
+    bool isTopLevelClass() const { return LateParsedDeclarations.getFlag(0); }
 
     /// Whether this class is an __interface.
-    bool IsInterface : 1;
+    bool isInterface() const { return LateParsedDeclarations.getFlag(1); }
 
     /// The class or class template whose definition we are parsing.
     Decl *TagOrTemplate;
@@ -4522,12 +4535,22 @@ class Parser : public CodeCompletionHandler {
   /// code like "foo : bar" as if it were a typo for "foo :: bar".  This is not
   /// safe in case statements and a few other things.  This is managed by the
   /// ColonProtectionRAIIObject RAII object.
-  bool ColonIsSacred;
+  bool getColonIsSacred() const {
+    return TentativelyDeclaredIdentifiers.getFlag(2);
+  }
+  void setColonIsSacred(bool Value) {
+    TentativelyDeclaredIdentifiers.setFlag(2, Value);
+  }
 
   // ParsingGenericAssociationType - Currently parsing the typename in
   // _Generic association. This is to consume the colon if what comes after it
   // is a type.
-  bool ParsingGenericAssociationType;
+  bool getParsingGenericAssociationType() const {
+    return TentativelyDeclaredIdentifiers.getFlag(3);
+  }
+  void setParsingGenericAssociationType(bool Value) {
+    TentativelyDeclaredIdentifiers.setFlag(3, Value);
+  }
 
   /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
   /// parenthesized ambiguous type-id. This uses tentative parsing to
@@ -5740,20 +5763,23 @@ class Parser : public CodeCompletionHandler {
   struct ObjCImplParsingDataRAII {
     Parser &P;
     Decl *Dcl;
-    bool HasCFunction;
+    bool getHasCFunction() const { return LateParsedObjCMethods.getFlag(0); }
+    void setHasCFunction(bool Value) {
+      LateParsedObjCMethods.setFlag(0, Value);
+    }
     typedef SmallVector<LexedMethod *, 8> LateParsedObjCMethodContainer;
-    LateParsedObjCMethodContainer LateParsedObjCMethods;
+    llvm::SmallVectorWithFlagsFor<LateParsedObjCMethodContainer, 2>
+        LateParsedObjCMethods;
 
     ObjCImplParsingDataRAII(Parser &parser, Decl *D)
-        : P(parser), Dcl(D), HasCFunction(false),
-          PrevParsedObjCImpl(parser.CurParsedObjCImpl) {
+        : P(parser), Dcl(D), PrevParsedObjCImpl(parser.CurParsedObjCImpl) {
       P.CurParsedObjCImpl = this;
-      Finished = false;
+      setFinished(false);
     }
     ~ObjCImplParsingDataRAII();
 
     void finish(SourceRange AtEnd);
-    bool isFinished() const { return Finished; }
+    bool isFinished() const { return getFinished(); }
 
   private:
     /// The \@implementation that was still open when this one started; made
@@ -5762,7 +5788,8 @@ class Parser : public CodeCompletionHandler {
     /// still open (e.g. through an intervening namespace). For valid code
     /// this is always null.
     ObjCImplParsingDataRAII *PrevParsedObjCImpl;
-    bool Finished;
+    bool getFinished() const { return LateParsedObjCMethods.getFlag(1); }
+    void setFinished(bool Value) { LateParsedObjCMethods.setFlag(1, Value); }
   };
   ObjCImplParsingDataRAII *CurParsedObjCImpl;
 
@@ -6226,10 +6253,11 @@ class Parser : public CodeCompletionHandler {
   };
 
   struct OpenACCWaitParseInfo {
-    bool Failed = false;
+    bool getFailed() const { return QueueIdExprs.getFlag(0); }
+    void setFailed(bool Value) { QueueIdExprs.setFlag(0, Value); }
     Expr *DevNumExpr = nullptr;
     SourceLocation QueuesLoc;
-    SmallVector<Expr *> QueueIdExprs;
+    llvm::SmallVectorWithFlags<Expr *> QueueIdExprs;
 
     SmallVector<Expr *> getAllExprs() {
       SmallVector<Expr *> Out;
@@ -8037,7 +8065,8 @@ class Parser : public CodeCompletionHandler {
   };
 
   /// Identifiers which have been declared within a tentative parse.
-  SmallVector<const IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;
+  llvm::SmallVectorWithFlags<const IdentifierInfo *, 8, 4>
+      TentativelyDeclaredIdentifiers;
 
   /// Tracker for '<' tokens that might have been intended to be treated as an
   /// angle bracket instead of a less-than comparison.
diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h
index 7b2c9c6c049a4..bd1b645da346a 100644
--- a/clang/include/clang/Parse/RAIIObjectsForParser.h
+++ b/clang/include/clang/Parse/RAIIObjectsForParser.h
@@ -275,15 +275,13 @@ namespace clang {
     bool OldVal;
   public:
     ColonProtectionRAIIObject(Parser &p, bool Value = true)
-      : P(p), OldVal(P.ColonIsSacred) {
-      P.ColonIsSacred = Value;
+        : P(p), OldVal(P.getColonIsSacred()) {
+      P.setColonIsSacred(Value);
     }
 
     /// restore - This can be used to restore the state early, before the dtor
     /// is run.
-    void restore() {
-      P.ColonIsSacred = OldVal;
-    }
+    void restore() { P.setColonIsSacred(OldVal); }
 
     ~ColonProtectionRAIIObject() {
       restore();
@@ -296,8 +294,8 @@ namespace clang {
 
   public:
     GenericAssociationTypeRAIIObject(Parser &P, bool Value = true)
-        : P(P), OldVal(P.ParsingGenericAssociationType) {
-      P.ParsingGenericAssociationType = Value;
+        : P(P), OldVal(P.getParsingGenericAssociationType()) {
+      P.setParsingGenericAssociationType(Value);
     }
 
     GenericAssociationTypeRAIIObject(const GenericAssociationTypeRAIIObject &) =
@@ -305,7 +303,7 @@ namespace clang {
     GenericAssociationTypeRAIIObject &
     operator=(const GenericAssociationTypeRAIIObject &) = delete;
 
-    void restore() { P.ParsingGenericAssociationType = OldVal; }
+    void restore() { P.setParsingGenericAssociationType(OldVal); }
 
     ~GenericAssociationTypeRAIIObject() { restore(); }
   };
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 66a6098a75ae9..14ebb7c9e7c2a 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -34,6 +34,7 @@
 #include "clang/Sema/ParsedAttr.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <optional>
@@ -1259,28 +1260,24 @@ class UnqualifiedId {
 typedef SmallVector<Token, 4> CachedTokens;
 
 // A list of late-parsed attributes.  Used by ParseGNUAttributes.
-class LateParsedAttrList : public SmallVector<LateParsedAttribute *, 2> {
+class LateParsedAttrList
+    : public llvm::SmallVectorWithFlags<LateParsedAttribute *, 2, 3> {
 public:
   LateParsedAttrList(bool PSoon = false,
                      bool LateAttrParseExperimentalExtOnly = false,
-                     bool LateAttrParseTypeAttrOnly = false)
-      : ParseSoon(PSoon),
-        LateAttrParseExperimentalExtOnly(LateAttrParseExperimentalExtOnly),
-        LateAttrParseTypeAttrOnly(LateAttrParseTypeAttrOnly) {}
+                     bool LateAttrParseTypeAttrOnly = false) {
+    // Flag bits 0-2 select immediate parsing and the two attribute filters.
+    setFlags(unsigned(PSoon) |
+             (unsigned(LateAttrParseExperimentalExtOnly) << 1) |
+             (unsigned(LateAttrParseTypeAttrOnly) << 2));
+  }
 
-  bool parseSoon() const { return ParseSoon; }
+  bool parseSoon() const { return getFlag(0); }
   /// returns true iff the attribute to be parsed should only be late parsed
   /// if it is annotated with `LateAttrParseExperimentalExt`
-  bool lateAttrParseExperimentalExtOnly() const {
-    return LateAttrParseExperimentalExtOnly;
-  }
+  bool lateAttrParseExperimentalExtOnly() const { return getFlag(1); }
 
-  bool lateAttrParseTypeAttrOnly() const { return LateAttrParseTypeAttrOnly; }
-
-private:
-  bool ParseSoon; // Are we planning to parse these shortly after creation?
-  bool LateAttrParseExperimentalExtOnly;
-  bool LateAttrParseTypeAttrOnly;
+  bool lateAttrParseTypeAttrOnly() const { return getFlag(2); }
 };
 
 /// One instance of this struct is used for each type in a
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 8dc40a5bc58bd..623e232c18759 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -30,6 +30,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/TinyPtrVector.h"
@@ -723,17 +724,28 @@ class CapturingScopeInfo : public FunctionScopeInfo {
 
   /// - Whether the target type of return statements in this context
   /// is deduced (e.g. a lambda or block with omitted return type).
-  bool HasImplicitReturnType = false;
+  bool getHasImplicitReturnType() const { return LocalPacks.getFlag(0); }
+  void setHasImplicitReturnType(bool Value) { LocalPacks.setFlag(0, Value); }
 
   /// Whether this contains an unexpanded parameter pack.
-  bool ContainsUnexpandedParameterPack = false;
+  bool getContainsUnexpandedParameterPack() const {
+    return LocalPacks.getFlag(1);
+  }
+  void setContainsUnexpandedParameterPack(bool Value) {
+    LocalPacks.setFlag(1, Value);
+  }
+
+  void addUnexpandedParameterPack(bool ContainsPack) {
+    setContainsUnexpandedParameterPack(getContainsUnexpandedParameterPack() |
+                                       (ContainsPack));
+  }
 
   /// ReturnType - The target type of return statements in this context,
   /// or null if unknown.
   QualType ReturnType;
 
   /// Packs introduced by this, if any.
-  SmallVector<NamedDecl *, 4> LocalPacks;
+  llvm::SmallVectorWithFlags<NamedDecl *, 4, 2> LocalPacks;
 
   void addCapture(ValueDecl *Var, bool isBlock, bool isByref, bool isNested,
                   SourceLocation Loc, SourceLocation EllipsisLoc,
@@ -877,9 +889,13 @@ class LambdaScopeInfo final :
   /// Indicate that we parsed the parameter list
   /// at which point the mutability of the lambda
   /// is known.
-  bool AfterParameterList = true;
+  bool getAfterParameterList() const { return !ShadowingDecls.getFlag(0); }
+  void setAfterParameterList(bool Value) { ShadowingDecls.setFlag(0, !Value); }
 
-  bool BeforeCompoundStatement = true;
+  bool getBeforeCompoundStatement() const { return !ShadowingDecls.getFlag(1); }
+  void setBeforeCompoundStatement(bool Value) {
+    ShadowingDecls.setFlag(1, !Value);
+  }
 
   ParmVarDecl *ExplicitObjectParameter = nullptr;
 
@@ -896,10 +912,15 @@ class LambdaScopeInfo final :
 
   /// Whether this is a mutable lambda. Until the mutable keyword is parsed,
   /// we assume the lambda is mutable.
-  bool Mutable = true;
+  bool getMutable() const { return !ShadowingDecls.getFlag(2); }
+  void setMutable(bool Value) { ShadowingDecls.setFlag(2, !Value); }
 
   /// Whether the (empty) parameter list is explicit.
-  bool ExplicitParams = false;
+  bool getExplicitParams() const { return ShadowingDecls.getFlag(3); }
+  bool setExplicitParams(bool Value) {
+    ShadowingDecls.setFlag(3, Value);
+    return Value;
+  }
 
   /// Whether any of the capture expressions requires cleanups.
   CleanupInfo Cleanup;
@@ -948,7 +969,7 @@ class LambdaScopeInfo final :
     const NamedDecl *VD;
     const NamedDecl *ShadowedDecl;
   };
-  llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls;
+  llvm::SmallVectorWithFlags<ShadowedOuterDecl, 4, 4> ShadowingDecls;
 
   SourceLocation PotentialThisCaptureLocation;
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 865defa98a1b3..cd6a1d25f1d04 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -86,6 +86,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/TinyPtrVector.h"
@@ -1141,7 +1142,12 @@ class Sema final : public SemaBase {
   /// Flushed whenever a diagnostic pragma changes severities.
   /// Level one is keyed on the diagnostic state alone.
   const void *DocDiagsStateKey = nullptr;
-  bool DocDiagsEnabledIgnoringSystem = false;
+  bool getDocDiagsEnabledIgnoringSystem() const {
+    return SavedPendingInstantiations.getFlag(0);
+  }
+  void setDocDiagsEnabledIgnoringSystem(bool Value) {
+    SavedPendingInstantiations.setFlag(0, Value);
+  }
 
   /// Level two, for when the location does matter. Bit i of each mask is a
   /// DiagStateSystemClass value; bit 0 is unused.
@@ -1392,11 +1398,22 @@ class Sema final : public SemaBase {
 
   /// Is the last error level diagnostic immediate. This is used to determined
   /// whether the next info diagnostic should be immediate.
-  bool IsLastErrorImmediate = true;
+  bool getIsLastErrorImmediate() const {
+    return !SavedPendingInstantiations.getFlag(1);
+  }
+  bool setIsLastErrorImmediate(bool Value) {
+    SavedPendingInstantiations.setFlag(1, !Value);
+    return Value;
+  }
 
   /// Track if we're currently analyzing overflow behavior types in assignment
   /// context.
-  bool InOverflowBehaviorAssignmentContext = false;
+  bool getInOverflowBehaviorAssignmentContext() const {
+    return SavedPendingInstantiations.getFlag(2);
+  }
+  void setInOverflowBehaviorAssignmentContext(bool Value) {
+    SavedPendingInstantiations.setFlag(2, Value);
+  }
 
   class DelayedDiagnostics;
 
@@ -1618,7 +1635,12 @@ class Sema final : public SemaBase {
 
 private:
   std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
-  bool WarnedDarwinSDKInfoMissing = false;
+  bool getWarnedDarwinSDKInfoMissing() const {
+    return SavedPendingInstantiations.getFlag(3);
+  }
+  void setWarnedDarwinSDKInfoMissing(bool Value) {
+    SavedPendingInstantiations.setFlag(3, Value);
+  }
 
   StackExhaustionHandler StackHandler;
 
@@ -1859,7 +1881,10 @@ class Sema final : public SemaBase {
   LangOptions::PragmaMSPointersToMembersKind
       MSPointerToMemberRepresentationMethod;
 
-  bool MSStructPragmaOn; // True when \#pragma ms_struct on
+  bool getMSStructPragmaOn() const { return SavedVTableUses.getFlag(0); }
+  void setMSStructPragmaOn(bool Value) {
+    SavedVTableUses.setFlag(0, Value);
+  } // True when \#pragma ms_struct on
 
   /// Source location for newly created implicit MSInheritanceAttrs
   SourceLocation ImplicitMSInheritanceAttrLoc;
@@ -2149,10 +2174,17 @@ class Sema final : public SemaBase {
 
   /// This an attribute introduced by \#pragma clang attribute.
   struct PragmaAttributeEntry {
+    PragmaAttributeEntry(SourceLocation Loc, ParsedAttr *Attribute,
+                         SmallVector<attr::SubjectMatchRule, 4> MatchRules,
+                         bool IsUsed)
+        : Loc(Loc), Attribute(Attribute),
+          MatchRules(unsigned(IsUsed), std::move(MatchRules)) {}
+
     SourceLocation Loc;
     ParsedAttr *Attribute;
-    SmallVector<attr::SubjectMatchRule, 4> MatchRules;
-    bool IsUsed;
+    llvm::SmallVectorWithFlags<attr::SubjectMatchRule, 4> MatchRules;
+    bool getIsUsed() const { return MatchRules.getFlag(0); }
+    void setIsUsed(bool Value) { MatchRules.setFlag(0, Value); }
   };
 
   /// A push'd group of PragmaAttributeEntries.
@@ -2186,7 +2218,10 @@ class Sema final : public SemaBase {
   /// turned off or on. This boolean is true by default because command line
   /// options are honored when `#pragma optimize("", on)`.
   /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing)
-  bool MSPragmaOptimizeIsOn = true;
+  bool getMSPragmaOptimizeIsOn() const { return !SavedVTableUses.getFlag(1); }
+  void setMSPragmaOptimizeIsOn(bool Value) {
+    SavedVTableUses.setFlag(1, !Value);
+  }
 
   /// Set of no-builtin functions listed by \#pragma function.
   llvm::SmallSetVector<StringRef, 4> MSFunctionNoBuiltins;
@@ -6889,11 +6924,12 @@ class Sema final : public SemaBase {
 
     /// If we are processing a decltype type, a set of call expressions
     /// for which we have deferred checking the completeness of the return type.
-    SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
+    llvm::SmallVectorWithFlags<CallExpr *, 8, 4> DelayedDecltypeCalls;
 
     /// If we are processing a decltype type, a set of temporary binding
     /// expressions for which we have deferred checking the destructor.
-    SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+    llvm::SmallVectorWithFlags<CXXBindTemporaryExpr *, 8, 4>
+        DelayedDecltypeBinds;
 
     llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
 
@@ -6932,27 +6968,64 @@ class Sema final : public SemaBase {
 
     // A context can be nested in both a discarded statement context and
     // an immediate function context, so they need to be tracked independently.
-    bool InDiscardedStatement;
-    bool InImmediateFunctionContext;
-    bool InImmediateEscalatingFunctionContext;
+    bool getInDiscardedStatement() const {
+      return DelayedDecltypeBinds.getFlag(0);
+    }
+    void setInDiscardedStatement(bool Value) {
+      DelayedDecltypeBinds.setFlag(0, Value);
+    }
+    bool getInImmediateFunctionContext() const {
+      return DelayedDecltypeBinds.getFlag(1);
+    }
+    bool setInImmediateFunctionContext(bool Value) {
+      DelayedDecltypeBinds.setFlag(1, Value);
+      return Value;
+    }
+    bool getInImmediateEscalatingFunctionContext() const {
+      return DelayedDecltypeBinds.getFlag(2);
+    }
+    void setInImmediateEscalatingFunctionContext(bool Value) {
+      DelayedDecltypeBinds.setFlag(2, Value);
+    }
 
-    bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
+    bool getIsCurrentlyCheckingDefaultArgumentOrInitializer() const {
+      return DelayedDecltypeBinds.getFlag(3);
+    }
+    void setIsCurrentlyCheckingDefaultArgumentOrInitializer(bool Value) {
+      DelayedDecltypeBinds.setFlag(3, Value);
+    }
 
     // We are in a constant context, but we also allow
     // non constant expressions, for example for array bounds (which may be
     // VLAs).
-    bool InConditionallyConstantEvaluateContext = false;
+    bool getInConditionallyConstantEvaluateContext() const {
+      return DelayedDecltypeCalls.getFlag(0);
+    }
+    void setInConditionallyConstantEvaluateContext(bool Value) {
+      DelayedDecltypeCalls.setFlag(0, Value);
+    }
 
     /// Whether we are currently in a context in which all temporaries must be
     /// lifetime-extended, even if they're not bound to a reference (for
     /// example, in a for-range initializer).
-    bool InLifetimeExtendingContext = false;
+    bool getInLifetimeExtendingContext() const {
+      return DelayedDecltypeCalls.getFlag(1);
+    }
+    void setInLifetimeExtendingContext(bool Value) {
+      DelayedDecltypeCalls.setFlag(1, Value);
+    }
 
     /// Whether evaluating an expression for a switch case label.
-    bool IsCaseExpr = false;
+    bool getIsCaseExpr() const { return DelayedDecltypeCalls.getFlag(2); }
+    void setIsCaseExpr(bool Value) { DelayedDecltypeCalls.setFlag(2, Value); }
 
     /// Whether we should rebuild CXXDefaultArgExpr and CXXDefaultInitExpr.
-    bool RebuildDefaultArgOrDefaultInit = false;
+    bool getRebuildDefaultArgOrDefaultInit() const {
+      return DelayedDecltypeCalls.getFlag(3);
+    }
+    void setRebuildDefaultArgOrDefaultInit(bool Value) {
+      DelayedDecltypeCalls.setFlag(3, Value);
+    }
 
     // When evaluating immediate functions in the initializer of a default
     // argument or default member initializer, this is the declaration whose
@@ -6978,9 +7051,7 @@ class Sema final : public SemaBase {
                                       ExpressionKind ExprContext)
         : Context(Context), ParentCleanup(ParentCleanup),
           NumCleanupObjects(NumCleanupObjects),
-          ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
-          InDiscardedStatement(false), InImmediateFunctionContext(false),
-          InImmediateEscalatingFunctionContext(false) {}
+          ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext) {}
 
     bool isUnevaluated() const {
       return Context == ExpressionEvaluationContext::Unevaluated ||
@@ -7003,7 +7074,7 @@ class Sema final : public SemaBase {
     bool isImmediateFunctionContext() const {
       return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
              (Context == ExpressionEvaluationContext::DiscardedStatement &&
-              InImmediateFunctionContext) ||
+              getInImmediateFunctionContext()) ||
              // C++23 [expr.const]p14:
              // An expression or conversion is in an immediate function
              // context if it is potentially evaluated and either:
@@ -7012,7 +7083,7 @@ class Sema final : public SemaBase {
              //   * its enclosing statement is enclosed by the compound-
              //     statement of a consteval if statement.
              (Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
-              InImmediateFunctionContext);
+              getInImmediateFunctionContext());
     }
 
     bool isDiscardedStatementContext() const {
@@ -7020,7 +7091,7 @@ class Sema final : public SemaBase {
              ((Context ==
                    ExpressionEvaluationContext::ImmediateFunctionContext ||
                isPotentiallyEvaluated()) &&
-              InDiscardedStatement);
+              getInDiscardedStatement());
     }
   };
 
@@ -8275,12 +8346,17 @@ class Sema final : public SemaBase {
   /// Whether the AST is currently being rebuilt to correct immediate
   /// invocations. Immediate invocation candidates and references to consteval
   /// functions aren't tracked when this is set.
-  bool RebuildingImmediateInvocation = false;
+  bool getRebuildingImmediateInvocation() const {
+    return SavedVTableUses.getFlag(2);
+  }
+  void setRebuildingImmediateInvocation(bool Value) {
+    SavedVTableUses.setFlag(2, Value);
+  }
 
   bool isAlwaysConstantEvaluatedContext() const {
     const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
     return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
-           !Ctx.InConditionallyConstantEvaluateContext;
+           !Ctx.getInConditionallyConstantEvaluateContext();
   }
 
   /// Determines whether we are currently in a context that
@@ -8294,18 +8370,18 @@ class Sema final : public SemaBase {
   }
 
   bool isInLifetimeExtendingContext() const {
-    return currentEvaluationContext().InLifetimeExtendingContext;
+    return currentEvaluationContext().getInLifetimeExtendingContext();
   }
 
   bool needsRebuildOfDefaultArgOrInit() const {
-    return currentEvaluationContext().RebuildDefaultArgOrDefaultInit;
+    return currentEvaluationContext().getRebuildDefaultArgOrDefaultInit();
   }
 
   bool isCheckingDefaultArgumentOrInitializer() const {
     const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
     return (Ctx.Context ==
             ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
-           Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
+           Ctx.getIsCurrentlyCheckingDefaultArgumentOrInitializer();
   }
 
   std::optional<ExpressionEvaluationContextRecord::InitializationContext>
@@ -8477,7 +8553,10 @@ class Sema final : public SemaBase {
 
   /// A flag to remember whether the implicit forms of operator new and delete
   /// have been declared.
-  bool GlobalNewDeleteDeclared;
+  bool getGlobalNewDeleteDeclared() const { return SavedVTableUses.getFlag(3); }
+  void setGlobalNewDeleteDeclared(bool Value) {
+    SavedVTableUses.setFlag(3, Value);
+  }
 
   /// Delete-expressions to be analyzed at the end of translation unit
   ///
@@ -9391,7 +9470,12 @@ class Sema final : public SemaBase {
 public:
   /// Tracks whether we are in a context where typo correction is
   /// disabled.
-  bool DisableTypoCorrection;
+  bool getDisableTypoCorrection() const {
+    return LateParsedInstantiations.getFlag(0);
+  }
+  void setDisableTypoCorrection(bool Value) {
+    LateParsedInstantiations.setFlag(0, Value);
+  }
 
   /// The number of typos corrected by CorrectTypo.
   unsigned TyposCorrected;
@@ -9914,7 +9998,12 @@ class Sema final : public SemaBase {
 
   /// Whether we have already loaded known namespaces from an extenal
   /// source.
-  bool LoadedExternalKnownNamespaces;
+  bool getLoadedExternalKnownNamespaces() const {
+    return LateParsedInstantiations.getFlag(1);
+  }
+  void setLoadedExternalKnownNamespaces(bool Value) {
+    LateParsedInstantiations.setFlag(1, Value);
+  }
 
   bool CppLookupName(LookupResult &R, Scope *S);
 
@@ -10131,7 +10220,12 @@ class Sema final : public SemaBase {
   VisibleModuleSet VisibleModules;
 
   /// Whether we had imported any named modules.
-  bool HadImportedNamedModules = false;
+  bool getHadImportedNamedModules() const {
+    return LateParsedInstantiations.getFlag(2);
+  }
+  void setHadImportedNamedModules(bool Value) {
+    LateParsedInstantiations.setFlag(2, Value);
+  }
   /// The set of instantiations we need to check if they references TU-local
   /// entity from TUs. This only makes sense if we imported any named modules.
   llvm::SmallVector<std::pair<FunctionDecl *, SourceLocation>>
@@ -10158,7 +10252,8 @@ class Sema final : public SemaBase {
 
 public:
   /// Whether deferrable diagnostics should be deferred.
-  bool DeferDiags = false;
+  bool getDeferDiags() const { return LateParsedInstantiations.getFlag(3); }
+  void setDeferDiags(bool Value) { LateParsedInstantiations.setFlag(3, Value); }
 
   /// RAII class to control scope of DeferDiags.
   class DeferDiagsRAII {
@@ -10167,10 +10262,10 @@ class Sema final : public SemaBase {
 
   public:
     DeferDiagsRAII(Sema &S, bool DeferDiags)
-        : S(S), SavedDeferDiags(S.DeferDiags) {
-      S.DeferDiags = SavedDeferDiags || DeferDiags;
+        : S(S), SavedDeferDiags(S.getDeferDiags()) {
+      S.setDeferDiags(SavedDeferDiags || DeferDiags);
     }
-    ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+    ~DeferDiagsRAII() { S.setDeferDiags(SavedDeferDiags); }
     DeferDiagsRAII(const DeferDiagsRAII &) = delete;
     DeferDiagsRAII &operator=(const DeferDiagsRAII &) = delete;
   };
@@ -10179,7 +10274,12 @@ class Sema final : public SemaBase {
   ///
   /// This flag is used to avoid building recovery call expressions
   /// if Sema is already doing so, which would cause infinite recursions.
-  bool IsBuildingRecoveryCallExpr;
+  bool getIsBuildingRecoveryCallExpr() const {
+    return CodeSynthesisContextLookupModules.getFlag(0);
+  }
+  void setIsBuildingRecoveryCallExpr(bool Value) {
+    CodeSynthesisContextLookupModules.setFlag(0, Value);
+  }
 
   /// Determine whether the given New declaration is an overload of the
   /// declarations in Old. This routine returns OverloadKind::Match or
@@ -12154,28 +12254,37 @@ class Sema final : public SemaBase {
   struct CheckTemplateArgumentInfo {
     explicit CheckTemplateArgumentInfo(bool PartialOrdering = false,
                                        bool MatchingTTP = false)
-        : PartialOrdering(PartialOrdering), MatchingTTP(MatchingTTP) {}
+        : CanonicalConverted(decltype(this->CanonicalConverted)::withFlags(
+              unsigned(PartialOrdering) | (unsigned(MatchingTTP) << 1))) {}
     CheckTemplateArgumentInfo(const CheckTemplateArgumentInfo &) = delete;
     CheckTemplateArgumentInfo &
     operator=(const CheckTemplateArgumentInfo &) = delete;
 
     /// The checked, converted argument will be added to the
     /// end of these vectors.
-    SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
+    SmallVector<TemplateArgument, 4> SugaredConverted;
+    llvm::SmallVectorWithFlags<TemplateArgument, 4, 3> CanonicalConverted;
 
     /// The check is being performed in the context of partial ordering.
-    bool PartialOrdering;
+    bool getPartialOrdering() const { return CanonicalConverted.getFlag(0); }
+    void setPartialOrdering(bool Value) {
+      CanonicalConverted.setFlag(0, Value);
+    }
 
     /// If true, assume these template arguments are
     /// the injected template arguments for a template template parameter.
     /// This will relax the requirement that all its possible uses are valid:
     /// TTP checking is loose, and assumes that invalid uses will be diagnosed
     /// during instantiation.
-    bool MatchingTTP;
+    bool getMatchingTTP() const { return CanonicalConverted.getFlag(1); }
+    void setMatchingTTP(bool Value) { CanonicalConverted.setFlag(1, Value); }
 
     /// Is set to true when, in the context of TTP matching, a pack parameter
     /// matches non-pack arguments.
-    bool StrictPackMatch = false;
+    bool getStrictPackMatch() const { return CanonicalConverted.getFlag(2); }
+    void setStrictPackMatch(bool Value) {
+      CanonicalConverted.setFlag(2, Value);
+    }
   };
 
   /// Check that the given template argument corresponds to the given
@@ -12256,10 +12365,9 @@ class Sema final : public SemaBase {
       CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
       bool *ConstraintsNotSatisfied = nullptr);
 
-  bool CheckTemplateTypeArgument(
-      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
-      SmallVectorImpl<TemplateArgument> &SugaredConverted,
-      SmallVectorImpl<TemplateArgument> &CanonicalConverted);
+  bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+                                 TemplateArgumentLoc &Arg,
+                                 CheckTemplateArgumentInfo &CTAI);
 
   /// Check a template argument against its corresponding
   /// template type parameter.
@@ -12679,11 +12787,11 @@ class Sema final : public SemaBase {
   public:
     explicit TentativeAnalysisScope(Sema &SemaRef)
         : SemaRef(SemaRef), Trap(SemaRef, /*ForValidityCheck=*/true),
-          PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
-      SemaRef.DisableTypoCorrection = true;
+          PrevDisableTypoCorrection(SemaRef.getDisableTypoCorrection()) {
+      SemaRef.setDisableTypoCorrection(true);
     }
     ~TentativeAnalysisScope() {
-      SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
+      SemaRef.setDisableTypoCorrection(PrevDisableTypoCorrection);
     }
 
     TentativeAnalysisScope(const TentativeAnalysisScope &) = delete;
@@ -13212,8 +13320,9 @@ class Sema final : public SemaBase {
 public:
   /// A helper class for building up ExtParameterInfos.
   class ExtParameterInfoBuilder {
-    SmallVector<FunctionProtoType::ExtParameterInfo, 16> Infos;
-    bool HasInteresting = false;
+    llvm::SmallVectorWithFlags<FunctionProtoType::ExtParameterInfo, 16> Infos;
+    bool getHasInteresting() const { return Infos.getFlag(0); }
+    void setHasInteresting(bool Value) { Infos.setFlag(0, Value); }
 
   public:
     /// Set the ExtParameterInfo for the parameter at the given index,
@@ -13223,15 +13332,15 @@ class Sema final : public SemaBase {
       Infos.resize(index);
       Infos.push_back(info);
 
-      if (!HasInteresting)
-        HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
+      if (!getHasInteresting())
+        setHasInteresting((info != FunctionProtoType::ExtParameterInfo()));
     }
 
     /// Return a pointer (suitable for setting in an ExtProtoInfo) to the
     /// ExtParameterInfo array we've built up.
     const FunctionProtoType::ExtParameterInfo *
     getPointerOrNull(unsigned numParams) {
-      if (!HasInteresting)
+      if (!getHasInteresting())
         return nullptr;
       Infos.resize(numParams);
       return Infos.data();
@@ -13800,7 +13909,7 @@ class Sema final : public SemaBase {
 
   /// Extra modules inspected when performing a lookup during a template
   /// instantiation. Computed lazily.
-  SmallVector<Module *, 16> CodeSynthesisContextLookupModules;
+  llvm::SmallVectorWithFlags<Module *, 16> CodeSynthesisContextLookupModules;
 
   /// Cache of additional modules that should be used for name lookup
   /// within the current template instantiation. Computed lazily; use
@@ -14189,10 +14298,11 @@ class Sema final : public SemaBase {
 
   /// Queue of implicit template instantiations that cannot be performed
   /// eagerly.
-  SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+  llvm::SmallVectorWithFlags<PendingImplicitInstantiation, 1, 4>
+      LateParsedInstantiations;
 
-  SmallVector<SmallVector<VTableUse, 16>, 8> SavedVTableUses;
-  SmallVector<std::deque<PendingImplicitInstantiation>, 8>
+  llvm::SmallVectorWithFlags<SmallVector<VTableUse, 16>, 8, 4> SavedVTableUses;
+  llvm::SmallVectorWithFlags<std::deque<PendingImplicitInstantiation>, 8, 4>
       SavedPendingInstantiations;
 
   /// The queue of implicit template instantiations that are required
@@ -14395,8 +14505,7 @@ class Sema final : public SemaBase {
   VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
       VarTemplateDecl *VarTemplate, VarDecl *FromVar,
       const TemplateArgumentList *PartialSpecArgs,
-      SmallVectorImpl<TemplateArgument> &Converted,
-      SourceLocation PointOfInstantiation,
+      ArrayRef<TemplateArgument> Converted, SourceLocation PointOfInstantiation,
       LateInstantiatedAttrVec *LateAttrs = nullptr,
       LocalInstantiationScope *StartingScope = nullptr);
 
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 3d62f47dfde69..eafe3a300c602 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Frontend/HLSL/SemanticSignatures.h"
 #include "llvm/TargetParser/Triple.h"
@@ -265,13 +266,18 @@ class SemaHLSL : public SemaBase {
 
   // Global declaration collected for the $Globals default constant
   // buffer which will be created at the end of the translation unit.
-  llvm::SmallVector<Decl *> DefaultCBufferDecls;
+  llvm::SmallVectorWithFlags<Decl *> DefaultCBufferDecls;
 
   uint32_t ImplicitBindingNextOrderID = 0;
 
   IdentifierInfo *RootSigOverrideIdent = nullptr;
 
-  bool HasDeclaredAPushConstant = false;
+  bool getHasDeclaredAPushConstant() const {
+    return DefaultCBufferDecls.getFlag(0);
+  }
+  void setHasDeclaredAPushConstant(bool Value) {
+    DefaultCBufferDecls.setFlag(0, Value);
+  }
 
   // Information about the current subtree being flattened.
   struct SemanticInfo {
diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h
index 8f6041b5f00e4..9a031f60c07f0 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -19,6 +19,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 
@@ -90,20 +91,19 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
   typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
 
 public:
-  TypoCorrectionConsumer(Sema &SemaRef,
-                         const DeclarationNameInfo &TypoName,
-                         Sema::LookupNameKind LookupKind,
-                         Scope *S, CXXScopeSpec *SS,
+  TypoCorrectionConsumer(Sema &SemaRef, const DeclarationNameInfo &TypoName,
+                         Sema::LookupNameKind LookupKind, Scope *S,
+                         CXXScopeSpec *SS,
                          std::unique_ptr<CorrectionCandidateCallback> CCC,
-                         DeclContext *MemberContext,
-                         bool EnteringContext)
+                         DeclContext *MemberContext, bool EnteringContext)
       : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
         SavedTCIndex(0), SemaRef(SemaRef), S(S),
         SS(SS ? std::make_unique<CXXScopeSpec>(*SS) : nullptr),
         CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
         Result(SemaRef, TypoName, LookupKind),
         Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
-        EnteringContext(EnteringContext), SearchNamespaces(false) {
+        QualifiedResults(decltype(this->QualifiedResults)::withFlags(
+            unsigned(EnteringContext))) {
     Result.suppressDiagnostics();
     // Arrange for ValidatedCorrections[0] to always be an empty correction.
     ValidatedCorrections.push_back(TypoCorrection());
@@ -315,9 +315,11 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
   DeclContext *MemberContext;
   LookupResult Result;
   NamespaceSpecifierSet Namespaces;
-  SmallVector<TypoCorrection, 2> QualifiedResults;
-  bool EnteringContext;
-  bool SearchNamespaces;
+  llvm::SmallVectorWithFlags<TypoCorrection, 2, 2> QualifiedResults;
+  bool getEnteringContext() const { return QualifiedResults.getFlag(0); }
+  void setEnteringContext(bool Value) { QualifiedResults.setFlag(0, Value); }
+  bool getSearchNamespaces() const { return QualifiedResults.getFlag(1); }
+  void setSearchNamespaces(bool Value) { QualifiedResults.setFlag(1, Value); }
 };
 
 } // end namespace clang
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 50e950e56c6ca..cf001564964e2 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cassert>
 #include <optional>
 #include <utility>
@@ -409,7 +410,7 @@ enum class TemplateSubstitutionKind : char {
     LocalDeclsMap LocalDecls;
 
     /// The set of argument packs we've allocated.
-    SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
+    llvm::SmallVectorWithFlags<DeclArgumentPack *, 1, 3> ArgumentPacks;
 
     /// The outer scope, which contains local variable
     /// definitions from some other instantiation (that may not be
@@ -417,16 +418,25 @@ enum class TemplateSubstitutionKind : char {
     LocalInstantiationScope *Outer;
 
     /// Whether we have already exited this scope.
-    bool Exited = false;
+    bool getExited() const { return ArgumentPacks.getFlag(0); }
+    void setExited(bool Value) { ArgumentPacks.setFlag(0, Value); }
 
     /// Whether to combine this scope with the outer scope, such that
     /// lookup will search our outer scope.
-    bool CombineWithOuterScope;
+    bool getCombineWithOuterScope() const { return ArgumentPacks.getFlag(1); }
+    void setCombineWithOuterScope(bool Value) {
+      ArgumentPacks.setFlag(1, Value);
+    }
 
     /// Whether this scope is being used to instantiate a lambda or block
     /// expression, in which case it should be reused for instantiating the
     /// lambda's FunctionProtoType.
-    bool InstantiatingLambdaOrBlock = false;
+    bool getInstantiatingLambdaOrBlock() const {
+      return ArgumentPacks.getFlag(2);
+    }
+    void setInstantiatingLambdaOrBlock(bool Value) {
+      ArgumentPacks.setFlag(2, Value);
+    }
 
     /// If non-NULL, the template parameter pack that has been
     /// partially substituted per C++0x [temp.arg.explicit]p9.
@@ -444,9 +454,10 @@ enum class TemplateSubstitutionKind : char {
   public:
     LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false,
                             bool InstantiatingLambdaOrBlock = false)
-        : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
-          CombineWithOuterScope(CombineWithOuterScope),
-          InstantiatingLambdaOrBlock(InstantiatingLambdaOrBlock) {
+        : SemaRef(SemaRef), ArgumentPacks(decltype(ArgumentPacks)::withFlags(
+                                (unsigned(CombineWithOuterScope) << 1) |
+                                (unsigned(InstantiatingLambdaOrBlock) << 2))),
+          Outer(SemaRef.CurrentInstantiationScope) {
       SemaRef.CurrentInstantiationScope = this;
     }
 
@@ -462,14 +473,14 @@ enum class TemplateSubstitutionKind : char {
 
     /// Exit this local instantiation scope early.
     void Exit() {
-      if (Exited)
+      if (getExited())
         return;
 
       for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
         delete ArgumentPacks[I];
 
       SemaRef.CurrentInstantiationScope = Outer;
-      Exited = true;
+      setExited(true);
     }
 
     /// Clone this scope, and all outer scopes, down to the given
@@ -482,7 +493,7 @@ enum class TemplateSubstitutionKind : char {
       LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
 
       LocalInstantiationScope *newScope =
-        new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
+          new LocalInstantiationScope(SemaRef, getCombineWithOuterScope());
 
       newScope->Outer = nullptr;
       if (Outer)
@@ -580,7 +591,7 @@ enum class TemplateSubstitutionKind : char {
     bool isLocalPackExpansion(const Decl *D);
 
     /// Determine whether this scope is for instantiating a lambda or block.
-    bool isLambdaOrBlock() const { return InstantiatingLambdaOrBlock; }
+    bool isLambdaOrBlock() const { return getInstantiatingLambdaOrBlock(); }
   };
 
   class TemplateDeclInstantiator
@@ -593,7 +604,12 @@ enum class TemplateSubstitutionKind : char {
     Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
     LocalInstantiationScope *StartingScope = nullptr;
     // Whether to evaluate the C++20 constraints or simply substitute into them.
-    bool EvaluateConstraints = true;
+    bool getEvaluateConstraintsFlag() const {
+      return !OutOfLineVarPartialSpecs.getFlag(0);
+    }
+    void setEvaluateConstraintsFlag(bool Value) {
+      OutOfLineVarPartialSpecs.setFlag(0, !Value);
+    }
 
     /// A list of out-of-line class template partial
     /// specializations that will need to be instantiated after the
@@ -607,7 +623,7 @@ enum class TemplateSubstitutionKind : char {
     /// specializations that will need to be instantiated after the
     /// enclosing variable's instantiation is complete.
     /// FIXME: Verify that this is needed.
-    SmallVector<
+    llvm::SmallVectorWithFlags<
         std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 1>
         OutOfLineVarPartialSpecs;
 
@@ -617,12 +633,8 @@ enum class TemplateSubstitutionKind : char {
         : SemaRef(SemaRef), SubstIndex(SemaRef, SemaRef.ArgPackSubstIndex),
           Owner(Owner), TemplateArgs(TemplateArgs) {}
 
-    void setEvaluateConstraints(bool B) {
-      EvaluateConstraints = B;
-    }
-    bool getEvaluateConstraints() {
-      return EvaluateConstraints;
-    }
+    void setEvaluateConstraints(bool B) { setEvaluateConstraintsFlag(B); }
+    bool getEvaluateConstraints() { return getEvaluateConstraintsFlag(); }
 
 // Define all the decl visitors using DeclNodes.inc
 #define DECL(DERIVED, BASE) \
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index dd9fe46c9bf8a..8b34eb9a6e413 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -14,15 +14,16 @@
 #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
 #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
 
-#include "clang/Sema/Ownership.h"
-#include "clang/Sema/SemaConcept.h"
 #include "clang/AST/ASTConcept.h"
 #include "clang/AST/DeclAccessPair.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaConcept.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cassert>
 #include <cstddef>
 #include <optional>
@@ -351,13 +352,14 @@ struct TemplateSpecCandidate {
 /// TODO: In the future, we may need to unify/generalize this with
 /// OverloadCandidateSet.
 class TemplateSpecCandidateSet {
-  SmallVector<TemplateSpecCandidate, 16> Candidates;
+  llvm::SmallVectorWithFlags<TemplateSpecCandidate, 16> Candidates;
   SourceLocation Loc;
 
   // Stores whether we're taking the address of these candidates. This helps us
   // produce better error messages when dealing with the pass_object_size
   // attribute on parameters.
-  bool ForTakingAddress;
+  bool getForTakingAddress() const { return Candidates.getFlag(0); }
+  void setForTakingAddress(bool Value) { Candidates.setFlag(0, Value); }
 
   TemplateSpecCandidateSetKind CandidateSetKind;
 
@@ -367,8 +369,8 @@ class TemplateSpecCandidateSet {
   TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false,
                            TemplateSpecCandidateSetKind CandidateSetKind =
                                TemplateSpecCandidateSetKind::Normal)
-      : Loc(Loc), ForTakingAddress(ForTakingAddress),
-        CandidateSetKind(CandidateSetKind) {}
+      : Candidates(decltype(Candidates)::withFlags(unsigned(ForTakingAddress))),
+        Loc(Loc), CandidateSetKind(CandidateSetKind) {}
   TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
   TemplateSpecCandidateSet &
   operator=(const TemplateSpecCandidateSet &) = delete;
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 275383d40cf80..b8a58fcfe79d0 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -44,6 +44,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
@@ -484,7 +485,12 @@ class ASTReader : public ExternalPreprocessorSource,
   /// The receiver of deserialization events.
   ASTDeserializationListener *DeserializationListener = nullptr;
 
-  bool OwnsDeserializationListener = false;
+  bool getOwnsDeserializationListener() const {
+    return CommentsCursors.getFlag(0);
+  }
+  void setOwnsDeserializationListener(bool Value) {
+    CommentsCursors.setFlag(0, Value);
+  }
 
   SourceManager &SourceMgr;
   FileManager &FileMgr;
@@ -1087,29 +1093,59 @@ class ASTReader : public ExternalPreprocessorSource,
   DisableValidationForModuleKind DisableValidationKind;
 
   /// Whether to accept an AST file with compiler errors.
-  bool AllowASTWithCompilerErrors;
+  bool getAllowASTWithCompilerErrors() const {
+    return CommentsCursors.getFlag(1);
+  }
+  void setAllowASTWithCompilerErrors(bool Value) {
+    CommentsCursors.setFlag(1, Value);
+  }
 
   /// Whether to accept an AST file that has a different configuration
   /// from the current compiler instance.
-  bool AllowConfigurationMismatch;
+  bool getAllowConfigurationMismatch() const {
+    return CommentsCursors.getFlag(2);
+  }
+  void setAllowConfigurationMismatch(bool Value) {
+    CommentsCursors.setFlag(2, Value);
+  }
 
   /// Whether to validate system input files.
-  bool ValidateSystemInputs;
+  bool getValidateSystemInputs() const { return CommentsCursors.getFlag(3); }
+  void setValidateSystemInputs(bool Value) {
+    CommentsCursors.setFlag(3, Value);
+  }
 
   /// Whether to force the validation of user input files.
-  bool ForceValidateUserInputs;
+  bool getForceValidateUserInputs() const {
+    return PreloadedDeclIDs.getFlag(0);
+  }
+  void setForceValidateUserInputs(bool Value) {
+    PreloadedDeclIDs.setFlag(0, Value);
+  }
 
   /// Whether validate headers and module maps using hash based on contents.
-  bool ValidateASTInputFilesContent;
+  bool getValidateASTInputFilesContent() const {
+    return PreloadedDeclIDs.getFlag(1);
+  }
+  void setValidateASTInputFilesContent(bool Value) {
+    PreloadedDeclIDs.setFlag(1, Value);
+  }
 
   /// Whether we are allowed to use the global module index.
-  bool UseGlobalIndex;
+  bool getUseGlobalIndex() const { return PreloadedDeclIDs.getFlag(2); }
+  void setUseGlobalIndex(bool Value) { PreloadedDeclIDs.setFlag(2, Value); }
 
   /// Whether we have tried loading the global module index yet.
-  bool TriedLoadingGlobalIndex = false;
+  bool getTriedLoadingGlobalIndex() const {
+    return PreloadedDeclIDs.getFlag(3);
+  }
+  void setTriedLoadingGlobalIndex(bool Value) {
+    PreloadedDeclIDs.setFlag(3, Value);
+  }
 
   ///Whether we are currently processing update records.
-  bool ProcessingUpdateRecords = false;
+  bool getProcessingUpdateRecords() const { return StmtStack.getFlag(0); }
+  void setProcessingUpdateRecords(bool Value) { StmtStack.setFlag(0, Value); }
 
   using SwitchCaseMapTy = llvm::DenseMap<unsigned, SwitchCase *>;
 
@@ -1197,7 +1233,8 @@ class ASTReader : public ExternalPreprocessorSource,
   /// "interesting" decls to the consumer inside FinishedDeserializing().
   /// This is used as a guard to avoid recursively entering the process of
   /// passing decls to consumer.
-  bool CanPassDeclsToConsumer = true;
+  bool getCanPassDeclsToConsumer() const { return !StmtStack.getFlag(1); }
+  void setCanPassDeclsToConsumer(bool Value) { StmtStack.setFlag(1, !Value); }
 
   /// The set of identifiers that were read while the AST reader was
   /// (recursively) loading declarations.
@@ -1354,7 +1391,7 @@ class ASTReader : public ExternalPreprocessorSource,
   llvm::DenseMap<RecordDecl *, RecordDecl *> RecordDefinitions;
 
   /// When reading a Stmt tree, Stmt operands are placed in this stack.
-  SmallVector<Stmt *, 16> StmtStack;
+  llvm::SmallVectorWithFlags<Stmt *, 16, 2> StmtStack;
 
   /// What kind of records we are reading.
   enum ReadingKind {
@@ -1387,14 +1424,16 @@ class ASTReader : public ExternalPreprocessorSource,
 
   public:
     ProcessingUpdatesRAIIObj(ASTReader &reader)
-        : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) {
-      Reader.ProcessingUpdateRecords = true;
+        : Reader(reader), PrevState(Reader.getProcessingUpdateRecords()) {
+      Reader.setProcessingUpdateRecords(true);
     }
 
     ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete;
     ProcessingUpdatesRAIIObj &
     operator=(const ProcessingUpdatesRAIIObj &) = delete;
-    ~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; }
+    ~ProcessingUpdatesRAIIObj() {
+      Reader.setProcessingUpdateRecords(PrevState);
+    }
   };
 
   /// Suggested contents of the predefines buffer, after this
@@ -1952,7 +1991,7 @@ class ASTReader : public ExternalPreprocessorSource,
   GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); }
 
   /// Reset reader for a reload try.
-  void resetForReload() { TriedLoadingGlobalIndex = false; }
+  void resetForReload() { setTriedLoadingGlobalIndex(false); }
 
   /// Attempts to load the global index.
   ///
@@ -2622,7 +2661,7 @@ class ASTReader : public ExternalPreprocessorSource,
 
   // Contains the IDs for declarations that were requested before we have
   // access to a Sema object.
-  SmallVector<GlobalDeclID, 16> PreloadedDeclIDs;
+  llvm::SmallVectorWithFlags<GlobalDeclID, 16, 4> PreloadedDeclIDs;
 
   /// Retrieve the semantic analysis object used to analyze the
   /// translation unit in which the precompiled header is being
@@ -2648,8 +2687,9 @@ class ASTReader : public ExternalPreprocessorSource,
   void ClearSwitchCaseIDs();
 
   /// Cursors for comments blocks.
-  SmallVector<std::pair<llvm::BitstreamCursor,
-                        serialization::ModuleFile *>, 8> CommentsCursors;
+  llvm::SmallVectorWithFlags<
+      std::pair<llvm::BitstreamCursor, serialization::ModuleFile *>, 8, 4>
+      CommentsCursors;
 
   /// Loads comments ranges.
   void ReadComments() override;
@@ -2672,7 +2712,7 @@ class ASTReader : public ExternalPreprocessorSource,
   void visitTopLevelModuleMaps(serialization::ModuleFile &MF,
                                llvm::function_ref<void(FileEntryRef)> Visitor);
 
-  bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
+  bool isProcessingUpdateRecords() { return getProcessingUpdateRecords(); }
 };
 
 /// A simple helper class to unpack an integer to bits and consuming
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 576eb86395929..8bf3d54839a29 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -32,6 +32,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitstream/BitstreamWriter.h"
 #include <cassert>
@@ -157,27 +158,45 @@ class ASTWriter : public ASTDeserializationListener,
   /// module file. This is the case for files implicitly written to the
   /// module cache, where we need the timestamps to determine if the module
   /// file is up to date, but not otherwise.
-  bool IncludeTimestamps;
+  bool getIncludeTimestamps() const {
+    return PendingEmittingVTables.getFlag(0);
+  }
+  void setIncludeTimestamps(bool Value) {
+    PendingEmittingVTables.setFlag(0, Value);
+  }
 
   /// Indicates whether the AST file being written is an implicit module.
   /// If that's the case, we may be able to skip writing some information that
   /// are guaranteed to be the same in the importer by the context hash.
-  bool BuildingImplicitModule = false;
+  bool getBuildingImplicitModule() const {
+    return PendingEmittingVTables.getFlag(1);
+  }
+  void setBuildingImplicitModule(bool Value) {
+    PendingEmittingVTables.setFlag(1, Value);
+  }
 
   /// Indicates when the AST writing is actively performing
   /// serialization, rather than just queueing updates.
-  bool WritingAST = false;
+  bool getWritingAST() const { return PendingEmittingVTables.getFlag(2); }
+  void setWritingAST(bool Value) { PendingEmittingVTables.setFlag(2, Value); }
 
   /// Indicates that we are done serializing the collection of decls
   /// and types to emit.
-  bool DoneWritingDeclsAndTypes = false;
+  bool getDoneWritingDeclsAndTypesFlag() const {
+    return PendingEmittingVTables.getFlag(3);
+  }
+  void setDoneWritingDeclsAndTypesFlag(bool Value) {
+    PendingEmittingVTables.setFlag(3, Value);
+  }
 
   /// Indicates that the AST contained compiler errors.
-  bool ASTHasCompilerErrors = false;
+  bool getASTHasCompilerErrors() const { return Redeclarations.getFlag(0); }
+  void setASTHasCompilerErrors(bool Value) { Redeclarations.setFlag(0, Value); }
 
   /// Indicates that we're going to generate the reduced BMI for C++20
   /// named modules.
-  bool GeneratingReducedBMI = false;
+  bool getGeneratingReducedBMI() const { return Redeclarations.getFlag(1); }
+  void setGeneratingReducedBMI(bool Value) { Redeclarations.setFlag(1, Value); }
 
   /// Mapping from input file entries to the index into the
   /// offset table where information about that input file is stored.
@@ -491,7 +510,7 @@ class ASTWriter : public ASTDeserializationListener,
 
   /// The set of declarations that may have redeclaration chains that
   /// need to be serialized.
-  llvm::SmallVector<const Decl *, 16> Redeclarations;
+  llvm::SmallVectorWithFlags<const Decl *, 16, 2> Redeclarations;
 
   /// A cache of the first local declaration for "interesting"
   /// redeclaration chains.
@@ -545,7 +564,11 @@ class ASTWriter : public ASTDeserializationListener,
 
   /// A list of classes in named modules which need to emit the VTable in
   /// the corresponding object file.
-  llvm::SmallVector<CXXRecordDecl *> PendingEmittingVTables;
+  llvm::SmallVectorWithFlags<
+      CXXRecordDecl *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<CXXRecordDecl *>::value,
+      4>
+      PendingEmittingVTables;
 
   /// Computes input files that didn't affect compilation of the current module,
   /// and initializes data structures necessary for leaving those files out
@@ -949,9 +972,11 @@ class ASTWriter : public ASTDeserializationListener,
     return WritingModule && WritingModule->isHeaderUnit();
   }
 
-  bool isGeneratingReducedBMI() const { return GeneratingReducedBMI; }
+  bool isGeneratingReducedBMI() const { return getGeneratingReducedBMI(); }
 
-  bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; }
+  bool getDoneWritingDeclsAndTypes() const {
+    return getDoneWritingDeclsAndTypesFlag();
+  }
 
   bool isDeclPredefined(const Decl *D) const {
     return PredefinedDecls.count(D);
@@ -1036,9 +1061,9 @@ class PCHGenerator : public SemaConsumer {
 protected:
   ASTWriter &getWriter() { return Writer; }
   const ASTWriter &getWriter() const { return Writer; }
-  SmallVectorImpl<char> &getPCH() const { return Buffer->Data; }
+  llvm::SmallVectorWithFlagsImpl<char> &getPCH() const { return Buffer->Data; }
 
-  bool isComplete() const { return Buffer->IsComplete; }
+  bool isComplete() const { return Buffer->getIsComplete(); }
   PCHBuffer *getBufferPtr() { return Buffer.get(); }
   StringRef getOutputFile() const { return OutputFile; }
   DiagnosticsEngine &getDiagnostics() const;
@@ -1061,7 +1086,7 @@ class PCHGenerator : public SemaConsumer {
   void HandleVTable(CXXRecordDecl *RD) override { Writer.handleVTable(RD); }
   ASTMutationListener *GetASTMutationListener() override;
   ASTDeserializationListener *GetASTDeserializationListener() override;
-  bool hasEmittedPCH() const { return Buffer->IsComplete; }
+  bool hasEmittedPCH() const { return Buffer->getIsComplete(); }
 };
 
 class CXX20ModulesGenerator : public PCHGenerator {
diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h
index c6353d31d4e54..b903ed6eb7f80 100644
--- a/clang/include/clang/Serialization/ModuleFile.h
+++ b/clang/include/clang/Serialization/ModuleFile.h
@@ -26,6 +26,7 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitstream/BitstreamReader.h"
 #include "llvm/Support/Endian.h"
@@ -208,16 +209,24 @@ class ModuleFile {
   std::vector<std::string> DirectoryDependencies;
 
   /// Whether this precompiled header is a relocatable PCH file.
-  bool RelocatablePCH = false;
+  bool getRelocatablePCH() const { return TransitiveImports.getFlag(0); }
+  void setRelocatablePCH(bool Value) { TransitiveImports.setFlag(0, Value); }
 
   /// Whether this module file is a standard C++ module.
-  bool StandardCXXModule = false;
+  bool getStandardCXXModule() const { return TransitiveImports.getFlag(1); }
+  void setStandardCXXModule(bool Value) { TransitiveImports.setFlag(1, Value); }
 
   /// Whether timestamps are included in this module file.
-  bool HasTimestamps = false;
+  bool getHasTimestamps() const { return TransitiveImports.getFlag(2); }
+  void setHasTimestamps(bool Value) { TransitiveImports.setFlag(2, Value); }
 
   /// Whether the top-level module has been read from the AST file.
-  bool DidReadTopLevelSubmodule = false;
+  bool getDidReadTopLevelSubmodule() const {
+    return TransitiveImports.getFlag(3);
+  }
+  void setDidReadTopLevelSubmodule(bool Value) {
+    TransitiveImports.setFlag(3, Value);
+  }
 
   /// Size of the module file.
   off_t Size = 0;
@@ -563,7 +572,7 @@ class ModuleFile {
   /// the same order with that module file manager when we write
   /// the current module file. The value of the member will be initialized
   /// in `ASTReader::ReadModuleOffsetMap`.
-  llvm::SmallVector<ModuleFile *, 16> TransitiveImports;
+  llvm::SmallVectorWithFlags<ModuleFile *, 16, 4> TransitiveImports;
 
   /// Determine whether this module was directly imported at
   /// any point during translation.
diff --git a/clang/include/clang/Serialization/PCHContainerOperations.h b/clang/include/clang/Serialization/PCHContainerOperations.h
index c9a7e334ce6eb..3870a283cb9bb 100644
--- a/clang/include/clang/Serialization/PCHContainerOperations.h
+++ b/clang/include/clang/Serialization/PCHContainerOperations.h
@@ -11,6 +11,7 @@
 
 #include "clang/Basic/Module.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include <memory>
@@ -26,8 +27,9 @@ class CompilerInstance;
 
 struct PCHBuffer {
   ASTFileSignature Signature;
-  llvm::SmallVector<char, 0> Data;
-  bool IsComplete;
+  llvm::SmallVectorWithFlags<char, 0> Data;
+  bool getIsComplete() const { return Data.getFlag(0); }
+  void setIsComplete(bool Value) { Data.setFlag(0, Value); }
 };
 
 /// This abstract interface provides operations for creating
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 51c54151ac07b..17f17c6b0a4e9 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -31,6 +31,7 @@
 #include "llvm/ADT/ImmutableSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -329,7 +330,7 @@ class PathSensitiveBugReport : public BugReport {
 
   /// A set of custom visitors which generate "event" diagnostics at
   /// interesting points in the path.
-  VisitorList Callbacks;
+  llvm::SmallVectorWithFlagsFor<VisitorList, 1> Callbacks;
 
   /// Used for ensuring the visitors are only added once.
   llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
@@ -337,7 +338,8 @@ class PathSensitiveBugReport : public BugReport {
   /// When set, this flag disables all callstack pruning from a diagnostic
   /// path.  This is useful for some reports that want maximum fidelty
   /// when reporting an issue.
-  bool DoNotPrunePath = false;
+  bool getDoNotPrunePath() const { return Callbacks.getFlag(0); }
+  void setDoNotPrunePath(bool Value) { Callbacks.setFlag(0, Value); }
 
   /// Used to track unique reasons why a bug report might be invalid.
   ///
@@ -408,10 +410,10 @@ class PathSensitiveBugReport : public BugReport {
 
   /// Indicates whether or not any path pruning should take place
   /// when generating a PathDiagnostic from this BugReport.
-  bool shouldPrunePath() const { return !DoNotPrunePath; }
+  bool shouldPrunePath() const { return !getDoNotPrunePath(); }
 
   /// Disable all path pruning when generating a PathDiagnostic.
-  void disablePathPruning() { DoNotPrunePath = true; }
+  void disablePathPruning() { setDoNotPrunePath(true); }
 
   /// Get the location on which the report should be uniqued.
   PathDiagnosticLocation getUniqueingLocation() const override {
diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 46e648c6b7d90..4ee0a415cb82c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include <vector>
 
@@ -613,7 +614,7 @@ class CheckerManager {
   template <typename EVENT>
   void _registerDispatcherForEvent() {
     EventInfo &info = Events[&EVENT::Tag];
-    info.HasDispatcher = true;
+    info.setHasDispatcher(true);
   }
 
   template <typename EVENT>
@@ -706,8 +707,9 @@ class CheckerManager {
   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
 
   struct EventInfo {
-    SmallVector<CheckEventFunc, 4> Checkers;
-    bool HasDispatcher = false;
+    llvm::SmallVectorWithFlags<CheckEventFunc, 4> Checkers;
+    bool getHasDispatcher() const { return Checkers.getFlag(0); }
+    void setHasDispatcher(bool Value) { Checkers.setFlag(0, Value); }
 
     EventInfo() = default;
   };
diff --git a/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h b/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
index 84b1d19e52c8a..ca1b586b311cd 100644
--- a/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ b/clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -13,6 +13,7 @@
 #include "clang/Tooling/Inclusions/IncludeStyle.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Regex.h"
 #include <list>
@@ -43,9 +44,10 @@ class IncludeCategoryManager {
   bool isMainHeader(StringRef IncludeName) const;
 
   const IncludeStyle Style;
-  bool IsMainFile;
+  bool getIsMainFile() const { return CategoryRegexs.getFlag(0); }
+  void setIsMainFile(bool Value) { CategoryRegexs.setFlag(0, Value); }
   std::string FileName;
-  SmallVector<llvm::Regex, 4> CategoryRegexs;
+  llvm::SmallVectorWithFlags<llvm::Regex, 4> CategoryRegexs;
 };
 
 enum class IncludeDirective { Include, Import };
diff --git a/clang/include/clang/Tooling/Refactoring/ASTSelection.h b/clang/include/clang/Tooling/Refactoring/ASTSelection.h
index ae778acb5e017..e38cba8cd2acb 100644
--- a/clang/include/clang/Tooling/Refactoring/ASTSelection.h
+++ b/clang/include/clang/Tooling/Refactoring/ASTSelection.h
@@ -13,6 +13,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/raw_ostream.h"
 #include <optional>
 #include <vector>
@@ -103,13 +104,13 @@ class CodeRangeASTSelection {
 
   /// Returns the number of selected statements.
   size_t size() const {
-    if (!AreChildrenSelected)
+    if (!getAreChildrenSelected())
       return 1;
     return SelectedNode.get().Children.size();
   }
 
   const Stmt *operator[](size_t I) const {
-    if (!AreChildrenSelected) {
+    if (!getAreChildrenSelected()) {
       assert(I == 0 && "Invalid index");
       return SelectedNode.get().Node.get<Stmt>();
     }
@@ -138,16 +139,18 @@ class CodeRangeASTSelection {
   CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode,
                         ArrayRef<SelectedASTNode::ReferenceType> Parents,
                         bool AreChildrenSelected)
-      : SelectedNode(SelectedNode), Parents(Parents),
-        AreChildrenSelected(AreChildrenSelected) {}
+      : SelectedNode(SelectedNode),
+        Parents(decltype(this->Parents)::withFlags(
+            unsigned(AreChildrenSelected), Parents)) {}
 
   /// The reference to the selected node (or reference to the selected
   /// child nodes).
   SelectedASTNode::ReferenceType SelectedNode;
   /// The parent hierarchy (top to bottom) for the selected noe.
-  llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
+  llvm::SmallVectorWithFlags<SelectedASTNode::ReferenceType, 8> Parents;
   /// True only when the children of the selected node are actually selected.
-  bool AreChildrenSelected;
+  bool getAreChildrenSelected() const { return Parents.getFlag(0); }
+  void setAreChildrenSelected(bool Value) { Parents.setFlag(0, Value); }
 };
 
 } // end namespace tooling
diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp
index 5c1bb41d804e9..0009e88b4b678 100644
--- a/clang/lib/APINotes/APINotesManager.cpp
+++ b/clang/lib/APINotes/APINotesManager.cpp
@@ -210,7 +210,7 @@ static void checkPrivateAPINotesName(DiagnosticsEngine &Diags,
     return;
 
   unsigned DiagID = diag::warn_apinotes_private_case;
-  if (M->IsSystem)
+  if (M->getIsSystem())
     DiagID = diag::warn_apinotes_private_case_system;
 
   Diags.Report(SourceLocation(), DiagID) << M->Name << RealFileName;
@@ -220,7 +220,7 @@ static void checkPrivateAPINotesName(DiagnosticsEngine &Diags,
 /// private module map
 static bool hasPrivateSubmodules(const Module *M) {
   return llvm::any_of(M->submodules(), [](const Module *Submodule) {
-    return Submodule->ModuleMapIsPrivate;
+    return Submodule->getModuleMapIsPrivate();
   });
 }
 
@@ -248,7 +248,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
           APINotes.push_back(*File);
     };
 
-    if (M->IsFramework) {
+    if (M->getIsFramework()) {
       // For frameworks, we search in the "Headers" or "PrivateHeaders"
       // subdirectory.
       //
@@ -260,7 +260,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
       //   the word "Private" in it in practice)
       llvm::SmallString<128> Path(M->Directory->getName());
 
-      if (!M->ModuleMapIsPrivate) {
+      if (!M->getModuleMapIsPrivate()) {
         unsigned PathLen = Path.size();
 
         llvm::sys::path::append(Path, "Headers");
@@ -270,11 +270,11 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
         Path.resize(PathLen);
       }
 
-      if (M->ModuleMapIsPrivate || hasPrivateSubmodules(M)) {
+      if (M->getModuleMapIsPrivate() || hasPrivateSubmodules(M)) {
         llvm::sys::path::append(Path, "PrivateHeaders");
         if (auto PrivateAPINotesDir = FM.getOptionalDirectoryRef(Path))
           tryAPINotes(*PrivateAPINotesDir,
-                      /*wantPublic=*/M->ModuleMapIsPrivate);
+                      /*wantPublic=*/M->getModuleMapIsPrivate());
       }
     } else {
       // Public modules:
@@ -284,7 +284,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
       // - Bar.apinotes (except that 'Bar' probably already has the word
       //   "Private" in it in practice)
       tryAPINotes(*M->Directory, /*wantPublic=*/true);
-      if (!M->ModuleMapIsPrivate && hasPrivateSubmodules(M))
+      if (!M->getModuleMapIsPrivate() && hasPrivateSubmodules(M))
         tryAPINotes(*M->Directory, /*wantPublic=*/false);
     }
 
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index 2b04821a157da..362d6f51f16cb 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -44,8 +44,8 @@ CreateUnsatisfiedConstraintRecord(const ASTContext &C,
 ASTConstraintSatisfaction::ASTConstraintSatisfaction(
     const ASTContext &C, const ConstraintSatisfaction &Satisfaction)
     : NumRecords{Satisfaction.Details.size()},
-      IsSatisfied{Satisfaction.IsSatisfied}, ContainsErrors{
-                                                 Satisfaction.ContainsErrors} {
+      IsSatisfied{Satisfaction.isSatisfied()},
+      ContainsErrors{Satisfaction.containsErrors()} {
   for (unsigned I = 0; I < NumRecords; ++I)
     CreateUnsatisfiedConstraintRecord(C, Satisfaction.Details[I],
                                       getTrailingObjects() + I);
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index ed22919b7a70b..9954f1f7a6a09 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -333,9 +333,9 @@ RawComment *ASTContext::getRawCommentNoCache(RawCommentLookupKey Key) const {
     if (Loc.isInvalid() || !Loc.isFileID())
       continue;
 
-    if (ExternalSource && !CommentsLoaded) {
+    if (ExternalSource && !getCommentsLoaded()) {
       ExternalSource->ReadComments();
-      CommentsLoaded = true;
+      setCommentsLoaded(true);
     }
 
     if (Comments.empty())
@@ -1281,7 +1281,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
   this->AuxTarget = AuxTarget;
 
   ABI.reset(createCXXABI(Target));
-  AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts);
+  setAddrSpaceMapMangling(isAddrSpaceMapManglingEnabled(Target, LangOpts));
 
   // C99 6.2.5p19.
   InitBuiltinType(VoidTy,              BuiltinType::Void);
@@ -5277,7 +5277,7 @@ QualType ASTContext::getFunctionTypeInternal(
   if (!Unique)
     FunctionProtoTypes.insert(FTP, Token);
   if (!EPI.FunctionEffects.empty())
-    AnyFunctionEffects = true;
+    setAnyFunctionEffects(true);
   return QualType(FTP, 0);
 }
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 4c296b6829b1b..b3fbf25efb345 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1076,9 +1076,9 @@ StringRef ASTNodeImporter::ImportASTStringRef(StringRef FromStr) {
 
 Error ASTNodeImporter::ImportConstraintSatisfaction(
     const ASTConstraintSatisfaction &FromSat, ConstraintSatisfaction &ToSat) {
-  ToSat.IsSatisfied = FromSat.IsSatisfied;
-  ToSat.ContainsErrors = FromSat.ContainsErrors;
-  if (!ToSat.IsSatisfied) {
+  ToSat.setIsSatisfied(FromSat.IsSatisfied);
+  ToSat.setContainsErrors(FromSat.ContainsErrors);
+  if (!ToSat.isSatisfied()) {
     for (auto Record = FromSat.begin(); Record != FromSat.end(); ++Record) {
       if (const Expr *E = dyn_cast<const Expr *>(*Record)) {
         ExpectedExpr ToSecondExpr = import(E);
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp
index 7272ad0de9a2c..ce43f611d5e39 100644
--- a/clang/lib/AST/AttrImpl.cpp
+++ b/clang/lib/AST/AttrImpl.cpp
@@ -241,7 +241,7 @@ void OMPDeclareVariantAttr::printPrettyPragma(
       OS << "interop(";
       if (!I->Prefs.empty()) {
         OS << "prefer_type(";
-        if (I->HasPreferAttrs) {
+        if (I->hasPreferAttrs()) {
           StringRef Sep = "";
           for (const auto &P : I->Prefs) {
             OS << Sep << "{";
diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp
index cd9152745826f..6059723a09746 100644
--- a/clang/lib/AST/Availability.cpp
+++ b/clang/lib/AST/Availability.cpp
@@ -15,13 +15,24 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace {
 
 /// Represents the availability of a symbol across platforms.
 struct AvailabilitySet {
-  bool UnconditionallyDeprecated = false;
-  bool UnconditionallyUnavailable = false;
+  bool getUnconditionallyDeprecated() const {
+    return Availabilities.getFlag(0);
+  }
+  void setUnconditionallyDeprecated(bool Value) {
+    Availabilities.setFlag(0, Value);
+  }
+  bool getUnconditionallyUnavailable() const {
+    return Availabilities.getFlag(1);
+  }
+  void setUnconditionallyUnavailable(bool Value) {
+    Availabilities.setFlag(1, Value);
+  }
 
   void insert(clang::AvailabilityInfo &&Availability) {
     auto *Found = getForPlatform(Availability.Domain);
@@ -40,7 +51,11 @@ struct AvailabilitySet {
   }
 
 private:
-  llvm::SmallVector<clang::AvailabilityInfo> Availabilities;
+  llvm::SmallVectorWithFlags<clang::AvailabilityInfo,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 clang::AvailabilityInfo>::value,
+                             2>
+      Availabilities;
 };
 
 static void createInfoForDecl(const clang::Decl *Decl,
@@ -57,11 +72,11 @@ static void createInfoForDecl(const clang::Decl *Decl,
 
     if (const auto *A = RD->getAttr<clang::UnavailableAttr>())
       if (!A->isImplicit())
-        Availabilities.UnconditionallyUnavailable = true;
+        Availabilities.setUnconditionallyUnavailable(true);
 
     if (const auto *A = RD->getAttr<clang::DeprecatedAttr>())
       if (!A->isImplicit())
-        Availabilities.UnconditionallyDeprecated = true;
+        Availabilities.setUnconditionallyDeprecated(true);
   }
 }
 
@@ -106,15 +121,18 @@ AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *D) {
 
   if (auto *Avail = Availabilities.getForPlatform(
           D->getASTContext().getTargetInfo().getPlatformName())) {
-    Avail->UnconditionallyDeprecated = Availabilities.UnconditionallyDeprecated;
+    Avail->UnconditionallyDeprecated =
+        Availabilities.getUnconditionallyDeprecated();
     Avail->UnconditionallyUnavailable =
-        Availabilities.UnconditionallyUnavailable;
+        Availabilities.getUnconditionallyUnavailable();
     return std::move(*Avail);
   }
 
   AvailabilityInfo Avail;
-  Avail.UnconditionallyDeprecated = Availabilities.UnconditionallyDeprecated;
-  Avail.UnconditionallyUnavailable = Availabilities.UnconditionallyUnavailable;
+  Avail.UnconditionallyDeprecated =
+      Availabilities.getUnconditionallyDeprecated();
+  Avail.UnconditionallyUnavailable =
+      Availabilities.getUnconditionallyUnavailable();
   return Avail;
 }
 
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index b57ace795fa77..0a498daa8365b 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -27,6 +27,7 @@
 #include "clang/AST/ASTDumperUtils.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/FormatVariadic.h"
 
@@ -164,9 +165,14 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
   struct OpText {
     size_t Addr;
     std::string Op;
-    bool IsJump;
-    bool CurrentOp = false;
-    llvm::SmallVector<std::string> Args;
+    bool getIsJump() const { return Args.getFlag(0); }
+    void setIsJump(bool Value) { Args.setFlag(0, Value); }
+    bool getCurrentOp() const { return Args.getFlag(1); }
+    void setCurrentOp(bool Value) { Args.setFlag(1, Value); }
+    llvm::SmallVectorWithFlags<
+        std::string,
+        llvm::CalculateSmallVectorDefaultInlinedElements<std::string>::value, 2>
+        Args;
   };
 
   auto PrintName = [](const char *Name) -> std::string {
@@ -182,8 +188,8 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
     OpText Text;
     auto Op = PC.read<Opcode>();
     Text.Addr = Addr;
-    Text.IsJump = isJumpOpcode(Op);
-    Text.CurrentOp = (PC == OpPC);
+    Text.setIsJump(isJumpOpcode(Op));
+    Text.setCurrentOp((PC == OpPC));
     switch (Op) {
 #define GET_DISASM
 #include "Opcodes.inc"
@@ -201,7 +207,7 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
   };
   llvm::SmallVector<JmpData> Jumps;
   for (auto &Text : Code) {
-    if (Text.IsJump)
+    if (Text.getIsJump())
       Jumps.push_back({Text.Addr, Text.Addr + std::stoi(Text.Args[0]) +
                                       align(sizeof(Opcode)) +
                                       align(sizeof(int32_t))});
@@ -215,7 +221,7 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
     std::string Line;
     llvm::raw_string_ostream LS(Line);
     if (OpPC) {
-      if (C.CurrentOp)
+      if (C.getCurrentOp())
         LS << " * ";
       else
         LS << "   ";
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 73f2d415cf56e..96f13308d5160 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3721,7 +3721,7 @@ inline bool PushIgnoreDiags(InterpState &S) {
     return true;
   assert(S.PrevDiags == nullptr);
   S.PrevDiags = S.getEvalStatus().Diag;
-  S.PrevDiagsEmitted = S.getEvalStatus().DiagEmitted;
+  S.setPrevDiagsEmitted(S.getEvalStatus().DiagEmitted);
   S.getEvalStatus().Diag = nullptr;
   assert(!S.diagnosing());
   return true;
@@ -3732,7 +3732,7 @@ inline bool PopIgnoreDiags(InterpState &S) {
   --S.DiagIgnoreDepth;
   if (S.DiagIgnoreDepth == 0) {
     S.getEvalStatus().Diag = S.PrevDiags;
-    S.getEvalStatus().DiagEmitted = S.PrevDiagsEmitted;
+    S.getEvalStatus().DiagEmitted = S.getPrevDiagsEmitted();
     S.PrevDiags = nullptr;
   }
   return true;
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index 44f6fb3216b77..18a865fa14079 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -25,7 +25,9 @@ InterpState::InterpState(const EvalSettings &Settings, Program &P,
     : State(Ctx.getASTContext(), Settings.EvalStatus), M(M),
       FrameAlloc(FrameAlloc), P(P), Stk(Stk), Ctx(Ctx), BottomFrame(*this),
       Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
-      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
+      EvalID(Ctx.getEvalID()),
+      InitializingPtrs(decltype(this->InitializingPtrs)::withFlags(
+          unsigned(bool(StepsLeft == 0)))) {
   InConstantContext = Settings.InConstantContext;
   CheckingPotentialConstantExpression =
       Settings.CheckingPotentialConstantExpression;
@@ -39,7 +41,9 @@ InterpState::InterpState(const EvalSettings &Settings, Program &P,
     : State(Ctx.getASTContext(), Settings.EvalStatus), M(nullptr),
       FrameAlloc(FrameAlloc), P(P), Stk(Stk), Ctx(Ctx), BottomFrame(*this),
       Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
-      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
+      EvalID(Ctx.getEvalID()),
+      InitializingPtrs(decltype(this->InitializingPtrs)::withFlags(
+          unsigned(bool(StepsLeft == 0)))) {
   InConstantContext = Settings.InConstantContext;
   CheckingPotentialConstantExpression =
       Settings.CheckingPotentialConstantExpression;
@@ -52,8 +56,9 @@ InterpState::InterpState(Expr::EvalStatus &Status, Program &P, InterpStack &Stk,
                          SourceMapper *M)
     : State(Ctx.getASTContext(), Status), M(M), FrameAlloc(FrameAlloc), P(P),
       Stk(Stk), Ctx(Ctx), BottomFrame(*this), Current(&BottomFrame),
-      StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
-      InfiniteSteps(StepsLeft == 0), EvalID(Ctx.getEvalID()) {
+      StepsLeft(Ctx.getLangOpts().ConstexprStepLimit), EvalID(Ctx.getEvalID()),
+      InitializingPtrs(decltype(this->InitializingPtrs)::withFlags(
+          unsigned(bool(StepsLeft == 0)))) {
   InConstantContext = true;
   CheckingPotentialConstantExpression = false;
   CheckingForUndefinedBehavior = true;
diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h
index eb290584285db..4bd6325292afe 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -21,6 +21,7 @@
 #include "InterpFrame.h"
 #include "InterpStack.h"
 #include "State.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <limits>
 
 namespace clang {
@@ -157,7 +158,7 @@ class InterpState final : public State {
   /// Note that a step has been executed. If there are no more steps remaining,
   /// diagnoses and returns \c false.
   bool noteStep(CodePtr OpPC) {
-    if (InfiniteSteps)
+    if (getInfiniteSteps())
       return true;
 
     --StepsLeft;
@@ -259,7 +260,7 @@ class InterpState final : public State {
   unsigned StepsLeft = 1;
   /// Whether infinite evaluation steps have been requested. If this is false,
   /// we use the StepsLeft value above.
-  const bool InfiniteSteps = false;
+  bool getInfiniteSteps() const { return InitializingPtrs.getFlag(0); }
   /// ID identifying this evaluation.
   const unsigned EvalID;
 
@@ -269,7 +270,8 @@ class InterpState final : public State {
 
   /// Things needed to do speculative execution.
   SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;
-  bool PrevDiagsEmitted = false;
+  bool getPrevDiagsEmitted() const { return InitializingPtrs.getFlag(1); }
+  void setPrevDiagsEmitted(bool Value) { InitializingPtrs.setFlag(1, Value); }
 #ifndef NDEBUG
   unsigned SpeculationDepth = 0;
 #endif
@@ -282,7 +284,10 @@ class InterpState final : public State {
 
   /// List of blocks we're currently running either constructors or destructors
   /// for.
-  llvm::SmallVector<PtrView> InitializingPtrs;
+  llvm::SmallVectorWithFlags<
+      PtrView, llvm::CalculateSmallVectorDefaultInlinedElements<PtrView>::value,
+      2>
+      InitializingPtrs;
 };
 
 class InterpStateCCOverride final {
diff --git a/clang/lib/AST/CommentParser.cpp b/clang/lib/AST/CommentParser.cpp
index 87f8c870919d1..eaca0156b8dfb 100644
--- a/clang/lib/AST/CommentParser.cpp
+++ b/clang/lib/AST/CommentParser.cpp
@@ -13,6 +13,7 @@
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/DiagnosticComment.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/ErrorHandling.h"
 
 namespace clang {
@@ -33,10 +34,11 @@ class TextTokenRetokenizer {
   Parser &P;
 
   /// This flag is set when there are no more tokens we can fetch from lexer.
-  bool NoMoreInterestingTokens;
+  bool getNoMoreInterestingTokens() const { return Toks.getFlag(0); }
+  void setNoMoreInterestingTokens(bool Value) { Toks.setFlag(0, Value); }
 
   /// Token buffer: tokens we have processed and lookahead.
-  SmallVector<Token, 16> Toks;
+  llvm::SmallVectorWithFlags<Token, 16> Toks;
 
   /// A position in \c Toks.
   struct Position {
@@ -119,7 +121,7 @@ class TextTokenRetokenizer {
   /// Returns true on success, false if there are no interesting tokens to
   /// fetch from lexer.
   bool addToken() {
-    if (NoMoreInterestingTokens)
+    if (getNoMoreInterestingTokens())
       return false;
 
     if (P.Tok.is(tok::newline)) {
@@ -128,12 +130,12 @@ class TextTokenRetokenizer {
       P.consumeToken();
       if (P.Tok.isNot(tok::text)) {
         P.putBack(Newline);
-        NoMoreInterestingTokens = true;
+        setNoMoreInterestingTokens(true);
         return false;
       }
     }
     if (P.Tok.isNot(tok::text)) {
-      NoMoreInterestingTokens = true;
+      setNoMoreInterestingTokens(true);
       return false;
     }
 
@@ -169,8 +171,8 @@ class TextTokenRetokenizer {
   }
 
 public:
-  TextTokenRetokenizer(llvm::BumpPtrAllocator &Allocator, Parser &P):
-      Allocator(Allocator), P(P), NoMoreInterestingTokens(false) {
+  TextTokenRetokenizer(llvm::BumpPtrAllocator &Allocator, Parser &P)
+      : Allocator(Allocator), P(P) {
     Pos.CurToken = 0;
     addToken();
   }
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6d390032e2c71..dbfcb0b7357b3 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -61,6 +61,7 @@
 #include "llvm/ADT/APFixedPoint.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/Support/CRC.h"
@@ -512,7 +513,7 @@ namespace {
     unsigned Index;
 
     /// The stack of integers for tracking version numbers for temporaries.
-    SmallVector<unsigned, 2> TempVersionStack = {1};
+    llvm::SmallVectorWithFlags<unsigned, 2> TempVersionStack = {1};
     unsigned CurTempVersion = TempVersionStack.back();
 
     unsigned getTempVersion() const { return TempVersionStack.back(); }
@@ -596,7 +597,10 @@ namespace {
 
     /// Whether we're in a context where [[msvc::constexpr]] evaluation is
     /// permitted. See MSConstexprDocs for description of permitted contexts.
-    bool CanEvalMSConstexpr = false;
+    bool getCanEvalMSConstexpr() const { return TempVersionStack.getFlag(0); }
+    void setCanEvalMSConstexpr(bool Value) {
+      TempVersionStack.setFlag(0, Value);
+    }
 
   private:
     APValue &createLocal(APValue::LValueBase Base, const void *Key, QualType T,
@@ -638,11 +642,11 @@ namespace {
     CallStackFrame &Frame;
     bool OldValue;
     explicit MSConstexprContextRAII(CallStackFrame &Frame, bool Value)
-        : Frame(Frame), OldValue(Frame.CanEvalMSConstexpr) {
-      Frame.CanEvalMSConstexpr = Value;
+        : Frame(Frame), OldValue(Frame.getCanEvalMSConstexpr()) {
+      Frame.setCanEvalMSConstexpr(Value);
     }
 
-    ~MSConstexprContextRAII() { Frame.CanEvalMSConstexpr = OldValue; }
+    ~MSConstexprContextRAII() { Frame.setCanEvalMSConstexpr(OldValue); }
   };
 }
 
@@ -6591,8 +6595,9 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
 
   // Can we evaluate this function call?
   if (Definition && Body &&
-      (Definition->isConstexpr() || (Info.CurrentCall->CanEvalMSConstexpr &&
-                                        Definition->hasAttr<MSConstexprAttr>())))
+      (Definition->isConstexpr() ||
+       (Info.CurrentCall->getCanEvalMSConstexpr() &&
+        Definition->hasAttr<MSConstexprAttr>())))
     return true;
 
   const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
@@ -7982,17 +7987,18 @@ class BitCastBuffer {
   // FIXME: Its possible under the C++ standard for 'char' to not be 8 bits, but
   // we don't support a host or target where that is the case. Still, we should
   // use a more generic type in case we ever do.
-  SmallVector<std::optional<unsigned char>, 32> Bytes;
+  llvm::SmallVectorWithFlags<std::optional<unsigned char>, 32> Bytes;
 
   static_assert(std::numeric_limits<unsigned char>::digits >= 8,
                 "Need at least 8 bit unsigned char");
 
-  bool TargetIsLittleEndian;
+  bool getTargetIsLittleEndian() const { return Bytes.getFlag(0); }
+  void setTargetIsLittleEndian(bool Value) { Bytes.setFlag(0, Value); }
 
 public:
   BitCastBuffer(CharUnits Width, bool TargetIsLittleEndian)
-      : Bytes(Width.getQuantity()),
-        TargetIsLittleEndian(TargetIsLittleEndian) {}
+      : Bytes(decltype(this->Bytes)::withFlags(unsigned(TargetIsLittleEndian),
+                                               Width.getQuantity())) {}
 
   [[nodiscard]] bool readObject(CharUnits Offset, CharUnits Width,
                                 SmallVectorImpl<unsigned char> &Output) const {
@@ -8003,13 +8009,13 @@ class BitCastBuffer {
         return false;
       Output.push_back(*Bytes[I.getQuantity()]);
     }
-    if (llvm::sys::IsLittleEndianHost != TargetIsLittleEndian)
+    if (llvm::sys::IsLittleEndianHost != getTargetIsLittleEndian())
       std::reverse(Output.begin(), Output.end());
     return true;
   }
 
   void writeObject(CharUnits Offset, SmallVectorImpl<unsigned char> &Input) {
-    if (llvm::sys::IsLittleEndianHost != TargetIsLittleEndian)
+    if (llvm::sys::IsLittleEndianHost != getTargetIsLittleEndian())
       std::reverse(Input.begin(), Input.end());
 
     size_t Index = 0;
@@ -11113,7 +11119,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
 
   if (OperatorNew->isReservedGlobalPlacementOperator()) {
     if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26 ||
-        (Info.CurrentCall->CanEvalMSConstexpr &&
+        (Info.CurrentCall->getCanEvalMSConstexpr() &&
          OperatorNew->hasAttr<MSConstexprAttr>())) {
       if (!EvaluatePointer(E->getPlacementArg(0), Result, Info))
         return false;
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 74edee531e48a..59ffd4f9a23bf 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -31,6 +31,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CRC.h"
 #include "llvm/Support/MD5.h"
@@ -316,7 +317,7 @@ class MicrosoftCXXNameMangler {
   unsigned StructorType;
 
   typedef llvm::SmallVector<std::string, 10> BackRefVec;
-  BackRefVec NameBackReferences;
+  llvm::SmallVectorWithFlagsFor<BackRefVec, 1> NameBackReferences;
 
   typedef llvm::DenseMap<const void *, unsigned> ArgBackRefMap;
   ArgBackRefMap FunArgBackReferences;
@@ -332,7 +333,7 @@ class MicrosoftCXXNameMangler {
 
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
-  const bool PointersAre64Bit;
+  bool getPointersAre64Bit() const { return NameBackReferences.getFlag(0); }
 
   DiagnosticBuilder Error(SourceLocation, StringRef, StringRef);
   DiagnosticBuilder Error(SourceLocation, StringRef);
@@ -344,23 +345,26 @@ class MicrosoftCXXNameMangler {
 
   MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
       : Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
-        TemplateArgStringStorage(TemplateArgStringStorageAlloc),
-        PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(
-                             LangAS::Default) == 64) {}
+        NameBackReferences(decltype(this->NameBackReferences)::withFlags(
+            unsigned(bool(C.getASTContext().getTargetInfo().getPointerWidth(
+                              LangAS::Default) == 64)))),
+        TemplateArgStringStorage(TemplateArgStringStorageAlloc) {}
 
   MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
                           const CXXConstructorDecl *D, CXXCtorType Type)
       : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-        TemplateArgStringStorage(TemplateArgStringStorageAlloc),
-        PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(
-                             LangAS::Default) == 64) {}
+        NameBackReferences(decltype(this->NameBackReferences)::withFlags(
+            unsigned(bool(C.getASTContext().getTargetInfo().getPointerWidth(
+                              LangAS::Default) == 64)))),
+        TemplateArgStringStorage(TemplateArgStringStorageAlloc) {}
 
   MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
                           const CXXDestructorDecl *D, CXXDtorType Type)
       : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-        TemplateArgStringStorage(TemplateArgStringStorageAlloc),
-        PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(
-                             LangAS::Default) == 64) {}
+        NameBackReferences(decltype(this->NameBackReferences)::withFlags(
+            unsigned(bool(C.getASTContext().getTargetInfo().getPointerWidth(
+                              LangAS::Default) == 64)))),
+        TemplateArgStringStorage(TemplateArgStringStorageAlloc) {}
 
   raw_ostream &getStream() const { return Out; }
 
@@ -415,8 +419,8 @@ class MicrosoftCXXNameMangler {
   bool is64BitPointer(Qualifiers Quals) const {
     LangAS AddrSpace = Quals.getAddressSpace();
     return AddrSpace == LangAS::ptr64 ||
-           (PointersAre64Bit && !(AddrSpace == LangAS::ptr32_sptr ||
-                                  AddrSpace == LangAS::ptr32_uptr));
+           (getPointersAre64Bit() && !(AddrSpace == LangAS::ptr32_sptr ||
+                                       AddrSpace == LangAS::ptr32_uptr));
   }
 
   void mangleUnqualifiedName(GlobalDecl GD) {
@@ -1443,7 +1447,7 @@ void MicrosoftCXXNameMangler::mangleNestedName(GlobalDecl GD) {
       // struct __block_literal *
       Out << 'P';
       // __ptr64
-      if (PointersAre64Bit)
+      if (getPointersAre64Bit())
         Out << 'E';
       Out << 'A';
       mangleArtificialTagType(TagTypeKind::Struct,
@@ -1658,7 +1662,8 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
   // Templates have their own context for back references.
   ArgBackRefMap OuterFunArgsContext;
   ArgBackRefMap OuterTemplateArgsContext;
-  BackRefVec OuterTemplateContext;
+  auto OuterTemplateContext =
+      decltype(NameBackReferences)::withFlags(NameBackReferences.getFlags());
   PassObjectSizeArgsSet OuterPassObjectSizeArgs;
   NameBackReferences.swap(OuterTemplateContext);
   FunArgBackReferences.swap(OuterFunArgsContext);
@@ -2338,8 +2343,9 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
 void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
                                                          QualType PointeeType) {
   // Check if this is a default 64-bit pointer or has __ptr64 qualifier.
-  bool is64Bit = PointeeType.isNull() ? PointersAre64Bit :
-      is64BitPointer(PointeeType.getQualifiers());
+  bool is64Bit = PointeeType.isNull()
+                     ? getPointersAre64Bit()
+                     : is64BitPointer(PointeeType.getQualifiers());
   if (is64Bit && (PointeeType.isNull() || !PointeeType->isFunctionType()))
     Out << 'E';
 
@@ -3156,7 +3162,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
       // extra argument is not reflected in the AST.
       if (StructorType == Dtor_Deleting ||
           StructorType == Dtor_VectorDeleting) {
-        Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
+        Out << (getPointersAre64Bit() ? "PEAXI at Z" : "PAXI at Z");
         return;
       }
       // The vbase destructor returns void which is not reflected in the AST.
@@ -3837,7 +3843,8 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
 
   ArgBackRefMap OuterFunArgsContext;
   ArgBackRefMap OuterTemplateArgsContext;
-  BackRefVec OuterTemplateContext;
+  auto OuterTemplateContext =
+      decltype(NameBackReferences)::withFlags(NameBackReferences.getFlags());
 
   FunArgBackReferences.swap(OuterFunArgsContext);
   TemplateArgBackReferences.swap(OuterTemplateArgsContext);
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 5e338c960878b..5308bc51efd83 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1732,11 +1732,11 @@ OMPInitClause *OMPInitClause::Create(const ASTContext &C, Expr *InteropVar,
   // Trailing layout: Expr*[1 + NumPrefs + NumAttrs], unsigned[NumPrefs].
   void *Mem = C.Allocate(
       totalSizeToAlloc<Expr *, unsigned>(1 + NumPrefs + NumAttrs, NumPrefs));
-  auto *Clause = new (Mem)
-      OMPInitClause(InteropInfo.IsTarget, InteropInfo.IsTargetSync, StartLoc,
-                    LParenLoc, VarLoc, EndLoc, /*VarListN=*/1 + NumPrefs);
+  auto *Clause = new (Mem) OMPInitClause(
+      InteropInfo.isTarget(), InteropInfo.isTargetSync(), StartLoc, LParenLoc,
+      VarLoc, EndLoc, /*VarListN=*/1 + NumPrefs);
   Clause->NumAttrs = NumAttrs;
-  Clause->HasPreferAttrs = InteropInfo.HasPreferAttrs;
+  Clause->HasPreferAttrs = InteropInfo.hasPreferAttrs();
 
   Expr **E = Clause->getTrailingObjects<Expr *>();
   E[0] = InteropVar;
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 40b747da5f9bc..336ea9fde14ca 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/VTableBuilder.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MathExtras.h"
 
@@ -40,10 +41,11 @@ struct BaseSubobjectInfo {
   const CXXRecordDecl *Class;
 
   /// IsVirtual - Whether the BaseInfo represents a virtual base or not.
-  bool IsVirtual;
+  bool getIsVirtual() const { return Bases.getFlag(0); }
+  void setIsVirtual(bool Value) { Bases.setFlag(0, Value); }
 
   /// Bases - Information about the base subobjects.
-  SmallVector<BaseSubobjectInfo*, 4> Bases;
+  llvm::SmallVectorWithFlags<BaseSubobjectInfo *, 4> Bases;
 
   /// PrimaryVirtualBaseInfo - Holds the base info for the primary virtual base
   /// of this base info (if one exists).
@@ -278,7 +280,7 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
   // Traverse all non-virtual bases.
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
   for (const BaseSubobjectInfo *Base : Info->Bases) {
-    if (Base->IsVirtual)
+    if (Base->getIsVirtual())
       continue;
 
     CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
@@ -326,7 +328,7 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
   // Traverse all non-virtual bases.
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
   for (const BaseSubobjectInfo *Base : Info->Bases) {
-    if (Base->IsVirtual)
+    if (Base->getIsVirtual())
       continue;
 
     CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
@@ -583,7 +585,7 @@ class ItaniumRecordLayoutBuilder {
   /// \brief The maximum of the alignments of top-level members.
   CharUnits UnadjustedAlignment;
 
-  SmallVector<uint64_t, 16> FieldOffsets;
+  llvm::SmallVectorWithFlags<uint64_t, 16, 4> FieldOffsets;
 
   /// Whether the external AST source has provided a layout for this
   /// record.
@@ -642,20 +644,28 @@ class ItaniumRecordLayoutBuilder {
 
   /// PrimaryBaseIsVirtual - Whether the primary base of the class we're laying
   /// out is virtual.
-  bool PrimaryBaseIsVirtual;
+  bool getPrimaryBaseIsVirtual() const { return FieldOffsets.getFlag(0); }
+  void setPrimaryBaseIsVirtual(bool Value) { FieldOffsets.setFlag(0, Value); }
 
   /// HasOwnVFPtr - Whether the class provides its own vtable/vftbl
   /// pointer, as opposed to inheriting one from a primary base class.
-  bool HasOwnVFPtr;
+  bool getHasOwnVFPtr() const { return FieldOffsets.getFlag(1); }
+  void setHasOwnVFPtr(bool Value) { FieldOffsets.setFlag(1, Value); }
 
   /// the flag of field offset changing due to packed attribute.
-  bool HasPackedField;
+  bool getHasPackedField() const { return FieldOffsets.getFlag(2); }
+  void setHasPackedField(bool Value) { FieldOffsets.setFlag(2, Value); }
 
   /// HandledFirstNonOverlappingEmptyField - An auxiliary field used for AIX.
   /// When there are OverlappingEmptyFields existing in the aggregate, the
   /// flag shows if the following first non-empty or empty-but-non-overlapping
   /// field has been handled, if any.
-  bool HandledFirstNonOverlappingEmptyField;
+  bool getHandledFirstNonOverlappingEmptyField() const {
+    return FieldOffsets.getFlag(3);
+  }
+  void setHandledFirstNonOverlappingEmptyField(bool Value) {
+    FieldOffsets.setFlag(3, Value);
+  }
 
   typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
 
@@ -695,8 +705,6 @@ class ItaniumRecordLayoutBuilder {
         NonVirtualAlignment(CharUnits::One()),
         PreferredNVAlignment(CharUnits::One()),
         PaddedFieldSize(CharUnits::Zero()), PrimaryBase(nullptr),
-        PrimaryBaseIsVirtual(false), HasOwnVFPtr(false), HasPackedField(false),
-        HandledFirstNonOverlappingEmptyField(false),
         FirstNearlyEmptyVBase(nullptr) {}
 
   void Layout(const RecordDecl *D);
@@ -833,7 +841,7 @@ void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
       // base.
       if (!IndirectPrimaryBases.count(Base)) {
         PrimaryBase = Base;
-        PrimaryBaseIsVirtual = true;
+        setPrimaryBaseIsVirtual(true);
         return;
       }
 
@@ -871,7 +879,7 @@ void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
     if (Base->isDynamicClass()) {
       // We found it.
       PrimaryBase = Base;
-      PrimaryBaseIsVirtual = false;
+      setPrimaryBaseIsVirtual(false);
       return;
     }
   }
@@ -889,7 +897,7 @@ void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
   // Otherwise, it is the first indirect primary base class, if one exists.
   if (FirstNearlyEmptyVBase) {
     PrimaryBase = FirstNearlyEmptyVBase;
-    PrimaryBaseIsVirtual = true;
+    setPrimaryBaseIsVirtual(true);
     return;
   }
 
@@ -916,7 +924,7 @@ BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
   }
 
   Info->Class = RD;
-  Info->IsVirtual = IsVirtual;
+  Info->setIsVirtual(IsVirtual);
   Info->Derived = nullptr;
   Info->PrimaryVirtualBaseInfo = nullptr;
 
@@ -1024,7 +1032,7 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
 
   // If we have a primary base class, lay it out.
   if (PrimaryBase) {
-    if (PrimaryBaseIsVirtual) {
+    if (getPrimaryBaseIsVirtual()) {
       // If the primary virtual base was a primary virtual base of some other
       // base class we'll have to steal it.
       BaseSubobjectInfo *PrimaryBaseInfo = VirtualBaseInfo.lookup(PrimaryBase);
@@ -1056,10 +1064,10 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
     CharUnits PtrAlign = Context.toCharUnitsFromBits(
         Context.getTargetInfo().getPointerAlign(LangAS::Default));
     EnsureVTablePointerAlignment(PtrAlign);
-    HasOwnVFPtr = true;
+    setHasOwnVFPtr(true);
 
     assert(!IsUnion && "Unions cannot be dynamic classes.");
-    HandledFirstNonOverlappingEmptyField = true;
+    setHandledFirstNonOverlappingEmptyField(true);
 
     setSize(getSize() + PtrWidth);
     setDataSize(getSize());
@@ -1077,7 +1085,7 @@ void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
     // Skip the primary base, because we've already laid it out.  The
     // !PrimaryBaseIsVirtual check is required because we might have a
     // non-virtual base of the same type as a primary virtual base.
-    if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual)
+    if (BaseDecl == PrimaryBase && !getPrimaryBaseIsVirtual())
       continue;
 
     // Lay out the base.
@@ -1108,7 +1116,7 @@ void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
 
   // First, check if we have a virtual primary base to add offsets for.
   if (Info->PrimaryVirtualBaseInfo) {
-    assert(Info->PrimaryVirtualBaseInfo->IsVirtual &&
+    assert(Info->PrimaryVirtualBaseInfo->getIsVirtual() &&
            "Primary virtual base is not virtual!");
     if (Info->PrimaryVirtualBaseInfo->Derived == Info) {
       // Add the offset.
@@ -1125,7 +1133,7 @@ void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
   // Now go through all direct non-virtual bases.
   const ASTRecordLayout &Layout = Context.getASTRecordLayout(Info->Class);
   for (const BaseSubobjectInfo *Base : Info->Bases) {
-    if (Base->IsVirtual)
+    if (Base->getIsVirtual())
       continue;
 
     CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base->Class);
@@ -1140,7 +1148,7 @@ void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
 
   if (MostDerivedClass == RD) {
     PrimaryBase = this->PrimaryBase;
-    PrimaryBaseIsVirtual = this->PrimaryBaseIsVirtual;
+    PrimaryBaseIsVirtual = this->getPrimaryBaseIsVirtual();
   } else {
     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
     PrimaryBase = Layout.getPrimaryBase();
@@ -1204,7 +1212,7 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
   // Query the external layout to see if it provides an offset.
   bool HasExternalLayout = false;
   if (UseExternalLayout) {
-    if (Base->IsVirtual)
+    if (Base->getIsVirtual())
       HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset);
     else
       HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset);
@@ -1235,10 +1243,10 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
     // non-union classes if the source of the alignment (the current base in
     // this context) follows introduction of the first subobject with
     // exclusively allocated space or zero-extent array.
-    if (!Base->Class->isEmpty() && !HandledFirstNonOverlappingEmptyField) {
+    if (!Base->Class->isEmpty() && !getHandledFirstNonOverlappingEmptyField()) {
       // By handling a base class that is not empty, we're handling the
       // "first (inherited) member".
-      HandledFirstNonOverlappingEmptyField = true;
+      setHandledFirstNonOverlappingEmptyField(true);
     } else if (!IsNaturalAlign) {
       UnpackedPreferredBaseAlign = UnpackedBaseAlign;
       PreferredBaseAlign = BaseAlign;
@@ -1341,8 +1349,8 @@ void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
       UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign));
   }
 
-  HandledFirstNonOverlappingEmptyField =
-      !Context.getTargetInfo().defaultsToAIXPowerAlignment() || IsNaturalAlign;
+  setHandledFirstNonOverlappingEmptyField(
+      !Context.getTargetInfo().defaultsToAIXPowerAlignment() || IsNaturalAlign);
 
   // If there is an external AST source, ask it for the various offsets.
   if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
@@ -1859,7 +1867,8 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
   const bool DefaultsToAIXPowerAlignment =
       Context.getTargetInfo().defaultsToAIXPowerAlignment();
   bool FoundFirstNonOverlappingEmptyFieldForAIX = false;
-  if (DefaultsToAIXPowerAlignment && !HandledFirstNonOverlappingEmptyField) {
+  if (DefaultsToAIXPowerAlignment &&
+      !getHandledFirstNonOverlappingEmptyField()) {
     assert(FieldOffset == CharUnits::Zero() &&
            "The first non-overlapping empty field should have been handled.");
 
@@ -1871,7 +1880,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
       // invocation of this function; record it as handled for future
       // invocations (except for unions, because the current field does not
       // represent all "firsts").
-      HandledFirstNonOverlappingEmptyField = !IsUnion;
+      setHandledFirstNonOverlappingEmptyField(!IsUnion);
     }
   }
 
@@ -2202,7 +2211,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
     // attribute on such a type does allow the type to be packed into other
     // structures that use the packed attribute.
     if (Packed && UnpackedAlignment <= Alignment &&
-        UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
+        UnpackedSizeInBits == getSizeInBits() && !getHasPackedField() &&
         (!CXXRD || CXXRD->isPOD() ||
          Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver15)))
       Diag(D->getLocation(), diag::warn_unnecessary_packed)
@@ -2320,7 +2329,7 @@ void ItaniumRecordLayoutBuilder::CheckFieldPadding(
     unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
   ::CheckFieldPadding(Context, IsUnion, Offset, UnpaddedOffset, D);
   if (isPacked && Offset != UnpackedOffset) {
-    HasPackedField = true;
+    setHasPackedField(true);
   }
 }
 
@@ -3518,13 +3527,13 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
           Builder.PreferredAlignment, Builder.UnadjustedAlignment,
           /*RequiredAlignment : used by MS-ABI)*/
           Builder.Alignment, /*PragmaPackResistantAlignment=*/CharUnits::Zero(),
-          Builder.HasOwnVFPtr, RD->isDynamicClass(),
+          Builder.getHasOwnVFPtr(), RD->isDynamicClass(),
           CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets,
           NonVirtualSize, Builder.NonVirtualAlignment,
           Builder.PreferredNVAlignment, Builder.NonVirtualAlignment,
           EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
-          Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
-          Builder.VBases);
+          Builder.getPrimaryBaseIsVirtual(), nullptr, false, false,
+          Builder.Bases, Builder.VBases);
     } else {
       ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
       Builder.Layout(D);
diff --git a/clang/lib/AST/VTTBuilder.cpp b/clang/lib/AST/VTTBuilder.cpp
index 89b58b557ddca..1fcfe165f29f4 100644
--- a/clang/lib/AST/VTTBuilder.cpp
+++ b/clang/lib/AST/VTTBuilder.cpp
@@ -27,12 +27,12 @@ using namespace clang;
 
 #define DUMP_OVERRIDERS 0
 
-VTTBuilder::VTTBuilder(ASTContext &Ctx,
-                       const CXXRecordDecl *MostDerivedClass,
+VTTBuilder::VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
                        bool GenerateDefinition)
     : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
-      MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
-      GenerateDefinition(GenerateDefinition) {
+      VTTComponents(decltype(this->VTTComponents)::withFlags(
+          unsigned(GenerateDefinition))),
+      MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)) {
   // Lay out this VTT.
   LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
             /*BaseIsVirtual=*/false);
@@ -47,7 +47,7 @@ void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
     SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
   }
 
-  if (!GenerateDefinition) {
+  if (!getGenerateDefinition()) {
     VTTComponents.push_back(VTTComponent());
     return;
   }
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 3c05d4b22b03e..909cafc36b572 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/SetOperations.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -806,7 +807,10 @@ class ItaniumVTableBuilder {
 
   /// MostDerivedClassIsVirtual - Whether the most derived class is a virtual
   /// base. (This only makes sense when building a construction vtable).
-  bool MostDerivedClassIsVirtual;
+  bool getMostDerivedClassIsVirtual() const { return Components.getFlag(0); }
+  void setMostDerivedClassIsVirtual(bool Value) {
+    Components.setFlag(0, Value);
+  }
 
   /// LayoutClass - The class we're using for layout information. Will be
   /// different than the most derived class if we're building a construction
@@ -828,7 +832,7 @@ class ItaniumVTableBuilder {
   VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
 
   /// Components - The components of the vtable being built.
-  SmallVector<VTableComponent, 64> Components;
+  llvm::SmallVectorWithFlags<VTableComponent, 64> Components;
 
   /// AddressPoints - Address points for the vtable being built.
   AddressPointsMapTy AddressPoints;
@@ -1004,9 +1008,10 @@ class ItaniumVTableBuilder {
                        const CXXRecordDecl *LayoutClass)
       : VTables(VTables), MostDerivedClass(MostDerivedClass),
         MostDerivedClassOffset(MostDerivedClassOffset),
-        MostDerivedClassIsVirtual(MostDerivedClassIsVirtual),
         LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()),
-        Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass) {
+        Overriders(MostDerivedClass, MostDerivedClassOffset, LayoutClass),
+        Components(decltype(this->Components)::withFlags(
+            unsigned(MostDerivedClassIsVirtual))) {
     assert(!Context.getTargetInfo().getCXXABI().isMicrosoft());
 
     LayoutVTable();
@@ -1661,11 +1666,10 @@ void ItaniumVTableBuilder::AddMethods(
 }
 
 void ItaniumVTableBuilder::LayoutVTable() {
-  LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass,
-                                                 CharUnits::Zero()),
-                                   /*BaseIsMorallyVirtual=*/false,
-                                   MostDerivedClassIsVirtual,
-                                   MostDerivedClassOffset);
+  LayoutPrimaryAndSecondaryVTables(
+      BaseSubobject(MostDerivedClass, CharUnits::Zero()),
+      /*BaseIsMorallyVirtual=*/false, getMostDerivedClassIsVirtual(),
+      MostDerivedClassOffset);
 
   VisitedVirtualBasesSetTy VBases;
 
@@ -2534,12 +2538,13 @@ class VFTableBuilder {
   const FinalOverriders Overriders;
 
   /// Components - The components of the vftable being built.
-  SmallVector<VTableComponent, 64> Components;
+  llvm::SmallVectorWithFlags<VTableComponent, 64> Components;
 
   MethodVFTableLocationsTy MethodVFTableLocations;
 
   /// Does this class have an RTTI component?
-  bool HasRTTIComponent = false;
+  bool getHasRTTIComponent() const { return Components.getFlag(0); }
+  void setHasRTTIComponent(bool Value) { Components.setFlag(0, Value); }
 
   /// MethodInfo - Contains information about a method in a vtable.
   /// (Used for computing 'this' pointer adjustment thunks.
@@ -2631,7 +2636,7 @@ class VFTableBuilder {
 
   void LayoutVFTable() {
     // RTTI data goes before all other entries.
-    if (HasRTTIComponent)
+    if (getHasRTTIComponent())
       Components.push_back(VTableComponent::MakeRTTI(MostDerivedClass));
 
     BasesSetVectorTy VisitedBases;
@@ -2681,7 +2686,7 @@ class VFTableBuilder {
     // dllimport or extern template instantiations, but eventually we may add a
     // flag to support additional devirtualization that needs this.
     if (Context.getLangOpts().RTTIData)
-      HasRTTIComponent = true;
+      setHasRTTIComponent(true);
 
     LayoutVFTable();
 
@@ -3162,7 +3167,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
     // If we got here, MD is a method not seen in any of the sub-bases or
     // it requires return adjustment. Insert the method info for this method.
     MethodInfo MI(VBIndex,
-                  HasRTTIComponent ? Components.size() - 1 : Components.size(),
+                  getHasRTTIComponent() ? Components.size() - 1
+                                        : Components.size(),
                   ReturnAdjustingThunk);
 
     assert(!MethodInfoMap.count(MD) &&
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 556e08f5c1df8..931cdd1d7470d 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -45,6 +45,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DOTGraphTraits.h"
@@ -700,7 +701,8 @@ class CFGBuilder {
   struct TempDtorContext {
     TempDtorContext() = default;
     TempDtorContext(TryResult KnownExecuted)
-        : IsConditional(true), KnownExecuted(KnownExecuted) {}
+        : CollectedMTEs(decltype(this->CollectedMTEs)::withFlags(1)),
+          KnownExecuted(KnownExecuted) {}
     /// Returns whether we need to start a new branch for a temporary destructor
     /// call. This is the case when the temporary destructor is
     /// conditionally executed, and it is the first one we encounter while
@@ -708,7 +710,7 @@ class CFGBuilder {
     /// will be added to the same block and are executed under the same
     /// condition.
     bool needsTempDtorBranch() const {
-      return IsConditional && !TerminatorExpr;
+      return getIsConditional() && !TerminatorExpr;
     }
 
     /// Remember the successor S of a temporary destructor decision branch for
@@ -722,11 +724,18 @@ class CFGBuilder {
       CollectedMTEs.push_back(MTE);
     }
 
-    const bool IsConditional = false;
-    SmallVector<const MaterializeTemporaryExpr *, 5> CollectedMTEs;
+    bool getIsConditional() const { return CollectedMTEs.getFlag(0); }
+    llvm::SmallVectorWithFlags<const MaterializeTemporaryExpr *, 5>
+        CollectedMTEs;
     const TryResult KnownExecuted = true;
     CFGBlock *Succ = nullptr;
     CXXBindTemporaryExpr *TerminatorExpr = nullptr;
+
+  public:
+    TempDtorContext(const TempDtorContext &) = default;
+    TempDtorContext(TempDtorContext &&) = default;
+    TempDtorContext &operator=(const TempDtorContext &) = delete;
+    TempDtorContext &operator=(TempDtorContext &&) = delete;
   };
 
   // Visitors to walk an AST and generate destructors of temporaries in
@@ -5298,7 +5307,8 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaries(
     InsertTempDecisionBlock(RHSContext);
 
     if (BuildOpts.AddLifetime)
-      Context.CollectedMTEs.append(RHSContext.CollectedMTEs);
+      Context.CollectedMTEs.append(RHSContext.CollectedMTEs.begin(),
+                                   RHSContext.CollectedMTEs.end());
 
     return Block;
   }
@@ -5409,8 +5419,10 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaries(
     InsertTempDecisionBlock(FalseContext);
   }
   if (BuildOpts.AddLifetime) {
-    Context.CollectedMTEs.append(TrueContext.CollectedMTEs);
-    Context.CollectedMTEs.append(FalseContext.CollectedMTEs);
+    Context.CollectedMTEs.append(TrueContext.CollectedMTEs.begin(),
+                                 TrueContext.CollectedMTEs.end());
+    Context.CollectedMTEs.append(FalseContext.CollectedMTEs.begin(),
+                                 FalseContext.CollectedMTEs.end());
   }
 
   return Block;
diff --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp
index 95f3fdbe6e999..6242882c8d487 100644
--- a/clang/lib/Analysis/CalledOnceCheck.cpp
+++ b/clang/lib/Analysis/CalledOnceCheck.cpp
@@ -31,6 +31,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -609,9 +610,9 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
 private:
   CalledOnceChecker(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler,
                     bool CheckConventionalParameters)
-      : FunctionCFG(*AC.getCFG()), AC(AC), Handler(Handler),
-        CheckConventionalParameters(CheckConventionalParameters),
-        CurrentState(0) {
+      : FunctionCFG(*AC.getCFG()), AC(AC), Handler(Handler), CurrentState(0),
+        TrackedParams(decltype(TrackedParams)::withFlags(
+            unsigned(CheckConventionalParameters))) {
     initDataStructures();
     assert((size() == 0 || !States.empty()) &&
            "Data structures are inconsistent");
@@ -815,7 +816,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
         // ... or if we've seen variables with cleanup functions.
         // We can't reason that we've seen every path in this case,
         // and thus abandon reporting any warnings that imply that.
-        !FunctionHasCleanupVars)
+        !getFunctionHasCleanupVars())
       return;
 
     // We are looking for a pair of blocks A, B so that the following is true:
@@ -1034,7 +1035,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
 
   bool shouldBeCalledOnce(const ParmVarDecl *Parameter) const {
     return isExplicitlyMarked(Parameter) ||
-           (CheckConventionalParameters &&
+           (getCheckConventionalParameters() &&
             (isConventional(Parameter->getName()) ||
              hasConventionalSuffix(Parameter->getName())) &&
             isConventional(Parameter->getType()));
@@ -1068,7 +1069,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
     }
 
     return shouldBeCalledOnce(Function->getParamDecl(ParamIndex)) ||
-           (CheckConventionalParameters &&
+           (getCheckConventionalParameters() &&
             isOnlyParameterConventional(Function));
   }
 
@@ -1086,7 +1087,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
 
     const ParmVarDecl *Parameter = Method->getParamDecl(ParamIndex);
     return shouldBeCalledOnce(Parameter) ||
-           (CheckConventionalParameters &&
+           (getCheckConventionalParameters() &&
             isConventionalSelectorPiece(MethodSelector, ParamIndex,
                                         Parameter->getType()));
   }
@@ -1343,7 +1344,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
   void handleConditional(const CFGBlock *BB, const Expr *Condition,
                          State &ToAlter) const {
     handleParameterCheck(BB, Condition, ToAlter);
-    if (SuppressOnConventionalErrorPaths) {
+    if (getSuppressOnConventionalErrorPaths()) {
       handleConventionalCheck(BB, Condition, ToAlter);
     }
   }
@@ -1611,7 +1612,7 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
         }
 
         if (Var->hasAttr<CleanupAttr>()) {
-          FunctionHasCleanupVars = true;
+          setFunctionHasCleanupVars(true);
         }
       }
     }
@@ -1672,24 +1673,38 @@ class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> {
   const CFG &FunctionCFG;
   AnalysisDeclContext &AC;
   CalledOnceCheckHandler &Handler;
-  bool CheckConventionalParameters;
+  bool getCheckConventionalParameters() const {
+    return TrackedParams.getFlag(0);
+  }
+  void setCheckConventionalParameters(bool Value) {
+    TrackedParams.setFlag(0, Value);
+  }
   // As of now, we turn this behavior off.  So, we still are going to report
   // missing calls on paths that look like it was intentional.
   // Technically such reports are true positives, but they can make some users
   // grumpy because of the sheer number of warnings.
   // It can be turned back on if we decide that we want to have the other way
   // around.
-  bool SuppressOnConventionalErrorPaths = false;
+  bool getSuppressOnConventionalErrorPaths() const {
+    return TrackedParams.getFlag(1);
+  }
+  void setSuppressOnConventionalErrorPaths(bool Value) {
+    TrackedParams.setFlag(1, Value);
+  }
 
   // The user can annotate variable declarations with cleanup functions, which
   // essentially imposes a custom destructor logic on that variable.
   // It is possible to use it, however, to call tracked parameters on all exits
   // from the function.  For this reason, we track the fact that the function
   // actually has these.
-  bool FunctionHasCleanupVars = false;
+  bool getFunctionHasCleanupVars() const { return TrackedParams.getFlag(2); }
+  void setFunctionHasCleanupVars(bool Value) {
+    TrackedParams.setFlag(2, Value);
+  }
 
   State CurrentState;
-  ParamSizedVector<const ParmVarDecl *> TrackedParams;
+  llvm::SmallVectorWithFlagsFor<ParamSizedVector<const ParmVarDecl *>, 3>
+      TrackedParams;
   CFGSizedVector<State> States;
 };
 
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 6a805bb7be2d8..b56cf863cf2c4 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -364,7 +364,7 @@ void FactsGenerator::VisitUnaryOperator(const UnaryOperator *UO) {
       return;
     // Skip address-of on void expressions: GNU C permits them, but void itself
     // has no origins to track.
-    if (IsCMode && SubExpr->getType()->isVoidType())
+    if (getIsCMode() && SubExpr->getType()->isVoidType())
       return;
     assert(!SubExpr->getType()->isVoidType() &&
            "Taking address of void is not valid in C++");
@@ -456,7 +456,7 @@ void FactsGenerator::handleAssignment(const Expr *TargetExpr,
 
   // In C, assignment expressions are not GLValues, so the assignment result has
   // the assigned value origins, not the LHS storage origin.
-  if (IsCMode)
+  if (getIsCMode())
     LHSList = LHSList->peelOuterOrigin();
   flow(getOriginsList(*TargetExpr), LHSList, /*Kill=*/true);
 }
@@ -503,7 +503,8 @@ void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) {
     // (storage) origin.
     if (BO->getType()->isPointerType()) {
       OriginList *LHSList = getOriginsList(*BO->getLHS());
-      flow(getOriginsList(*BO), IsCMode ? LHSList->peelOuterOrigin() : LHSList,
+      flow(getOriginsList(*BO),
+           getIsCMode() ? LHSList->peelOuterOrigin() : LHSList,
            /*Kill=*/true);
     }
     return;
@@ -683,7 +684,7 @@ void FactsGenerator::VisitLambdaExpr(const LambdaExpr *LE) {
 void FactsGenerator::VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE) {
   // Some C subscripts do not refer to addressable storage with origins, such as
   // GNU void-pointer subscripts and vector element extraction from rvalues.
-  if (IsCMode && !ASE->isGLValue())
+  if (getIsCMode() && !ASE->isGLValue())
     return;
   assert(ASE->isGLValue() && "Array subscript should be a GL value");
   OriginList *Dst = getOriginsList(*ASE);
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 80a21cba8e2fc..d832adeb58e3a 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -38,21 +38,20 @@ Module::Module(ModuleConstructorTag, StringRef Name,
                SourceLocation DefinitionLoc, Module *Parent, bool IsFramework,
                bool IsExplicit, unsigned VisibilityID)
     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
-      VisibilityID(VisibilityID), IsUnimportable(false),
-      HasIncompatibleModuleFile(false), IsAvailable(true),
-      IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
-      IsSystem(false), IsExternC(false), IsInferred(false),
-      InferSubmodules(false), InferExplicitSubmodules(false),
-      InferExportWildcard(false), ConfigMacrosExhaustive(false),
-      NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
-      NamedModuleHasInit(true), NameVisibility(Hidden) {
+      VisibilityID(VisibilityID),
+      HeadersStorage(decltype(this->HeadersStorage)::withFlags(
+          unsigned((unsigned(IsFramework) & 1)) |
+          (unsigned((unsigned(IsExplicit) & 1)) << 1))),
+      Requirements(decltype(this->Requirements)::withFlags(4)),
+      NameVisibility(Hidden),
+      UnresolvedDirectUses(decltype(this->UnresolvedDirectUses)::withFlags(8)) {
   if (Parent) {
-    IsAvailable = Parent->isAvailable();
-    IsUnimportable = Parent->isUnimportable();
-    IsSystem = Parent->IsSystem;
-    IsExternC = Parent->IsExternC;
-    NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;
-    ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;
+    setIsAvailable(Parent->isAvailable());
+    setIsUnimportable(Parent->isUnimportable());
+    setIsSystem(Parent->getIsSystem());
+    setIsExternC(Parent->getIsExternC());
+    setNoUndeclaredIncludes(Parent->getNoUndeclaredIncludes());
+    setModuleMapIsPrivate(Parent->getModuleMapIsPrivate());
 
     Parent->addSubmodule(Name, this);
   }
@@ -128,7 +127,7 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
 bool Module::isUnimportable(const LangOptions &LangOpts,
                             const TargetInfo &Target, Requirement &Req,
                             Module *&ShadowingModule) const {
-  if (!IsUnimportable)
+  if (!getIsUnimportable())
     return false;
 
   for (const Module *Current = this; Current; Current = Current->Parent) {
@@ -161,7 +160,7 @@ bool Module::isForBuilding(const LangOptions &LangOpts) const {
   // When building the implementation of framework Foo, we want to make sure
   // that Foo *and* Foo_Private are textually included and no modules are built
   // for either.
-  if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework &&
+  if (!LangOpts.isCompilingModule() && getTopLevelModule()->getIsFramework() &&
       CurrentModule == LangOpts.ModuleName &&
       !CurrentModule.ends_with("_Private") &&
       TopLevelName.ends_with("_Private"))
@@ -174,7 +173,7 @@ bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
                          Requirement &Req,
                          UnresolvedHeaderDirective &MissingHeader,
                          Module *&ShadowingModule) const {
-  if (IsAvailable)
+  if (getIsAvailable())
     return true;
 
   if (isUnimportable(LangOpts, Target, Req, ShadowingModule))
@@ -327,7 +326,7 @@ bool Module::directlyUses(const Module *Requested) {
   if (!Requested->Parent && Requested->Name == "ptrauth")
     return true;
 
-  if (NoUndeclaredIncludes)
+  if (getNoUndeclaredIncludes())
     UndeclaredUses.insert(Requested);
 
   return false;
@@ -347,7 +346,7 @@ void Module::addRequirement(StringRef Feature, bool RequiredState,
 
 void Module::markUnavailable(bool Unimportable) {
   auto needUpdate = [Unimportable](Module *M) {
-    return M->IsAvailable || (!M->IsUnimportable && Unimportable);
+    return M->getIsAvailable() || (!M->getIsUnimportable() && Unimportable);
   };
 
   if (!needUpdate(this))
@@ -361,8 +360,9 @@ void Module::markUnavailable(bool Unimportable) {
     if (!needUpdate(Current))
       continue;
 
-    Current->IsAvailable = false;
-    Current->IsUnimportable |= Unimportable;
+    Current->setIsAvailable(false);
+    Current->setIsUnimportable(int(Current->getIsUnimportable()) |
+                               (Unimportable));
     for (Module *Submodule : Current->submodules()) {
       if (needUpdate(Submodule))
         Stack.push_back(Submodule);
@@ -402,7 +402,7 @@ Module *Module::getPrivateModuleFragment() const {
 void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
   // All non-explicit submodules are exported.
   for (Module *Mod : submodules())
-    if (!Mod->IsExplicit)
+    if (!Mod->getIsExplicit())
       Exported.push_back(Mod);
 
   // Find re-exported modules by filtering the list of imported modules.
@@ -477,18 +477,18 @@ void Module::buildVisibleModulesCache() const {
 
 void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
   OS.indent(Indent);
-  if (IsFramework)
+  if (getIsFramework())
     OS << "framework ";
-  if (IsExplicit)
+  if (getIsExplicit())
     OS << "explicit ";
   OS << "module ";
   printModuleId(OS, &Name, &Name + 1);
 
-  if (IsSystem || IsExternC) {
+  if (getIsSystem() || getIsExternC()) {
     OS.indent(Indent + 2);
-    if (IsSystem)
+    if (getIsSystem())
       OS << " [system]";
-    if (IsExternC)
+    if (getIsExternC())
       OS << " [extern_c]";
   }
 
@@ -519,10 +519,10 @@ void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
     OS << "\"\n";
   }
 
-  if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
+  if (!ConfigMacros.empty() || getConfigMacrosExhaustive()) {
     OS.indent(Indent + 2);
     OS << "config_macros ";
-    if (ConfigMacrosExhaustive)
+    if (getConfigMacrosExhaustive())
       OS << "[exhaustive]";
     for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
       if (I)
@@ -579,7 +579,7 @@ void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
     // them (requires expensive directory iteration + stat calls) when we build
     // the module. Regular inferred submodules are OK, as we need to look at all
     // those header files anyway.
-    if (!Submodule->IsInferred || Submodule->IsFramework)
+    if (!Submodule->getIsInferred() || Submodule->getIsFramework())
       Submodule->print(OS, Indent + 2, Dump);
 
   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
@@ -599,7 +599,7 @@ void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
     OS.indent(Indent + 2);
     OS << "export ";
     printModuleId(OS, UnresolvedExports[I].Id);
-    if (UnresolvedExports[I].Wildcard)
+    if (UnresolvedExports[I].getWildcard())
       OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
     OS << "\n";
   }
@@ -653,12 +653,12 @@ void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
     OS << "\"\n";
   }
 
-  if (InferSubmodules) {
+  if (getInferSubmodules()) {
     OS.indent(Indent + 2);
-    if (InferExplicitSubmodules)
+    if (getInferExplicitSubmodules())
       OS << "explicit ";
     OS << "module * {\n";
-    if (InferExportWildcard) {
+    if (getInferExportWildcard()) {
       OS.indent(Indent + 4);
       OS << "export *\n";
     }
diff --git a/clang/lib/Basic/Sarif.cpp b/clang/lib/Basic/Sarif.cpp
index e829b9bb47ad9..091bd16dd9fea 100644
--- a/clang/lib/Basic/Sarif.cpp
+++ b/clang/lib/Basic/Sarif.cpp
@@ -242,8 +242,9 @@ SarifDocumentWriter::createPhysicalLocation(const CharSourceRange &R) {
 }
 
 json::Object &SarifDocumentWriter::getCurrentTool() {
-  assert(!Closed && "SARIF Document is closed. "
-                    "Need to call createRun() before using getcurrentTool!");
+  assert(!getClosed() &&
+         "SARIF Document is closed. "
+         "Need to call createRun() before using getcurrentTool!");
 
   // Since Closed = false here, expect there to be at least 1 Run, anything
   // else is an invalid state.
@@ -259,7 +260,7 @@ void SarifDocumentWriter::reset() {
 
 void SarifDocumentWriter::endRun() {
   // Exit early if trying to close a closed Document.
-  if (Closed) {
+  if (getClosed()) {
     reset();
     return;
   }
@@ -320,7 +321,7 @@ void SarifDocumentWriter::endRun() {
   reset();
 
   // Mark the document as closed.
-  Closed = true;
+  setClosed(true);
 }
 
 json::Array
@@ -349,7 +350,7 @@ void SarifDocumentWriter::createRun(StringRef ShortToolName,
   endRun();
 
   // Signify a new run has begun.
-  Closed = false;
+  setClosed(false);
 
   json::Object Tool{
       {"driver",
@@ -367,7 +368,7 @@ void SarifDocumentWriter::createRun(StringRef ShortToolName,
 }
 
 json::Object &SarifDocumentWriter::getCurrentRun() {
-  assert(!Closed &&
+  assert(!getClosed() &&
          "SARIF Document is closed. "
          "Can only getCurrentRun() if document is opened via createRun(), "
          "create a run first");
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index c9567d263c444..ae284af4e30df 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -320,7 +320,9 @@ LineTableInfo &SourceManager::getLineTable() {
 
 SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
                              bool UserFilesAreVolatile)
-  : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
+    : Diag(Diag), FileMgr(FileMgr),
+      StoredModuleBuildStack(decltype(this->StoredModuleBuildStack)::withFlags(
+          (unsigned(UserFilesAreVolatile) << 1))) {
   clearIDTables();
   Diag.setSourceManager(this);
 }
@@ -423,15 +425,15 @@ ContentCache &SourceManager::getOrCreateContentCache(FileEntryRef FileEnt,
     if (overI == OverriddenFilesInfo->OverriddenFiles.end())
       new (Entry) ContentCache(FileEnt);
     else
-      new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
-                                                              : overI->second,
-                               overI->second);
+      new (Entry) ContentCache(
+          getOverridenFilesKeepOriginalNameFlag() ? FileEnt : overI->second,
+          overI->second);
   } else {
     new (Entry) ContentCache(FileEnt);
   }
 
-  Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
-  Entry->IsTransient = FilesAreTransient;
+  Entry->IsFileVolatile = getUserFilesAreVolatile() && !isSystemFile;
+  Entry->IsTransient = getFilesAreTransient();
   Entry->BufferOverridden |= FileEnt.isNamedPipe();
 
   return *Entry;
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 17d832046363f..e242b1a34e883 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -158,7 +158,7 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
   } else {
     // Non-constant size type
     assert(!cir::MissingFeatures::openMP());
-    if (!didCallStackSave) {
+    if (!getDidCallStackSave()) {
       // Save the stack.
       cir::PointerType defaultTy = allocaInt8PtrTy;
       CharUnits align = CharUnits::fromQuantity(
@@ -169,7 +169,7 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
       assert(v.getType() == allocaInt8PtrTy);
       builder.createStore(loc, v, stack);
 
-      didCallStackSave = true;
+      setDidCallStackSave(true);
 
       // Push a cleanup block and restore the stack there.
       // FIXME: in general circumstances, this should be an EH cleanup.
@@ -1532,7 +1532,7 @@ void CIRGenFunction::maybeEmitDeferredVarDeclInit(const VarDecl *vd) {
 }
 
 bool CIRGenFunction::emitLifetimeStartOp(mlir::Location loc, mlir::Value addr) {
-  if (!shouldEmitLifetimeMarkers)
+  if (!getShouldEmitLifetimeMarkers())
     return false;
 
   assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
@@ -1544,7 +1544,7 @@ bool CIRGenFunction::emitLifetimeStartOp(mlir::Location loc, mlir::Value addr) {
 }
 
 void CIRGenFunction::emitLifetimeEndOp(mlir::Location loc, mlir::Value addr) {
-  if (!shouldEmitLifetimeMarkers)
+  if (!getShouldEmitLifetimeMarkers())
     return;
 
   assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 14fc9cdff3ab6..d3cbdbbbfa777 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -49,8 +49,8 @@ CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,
     : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder),
       curFPFeatures(cgm.getLangOpts()) {
   ehStack.setCGF(this);
-  shouldEmitLifetimeMarkers = CodeGenUtils::shouldEmitLifetimeMarkers(
-      cgm.getCodeGenOpts(), getContext().getLangOpts());
+  setShouldEmitLifetimeMarkers(CodeGenUtils::shouldEmitLifetimeMarkers(
+      cgm.getCodeGenOpts(), getContext().getLangOpts()));
 }
 
 CIRGenFunction::~CIRGenFunction() {}
@@ -402,7 +402,7 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
   // That influences whether the terminating op is trap, unreachable, or
   // return.
   if (fd && cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&
-      !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&
+      !cgf.getSawAsmBlock() && !fd->getReturnType()->isVoidType() &&
       builder.getInsertionBlock() &&
       !previousOpIsNonYieldingCleanup(builder.getInsertionBlock())) {
     bool shouldEmitUnreachable =
@@ -521,7 +521,7 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
 
   const Decl *d = gd.getDecl();
 
-  didCallStackSave = false;
+  setDidCallStackSave(false);
   curCodeDecl = d;
   const auto *fd = dyn_cast_or_null<FunctionDecl>(d);
   curFuncDecl = (d ? d->getNonClosureContext() : nullptr);
@@ -787,8 +787,8 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
       fn->setAttr(cir::CIRDialect::getMustProgressAttrName(),
                   mlir::UnitAttr::get(&getMLIRContext()));
 
-    if (shouldEmitLifetimeMarkers)
-      fnHasBypassStmt = functionMightHaveBypass(body);
+    if (getShouldEmitLifetimeMarkers())
+      setFnHasBypassStmt(functionMightHaveBypass(body));
 
     if (isa<CXXDestructorDecl>(funcDecl)) {
       emitDestructorBody(args);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 8be794a660224..298c08f8b179d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -19,6 +19,7 @@
 #include "CIRGenTypeCache.h"
 #include "CIRGenValue.h"
 #include "EHScopeStack.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "Address.h"
 
@@ -311,7 +312,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   mlir::Operation *curFn = nullptr;
 
   /// Save Parameter Decl for coroutine.
-  llvm::SmallVector<const ParmVarDecl *> fnArgs;
+  llvm::SmallVectorWithFlags<const ParmVarDecl *> fnArgs;
 
   using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
   /// This keeps track of the CIR allocas or globals for local C
@@ -319,7 +320,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   DeclMapTy localDeclMap;
 
   /// The type of the condition for the emitting switch statement.
-  llvm::SmallVector<mlir::Type, 2> condTypeStack;
+  llvm::SmallVectorWithFlags<mlir::Type, 2, 4> condTypeStack;
 
   clang::ASTContext &getContext() const { return cgm.getASTContext(); }
 
@@ -368,15 +369,18 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   /// Whether a cir.stacksave operation has been added. Used to avoid
   /// inserting cir.stacksave for multiple VLAs in the same scope.
-  bool didCallStackSave = false;
+  bool getDidCallStackSave() const { return condTypeStack.getFlag(0); }
+  void setDidCallStackSave(bool Value) { condTypeStack.setFlag(0, Value); }
 
   /// Whether or not a Microsoft-style asm block has been processed within
   /// this fuction. These can potentially set the return value.
-  bool sawAsmBlock = false;
+  bool getSawAsmBlock() const { return condTypeStack.getFlag(1); }
+  void setSawAsmBlock(bool Value) { condTypeStack.setFlag(1, Value); }
 
   /// In C++, whether we are code generating a thunk. This controls whether we
   /// should emit cleanups.
-  bool curFuncIsThunk = false;
+  bool getCurFuncIsThunk() const { return condTypeStack.getFlag(2); }
+  void setCurFuncIsThunk(bool Value) { condTypeStack.setFlag(2, Value); }
 
   mlir::Type convertTypeForMem(QualType t);
 
@@ -1375,8 +1379,8 @@ class CIRGenFunction : public CIRGenTypeCache {
       cleanupStackDepth = cgf.ehStack.stable_begin();
       lifetimeExtendedCleanupStackSize =
           cgf.lifetimeExtendedCleanupStack.size();
-      oldDidCallStackSave = cgf.didCallStackSave;
-      cgf.didCallStackSave = false;
+      oldDidCallStackSave = cgf.getDidCallStackSave();
+      cgf.setDidCallStackSave(false);
       oldCleanupStackDepth = cgf.currentCleanupStackDepth;
       cgf.currentCleanupStackDepth = cleanupStackDepth;
     }
@@ -1391,7 +1395,7 @@ class CIRGenFunction : public CIRGenTypeCache {
     /// until this object is destroyed.
     void forceCleanup(ArrayRef<mlir::Value *> valuesToReload = {}) {
       assert(performCleanup && "Already forced cleanup");
-      cgf.didCallStackSave = oldDidCallStackSave;
+      cgf.setDidCallStackSave(oldDidCallStackSave);
 
       // forceDeactivate() can pop cleanup scopes that were pushed with
       // deferred deactivation, which moves the insertion point out of the
@@ -1462,7 +1466,7 @@ class CIRGenFunction : public CIRGenTypeCache {
     /// scope.
     void forceCleanupExceptLifetimeExtended() {
       assert(performCleanup && "Already forced cleanup");
-      cgf.didCallStackSave = oldDidCallStackSave;
+      cgf.setDidCallStackSave(oldDidCallStackSave);
       deactivateCleanups.forceDeactivate();
       cgf.popCleanupBlocks(cleanupStackDepth);
     }
@@ -3074,13 +3078,20 @@ class CIRGenFunction : public CIRGenTypeCache {
 private:
   QualType getVarArgType(const Expr *arg);
 
-  bool shouldEmitLifetimeMarkers = false;
+  bool getShouldEmitLifetimeMarkers() const { return condTypeStack.getFlag(3); }
+  void setShouldEmitLifetimeMarkers(bool Value) {
+    condTypeStack.setFlag(3, Value);
+  }
   /// Set when the current function has a goto/switch that may bypass a local's
   /// init; lifetime markers are then suppressed. See functionMightHaveBypass.
-  bool fnHasBypassStmt = false;
+  bool getFnHasBypassStmt() const { return fnArgs.getFlag(0); }
+  bool setFnHasBypassStmt(bool Value) {
+    fnArgs.setFlag(0, Value);
+    return Value;
+  }
 
   bool shouldEmitLifetimeMarkersForAutoVar() const {
-    return shouldEmitLifetimeMarkers && !fnHasBypassStmt;
+    return getShouldEmitLifetimeMarkers() && !getFnHasBypassStmt();
   }
 
   class InlinedInheritingConstructorScope {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 614a731158e45..0bd2494c92e87 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -97,9 +97,9 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
   // initializer function of their own only under the Itanium mangler, since
   // no Microsoft mangling for it has been settled on yet; otherwise they fall
   // back to `_GLOBAL__sub_I_` as in classic CodeGen.
-  cxx20ModuleInits =
-      langOpts.CPlusPlusModules &&
-      getCXXABI().getMangleContext().getKind() == MangleContext::MK_Itanium;
+  setCxx20ModuleInits(langOpts.CPlusPlusModules &&
+                      getCXXABI().getMangleContext().getKind() ==
+                          MangleContext::MK_Itanium);
 
   // Initialize cached types
   voidTy = cir::VoidType::get(&getMLIRContext());
@@ -2556,7 +2556,7 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
     // initializers are not emitted here. The global init function of this
     // translation unit calls that initializer, which in turn covers the
     // modules it imports itself; release() records the modules to call.
-    if (cxx20ModuleInits && mod->isNamedModule())
+    if (getCxx20ModuleInits() && mod->isNamedModule())
       break;
 
     // For clang C++ module map modules the initializers for sub-modules are
@@ -2580,7 +2580,7 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
       for (clang::Module *submodule : cur->submodules()) {
         // Skip explicit children; they need to be explicitly imported to emit
         // the initializers.
-        if (submodule->IsExplicit)
+        if (submodule->getIsExplicit())
           continue;
 
         if (visited.insert(submodule).second)
@@ -4065,7 +4065,7 @@ void CIRGenModule::release() {
   // and that the function needs external linkage, and its absence selects the
   // `_GLOBAL__sub_I_` form.  Lowering therefore never has to rediscover the
   // module from the AST.
-  if (cxx20ModuleInits) {
+  if (getCxx20ModuleInits()) {
     clang::Module *primary = astContext.getCurrentNamedModule();
     bool isInterfaceUnit = primary && !primary->isModuleImplementation();
     if (isInterfaceUnit)
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 80bf5940e461e..ff3814cd90cf8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -21,6 +21,7 @@
 #include "CIRGenTypes.h"
 #include "CIRGenVTables.h"
 #include "CIRGenValue.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "clang/AST/CharUnits.h"
 #include "clang/CIR/Dialect/IR/CIRDataLayout.h"
@@ -116,11 +117,14 @@ class CIRGenModule : public CIRGenTypeCache {
   llvm::SmallVector<mlir::Attribute> globalScopeAsm;
 
   /// Accumulated record layout entries, materialized in release().
-  llvm::SmallVector<mlir::NamedAttribute> recordLayoutEntries;
+  llvm::SmallVectorWithFlags<mlir::NamedAttribute> recordLayoutEntries;
 
   /// Whether C++20 named modules get their own module initializer function,
   /// which requires the Itanium mangling of the initializer name.
-  bool cxx20ModuleInits = false;
+  bool getCxx20ModuleInits() const { return recordLayoutEntries.getFlag(0); }
+  void setCxx20ModuleInits(bool Value) {
+    recordLayoutEntries.setFlag(0, Value);
+  }
 
   /// The complete set of modules that have been imported.
   llvm::SetVector<clang::Module *> importedModules;
diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
index c2d39468782ce..5efa5b461d3e4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp
@@ -14,6 +14,7 @@
 #include "CIRGenModule.h"
 #include "CIRGenTypes.h"
 #include "TargetInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
@@ -325,19 +326,32 @@ struct CIRRecordLowering final {
   llvm::DenseMap<const CXXRecordDecl *, unsigned> virtualBases;
   cir::CIRDataLayout dataLayout;
 
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned zeroInitializable : 1;
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned zeroInitializableAsBase : 1;
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned packed : 1;
+  unsigned getZeroInitializable() const { return fieldKinds.getFlag(0); }
+  unsigned setZeroInitializable(unsigned Value) {
+    fieldKinds.setFlag(0, (Value & 1));
+    return (Value & 1);
+  }
+  unsigned getZeroInitializableAsBase() const { return fieldKinds.getFlag(1); }
+  unsigned setZeroInitializableAsBase(unsigned Value) {
+    fieldKinds.setFlag(1, (Value & 1));
+    return (Value & 1);
+  }
+  unsigned getPacked() const { return fieldKinds.getFlag(2); }
+  unsigned setPacked(unsigned Value) {
+    fieldKinds.setFlag(2, (Value & 1));
+    return (Value & 1);
+  }
 
 private:
   // Output fields, consumed by CIRGenTypes::computeRecordLayout.  Private so
   // that every append goes through addField and fieldKinds stays parallel to
   // fieldTypes.
   llvm::SmallVector<mlir::Type, 16> fieldTypes;
-  llvm::SmallVector<cir::RecordMemberKind> fieldKinds;
+  llvm::SmallVectorWithFlags<cir::RecordMemberKind,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 cir::RecordMemberKind>::value,
+                             3>
+      fieldKinds;
 
   CIRRecordLowering(const CIRRecordLowering &) = delete;
   void operator=(const CIRRecordLowering &) = delete;
@@ -352,7 +366,8 @@ CIRRecordLowering::CIRRecordLowering(CIRGenTypes &cirGenTypes,
       astRecordLayout{
           cirGenTypes.getASTContext().getASTRecordLayout(recordDecl)},
       dataLayout{cirGenTypes.getCGModule().getModule()},
-      zeroInitializable{true}, zeroInitializableAsBase{true}, packed{packed} {}
+      fieldKinds(decltype(this->fieldKinds)::withFlags(
+          (unsigned((unsigned(packed) & 1)) << 2) | 3)) {}
 
 void CIRRecordLowering::setBitFieldInfo(const FieldDecl *fd,
                                         CharUnits startOffset,
@@ -780,21 +795,21 @@ void CIRRecordLowering::calculateZeroInit() {
     if (member.kind == MemberInfo::InfoKind::Field) {
       if (!member.fieldDecl || isZeroInitializable(member.fieldDecl))
         continue;
-      zeroInitializable = zeroInitializableAsBase = false;
+      setZeroInitializable(setZeroInitializableAsBase(false));
       return;
     } else if (member.kind == MemberInfo::InfoKind::Base ||
                member.kind == MemberInfo::InfoKind::VBase) {
       if (isZeroInitializable(member.cxxRecordDecl))
         continue;
-      zeroInitializable = false;
+      setZeroInitializable(false);
       if (member.kind == MemberInfo::InfoKind::Base)
-        zeroInitializableAsBase = false;
+        setZeroInitializableAsBase(false);
     }
   }
 }
 
 void CIRRecordLowering::determinePacked(bool nvBaseType) {
-  if (packed)
+  if (getPacked())
     return;
   CharUnits alignment = CharUnits::One();
   CharUnits nvAlignment = CharUnits::One();
@@ -810,7 +825,7 @@ void CIRRecordLowering::determinePacked(bool nvBaseType) {
     // If any member falls at an offset that it not a multiple of its alignment,
     // then the entire record must be packed.
     if (!member.offset.isMultipleOf(getMemberAlignment(member.data)))
-      packed = true;
+      setPacked(true);
     if (member.offset < nvSize)
       nvAlignment = std::max(nvAlignment, getMemberAlignment(member.data));
     alignment = std::max(alignment, getMemberAlignment(member.data));
@@ -818,14 +833,14 @@ void CIRRecordLowering::determinePacked(bool nvBaseType) {
   // If the size of the record (the capstone's offset) is not a multiple of the
   // record's alignment, it must be packed.
   if (!members.back().offset.isMultipleOf(alignment))
-    packed = true;
+    setPacked(true);
   // If the non-virtual sub-object is not a multiple of the non-virtual
   // sub-object's alignment, it must be packed.  We cannot have a packed
   // non-virtual sub-object and an unpacked complete object or vise versa.
   if (!nvSize.isMultipleOf(nvAlignment))
-    packed = true;
+    setPacked(true);
   // Update the alignment of the sentinel.
-  if (!packed)
+  if (!getPacked())
     members.back().data = getUIntNType(astContext.toBits(alignment));
 }
 
@@ -850,8 +865,8 @@ void CIRRecordLowering::insertPadding() {
     CharUnits offset = member.offset;
     assert(offset >= size);
     // Insert padding if we need to.
-    if (offset != size.alignTo(packed ? CharUnits::One()
-                                      : getMemberAlignment(member.data)))
+    if (offset != size.alignTo(getPacked() ? CharUnits::One()
+                                           : getMemberAlignment(member.data)))
       padding.push_back(std::make_pair(size, offset - size));
     size = offset + getSize(member.data);
   }
@@ -913,12 +928,13 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
     // union is empty, so a zero-data union does not spuriously qualify).
     if (lowering.astRecordLayout.getNonVirtualSize() !=
         lowering.astRecordLayout.getSize()) {
-      CIRRecordLowering baseLowering(*this, rd, /*Packed=*/lowering.packed);
+      CIRRecordLowering baseLowering(*this, rd,
+                                     /*Packed=*/lowering.getPacked());
       baseLowering.lower(/*nonVirtualBaseType=*/true);
       std::string baseIdentifier = getRecordTypeName(rd, ".base");
       baseTy = builder.getCompleteNamedRecordType(
-          baseLowering.getFieldTypes(), baseLowering.packed, baseIdentifier,
-          baseLowering.getFieldKinds());
+          baseLowering.getFieldTypes(), baseLowering.getPacked(),
+          baseIdentifier, baseLowering.getFieldKinds());
       // TODO(cir): add something like addRecordTypeName
 
       // BaseTy and Ty must agree on their packedness for getCIRFieldNo to work
@@ -927,8 +943,9 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
       // base subobject but the full size for the complete object, so the two
       // can legitimately disagree.  (Classic CodeGen derives both from the data
       // size and so needs no such exemption.)
-      assert((rd->isUnion() || lowering.packed == baseLowering.packed) &&
-             "Non-virtual and complete types must agree on packedness");
+      assert(
+          (rd->isUnion() || lowering.getPacked() == baseLowering.getPacked()) &&
+          "Non-virtual and complete types must agree on packedness");
       // Emptiness is a property of the decl, so the base subobject must answer
       // the same way the complete object does.  The two are not comparable
       // mark by mark: they see different sizes and so different tail padding.
@@ -942,8 +959,8 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
   // signifies that the type is no longer opaque and record layout is complete,
   // but we may need to recursively layout rd while laying D out as a base type.
   assert(!cir::MissingFeatures::astRecordDeclAttr());
-  ty->complete(lowering.getFieldTypes(), lowering.packed, lowering.unionPadding,
-               lowering.getFieldKinds());
+  ty->complete(lowering.getFieldTypes(), lowering.getPacked(),
+               lowering.unionPadding, lowering.getFieldKinds());
 
   // The marks exist so that emptiness can be read off the type, so check that
   // answer against the AST predicate on every record CIRGen lays out.  This
@@ -972,7 +989,8 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
 
   auto rl = std::make_unique<CIRGenRecordLayout>(
       ty ? *ty : cir::RecordType{}, baseTy ? baseTy : cir::RecordType{},
-      (bool)lowering.zeroInitializable, (bool)lowering.zeroInitializableAsBase);
+      (bool)lowering.getZeroInitializable(),
+      (bool)lowering.getZeroInitializableAsBase());
 
   rl->nonVirtualBases.swap(lowering.nonVirtualBases);
   rl->completeObjectVirtualBases.swap(lowering.virtualBases);
@@ -1089,7 +1107,7 @@ void CIRRecordLowering::lowerUnion(bool nonVirtualBaseType) {
 
   if (firstNamedMemberItr != recordDecl->fields().end() &&
       !isZeroInitializable(*firstNamedMemberItr))
-    zeroInitializable = zeroInitializableAsBase = false;
+    setZeroInitializable(setZeroInitializableAsBase(false));
 
   // If we have no candidates for storage, we are JUST padding.
   if (getFieldTypes().empty()) {
@@ -1129,7 +1147,7 @@ void CIRRecordLowering::lowerUnion(bool nonVirtualBaseType) {
     // Else we just add padding normally.
     appendPaddingBytes(layoutSize - getSize(storageType));
   }
-  packed = !layoutSize.isMultipleOf(getMemberAlignment(storageType));
+  setPacked(!layoutSize.isMultipleOf(getMemberAlignment(storageType)));
 }
 
 /// The AAPCS that defines that, when possible, bit-fields should
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 270b8a6a539ba..27df6eb104efe 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -648,7 +648,7 @@ void CIRGenFunction::startThunk(cir::FuncOp fn, GlobalDecl gd,
                                 bool isUnprototyped) {
   assert(!curGD.getDecl() && "curGD was already set!");
   curGD = gd;
-  curFuncIsThunk = true;
+  setCurFuncIsThunk(true);
 
   // Build FunctionArgs.
   const CXXMethodDecl *md = cast<CXXMethodDecl>(gd.getDecl());
diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
index aaacedeff1e74..c1f01ff8b777d 100644
--- a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
@@ -712,7 +712,7 @@ static std::optional<FunctionClassification> classifyX86_64Signature(
   };
 
   FunctionClassification fc;
-  fc.returnsVoid = voidRet;
+  fc.setReturnsVoid(voidRet);
   mlir::Type origRet = voidRet ? mlir::Type() : retCIR;
   std::optional<ArgClassification> retAc =
       convertABIArgInfo(fi->getReturnInfo(), ctx, origRet);
@@ -880,7 +880,7 @@ static std::optional<FunctionClassification>
 withReturnVoidness(std::optional<FunctionClassification> fc,
                    mlir::Type returnType) {
   if (fc)
-    fc->returnsVoid = mlir::isa<cir::VoidType>(returnType);
+    fc->setReturnsVoid(mlir::isa<cir::VoidType>(returnType));
   return fc;
 }
 
diff --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h
index 5337a5f7a1b4a..da16bb3b358e1 100644
--- a/clang/lib/CodeGen/BackendConsumer.h
+++ b/clang/lib/CodeGen/BackendConsumer.h
@@ -13,6 +13,7 @@
 #include "clang/CodeGen/CodeGenAction.h"
 #include "clang/CodeGen/ModuleLinker.h"
 #include "clang/CodeGenUtils/BackendDiagnosticHandler.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "llvm/Support/Timer.h"
 
@@ -35,13 +36,14 @@ class BackendConsumer : public ASTConsumer {
   llvm::Timer LLVMIRGeneration;
   unsigned LLVMIRGenerationRefCount = 0;
 
-  bool TimerIsEnabled = false;
+  bool getTimerIsEnabled() const { return LinkModules.getFlag(0); }
+  void setTimerIsEnabled(bool Value) { LinkModules.setFlag(0, Value); }
 
   BackendAction Action;
 
   std::unique_ptr<CodeGenerator> Gen;
 
-  SmallVector<LinkModule, 4> LinkModules;
+  llvm::SmallVectorWithFlags<LinkModule, 4> LinkModules;
 
   // Translates LLVM backend diagnostics into clang diagnostics; shared with
   // CIR so that both LLVM-emitting pipelines report backend diagnostics
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c93375ff3a18e..42971127111e8 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3382,14 +3382,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     }
 
     // Nested builtin_preserve_access_index() not supported
-    if (IsInPreservedAIRegion) {
+    if (getIsInPreservedAIRegion()) {
       CGM.Error(E->getExprLoc(), "nested builtin_preserve_access_index() not supported");
       return RValue::get(EmitScalarExpr(E->getArg(0)));
     }
 
-    IsInPreservedAIRegion = true;
+    setIsInPreservedAIRegion(true);
     Value *Res = EmitScalarExpr(E->getArg(0));
-    IsInPreservedAIRegion = false;
+    setIsInPreservedAIRegion(false);
     return RValue::get(Res);
   }
 
diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp
index ac2ed9a109c4f..bd2145658ecb2 100644
--- a/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/clang/lib/CodeGen/CGCUDANV.cpp
@@ -20,6 +20,7 @@
 #include "clang/Basic/Cuda.h"
 #include "clang/CodeGen/CodeGenABITypes.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Frontend/Offloading/Utility.h"
 #include "llvm/IR/BasicBlock.h"
@@ -85,9 +86,15 @@ class CGNVCUDARuntime : public CGCUDARuntime {
     llvm::GlobalVariable *Shadow;
     std::string DeviceName;
   };
-  llvm::SmallVector<OffloadProfSectionShadowInfo, 16> OffloadProfSectionShadows;
+  llvm::SmallVectorWithFlags<OffloadProfSectionShadowInfo, 16>
+      OffloadProfSectionShadows;
   /// Whether we generate relocatable device code.
-  bool RelocatableDeviceCode;
+  bool getRelocatableDeviceCode() const {
+    return OffloadProfSectionShadows.getFlag(0);
+  }
+  void setRelocatableDeviceCode(bool Value) {
+    OffloadProfSectionShadows.setFlag(0, Value);
+  }
   /// Mangle context for device.
   std::unique_ptr<MangleContext> DeviceMC;
 
@@ -247,7 +254,9 @@ static std::unique_ptr<MangleContext> InitDeviceMC(CodeGenModule &CGM) {
 CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
     : CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
       TheModule(CGM.getModule()),
-      RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode),
+      OffloadProfSectionShadows(
+          decltype(this->OffloadProfSectionShadows)::withFlags(
+              unsigned(bool(CGM.getLangOpts().GPURelocatableDeviceCode)))),
       DeviceMC(InitDeviceMC(CGM)) {
   IntTy = CGM.IntTy;
   SizeTy = CGM.SizeTy;
@@ -849,15 +858,15 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
       CGM.getCodeGenOpts().OffloadBinaryToEmbedFile;
   if (CudaGpuBinaryFileName.empty() && !IsHIP)
     return nullptr;
-  if ((IsHIP || (IsCUDA && !RelocatableDeviceCode)) && EmittedKernels.empty() &&
-      DeviceVars.empty())
+  if ((IsHIP || (IsCUDA && !getRelocatableDeviceCode())) &&
+      EmittedKernels.empty() && DeviceVars.empty())
     return nullptr;
 
   // void __{cuda|hip}_register_globals(void* handle);
   llvm::Function *RegisterGlobalsFunc = makeRegisterGlobalsFn();
   // We always need a function to pass in as callback. Create a dummy
   // implementation if we don't need to register anything.
-  if (RelocatableDeviceCode && !RegisterGlobalsFunc)
+  if (getRelocatableDeviceCode() && !RegisterGlobalsFunc)
     RegisterGlobalsFunc = makeDummyFunction(getRegisterGlobalsFnTy());
 
   // void ** __{cuda|hip}RegisterFatBinary(void *);
@@ -935,7 +944,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
 
     FatMagic = HIPFatMagic;
   } else {
-    if (RelocatableDeviceCode)
+    if (getRelocatableDeviceCode())
       FatbinConstantName = CGM.getTriple().isMacOSX()
                                ? "__NV_CUDA,__nv_relfatbin"
                                : "__nv_relfatbin";
@@ -983,8 +992,9 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
   // thread safety of the loaded program. Therefore we can assume sequential
   // execution of constructor functions here.
   if (IsHIP) {
-    auto Linkage = RelocatableDeviceCode ? llvm::GlobalValue::ExternalLinkage
-                                         : llvm::GlobalValue::InternalLinkage;
+    auto Linkage = getRelocatableDeviceCode()
+                       ? llvm::GlobalValue::ExternalLinkage
+                       : llvm::GlobalValue::InternalLinkage;
     llvm::BasicBlock *IfBlock =
         llvm::BasicBlock::Create(Context, "if", ModuleCtorFunc);
     llvm::BasicBlock *ExitBlock =
@@ -994,8 +1004,8 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
     GpuBinaryHandle = new llvm::GlobalVariable(
         TheModule, PtrTy, /*isConstant=*/false, Linkage,
         /*Initializer=*/
-        !RelocatableDeviceCode ? llvm::ConstantPointerNull::get(PtrTy)
-                               : nullptr,
+        !getRelocatableDeviceCode() ? llvm::ConstantPointerNull::get(PtrTy)
+                                    : nullptr,
         "__hip_gpubin_handle" + (CGM.getLangOpts().CUID.empty()
                                      ? ""
                                      : "_" + CGM.getContext().getCUIDHash()));
@@ -1029,7 +1039,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
         CtorBuilder.CreateCall(RegisterGlobalsFunc, HandleValue);
       }
     }
-  } else if (!RelocatableDeviceCode) {
+  } else if (!getRelocatableDeviceCode()) {
     // Register binary with CUDA runtime. This is substantially different in
     // default mode vs. separate compilation!
     // GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper);
@@ -1492,7 +1502,7 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() {
     return nullptr;
   }
   if (!CGM.getLangOpts().CUDANVCCABI &&
-      (CGM.getLangOpts().OffloadViaLLVM || RelocatableDeviceCode))
+      (CGM.getLangOpts().OffloadViaLLVM || getRelocatableDeviceCode()))
     createOffloadingEntries();
   else
     return makeModuleCtorFunction();
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 1f4fd55060d39..ae3ff1a9efe05 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4478,7 +4478,7 @@ void CodeGenFunction::EmitFunctionEpilog(
         // Reuse the debug location from the store unless there is
         // cleanup code to be emitted between the store and return
         // instruction.
-        if (EmitRetDbgLoc && !AutoreleaseResult)
+        if (EmitRetDbgLoc && !getAutoreleaseResult())
           RetDbgLoc = SI->getDebugLoc();
         // Get the stored value and nuke the now-dead store.
         RV = SI->getValueOperand();
@@ -4497,7 +4497,7 @@ void CodeGenFunction::EmitFunctionEpilog(
 
     // In ARC, end functions that return a retainable type with a call
     // to objc_autoreleaseReturnValue.
-    if (AutoreleaseResult) {
+    if (getAutoreleaseResult()) {
 #ifndef NDEBUG
       // Type::isObjCRetainabletype has to be called on a QualType that hasn't
       // been stripped of the typedefs, so we cannot use RetTy here. Get the
@@ -4722,7 +4722,7 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
   }
 
   // Deactivate the cleanup for the callee-destructed param that was pushed.
-  if (type->isRecordType() && !CurFuncIsThunk &&
+  if (type->isRecordType() && !getCurFuncIsThunk() &&
       type->castAsRecordDecl()->isParamDestroyedInCallee() &&
       param->needsDestruction(getContext())) {
     EHScopeStack::stable_iterator cleanup =
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 2901233638ffe..7f68ff493632c 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -27,6 +27,7 @@
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGenUtils/ClassUtils.h"
 #include "clang/CodeGenUtils/RecordLayoutUtils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Support/SaveAndRestore.h"
@@ -1005,7 +1006,7 @@ class ConstructorMemcpyizer : public FieldMemcpyizer {
   // Returns true if a CXXCtorInitializer represents a member initialization
   // that can be rolled into a memcpy.
   bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {
-    if (!MemcpyableCtor)
+    if (!getMemcpyableCtor())
       return false;
     FieldDecl *Field = MemberInit->getMember();
     assert(Field && "No field for member init.");
@@ -1032,10 +1033,10 @@ class ConstructorMemcpyizer : public FieldMemcpyizer {
                         FunctionArgList &Args)
       : FieldMemcpyizer(CGF, CD->getParent(),
                         getTrivialCopySource(CGF, CD, Args)),
-        ConstructorDecl(CD),
-        MemcpyableCtor(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
-                       CGF.getLangOpts().getGC() == LangOptions::NonGC),
-        Args(Args) {}
+        ConstructorDecl(CD), Args(Args),
+        AggregatedInits(decltype(this->AggregatedInits)::withFlags(
+            unsigned(bool(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
+                          CGF.getLangOpts().getGC() == LangOptions::NonGC)))) {}
 
   void addMemberInitializer(CXXCtorInitializer *MemberInit) {
     if (isMemberInitMemcpyable(MemberInit)) {
@@ -1089,9 +1090,10 @@ class ConstructorMemcpyizer : public FieldMemcpyizer {
 
 private:
   const CXXConstructorDecl *ConstructorDecl;
-  bool MemcpyableCtor;
+  bool getMemcpyableCtor() const { return AggregatedInits.getFlag(0); }
+  void setMemcpyableCtor(bool Value) { AggregatedInits.setFlag(0, Value); }
   FunctionArgList &Args;
-  SmallVector<CXXCtorInitializer *, 16> AggregatedInits;
+  llvm::SmallVectorWithFlags<CXXCtorInitializer *, 16> AggregatedInits;
 };
 
 class AssignmentMemcpyizer : public FieldMemcpyizer {
@@ -2910,7 +2912,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
                                          llvm::Value *VTable,
                                          CFITypeCheckKind TCK,
                                          SourceLocation Loc) {
-  assert(IsSanitizerScope);
+  assert(getIsSanitizerScope());
 
   if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
       !CGM.HasHiddenLTOVisibility(RD))
diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h
index fd8206fbccfe1..73ead570d8c75 100644
--- a/clang/lib/CodeGen/CGCleanup.h
+++ b/clang/lib/CodeGen/CGCleanup.h
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
 
 #include "EHScopeStack.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "Address.h"
 #include "clang/CodeGenUtils/EHPersonality.h"
@@ -284,20 +285,21 @@ class alignas(8) EHCleanupScope : public EHScope {
   /// Cleanups should mark these allocas as 'used' if the cleanup is
   /// emitted, otherwise these instructions would be erased.
   struct AuxillaryAllocas {
-    SmallVector<llvm::Instruction *, 1> AuxAllocas;
-    bool used = false;
+    llvm::SmallVectorWithFlags<llvm::Instruction *, 1> AuxAllocas;
+    bool getUsed() const { return AuxAllocas.getFlag(0); }
+    void setUsed(bool Value) { AuxAllocas.setFlag(0, Value); }
 
     // Records a potentially unused instruction to be erased later.
     void Add(llvm::AllocaInst *Alloca) { AuxAllocas.push_back(Alloca); }
 
     // Mark all recorded instructions as used. These will not be erased later.
     void MarkUsed() {
-      used = true;
+      setUsed(true);
       AuxAllocas.clear();
     }
 
     ~AuxillaryAllocas() {
-      if (used)
+      if (getUsed())
         return;
       llvm::SetVector<llvm::Instruction *> Uses;
       for (auto *Inst : llvm::reverse(AuxAllocas))
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index 2f162519139e0..a8e959a7abf87 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -928,7 +928,7 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
   GetReturnObjectManager GroManager(*this, S);
   CurCoro.Data->SuspendBB =
       GroManager.DirectEmit ? RetBB : createBasicBlock("pre.gvo.conv");
-  assert(ShouldEmitLifetimeMarkers &&
+  assert(getShouldEmitLifetimeMarkers() &&
          "Must emit lifetime intrinsics for coroutines");
 
   // Backend is allowed to elide memory allocations, to help it, emit
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 93428777b9b24..472e6cfa4c2d4 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -6976,11 +6976,11 @@ SanitizerDebugLocation::SanitizerDebugLocation(
     SanitizerHandler Handler)
     : CGF(CGF),
       Apply(*CGF, CGF->SanitizerAnnotateDebugInfo(Ordinals, Handler)) {
-  assert(!CGF->IsSanitizerScope);
-  CGF->IsSanitizerScope = true;
+  assert(!CGF->getIsSanitizerScope());
+  CGF->setIsSanitizerScope(true);
 }
 
 SanitizerDebugLocation::~SanitizerDebugLocation() {
-  assert(CGF->IsSanitizerScope);
-  CGF->IsSanitizerScope = false;
+  assert(CGF->getIsSanitizerScope());
+  CGF->setIsSanitizerScope(false);
 }
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 019b7ac22272e..934e59a164ed9 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1366,7 +1366,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
 /// Emit a lifetime.begin marker if some criteria are satisfied.
 /// \return whether the marker was emitted.
 bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
-  if (!ShouldEmitLifetimeMarkers)
+  if (!getShouldEmitLifetimeMarkers())
     return false;
 
   assert(Addr->getType()->getPointerAddressSpace() ==
@@ -1378,7 +1378,7 @@ bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
 }
 
 void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
-  if (!ShouldEmitLifetimeMarkers)
+  if (!getShouldEmitLifetimeMarkers())
     return;
 
   assert(Addr->getType()->getPointerAddressSpace() ==
@@ -1727,7 +1727,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
     }
 
     if (!VarAllocated) {
-      if (!DidCallStackSave) {
+      if (!getDidCallStackSave()) {
         // Save the stack.
         Address Stack =
             CreateDefaultAlignTempAlloca(AllocaInt8PtrTy, "saved_stack");
@@ -1736,7 +1736,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
         assert(V->getType() == AllocaInt8PtrTy);
         Builder.CreateStore(V, Stack);
 
-        DidCallStackSave = true;
+        setDidCallStackSave(true);
 
         // Push a cleanup block and restore the stack there.
         // FIXME: in general circumstances, this should be an EH cleanup.
@@ -2810,7 +2810,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
     // Push a destructor cleanup for this parameter if the ABI requires it.
     // Don't push a cleanup in a thunk for a method that will also emit a
     // cleanup.
-    if (Ty->isRecordType() && !CurFuncIsThunk &&
+    if (Ty->isRecordType() && !getCurFuncIsThunk() &&
         Ty->castAsRecordDecl()->isParamDestroyedInCallee()) {
       if (QualType::DestructionKind DtorKind =
               D.needsDestruction(getContext())) {
@@ -2844,7 +2844,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
   LValue lv = MakeAddrLValue(DeclPtr, Ty);
   // If this is a thunk, don't bother with ARC lifetime management.
   // The true implementation will take care of that.
-  if (IsScalar && !CurFuncIsThunk) {
+  if (IsScalar && !getCurFuncIsThunk()) {
     Qualifiers qs = Ty.getQualifiers();
     if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
       // We honor __attribute__((ns_consumed)) for types with lifetime.
@@ -2927,7 +2927,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
 
   // Emit debug info for param declarations in non-thunk functions.
   if (CGDebugInfo *DI = getDebugInfo()) {
-    if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk &&
+    if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !getCurFuncIsThunk() &&
         !NoDebugInfo) {
       llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable(
           &D, AllocaPtr.getPointer(), ArgNo, Builder, UseIndirectDebugAddress);
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 566f7e5d64f3e..cc2143b5103b1 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -838,7 +838,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
 
   // When we import C++20 modules, we must run their initializers first.
   SmallVector<llvm::Function *, 8> ModuleInits;
-  if (CXX20ModuleInits)
+  if (getCXX20ModuleInits())
     for (Module *M : CodeGenUtils::importedModulesToInitialize(
              getContext().getCurrentNamedModule(),
              ImportedModules.getArrayRef())) {
@@ -912,7 +912,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
   // with priority emitted above.  Module implementation units behave the same
   // way as a non-modular TU with imports.
   llvm::Function *Fn;
-  if (CXX20ModuleInits && getContext().getCurrentNamedModule() &&
+  if (getCXX20ModuleInits() && getContext().getCurrentNamedModule() &&
       !getContext().getCurrentNamedModule()->isModuleImplementation()) {
     SmallString<256> InitFnName;
     llvm::raw_svector_ostream Out(InitFnName);
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 78cc7ab2b8be0..43e181fb42ae9 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -1598,7 +1598,7 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
     QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
     llvm::Value *FP = nullptr;
     // If CFG.IsOutlinedSEHHelper is true, then we are within a finally block.
-    if (CGF.IsOutlinedSEHHelper) {
+    if (CGF.getIsOutlinedSEHHelper()) {
       FP = &CGF.CurFn->arg_begin()[1];
     } else {
       llvm::Function *LocalAddrFn =
@@ -1941,7 +1941,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
   llvm::Function *Fn = llvm::Function::Create(
       FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
 
-  IsOutlinedSEHHelper = true;
+  setIsOutlinedSEHHelper(true);
 
   StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
                 OutlinedStmt->getBeginLoc(), OutlinedStmt->getBeginLoc());
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 927652c460922..3b510aeaf4460 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -622,7 +622,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
       break;
 
     case SD_FullExpression: {
-      if (!ShouldEmitLifetimeMarkers)
+      if (!getShouldEmitLifetimeMarkers())
         break;
 
       // Avoid creating a conditional cleanup just to hold an llvm.lifetime.end
@@ -4355,7 +4355,7 @@ void CodeGenFunction::EmitCheck(
     ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked,
     SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs,
     ArrayRef<llvm::Value *> DynamicArgs, const TrapReason *TR) {
-  assert(IsSanitizerScope);
+  assert(getIsSanitizerScope());
   assert(Checked.size() > 0);
   assert(CheckHandler >= 0 &&
          size_t(CheckHandler) < std::size(SanitizerHandlers));
@@ -5003,7 +5003,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
   llvm::Value *eltPtr;
   auto LastIndex = dyn_cast<llvm::ConstantInt>(indices.back());
   if (!LastIndex ||
-      (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) {
+      (!CGF.getIsInPreservedAIRegion() && !IsPreserveAIArrayBase(CGF, Base))) {
     addr = emitArraySubscriptGEP(CGF, addr, indices,
                                  arrayType ? CGF.ConvertTypeForMem(*arrayType)
                                            : nullptr,
@@ -6007,7 +6007,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
     if (hasBPFPreserveStaticOffset(rec))
       Addr = wrapWithBPFPreserveStaticOffset(*this, Addr);
     if (!UseVolatile) {
-      if (!IsInPreservedAIRegion &&
+      if (!getIsInPreservedAIRegion() &&
           (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
         if (Idx != 0) {
           // For structs, we GEP to the field that the record layout suggests.
@@ -6094,7 +6094,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
       // a barrier every time CXXRecord field with vptr is referenced.
       addr = Builder.CreateLaunderInvariantGroup(addr);
 
-    if (IsInPreservedAIRegion ||
+    if (getIsInPreservedAIRegion() ||
         (getDebugInfo() && rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
       // Remember the original union field index
       llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(),
@@ -6109,7 +6109,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
     if (FieldType->isReferenceType())
       addr = addr.withElementType(CGM.getTypes().ConvertTypeForMem(FieldType));
   } else {
-    if (!IsInPreservedAIRegion &&
+    if (!getIsInPreservedAIRegion() &&
         (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>()))
       // For structs, we GEP to the field that the record layout suggests.
       addr = emitAddrOfFieldStorage(*this, addr, field, IsInBounds);
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index e2ec07bbae711..bc0c58e5e2264 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -29,6 +29,7 @@
 #include "clang/CodeGenUtils/RecordLayoutUtils.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
@@ -96,7 +97,7 @@ class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
   /// natural layout), but need not. Gaps between elements are implicitly
   /// considered to be filled with undef.
   llvm::SmallVector<llvm::Constant*, 32> Elems;
-  llvm::SmallVector<CharUnits, 32> Offsets;
+  llvm::SmallVectorWithFlags<CharUnits, 32> Offsets;
 
   /// The size of the constant (the maximum end offset of any added element).
   /// May be larger than the end of Elems.back() if we split the last element
@@ -105,7 +106,11 @@ class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
 
   /// This is true only if laying out Elems in order as the elements of a
   /// non-packed LLVM struct will give the correct layout.
-  bool NaturalLayout = true;
+  bool getNaturalLayout() const { return !Offsets.getFlag(0); }
+  bool setNaturalLayout(bool Value) {
+    Offsets.setFlag(0, !Value);
+    return Value;
+  }
 
   bool split(size_t Index, CharUnits Hint);
   std::optional<size_t> splitAt(CharUnits Pos);
@@ -142,7 +147,7 @@ class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
   /// even if we can't represent it as that type.
   llvm::Constant *build(llvm::Type *DesiredTy, bool AllowOversized) const {
     return buildFrom(CGM, Elems, Offsets, CharUnits::Zero(), Size,
-                     NaturalLayout, DesiredTy, AllowOversized);
+                     getNaturalLayout(), DesiredTy, AllowOversized);
   }
 };
 
@@ -160,7 +165,7 @@ bool ConstantAggregateBuilder::add(llvm::Constant *C, CharUnits Offset,
     CharUnits Align = getAlignment(C);
     CharUnits AlignedSize = Size.alignTo(Align);
     if (AlignedSize > Offset || Offset.alignTo(Align) != Offset)
-      NaturalLayout = false;
+      setNaturalLayout(false);
     else if (AlignedSize < Offset) {
       Elems.push_back(getPadding(Offset - Size));
       Offsets.push_back(Size);
@@ -187,7 +192,7 @@ bool ConstantAggregateBuilder::add(llvm::Constant *C, CharUnits Offset,
   replace(Elems, *FirstElemToReplace, *LastElemToReplace, {C});
   replace(Offsets, *FirstElemToReplace, *LastElemToReplace, {Offset});
   Size = std::max(Size, Offset + CSize);
-  NaturalLayout = false;
+  setNaturalLayout(false);
   return true;
 }
 
@@ -327,7 +332,7 @@ std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits Pos) {
 /// Hint indicates the location at which we'd like to split, but may be
 /// ignored.
 bool ConstantAggregateBuilder::split(size_t Index, CharUnits Hint) {
-  NaturalLayout = false;
+  setNaturalLayout(false);
   llvm::Constant *C = Elems[Index];
   CharUnits Offset = Offsets[Index];
 
@@ -1939,7 +1944,7 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
           return CGM.EmitNullConstant(D.getType());
       }
   }
-  InConstantContext = D.hasConstantInitialization();
+  setInConstantContext(D.hasConstantInitialization());
 
   QualType destType = D.getType();
   const Expr *E = D.getInit();
@@ -2126,7 +2131,8 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
   if (destType->isReferenceType())
     Success = E->EvaluateAsLValue(Result, CGM.getContext());
   else
-    Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);
+    Success =
+        E->EvaluateAsRValue(Result, CGM.getContext(), isInConstantContext());
 
   if (Success && !Result.HasSideEffects)
     return tryEmitPrivate(Result.Val, destType);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index db2b7a4ad1fce..539db62461104 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1909,7 +1909,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
 void ScalarExprEmitter::EmitBinOpCheck(
     ArrayRef<std::pair<Value *, SanitizerKind::SanitizerOrdinal>> Checks,
     const BinOpInfo &Info) {
-  assert(CGF.IsSanitizerScope);
+  assert(CGF.getIsSanitizerScope());
   SanitizerHandler Check;
   SmallVector<llvm::Constant *, 4> StaticData;
   SmallVector<llvm::Value *, 2> DynamicData;
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index cb738d060c24a..219ac26301a2d 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1233,7 +1233,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
     Builder.CreateStore(ivarVal, ReturnValue.withElementType(bitcastType));
 
     // Make sure we don't do an autorelease.
-    AutoreleaseResult = false;
+    setAutoreleaseResult(false);
     return;
   }
 
@@ -1290,7 +1290,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
     EmitReturnOfRValue(RV, propType);
 
     // objc_getProperty does an autorelease, so we should suppress ours.
-    AutoreleaseResult = false;
+    setAutoreleaseResult(false);
 
     return;
   }
@@ -1356,7 +1356,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
           } else
             value = EmitLoadOfLValue(LV, SourceLocation()).getScalarVal();
 
-          AutoreleaseResult = false;
+          setAutoreleaseResult(false);
         }
 
         value = Builder.CreateBitCast(
@@ -1777,7 +1777,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
   // Emit .cxx_construct.
   if (ctor) {
     // Suppress the final autorelease in ARC.
-    AutoreleaseResult = false;
+    setAutoreleaseResult(false);
 
     for (const auto *IvarInit : IMP->inits()) {
       FieldDecl *Field = IvarInit->getAnyMember();
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 7bfe0e0249407..d3b0b61da78cf 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -33,6 +33,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -2948,18 +2949,20 @@ class IvarLayoutBuilder {
   CharUnits InstanceEnd;
 
   /// Whether we're generating the strong layout or the weak layout.
-  bool ForStrongLayout;
+  bool getForStrongLayout() const { return IvarsInfo.getFlag(0); }
+  void setForStrongLayout(bool Value) { IvarsInfo.setFlag(0, Value); }
 
   /// Whether the offsets in IvarsInfo might be out-of-order.
-  bool IsDisordered = false;
+  bool getIsDisordered() const { return IvarsInfo.getFlag(1); }
+  void setIsDisordered(bool Value) { IvarsInfo.setFlag(1, Value); }
 
-  llvm::SmallVector<IvarInfo, 8> IvarsInfo;
+  llvm::SmallVectorWithFlags<IvarInfo, 8, 2> IvarsInfo;
 
 public:
   IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
                     CharUnits instanceEnd, bool forStrongLayout)
       : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
-        ForStrongLayout(forStrongLayout) {}
+        IvarsInfo(decltype(IvarsInfo)::withFlags(unsigned(forStrongLayout))) {}
 
   void visitRecord(const RecordType *RT, CharUnits offset);
 
@@ -3044,7 +3047,7 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
     // Block fields are not necessarily ordered; if we detect that we're
     // adding them out-of-order, make sure we sort later.
     if (fieldOffset < lastFieldOffset)
-      IsDisordered = true;
+      setIsDisordered(true);
     lastFieldOffset = fieldOffset;
 
     // __block variables are passed by their descriptor address.
@@ -4693,7 +4696,7 @@ void CodeGenFunction::StartObjCDirectPreconditionThunk(
   // call. Both hold whether we tail-call or not. Class realization could in
   // theory invalidate parameters, but we assume that doesn't happen in
   // practice.
-  CurFuncIsThunk = true;
+  setCurFuncIsThunk(true);
 
   // Build argument list for StartFunction.
   // We must include all parameters to match the thunk's LLVM function type.
@@ -4732,7 +4735,7 @@ void CodeGenFunction::FinishObjCDirectPreconditionThunk() {
   // Disable the final ARC autorelease.
   // Thunk functions are tailcall to actual implementation, so it doesn't need
   // to worry about ARC.
-  AutoreleaseResult = false;
+  setAutoreleaseResult(false);
 
   // Clear these to restore the invariants expected by
   // StartFunction/FinishFunction.
@@ -6197,7 +6200,7 @@ void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
   // If this is a union, remember that we had one, because it might mess
   // up the ordering of layout entries.
   if (RD->isUnion())
-    IsDisordered = true;
+    setIsDisordered(true);
 
   const ASTRecordLayout *recLayout = nullptr;
   visitAggregate(RD->field_begin(), RD->field_end(), offset,
@@ -6281,8 +6284,8 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field,
   Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
 
   // If it matches what we're looking for, add an entry.
-  if ((ForStrongLayout && GCAttr == Qualifiers::Strong) ||
-      (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
+  if ((getForStrongLayout() && GCAttr == Qualifiers::Strong) ||
+      (!getForStrongLayout() && GCAttr == Qualifiers::Weak)) {
     assert(CGM.getContext().getTypeSizeInChars(fieldType) ==
            CGM.getPointerSize());
     IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
@@ -6305,7 +6308,7 @@ IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
 
   // Sort the ivar info on byte position in case we encounterred a
   // union nested in the ivar list.
-  if (IsDisordered) {
+  if (getIsDisordered()) {
     // This isn't a stable sort, but our algorithm should handle it fine.
     llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
   } else {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index d24eac79f2ff1..24226e2e29959 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1062,7 +1062,7 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
   // The user forces the compiler to behave as if omp requires
   // unified_shared_memory was given.
   if (CGM.getLangOpts().OpenMPForceUSM) {
-    HasRequiresUnifiedSharedMemory = true;
+    setHasRequiresUnifiedSharedMemory(true);
     OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(true);
   }
 }
@@ -4049,7 +4049,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
     FreeAgentFlag = 0x80,
     TransparentFlag = 0x100,
   };
-  unsigned Flags = Data.Tied ? TiedFlag : 0;
+  unsigned Flags = Data.getTied() ? TiedFlag : 0;
   bool NeedsCleanup = false;
   if (!Privates.empty()) {
     NeedsCleanup =
@@ -4874,7 +4874,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
   }
   auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
                         &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
-    if (!Data.Tied) {
+    if (!Data.getTied()) {
       auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
       LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
       CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
@@ -4904,7 +4904,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
     DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
     DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
     DepWaitTaskArgs[6] =
-        llvm::ConstantInt::get(CGF.Int32Ty, Data.HasNowaitClause);
+        llvm::ConstantInt::get(CGF.Int32Ty, Data.getHasNowaitClause());
   }
   auto &M = CGM.getModule();
   auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
@@ -5026,7 +5026,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
           ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
                                       /*isSigned=*/false)
           : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0)};
-  if (Data.HasModifier)
+  if (Data.getHasModifier())
     TaskArgs.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 1));
 
   TaskArgs.push_back(Result.TaskDupFn
@@ -5034,7 +5034,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
                                Result.TaskDupFn, CGF.VoidPtrTy)
                          : llvm::ConstantPointerNull::get(CGF.VoidPtrTy));
   CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
-                          CGM.getModule(), Data.HasModifier
+                          CGM.getModule(), Data.getHasModifier()
                                                ? OMPRTL___kmpc_taskloop_5
                                                : OMPRTL___kmpc_taskloop),
                       TaskArgs);
@@ -5509,8 +5509,8 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
   if (!CGF.HaveInsertPoint())
     return;
 
-  bool WithNowait = Options.WithNowait;
-  bool SimpleReduction = Options.SimpleReduction;
+  bool WithNowait = Options.getWithNowait();
+  bool SimpleReduction = Options.getSimpleReduction();
 
   // Next code should be emitted for reduction:
   //
@@ -6154,7 +6154,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
     } else
       CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
   }
-  if (Data.IsReductionWithTaskMod) {
+  if (Data.getIsReductionWithTaskMod()) {
     // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
     // is_ws, int num, void *data);
     llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
@@ -6162,7 +6162,8 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
                                                   CGM.IntTy, /*isSigned=*/true);
     llvm::Value *Args[] = {
         IdentTLoc, GTid,
-        llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0,
+        llvm::ConstantInt::get(CGM.IntTy,
+                               Data.getIsWorksharingReduction() ? 1 : 0,
                                /*isSigned=*/true),
         llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
         CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
@@ -6264,7 +6265,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
       DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
       DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
       DepWaitTaskArgs[6] =
-          llvm::ConstantInt::get(CGF.Int32Ty, Data.HasNowaitClause);
+          llvm::ConstantInt::get(CGF.Int32Ty, Data.getHasNowaitClause());
 
       CodeGenFunction::RunCleanupsScope LocalScope(CGF);
 
@@ -6466,7 +6467,7 @@ void CGOpenMPRuntime::emitTargetOutlinedFunction(
     llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
     bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
   assert(!ParentName.empty() && "Invalid target entry parent name!");
-  HasEmittedTargetRegion = true;
+  setHasEmittedTargetRegion(true);
   SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators;
   for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) {
     for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
@@ -8287,7 +8288,7 @@ class MappableExprsHandler {
     // if the stride is not a constant expression (conservatively assumed
     // non-contiguous).
     bool IsNonContiguous =
-        CombinedInfo.NonContigInfo.IsNonContiguous ||
+        CombinedInfo.NonContigInfo.getIsNonContiguous() ||
         any_of(Components, [&](const auto &Component) {
           const auto *OASE =
               dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
@@ -9458,8 +9459,8 @@ class MappableExprsHandler {
           unsigned StructBasePointersIdx =
               GroupStructBaseCurInfo.BasePointers.size();
 
-          GroupCurInfo.NonContigInfo.IsNonContiguous =
-              L.Components.back().isNonContiguous();
+          GroupCurInfo.NonContigInfo.setIsNonContiguous(
+              L.Components.back().isNonContiguous());
           generateInfoForComponentList(
               L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
               GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
@@ -11638,7 +11639,7 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
   if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
       ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
         *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
-       HasRequiresUnifiedSharedMemory)) {
+       getHasRequiresUnifiedSharedMemory())) {
     DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
     return true;
   }
@@ -11715,14 +11716,14 @@ void CGOpenMPRuntime::emitDeferredTargetDecls() const {
     if (*Res == OMPDeclareTargetDeclAttr::MT_Local ||
         ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
           *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
-         !HasRequiresUnifiedSharedMemory)) {
+         !getHasRequiresUnifiedSharedMemory())) {
       CGM.EmitGlobal(VD);
     } else {
       assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
               ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
                 *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
                 *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
-               HasRequiresUnifiedSharedMemory)) &&
+               getHasRequiresUnifiedSharedMemory())) &&
              "Expected link clause or to clause with unified memory.");
       (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
     }
@@ -11738,7 +11739,7 @@ void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
   for (const OMPClause *Clause : D->clauselists()) {
     if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
-      HasRequiresUnifiedSharedMemory = true;
+      setHasRequiresUnifiedSharedMemory(true);
       OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(true);
     } else if (const auto *AC =
                    dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
@@ -11789,25 +11790,28 @@ bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
 }
 
 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
-  return HasRequiresUnifiedSharedMemory;
+  return getHasRequiresUnifiedSharedMemory();
 }
 
 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
     CodeGenModule &CGM)
     : CGM(CGM) {
   if (CGM.getLangOpts().OpenMPIsTargetDevice) {
-    SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
-    CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
+    SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().getShouldMarkAsGlobal();
+    CGM.getOpenMPRuntime().setShouldMarkAsGlobal(false);
   }
 }
 
 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
   if (CGM.getLangOpts().OpenMPIsTargetDevice)
-    CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
+    [&] {
+      auto PackedFlagValue = SavedShouldMarkAsGlobal;
+      return CGM.getOpenMPRuntime().setShouldMarkAsGlobal(PackedFlagValue);
+    }();
 }
 
 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
-  if (!CGM.getLangOpts().OpenMPIsTargetDevice || !ShouldMarkAsGlobal)
+  if (!CGM.getLangOpts().OpenMPIsTargetDevice || !getShouldMarkAsGlobal())
     return true;
 
   const auto *D = cast<FunctionDecl>(GD.getDecl());
@@ -12718,7 +12722,7 @@ void CGOpenMPRuntime::emitOutlinedFunctionCall(
 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
   if (const auto *FD = dyn_cast<FunctionDecl>(D))
     if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
-      HasEmittedDeclareTargetRegion = true;
+      setHasEmittedDeclareTargetRegion(true);
 }
 
 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
@@ -13568,7 +13572,7 @@ void CGOpenMPSIMDRuntime::emitReduction(
     CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
     ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
     ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
-  assert(Options.SimpleReduction && "Only simple reduction is expected.");
+  assert(Options.getSimpleReduction() && "Only simple reduction is expected.");
   CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
                                  ReductionOps, Options);
 }
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index ae55295cadc14..2ced2b6238b54 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
@@ -102,7 +103,8 @@ struct OMPTaskDataTy final {
   SmallVector<const Expr *, 4> ReductionOrigs;
   SmallVector<const Expr *, 4> ReductionCopies;
   SmallVector<const Expr *, 4> ReductionOps;
-  SmallVector<CanonicalDeclPtr<const VarDecl>, 4> PrivateLocals;
+  llvm::SmallVectorWithFlags<CanonicalDeclPtr<const VarDecl>, 4, 2>
+      PrivateLocals;
   struct DependData {
     OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
     const Expr *IteratorExpr = nullptr;
@@ -111,18 +113,24 @@ struct OMPTaskDataTy final {
     DependData(OpenMPDependClauseKind DepKind, const Expr *IteratorExpr)
         : DepKind(DepKind), IteratorExpr(IteratorExpr) {}
   };
-  SmallVector<DependData, 4> Dependences;
+  llvm::SmallVectorWithFlags<DependData, 4, 4> Dependences;
   llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
   llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule;
   llvm::PointerIntPair<llvm::Value *, 1, bool> Priority;
   llvm::Value *Reductions = nullptr;
   unsigned NumberOfParts = 0;
-  bool Tied = true;
-  bool Nogroup = false;
-  bool IsReductionWithTaskMod = false;
-  bool IsWorksharingReduction = false;
-  bool HasNowaitClause = false;
-  bool HasModifier = false;
+  bool getTied() const { return !Dependences.getFlag(0); }
+  void setTied(bool Value) { Dependences.setFlag(0, !Value); }
+  bool getNogroup() const { return Dependences.getFlag(1); }
+  void setNogroup(bool Value) { Dependences.setFlag(1, Value); }
+  bool getIsReductionWithTaskMod() const { return Dependences.getFlag(2); }
+  void setIsReductionWithTaskMod(bool Value) { Dependences.setFlag(2, Value); }
+  bool getIsWorksharingReduction() const { return Dependences.getFlag(3); }
+  void setIsWorksharingReduction(bool Value) { Dependences.setFlag(3, Value); }
+  bool getHasNowaitClause() const { return PrivateLocals.getFlag(0); }
+  void setHasNowaitClause(bool Value) { PrivateLocals.setFlag(0, Value); }
+  bool getHasModifier() const { return PrivateLocals.getFlag(1); }
+  void setHasModifier(bool Value) { PrivateLocals.setFlag(1, Value); }
 };
 
 /// Class intended to support codegen of all kind of the reduction clauses.
@@ -477,7 +485,13 @@ class CGOpenMPRuntime {
   /// };
   QualType KmpDimTy;
 
-  bool ShouldMarkAsGlobal = true;
+  bool getShouldMarkAsGlobal() const {
+    return !LastprivateConditionalStack.getFlag(0);
+  }
+  bool setShouldMarkAsGlobal(bool Value) {
+    LastprivateConditionalStack.setFlag(0, !Value);
+    return Value;
+  }
   /// List of the emitted declarations.
   llvm::DenseSet<CanonicalDeclPtr<const Decl>> AlreadyEmittedTargetDecls;
   /// List of the global variables with their addresses that should not be
@@ -501,21 +515,38 @@ class CGOpenMPRuntime {
   /// Stack for list of addresses of declarations in current context marked as
   /// lastprivate conditional. The set is the union of all current stack
   /// elements.
-  llvm::SmallVector<LastprivateConditionalData, 4> LastprivateConditionalStack;
+  llvm::SmallVectorWithFlags<LastprivateConditionalData, 4, 4>
+      LastprivateConditionalStack;
 
   /// Flag for keeping track of weather a requires unified_shared_memory
   /// directive is present.
-  bool HasRequiresUnifiedSharedMemory = false;
+  bool getHasRequiresUnifiedSharedMemory() const {
+    return LastprivateConditionalStack.getFlag(1);
+  }
+  void setHasRequiresUnifiedSharedMemory(bool Value) {
+    LastprivateConditionalStack.setFlag(1, Value);
+  }
 
   /// Atomic ordering from the omp requires directive.
   llvm::AtomicOrdering RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
 
   /// Flag for keeping track of weather a target region has been emitted.
-  bool HasEmittedTargetRegion = false;
+  bool getHasEmittedTargetRegion() const {
+    return LastprivateConditionalStack.getFlag(2);
+  }
+  void setHasEmittedTargetRegion(bool Value) {
+    LastprivateConditionalStack.setFlag(2, Value);
+  }
 
   /// Flag for keeping track of weather a device routine has been emitted.
   /// Device routines are specific to the
-  bool HasEmittedDeclareTargetRegion = false;
+  bool getHasEmittedDeclareTargetRegion() const {
+    return LastprivateConditionalStack.getFlag(3);
+  }
+  bool setHasEmittedDeclareTargetRegion(bool Value) {
+    LastprivateConditionalStack.setFlag(3, Value);
+    return Value;
+  }
 
   /// Start scanning from statement \a S and emit all target regions
   /// found along the way.
@@ -1245,9 +1276,21 @@ class CGOpenMPRuntime {
                                    const DeclRefExpr *RHS);
 
   struct ReductionOptionsTy {
-    bool WithNowait;
-    bool SimpleReduction;
-    llvm::SmallVector<bool, 8> IsPrivateVarReduction;
+    ReductionOptionsTy(bool WithNowait, bool SimpleReduction,
+                       llvm::SmallVector<bool, 8> IsPrivateVarReduction,
+                       OpenMPDirectiveKind ReductionKind)
+        : IsPrivateVarReduction(unsigned(WithNowait) |
+                                    (unsigned(SimpleReduction) << 1),
+                                std::move(IsPrivateVarReduction)),
+          ReductionKind(ReductionKind) {}
+
+    bool getWithNowait() const { return IsPrivateVarReduction.getFlag(0); }
+    void setWithNowait(bool Value) { IsPrivateVarReduction.setFlag(0, Value); }
+    bool getSimpleReduction() const { return IsPrivateVarReduction.getFlag(1); }
+    void setSimpleReduction(bool Value) {
+      IsPrivateVarReduction.setFlag(1, Value);
+    }
+    llvm::SmallVectorWithFlags<bool, 8, 2> IsPrivateVarReduction;
     OpenMPDirectiveKind ReductionKind;
   };
 
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index e7322bdd0deca..6deceda66a07b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -1768,7 +1768,7 @@ void CGOpenMPRuntimeGPU::emitReduction(
   bool ParallelReduction = isOpenMPParallelDirective(Options.ReductionKind);
   bool TeamsReduction = isOpenMPTeamsDirective(Options.ReductionKind);
 
-  if (Options.SimpleReduction) {
+  if (Options.getSimpleReduction()) {
     assert(!TeamsReduction && !ParallelReduction &&
            "Invalid reduction selection in emitReduction.");
     (void)ParallelReduction;
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 0a5fd222b7d80..6364179fd9cd3 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -23,6 +23,7 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/CodeGenUtils/RecordLayoutUtils.h"
 #include "clang/CodeGenUtils/TargetUtils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
@@ -191,14 +192,24 @@ struct CGRecordLowering {
   // Helpful intermediate data-structures.
   std::vector<MemberInfo> Members;
   // Output fields, consumed by CodeGenTypes::ComputeRecordLayout.
-  SmallVector<llvm::Type *, 16> FieldTypes;
+  llvm::SmallVectorWithFlags<llvm::Type *, 16, 3> FieldTypes;
   llvm::DenseMap<const FieldDecl *, unsigned> Fields;
   llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields;
   llvm::DenseMap<const CXXRecordDecl *, unsigned> NonVirtualBases;
   llvm::DenseMap<const CXXRecordDecl *, unsigned> VirtualBases;
-  bool IsZeroInitializable : 1;
-  bool IsZeroInitializableAsBase : 1;
-  bool Packed : 1;
+  bool getIsZeroInitializable() const { return FieldTypes.getFlag(0); }
+  void setIsZeroInitializable(bool Value) { FieldTypes.setFlag(0, Value); }
+  bool getIsZeroInitializableAsBase() const { return FieldTypes.getFlag(1); }
+  bool setIsZeroInitializableAsBase(bool Value) {
+    FieldTypes.setFlag(1, Value);
+    return Value;
+  }
+  bool getPacked() const { return FieldTypes.getFlag(2); }
+  bool setPacked(bool Value) {
+    FieldTypes.setFlag(2, Value);
+    return Value;
+  }
+
 private:
   CGRecordLowering(const CGRecordLowering &) = delete;
   void operator =(const CGRecordLowering &) = delete;
@@ -210,8 +221,9 @@ CGRecordLowering::CGRecordLowering(CodeGenTypes &Types, const RecordDecl *D,
     : Types(Types), Context(Types.getContext()), D(D),
       RD(dyn_cast<CXXRecordDecl>(D)),
       Layout(Types.getContext().getASTRecordLayout(D)),
-      DataLayout(Types.getDataLayout()), IsZeroInitializable(true),
-      IsZeroInitializableAsBase(true), Packed(Packed) {}
+      DataLayout(Types.getDataLayout()),
+      FieldTypes(
+          decltype(this->FieldTypes)::withFlags((unsigned(Packed) << 2) | 3)) {}
 
 void CGRecordLowering::setBitFieldInfo(
     const FieldDecl *FD, CharUnits StartOffset, llvm::Type *StorageType) {
@@ -324,13 +336,13 @@ void CGRecordLowering::lowerUnion(bool isNonVirtualBaseType) {
         if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
           SeenNamedMember = FieldRD->findFirstNamedDataMember();
       if (SeenNamedMember && !isZeroInitializable(Field)) {
-        IsZeroInitializable = IsZeroInitializableAsBase = false;
+        setIsZeroInitializable(setIsZeroInitializableAsBase(false));
         StorageType = FieldType;
       }
     }
     // Because our union isn't zero initializable, we won't be getting a better
     // storage type.
-    if (!IsZeroInitializable)
+    if (!getIsZeroInitializable())
       continue;
     // Conditionally update our storage type if we've got a new "better" one.
     if (!StorageType ||
@@ -355,7 +367,7 @@ void CGRecordLowering::lowerUnion(bool isNonVirtualBaseType) {
          "Union's standard layout and no_unique_address layout must agree on "
          "packedness");
   if (!Layout.getDataSize().isMultipleOf(StorageAlignment))
-    Packed = true;
+    setPacked(true);
 }
 
 void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
@@ -903,18 +915,18 @@ void CGRecordLowering::accumulateVBases() {
 void CGRecordLowering::calculateZeroInit() {
   for (std::vector<MemberInfo>::const_iterator Member = Members.begin(),
                                                MemberEnd = Members.end();
-       IsZeroInitializableAsBase && Member != MemberEnd; ++Member) {
+       getIsZeroInitializableAsBase() && Member != MemberEnd; ++Member) {
     if (Member->Kind == MemberInfo::Field) {
       if (!Member->FD || isZeroInitializable(Member->FD))
         continue;
-      IsZeroInitializable = IsZeroInitializableAsBase = false;
+      setIsZeroInitializable(setIsZeroInitializableAsBase(false));
     } else if (Member->Kind == MemberInfo::Base ||
                Member->Kind == MemberInfo::VBase) {
       if (isZeroInitializable(Member->RD))
         continue;
-      IsZeroInitializable = false;
+      setIsZeroInitializable(false);
       if (Member->Kind == MemberInfo::Base)
-        IsZeroInitializableAsBase = false;
+        setIsZeroInitializableAsBase(false);
     }
   }
 }
@@ -938,7 +950,7 @@ void CGRecordLowering::checkBitfieldClipping(bool IsNonVirtualBaseType) const {
 }
 
 void CGRecordLowering::determinePacked(bool NVBaseType) {
-  if (Packed)
+  if (getPacked())
     return;
   CharUnits Alignment = CharUnits::One();
   CharUnits NVAlignment = CharUnits::One();
@@ -950,7 +962,7 @@ void CGRecordLowering::determinePacked(bool NVBaseType) {
     // If any member falls at an offset that it not a multiple of its alignment,
     // then the entire record must be packed.
     if (!Member.Offset.isMultipleOf(getAlignment(Member.Data)))
-      Packed = true;
+      setPacked(true);
     if (Member.Offset < NVSize)
       NVAlignment = std::max(NVAlignment, getAlignment(Member.Data));
     Alignment = std::max(Alignment, getAlignment(Member.Data));
@@ -958,14 +970,14 @@ void CGRecordLowering::determinePacked(bool NVBaseType) {
   // If the size of the record (the capstone's offset) is not a multiple of the
   // record's alignment, it must be packed.
   if (!Members.back().Offset.isMultipleOf(Alignment))
-    Packed = true;
+    setPacked(true);
   // If the non-virtual sub-object is not a multiple of the non-virtual
   // sub-object's alignment, it must be packed.  We cannot have a packed
   // non-virtual sub-object and an unpacked complete object or vise versa.
   if (!NVSize.isMultipleOf(NVAlignment))
-    Packed = true;
+    setPacked(true);
   // Update the alignment of the sentinel.
-  if (!Packed)
+  if (!getPacked())
     Members.back().Data = getIntNType(Context.toBits(Alignment));
 }
 
@@ -978,8 +990,8 @@ void CGRecordLowering::insertPadding() {
     CharUnits Offset = Member.Offset;
     assert(Offset >= Size);
     // Insert padding if we need to.
-    if (Offset !=
-        Size.alignTo(Packed ? CharUnits::One() : getAlignment(Member.Data)))
+    if (Offset != Size.alignTo(getPacked() ? CharUnits::One()
+                                           : getAlignment(Member.Data)))
       Padding.push_back(std::make_pair(Size, Offset - Size));
     Size = Offset + getSize(Member.Data);
   }
@@ -1061,14 +1073,15 @@ CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
   if (isa<CXXRecordDecl>(D)) {
     BaseTy = Ty;
     if (Builder.Layout.getNonVirtualSize() != Builder.Layout.getSize()) {
-      CGRecordLowering BaseBuilder(*this, D, /*Packed=*/Builder.Packed);
+      CGRecordLowering BaseBuilder(*this, D, /*Packed=*/Builder.getPacked());
       BaseBuilder.lower(/*NonVirtualBaseType=*/true);
-      BaseTy = llvm::StructType::create(
-          getLLVMContext(), BaseBuilder.FieldTypes, "", BaseBuilder.Packed);
+      BaseTy =
+          llvm::StructType::create(getLLVMContext(), BaseBuilder.FieldTypes, "",
+                                   BaseBuilder.getPacked());
       addRecordTypeName(D, BaseTy, ".base");
       // BaseTy and Ty must agree on their packedness for getLLVMFieldNo to work
       // on both of them with the same index.
-      assert(Builder.Packed == BaseBuilder.Packed &&
+      assert(Builder.getPacked() == BaseBuilder.getPacked() &&
              "Non-virtual and complete types must agree on packedness");
     }
   }
@@ -1076,11 +1089,11 @@ CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
   // Fill in the struct *after* computing the base type.  Filling in the body
   // signifies that the type is no longer opaque and record layout is complete,
   // but we may need to recursively layout D while laying D out as a base type.
-  Ty->setBody(Builder.FieldTypes, Builder.Packed);
+  Ty->setBody(Builder.FieldTypes, Builder.getPacked());
 
   auto RL = std::make_unique<CGRecordLayout>(
-      Ty, BaseTy, (bool)Builder.IsZeroInitializable,
-      (bool)Builder.IsZeroInitializableAsBase);
+      Ty, BaseTy, (bool)Builder.getIsZeroInitializable(),
+      (bool)Builder.getIsZeroInitializableAsBase());
 
   RL->NonVirtualBases.swap(Builder.NonVirtualBases);
   RL->CompleteObjectVirtualBases.swap(Builder.VirtualBases);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 05b3693138b0a..84f3352df7409 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/Assumptions.h"
 #include "llvm/IR/DataLayout.h"
@@ -1586,7 +1587,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
   }
 
   // Returning from an outlined SEH helper is UB, and we already warn on it.
-  if (IsOutlinedSEHHelper) {
+  if (getIsOutlinedSEHHelper()) {
     Builder.CreateUnreachable();
     Builder.ClearInsertionPoint();
   }
@@ -2675,7 +2676,7 @@ class AsmConstraintsInfo {
 
   // Destination blocks for 'asm gotos'.
   llvm::BasicBlock *DefaultDest = nullptr;
-  SmallVector<llvm::BasicBlock *, 3> IndirectDests;
+  llvm::SmallVectorWithFlags<llvm::BasicBlock *, 3, 2> IndirectDests;
 
   std::vector<std::optional<std::pair<unsigned, unsigned>>> ResultBounds;
 
@@ -2688,8 +2689,10 @@ class AsmConstraintsInfo {
   //
   // It can be marked readnone if it doesn't have any input memory
   // constraints in addition to meeting the conditions listed above.
-  bool ReadOnly = true;
-  bool ReadNone = true;
+  bool getReadOnly() const { return !IndirectDests.getFlag(0); }
+  void setReadOnly(bool Value) { IndirectDests.setFlag(0, !Value); }
+  bool getReadNone() const { return !IndirectDests.getFlag(1); }
+  void setReadNone(bool Value) { IndirectDests.setFlag(1, !Value); }
 
   bool GetOutputAndInputConstraints();
   void HandleOutputConstraints();
@@ -3023,8 +3026,8 @@ void AsmConstraintsInfo::HandleOutputConstraints() {
       Args.push_back(DestAddr.emitRawPointer(CGF));
 
       Constraints += "=*" + OutputConstraint;
-      ReadOnly = false;
-      ReadNone = false;
+      setReadOnly(false);
+      setReadNone(false);
     }
 
     if (!Info.isReadWrite())
@@ -3078,7 +3081,7 @@ void AsmConstraintsInfo::HandleMSStyleAsmBlob() {
   CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
       CGF, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
       ResultRegDests, AsmString, S.getNumOutputs());
-  CGF.SawAsmBlock = true;
+  CGF.setSawAsmBlock(true);
 }
 
 /// Process the input constraints of an inline assembly statement. It handles
@@ -3092,7 +3095,7 @@ void AsmConstraintsInfo::HandleInputConstraints() {
     const Expr *InputExpr = S.getInputExpr(I);
 
     if (Info.allowsMemory())
-      ReadNone = false;
+      setReadNone(false);
 
     if (!Constraints.empty())
       Constraints += ',';
@@ -3209,8 +3212,8 @@ bool AsmConstraintsInfo::HandleClobbers() {
     }
 
     if (Clobber == "memory") {
-      ReadOnly = false;
-      ReadNone = false;
+      setReadOnly(false);
+      setReadNone(false);
     } else if (Clobber != "cc") {
       Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
       if (CGM.getCodeGenOpts().StackClashProtector &&
@@ -3260,9 +3263,9 @@ void AsmConstraintsInfo::UpdateAsmCallInst(
 
   // Attach readnone and readonly attributes.
   if (!HasSideEffect) {
-    if (ReadNone)
+    if (getReadNone())
       Result.setDoesNotAccessMemory();
-    else if (ReadOnly)
+    else if (getReadOnly())
       Result.setOnlyReadsMemory();
   }
 
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index b8fdcee65bf93..adecf1bb8957c 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1829,8 +1829,8 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
   }
   if (!Data.ReductionVars.empty()) {
     OpenMPDirectiveKind EKind = getEffectiveDirectiveKind(D);
-    Data.IsReductionWithTaskMod = true;
-    Data.IsWorksharingReduction = isOpenMPWorksharingDirective(EKind);
+    Data.setIsReductionWithTaskMod(true);
+    Data.setIsWorksharingReduction(isOpenMPWorksharingDirective(EKind));
     llvm::Value *ReductionDesc = CGM.getOpenMPRuntime().emitTaskReductionInit(
         *this, D.getBeginLoc(), TaskLHSs, TaskRHSs, Data);
     const Expr *TaskRedRef = nullptr;
@@ -3417,7 +3417,7 @@ static void emitOMPSimdDirective(const OMPLoopDirective &S,
   }
 
   CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
-  CGF.OMPFirstScanLoop = true;
+  CGF.setOMPFirstScanLoop(true);
   auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
     emitOMPSimdRegion(CGF, S, Action);
   };
@@ -4439,7 +4439,7 @@ static void emitScanBasedDirective(
     //   <input phase>;
     //   buffer[i] = red;
     // }
-    CGF.OMPFirstScanLoop = true;
+    CGF.setOMPFirstScanLoop(true);
     CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
     FirstGen(CGF);
   }
@@ -4548,7 +4548,7 @@ static void emitScanBasedDirective(
     RCG(CGF);
   }
 
-  CGF.OMPFirstScanLoop = false;
+  CGF.setOMPFirstScanLoop(false);
   SecondGen(CGF);
 }
 
@@ -5529,7 +5529,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   // Build list of dependences.
   buildDependences(S, Data);
   // Get list of local vars for untied tasks.
-  if (!Data.Tied) {
+  if (!Data.getTied()) {
     CheckVarsEscapingUntiedTaskDeclContext Checker;
     Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
     Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
@@ -5833,7 +5833,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   };
   OpenMPDirectiveKind EKind = getEffectiveDirectiveKind(S);
   llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
-      S, *I, *PartId, *TaskT, EKind, CodeGen, Data.Tied, Data.NumberOfParts);
+      S, *I, *PartId, *TaskT, EKind, CodeGen, Data.getTied(),
+      Data.NumberOfParts);
   OMPLexicalScope Scope(*this, S, std::nullopt,
                         !isOpenMPParallelDirective(EKind) &&
                             !isOpenMPSimdDirective(EKind));
@@ -6124,7 +6125,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
 
   OMPTaskDataTy Data;
   // Check if we should emit tied or untied task.
-  Data.Tied = !S.getSingleClause<OMPUntiedClause>();
+  Data.setTied(!S.getSingleClause<OMPUntiedClause>());
   auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
     CGF.EmitStmt(CS->getCapturedStmt());
   };
@@ -6163,7 +6164,7 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
   OMPTaskDataTy Data;
   // Build list of dependences
   buildDependences(S, Data);
-  Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
+  Data.setHasNowaitClause(S.hasClausesOfKind<OMPNowaitClause>());
   CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
 }
 
@@ -6389,7 +6390,7 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) {
     EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
     EmitBlock(OMPScanExitBlock);
   }
-  if (OMPFirstScanLoop) {
+  if (getOMPFirstScanLoop()) {
     // Emit buffer[i] = red; at the end of the input phase.
     const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
                              .getIterationVariable()
@@ -6420,7 +6421,7 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) {
     EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
   }
   EmitBlock(OMPScanDispatch);
-  if (!OMPFirstScanLoop) {
+  if (!getOMPFirstScanLoop()) {
     // Emit red = buffer[i]; at the entrance to the scan phase.
     const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
                              .getIterationVariable()
@@ -6458,8 +6459,8 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) {
       EmitBlock(ExclusiveExitBB);
     }
   }
-  EmitBranch((OMPFirstScanLoop == IsInclusive) ? OMPBeforeScanBlock
-                                               : OMPAfterScanBlock);
+  EmitBranch((getOMPFirstScanLoop() == IsInclusive) ? OMPBeforeScanBlock
+                                                    : OMPAfterScanBlock);
   EmitBlock(OMPAfterScanBlock);
 }
 
@@ -7941,12 +7942,13 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
                                                 S.getBeginLoc());
     DependenceList = DependenciesArray.emitRawPointer(*this);
   }
-  Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
+  Data.setHasNowaitClause(S.hasClausesOfKind<OMPNowaitClause>());
 
-  assert(!(Data.HasNowaitClause && !(S.getSingleClause<OMPInitClause>() ||
-                                     S.getSingleClause<OMPDestroyClause>() ||
-                                     S.getSingleClause<OMPUseClause>())) &&
-         "OMPNowaitClause clause is used separately in OMPInteropDirective.");
+  assert(
+      !(Data.getHasNowaitClause() && !(S.getSingleClause<OMPInitClause>() ||
+                                       S.getSingleClause<OMPDestroyClause>() ||
+                                       S.getSingleClause<OMPUseClause>())) &&
+      "OMPNowaitClause clause is used separately in OMPInteropDirective.");
 
   auto ItOMPInitClause = S.getClausesOfKind<OMPInitClause>();
   if (!ItOMPInitClause.empty()) {
@@ -7965,7 +7967,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
       }
       OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType,
                                       Device, NumDependences, DependenceList,
-                                      Data.HasNowaitClause);
+                                      Data.getHasNowaitClause());
     }
   }
   auto ItOMPDestroyClause = S.getClausesOfKind<OMPDestroyClause>();
@@ -7976,7 +7978,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
           EmitLValue(C->getInteropVar()).getPointer(*this);
       OMPBuilder.createOMPInteropDestroy(Builder, InteropvarPtr, Device,
                                          NumDependences, DependenceList,
-                                         Data.HasNowaitClause);
+                                         Data.getHasNowaitClause());
     }
   }
   auto ItOMPUseClause = S.getClausesOfKind<OMPUseClause>();
@@ -7987,7 +7989,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
           EmitLValue(C->getInteropVar()).getPointer(*this);
       OMPBuilder.createOMPInteropUse(Builder, InteropvarPtr, Device,
                                      NumDependences, DependenceList,
-                                     Data.HasNowaitClause);
+                                     Data.getHasNowaitClause());
     }
   }
 }
@@ -8560,22 +8562,22 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
 
   OMPTaskDataTy Data;
   // Check if taskloop must be emitted without taskgroup.
-  Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
+  Data.setNogroup(S.getSingleClause<OMPNogroupClause>());
   // TODO: Check if we should emit tied or untied task.
-  Data.Tied = true;
+  Data.setTied(true);
   // Set scheduling for taskloop
   if (const auto *Clause = S.getSingleClause<OMPGrainsizeClause>()) {
     // grainsize clause
     Data.Schedule.setInt(/*IntVal=*/false);
     Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
-    Data.HasModifier =
-        (Clause->getModifier() == OMPC_GRAINSIZE_strict) ? true : false;
+    Data.setHasModifier(
+        (Clause->getModifier() == OMPC_GRAINSIZE_strict) ? true : false);
   } else if (const auto *Clause = S.getSingleClause<OMPNumTasksClause>()) {
     // num_tasks clause
     Data.Schedule.setInt(/*IntVal=*/true);
     Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
-    Data.HasModifier =
-        (Clause->getModifier() == OMPC_NUMTASKS_strict) ? true : false;
+    Data.setHasModifier(
+        (Clause->getModifier() == OMPC_NUMTASKS_strict) ? true : false);
   }
 
   auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
@@ -8690,7 +8692,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
     CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
                                                     CodeGen);
   };
-  if (Data.Nogroup) {
+  if (Data.getNogroup()) {
     EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
   } else {
     CGM.getOpenMPRuntime().emitTaskgroupRegion(
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 1aa3fb1928279..133019180ce7d 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -271,7 +271,7 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
                                  bool IsUnprototyped) {
   assert(!CurGD.getDecl() && "CurGD was already set!");
   CurGD = GD;
-  CurFuncIsThunk = true;
+  setCurFuncIsThunk(true);
 
   // Build FunctionArgs.
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@@ -424,7 +424,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
     CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
 
   // Disable the final ARC autorelease.
-  AutoreleaseResult = false;
+  setAutoreleaseResult(false);
 
   FinishThunk();
 }
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 2edd0988c39a7..22c1ab6a9da5e 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -93,9 +93,9 @@ BackendConsumer::BackendConsumer(CompilerInstance &CI, BackendAction Action,
       TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
       AsmOutStream(std::move(OS)), FS(VFS), Action(Action),
       Gen(CreateLLVMCodeGen(CI, InFile, C, CoverageInfo)),
-      LinkModules(std::move(LinkModules)), DiagConsumer(Diags, CodeGenOpts) {
+      LinkModules(0, std::move(LinkModules)), DiagConsumer(Diags, CodeGenOpts) {
   DiagConsumer.setCurLinkModule(CurLinkModule);
-  TimerIsEnabled = CodeGenOpts.TimePasses;
+  setTimerIsEnabled(CodeGenOpts.TimePasses);
   {
     llvm::sys::SmartScopedLock<true> Lock(*TimePassesMutex);
     llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
@@ -127,12 +127,12 @@ void BackendConsumer::Initialize(ASTContext &Ctx) {
   Context = &Ctx;
   DiagConsumer.setSourceManager(&Ctx.getSourceManager());
 
-  if (TimerIsEnabled)
+  if (getTimerIsEnabled())
     LLVMIRGeneration.startTimer();
 
   Gen->Initialize(Ctx);
 
-  if (TimerIsEnabled)
+  if (getTimerIsEnabled())
     LLVMIRGeneration.stopTimer();
 }
 
@@ -142,12 +142,12 @@ bool BackendConsumer::HandleTopLevelDecl(DeclGroupRef D) {
                                  "LLVM IR generation of declaration");
 
   // Recurse.
-  if (TimerIsEnabled && !LLVMIRGenerationRefCount++)
+  if (getTimerIsEnabled() && !LLVMIRGenerationRefCount++)
     CI.getFrontendTimer().yieldTo(LLVMIRGeneration);
 
   Gen->HandleTopLevelDecl(D);
 
-  if (TimerIsEnabled && !--LLVMIRGenerationRefCount)
+  if (getTimerIsEnabled() && !--LLVMIRGenerationRefCount)
     LLVMIRGeneration.yieldTo(CI.getFrontendTimer());
 
   return true;
@@ -157,12 +157,12 @@ void BackendConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
   PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                  Context->getSourceManager(),
                                  "LLVM IR generation of inline function");
-  if (TimerIsEnabled)
+  if (getTimerIsEnabled())
     CI.getFrontendTimer().yieldTo(LLVMIRGeneration);
 
   Gen->HandleInlineFunctionDefinition(D);
 
-  if (TimerIsEnabled)
+  if (getTimerIsEnabled())
     LLVMIRGeneration.yieldTo(CI.getFrontendTimer());
 }
 
@@ -172,20 +172,24 @@ void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) {
 
 // Links each entry in LinkModules into our module. Returns true on error.
 bool BackendConsumer::LinkInModules(llvm::Module *M) {
-  return linkInModules(*M, LinkModules, CodeGenOpts, LangOpts, TargetOpts,
-                       DiagConsumer);
+  SmallVector<LinkModule, 4> Modules;
+  Modules = std::move(LinkModules);
+  bool Failed = linkInModules(*M, Modules, CodeGenOpts, LangOpts, TargetOpts,
+                              DiagConsumer);
+  LinkModules.assign(std::move(Modules));
+  return Failed;
 }
 
 void BackendConsumer::HandleTranslationUnit(ASTContext &C) {
   {
     llvm::TimeTraceScope TimeScope("Frontend");
     PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
-    if (TimerIsEnabled && !LLVMIRGenerationRefCount++)
+    if (getTimerIsEnabled() && !LLVMIRGenerationRefCount++)
       CI.getFrontendTimer().yieldTo(LLVMIRGeneration);
 
     Gen->HandleTranslationUnit(C);
 
-    if (TimerIsEnabled && !--LLVMIRGenerationRefCount)
+    if (getTimerIsEnabled() && !--LLVMIRGenerationRefCount)
       LLVMIRGeneration.yieldTo(CI.getFrontendTimer());
   }
 
@@ -298,12 +302,13 @@ BackendConsumer::createDiagnosticHandler() {
 }
 
 CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
-    : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
-      OwnsVMContext(!_VMContext) {}
+    : Act(_Act), LinkModules(decltype(this->LinkModules)::withFlags(
+                     unsigned(bool(!_VMContext)))),
+      VMContext(_VMContext ? _VMContext : new LLVMContext) {}
 
 CodeGenAction::~CodeGenAction() {
   TheModule.reset();
-  if (OwnsVMContext)
+  if (getOwnsVMContext())
     delete VMContext;
 }
 
@@ -325,7 +330,7 @@ std::unique_ptr<llvm::Module> CodeGenAction::takeModule() {
 }
 
 llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
-  OwnsVMContext = false;
+  setOwnsVMContext(false);
   return VMContext;
 }
 
@@ -371,7 +376,12 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
     return nullptr;
 
   // Load bitcode modules to link with, if we need to.
-  if (clang::loadLinkModules(CI, *VMContext, LinkModules))
+  SmallVector<LinkModule, 4> ModulesToLink;
+  ModulesToLink = std::move(LinkModules);
+  bool FailedToLoadModules =
+      clang::loadLinkModules(CI, *VMContext, ModulesToLink);
+  LinkModules.assign(std::move(ModulesToLink));
+  if (FailedToLoadModules)
     return nullptr;
 
   CoverageSourceInfo *CoverageInfo = nullptr;
@@ -380,9 +390,10 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
     CoverageInfo = CodeGen::CoverageMappingModuleGen::setUpCoverageCallbacks(
         CI.getPreprocessor());
 
-  std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
-      CI, BA, CI.getVirtualFileSystemPtr(), *VMContext, std::move(LinkModules),
-      InFile, std::move(OS), CoverageInfo));
+  std::unique_ptr<BackendConsumer> Result(
+      new BackendConsumer(CI, BA, CI.getVirtualFileSystemPtr(), *VMContext,
+                          SmallVector<LinkModule, 4>(std::move(LinkModules)),
+                          InFile, std::move(OS), CoverageInfo));
   BEConsumer = Result.get();
 
   // Enable generating macro debug info only when debug info is not disabled and
@@ -449,7 +460,12 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
   }
 
   // Load bitcode modules to link with, if we need to.
-  if (clang::loadLinkModules(CI, *VMContext, LinkModules))
+  SmallVector<LinkModule, 4> ModulesToLink;
+  ModulesToLink = std::move(LinkModules);
+  bool FailedToLoadModules =
+      clang::loadLinkModules(CI, *VMContext, ModulesToLink);
+  LinkModules.assign(std::move(ModulesToLink));
+  if (FailedToLoadModules)
     return nullptr;
 
   // Handle textual IR and bitcode file with one single module.
@@ -579,8 +595,8 @@ void CodeGenAction::ExecuteAction() {
   // Set clang diagnostic handler. To do this we need to create a fake
   // BackendConsumer.
   BackendConsumer Result(CI, BA, CI.getVirtualFileSystemPtr(), *VMContext,
-                         std::move(LinkModules), "", nullptr, nullptr,
-                         TheModule.get());
+                         SmallVector<LinkModule, 4>(std::move(LinkModules)), "",
+                         nullptr, nullptr, TheModule.get());
 
   // Link in each pending link module.
   if (!CodeGenOpts.LinkBitcodePostopt && Result.LinkInModules(&*TheModule))
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index e5bca359e6a85..c0b08a2691380 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -63,11 +63,13 @@ using namespace CodeGen;
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
     : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
       Builder(cgm, cgm.getModule().getContext(), CGBuilderInserterTy(this)),
+      OMPLoopNestStack(decltype(this->OMPLoopNestStack)::withFlags(
+          (unsigned(bool(CodeGenUtils::shouldEmitLifetimeMarkers(
+               CGM.getCodeGenOpts(), CGM.getLangOpts())))
+           << 1))),
       SanOpts(CGM.getLangOpts().Sanitize), CurFPFeatures(CGM.getLangOpts()),
       DebugInfo(CGM.getModuleDebugInfo()),
-      PGO(std::make_unique<CodeGenPGO>(cgm)),
-      ShouldEmitLifetimeMarkers(CodeGenUtils::shouldEmitLifetimeMarkers(
-          CGM.getCodeGenOpts(), CGM.getLangOpts())) {
+      PGO(std::make_unique<CodeGenPGO>(cgm)) {
   if (!suppressNewContext)
     CGM.getCXXABI().getMangleContext().startNewFunction();
   EHStack.setCGF(this);
@@ -750,7 +752,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
 
   const Decl *D = GD.getDecl();
 
-  DidCallStackSave = false;
+  setDidCallStackSave(false);
   CurCodeDecl = D;
   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
   if (FD && FD->usesSEHTry())
@@ -1170,7 +1172,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
     // convention.
     DI->emitFunctionStart(GD, Loc, StartLoc,
                           DI->getFunctionType(FD, RetTy, Args), CurFn,
-                          CurFuncIsThunk);
+                          getCurFuncIsThunk());
   }
 
   if (ShouldInstrumentFunction()) {
@@ -1280,7 +1282,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
     if (getLangOpts().ObjCAutoRefCount &&
         !CurFnInfo->isReturnsRetained() &&
         RetTy->isObjCRetainableType())
-      AutoreleaseResult = true;
+      setAutoreleaseResult(true);
   }
 
   EmitStartEHSpec(CurCodeDecl);
@@ -1570,11 +1572,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
   if (Body) {
     // Coroutines always emit lifetime markers.
     if (isa<CoroutineBodyStmt>(Body))
-      ShouldEmitLifetimeMarkers = true;
+      setShouldEmitLifetimeMarkers(true);
 
     // Detect jumps that invalidate lifetime markers or bypass auto-var-init.
     bool NeedsBypassDetection =
-        ShouldEmitLifetimeMarkers ||
+        getShouldEmitLifetimeMarkers() ||
         (CGM.getLangOpts().getTrivialAutoVarInit() !=
          LangOptions::TrivialAutoVarInitKind::Uninitialized);
     if (NeedsBypassDetection)
@@ -1659,8 +1661,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
   // C11 6.9.1p12:
   //   If the '}' that terminates a function is reached, and the value of the
   //   function call is used by the caller, the behavior is undefined.
-  if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock &&
-      !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
+  if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() &&
+      !getSawAsmBlock() && !FD->getReturnType()->isVoidType() &&
+      Builder.GetInsertBlock()) {
     bool ShouldEmitUnreachable =
         CGM.getCodeGenOpts().StrictReturn ||
         !CGM.MayDropFunctionReturn(FD->getASTContext(), FD->getReturnType());
@@ -2875,19 +2878,19 @@ CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
 
 CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)
     : CGF(CGF) {
-  assert(!CGF->IsSanitizerScope);
-  CGF->IsSanitizerScope = true;
+  assert(!CGF->getIsSanitizerScope());
+  CGF->setIsSanitizerScope(true);
 }
 
 CodeGenFunction::SanitizerScope::~SanitizerScope() {
-  CGF->IsSanitizerScope = false;
+  CGF->setIsSanitizerScope(false);
 }
 
 void CodeGenFunction::InsertHelper(llvm::Instruction *I,
                                    const llvm::Twine &Name,
                                    llvm::BasicBlock::iterator InsertPt) const {
   LoopStack.InsertHelper(I);
-  if (IsSanitizerScope)
+  if (getIsSanitizerScope())
     I->setNoSanitizeMetadata();
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 00294ad547d5e..3eb6d828e02ab 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -39,6 +39,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/ValueHandle.h"
@@ -327,10 +328,11 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// loop nest goes out of scope) or a second loop in the same level in which
   /// case it would be ambiguous into which of the two (or more) loops the loop
   /// nest would extend.
-  SmallVector<llvm::CanonicalLoopInfo *, 4> OMPLoopNestStack;
+  llvm::SmallVectorWithFlags<llvm::CanonicalLoopInfo *, 4, 2> OMPLoopNestStack;
 
   /// Stack to track the controlled convergence tokens.
-  SmallVector<llvm::ConvergenceControlInst *, 4> ConvergenceTokenStack;
+  llvm::SmallVectorWithFlags<llvm::ConvergenceControlInst *, 4, 4>
+      ConvergenceTokenStack;
 
   /// Number of nested loop to be consumed by the last surrounding
   /// loop-associated directive.
@@ -374,7 +376,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   const CastExpr *CurCast = nullptr;
 
   /// Save Parameter Decl for coroutine.
-  llvm::SmallVector<const ParmVarDecl *, 4> FnArgs;
+  llvm::SmallVectorWithFlags<const ParmVarDecl *, 4, 4> FnArgs;
 
   // Holds coroutine data if the current function is a coroutine. We use a
   // wrapper to manage its lifetime, so that we don't have to define CGCoroData
@@ -594,7 +596,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   SanitizerSet SanOpts;
 
   /// True if CodeGen currently emits code implementing sanitizer checks.
-  bool IsSanitizerScope = false;
+  bool getIsSanitizerScope() const { return FnArgs.getFlag(0); }
+  void setIsSanitizerScope(bool Value) { FnArgs.setFlag(0, Value); }
 
   /// RAII object to set/unset CodeGenFunction::IsSanitizerScope.
   class SanitizerScope {
@@ -607,24 +610,40 @@ class CodeGenFunction : public CodeGenTypeCache {
 
   /// In C++, whether we are code generating a thunk.  This controls whether we
   /// should emit cleanups.
-  bool CurFuncIsThunk = false;
+  bool getCurFuncIsThunk() const { return FnArgs.getFlag(1); }
+  void setCurFuncIsThunk(bool Value) { FnArgs.setFlag(1, Value); }
 
   /// In ARC, whether we should autorelease the return value.
-  bool AutoreleaseResult = false;
+  bool getAutoreleaseResult() const { return FnArgs.getFlag(2); }
+  bool setAutoreleaseResult(bool Value) {
+    FnArgs.setFlag(2, Value);
+    return Value;
+  }
 
   /// Whether we processed a Microsoft-style asm block during CodeGen. These can
   /// potentially set the return value.
-  bool SawAsmBlock = false;
+  bool getSawAsmBlock() const { return FnArgs.getFlag(3); }
+  void setSawAsmBlock(bool Value) { FnArgs.setFlag(3, Value); }
 
   GlobalDecl CurSEHParent;
 
   /// True if the current function is an outlined SEH helper. This can be a
   /// finally block or filter expression.
-  bool IsOutlinedSEHHelper = false;
+  bool getIsOutlinedSEHHelper() const {
+    return ConvergenceTokenStack.getFlag(0);
+  }
+  void setIsOutlinedSEHHelper(bool Value) {
+    ConvergenceTokenStack.setFlag(0, Value);
+  }
 
   /// True if CodeGen currently emits code inside presereved access index
   /// region.
-  bool IsInPreservedAIRegion = false;
+  bool getIsInPreservedAIRegion() const {
+    return ConvergenceTokenStack.getFlag(1);
+  }
+  void setIsInPreservedAIRegion(bool Value) {
+    ConvergenceTokenStack.setFlag(1, Value);
+  }
 
   /// True if the current statement has nomerge attribute.
   bool InNoMergeAttributedStmt = false;
@@ -810,7 +829,10 @@ class CodeGenFunction : public CodeGenTypeCache {
   llvm::BasicBlock *OMPAfterScanBlock = nullptr;
   llvm::BasicBlock *OMPScanExitBlock = nullptr;
   llvm::BasicBlock *OMPScanDispatch = nullptr;
-  bool OMPFirstScanLoop = false;
+  bool getOMPFirstScanLoop() const { return ConvergenceTokenStack.getFlag(2); }
+  void setOMPFirstScanLoop(bool Value) {
+    ConvergenceTokenStack.setFlag(2, Value);
+  }
 
   /// Manages parent directive for scan directives.
   class ParentLoopDirectiveForScanRegion {
@@ -1077,8 +1099,8 @@ class CodeGenFunction : public CodeGenTypeCache {
       CleanupStackDepth = CGF.EHStack.stable_begin();
       LifetimeExtendedCleanupStackSize =
           CGF.LifetimeExtendedCleanupStack.size();
-      OldDidCallStackSave = CGF.DidCallStackSave;
-      CGF.DidCallStackSave = false;
+      OldDidCallStackSave = CGF.getDidCallStackSave();
+      CGF.setDidCallStackSave(false);
       OldCleanupScopeDepth = CGF.CurrentCleanupScopeDepth;
       CGF.CurrentCleanupScopeDepth = CleanupStackDepth;
     }
@@ -1103,7 +1125,7 @@ class CodeGenFunction : public CodeGenTypeCache {
     void
     ForceCleanup(std::initializer_list<llvm::Value **> ValuesToReload = {}) {
       assert(PerformCleanup && "Already forced cleanup");
-      CGF.DidCallStackSave = OldDidCallStackSave;
+      CGF.setDidCallStackSave(OldDidCallStackSave);
       DeactivateCleanups.ForceDeactivate();
       CGF.PopCleanupBlocks(CleanupStackDepth, LifetimeExtendedCleanupStackSize,
                            ValuesToReload);
@@ -1579,11 +1601,15 @@ class CodeGenFunction : public CodeGenTypeCache {
   CGDebugInfo *DebugInfo;
   /// Used to create unique names for artificial VLA size debug info variables.
   unsigned VLAExprCounter = 0;
-  bool DisableDebugInfo = false;
+  bool getDisableDebugInfo() const { return ConvergenceTokenStack.getFlag(3); }
+  void setDisableDebugInfo(bool Value) {
+    ConvergenceTokenStack.setFlag(3, Value);
+  }
 
   /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
   /// calling llvm.stacksave for multiple VLAs in the same scope.
-  bool DidCallStackSave = false;
+  bool getDidCallStackSave() const { return OMPLoopNestStack.getFlag(0); }
+  void setDidCallStackSave(bool Value) { OMPLoopNestStack.setFlag(0, Value); }
 
   /// IndirectBranch - The first time an indirect goto is seen we create a block
   /// with an indirect branch.  Every time we see the address of a label taken,
@@ -2227,7 +2253,13 @@ class CodeGenFunction : public CodeGenTypeCache {
 
   /// True if we need emit the life-time markers. This is initially set in
   /// the constructor, but could be overwritten to true if this is a coroutine.
-  bool ShouldEmitLifetimeMarkers;
+  bool getShouldEmitLifetimeMarkers() const {
+    return OMPLoopNestStack.getFlag(1);
+  }
+  bool setShouldEmitLifetimeMarkers(bool Value) {
+    OMPLoopNestStack.setFlag(1, Value);
+    return Value;
+  }
 
   /// Add OpenCL kernel arg metadata and the kernel attribute metadata to
   /// the function metadata.
@@ -2240,12 +2272,12 @@ class CodeGenFunction : public CodeGenTypeCache {
   CodeGenTypes &getTypes() const { return CGM.getTypes(); }
   ASTContext &getContext() const { return CGM.getContext(); }
   CGDebugInfo *getDebugInfo() {
-    if (DisableDebugInfo)
+    if (getDisableDebugInfo())
       return nullptr;
     return DebugInfo;
   }
-  void disableDebugInfo() { DisableDebugInfo = true; }
-  void enableDebugInfo() { DisableDebugInfo = false; }
+  void disableDebugInfo() { setDisableDebugInfo(true); }
+  void enableDebugInfo() { setDisableDebugInfo(false); }
 
   bool shouldUseFusedARCCalls() {
     return CGM.getCodeGenOpts().OptimizationLevel == 0;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 00a82819681c1..b4b22819f4959 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -599,9 +599,9 @@ CodeGenModule::CodeGenModule(ASTContext &C,
   // Build C++20 Module initializers.
   // TODO: Add Microsoft here once we know the mangling required for the
   // initializers.
-  CXX20ModuleInits =
-      LangOpts.CPlusPlusModules && getCXXABI().getMangleContext().getKind() ==
-                                       ItaniumMangleContext::MK_Itanium;
+  setCXX20ModuleInits(LangOpts.CPlusPlusModules &&
+                      getCXXABI().getMangleContext().getKind() ==
+                          ItaniumMangleContext::MK_Itanium);
 
   RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
 
@@ -1184,7 +1184,7 @@ CodeGenModule::StackProtectorAttribute(const Decl *D) const {
 
 void CodeGenModule::Release() {
   Module *Primary = getContext().getCurrentNamedModule();
-  if (CXX20ModuleInits && Primary && !Primary->isHeaderLikeModule())
+  if (getCXX20ModuleInits() && Primary && !Primary->isHeaderLikeModule())
     EmitModuleInitializers(Primary);
   EmitDeferred();
   DeferredDecls.insert_range(EmittedDeferredDecls);
@@ -1205,7 +1205,7 @@ void CodeGenModule::Release() {
 
   // Module implementations are initialized the same way as a regular TU that
   // imports one or more modules.
-  if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition())
+  if (getCXX20ModuleInits() && Primary && Primary->isInterfaceOrPartition())
     EmitCXXModuleInitFunc(Primary);
   else
     EmitCXXGlobalInitFunc();
@@ -4062,7 +4062,7 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
 
   // For modules that use export_as for linking, use that module
   // name instead.
-  if (Mod->UseExportAsModuleLinkName)
+  if (Mod->getUseExportAsModuleLinkName())
     return;
 
   for (const Module::LinkLibrary &LL : llvm::reverse(Mod->LinkLibraries)) {
@@ -4155,7 +4155,7 @@ void CodeGenModule::EmitModuleLinkOptions() {
     for (const auto &SM : Mod->submodules()) {
       // Skip explicit children; they need to be explicitly imported to be
       // linked against.
-      if (SM->IsExplicit)
+      if (SM->getIsExplicit())
         continue;
 
       if (Visited.insert(SM).second) {
@@ -4613,7 +4613,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
       // A definition of an inline constexpr static data member may change
       // linkage later if it's redeclared outside the class.
       return false;
-    if (CXX20ModuleInits && VD->getOwningModule() &&
+    if (getCXX20ModuleInits() && VD->getOwningModule() &&
         !VD->getOwningModule()->isModuleMapModule()) {
       // For CXX20, module-owned initializers need to be deferred, since it is
       // not known at this point if they will be run for the current module or
@@ -8225,7 +8225,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     // For C++ standard modules we are done - we will call the module
     // initializer for imported modules, and that will likewise call those for
     // any imports it has.
-    if (CXX20ModuleInits && Import->getImportedModule() &&
+    if (getCXX20ModuleInits() && Import->getImportedModule() &&
         Import->getImportedModule()->isNamedModule())
       break;
 
@@ -8250,7 +8250,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
       for (Module *Submodule : Mod->submodules()) {
         // Skip explicit children; they need to be explicitly imported to emit
         // the initializers.
-        if (Submodule->IsExplicit)
+        if (Submodule->getIsExplicit())
           continue;
 
         if (Visited.insert(Submodule).second)
@@ -9040,7 +9040,7 @@ void CodeGenModule::addPendingGlobalDelete(
   PendingMSVCGlobalDeletes.insert({GlobalDeleteAlias, OperatorDeleteFD});
 }
 
-void CodeGenModule::noteDirectGlobalDelete() { HasDirectGlobalDelete = true; }
+void CodeGenModule::noteDirectGlobalDelete() { setHasDirectGlobalDelete(true); }
 
 /// Get or create the MSVC-compatible __global_delete wrapper function.
 ///
@@ -9156,7 +9156,7 @@ void CodeGenModule::emitGlobalDeleteForwardingBodies() {
   // path), we know ::operator delete must exist, so we replace the wrapper's
   // weak alias-to-empty fallback with a real __global_delete definition that
   // forwards to it.
-  if (!HasDirectGlobalDelete)
+  if (!getHasDirectGlobalDelete())
     return;
 
   for (const auto &Entry : PendingMSVCGlobalDeletes) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index d9f3901c0c67e..4e93aa0296e18 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -35,6 +35,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ValueHandle.h"
@@ -365,7 +366,10 @@ class CodeGenModule : public CodeGenTypeCache {
   std::unique_ptr<CGCXXABI> ABI;
   llvm::LLVMContext &VMContext;
   std::string ModuleNameHash;
-  bool CXX20ModuleInits = false;
+  bool getCXX20ModuleInits() const { return ELFDependentLibraries.getFlag(0); }
+  void setCXX20ModuleInits(bool Value) {
+    ELFDependentLibraries.setFlag(0, Value);
+  }
   std::unique_ptr<CodeGenTBAA> TBAA;
 
   mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
@@ -569,7 +573,12 @@ class CodeGenModule : public CodeGenTypeCache {
 
   /// Whether this TU contains a direct use of global ::operator delete
   /// (indicating that __global_delete forwarding bodies should be emitted).
-  bool HasDirectGlobalDelete = false;
+  bool getHasDirectGlobalDelete() const {
+    return ELFDependentLibraries.getFlag(1);
+  }
+  void setHasDirectGlobalDelete(bool Value) {
+    ELFDependentLibraries.setFlag(1, Value);
+  }
 
   typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *>
       GlobalInitData;
@@ -627,7 +636,7 @@ class CodeGenModule : public CodeGenTypeCache {
   SmallVector<llvm::MDNode *, 16> LinkerOptionsMetadata;
 
   /// A vector of metadata strings for dependent libraries for ELF.
-  SmallVector<llvm::MDNode *, 16> ELFDependentLibraries;
+  llvm::SmallVectorWithFlags<llvm::MDNode *, 16, 2> ELFDependentLibraries;
 
   /// Global variable for copyright pragma comment (if present).
   llvm::GlobalVariable *LoadTimeCommentGlobal = nullptr;
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 1b16be8106f56..c858c81f8a211 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/Support/CommandLine.h"
@@ -489,7 +490,10 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
 
   /// A flag that is set when the current count should be recorded on the
   /// next statement, such as at the exit of a loop.
-  bool RecordNextStmtCount;
+  bool getRecordNextStmtCount() const { return BreakContinueStack.getFlag(0); }
+  void setRecordNextStmtCount(bool Value) {
+    BreakContinueStack.setFlag(0, Value);
+  }
 
   /// The count at the current location in the traversal.
   uint64_t CurrentCount;
@@ -503,16 +507,16 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     uint64_t ContinueCount = 0;
     BreakContinue() = default;
   };
-  SmallVector<BreakContinue, 8> BreakContinueStack;
+  llvm::SmallVectorWithFlags<BreakContinue, 8> BreakContinueStack;
 
   ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
                       CodeGenPGO &PGO)
-      : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
+      : PGO(PGO), CountMap(CountMap) {}
 
   void RecordStmtCount(const Stmt *S) {
-    if (RecordNextStmtCount) {
+    if (getRecordNextStmtCount()) {
       CountMap[S] = CurrentCount;
-      RecordNextStmtCount = false;
+      setRecordNextStmtCount(false);
     }
   }
 
@@ -567,7 +571,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     if (S->getRetValue())
       Visit(S->getRetValue());
     CurrentCount = 0;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitCXXThrowExpr(const CXXThrowExpr *E) {
@@ -575,17 +579,17 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     if (E->getSubExpr())
       Visit(E->getSubExpr());
     CurrentCount = 0;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitGotoStmt(const GotoStmt *S) {
     RecordStmtCount(S);
     CurrentCount = 0;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitLabelStmt(const LabelStmt *S) {
-    RecordNextStmtCount = false;
+    setRecordNextStmtCount(false);
     // Counter tracks the block following the label.
     uint64_t BlockCount = setCount(PGO.getRegionCount(S));
     CountMap[S] = BlockCount;
@@ -597,7 +601,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
     BreakContinueStack.back().BreakCount += CurrentCount;
     CurrentCount = 0;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitContinueStmt(const ContinueStmt *S) {
@@ -605,7 +609,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
     BreakContinueStack.back().ContinueCount += CurrentCount;
     CurrentCount = 0;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitWhileStmt(const WhileStmt *S) {
@@ -630,7 +634,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     CountMap[S->getCond()] = CondCount;
     Visit(S->getCond());
     setCount(BC.BreakCount + CondCount - BodyCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -651,7 +655,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     CountMap[S->getCond()] = CondCount;
     Visit(S->getCond());
     setCount(BC.BreakCount + CondCount - LoopCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitForStmt(const ForStmt *S) {
@@ -686,7 +690,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
       Visit(S->getCond());
     }
     setCount(BC.BreakCount + CondCount - BodyCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -720,7 +724,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     CountMap[S->getCond()] = CondCount;
     Visit(S->getCond());
     setCount(BC.BreakCount + CondCount - BodyCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
@@ -737,7 +741,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
 
     setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
              BodyCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitSwitchStmt(const SwitchStmt *S) {
@@ -754,11 +758,11 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
       BreakContinueStack.back().ContinueCount += BC.ContinueCount;
     // Counter tracks the exit block of the switch.
     setCount(PGO.getRegionCount(S));
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitSwitchCase(const SwitchCase *S) {
-    RecordNextStmtCount = false;
+    setRecordNextStmtCount(false);
     // Counter for this particular case. This counts only jumps from the
     // switch header and does not include fallthrough from the case before
     // this one.
@@ -767,7 +771,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     // We need the count without fallthrough in the mapping, so it's more useful
     // for branch probabilities.
     CountMap[S] = CaseCount;
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
     Visit(S->getSubStmt());
   }
 
@@ -802,7 +806,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     } else
       OutCount += ElseCount;
     setCount(OutCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitCXXTryStmt(const CXXTryStmt *S) {
@@ -812,11 +816,11 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
       Visit(S->getHandler(I));
     // Counter tracks the continuation block of the try statement.
     setCount(PGO.getRegionCount(S));
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitCXXCatchStmt(const CXXCatchStmt *S) {
-    RecordNextStmtCount = false;
+    setRecordNextStmtCount(false);
     // Counter tracks the catch statement's handler block.
     uint64_t CatchCount = setCount(PGO.getRegionCount(S));
     CountMap[S] = CatchCount;
@@ -841,7 +845,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     OutCount += CurrentCount;
 
     setCount(OutCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitBinLAnd(const BinaryOperator *E) {
@@ -853,7 +857,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     CountMap[E->getRHS()] = RHSCount;
     Visit(E->getRHS());
     setCount(ParentCount + RHSCount - CurrentCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 
   void VisitBinLOr(const BinaryOperator *E) {
@@ -865,7 +869,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
     CountMap[E->getRHS()] = RHSCount;
     Visit(E->getRHS());
     setCount(ParentCount + RHSCount - CurrentCount);
-    RecordNextStmtCount = true;
+    setRecordNextStmtCount(true);
   }
 };
 } // end anonymous namespace
diff --git a/clang/lib/CodeGen/ConstantEmitter.h b/clang/lib/CodeGen/ConstantEmitter.h
index 581b05ae87add..5c326ff51d65b 100644
--- a/clang/lib/CodeGen/ConstantEmitter.h
+++ b/clang/lib/CodeGen/ConstantEmitter.h
@@ -16,6 +16,7 @@
 
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 namespace CodeGen {
@@ -37,15 +38,13 @@ class ConstantEmitter {
   /// Whether the constant-emission failed.
   bool Failed = false;
 
-  /// Whether we're in a constant context.
-  bool InConstantContext = false;
-
   /// The AST address space where this (non-abstract) initializer is going.
   /// Used for generating appropriate placeholders.
   LangAS DestAddressSpace = LangAS::Default;
 
-  llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4>
-    PlaceholderAddresses;
+  llvm::SmallVectorWithFlags<
+      std::pair<llvm::Constant *, llvm::GlobalVariable *>, 4>
+      PlaceholderAddresses;
 
 public:
   ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr)
@@ -67,8 +66,9 @@ class ConstantEmitter {
     return Abstract;
   }
 
-  bool isInConstantContext() const { return InConstantContext; }
-  void setInConstantContext(bool var) { InConstantContext = var; }
+  /// Whether we're in a constant context.
+  bool isInConstantContext() const { return PlaceholderAddresses.getFlag(0); }
+  void setInConstantContext(bool var) { PlaceholderAddresses.setFlag(0, var); }
 
   /// Try to emit the initiaizer of the given declaration as an abstract
   /// constant.  If this succeeds, the emission must be finalized.
diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp
index 93e5d40a11fe7..e026c72774581 100644
--- a/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -58,7 +58,7 @@ ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
 // Only used in this file.
 inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder)
     : Data(builder) {
-  assert(!builder->Frozen);
+  assert(!builder->getFrozen());
   assert(builder->Buffer.size() == 1);
   assert(builder->Buffer[0] != nullptr);
 }
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5bbb742a7b1ef..9e15fea510f7b 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -32,6 +32,7 @@
 #include "clang/Basic/PointerAuthOptions.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
 #include "clang/CodeGenUtils/ItaniumCXXABIUtils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Instructions.h"
@@ -51,25 +52,29 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
 
   /// All the thread wrapper functions that have been used.
-  llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>
+  llvm::SmallVectorWithFlags<std::pair<const VarDecl *, llvm::Function *>, 8, 3>
       ThreadWrappers;
 
 protected:
-  bool UseARMMethodPtrABI;
-  bool UseARMGuardVarABI;
-  bool Use32BitVTableOffsetABI;
+  bool getUseARMMethodPtrABI() const { return ThreadWrappers.getFlag(0); }
+  void setUseARMMethodPtrABI(bool Value) { ThreadWrappers.setFlag(0, Value); }
+  bool getUseARMGuardVarABI() const { return ThreadWrappers.getFlag(1); }
+  void setUseARMGuardVarABI(bool Value) { ThreadWrappers.setFlag(1, Value); }
+  bool getUse32BitVTableOffsetABI() const { return ThreadWrappers.getFlag(2); }
+  void setUse32BitVTableOffsetABI(bool Value) {
+    ThreadWrappers.setFlag(2, Value);
+  }
 
   ItaniumMangleContext &getMangleContext() {
     return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext());
   }
 
 public:
-  ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
-                bool UseARMMethodPtrABI = false,
-                bool UseARMGuardVarABI = false) :
-    CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
-    UseARMGuardVarABI(UseARMGuardVarABI),
-    Use32BitVTableOffsetABI(false) { }
+  ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool UseARMMethodPtrABI = false,
+                bool UseARMGuardVarABI = false)
+      : CGCXXABI(CGM), ThreadWrappers(decltype(ThreadWrappers)::withFlags(
+                           unsigned(UseARMMethodPtrABI) |
+                           (unsigned(UseARMGuardVarABI) << 1))) {}
 
   bool classifyReturnType(CGFunctionInfo &FI) const override;
 
@@ -525,7 +530,7 @@ class ARMCXXABI : public ItaniumCXXABI {
 class AppleARM64CXXABI : public ARMCXXABI {
 public:
   AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
-    Use32BitVTableOffsetABI = true;
+    setUse32BitVTableOffsetABI(true);
   }
 
   // ARM64 libraries are prepared for non-unique RTTI.
@@ -661,7 +666,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
 
   // Compute the true adjustment.
   llvm::Value *Adj = RawAdj;
-  if (UseARMMethodPtrABI)
+  if (getUseARMMethodPtrABI())
     Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
 
   // Apply the adjustment and cast back to the original struct type
@@ -676,7 +681,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
   // If the LSB in the function pointer is 1, the function pointer points to
   // a virtual function.
   llvm::Value *IsVirtual;
-  if (UseARMMethodPtrABI)
+  if (getUseARMMethodPtrABI())
     IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
   else
     IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
@@ -700,9 +705,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
   // On ARM64, to reserve extra space in virtual member function pointers,
   // we only pay attention to the low 32 bits of the offset.
   llvm::Value *VTableOffset = FnAsInt;
-  if (!UseARMMethodPtrABI)
+  if (!getUseARMMethodPtrABI())
     VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
-  if (Use32BitVTableOffsetABI) {
+  if (getUse32BitVTableOffsetABI()) {
     VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
     VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
   }
@@ -983,7 +988,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
       llvm::BasicBlock *MergeBB = CGF.createBasicBlock("merge");
 
       // Check whether we have a virtual offset or a pointer to a function.
-      assert(UseARMMethodPtrABI && "ARM ABI expected");
+      assert(getUseARMMethodPtrABI() && "ARM ABI expected");
       llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj");
       llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
       llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
@@ -1036,7 +1041,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
   }
 
   // The this-adjustment is left-shifted by 1 on ARM.
-  if (UseARMMethodPtrABI) {
+  if (getUseARMMethodPtrABI()) {
     uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
     offset <<= 1;
     adj = llvm::ConstantInt::get(adj->getType(), offset);
@@ -1118,7 +1123,7 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
   }
 
   // The this-adjustment is left-shifted by 1 on ARM.
-  if (UseARMMethodPtrABI) {
+  if (getUseARMMethodPtrABI()) {
     uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
     offset <<= 1;
     adj = llvm::ConstantInt::get(adj->getType(), offset);
@@ -1183,7 +1188,7 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
       VTableOffset = Index * PointerWidth.getQuantity();
     }
 
-    if (UseARMMethodPtrABI) {
+    if (getUseARMMethodPtrABI()) {
       // ARM C++ ABI 3.2.1:
       //   This ABI specifies that adj contains twice the this
       //   adjustment, plus 1 if the member function is virtual. The
@@ -1241,8 +1246,8 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
 
     MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
     MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
-                                       (UseARMMethodPtrABI ? 2 : 1) *
-                                       ThisAdjustment.getQuantity());
+                                       (getUseARMMethodPtrABI() ? 2 : 1) *
+                                           ThisAdjustment.getQuantity());
   }
 
   return llvm::ConstantStruct::getAnon(MemPtr);
@@ -1330,7 +1335,7 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
 
   // Null member function pointers on ARM clear the low bit of Adj,
   // so the zero condition has to check that neither low bit is set.
-  if (UseARMMethodPtrABI) {
+  if (getUseARMMethodPtrABI()) {
     llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
 
     // Compute (l.adj | r.adj) & 1 and test it against zero.
@@ -1370,7 +1375,7 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
 
   // On ARM, a member function pointer is also non-null if the low bit of 'adj'
   // (the virtual bit) is set.
-  if (UseARMMethodPtrABI) {
+  if (getUseARMMethodPtrABI()) {
     llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
     llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
     llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
@@ -2711,7 +2716,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
   } else {
     // Guard variables are 64 bits in the generic ABI and size width on ARM
     // (i.e. 32-bit on AArch32, 64-bit on AArch64).
-    if (UseARMGuardVarABI) {
+    if (getUseARMGuardVarABI()) {
       guardTy = CGF.SizeTy;
       guardAlignment = CGF.getSizeAlign();
     } else {
@@ -2824,7 +2829,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     //   variable; all other bits are platform defined. Bit 0 shall be 0 when the
     //   variable is not initialized and 1 when it is.
     llvm::Value *V =
-        (UseARMGuardVarABI && !useInt8GuardVariable)
+        (getUseARMGuardVarABI() && !useInt8GuardVariable)
             ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
             : LI;
     llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
@@ -3458,7 +3463,7 @@ ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
   // Start codegen.
   CodeGenFunction CGF(CGM);
   CGF.CurGD = GlobalDecl(MD);
-  CGF.CurFuncIsThunk = true;
+  CGF.setCurFuncIsThunk(true);
 
   // Build FunctionArgs.
   FunctionArgList FunctionArgs;
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 86916104d1344..ad43601148f9c 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1623,7 +1623,7 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
   // without making our codegen depend on debug info settings.
   llvm::Value *This = loadIncomingCXXThis(CGF);
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
-  if (!CGF.CurFuncIsThunk && MD->isVirtual()) {
+  if (!CGF.getCurFuncIsThunk() && MD->isVirtual()) {
     CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.CurGD);
     if (!Adjustment.isZero()) {
       assert(Adjustment.isPositive());
@@ -2156,7 +2156,7 @@ MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,
   // Start codegen.
   CodeGenFunction CGF(CGM);
   CGF.CurGD = GlobalDecl(MD);
-  CGF.CurFuncIsThunk = true;
+  CGF.setCurFuncIsThunk(true);
 
   // Build FunctionArgs, but only include the implicit 'this' parameter
   // declaration.
diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
index 88ab809e78a8e..623b4b58a5b8b 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
@@ -278,7 +278,7 @@ class PCHContainerGenerator : public ASTConsumer {
       llvm::report_fatal_error(llvm::Twine(Error));
 
     // Emit the serialized Clang AST into its own section.
-    assert(Buffer->IsComplete && "serialization did not complete");
+    assert(Buffer->getIsComplete() && "serialization did not complete");
     auto &SerializedAST = Buffer->Data;
     auto Size = SerializedAST.size();
 
@@ -333,7 +333,7 @@ class PCHContainerGenerator : public ASTConsumer {
 
     // Free the memory for the temporary buffer.
     llvm::SmallVector<char, 0> Empty;
-    SerializedAST = std::move(Empty);
+    SerializedAST.assign(std::move(Empty));
   }
 };
 
diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp
index 9b9a44270b8e6..4a0772c09038b 100644
--- a/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -468,7 +468,7 @@ bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first,
 
 void SwiftAggLowering::finish() {
   if (Entries.empty()) {
-    Finished = true;
+    setFinished(true);
     return;
   }
 
@@ -495,12 +495,12 @@ void SwiftAggLowering::finish() {
   // The rest of the algorithm leaves non-opaque entries alone, so if we
   // have no opaque entries, we're done.
   if (!hasOpaqueEntries) {
-    Finished = true;
+    setFinished(true);
     return;
   }
 
   // Okay, move the entries to a temporary and rebuild Entries.
-  auto orig = std::move(Entries);
+  auto orig = SmallVector<StorageEntry, 4>(std::move(Entries));
   assert(Entries.empty());
 
   for (size_t i = 0, e = orig.size(); i != e; ++i) {
@@ -554,11 +554,11 @@ void SwiftAggLowering::finish() {
   }
 
   // Okay, finally finished.
-  Finished = true;
+  setFinished(true);
 }
 
 void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const {
-  assert(Finished && "haven't yet finished lowering");
+  assert(getFinished() && "haven't yet finished lowering");
 
   for (auto &entry : Entries) {
     callback(entry.Begin, entry.End, entry.Type);
@@ -567,7 +567,7 @@ void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const {
 
 std::pair<llvm::StructType*, llvm::Type*>
 SwiftAggLowering::getCoerceAndExpandTypes() const {
-  assert(Finished && "haven't yet finished lowering");
+  assert(getFinished() && "haven't yet finished lowering");
 
   auto &ctx = CGM.getLLVMContext();
 
@@ -624,7 +624,7 @@ SwiftAggLowering::getCoerceAndExpandTypes() const {
 }
 
 bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const {
-  assert(Finished && "haven't yet finished lowering");
+  assert(getFinished() && "haven't yet finished lowering");
 
   // Empty types don't need to be passed indirectly.
   if (Entries.empty()) return false;
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 4a7bdba6d917e..7a04a52251b5f 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -7315,11 +7315,11 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
     }
 
     // Enable underlying preserve_*_access_index() generation.
-    bool OldIsInPreservedAIRegion = IsInPreservedAIRegion;
-    IsInPreservedAIRegion = true;
+    bool OldIsInPreservedAIRegion = getIsInPreservedAIRegion();
+    setIsInPreservedAIRegion(true);
     Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this)
                                   : EmitLValue(Arg).emitRawPointer(*this);
-    IsInPreservedAIRegion = OldIsInPreservedAIRegion;
+    setIsInPreservedAIRegion(OldIsInPreservedAIRegion);
 
     ConstantInt *C = cast<ConstantInt>(EmitScalarExpr(E->getArg(1)));
     Value *InfoKind = ConstantInt::get(Int64Ty, C->getSExtValue());
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index fcd2086964c48..98722973cc705 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <algorithm>
 
 using namespace clang;
@@ -225,14 +226,18 @@ class SparcV9ABIInfo : public ABIInfo {
   struct CoerceBuilder {
     llvm::LLVMContext &Context;
     const llvm::DataLayout &DL;
-    SmallVector<llvm::Type*, 8> Elems;
+    llvm::SmallVectorWithFlags<llvm::Type *, 8, 2> Elems;
     uint64_t Size;
-    bool InReg;
-    bool IsVarArg;
+    bool getInReg() const { return Elems.getFlag(0); }
+    void setInReg(bool Value) { Elems.setFlag(0, Value); }
+    bool getIsVarArg() const { return Elems.getFlag(1); }
+    void setIsVarArg(bool Value) { Elems.setFlag(1, Value); }
 
     CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl,
                   bool IsVarArg)
-        : Context(c), DL(dl), Size(0), InReg(false), IsVarArg(IsVarArg) {}
+        : Context(c), DL(dl),
+          Elems(decltype(Elems)::withFlags((unsigned(IsVarArg) << 1))),
+          Size(0) {}
 
     // Pad Elems with integers until Size is ToSize.
     void pad(uint64_t ToSize) {
@@ -263,14 +268,14 @@ class SparcV9ABIInfo : public ABIInfo {
     // Add a floating point element at Offset.
     void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) {
       // Varargs are treated as integers.
-      if (IsVarArg)
+      if (getIsVarArg())
         return;
       // Unaligned floats are treated as integers.
       if (Offset % Bits)
         return;
       // The InReg flag is only required if there are any floats < 64 bits.
       if (Bits < 64)
-        InReg = true;
+        setInReg(true);
       pad(Offset);
       Elems.push_back(Ty);
       Size = Offset + Bits;
@@ -431,7 +436,7 @@ ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,
   llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
 
   ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);
-  AAI.setInReg(CB.InReg);
+  AAI.setInReg(CB.getInReg());
   return AAI;
 }
 
diff --git a/clang/lib/CodeGen/VarBypassDetector.cpp b/clang/lib/CodeGen/VarBypassDetector.cpp
index f19ac2de6ea45..24a6f548523fd 100644
--- a/clang/lib/CodeGen/VarBypassDetector.cpp
+++ b/clang/lib/CodeGen/VarBypassDetector.cpp
@@ -48,12 +48,12 @@ void VarBypassDetector::Init(CodeGenModule &CGM, const Stmt *Body) {
   Bypasses.clear();
   BypassedVarsAtSource.clear();
   Scopes = {{~0U, nullptr}};
-  AlwaysBypassed = false;
+  setAlwaysBypassed(false);
   if (!hasJumpStmts(Body))
     return;
   unsigned ParentScope = 0;
-  AlwaysBypassed = !BuildScopeInformation(CGM, Body, ParentScope);
-  if (!AlwaysBypassed)
+  setAlwaysBypassed(!BuildScopeInformation(CGM, Body, ParentScope));
+  if (!isAlwaysBypassed())
     Detect();
 }
 
diff --git a/clang/lib/CodeGen/VarBypassDetector.h b/clang/lib/CodeGen/VarBypassDetector.h
index edcf17d1edd24..e456aced2bf46 100644
--- a/clang/lib/CodeGen/VarBypassDetector.h
+++ b/clang/lib/CodeGen/VarBypassDetector.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 
@@ -43,7 +44,7 @@ class VarBypassDetector {
   // declaration.
   llvm::SmallVector<std::pair<unsigned, const VarDecl *>, 48> Scopes;
   // List of jumps with scopes.
-  llvm::SmallVector<std::pair<const Stmt *, unsigned>, 16> FromScopes;
+  llvm::SmallVectorWithFlags<std::pair<const Stmt *, unsigned>, 16> FromScopes;
   // Lookup map to find scope for destinations.
   llvm::DenseMap<const Stmt *, unsigned> ToScopes;
   // Set of variables which were bypassed by some jump.
@@ -53,7 +54,7 @@ class VarBypassDetector {
   llvm::DenseMap<const Stmt *, llvm::SmallSetVector<const VarDecl *, 4>>
       BypassedVarsAtSource;
   // If true assume that all variables are being bypassed.
-  bool AlwaysBypassed = false;
+  void setAlwaysBypassed(bool Value) { FromScopes.setFlag(0, Value); }
 
 public:
   void Init(CodeGenModule &CGM, const Stmt *Body);
@@ -61,12 +62,12 @@ class VarBypassDetector {
   /// Returns true if the variable declaration was by bypassed by any goto or
   /// switch statement.
   bool IsBypassed(const VarDecl *D) const {
-    return AlwaysBypassed || Bypasses.contains(D);
+    return isAlwaysBypassed() || Bypasses.contains(D);
   }
 
   /// Returns true if jump sources cannot be determined (e.g. computed gotos),
   /// so all variables must be treated as bypassed.
-  bool isAlwaysBypassed() const { return AlwaysBypassed; }
+  bool isAlwaysBypassed() const { return FromScopes.getFlag(0); }
 
   /// Returns the variables bypassed by jumps from the given source statement,
   /// or nullptr if it bypasses none.
diff --git a/clang/lib/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/DependencyScanning/ModuleDepCollector.cpp
index ed660fc0707ac..eb07730b0c4e2 100644
--- a/clang/lib/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/DependencyScanning/ModuleDepCollector.cpp
@@ -316,7 +316,7 @@ ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
   CowCompilerInvocation CI = CommonInvocation;
 
   CI.getMutLangOpts().ModuleName = Deps.ID.ModuleName;
-  CI.getMutFrontendOpts().IsSystemModule = Deps.IsSystem;
+  CI.getMutFrontendOpts().IsSystemModule = Deps.getIsSystem();
 
   // Inputs
   InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
@@ -490,7 +490,7 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
   HashBuilder.add(getClangFullRepositoryVersion());
   HashBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);
   llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
-  if (CWD && !MD.IgnoreCWD)
+  if (CWD && !MD.getIgnoreCWD())
     HashBuilder.add(*CWD);
 
   // Hash the BuildInvocation without any input files.
@@ -735,17 +735,17 @@ ModuleDepCollector::handleTopLevelModule(serialization::ModuleFile *MF) {
   ModuleDeps &MD = *OwnedMD;
 
   MD.ID.ModuleName = MF->ModuleName;
-  MD.IsSystem = M->IsSystem;
+  MD.setIsSystem(M->getIsSystem());
 
   // Start off with the assumption that this module is shareable when there
   // are stable directories. As more dependencies are discovered, check if those
   // come from the provided directories.
-  MD.IsInStableDirectories = !MDC.StableDirs.empty();
+  MD.setIsInStableDirectories(!MDC.StableDirs.empty());
 
   // For modules which use export_as link name, the linked product that of the
   // corresponding export_as-named module.
-  if (!M->UseExportAsModuleLinkName)
-    MD.LinkLibraries = M->LinkLibraries;
+  if (!M->getUseExportAsModuleLinkName())
+    MD.LinkLibraries.assign(M->LinkLibraries.begin(), M->LinkLibraries.end());
 
   ModuleMap &ModMapInfo =
       MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
@@ -786,11 +786,11 @@ ModuleDepCollector::handleTopLevelModule(serialization::ModuleFile *MF) {
   MDC.ScanInstance.getASTReader()->visitInputFileInfos(
       *MF, /*IncludeSystem=*/true,
       [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
-        if (MD.IsInStableDirectories) {
+        if (MD.getIsInStableDirectories()) {
           auto FullFilePath = ASTReader::ResolveImportedPath(
               PathBuf, IFI.UnresolvedImportedFilename, MF->BaseDirectory);
-          MD.IsInStableDirectories =
-              isPathInStableDir(MDC.StableDirs, *FullFilePath);
+          MD.setIsInStableDirectories(
+              isPathInStableDir(MDC.StableDirs, *FullFilePath));
         }
         if (!(IFI.TopLevel && IFI.ModuleMap))
           return;
@@ -860,11 +860,11 @@ ModuleDepCollector::handleTopLevelModule(serialization::ModuleFile *MF) {
 
   // Check provided input paths from the invocation for determining
   // IsInStableDirectories.
-  if (MD.IsInStableDirectories)
-    MD.IsInStableDirectories =
-        areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts());
+  if (MD.getIsInStableDirectories())
+    MD.setIsInStableDirectories(
+        areOptionsInStableDir(MDC.StableDirs, CI.getHeaderSearchOpts()));
 
-  MD.IgnoreCWD = IgnoreCWD;
+  MD.setIgnoreCWD(IgnoreCWD);
   MDC.associateWithContextHash(CI, MD);
 
   // Finish the compiler invocation. Requires dependencies and the context hash.
@@ -885,18 +885,18 @@ void ModuleDepCollector::addAllModuleDeps(serialization::ModuleFile &MF,
   for (serialization::ModuleFile *Import : MF.Imports) {
     if (MDC.isPrebuiltModule(Import)) {
       MD.PrebuiltModuleDeps.push_back(createPrebuiltModuleDep(Import));
-      if (MD.IsInStableDirectories) {
+      if (MD.getIsInStableDirectories()) {
         auto It = MDC.PrebuiltModulesASTMap.find(
             MD.PrebuiltModuleDeps.back().PCMFile);
-        MD.IsInStableDirectories =
-            It != MDC.PrebuiltModulesASTMap.end() && It->second.isInStableDir();
+        MD.setIsInStableDirectories(It != MDC.PrebuiltModulesASTMap.end() &&
+                                    It->second.isInStableDir());
       }
     } else {
       if (auto ID = handleTopLevelModule(Import)) {
         MD.ClangModuleDeps.push_back(std::move(*ID));
-        if (MD.IsInStableDirectories)
-          MD.IsInStableDirectories =
-              MDC.ModularDeps[Import]->IsInStableDirectories;
+        if (MD.getIsInStableDirectories())
+          MD.setIsInStableDirectories(
+              MDC.ModularDeps[Import]->getIsInStableDirectories());
       }
     }
   }
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index c81c4445a29f9..9cefbb013d2a0 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -166,14 +166,14 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files,
 int Compilation::ExecuteCommand(const Command &C,
                                 const Command *&FailingCommand,
                                 bool LogOnly) const {
-  if ((getDriver().CCPrintOptions ||
-       getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
+  if ((getDriver().getCCPrintOptions() || getArgs().hasArg(options::OPT_v)) &&
+      !getDriver().CCGenDiagnostics) {
     raw_ostream *OS = &llvm::errs();
     std::unique_ptr<llvm::raw_fd_ostream> OwnedStream;
 
     // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
     // output stream.
-    if (getDriver().CCPrintOptions &&
+    if (getDriver().getCCPrintOptions() &&
         !getDriver().CCPrintOptionsFilename.empty()) {
       std::error_code EC;
       OwnedStream.reset(new llvm::raw_fd_ostream(
@@ -188,10 +188,10 @@ int Compilation::ExecuteCommand(const Command &C,
       OS = OwnedStream.get();
     }
 
-    if (getDriver().CCPrintOptions)
+    if (getDriver().getCCPrintOptions())
       *OS << "[Logging clang options]\n";
 
-    C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
+    C.Print(*OS, "\n", /*Quote=*/getDriver().getCCPrintOptions());
   }
 
   if (LogOnly)
@@ -370,7 +370,7 @@ void Compilation::ExecuteJobs(const JobList &Jobs,
   // In all but CLMode, execute all the jobs unless the necessary inputs for the
   // job is missing due to previous failures.
   bool CanRunJobsInParallel =
-      !LogOnly && !getDriver().CCPrintOptions &&
+      !LogOnly && !getDriver().getCCPrintOptions() &&
       !getDriver().CCPrintProcessStats && !getDriver().CCGenDiagnostics &&
       !getDriver().IsCLMode() && !getArgs().hasArg(options::OPT_v) &&
       Redirects.empty() && !PostCallback;
diff --git a/clang/lib/Driver/CreateASTUnitFromArgs.cpp b/clang/lib/Driver/CreateASTUnitFromArgs.cpp
index 7503cd4465716..253c1f595e18f 100644
--- a/clang/lib/Driver/CreateASTUnitFromArgs.cpp
+++ b/clang/lib/Driver/CreateASTUnitFromArgs.cpp
@@ -129,10 +129,10 @@ std::unique_ptr<ASTUnit> clang::CreateASTUnitFromCommandLine(
   VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
   AST->FileMgr =
       llvm::makeIntrusiveRefCnt<FileManager>(AST->FileSystemOpts, VFS);
-  AST->StorePreamblesInMemory = StorePreamblesInMemory;
+  AST->setStorePreamblesInMemory(StorePreamblesInMemory);
   AST->PreambleStoragePath = PreambleStoragePath;
   AST->ModCache = createCrossProcessModuleCache();
-  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->setOnlyLocalDeclsFlag(OnlyLocalDecls);
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->TUKind = TUKind;
   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a9a21175af9c5..9f517f621232d 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -205,12 +205,12 @@ Driver::Driver(StringRef DriverExecutable, StringRef TargetTriple,
       SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
       Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None),
       ModulesModeCXX20(false), DriverExecutable(DriverExecutable),
-      SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
-      CCPrintOptions(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-      CCPrintProcessStats(false), CCPrintInternalStats(false),
-      TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr),
-      PreferredLinker(CLANG_DEFAULT_LINKER), CheckInputsExist(true),
-      ProbePrecompiled(true), SuppressMissingInputWarning(false) {
+      SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCLogDiagnostics(false),
+      CCGenDiagnostics(false), CCPrintProcessStats(false),
+      CCPrintInternalStats(false), TargetTriple(TargetTriple), Saver(Alloc),
+      PrependArg(nullptr), PreferredLinker(CLANG_DEFAULT_LINKER),
+      CheckInputsExist(true), ProbePrecompiled(true),
+      SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
     this->VFS = llvm::vfs::getRealFileSystem();
@@ -1597,7 +1597,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   // options, either by introducing new ones or by overloading gcc ones like -V
   // or -b.
   CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
-  CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
+  setCCCPrintBindings(Args.hasArg(options::OPT_ccc_print_bindings));
   if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
     CCCGenericGCCName = A->getValue();
 
@@ -2926,7 +2926,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
       SibKind = OtherSibAction;
     });
   } else {
-    const ActionList *AL = &A->getInputs();
+    const auto *AL = &A->getInputs();
 
     if (AL->size()) {
       const char *Prefix = "{";
@@ -4847,7 +4847,7 @@ class ToolSelector final {
   /// Get previous dependent action or null if that does not exist. If
   /// \a CanBeCollapsed is false, that action must be legal to collapse or
   /// null will be returned.
-  const JobAction *getPrevDependentAction(const ActionList &Inputs,
+  const JobAction *getPrevDependentAction(ArrayRef<Action *> Inputs,
                                           ActionList &SavedOffloadAction,
                                           bool CanBeCollapsed = true) {
     // An option can be collapsed only if it has a single input.
@@ -4969,7 +4969,7 @@ class ToolSelector final {
     if (!T->hasIntegratedAssembler())
       return nullptr;
 
-    Inputs = CJ->getInputs();
+    Inputs.assign(CJ->getInputs().begin(), CJ->getInputs().end());
     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
                                  /*NumElements=*/3);
     return T;
@@ -4992,7 +4992,7 @@ class ToolSelector final {
     if (!T->hasIntegratedAssembler())
       return nullptr;
 
-    Inputs = BJ->getInputs();
+    Inputs.assign(BJ->getInputs().begin(), BJ->getInputs().end());
     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
                                  /*NumElements=*/2);
     return T;
@@ -5037,7 +5037,7 @@ class ToolSelector final {
     if (T->canEmitIR() && EmbedBitcode)
       return nullptr;
 
-    Inputs = CJ->getInputs();
+    Inputs.assign(CJ->getInputs().begin(), CJ->getInputs().end());
     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
                                  /*NumElements=*/2);
     return T;
@@ -5122,7 +5122,8 @@ class ToolSelector final {
     if (!T)
       T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
     if (!T) {
-      Inputs = BaseAction->getInputs();
+      Inputs.assign(BaseAction->getInputs().begin(),
+                    BaseAction->getInputs().end());
       T = TC.SelectTool(*BaseAction);
     }
 
@@ -5351,8 +5352,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
                               TargetDeviceOffloadKind);
   }
 
-
-  ActionList Inputs = A->getInputs();
+  ActionList Inputs(A->getInputs().begin(), A->getInputs().end());
 
   const JobAction *JA = cast<JobAction>(A);
   ActionList CollapsedOffloadActions;
@@ -5445,7 +5445,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
       handleTimeTrace(C, Args, JA, BaseInput, Result);
   }
 
-  if (CCCPrintBindings && !CCGenDiagnostics) {
+  if (getCCCPrintBindings() && !CCGenDiagnostics) {
     llvm::errs() << "# \"" << T->getToolChain().getEffectiveTriple().str()
                  << '"' << " - \"" << T->getName() << "\", inputs: [";
     for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
@@ -5872,8 +5872,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
 
 std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   // Search for Name in a list of paths.
-  auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)
-      -> std::optional<std::string> {
+  auto SearchPaths =
+      [&](llvm::ArrayRef<std::string> P) -> std::optional<std::string> {
     // Respect a limited subset of the '-Bprefix' functionality in GCC by
     // attempting to use this prefix when looking for file paths.
     for (const auto &Dir : P) {
diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp
index 473fe940d9970..16f30d9d3dc8a 100644
--- a/clang/lib/Driver/OffloadBundler.cpp
+++ b/clang/lib/Driver/OffloadBundler.cpp
@@ -112,7 +112,7 @@ bool OffloadTargetInfo::isOffloadKindCompatible(
       (OffloadKind == "hipv4" && TargetOffloadKind == "hip"))
     return true;
 
-  if (BundlerConfig.HipOpenmpCompatible) {
+  if (BundlerConfig.getHipOpenmpCompatible()) {
     bool HIPCompatibleWithOpenMP = OffloadKind.starts_with_insensitive("hip") &&
                                    TargetOffloadKind == "openmp";
     bool OpenMPCompatibleWithHIP =
@@ -714,7 +714,7 @@ class ObjectFileHandler final : public FileHandler {
   Error executeObjcopy(StringRef Objcopy, ArrayRef<StringRef> Args) {
     // If the user asked for the commands to be printed out, we do that
     // instead of executing it.
-    if (BundlerConfig.PrintExternalCommands) {
+    if (BundlerConfig.getPrintExternalCommands()) {
       errs() << "\"" << Objcopy << "\"";
       for (StringRef Arg : drop_begin(Args, 1))
         errs() << " \"" << Arg << "\"";
@@ -965,11 +965,11 @@ OffloadBundlerConfig::OffloadBundlerConfig()
     return;
   auto VerboseEnvVarOpt = llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_VERBOSE");
   if (VerboseEnvVarOpt.has_value())
-    Verbose = VerboseEnvVarOpt.value() == "1";
+    setVerbose(VerboseEnvVarOpt.value() == "1");
   auto CompressEnvVarOpt =
       llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESS");
   if (CompressEnvVarOpt.has_value())
-    Compress = CompressEnvVarOpt.value() == "1";
+    setCompress(CompressEnvVarOpt.value() == "1");
   auto CompressionLevelEnvVarOpt =
       llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESSION_LEVEL");
   if (CompressionLevelEnvVarOpt.has_value()) {
@@ -1064,7 +1064,7 @@ Error OffloadBundler::ListBundleIDsInFile(
     // Decompress the input if necessary.
     Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
         CompressedOffloadBundle::decompress(
-            **CodeOrErr, BundlerConfig.Verbose ? &llvm::errs() : nullptr);
+            **CodeOrErr, BundlerConfig.getVerbose() ? &llvm::errs() : nullptr);
     if (!DecompressedBufferOrErr)
       return createStringError(
           inconvertibleErrorCode(),
@@ -1189,12 +1189,14 @@ Error OffloadBundler::BundleFiles() {
   }
 
   // Get the file handler. We use the host buffer as reference.
-  assert((BundlerConfig.HostInputIndex != ~0u || BundlerConfig.AllowNoHost) &&
-         "Host input index undefined??");
-  Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr = CreateFileHandler(
-      *InputBuffers[BundlerConfig.AllowNoHost ? 0
-                                              : BundlerConfig.HostInputIndex],
-      BundlerConfig);
+  assert(
+      (BundlerConfig.HostInputIndex != ~0u || BundlerConfig.getAllowNoHost()) &&
+      "Host input index undefined??");
+  Expected<std::unique_ptr<FileHandler>> FileHandlerOrErr =
+      CreateFileHandler(*InputBuffers[BundlerConfig.getAllowNoHost()
+                                          ? 0
+                                          : BundlerConfig.HostInputIndex],
+                        BundlerConfig);
   if (!FileHandlerOrErr)
     return FileHandlerOrErr.takeError();
 
@@ -1224,7 +1226,7 @@ Error OffloadBundler::BundleFiles() {
     return createFileError(BundlerConfig.OutputFileNames.front(), EC);
 
   SmallVector<char, 0> CompressedBuffer;
-  if (BundlerConfig.Compress) {
+  if (BundlerConfig.getCompress()) {
     std::unique_ptr<llvm::MemoryBuffer> BufferMemory =
         llvm::MemoryBuffer::getMemBufferCopy(
             llvm::StringRef(Buffer.data(), Buffer.size()));
@@ -1232,7 +1234,7 @@ Error OffloadBundler::BundleFiles() {
         {BundlerConfig.CompressionFormat, BundlerConfig.CompressionLevel,
          /*zstdEnableLdm=*/true},
         *BufferMemory, BundlerConfig.CompressedBundleVersion,
-        BundlerConfig.Verbose ? &llvm::errs() : nullptr);
+        BundlerConfig.getVerbose() ? &llvm::errs() : nullptr);
     if (auto Error = CompressionResult.takeError())
       return Error;
 
@@ -1315,7 +1317,7 @@ Error OffloadBundler::UnbundleFiles() {
     // Decompress the blob if necessary.
     Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
         CompressedOffloadBundle::decompress(
-            **BlobOrErr, BundlerConfig.Verbose ? &llvm::errs() : nullptr);
+            **BlobOrErr, BundlerConfig.getVerbose() ? &llvm::errs() : nullptr);
     if (!DecompressedBufferOrErr)
       return createStringError(
           inconvertibleErrorCode(),
@@ -1386,7 +1388,7 @@ Error OffloadBundler::UnbundleFiles() {
       Offset += NextBundleStart;
   }
 
-  if (!BundlerConfig.AllowMissingBundles && !Worklist.empty()) {
+  if (!BundlerConfig.getAllowMissingBundles() && !Worklist.empty()) {
     std::string ErrMsg = "Can't find bundles for";
     std::set<StringRef> Sorted;
     for (auto &E : Worklist)
@@ -1428,7 +1430,7 @@ Error OffloadBundler::UnbundleFiles() {
   // If we found elements, we emit an error if none of those were for the host
   // in case host bundle name was provided in command line.
   if (!(FoundHostBundle || BundlerConfig.HostInputIndex == ~0u ||
-        BundlerConfig.AllowMissingBundles))
+        BundlerConfig.getAllowMissingBundles()))
     return createStringError(inconvertibleErrorCode(),
                              "Can't find bundle for the host target");
 
@@ -1574,7 +1576,7 @@ Error OffloadBundler::UnbundleArchive() {
 
   StringRef IFName = BundlerConfig.InputFileNames.front();
 
-  if (BundlerConfig.CheckInputArchive) {
+  if (BundlerConfig.getCheckInputArchive()) {
     // For a specific processor, a feature either shows up in all target IDs, or
     // does not show up in any target IDs. Otherwise the target ID combination
     // is invalid.
@@ -1622,7 +1624,7 @@ Error OffloadBundler::UnbundleArchive() {
     Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
         CompressedOffloadBundle::decompress(
             *TempCodeObjectBuffer,
-            BundlerConfig.Verbose ? &llvm::errs() : nullptr);
+            BundlerConfig.getVerbose() ? &llvm::errs() : nullptr);
     if (!DecompressedBufferOrErr)
       return createStringError(
           inconvertibleErrorCode(),
@@ -1720,7 +1722,7 @@ Error OffloadBundler::UnbundleArchive() {
                                         getDefaultArchiveKindForHost(), true,
                                         false, nullptr))
         return WriteErr;
-    } else if (!BundlerConfig.AllowMissingBundles) {
+    } else if (!BundlerConfig.getAllowMissingBundles()) {
       std::string ErrMsg =
           Twine("no compatible code object found for the target '" + Target +
                 "' in heterogeneous archive library: " + IFName)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 255a9c9602b54..2c944023e0266 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -536,6 +536,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
 SanitizerArgs
 ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs, BoundArch BA,
                             Action::OffloadKind DeviceOffloadKind) const {
+  const bool DiagnoseErrors = BoundArchSanitizerArgsChecked.empty();
   // When -fno-gpu-sanitize is specified for GPU targets, don't emit
   // diagnostics about unsupported sanitizers for specific GPU arches,
   // since sanitizers are disabled for the GPU anyway.
@@ -547,11 +548,9 @@ ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs, BoundArch BA,
     DiagnoseBoundArchErrors = false;
   }
 
-  SanitizerArgs SanArgs(*this, JobArgs,
-                        /*DiagnoseErrors=*/!SanitizerArgsChecked,
-                        DiagnoseBoundArchErrors, BA, DeviceOffloadKind);
+  SanitizerArgs SanArgs(*this, JobArgs, DiagnoseErrors, DiagnoseBoundArchErrors,
+                        BA, DeviceOffloadKind);
 
-  SanitizerArgsChecked = true;
   return SanArgs;
 }
 
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 54ef9bb27993a..0c681f5100675 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -184,7 +184,7 @@ bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef V) {
 
 /// \returns a list of candidate directories for ROCm installation, which is
 /// cached and populated only once.
-const SmallVectorImpl<RocmInstallationDetector::Candidate> &
+ArrayRef<RocmInstallationDetector::Candidate>
 RocmInstallationDetector::getInstallationPathCandidates() {
 
   // Return the cached candidate list if it has already been populated.
@@ -192,7 +192,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
     return ROCmSearchDirs;
 
   auto DoPrintROCmSearchDirs = [&]() {
-    if (PrintROCmSearchDirs)
+    if (getPrintROCmSearchDirs())
       for (auto Cand : ROCmSearchDirs) {
         llvm::errs() << "ROCm installation search path: " << Cand.Path << '\n';
       }
@@ -318,9 +318,9 @@ RocmInstallationDetector::RocmInstallationDetector(
     const Driver &D, const llvm::Triple &HostTriple,
     const llvm::opt::ArgList &Args, bool DetectHIPRuntime)
     : D(D) {
-  Verbose = Args.hasArg(options::OPT_v);
+  setVerbose(Args.hasArg(options::OPT_v));
   RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
-  PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
+  setPrintROCmSearchDirs(Args.hasArg(options::OPT_print_rocm_search_dirs));
   RocmDeviceLibPathArg =
       Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
   HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
@@ -396,13 +396,13 @@ void RocmInstallationDetector::detectDeviceLibrary() {
 
   // Check device library exists at the given path.
   auto CheckDeviceLib = [&](StringRef Path, bool StrictChecking) {
-    bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
+    bool CheckLibDevice = (!getNoBuiltinLibs() || StrictChecking);
     if (CheckLibDevice && !FS.exists(Path))
       return false;
 
     scanLibDevicePath(Path);
 
-    if (!NoBuiltinLibs) {
+    if (!getNoBuiltinLibs()) {
       // Check that the required non-target libraries are all available.
       if (!allGenericLibsValid())
         return false;
@@ -425,7 +425,7 @@ void RocmInstallationDetector::detectDeviceLibrary() {
 
   // Find device libraries in a legacy ROCm directory structure
   // ${ROCM_ROOT}/amdgcn/bitcode/*
-  auto &ROCmDirs = getInstallationPathCandidates();
+  auto ROCmDirs = getInstallationPathCandidates();
   for (const auto &Candidate : ROCmDirs) {
     LibDevicePath = Candidate.Path;
     llvm::sys::path::append(LibDevicePath, "amdgcn", "bitcode");
@@ -446,7 +446,7 @@ void RocmInstallationDetector::detectHIPRuntime(
       HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
   }
   if (HIPSearchDirs.empty())
-    HIPSearchDirs.append(getInstallationPathCandidates());
+    llvm::append_range(HIPSearchDirs, getInstallationPathCandidates());
   auto &FS = D.getVFS();
 
   for (const auto &Candidate : HIPSearchDirs) {
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index ec2641301909d..014c9264604c6 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -562,9 +562,9 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
 /// Hexagon Toolchain
 
-std::string HexagonToolChain::getHexagonTargetDir(
-      const std::string &InstalledDir,
-      const SmallVectorImpl<std::string> &PrefixDirs) const {
+std::string
+HexagonToolChain::getHexagonTargetDir(const std::string &InstalledDir,
+                                      ArrayRef<std::string> PrefixDirs) const {
   const Driver &D = getDriver();
 
   // Locate the rest of the toolchain ...
diff --git a/clang/lib/Driver/ToolChains/Hexagon.h b/clang/lib/Driver/ToolChains/Hexagon.h
index 1f848a8de061d..f4c471c3b2ba2 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/clang/lib/Driver/ToolChains/Hexagon.h
@@ -105,9 +105,8 @@ class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
 
   StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
 
-  std::string getHexagonTargetDir(
-      const std::string &InstalledDir,
-      const SmallVectorImpl<std::string> &PrefixDirs) const;
+  std::string getHexagonTargetDir(const std::string &InstalledDir,
+                                  ArrayRef<std::string> PrefixDirs) const;
   SmallString<128> getEffectiveSysRoot(const llvm::opt::ArgList &Args) const;
   void getBaseIncludeDir(const llvm::opt::ArgList &Args,
                          llvm::SmallString<128> &) const;
diff --git a/clang/lib/Edit/Commit.cpp b/clang/lib/Edit/Commit.cpp
index 415b1573d789a..2b82ca7eabc4b 100644
--- a/clang/lib/Edit/Commit.cpp
+++ b/clang/lib/Edit/Commit.cpp
@@ -52,7 +52,7 @@ bool Commit::insert(SourceLocation loc, StringRef text,
   FileOffset Offs;
   if ((!afterToken && !canInsert(loc, Offs)) ||
       ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -66,20 +66,20 @@ bool Commit::insertFromRange(SourceLocation loc,
   FileOffset RangeOffs;
   unsigned RangeLen;
   if (!canRemoveRange(range, RangeOffs, RangeLen)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
   FileOffset Offs;
   if ((!afterToken && !canInsert(loc, Offs)) ||
       ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
   if (PPRec &&
       PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -91,7 +91,7 @@ bool Commit::remove(CharSourceRange range) {
   FileOffset Offs;
   unsigned Len;
   if (!canRemoveRange(range, Offs, Len)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -119,7 +119,7 @@ bool Commit::replace(CharSourceRange range, StringRef text) {
   FileOffset Offs;
   unsigned Len;
   if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -133,14 +133,14 @@ bool Commit::replaceWithInner(CharSourceRange range,
   FileOffset OuterBegin;
   unsigned OuterLen;
   if (!canRemoveRange(range, OuterBegin, OuterLen)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
   FileOffset InnerBegin;
   unsigned InnerLen;
   if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -150,7 +150,7 @@ bool Commit::replaceWithInner(CharSourceRange range,
       InnerBegin < OuterBegin ||
       InnerBegin > OuterEnd ||
       InnerEnd > OuterEnd) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
@@ -169,7 +169,7 @@ bool Commit::replaceText(SourceLocation loc, StringRef text,
   FileOffset Offs;
   unsigned Len;
   if (!canReplaceText(loc, replacementText, Offs, Len)) {
-    IsCommitable = false;
+    setIsCommitable(false);
     return false;
   }
 
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 6228f2e687be2..3d1afed88df9c 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -605,8 +605,7 @@ void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
   serializeObject(Paren, "swiftGenerics", Generics);
 }
 
-Array generateParentContexts(const SmallVectorImpl<SymbolReference> &Parents,
-                             Language Lang) {
+Array generateParentContexts(ArrayRef<SymbolReference> Parents, Language Lang) {
   Array ParentContexts;
 
   for (const auto &Parent : Parents) {
@@ -703,7 +702,7 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
 }
 
 ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
-  if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
+  if (!getForceEmitToMainModule() && ModuleForCurrentSymbol)
     return *ModuleForCurrentSymbol;
 
   return MainModule;
@@ -734,7 +733,7 @@ void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
                                                   ExtendedModule &Into) {
   Object Relationship;
   SmallString<64> TestRelLabel;
-  if (EmitSymbolLabelsForTesting) {
+  if (getEmitSymbolLabelsForTesting()) {
     llvm::raw_svector_ostream OS(TestRelLabel);
     OS << SymbolGraphSerializer::getRelationshipString(Kind) << " $ "
        << Source.USR << " $ ";
@@ -749,7 +748,7 @@ void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
   Relationship["targetFallback"] = Target.Name;
   Relationship["kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
 
-  if (ForceEmitToMainModule)
+  if (getForceEmitToMainModule())
     MainModule.addRelationship(std::move(Relationship));
   else
     Into.addRelationship(std::move(Relationship));
@@ -770,7 +769,7 @@ void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) {
 
   // If we need symbol labels for testing emit the USR as the value and the key
   // starts with '!'' to ensure it ends up at the top of the object.
-  if (EmitSymbolLabelsForTesting)
+  if (getEmitSymbolLabelsForTesting())
     Obj["!testLabel"] = Record->USR;
 
   serializeObject(Obj, "identifier",
@@ -940,7 +939,7 @@ bool SymbolGraphSerializer::visitObjCInterfaceRecord(
 
 bool SymbolGraphSerializer::traverseObjCCategoryRecord(
     const ObjCCategoryRecord *Record) {
-  if (SkipSymbolsInCategoriesToExternalTypes &&
+  if (getSkipSymbolsInCategoriesToExternalTypes() &&
       !API.findRecordForUSR(Record->Interface.USR))
     return true;
 
@@ -1105,7 +1104,7 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
                                    /*ForceEmitToMainModule*/ true);
 
   // Set up serializer parent chain
-  Serializer.Hierarchy = generateHierarchyFromRecord(Record);
+  Serializer.Hierarchy.assign(generateHierarchyFromRecord(Record));
 
   Serializer.serializeSingleRecord(Record);
   serializeObject(Root, "symbolGraph",
diff --git a/clang/lib/Format/AffectedRangeManager.cpp b/clang/lib/Format/AffectedRangeManager.cpp
index 7e9acc9fbbb04..1f37ce64e5aa6 100644
--- a/clang/lib/Format/AffectedRangeManager.cpp
+++ b/clang/lib/Format/AffectedRangeManager.cpp
@@ -20,7 +20,7 @@ namespace clang {
 namespace format {
 
 bool AffectedRangeManager::computeAffectedLines(
-    SmallVectorImpl<AnnotatedLine *> &Lines) {
+    ArrayRef<AnnotatedLine *> Lines) {
   ArrayRef<AnnotatedLine *>::iterator I = Lines.begin();
   ArrayRef<AnnotatedLine *>::iterator E = Lines.end();
   bool SomeLineAffected = false;
@@ -99,9 +99,9 @@ void AffectedRangeManager::markAllAsAffected(
   }
 }
 
-bool AffectedRangeManager::nonPPLineAffected(
-    AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
-    SmallVectorImpl<AnnotatedLine *> &Lines) {
+bool AffectedRangeManager::nonPPLineAffected(AnnotatedLine *Line,
+                                             const AnnotatedLine *PreviousLine,
+                                             ArrayRef<AnnotatedLine *> Lines) {
   bool SomeLineAffected = false;
   Line->ChildrenAffected = computeAffectedLines(Line->Children);
   if (Line->ChildrenAffected)
diff --git a/clang/lib/Format/AffectedRangeManager.h b/clang/lib/Format/AffectedRangeManager.h
index eef056fdf0633..fca8108cb4856 100644
--- a/clang/lib/Format/AffectedRangeManager.h
+++ b/clang/lib/Format/AffectedRangeManager.h
@@ -31,7 +31,7 @@ class AffectedRangeManager {
   // Determines which lines are affected by the SourceRanges given as input.
   // Returns \c true if at least one line in \p Lines or one of their
   // children is affected.
-  bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *> &Lines);
+  bool computeAffectedLines(ArrayRef<AnnotatedLine *> Lines);
 
   // Returns true if 'Range' intersects with one of the input ranges.
   bool affectsCharSourceRange(const CharSourceRange &Range);
@@ -53,7 +53,7 @@ class AffectedRangeManager {
   // Determines whether 'Line' is affected by the SourceRanges given as input.
   // Returns \c true if line or one if its children is affected.
   bool nonPPLineAffected(AnnotatedLine *Line, const AnnotatedLine *PreviousLine,
-                         SmallVectorImpl<AnnotatedLine *> &Lines);
+                         ArrayRef<AnnotatedLine *> Lines);
 
   const SourceManager &SourceMgr;
   const SmallVector<CharSourceRange, 8> Ranges;
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index bb8179cbc4f95..2c0ebfc7a28f5 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -347,12 +347,12 @@ LineState ContinuationIndenter::getInitialState(unsigned FirstIndent,
   State.Stack.push_back(ParenState(/*Tok=*/nullptr, FirstIndent, FirstIndent,
                                    /*AvoidBinPacking=*/false,
                                    /*NoLineBreak=*/false));
-  State.NoContinuation = false;
+  State.setNoContinuation(false);
   State.StartOfStringLiteral = 0;
-  State.NoLineBreak = false;
+  State.setNoLineBreak(false);
   State.StartOfLineLevel = 0;
   State.LowestLevelOnLine = 0;
-  State.IgnoreStackForComparison = false;
+  State.setIgnoreStackForComparison(false);
 
   if (Style.isTextProto()) {
     // We need this in order to deal with the bin packing of text fields at
@@ -468,7 +468,7 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
     return true;
   }
 
-  return !State.NoLineBreak && !CurrentState.NoLineBreak;
+  return !State.getNoLineBreak() && !CurrentState.NoLineBreak;
 }
 
 bool ContinuationIndenter::mustBreak(const LineState &State) {
@@ -707,7 +707,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
   }
 
   if (Current.is(TT_FunctionDeclarationName) &&
-      !State.Line->ReturnTypeWrapped &&
+      !State.Line->getReturnTypeWrapped() &&
       // Don't break before a C# function when no break after return type.
       (!Style.isCSharp() ||
        Style.BreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
@@ -749,7 +749,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
   if (Previous.is(TT_BlockComment) && Previous.IsMultiline)
     return true;
 
-  if (State.NoContinuation)
+  if (State.getNoContinuation())
     return true;
 
   return false;
@@ -763,7 +763,7 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
   const FormatToken &Previous = *State.NextToken->Previous;
 
   assert(!State.Stack.empty());
-  State.NoContinuation = false;
+  State.setNoContinuation(false);
 
   if (Current.is(TT_ImplicitStringLiteral) &&
       (!Previous.Tok.getIdentifierInfo() ||
@@ -850,7 +850,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
   };
 
   if (DisallowLineBreaks())
-    State.NoLineBreak = true;
+    State.setNoLineBreak(true);
 
   if (Current.is(tok::equal) &&
       (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) &&
@@ -1031,7 +1031,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
       Previous.isNoneOf(TT_ObjCMethodExpr, TT_RequiresClause,
                         TT_TableGenDAGArgOpener,
                         TT_TableGenDAGArgOpenerToBreak) &&
-      !(Current.MacroParent && Previous.MacroParent) &&
+      !(Current.getMacroParent() && Previous.getMacroParent()) &&
       (Current.isNot(TT_LineComment) ||
        (Previous.is(BK_BracedInit) &&
         Style.Cpp11BracedListStyle != FormatStyle::BLS_FunctionCall) ||
@@ -1698,7 +1698,7 @@ ContinuationIndenter::getNewLineColumn(const LineState &State) {
                                     TT_LeadingJavaAnnotation))) ||
       (!Style.IndentWrappedFunctionNames &&
        NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName)) ||
-      (State.Line->ReturnTypeWrapped && PreviousNonComment &&
+      (State.Line->getReturnTypeWrapped() && PreviousNonComment &&
        isReturnTypePrefixSpecifier(*PreviousNonComment))) {
     return std::max(IndentationAndAlignment(CurrentState.LastSpace),
                     CurrentState.Indent);
@@ -3134,7 +3134,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
         Paren.BreakBeforeParameter = true;
 
     if (Current.is(TT_BlockComment))
-      State.NoContinuation = true;
+      State.setNoContinuation(true);
 
     State.Stack.back().LastSpace = StartColumn;
   }
diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h
index ed347591525ea..972b4759e21f2 100644
--- a/clang/lib/Format/ContinuationIndenter.h
+++ b/clang/lib/Format/ContinuationIndenter.h
@@ -17,6 +17,7 @@
 
 #include "Encoding.h"
 #include "FormatToken.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 class SourceManager;
@@ -459,7 +460,11 @@ struct LineState {
   FormatToken *NextToken;
 
   /// \c true if \p NextToken should not continue this line.
-  bool NoContinuation;
+  bool getNoContinuation() const { return Stack.getFlag(0); }
+  bool setNoContinuation(bool Value) {
+    Stack.setFlag(0, Value);
+    return Value;
+  }
 
   /// The \c NestingLevel at the start of this line.
   unsigned StartOfLineLevel;
@@ -472,11 +477,18 @@ struct LineState {
   unsigned StartOfStringLiteral;
 
   /// Disallow line breaks for this line.
-  bool NoLineBreak;
+  bool getNoLineBreak() const { return Stack.getFlag(1); }
+  bool setNoLineBreak(bool Value) {
+    Stack.setFlag(1, Value);
+    return Value;
+  }
 
   /// A stack keeping track of properties applying to parenthesis
   /// levels.
-  SmallVector<ParenState> Stack;
+  llvm::SmallVectorWithFlags<
+      ParenState,
+      llvm::CalculateSmallVectorDefaultInlinedElements<ParenState>::value, 3>
+      Stack;
 
   /// Ignore the stack of \c ParenStates for state comparison.
   ///
@@ -491,7 +503,11 @@ struct LineState {
   /// later.
   ///
   /// FIXME: Come up with a better algorithm instead.
-  bool IgnoreStackForComparison;
+  bool getIgnoreStackForComparison() const { return Stack.getFlag(2); }
+  bool setIgnoreStackForComparison(bool Value) {
+    Stack.setFlag(2, Value);
+    return Value;
+  }
 
   /// The indent of the first token.
   unsigned FirstIndent;
@@ -507,17 +523,17 @@ struct LineState {
       return NextToken < Other.NextToken;
     if (Column != Other.Column)
       return Column < Other.Column;
-    if (NoContinuation != Other.NoContinuation)
-      return NoContinuation;
+    if (getNoContinuation() != Other.getNoContinuation())
+      return getNoContinuation();
     if (StartOfLineLevel != Other.StartOfLineLevel)
       return StartOfLineLevel < Other.StartOfLineLevel;
     if (LowestLevelOnLine != Other.LowestLevelOnLine)
       return LowestLevelOnLine < Other.LowestLevelOnLine;
     if (StartOfStringLiteral != Other.StartOfStringLiteral)
       return StartOfStringLiteral < Other.StartOfStringLiteral;
-    if (IgnoreStackForComparison || Other.IgnoreStackForComparison)
+    if (getIgnoreStackForComparison() || Other.getIgnoreStackForComparison())
       return false;
-    return Stack < Other.Stack;
+    return llvm::ArrayRef(Stack) < llvm::ArrayRef(Other.Stack);
   }
 };
 
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index c4baf8002c274..1e6093d674680 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -24,6 +24,7 @@
 #include "UsingDeclarationsSorter.h"
 #include "clang/Tooling/Inclusions/HeaderIncludes.h"
 #include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/VirtualFileSystem.h"
@@ -2699,7 +2700,7 @@ class ParensRemover : public TokenAnalyzer {
   }
 
 private:
-  void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void removeParens(ArrayRef<AnnotatedLine *> Lines,
                     tooling::Replacements &Result) {
     const auto &SourceMgr = Env.getSourceManager();
     for (auto *Line : Lines) {
@@ -2732,7 +2733,7 @@ class BracesInserter : public TokenAnalyzer {
   }
 
 private:
-  void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void insertBraces(ArrayRef<AnnotatedLine *> Lines,
                     tooling::Replacements &Result) {
     const auto &SourceMgr = Env.getSourceManager();
     int OpeningBraceSurplus = 0;
@@ -2786,7 +2787,7 @@ class BracesRemover : public TokenAnalyzer {
   }
 
 private:
-  void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void removeBraces(ArrayRef<AnnotatedLine *> Lines,
                     tooling::Replacements &Result) {
     const auto &SourceMgr = Env.getSourceManager();
     const auto *End = Lines.end();
@@ -2827,8 +2828,7 @@ class SemiRemover : public TokenAnalyzer {
   }
 
 private:
-  void removeSemi(TokenAnnotator &Annotator,
-                  SmallVectorImpl<AnnotatedLine *> &Lines,
+  void removeSemi(TokenAnnotator &Annotator, ArrayRef<AnnotatedLine *> Lines,
                   tooling::Replacements &Result) {
     auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
       const auto *Prev = Tok.Previous;
@@ -2879,7 +2879,7 @@ class EnumTrailingCommaEditor : public TokenAnalyzer {
   }
 
 private:
-  void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void editEnumTrailingComma(ArrayRef<AnnotatedLine *> Lines,
                              tooling::Replacements &Result) {
     bool InEnumBraces = false;
     FormatToken *BeforeRBrace = nullptr;
@@ -2933,7 +2933,7 @@ class JavaScriptRequoter : public TokenAnalyzer {
 private:
   // Replaces double/single-quoted string literal as appropriate, re-escaping
   // the contents in the process.
-  void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void requoteJSStringLiteral(ArrayRef<AnnotatedLine *> Lines,
                               tooling::Replacements &Result) {
     for (AnnotatedLine *Line : Lines) {
       requoteJSStringLiteral(Line->Children, Result);
@@ -3047,8 +3047,7 @@ class Formatter : public TokenAnalyzer {
   }
 
 private:
-  bool
-  hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
+  bool hasCpp03IncompatibleFormat(ArrayRef<AnnotatedLine *> Lines) {
     for (const AnnotatedLine *Line : Lines) {
       if (hasCpp03IncompatibleFormat(Line->Children))
         return true;
@@ -3066,7 +3065,7 @@ class Formatter : public TokenAnalyzer {
     return false;
   }
 
-  int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
+  int countVariableAlignments(ArrayRef<AnnotatedLine *> Lines) {
     int AlignmentDiff = 0;
 
     for (const AnnotatedLine *Line : Lines) {
@@ -3176,7 +3175,7 @@ class TrailingCommaInserter : public TokenAnalyzer {
 private:
   /// Inserts trailing commas in [] and {} initializers if they wrap over
   /// multiple lines.
-  void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
+  void insertTrailingCommas(ArrayRef<AnnotatedLine *> Lines,
                             tooling::Replacements &Result) {
     for (AnnotatedLine *Line : Lines) {
       insertTrailingCommas(Line->Children, Result);
@@ -3461,10 +3460,9 @@ class ObjCHeaderStyleGuesser : public TokenAnalyzer {
   bool isObjC() { return IsObjC; }
 
 private:
-  static bool
-  guessIsObjC(const SourceManager &SourceManager,
-              const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
-              const AdditionalKeywords &Keywords) {
+  static bool guessIsObjC(const SourceManager &SourceManager,
+                          ArrayRef<AnnotatedLine *> AnnotatedLines,
+                          const AdditionalKeywords &Keywords) {
     // Keep this array sorted, since we are binary searching over it.
     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
         "CGFloat",
@@ -3594,11 +3592,19 @@ struct IncludeDirective {
 };
 
 struct JavaImportDirective {
+  JavaImportDirective(StringRef Identifier, StringRef Text, unsigned Offset,
+                      ArrayRef<StringRef> Comments, bool IsStatic)
+      : Identifier(Identifier), Text(Text), Offset(Offset),
+        AssociatedCommentLines(
+            decltype(this->AssociatedCommentLines)::withFlags(
+                unsigned(IsStatic), Comments)) {}
+
   StringRef Identifier;
   StringRef Text;
   unsigned Offset;
-  SmallVector<StringRef> AssociatedCommentLines;
-  bool IsStatic;
+  llvm::SmallVectorWithFlags<StringRef> AssociatedCommentLines;
+  bool getIsStatic() const { return AssociatedCommentLines.getFlag(0); }
+  void setIsStatic(bool Value) { AssociatedCommentLines.setFlag(0, Value); }
 };
 
 } // end anonymous namespace
@@ -4005,10 +4011,10 @@ static void sortJavaImports(const FormatStyle &Style,
       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
   sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
     // Negating IsStatic to push static imports above non-static imports.
-    return std::make_tuple(!Imports[LHSI].IsStatic ^
+    return std::make_tuple(!Imports[LHSI].getIsStatic() ^
                                StaticImportAfterNormalImport,
                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
-           std::make_tuple(!Imports[RHSI].IsStatic ^
+           std::make_tuple(!Imports[RHSI].getIsStatic() ^
                                StaticImportAfterNormalImport,
                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
   });
@@ -4020,14 +4026,14 @@ static void sortJavaImports(const FormatStyle &Style,
                              }),
                 Indices.end());
 
-  bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
+  bool CurrentIsStatic = Imports[Indices.front()].getIsStatic();
   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
 
   std::string result;
   for (unsigned Index : Indices) {
     if (!result.empty()) {
       result += "\n";
-      if (CurrentIsStatic != Imports[Index].IsStatic ||
+      if (CurrentIsStatic != Imports[Index].getIsStatic() ||
           CurrentImportGroup != JavaImportGroups[Index]) {
         result += "\n";
       }
@@ -4037,7 +4043,7 @@ static void sortJavaImports(const FormatStyle &Style,
       result += "\n";
     }
     result += Imports[Index].Text;
-    CurrentIsStatic = Imports[Index].IsStatic;
+    CurrentIsStatic = Imports[Index].getIsStatic();
     CurrentImportGroup = JavaImportGroups[Index];
   }
 
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index 33e7727f0162d..2de1c742152a1 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -162,7 +162,7 @@ unsigned CommaSeparatedList::formatFromToken(LineState &State,
                                              bool DryRun) {
   // Formatting with 1 Column isn't really a column layout, so we don't need the
   // special logic here. We can just avoid bin packing any of the parameters.
-  if (Formats.size() == 1 || HasNestedBracedList)
+  if (Formats.size() == 1 || getHasNestedBracedList())
     State.Stack.back().AvoidBinPacking = true;
   return 0;
 }
@@ -224,7 +224,7 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
 
     MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
     if (ItemBegin->is(tok::l_brace))
-      HasNestedBracedList = true;
+      setHasNestedBracedList(true);
     const FormatToken *ItemEnd = nullptr;
     if (i == Commas.size()) {
       ItemEnd = Token->MatchingParen;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 691ecdd24f448..27c991ffc1c20 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -19,6 +19,7 @@
 #include "clang/Basic/OperatorPrecedence.h"
 #include "clang/Format/Format.h"
 #include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <unordered_set>
 
 namespace clang {
@@ -583,7 +584,7 @@ struct FormatToken {
   ///
   /// If multiple fake parentheses start at a token, this vector stores them in
   /// reverse order, i.e. inner fake parenthesis first.
-  SmallVector<prec::Level, 4> FakeLParens;
+  llvm::SmallVectorWithFlags<prec::Level, 4> FakeLParens;
   /// Insert this many fake ) after this token for correct indentation.
   unsigned FakeRParens = 0;
 
@@ -646,7 +647,8 @@ struct FormatToken {
   /// This is deeply baked into the code and disentangling this will require
   /// signficant refactorings. \c MacroParent allows us to special-case the
   /// cases in which we treat parents as block-openers for now.
-  bool MacroParent = false;
+  bool getMacroParent() const { return FakeLParens.getFlag(0); }
+  void setMacroParent(bool Value) { FakeLParens.setFlag(0, Value); }
 
   bool is(tok::TokenKind Kind) const { return Tok.is(Kind); }
   bool is(tok::ObjCKeywordKind Kind) const {
@@ -1050,8 +1052,7 @@ class TokenRole {
 
 class CommaSeparatedList : public TokenRole {
 public:
-  CommaSeparatedList(const FormatStyle &Style)
-      : TokenRole(Style), HasNestedBracedList(false) {}
+  CommaSeparatedList(const FormatStyle &Style) : TokenRole(Style) {}
 
   void precomputeFormattingInfos(const FormatToken *Token) override;
 
@@ -1101,9 +1102,10 @@ class CommaSeparatedList : public TokenRole {
   SmallVector<unsigned, 8> ItemLengths;
 
   /// Precomputed formats that can be used for this list.
-  SmallVector<ColumnFormat, 4> Formats;
+  llvm::SmallVectorWithFlags<ColumnFormat, 4> Formats;
 
-  bool HasNestedBracedList;
+  bool getHasNestedBracedList() const { return Formats.getFlag(0); }
+  void setHasNestedBracedList(bool Value) { Formats.setFlag(0, Value); }
 };
 
 /// Encapsulates keywords that are context sensitive or for languages not
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 2a8bef21ad414..b6ea8eb9617cf 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -28,13 +28,13 @@ FormatTokenLexer::FormatTokenLexer(
     const FormatStyle &Style, encoding::Encoding Encoding,
     llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
     IdentifierTable &IdentTable)
-    : FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}),
-      Column(Column), TrailingWhitespace(0),
-      LangOpts(getFormattingLangOpts(Style)), SourceMgr(SourceMgr), ID(ID),
-      Style(Style), IdentTable(IdentTable), Keywords(IdentTable),
-      Encoding(Encoding), Allocator(Allocator), FirstInLineIndex(0),
-      FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
-      MacroBlockEndRegex(Style.MacroBlockEnd), VerilogProtectedBlock(false) {
+    : FormatTok(nullptr), StateStack({LexerState::NORMAL}), Column(Column),
+      TrailingWhitespace(0), LangOpts(getFormattingLangOpts(Style)),
+      SourceMgr(SourceMgr), ID(ID), Style(Style), IdentTable(IdentTable),
+      Keywords(IdentTable), Encoding(Encoding), Allocator(Allocator),
+      FirstInLineIndex(0), Tokens(decltype(Tokens)::withFlags(1)),
+      MacroBlockBeginRegex(Style.MacroBlockBegin),
+      MacroBlockEndRegex(Style.MacroBlockEnd) {
   Lex = std::make_unique<Lexer>(ID, SourceMgr.getBufferOrFake(ID), SourceMgr,
                                 LangOpts);
   Lex->SetKeepWhitespaceMode(true);
@@ -111,7 +111,7 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
       FormatOff = FO_None;
       [[fallthrough]];
     default:
-      if (!FormattingDisabled && FormatOffRegex.match(Tok.TokenText)) {
+      if (!getFormattingDisabled() && FormatOffRegex.match(Tok.TokenText)) {
         if (Tok.is(tok::comment) &&
             (NewlinesBefore > 0 || Tokens.size() == 1)) {
           Tok.Finalized = true;
@@ -1266,8 +1266,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
   readRawToken(*FormatTok);
   SourceLocation WhitespaceStart =
       FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace);
-  FormatTok->IsFirst = IsFirstToken;
-  IsFirstToken = false;
+  FormatTok->IsFirst = getIsFirstToken();
+  setIsFirstToken(false);
 
   // Consume and record whitespace until we find a significant token.
   // Some tok::unknown tokens are not just whitespace, e.g. whitespace
@@ -1441,7 +1441,7 @@ FormatToken *FormatTokenLexer::getNextToken() {
               Keywords.kw_data_public_key, Keywords.kw_digest_block,
               Keywords.kw_digest_decrypt_key, Keywords.kw_digest_public_key,
               Keywords.kw_key_block, Keywords.kw_key_public_key)) {
-        VerilogProtectedBlock = true;
+        setVerilogProtectedBlock(true);
       }
     }
   } else if (const bool Greater = FormatTok->is(tok::greatergreater);
@@ -1521,9 +1521,9 @@ FormatToken *FormatTokenLexer::getNextToken() {
 
 bool FormatTokenLexer::readVerilogProtected(FormatToken &Tok) {
   // The block follows the pragma line.
-  if (!VerilogProtectedBlock || Tok.NewlinesBefore == 0)
+  if (!getVerilogProtectedBlock() || Tok.NewlinesBefore == 0)
     return false;
-  VerilogProtectedBlock = false;
+  setVerilogProtectedBlock(false);
 
   // The block can be empty. Then no token is necessary. A backtick on its own
   // line is likely a uuencode line. A backtick followed by something is assumed
@@ -1634,12 +1634,12 @@ void FormatTokenLexer::readRawToken(FormatToken &Tok) {
     Tok.Tok.setKind(tok::string_literal);
 
   if (Tok.is(tok::comment) && isClangFormatOn(Tok.TokenText))
-    FormattingDisabled = false;
+    setFormattingDisabled(false);
 
-  Tok.Finalized = FormattingDisabled;
+  Tok.Finalized = getFormattingDisabled();
 
   if (Tok.is(tok::comment) && isClangFormatOff(Tok.TokenText))
-    FormattingDisabled = true;
+    setFormattingDisabled(true);
 }
 
 void FormatTokenLexer::resetLexer(unsigned Offset) {
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index 6fbd05aef7747..baff42e720831 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -19,6 +19,7 @@
 #include "FormatToken.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 
 #include <stack>
@@ -113,7 +114,8 @@ class FormatTokenLexer {
   FormatToken *getNextToken();
 
   FormatToken *FormatTok;
-  bool IsFirstToken;
+  bool getIsFirstToken() const { return Tokens.getFlag(0); }
+  void setIsFirstToken(bool Value) { Tokens.setFlag(0, Value); }
   std::stack<LexerState> StateStack;
   unsigned Column;
   unsigned TrailingWhitespace;
@@ -128,21 +130,23 @@ class FormatTokenLexer {
   llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator;
   // Index (in 'Tokens') of the last token that starts a new line.
   unsigned FirstInLineIndex;
-  SmallVector<FormatToken *, 16> Tokens;
+  llvm::SmallVectorWithFlags<FormatToken *, 16, 3> Tokens;
 
   llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;
 
   llvm::SmallPtrSet<IdentifierInfo *, 8> MacrosSkippedByRemoveParentheses,
       TemplateNames, TypeNames, VariableTemplates;
 
-  bool FormattingDisabled;
+  bool getFormattingDisabled() const { return Tokens.getFlag(1); }
+  void setFormattingDisabled(bool Value) { Tokens.setFlag(1, Value); }
 
   llvm::Regex MacroBlockBeginRegex;
   llvm::Regex MacroBlockEndRegex;
 
   // The next line is a Verilog protected block that should not be split into
   // tokens. Set at the 'pragma protect' line. Cleared at the next line.
-  bool VerilogProtectedBlock;
+  bool getVerilogProtectedBlock() const { return Tokens.getFlag(2); }
+  void setVerilogProtectedBlock(bool Value) { Tokens.setFlag(2, Value); }
 
   // Targets that may appear inside a C# attribute.
   static const llvm::StringSet<> CSharpAttributeTargets;
diff --git a/clang/lib/Format/MacroCallReconstructor.cpp b/clang/lib/Format/MacroCallReconstructor.cpp
index 895d9f93dfce3..cde29d816d3aa 100644
--- a/clang/lib/Format/MacroCallReconstructor.cpp
+++ b/clang/lib/Format/MacroCallReconstructor.cpp
@@ -199,7 +199,7 @@ FormatToken *MacroCallReconstructor::getParentInResult(FormatToken *Parent) {
   // If we use a different token than the parent in the expanded token stream
   // as parent, mark it as a special parent, so the formatting code knows it
   // needs to have its children formatted.
-  Parent->MacroParent = true;
+  Parent->setMacroParent(true);
   return Parent;
 }
 
@@ -426,7 +426,7 @@ bool MacroCallReconstructor::processNextReconstructed() {
       appendToken(Token);
       prepareParent(Token, /*NewLine=*/true,
                     MacroCallStructure.back().Line->Level);
-      Token->MacroParent = true;
+      Token->setMacroParent(true);
       return false;
     }
     if (!MacroCallStructure.empty()) {
@@ -434,7 +434,7 @@ bool MacroCallReconstructor::processNextReconstructed() {
         // Make new lines inside the next argument children of the comma token.
         SpelledParentToReconstructedParent
             [MacroCallStructure.back().Line->Tokens.back()->Tok] = Token;
-        Token->MacroParent = true;
+        Token->setMacroParent(true);
         appendToken(Token, MacroCallStructure.back().Line);
         prepareParent(Token, /*NewLine=*/true,
                       MacroCallStructure.back().Line->Level);
@@ -489,7 +489,7 @@ void MacroCallReconstructor::finalize() {
 
     // Mark the previous line's last token as generated by a macro expansion
     // so the formatting algorithm can take that into account.
-    Last->Tok->MacroParent = true;
+    Last->Tok->setMacroParent(true);
 
     Last = Last->Children.back()->Tokens.back().get();
   }
diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp
index 29c583855e3f5..22f0af531d812 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -573,7 +573,9 @@ LeftRightQualifierAlignmentFixer::LeftRightQualifierAlignmentFixer(
     const Environment &Env, const FormatStyle &Style,
     const std::string &Qualifier,
     const std::vector<tok::TokenKind> &QualifierTokens, bool RightAlign)
-    : TokenAnalyzer(Env, Style), Qualifier(Qualifier), RightAlign(RightAlign),
+    : TokenAnalyzer(Env, Style), Qualifier(Qualifier),
+      QualifierTokens(
+          decltype(this->QualifierTokens)::withFlags(unsigned(RightAlign))),
       ConfiguredQualifierTokens(QualifierTokens) {}
 
 std::pair<tooling::Replacements, unsigned>
@@ -588,7 +590,7 @@ LeftRightQualifierAlignmentFixer::analyze(
 }
 
 void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
-    SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, FormatTokenLexer &Tokens,
+    ArrayRef<AnnotatedLine *> AnnotatedLines, FormatTokenLexer &Tokens,
     tooling::Replacements &Fixes) {
   const AdditionalKeywords &Keywords = Tokens.getKeywords();
   const SourceManager &SourceMgr = Env.getSourceManager();
@@ -612,7 +614,7 @@ void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(
         break;
       if (Tok->is(tok::comment))
         continue;
-      if (RightAlign) {
+      if (getRightAlign()) {
         Tok = analyzeRight(SourceMgr, Keywords, Fixes, Tok, Qualifier,
                            QualifierToken);
       } else {
diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h
index 09fcd7b943e67..92090f2bae1a3 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.h
+++ b/clang/lib/Format/QualifierAlignmentFixer.h
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_LIB_FORMAT_QUALIFIERALIGNMENTFIXER_H
 
 #include "TokenAnalyzer.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 namespace format {
@@ -40,8 +41,9 @@ bool isConfiguredQualifierOrType(const FormatToken *Tok,
 
 class LeftRightQualifierAlignmentFixer : public TokenAnalyzer {
   std::string Qualifier;
-  bool RightAlign;
-  SmallVector<tok::TokenKind, 8> QualifierTokens;
+  bool getRightAlign() const { return QualifierTokens.getFlag(0); }
+  void setRightAlign(bool Value) { QualifierTokens.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<tok::TokenKind, 8> QualifierTokens;
   std::vector<tok::TokenKind> ConfiguredQualifierTokens;
 
 public:
@@ -58,7 +60,7 @@ class LeftRightQualifierAlignmentFixer : public TokenAnalyzer {
 
   static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier);
 
-  void fixQualifierAlignment(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+  void fixQualifierAlignment(ArrayRef<AnnotatedLine *> AnnotatedLines,
                              FormatTokenLexer &Tokens,
                              tooling::Replacements &Fixes);
 
diff --git a/clang/lib/Format/SortJavaScriptImports.cpp b/clang/lib/Format/SortJavaScriptImports.cpp
index a403a4fed664c..609479e06948a 100644
--- a/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/clang/lib/Format/SortJavaScriptImports.cpp
@@ -22,6 +22,7 @@
 #include "clang/Format/Format.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Debug.h"
 #include <string>
 
@@ -66,9 +67,12 @@ struct JsImportedSymbol {
 // This struct represents both exports and imports to build up the information
 // required for sorting module references.
 struct JsModuleReference {
-  bool FormattingOff = false;
-  bool IsExport = false;
-  bool IsTypeOnly = false;
+  bool getFormattingOff() const { return Symbols.getFlag(0); }
+  void setFormattingOff(bool Value) { Symbols.setFlag(0, Value); }
+  bool getIsExport() const { return Symbols.getFlag(1); }
+  void setIsExport(bool Value) { Symbols.setFlag(1, Value); }
+  bool getIsTypeOnly() const { return Symbols.getFlag(2); }
+  void setIsTypeOnly(bool Value) { Symbols.setFlag(2, Value); }
   // Module references are sorted into these categories, in order.
   enum ReferenceCategory {
     SIDE_EFFECT,     // "import 'something';"
@@ -86,10 +90,11 @@ struct JsModuleReference {
   // Default import from "import DefaultName from '...';".
   StringRef DefaultImport;
   // Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
-  SmallVector<JsImportedSymbol, 1> Symbols;
+  llvm::SmallVectorWithFlags<JsImportedSymbol, 1, 4> Symbols;
   // Whether some symbols were merged into this one. Controls if the module
   // reference needs re-formatting.
-  bool SymbolsMerged = false;
+  bool getSymbolsMerged() const { return Symbols.getFlag(3); }
+  void setSymbolsMerged(bool Value) { Symbols.setFlag(3, Value); }
   // The source location just after { and just before } in the import.
   // Extracted eagerly to allow modification of Symbols later on.
   SourceLocation SymbolsStart, SymbolsEnd;
@@ -99,8 +104,8 @@ struct JsModuleReference {
 };
 
 bool operator<(const JsModuleReference &LHS, const JsModuleReference &RHS) {
-  if (LHS.IsExport != RHS.IsExport)
-    return LHS.IsExport < RHS.IsExport;
+  if (LHS.getIsExport() != RHS.getIsExport())
+    return LHS.getIsExport() < RHS.getIsExport();
   if (LHS.Category != RHS.Category)
     return LHS.Category < RHS.Category;
   if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
@@ -167,8 +172,8 @@ class JavaScriptImportSorter : public TokenAnalyzer {
         ReferencesText += "\n";
         // Separate imports groups with two line breaks, but keep all exports
         // in a single group.
-        if (!Reference.IsExport &&
-            (Reference.IsExport != References[I + 1].IsExport ||
+        if (!Reference.getIsExport() &&
+            (Reference.getIsExport() != References[I + 1].getIsExport() ||
              Reference.Category != References[I + 1].Category)) {
           ReferencesText += "\n";
         }
@@ -261,13 +266,13 @@ class JavaScriptImportSorter : public TokenAnalyzer {
     const auto *Start = References.begin();
     SmallVector<JsModuleReference, 16> ReferencesSorted;
     while (Start != References.end()) {
-      while (Start != References.end() && Start->FormattingOff) {
+      while (Start != References.end() && Start->getFormattingOff()) {
         // Skip over all imports w/ disabled formatting.
         ReferencesSorted.push_back(*Start);
         ++Start;
       }
       SmallVector<JsModuleReference, 16> SortChunk;
-      while (Start != References.end() && !Start->FormattingOff) {
+      while (Start != References.end() && !Start->getFormattingOff()) {
         // Skip over all imports w/ disabled formatting.
         SortChunk.push_back(*Start);
         ++Start;
@@ -301,8 +306,8 @@ class JavaScriptImportSorter : public TokenAnalyzer {
       //   mismatching
       if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
           PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
-          Reference->IsExport != PreviousReference->IsExport ||
-          Reference->IsTypeOnly != PreviousReference->IsTypeOnly ||
+          Reference->getIsExport() != PreviousReference->getIsExport() ||
+          Reference->getIsTypeOnly() != PreviousReference->getIsTypeOnly() ||
           !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
           !PreviousReference->DefaultImport.empty() ||
           !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
@@ -312,8 +317,8 @@ class JavaScriptImportSorter : public TokenAnalyzer {
         continue;
       }
       // Merge symbols from identical imports.
-      PreviousReference->Symbols.append(Reference->Symbols);
-      PreviousReference->SymbolsMerged = true;
+      llvm::append_range(PreviousReference->Symbols, Reference->Symbols);
+      PreviousReference->setSymbolsMerged(true);
       // Remove the merged import.
       Reference = References.erase(Reference);
     }
@@ -321,19 +326,22 @@ class JavaScriptImportSorter : public TokenAnalyzer {
 
   // Appends ``Reference`` to ``Buffer``.
   void appendReference(std::string &Buffer, JsModuleReference &Reference) {
-    if (Reference.FormattingOff) {
+    if (Reference.getFormattingOff()) {
       Buffer +=
           getSourceText(Reference.Range.getBegin(), Reference.Range.getEnd());
       return;
     }
     // Sort the individual symbols within the import.
     // E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';`
-    SmallVector<JsImportedSymbol, 1> Symbols = Reference.Symbols;
+    SmallVector<JsImportedSymbol, 1> Symbols(Reference.Symbols.begin(),
+                                             Reference.Symbols.end());
     stable_sort(Symbols,
                 [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) {
                   return LHS.Symbol.compare_insensitive(RHS.Symbol) < 0;
                 });
-    if (!Reference.SymbolsMerged && Symbols == Reference.Symbols) {
+    if (!Reference.getSymbolsMerged() &&
+        llvm::ArrayRef<JsImportedSymbol>(Symbols) ==
+            llvm::ArrayRef<JsImportedSymbol>(Reference.Symbols)) {
       // Symbols didn't change, just emit the entire module reference.
       StringRef ReferenceStmt = getSourceText(Reference.Range);
       Buffer += ReferenceStmt;
@@ -401,7 +409,7 @@ class JavaScriptImportSorter : public TokenAnalyzer {
         continue;
       }
       JsModuleReference Reference;
-      Reference.FormattingOff = FormattingOff;
+      Reference.setFormattingOff(FormattingOff);
       Reference.Range.setBegin(Start);
       // References w/o a URL, e.g. export {A}, groups with RELATIVE.
       Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
@@ -415,8 +423,8 @@ class JavaScriptImportSorter : public TokenAnalyzer {
       Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
       LLVM_DEBUG({
         llvm::dbgs() << "JsModuleReference: {"
-                     << "formatting_off: " << Reference.FormattingOff
-                     << ", is_export: " << Reference.IsExport
+                     << "formatting_off: " << Reference.getFormattingOff()
+                     << ", is_export: " << Reference.getIsExport()
                      << ", cat: " << Reference.Category
                      << ", url: " << Reference.URL
                      << ", prefix: " << Reference.Prefix;
@@ -441,10 +449,10 @@ class JavaScriptImportSorter : public TokenAnalyzer {
                             JsModuleReference &Reference) {
     if (!Current || Current->isNoneOf(Keywords.kw_import, tok::kw_export))
       return false;
-    Reference.IsExport = Current->is(tok::kw_export);
+    Reference.setIsExport(Current->is(tok::kw_export));
 
     nextToken();
-    if (Current->isStringLiteral() && !Reference.IsExport) {
+    if (Current->isStringLiteral() && !Reference.getIsExport()) {
       // "import 'side-effect';"
       Reference.Category = JsModuleReference::ReferenceCategory::SIDE_EFFECT;
       Reference.URL =
@@ -487,7 +495,7 @@ class JavaScriptImportSorter : public TokenAnalyzer {
     // * as prefix from '...';
     if (Current->is(Keywords.kw_type) && Current->Next &&
         Current->Next->is(tok::star)) {
-      Reference.IsTypeOnly = true;
+      Reference.setIsTypeOnly(true);
       nextToken();
     }
     if (Current->isNot(tok::star))
@@ -507,12 +515,12 @@ class JavaScriptImportSorter : public TokenAnalyzer {
                           JsModuleReference &Reference) {
     if (Current->is(Keywords.kw_type) && Current->Next &&
         Current->Next->isOneOf(tok::identifier, tok::l_brace)) {
-      Reference.IsTypeOnly = true;
+      Reference.setIsTypeOnly(true);
       nextToken();
     }
 
     // eat a potential "import X, " prefix.
-    if (!Reference.IsExport && Current->is(tok::identifier)) {
+    if (!Reference.getIsExport() && Current->is(tok::identifier)) {
       Reference.DefaultImport = Current->TokenText;
       nextToken();
       if (Current->is(Keywords.kw_from))
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 382f15081ad74..2a67971468f7b 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -16,6 +16,7 @@
 #include "FormatToken.h"
 #include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Debug.h"
 
 #define DEBUG_TYPE "format-token-annotator"
@@ -125,10 +126,12 @@ class AnnotatingParser {
 public:
   AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
                    const AdditionalKeywords &Keywords,
-                   SmallVector<ScopeType> &Scopes)
-      : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
-        IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),
-        Keywords(Keywords), Scopes(Scopes), TemplateDeclarationDepth(0) {
+                   llvm::SmallVectorWithFlagsImpl<ScopeType> &Scopes)
+      : Contexts(decltype(this->Contexts)::withFlags(
+            unsigned(bool(Style.isCpp())) << 1)),
+        Style(Style), Line(Line), CurrentToken(Line.First),
+        LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
+        Scopes(Scopes), TemplateDeclarationDepth(0) {
     Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
     resetTokenMetadata();
   }
@@ -696,13 +699,13 @@ class AnnotatingParser {
     // In C++, this can happen either in array of templates (foo<int>[10])
     // or when array is a nested template type (unique_ptr<type1<type2>[]>).
     bool CppArrayTemplates =
-        IsCpp && Parent && Parent->is(TT_TemplateCloser) &&
+        getIsCpp() && Parent && Parent->is(TT_TemplateCloser) &&
         (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
          Contexts.back().ContextType == Context::TemplateArgument);
 
     const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
     const bool IsCpp11AttributeSpecifier =
-        isCppAttribute(IsCpp, *Left) || IsInnerSquare;
+        isCppAttribute(getIsCpp(), *Left) || IsInnerSquare;
 
     // Treat C# Attributes [STAThread] much like C++ attributes [[...]].
     bool IsCSharpAttributeSpecifier =
@@ -710,11 +713,12 @@ class AnnotatingParser {
         Contexts.back().InCSharpAttributeSpecifier;
 
     bool InsideInlineASM = Line.startsWith(tok::kw_asm);
-    bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp);
+    bool IsCppStructuredBinding = Left->isCppStructuredBinding(getIsCpp());
     bool StartsObjCMethodExpr =
         !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
-        IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&
-        Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
+        getIsCpp() && !IsCpp11AttributeSpecifier &&
+        !IsCSharpAttributeSpecifier && Contexts.back().CanBeExpression &&
+        Left->isNot(TT_LambdaLSquare) &&
         CurrentToken->isNoneOf(tok::l_brace, tok::r_square) &&
         // Do not consider '[' after a comma inside a braced initializer the
         // start of an ObjC method expression. In braced initializer lists,
@@ -749,7 +753,7 @@ class AnnotatingParser {
                  Contexts.back().ContextKind == tok::l_brace &&
                  Parent->isOneOf(tok::l_brace, tok::comma)) {
         Left->setType(TT_JsComputedPropertyName);
-      } else if (IsCpp && Contexts.back().ContextKind == tok::l_brace &&
+      } else if (getIsCpp() && Contexts.back().ContextKind == tok::l_brace &&
                  Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
         Left->setType(TT_DesignatedInitializerLSquare);
       } else if (IsCSharpAttributeSpecifier) {
@@ -1239,7 +1243,7 @@ class AnnotatingParser {
         if (Previous->is(TT_JsTypeOptionalQuestion))
           Previous = Previous->getPreviousNonComment();
         if ((CurrentToken->is(tok::colon) && !Style.isTableGen() &&
-             (!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
+             (!Contexts.back().ColonIsDictLiteral || !getIsCpp())) ||
             Style.isProto()) {
           OpeningBrace.setType(TT_DictLiteral);
           Scopes.back() = getScopeType(OpeningBrace);
@@ -1329,7 +1333,7 @@ class AnnotatingParser {
   }
 
   bool consumeToken() {
-    if (IsCpp) {
+    if (getIsCpp()) {
       const auto *Prev = CurrentToken->getPreviousNonComment();
       if (Prev && Prev->is(TT_AttributeRSquare) &&
           CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,
@@ -1518,7 +1522,7 @@ class AnnotatingParser {
         if (CurrentToken && CurrentToken->is(Keywords.kw_await))
           next();
       }
-      if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))
+      if (getIsCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await))
         next();
       Contexts.back().ColonIsForRangeExpr = true;
       if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
@@ -1607,7 +1611,7 @@ class AnnotatingParser {
         return false;
       break;
     case tok::l_brace:
-      if (IsCpp) {
+      if (getIsCpp()) {
         if (Tok->is(TT_RequiresExpressionLBrace))
           Line.Type = LT_RequiresExpression;
       } else if (Style.isTextProto()) {
@@ -1663,7 +1667,7 @@ class AnnotatingParser {
       if (Style.isProto())
         break;
       // Handle C++ user-defined conversion function.
-      if (IsCpp && CurrentToken) {
+      if (getIsCpp() && CurrentToken) {
         const auto *Info = CurrentToken->Tok.getIdentifierInfo();
         // What follows Tok is an identifier or a non-operator keyword.
         if (Info && !(CurrentToken->isPlacementOperator() ||
@@ -1806,7 +1810,7 @@ class AnnotatingParser {
                        Keywords.kw___has_include_next)) {
         parseHasInclude();
       }
-      if (IsCpp) {
+      if (getIsCpp()) {
         if (Next && Next->is(tok::l_paren) && Prev &&
             Prev->isOneOf(tok::kw___cdecl, tok::kw___stdcall,
                           tok::kw___fastcall, tok::kw___thiscall,
@@ -1819,7 +1823,7 @@ class AnnotatingParser {
           Tok->setType(TT_CSharpGenericTypeConstraint);
           parseCSharpGenericTypeConstraint();
           if (!Prev)
-            Line.IsContinuation = true;
+            Line.setIsContinuation(true);
         }
       } else if (Style.isTableGen()) {
         if (Tok->is(Keywords.kw_assert)) {
@@ -2456,13 +2460,13 @@ class AnnotatingParser {
       // having multiple variable declarations.
       Contexts.back().FirstStartOfName = nullptr;
     } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
-      AutoFound = true;
+      setAutoFound(true);
     } else if (Current.is(tok::arrow) && Style.isJava()) {
       Current.setType(TT_LambdaArrow);
     } else if (Current.is(tok::arrow) && Style.isVerilog()) {
       // The implication operator.
       Current.setType(TT_BinaryOperator);
-    } else if (Current.is(tok::arrow) && AutoFound &&
+    } else if (Current.is(tok::arrow) && getAutoFound() &&
                Line.MightBeFunctionDecl && Current.NestingLevel == 0 &&
                Current.Previous->isNoneOf(tok::kw_operator, tok::identifier)) {
       // not auto operator->() -> xxx;
@@ -2502,7 +2506,7 @@ class AnnotatingParser {
         Current.setType(TT_Unknown);
       } else {
         Current.setType(TT_ConditionalExpr);
-        if (IsCpp)
+        if (getIsCpp())
           Contexts.back().IsExpression = true;
       }
     } else if (Current.isBinaryOperator() &&
@@ -2740,7 +2744,7 @@ class AnnotatingParser {
   /// Determine whether '(' is starting a C++ cast.
   bool lParenStartsCppCast(const FormatToken &Tok) {
     // C-style casts are only used in C++.
-    if (!IsCpp)
+    if (!getIsCpp())
       return false;
 
     FormatToken *LeftOfParens = Tok.getPreviousNonComment();
@@ -2766,7 +2770,7 @@ class AnnotatingParser {
       return false;
 
     // C-style casts are only used in C++, C# and Java.
-    if (!IsCpp && !Style.isCSharp() && !Style.isJava())
+    if (!getIsCpp() && !Style.isCSharp() && !Style.isJava())
       return false;
 
     const auto *LParen = Tok.MatchingParen;
@@ -2850,7 +2854,7 @@ class AnnotatingParser {
     if (AfterRParen->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
                              tok::kw_requires, tok::kw_throw, tok::arrow,
                              Keywords.kw_override, Keywords.kw_final) ||
-        isCppAttribute(IsCpp, *AfterRParen)) {
+        isCppAttribute(getIsCpp(), *AfterRParen)) {
       return false;
     }
 
@@ -3223,17 +3227,19 @@ class AnnotatingParser {
     return TT_UnaryOperator;
   }
 
-  SmallVector<Context, 8> Contexts;
+  llvm::SmallVectorWithFlags<Context, 8, 2> Contexts;
 
   const FormatStyle &Style;
   AnnotatedLine &Line;
   FormatToken *CurrentToken;
-  bool AutoFound;
-  bool IsCpp;
+  bool getAutoFound() const { return Contexts.getFlag(0); }
+  void setAutoFound(bool Value) { Contexts.setFlag(0, Value); }
+  bool getIsCpp() const { return Contexts.getFlag(1); }
+  void setIsCpp(bool Value) { Contexts.setFlag(1, Value); }
   LangOptions LangOpts;
   const AdditionalKeywords &Keywords;
 
-  SmallVector<ScopeType> &Scopes;
+  llvm::SmallVectorWithFlagsImpl<ScopeType> &Scopes;
 
   // Set of "<" tokens that do not open a template parameter list. If parseAngle
   // determines that a specific token can't be a template opener, it will make
@@ -3462,7 +3468,7 @@ class ExpressionParser {
     // unexpanded macro call. The line within the macro call contains
     // the parenthesis and commas, and we will not find operators within
     // that structure.
-    if (Start->MacroParent)
+    if (Start->getMacroParent())
       return;
 
     Start->FakeLParens.push_back(Precedence);
@@ -3662,7 +3668,7 @@ class ExpressionParser {
 } // end anonymous namespace
 
 void TokenAnnotator::setCommentLineLevels(
-    SmallVectorImpl<AnnotatedLine *> &Lines) const {
+    ArrayRef<AnnotatedLine *> Lines) const {
   const AnnotatedLine *NextNonCommentLine = nullptr;
   for (AnnotatedLine *Line : reverse(Lines)) {
     assert(Line->First);
@@ -3876,7 +3882,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
   ExpressionParser ExprParser(Style, Keywords, Line);
   ExprParser.parse();
 
-  if (IsCpp) {
+  if (getIsCpp()) {
     FormatToken *OpeningParen = nullptr;
     auto *Tok = getFunctionName(Line, OpeningParen);
     if (Tok && ((!ScopeStack.empty() && ScopeStack.back() == ST_Class) ||
@@ -4190,7 +4196,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
     }
   }
 
-  if (IsCpp) {
+  if (getIsCpp()) {
     if ((LineIsFunctionDeclaration ||
          (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) &&
         Line.endsWith(tok::semi, tok::r_brace)) {
@@ -4209,11 +4215,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
         mustBreakAfterAttributes(*AfterLastAttribute, Style)) {
       AfterLastAttribute->MustBreakBefore = true;
       if (LineIsFunctionDeclaration)
-        Line.ReturnTypeWrapped = true;
+        Line.setReturnTypeWrapped(true);
     }
 
     if (!LineIsFunctionDeclaration) {
-      Line.ReturnTypeWrapped = false;
+      Line.setReturnTypeWrapped(false);
       // Annotate */&/&& in `operator` function calls as binary operators.
       for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) {
         if (Tok->isNot(tok::kw_operator))
@@ -4265,7 +4271,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
         ReturnTypeStart->isNoneOf(TT_FunctionDeclarationName,
                                   TT_CtorDtorDeclName, tok::tilde)) {
       ReturnTypeStart->MustBreakBefore = true;
-      Line.ReturnTypeWrapped = true;
+      Line.setReturnTypeWrapped(true);
     }
   }
 
@@ -5206,7 +5212,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
     return Right.hasWhitespaceBefore();
 
   const bool IsVerilog = Style.isVerilog();
-  assert(!IsVerilog || !IsCpp);
+  assert(!IsVerilog || !getIsCpp());
 
   // Never ever merge two words.
   if (Keywords.isWordLike(Right, IsVerilog) &&
@@ -5232,7 +5238,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
 
   const auto *BeforeLeft = Left.Previous;
 
-  if (IsCpp) {
+  if (getIsCpp()) {
     if (Left.is(TT_OverloadedOperator) &&
         Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
       return true;
@@ -5663,7 +5669,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
   if (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) &&
       // In an unexpanded macro call we only find the parentheses and commas
       // in a line; the commas and closing parenthesis do not require a space.
-      (Left.Children.empty() || !Left.MacroParent)) {
+      (Left.Children.empty() || !Left.getMacroParent())) {
     return true;
   }
   if (Right.is(tok::comma))
@@ -5986,7 +5992,7 @@ bool TokenAnnotator::mustBreakBefore(AnnotatedLine &Line,
     if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
       return true;
   } else if (Style.BreakAdjacentStringLiterals &&
-             (IsCpp || Style.isProto() || Style.isTableGen())) {
+             (getIsCpp() || Style.isProto() || Style.isTableGen())) {
     if (Left.isStringLiteral() && Right.isStringLiteral())
       return true;
   }
@@ -6346,7 +6352,7 @@ bool TokenAnnotator::mustBreakBefore(AnnotatedLine &Line,
 
   if (Style.BreakAfterAttributes == FormatStyle::ABS_LeaveAll &&
       Left.is(TT_AttributeRSquare) && Right.NewlinesBefore > 0) {
-    Line.ReturnTypeWrapped = true;
+    Line.setReturnTypeWrapped(true);
     return true;
   }
 
@@ -6777,7 +6783,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
 
 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
   llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
-               << ", T=" << Line.Type << ", C=" << Line.IsContinuation
+               << ", T=" << Line.Type << ", C=" << Line.getIsContinuation()
                << "):\n";
   const FormatToken *Tok = Line.First;
   while (Tok) {
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index c909c39e92ea3..8045a1c688db9 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H
 
 #include "UnwrappedLineParser.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 namespace format {
@@ -51,8 +52,10 @@ enum ScopeType {
 class AnnotatedLine {
 public:
   AnnotatedLine(const UnwrappedLine &Line)
-      : First(Line.Tokens.front().Tok), Type(LT_Other), Level(Line.Level),
-        PPLevel(Line.PPLevel),
+      : First(Line.Tokens.front().Tok),
+        Children(decltype(this->Children)::withFlags(
+            unsigned(bool(Line.IsContinuation)) << 1)),
+        Type(LT_Other), Level(Line.Level), PPLevel(Line.PPLevel),
         MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
         MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
         InPPDirective(Line.InPPDirective),
@@ -62,7 +65,6 @@ class AnnotatedLine {
         MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
         IsMultiVariableDeclStmt(false), Affected(false),
         LeadingEmptyLinesAffected(false), ChildrenAffected(false),
-        ReturnTypeWrapped(false), IsContinuation(Line.IsContinuation),
         FirstStartColumn(Line.FirstStartColumn) {
     assert(!Line.Tokens.empty());
 
@@ -73,7 +75,7 @@ class AnnotatedLine {
     FormatToken *Current = First;
     addChildren(Line.Tokens.front(), Current);
     for (const UnwrappedLineNode &Node : llvm::drop_begin(Line.Tokens)) {
-      if (Node.Tok->MacroParent)
+      if (Node.Tok->getMacroParent())
         ContainsMacroCall = true;
       Current->Next = Node.Tok;
       Node.Tok->Previous = Current;
@@ -170,7 +172,7 @@ class AnnotatedLine {
   FormatToken *First;
   FormatToken *Last;
 
-  SmallVector<AnnotatedLine *, 0> Children;
+  llvm::SmallVectorWithFlags<AnnotatedLine *, 0, 2> Children;
 
   LineType Type;
   unsigned Level;
@@ -203,11 +205,19 @@ class AnnotatedLine {
   bool ChildrenAffected;
 
   /// \c True if breaking after last attribute group in function return type.
-  bool ReturnTypeWrapped;
+  bool getReturnTypeWrapped() const { return Children.getFlag(0); }
+  bool setReturnTypeWrapped(bool Value) {
+    Children.setFlag(0, Value);
+    return Value;
+  }
 
   /// \c True if this line should be indented by ContinuationIndent in addition
   /// to the normal indention level.
-  bool IsContinuation;
+  bool getIsContinuation() const { return Children.getFlag(1); }
+  bool setIsContinuation(bool Value) {
+    Children.setFlag(1, Value);
+    return Value;
+  }
 
   unsigned FirstStartColumn;
 
@@ -222,13 +232,14 @@ class AnnotatedLine {
 class TokenAnnotator {
 public:
   TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
-      : Style(Style), IsCpp(Style.isCpp()),
-        LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords) {}
+      : Style(Style), LangOpts(getFormattingLangOpts(Style)),
+        Keywords(Keywords), Scopes(decltype(Scopes)::withFlags(Style.isCpp())) {
+  }
 
   /// Adapts the indent levels of comment lines to the indent of the
   /// subsequent line.
   // FIXME: Can/should this be done in the UnwrappedLineParser?
-  void setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) const;
+  void setCommentLineLevels(ArrayRef<AnnotatedLine *> Lines) const;
 
   void annotate(AnnotatedLine &Line);
   void calculateFormattingInformation(AnnotatedLine &Line) const;
@@ -272,12 +283,13 @@ class TokenAnnotator {
 
   const FormatStyle &Style;
 
-  bool IsCpp;
+  bool getIsCpp() const { return Scopes.getFlag(0); }
   LangOptions LangOpts;
 
   const AdditionalKeywords &Keywords;
 
-  SmallVector<ScopeType> Scopes, MacroBodyScopes;
+  llvm::SmallVectorWithFlags<ScopeType> Scopes;
+  llvm::SmallVectorWithFlags<ScopeType> MacroBodyScopes;
 };
 
 } // end namespace format
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index e42a2083f7268..8c5960606254c 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -90,7 +90,7 @@ class LevelIndentTracker {
     }
     if (static_cast<int>(Indent) + Offset >= 0)
       Indent += Offset;
-    if (Line.IsContinuation)
+    if (Line.getIsContinuation())
       Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth;
   }
 
@@ -100,7 +100,7 @@ class LevelIndentTracker {
   /// level to the same indent.
   /// Note that \c nextLine must have been called before this method.
   void adjustToUnmodifiedLine(const AnnotatedLine &Line) {
-    if (Line.InPPDirective || Line.IsContinuation)
+    if (Line.InPPDirective || Line.getIsContinuation())
       return;
     assert(Line.Level < IndentForLevel.size());
     if (Line.First->is(tok::comment) && IndentForLevel[Line.Level] != -1)
@@ -1216,13 +1216,14 @@ class LineFormatter {
     const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
     bool HasLBrace = LBrace && LBrace->is(tok::l_brace) && LBrace->is(BK_Block);
     FormatToken &Previous = *State.NextToken->Previous;
-    if (Previous.Children.empty() || (!HasLBrace && !LBrace->MacroParent)) {
+    if (Previous.Children.empty() ||
+        (!HasLBrace && !LBrace->getMacroParent())) {
       // The previous token does not open a block. Nothing to do. We don't
       // assert so that we can simply call this function for all tokens.
       return true;
     }
 
-    if (NewLine || Previous.MacroParent) {
+    if (NewLine || Previous.getMacroParent()) {
       const ParenState &P = State.Stack.back();
 
       int AdditionalIndent =
@@ -1430,7 +1431,7 @@ class OptimizingLineFormatter : public LineFormatter {
       // Cut off the analysis of certain solutions if the analysis gets too
       // complex. See description of IgnoreStackForComparison.
       if (Count > 50'000)
-        Node->State.IgnoreStackForComparison = true;
+        Node->State.setIgnoreStackForComparison(true);
 
       if (!Seen.insert(&Node->State).second) {
         // State already examined with lower penalty.
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 901335950b9fa..2631593a45f73 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -123,7 +123,7 @@ class ScopedLineState {
       Parser.CurrentLines->truncate(OriginalNumLines);
     Parser.Line = std::move(PreBlockLine);
     if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
-      Parser.PP.AtEndOfPPLine = true;
+      Parser.PP.setAtEndOfPPLine(true);
     Parser.CurrentLines = OriginalLines;
   }
 
@@ -166,9 +166,11 @@ UnwrappedLineParser::UnwrappedLineParser(
     llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator,
     IdentifierTable &IdentTable)
     : Line(new UnwrappedLine), CurrentLines(&Lines), Style(Style),
-      IsCpp(Style.isCpp()), LangOpts(getFormattingLangOpts(Style)),
-      Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas),
-      Tokens(nullptr), Callback(Callback), AllTokens(Tokens),
+      LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
+      CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
+      Callback(Callback), AllTokens(Tokens),
+      NestedLambdas(decltype(this->NestedLambdas)::withFlags(
+          unsigned(bool(Style.isCpp())) << 1)),
       PP(getIncludeGuardState(Style.IndentPPDirectives)),
       FirstStartColumn(FirstStartColumn),
       Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}
@@ -181,8 +183,8 @@ void UnwrappedLineParser::reset() {
   Line.reset(new UnwrappedLine);
   CommentsBeforeNextToken.clear();
   FormatTok = nullptr;
-  PP.AtEndOfPPLine = false;
-  IsDecltypeAutoFunction = false;
+  PP.setAtEndOfPPLine(false);
+  setIsDecltypeAutoFunction(false);
   PreprocessorDirectives.clear();
   CurrentLines = &Lines;
   DeclarationScopeStack.clear();
@@ -197,7 +199,7 @@ void UnwrappedLineParser::reset() {
   CurrentExpandedLines.clear();
   ExpandedLines.clear();
   Unexpanded.clear();
-  InExpansion = false;
+  setInExpansion(false);
   Reconstruct.reset();
 }
 
@@ -583,8 +585,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
                                                  Keywords.kw_as));
           ProbablyBracedList =
               ProbablyBracedList ||
-              (IsCpp && (PrevTok->Tok.isLiteral() ||
-                         NextTok->isOneOf(tok::l_paren, tok::arrow)));
+              (getIsCpp() && (PrevTok->Tok.isLiteral() ||
+                              NextTok->isOneOf(tok::l_paren, tok::arrow)));
 
           // If there is a comma, or right paren after the closing brace, we
           // assume this is a braced initializer list.
@@ -624,7 +626,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
           }
 
           // Cpp macro definition body that is a nonempty braced list or block:
-          if (IsCpp && Line->InMacroBody && PrevTok != FormatTok &&
+          if (getIsCpp() && Line->InMacroBody && PrevTok != FormatTok &&
               !FormatTok->Previous && NextTok->is(tok::eof) &&
               // A statement can end with only `;` (simple statement), a block
               // closing brace (compound statement), or `:` (label statement).
@@ -1377,7 +1379,7 @@ static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,
 }
 
 bool UnwrappedLineParser::parseModuleDecl() {
-  assert(IsCpp);
+  assert(getIsCpp());
   assert(FormatTok->is(Keywords.kw_module));
 
   if (Style.Language == FormatStyle::LK_C ||
@@ -1400,7 +1402,7 @@ bool UnwrappedLineParser::parseModuleDecl() {
 }
 
 bool UnwrappedLineParser::parseImportDecl() {
-  assert(IsCpp);
+  assert(getIsCpp());
   assert(FormatTok->is(Keywords.kw_import) && "'import' expected");
 
   if (Style.Language == FormatStyle::LK_C ||
@@ -1493,7 +1495,7 @@ void UnwrappedLineParser::parseStructuralElement(
     return;
   }
 
-  if (IsCpp) {
+  if (getIsCpp()) {
     while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
     }
   } else if (Style.isVerilog()) {
@@ -1702,7 +1704,7 @@ void UnwrappedLineParser::parseStructuralElement(
     }
     break;
   case tok::kw_export:
-    if (IsCpp) {
+    if (getIsCpp()) {
       nextToken();
       if (FormatTok->is(tok::kw_namespace)) {
         parseNamespace();
@@ -1745,7 +1747,7 @@ void UnwrappedLineParser::parseStructuralElement(
       return;
     }
     if (FormatTok->is(Keywords.kw_import)) {
-      if (IsCpp && parseImportDecl())
+      if (getIsCpp() && parseImportDecl())
         return;
       if (Style.isJavaScript()) {
         parseJavaScriptEs6ImportExport();
@@ -1768,7 +1770,7 @@ void UnwrappedLineParser::parseStructuralElement(
         return;
       }
     }
-    if (IsCpp) {
+    if (getIsCpp()) {
       if (FormatTok->is(Keywords.kw_module) && parseModuleDecl())
         return;
       if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
@@ -1881,7 +1883,7 @@ void UnwrappedLineParser::parseStructuralElement(
       }
       break;
     case tok::kw_requires: {
-      if (IsCpp) {
+      if (getIsCpp()) {
         bool ParsedClause = parseRequires(SeenEqual);
         if (ParsedClause)
           return;
@@ -1903,7 +1905,7 @@ void UnwrappedLineParser::parseStructuralElement(
       if (!parseEnum())
         break;
       // This only applies to C++ and Verilog.
-      if (!IsCpp && !Style.isVerilog()) {
+      if (!getIsCpp() && !Style.isVerilog()) {
         addUnwrappedLine();
         return;
       }
@@ -1978,7 +1980,7 @@ void UnwrappedLineParser::parseStructuralElement(
       parseParens();
       // Break the unwrapped line if a K&R C function definition has a parameter
       // declaration.
-      if (OpeningBrace || !IsCpp || !Previous || eof())
+      if (OpeningBrace || !getIsCpp() || !Previous || eof())
         break;
       if (isC78ParameterDecl(FormatTok,
                              Tokens->peekNextToken(/*SkipComment=*/true),
@@ -2022,7 +2024,7 @@ void UnwrappedLineParser::parseStructuralElement(
       if (InRequiresExpression)
         FormatTok->setFinalizedType(TT_BracedListLBrace);
       if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
-        IsDecltypeAutoFunction = Line->SeenDecltypeAuto;
+        setIsDecltypeAutoFunction(Line->SeenDecltypeAuto);
         // A block outside of parentheses must be the last part of a
         // structural element.
         // FIXME: Figure out cases where this is not true, and add projections
@@ -2041,7 +2043,7 @@ void UnwrappedLineParser::parseStructuralElement(
         if (!Previous || Previous->isNot(TT_TypeDeclarationParen))
           FormatTok->setFinalizedType(TT_FunctionLBrace);
         parseBlock();
-        IsDecltypeAutoFunction = false;
+        setIsDecltypeAutoFunction(false);
         addUnwrappedLine();
         return;
       }
@@ -2116,13 +2118,13 @@ void UnwrappedLineParser::parseStructuralElement(
         }
       }
 
-      if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
+      if (!getIsCpp() && FormatTok->is(Keywords.kw_interface)) {
         if (parseStructLike())
           return;
         break;
       }
 
-      if (IsCpp && FormatTok->is(TT_StatementMacro)) {
+      if (getIsCpp() && FormatTok->is(TT_StatementMacro)) {
         parseStatementMacro();
         return;
       }
@@ -2374,7 +2376,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() {
 
 bool UnwrappedLineParser::tryToParseLambda() {
   assert(FormatTok->is(tok::l_square));
-  if (!IsCpp) {
+  if (!getIsCpp()) {
     nextToken();
     return false;
   }
@@ -2516,7 +2518,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
       return false;
     }
   }
-  if (LeftSquare->isCppStructuredBinding(IsCpp))
+  if (LeftSquare->isCppStructuredBinding(getIsCpp()))
     return false;
   if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
     return false;
@@ -2757,7 +2759,7 @@ bool UnwrappedLineParser::parseParens(TokenType StarAndAmpTokenType,
             }
             const bool ReturnParens =
                 Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement &&
-                ((NestedLambdas.empty() && !IsDecltypeAutoFunction) ||
+                ((NestedLambdas.empty() && !getIsDecltypeAutoFunction()) ||
                  (!NestedLambdas.empty() && !NestedLambdas.back())) &&
                 Prev->isOneOf(tok::kw_return, tok::kw_co_return) &&
                 FormatTok->is(tok::semi);
@@ -3434,7 +3436,7 @@ void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {
   // JS' for await ( ...
   if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
     nextToken();
-  if (IsCpp && FormatTok->is(tok::kw_co_await))
+  if (getIsCpp() && FormatTok->is(tok::kw_co_await))
     nextToken();
   if (HasParens && FormatTok->is(tok::l_paren)) {
     // The type is only set for Verilog basically because we were afraid to
@@ -3944,7 +3946,7 @@ bool UnwrappedLineParser::parseEnum() {
   if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
     return false;
 
-  if (IsCpp) {
+  if (getIsCpp()) {
     // Eat up enum class ...
     if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
       nextToken();
@@ -3975,7 +3977,7 @@ bool UnwrappedLineParser::parseEnum() {
       nextToken();
       // If there are two identifiers in a row, this is likely an elaborate
       // return type. In Java, this can be "implements", etc.
-      if (IsCpp && FormatTok->is(tok::identifier))
+      if (getIsCpp() && FormatTok->is(tok::identifier))
         return false;
     }
   }
@@ -4783,7 +4785,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
   // If the current line was expanded from a macro call, we use it to
   // reconstruct an unwrapped line from the structure of the expanded unwrapped
   // line and the unexpanded token stream.
-  if (!parsingPPDirective() && !InExpansion && containsExpansion(*Line)) {
+  if (!parsingPPDirective() && !getInExpansion() && containsExpansion(*Line)) {
     if (!Reconstruct)
       Reconstruct.emplace(Line->Level, Unexpanded);
     Reconstruct->addLine(*Line);
@@ -5155,11 +5157,11 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
       // call with its expansion.
       auto PreCall = std::move(Line);
       Line.reset(new UnwrappedLine);
-      bool OldInExpansion = InExpansion;
-      InExpansion = true;
+      bool OldInExpansion = getInExpansion();
+      setInExpansion(true);
       // We parse the macro call into a new line.
       auto Args = parseMacroCall(SavedPPState);
-      InExpansion = OldInExpansion;
+      setInExpansion(OldInExpansion);
       assert(Line->Tokens.front().Tok == ID);
       // And remember the unexpanded macro call tokens.
       auto UnexpandedLine = std::move(Line);
@@ -5319,12 +5321,12 @@ UnwrappedLineParser::parseMacroCall(const PPState &SavedPPState) {
 
 void UnwrappedLineParser::pushToken(FormatToken *Tok) {
   Line->Tokens.push_back(UnwrappedLineNode(Tok));
-  if (PP.AtEndOfPPLine) {
+  if (PP.getAtEndOfPPLine()) {
     auto &Tok = *Line->Tokens.back().Tok;
     Tok.MustBreakBefore = true;
     Tok.MustBreakBeforeFinalized = true;
     Tok.FirstAfterPPLine = true;
-    PP.AtEndOfPPLine = false;
+    PP.setAtEndOfPPLine(false);
   }
 }
 
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 2e1755ad3b2c6..0073bfc69b26a 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -17,6 +17,7 @@
 
 #include "Macros.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <stack>
 
 namespace clang {
@@ -299,7 +300,8 @@ class UnwrappedLineParser {
 
   // For recursive macro expansions, trigger reconstruction only on the
   // outermost expansion.
-  bool InExpansion = false;
+  bool getInExpansion() const { return NestedLambdas.getFlag(0); }
+  void setInExpansion(bool Value) { NestedLambdas.setFlag(0, Value); }
 
   // Set while we reconstruct a macro call.
   // For reconstruction, we feed the expanded lines into the reconstructor
@@ -333,7 +335,8 @@ class UnwrappedLineParser {
   llvm::BitVector DeclarationScopeStack;
 
   const FormatStyle &Style;
-  bool IsCpp;
+  bool getIsCpp() const { return NestedLambdas.getFlag(1); }
+  void setIsCpp(bool Value) { NestedLambdas.setFlag(1, Value); }
   LangOptions LangOpts;
   const AdditionalKeywords &Keywords;
 
@@ -350,11 +353,14 @@ class UnwrappedLineParser {
 
   // Keeps a stack of the states of nested lambdas (true if the return type of
   // the lambda is `decltype(auto)`).
-  SmallVector<bool, 4> NestedLambdas;
+  llvm::SmallVectorWithFlags<bool, 4, 3> NestedLambdas;
 
   // Whether the parser is parsing the body of a function whose return type is
   // `decltype(auto)`.
-  bool IsDecltypeAutoFunction = false;
+  bool getIsDecltypeAutoFunction() const { return NestedLambdas.getFlag(2); }
+  void setIsDecltypeAutoFunction(bool Value) {
+    NestedLambdas.setFlag(2, Value);
+  }
 
   // Represents preprocessor branch type, so we can find matching
   // #if/#else/#endif directives.
@@ -409,7 +415,7 @@ class UnwrappedLineParser {
     SmallVector<int, 8> LevelBranchIndex;
 
     // Contains the maximum number of branches at each nesting level.
-    SmallVector<int, 8> LevelBranchCount;
+    llvm::SmallVectorWithFlags<int, 8> LevelBranchCount;
 
     // Contains the number of branches per nesting level we are currently
     // in while parsing a preprocessor branch sequence.
@@ -425,7 +431,11 @@ class UnwrappedLineParser {
     FormatToken *IncludeGuardToken = nullptr;
 
     // Has just finished parsing a preprocessor line.
-    bool AtEndOfPPLine = false;
+    bool getAtEndOfPPLine() const { return LevelBranchCount.getFlag(0); }
+    bool setAtEndOfPPLine(bool Value) {
+      LevelBranchCount.setFlag(0, Value);
+      return Value;
+    }
   } PP;
 
   // The hash tokens of the parsed preprocessor directives. The lines of a
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index cd2feb3a5964b..bf976d72d7f48 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -346,7 +346,7 @@ static void
 AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
                    unsigned Column, bool RightJustify,
                    ArrayRef<unsigned> Matches,
-                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
+                   MutableArrayRef<WhitespaceManager::Change> Changes) {
   unsigned OriginalMatchColumn = 0;
   int Shift = 0;
 
@@ -504,7 +504,7 @@ enum class AlignStrategy { Normal, Macro, CaseBody, CaseColon };
 // lookahead.
 template <typename F, AlignStrategy Strategy = AlignStrategy::Normal>
 static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
-                            SmallVector<WhitespaceManager::Change, 16> &Changes,
+                            MutableArrayRef<WhitespaceManager::Change> Changes,
                             unsigned StartAt,
                             const FormatStyle::AlignConsecutiveStyle &ACS = {},
                             bool RightJustify = false) {
@@ -1670,7 +1670,7 @@ void WhitespaceManager::appendNewlineText(std::string &Text, const Change &C) {
   if (C.NewlinesBefore <= 0)
     return;
 
-  StringRef Newline = UseCRLF ? "\r\n" : "\n";
+  StringRef Newline = getUseCRLF() ? "\r\n" : "\n";
   Text.append(Newline);
 
   if (C.Tok->HasFormFeedBefore)
@@ -1688,7 +1688,7 @@ void WhitespaceManager::appendEscapedNewlineText(
         std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
     for (unsigned i = 0; i < Newlines; ++i) {
       Text.append(Spaces, ' ');
-      Text.append(UseCRLF ? "\\\r\n" : "\\\n");
+      Text.append(getUseCRLF() ? "\\\r\n" : "\\\n");
       Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
     }
   }
diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h
index 66a064ae81dbf..eb837a6875a5d 100644
--- a/clang/lib/Format/WhitespaceManager.h
+++ b/clang/lib/Format/WhitespaceManager.h
@@ -17,6 +17,7 @@
 
 #include "TokenAnnotator.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 namespace format {
@@ -36,9 +37,10 @@ class WhitespaceManager {
 public:
   WhitespaceManager(const SourceManager &SourceMgr, const FormatStyle &Style,
                     bool UseCRLF)
-      : SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {}
+      : Changes(decltype(this->Changes)::withFlags(unsigned(UseCRLF))),
+        SourceMgr(SourceMgr), Style(Style) {}
 
-  bool useCRLF() const { return UseCRLF; }
+  bool useCRLF() const { return getUseCRLF(); }
 
   /// Infers whether the input is using CRLF.
   static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF);
@@ -375,11 +377,12 @@ class WhitespaceManager {
   unsigned appendTabIndent(std::string &Text, unsigned Spaces,
                            unsigned Indentation);
 
-  SmallVector<Change, 16> Changes;
+  llvm::SmallVectorWithFlags<Change, 16> Changes;
   const SourceManager &SourceMgr;
   tooling::Replacements Replaces;
   const FormatStyle &Style;
-  bool UseCRLF;
+  bool getUseCRLF() const { return Changes.getFlag(0); }
+  void setUseCRLF(bool Value) { Changes.setFlag(0, Value); }
 };
 
 } // namespace format
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 738fe99cef46b..f4bc2323d4d17 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -221,7 +221,9 @@ static std::atomic<unsigned> ActiveASTUnitObjects;
 
 ASTUnit::ASTUnit(bool _MainFileIsAST)
     : CodeGenOpts(std::make_unique<CodeGenOptions>()),
-      MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
+      WantTiming(getenv("LIBCLANG_TIMING")),
+      PreambleDiagnostics(decltype(this->PreambleDiagnostics)::withFlags(
+          (unsigned(_MainFileIsAST) << 3))),
       ShouldCacheCodeCompletionResults(false),
       IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
       UnsafeToFree(false) {
@@ -231,7 +233,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
 
 ASTUnit::~ASTUnit() {
   // If we loaded from an AST file, balance out the BeginSourceFile call.
-  if (MainFileIsAST && getDiagnostics().getClient()) {
+  if (getMainFileIsAST() && getDiagnostics().getClient()) {
     getDiagnostics().getClient()->EndSourceFile();
   }
 
@@ -711,7 +713,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
   }();
 
   AST->LangOpts = std::make_unique<LangOptions>(LangOpts);
-  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->setOnlyLocalDeclsFlag(OnlyLocalDecls);
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->DiagOpts = DiagOpts;
   AST->Diagnostics = Diags;
@@ -1349,7 +1351,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
 
     llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
         PreambleInvocationIn, MainFileBuffer.get(), Bounds, Diagnostics, VFS,
-        PCHContainerOps, StorePreamblesInMemory, PreambleStoragePath,
+        PCHContainerOps, getStorePreamblesInMemory(), PreambleStoragePath,
         Callbacks);
 
     PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =
@@ -1386,7 +1388,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
 
   checkAndRemoveNonDriverDiags(NewPreambleDiags);
   StoredDiagnostics = std::move(NewPreambleDiags);
-  PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);
+  PreambleDiagnostics.assign(std::move(NewPreambleDiagsStandalone));
 
   // If the hash of top-level entities differs from the hash of the top-level
   // entities the last time we rebuilt the preamble, clear out the completion
@@ -1432,7 +1434,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
     Target = CI.getTargetPtr();
   Reader = CI.getASTReader();
   ModCache = CI.getModuleCachePtr();
-  HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
+  setHadModuleLoaderFatalFailure(CI.hadModuleLoaderFatalFailure());
   if (Invocation != CI.getInvocationPtr()) {
     // This happens when Parse creates a copy of \c Invocation to modify.
     ModifiedInvocation = CI.getInvocationPtr();
@@ -1516,7 +1518,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
     // Override the resources path.
     CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
   }
-  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->setOnlyLocalDeclsFlag(OnlyLocalDecls);
   AST->CaptureDiagnostics = CaptureDiagnostics;
   if (PrecompilePreambleAfterNParses > 0)
     AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;
@@ -1688,7 +1690,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
   *AST->CodeGenOpts = CI->getCodeGenOpts();
   AST->DiagOpts = DiagOpts;
   AST->Diagnostics = Diags;
-  AST->OnlyLocalDecls = OnlyLocalDecls;
+  AST->setOnlyLocalDeclsFlag(OnlyLocalDecls);
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->TUKind = TUKind;
   AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
@@ -2190,7 +2192,7 @@ void ASTUnit::CodeComplete(
 }
 
 bool ASTUnit::Save(StringRef File) {
-  if (HadModuleLoaderFatalFailure)
+  if (getHadModuleLoaderFatalFailure())
     return true;
 
   // FIXME: Can we somehow regenerate the stat cache here, or do we need to
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 7a552a572ca78..e3003aed327b7 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -183,7 +183,7 @@ clang::createChainedIncludesSource(CompilerInstance &CI,
 
     ParseAST(Clang->getSema());
     Clang->getDiagnosticClient().EndSourceFile();
-    assert(Buffer->IsComplete && "serialization did not complete");
+    assert(Buffer->getIsComplete() && "serialization did not complete");
     auto &serialAST = Buffer->Data;
     SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(
         StringRef(serialAST.data(), serialAST.size())));
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index f122208d6b4c8..1510318a2e039 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -615,7 +615,7 @@ struct ReadModuleNames : ASTReaderListener {
     for (const std::string &LoadedModule : LoadedModules) {
       if (Module *M = PP.getHeaderSearchInfo().getModuleMap().findOrLoadModule(
               LoadedModule)) {
-        M->HasIncompatibleModuleFile = true;
+        M->setHasIncompatibleModuleFile(true);
 
         // Mark module as available if the only reason it was unavailable
         // was missing headers.
@@ -623,8 +623,9 @@ struct ReadModuleNames : ASTReaderListener {
         Stack.push_back(M);
         while (!Stack.empty()) {
           Module *Current = Stack.pop_back_val();
-          if (Current->IsUnimportable) continue;
-          Current->IsAvailable = true;
+          if (Current->getIsUnimportable())
+            continue;
+          Current->setIsAvailable(true);
           auto SubmodulesRange = Current->submodules();
           llvm::append_range(Stack, SubmodulesRange);
         }
@@ -1477,7 +1478,7 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompile(
 
   auto Instance = cloneForModuleCompileImpl(
       ImportLoc, ModuleName,
-      FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
+      FrontendInputFile(FakeModuleMapFile, IK, +Module->getIsSystem()),
       ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName,
       Module->getDirectoryDependencies(), std::move(ThreadSafeConfig));
 
@@ -1960,7 +1961,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
     return nullptr;
   }
   if (ModuleFilename.empty()) {
-    if (M && M->HasIncompatibleModuleFile) {
+    if (M && M->getHasIncompatibleModuleFile()) {
       // We tried and failed to load a module file for this module. Fall
       // back to textual inclusion for its headers.
       return ModuleLoadResult::ConfigMismatch;
@@ -2155,7 +2156,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
       while (!Worklist.empty()) {
         clang::Module *M = Worklist.back();
         Worklist.pop_back();
-        M->IsFromModuleFile = true;
+        M->setIsFromModuleFile(true);
         for (clang::Module *SubM : M->submodules())
           Worklist.push_back(SubM);
       }
@@ -2272,7 +2273,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
   // Make the named module visible, if it's not already part of the module
   // we are parsing.
   if (ModuleName != getLangOpts().CurrentModule) {
-    if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
+    if (!Module->getIsFromModuleFile() && !MapPrivateSubModToTopLevel) {
       // We have an umbrella header or directory that doesn't actually include
       // all of the headers within the directory it covers. Complain about
       // this missing submodule and recover by forgetting that we ever saw
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 001ad1fd1e654..883d43e3d781f 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -630,7 +630,7 @@ static std::error_code collectModuleHeaderIncludes(
       // the module map file) so this will find the same file that we found
       // while parsing the module map.
       addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
-                       Module->IsExternC);
+                       Module->getIsExternC());
     }
   }
   // Note that Module->PrivateHeaders will not be a TopHeader.
@@ -641,7 +641,7 @@ static std::error_code collectModuleHeaderIncludes(
     if (Module->Parent)
       // Include the umbrella header for submodules.
       addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,
-                       Includes, LangOpts, Module->IsExternC);
+                       Includes, LangOpts, Module->getIsExternC());
   } else if (std::optional<Module::DirectoryName> UmbrellaDir =
                  Module->getUmbrellaDirAsWritten()) {
     // Add all of the headers we find in this subdirectory.
@@ -697,7 +697,7 @@ static std::error_code collectModuleHeaderIncludes(
 
       // Include this header as part of the umbrella directory.
       Module->addTopHeader(*Header);
-      addHeaderInclude(RelPath, Includes, LangOpts, Module->IsExternC);
+      addHeaderInclude(RelPath, Includes, LangOpts, Module->getIsExternC());
     }
   }
 
@@ -802,8 +802,8 @@ static Module *prepareToBuildModule(CompilerInstance &CI,
     }
     if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID(
                                   CI.getSourceManager().getMainFileID())) {
-      auto FileCharacter =
-          M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
+      auto FileCharacter = M->getIsSystem() ? SrcMgr::C_System_ModuleMap
+                                            : SrcMgr::C_User_ModuleMap;
       FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID(
           *OriginalModuleMap, FileCharacter);
       CI.getPreprocessor()
@@ -839,7 +839,7 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) {
   if (std::optional<Module::Header> UmbrellaHeader =
           M->getUmbrellaHeaderAsWritten())
     addHeaderInclude(UmbrellaHeader->PathRelativeToRootModuleDirectory,
-                     HeaderContents, CI.getLangOpts(), M->IsExternC);
+                     HeaderContents, CI.getLangOpts(), M->getIsExternC());
   Err = collectModuleHeaderIncludes(
       CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
       CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,
@@ -1204,7 +1204,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
         return false;
 
       // Reinitialize the main file entry to refer to the new input.
-      auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
+      auto Kind =
+          CurrentModule->getIsSystem() ? SrcMgr::C_System : SrcMgr::C_User;
       auto &SourceMgr = CI.getSourceManager();
       auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind);
       assert(BufferID.isValid() && "couldn't create module buffer ID");
@@ -1331,7 +1332,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     if (!CI.loadModuleFile(ModuleFileName::makeExplicit(ModuleFile), Loaded))
       return false;
 
-    if (Loaded && Loaded->StandardCXXModule)
+    if (Loaded && Loaded->getStandardCXXModule())
       CI.getDiagnostics().Report(
           diag::warn_eagerly_load_for_standard_cplusplus_modules);
   }
@@ -1342,7 +1343,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
     if (!CI.loadModuleFile(ModuleFile, Loaded))
       return false;
 
-    if (Loaded && Loaded->StandardCXXModule)
+    if (Loaded && Loaded->getStandardCXXModule())
       CI.getDiagnostics().Report(
           diag::warn_eagerly_load_for_standard_cplusplus_modules);
   }
diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp
index fc45b295d4e14..9b27e9916d792 100644
--- a/clang/lib/Frontend/HeaderIncludeGen.cpp
+++ b/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -12,6 +12,7 @@
 #include "clang/Frontend/Utils.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -79,17 +80,19 @@ class HeaderIncludesCallback : public PPCallbacks {
 class HeaderIncludesJSONCallback : public PPCallbacks {
   SourceManager &SM;
   raw_ostream *OutputFile;
-  bool OwnsOutputFile;
-  SmallVector<std::string, 16> IncludedHeaders;
+  bool getOwnsOutputFile() const { return IncludedHeaders.getFlag(0); }
+  void setOwnsOutputFile(bool Value) { IncludedHeaders.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<std::string, 16> IncludedHeaders;
 
 public:
   HeaderIncludesJSONCallback(const Preprocessor *PP, raw_ostream *OutputFile_,
                              bool OwnsOutputFile_)
       : SM(PP->getSourceManager()), OutputFile(OutputFile_),
-        OwnsOutputFile(OwnsOutputFile_) {}
+        IncludedHeaders(
+            decltype(IncludedHeaders)::withFlags(unsigned(OwnsOutputFile_))) {}
 
   ~HeaderIncludesJSONCallback() override {
-    if (OwnsOutputFile)
+    if (getOwnsOutputFile())
       delete OutputFile;
   }
 
diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp
index 9bf18b4d897ce..fceca3f9af86f 100644
--- a/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -258,7 +258,7 @@ class PrecompilePreambleAction : public ASTFrontendAction {
 
   void setEmittedPreamblePCH(ASTWriter &Writer) {
     if (FileOS) {
-      *FileOS << Buffer->Data;
+      *FileOS << StringRef(Buffer->Data.data(), Buffer->Data.size());
       // Make sure it hits disk now.
       FileOS.reset();
     }
diff --git a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 20bfd35e2a7d3..6a766468acc8e 100644
--- a/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -17,6 +17,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitstream/BitCodes.h"
 #include "llvm/Support/FileSystem.h"
@@ -44,8 +45,8 @@ class AbbreviationMap {
   }
 };
 
-typedef SmallVector<uint64_t, 64> RecordData;
-typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+typedef llvm::SmallVectorWithFlags<uint64_t, 64> RecordData;
+typedef llvm::SmallVectorWithFlagsImpl<uint64_t> RecordDataImpl;
 typedef ArrayRef<uint64_t> RecordDataRef;
 
 class SDiagsWriter;
@@ -238,8 +239,7 @@ class SDiagsWriter : public DiagnosticConsumer {
   /// consumer.
   struct SharedState {
     SharedState(StringRef File, DiagnosticOptions &DiagOpts)
-        : DiagOpts(DiagOpts), Stream(Buffer), OutputFile(File.str()),
-          EmittedAnyDiagBlocks(false) {}
+        : DiagOpts(DiagOpts), Stream(Buffer), OutputFile(File.str()) {}
 
     /// Diagnostic options.
     DiagnosticOptions DiagOpts;
@@ -277,7 +277,8 @@ class SDiagsWriter : public DiagnosticConsumer {
     /// Whether we have already started emission of any DIAG blocks. Once
     /// this becomes \c true, we never close a DIAG block until we know that we're
     /// starting another one or we're done.
-    bool EmittedAnyDiagBlocks;
+    bool getEmittedAnyDiagBlocks() const { return Record.getFlag(0); }
+    void setEmittedAnyDiagBlocks(bool Value) { Record.setFlag(0, Value); }
 
     /// Engine for emitting diagnostics about the diagnostics.
     std::unique_ptr<DiagnosticsEngine> MetaDiagnostics;
@@ -582,11 +583,11 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   // for beginDiagnostic, in case associated notes are emitted before we get
   // there.
   if (DiagLevel != DiagnosticsEngine::Note) {
-    if (State->EmittedAnyDiagBlocks)
+    if (State->getEmittedAnyDiagBlocks())
       ExitDiagBlock();
 
     EnterDiagBlock();
-    State->EmittedAnyDiagBlocks = true;
+    State->setEmittedAnyDiagBlocks(true);
   }
 
   // Compute the diagnostic text.
@@ -777,11 +778,11 @@ SDiagsWriter::~SDiagsWriter() {
     return;
 
   // Finish off any diagnostic we were in the process of emitting.
-  if (State->EmittedAnyDiagBlocks)
+  if (State->getEmittedAnyDiagBlocks())
     ExitDiagBlock();
 
   if (MergeChildRecords) {
-    if (!State->EmittedAnyDiagBlocks)
+    if (!State->getEmittedAnyDiagBlocks())
       // We have no diagnostics of our own, so we can just leave the child
       // process' output alone
       return;
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index 6f599ababcaf5..7b4d3f98e1dea 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -13,6 +13,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/Sema/HeuristicResolver.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 using namespace clang;
 using namespace index;
@@ -23,16 +24,18 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
   IndexingContext &IndexCtx;
   const NamedDecl *Parent;
   const DeclContext *ParentDC;
-  bool IsBase;
-  SmallVector<SymbolRelation, 3> Relations;
+  bool getIsBase() const { return Relations.getFlag(0); }
+  void setIsBase(bool Value) { Relations.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<SymbolRelation, 3> Relations;
 
   typedef RecursiveASTVisitor<TypeIndexer> base;
 
 public:
   TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
               const DeclContext *DC, bool isBase, bool isIBType)
-    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC), IsBase(isBase) {
-    if (IsBase) {
+      : IndexCtx(indexCtx), Parent(parent), ParentDC(DC),
+        Relations(decltype(this->Relations)::withFlags(unsigned(isBase))) {
+    if (getIsBase()) {
       assert(Parent);
       Relations.emplace_back((unsigned)SymbolRole::RelationBaseOf, Parent);
     }
@@ -65,7 +68,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
       return IndexCtx.handleReference(Underlying, Loc, Parent,
                                       ParentDC, SymbolRoleSet(), Relations);
     }
-    if (IsBase) {
+    if (getIsBase()) {
       TRY_TO(IndexCtx.handleReference(ND, Loc,
                                       Parent, ParentDC, SymbolRoleSet()));
       if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
@@ -181,10 +184,12 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
 
     // The relations we have to `Parent` do not apply to our template arguments,
     // so clear them while visiting the args.
-    SmallVector<SymbolRelation, 3> SavedRelations = Relations;
+    SmallVector<SymbolRelation, 3> SavedRelations(Relations.begin(),
+                                                  Relations.end());
     Relations.clear();
-    llvm::scope_exit ResetSavedRelations(
-        [&] { this->Relations = SavedRelations; });
+    llvm::scope_exit ResetSavedRelations([&] {
+      this->Relations.assign(SavedRelations.begin(), SavedRelations.end());
+    });
     for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
       if (!TraverseTemplateArgumentLoc(TL.getArgLoc(I)))
         return false;
diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp
index 76a2a0e698a8a..c74404641fdaa 100644
--- a/clang/lib/Lex/DependencyDirectivesScanner.cpp
+++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp
@@ -22,6 +22,7 @@
 #include "clang/Lex/Pragma.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
 #include <optional>
@@ -186,7 +187,12 @@ struct Scanner {
   /// true at the end.
   bool reportError(const char *CurPtr, unsigned Err);
 
-  bool ScanningPreprocessedModuleFile = false;
+  bool getScanningPreprocessedModuleFile() const {
+    return DirsWithToks.getFlag(0);
+  }
+  void setScanningPreprocessedModuleFile(bool Value) {
+    DirsWithToks.setFlag(0, Value);
+  }
   StringMap<char> SplitIds;
   StringRef Input;
   SmallVectorImpl<dependency_directives_scan::Token> &Tokens;
@@ -201,7 +207,7 @@ struct Scanner {
   /// The directives that were lexed along with the number of tokens that each
   /// directive contains. The tokens of all the directives are kept in \p Tokens
   /// vector, in the same order as the directives order in \p DirsWithToks.
-  SmallVector<DirectiveWithTokens, 64> DirsWithToks;
+  llvm::SmallVectorWithFlags<DirectiveWithTokens, 64> DirsWithToks;
   LangOptions LangOpts;
   Lexer TheLexer;
 };
@@ -735,9 +741,9 @@ bool Scanner::lexModule(const char *&First, const char *const End) {
   }
 
   StringRef Module =
-      ScanningPreprocessedModuleFile ? "__preprocessed_module" : "module";
+      getScanningPreprocessedModuleFile() ? "__preprocessed_module" : "module";
   StringRef Import =
-      ScanningPreprocessedModuleFile ? "__preprocessed_import" : "import";
+      getScanningPreprocessedModuleFile() ? "__preprocessed_import" : "import";
 
   if (Id != Module && Id != Import) {
     skipLine(First, End);
@@ -1059,7 +1065,7 @@ bool Scanner::scanImpl(const char *First, const char *const End) {
 }
 
 bool Scanner::scan(SmallVectorImpl<Directive> &Directives) {
-  ScanningPreprocessedModuleFile = clang::isPreprocessedModuleFile(Input);
+  setScanningPreprocessedModuleFile(clang::isPreprocessedModuleFile(Input));
   bool Error = scanImpl(Input.begin(), Input.end());
 
   if (!Error) {
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 906ce07b96a79..a752d266f30ac 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -617,7 +617,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
 static bool needModuleLookup(Module *RequestingModule,
                              bool HasSuggestedModule) {
   return HasSuggestedModule ||
-         (RequestingModule && RequestingModule->NoUndeclaredIncludes);
+         (RequestingModule && RequestingModule->getNoUndeclaredIncludes());
 }
 
 /// DoFrameworkLookup - Do a lookup of the specified file in the current
@@ -1880,7 +1880,8 @@ static bool suggestModule(HeaderSearch &HS, ModuleMap::KnownHeader Module,
                           ModuleMap::KnownHeader *SuggestedModule) {
   // If this module specifies [no_undeclared_includes], we cannot find any
   // file that's in a non-dependency module.
-  if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {
+  if (RequestingModule && Module &&
+      RequestingModule->getNoUndeclaredIncludes()) {
     HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false);
     if (!RequestingModule->directlyUses(Module.getModule())) {
       // Builtin headers are a special case. Multiple modules can use the same
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index b659780bac593..33f39eebd6e7c 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -27,6 +27,7 @@
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -37,6 +38,7 @@
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/Unicode.h"
 #include "llvm/Support/UnicodeCharRanges.h"
+#include <memory>
 
 #include <algorithm>
 #include <cassert>
@@ -171,16 +173,16 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
   HasLeadingEmptyMacro = false;
 
   // We are not after parsing a #.
-  ParsingPreprocessorDirective = false;
+  setParsingPreprocessorDirectiveFlag(false);
 
   // We are not after parsing #include.
-  ParsingFilename = false;
+  setParsingFilename(false);
 
   // We are not in raw mode.  Raw mode disables diagnostics and interpretation
   // of tokens (e.g. identifiers, thus disabling macro expansion).  It is used
   // to quickly lex the tokens of the buffer, e.g. when handling a "#if 0" block
   // or otherwise skipping over tokens.
-  LexingRawMode = false;
+  setLexingRawMode(false);
 
   // Default to not keeping comments.
   ExtendedTokenMode = 0;
@@ -215,7 +217,7 @@ Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts,
   InitLexer(BufStart, BufPtr, BufEnd);
 
   // We *are* in raw mode.
-  LexingRawMode = true;
+  setLexingRawMode(true);
 }
 
 /// Lexer constructor - Create a new raw lexer object.  This object is only
@@ -278,7 +280,7 @@ std::unique_ptr<Lexer> Lexer::Create_PragmaLexer(
 
   // Ensure that the lexer thinks it is inside a directive, so that end \n will
   // return an EOD token.
-  L->ParsingPreprocessorDirective = true;
+  L->setParsingPreprocessorDirectiveFlag(true);
 
   // This lexer really is for _Pragma.
   L->Is_PragmaLexer = true;
@@ -1860,7 +1862,7 @@ bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
       return false;
 
     bool DiagnoseAndContinue = !isLexingRawMode() &&
-                               !ParsingPreprocessorDirective &&
+                               !getParsingPreprocessorDirectiveFlag() &&
                                !PP->isPreprocessedOutput();
     if (!CheckCodepointValidInIdentifier(
             PP, LangOpts, CodePoint, makeCharRange(*this, CurPtr, UCNPtr),
@@ -1915,7 +1917,7 @@ bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr, Token &Result) {
       return false;
 
     bool DiagnoseAndContinue = !isLexingRawMode() &&
-                               !ParsingPreprocessorDirective &&
+                               !getParsingPreprocessorDirectiveFlag() &&
                                !PP->isPreprocessedOutput();
 
     if (!CheckCodepointValidInIdentifier(
@@ -1951,7 +1953,7 @@ bool Lexer::LexUnicodeIdentifierStart(Token &Result, uint32_t C,
                                       const char *CurPtr) {
   bool IsExtension = false;
   if (isAllowedInitiallyIDChar(C, LangOpts, IsExtension)) {
-    if (!isLexingRawMode() && !ParsingPreprocessorDirective &&
+    if (!isLexingRawMode() && !getParsingPreprocessorDirectiveFlag() &&
         !PP->isPreprocessedOutput()) {
       if (IsExtension)
         diagnoseMathematicalNotationInIdentifier(
@@ -1968,7 +1970,7 @@ bool Lexer::LexUnicodeIdentifierStart(Token &Result, uint32_t C,
     return LexIdentifierContinue(Result, CurPtr);
   }
 
-  if (!isLexingRawMode() && !ParsingPreprocessorDirective &&
+  if (!isLexingRawMode() && !getParsingPreprocessorDirectiveFlag() &&
       !PP->isPreprocessedOutput() && !isASCII(*BufferPtr) &&
       !isUnicodeWhitespace(C)) {
     // Non-ASCII characters tend to creep into source code unintentionally.
@@ -2077,7 +2079,7 @@ bool Lexer::LexIdentifierContinue(Token &Result, const char *CurPtr) {
 
   // If we are in raw mode, return this identifier raw.  There is no need to
   // look up identifier information or attempt to macro expand it.
-  if (LexingRawMode)
+  if (getLexingRawMode())
     return true;
 
   // Fill in Result.IdentifierInfo and update the token kind,
@@ -2338,7 +2340,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
       // The implementation-defined semantics cannot be taken as causing '\' to
       // "escape" the following " because there is no provision for " in a
       // q-char-sequence.
-      if (ParsingFilename && C == '"')
+      if (getParsingFilename() && C == '"')
         CurPtr = SavedCurPtr;
     }
 
@@ -2352,7 +2354,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
 
     if (C == 0) {
       if (isCodeCompletionPoint(CurPtr-1)) {
-        if (ParsingFilename)
+        if (getParsingFilename())
           codeCompleteIncludedFile(AfterQuote, CurPtr - 1, /*IsAngled=*/false);
         else
           PP->CodeCompleteNaturalLanguage();
@@ -2643,7 +2645,7 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr) {
     if (!isVerticalWhitespace(Char))
       break;
 
-    if (ParsingPreprocessorDirective) {
+    if (getParsingPreprocessorDirectiveFlag()) {
       // End of preprocessor directive line, let LexTokenInternal handle this.
       BufferPtr = CurPtr;
       return false;
@@ -2774,9 +2776,9 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr) {
     // we'll handle it below.
     const char *OldPtr = CurPtr;
     bool OldRawMode = isLexingRawMode();
-    LexingRawMode = true;
+    setLexingRawMode(true);
     C = getAndAdvanceChar(CurPtr, Result);
-    LexingRawMode = OldRawMode;
+    setLexingRawMode(OldRawMode);
 
     // If we only read only one character, then no special handling is needed.
     // We're done and can skip forward to the newline.
@@ -2835,7 +2837,7 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr) {
 
   // If we are inside a preprocessor directive and we see the end of line,
   // return immediately, so that the lexer can return this as an EOD token.
-  if (ParsingPreprocessorDirective || CurPtr == BufferEnd) {
+  if (getParsingPreprocessorDirectiveFlag() || CurPtr == BufferEnd) {
     BufferPtr = CurPtr;
     return false;
   }
@@ -2863,7 +2865,7 @@ bool Lexer::SaveLineComment(Token &Result, const char *CurPtr) {
   // directly.
   FormTokenWithChars(Result, CurPtr, tok::comment);
 
-  if (!ParsingPreprocessorDirective || LexingRawMode)
+  if (!getParsingPreprocessorDirectiveFlag() || getLexingRawMode())
     return true;
 
   // If this Line-style comment is in a macro definition, transmogrify it into
@@ -3195,7 +3197,8 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
 /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
 /// uninterpreted string.  This switches the lexer out of directive mode.
 void Lexer::ReadToEndOfLine(SmallVectorImpl<char> *Result) {
-  assert(ParsingPreprocessorDirective && ParsingFilename == false &&
+  assert(getParsingPreprocessorDirectiveFlag() &&
+         getParsingFilename() == false &&
          "Must be in a preprocessing directive!");
   Token Tmp;
   Tmp.startToken();
@@ -3254,9 +3257,9 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
   // If we hit the end of the file while parsing a preprocessor directive,
   // end the preprocessor directive first.  The next token returned will
   // then be the end of file.
-  if (ParsingPreprocessorDirective) {
+  if (getParsingPreprocessorDirectiveFlag()) {
     // Done parsing the "line".
-    ParsingPreprocessorDirective = false;
+    setParsingPreprocessorDirectiveFlag(false);
     // Update the location of token as well as BufferPtr.
     FormTokenWithChars(Result, CurPtr, tok::eod);
 
@@ -3312,7 +3315,8 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
 /// buffer controlled by this lexer, otherwise return the next unexpanded
 /// token.
 std::optional<Token> Lexer::peekNextPPToken() {
-  assert(!LexingRawMode && "How can we expand a macro from a skipping buffer?");
+  assert(!getLexingRawMode() &&
+         "How can we expand a macro from a skipping buffer?");
 
   if (isDependencyDirectivesLexer()) {
     if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
@@ -3326,11 +3330,11 @@ std::optional<Token> Lexer::peekNextPPToken() {
   // Switch to 'skipping' mode.  This will ensure that we can lex a token
   // without emitting diagnostics, disables macro expansion, and will cause EOF
   // to return an EOF token instead of popping the include stack.
-  LexingRawMode = true;
+  setLexingRawMode(true);
 
   // Save state that can be changed while lexing so that we can restore it.
   const char *TmpBufferPtr = BufferPtr;
-  bool inPPDirectiveMode = ParsingPreprocessorDirective;
+  bool inPPDirectiveMode = getParsingPreprocessorDirectiveFlag();
   bool atStartOfLine = IsAtStartOfLine;
   bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
   bool leadingSpace = HasLeadingSpace;
@@ -3341,13 +3345,13 @@ std::optional<Token> Lexer::peekNextPPToken() {
 
   // Restore state that may have changed.
   BufferPtr = TmpBufferPtr;
-  ParsingPreprocessorDirective = inPPDirectiveMode;
+  setParsingPreprocessorDirectiveFlag(inPPDirectiveMode);
   HasLeadingSpace = leadingSpace;
   IsAtStartOfLine = atStartOfLine;
   IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
   MIOpt = MIOptState;
   // Restore the lexer back to non-skipping mode.
-  LexingRawMode = false;
+  setLexingRawMode(false);
 
   if (Tok.is(tok::eof))
     return std::nullopt;
@@ -3473,7 +3477,8 @@ static const char *findPlaceholderEnd(const char *CurPtr,
 
 bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) {
   assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!");
-  if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders || LexingRawMode)
+  if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders ||
+      getLexingRawMode())
     return false;
   const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd);
   if (!End)
@@ -3935,9 +3940,9 @@ bool Lexer::LexTokenInternal(Token &Result) {
   case '\n':
     // If we are inside a preprocessor directive and we see the end of line,
     // we know we are done with the directive, so return an EOD token.
-    if (ParsingPreprocessorDirective) {
+    if (getParsingPreprocessorDirectiveFlag()) {
       // Done parsing the "line".
-      ParsingPreprocessorDirective = false;
+      setParsingPreprocessorDirectiveFlag(false);
 
       // Restore comment saving mode, in case it was disabled for directive.
       if (PP)
@@ -4166,8 +4171,8 @@ bool Lexer::LexTokenInternal(Token &Result) {
     // Notify MIOpt that we read a non-whitespace/non-comment token.
     MIOpt.ReadToken();
     return LexStringLiteral(Result, CurPtr,
-                            ParsingFilename ? tok::header_name
-                                            : tok::string_literal);
+                            getParsingFilename() ? tok::header_name
+                                                 : tok::string_literal);
 
   // C99 6.4.6: Punctuators.
   case '?':
@@ -4343,7 +4348,7 @@ bool Lexer::LexTokenInternal(Token &Result) {
         // it's actually the start of a preprocessing directive.  Callback to
         // the preprocessor to handle it.
         // TODO: -fpreprocessed mode??
-        if (Result.isAtPhysicalStartOfLine() && !LexingRawMode &&
+        if (Result.isAtPhysicalStartOfLine() && !getLexingRawMode() &&
             !Is_PragmaLexer)
           goto HandleDirective;
 
@@ -4355,7 +4360,7 @@ bool Lexer::LexTokenInternal(Token &Result) {
     break;
   case '<':
     Char = getCharAndSize(CurPtr, SizeTmp);
-    if (ParsingFilename && LexAngledStringLiteral(Result, CurPtr))
+    if (getParsingFilename() && LexAngledStringLiteral(Result, CurPtr))
       return true;
 
     if (Char == '<') {
@@ -4536,7 +4541,8 @@ bool Lexer::LexTokenInternal(Token &Result) {
       // it's actually the start of a preprocessing directive.  Callback to
       // the preprocessor to handle it.
       // TODO: -fpreprocessed mode??
-      if (Result.isAtPhysicalStartOfLine() && !LexingRawMode && !Is_PragmaLexer)
+      if (Result.isAtPhysicalStartOfLine() && !getLexingRawMode() &&
+          !Is_PragmaLexer)
         goto HandleDirective;
 
       Kind = tok::hash;
@@ -4547,13 +4553,20 @@ bool Lexer::LexTokenInternal(Token &Result) {
     // Objective C support.
     if (CurPtr[-1] == '@' && LangOpts.ObjC) {
       FormTokenWithChars(Result, CurPtr, tok::at);
-      if (PP && Result.isAtPhysicalStartOfLine() && !LexingRawMode &&
+      if (PP && Result.isAtPhysicalStartOfLine() && !getLexingRawMode() &&
           !Is_PragmaLexer) {
         Token NextPPTok;
         NextPPTok.startToken();
         {
-          llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
-              this->ParsingPreprocessorDirective, true);
+          auto SavedParsingPreprocessorDirective = [PackedFlagOwner_ = this] {
+            const bool PackedFlagOld_ =
+                PackedFlagOwner_->getParsingPreprocessorDirectiveFlag();
+            PackedFlagOwner_->setParsingPreprocessorDirectiveFlag(true);
+            return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+              PackedFlagOwner_->setParsingPreprocessorDirectiveFlag(
+                  PackedFlagOld_);
+            });
+          }();
           auto NextTokOr = peekNextPPToken();
           if (NextTokOr.has_value()) {
             NextPPTok = *NextTokOr;
@@ -4618,7 +4631,7 @@ bool Lexer::LexTokenInternal(Token &Result) {
       return LexUnicodeIdentifierStart(Result, CodePoint, CurPtr);
     }
 
-    if (isLexingRawMode() || ParsingPreprocessorDirective ||
+    if (isLexingRawMode() || getParsingPreprocessorDirectiveFlag() ||
         PP->isPreprocessedOutput()) {
       ++CurPtr;
       Kind = tok::unknown;
@@ -4703,7 +4716,7 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {
   }
 
   const char *DDTokPtr = BufferStart + DDTok.Offset;
-  if (ParsingFilename && *DDTokPtr == '<') {
+  if (getParsingFilename() && *DDTokPtr == '<') {
     Result.setFlag((clang::Token::TokenFlags)DDTok.Flags);
     Result.clearFlag(clang::Token::NeedsCleaning);
     BufferPtr = DDTokPtr;
@@ -4771,7 +4784,7 @@ bool Lexer::LexDependencyDirectiveToken(Token &Result) {
     return true;
   }
   if (Result.is(tok::eod))
-    ParsingPreprocessorDirective = false;
+    setParsingPreprocessorDirectiveFlag(false);
 
   return true;
 }
diff --git a/clang/lib/Lex/MacroArgs.cpp b/clang/lib/Lex/MacroArgs.cpp
index 548df16c59f6b..641ab93d73fe2 100644
--- a/clang/lib/Lex/MacroArgs.cpp
+++ b/clang/lib/Lex/MacroArgs.cpp
@@ -14,8 +14,10 @@
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include <algorithm>
+#include <memory>
 
 using namespace clang;
 
@@ -168,7 +170,13 @@ const std::vector<Token> &MacroArgs::getPreExpArgument(unsigned Arg,
   std::vector<Token> &Result = PreExpArgTokens[Arg];
   if (!Result.empty()) return Result;
 
-  SaveAndRestore PreExpandingMacroArgs(PP.InMacroArgPreExpansion, true);
+  auto PreExpandingMacroArgs = [PackedFlagOwner = std::addressof(PP)] {
+    const bool PackedFlagOld = PackedFlagOwner->getInMacroArgPreExpansion();
+    PackedFlagOwner->setInMacroArgPreExpansion(true);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setInMacroArgPreExpansion(PackedFlagOld);
+    });
+  }();
 
   const Token *AT = getUnexpArgument(Arg);
   unsigned NumToks = getArgLength(AT)+1;  // Include the EOF.
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index b75f5c98ba72b..600771299536b 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -56,14 +56,14 @@ void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
     for (auto &Name : PendingLinkAs->second) {
       auto *M = findModule(Name.getKey());
       if (M)
-        M->UseExportAsModuleLinkName = true;
+        M->setUseExportAsModuleLinkName(true);
     }
   }
 }
 
 void ModuleMap::addLinkAsDependency(Module *Mod) {
   if (findModule(Mod->ExportAsModule))
-    Mod->UseExportAsModuleLinkName = true;
+    Mod->setUseExportAsModuleLinkName(true);
   else
     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
 }
@@ -111,7 +111,7 @@ ModuleMap::resolveExport(Module *Mod,
                          bool Complain) const {
   // We may have just a wildcard.
   if (Unresolved.Id.empty()) {
-    assert(Unresolved.Wildcard && "Invalid unresolved export");
+    assert(Unresolved.getWildcard() && "Invalid unresolved export");
     return Module::ExportDecl(nullptr, true);
   }
 
@@ -120,11 +120,11 @@ ModuleMap::resolveExport(Module *Mod,
   if (!Context)
     return {};
 
-  return Module::ExportDecl(Context, Unresolved.Wildcard);
+  return Module::ExportDecl(Context, Unresolved.getWildcard());
 }
 
-Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
-                                   bool Complain) const {
+Module *ModuleMap::resolveModuleId(llvm::ArrayRef<ModuleId::value_type> Id,
+                                   Module *Mod, bool Complain) const {
   // Find the starting module.
   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
   if (!Context) {
@@ -160,7 +160,7 @@ static void appendSubframeworkPaths(Module *Mod,
   // Collect the framework names from the given module to the top-level module.
   SmallVector<StringRef, 2> Paths;
   for (; Mod; Mod = Mod->Parent) {
-    if (Mod->IsFramework)
+    if (Mod->getIsFramework())
       Paths.push_back(Mod->Name);
   }
 
@@ -212,7 +212,7 @@ OptionalFileEntryRef ModuleMap::findHeader(
     // 'framework module FrameworkName.Private', since a 'Private.Framework'
     // does not usually exist. However, since both are currently widely used
     // for private modules, make sure we find the right path in both cases.
-    if (M->IsFramework && M->Name == "Private")
+    if (M->getIsFramework() && M->Name == "Private")
       RelativePathName.clear();
     else
       RelativePathName.resize(RelativePathLength);
@@ -333,9 +333,10 @@ bool ModuleMap::resolveAsBuiltinHeader(
     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
   if (Header.Kind == Module::HK_Excluded ||
       llvm::sys::path::is_absolute(Header.FileName) ||
-      Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
+      Mod->isPartOfFramework() || !Mod->getIsSystem() || Header.IsUmbrella ||
       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
-      !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
+      !LangOpts.BuiltinHeadersInSystemModules ||
+      !isBuiltinHeaderName(Header.FileName))
     return false;
 
   // This is a system module with a top-level header. This header
@@ -413,7 +414,7 @@ bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
 bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
                                                         Module *Module) const {
   return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
-         Module->IsSystem && !Module->isPartOfFramework() &&
+         Module->getIsSystem() && !Module->isPartOfFramework() &&
          isBuiltinHeaderName(FileName);
 }
 
@@ -593,9 +594,9 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
              LangOpts.isCompilingModule()) {
     // Do not diagnose when we are not compiling a module.
-    diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
-        diag::warn_non_modular_include_in_framework_module :
-        diag::warn_non_modular_include_in_module;
+    diag::kind DiagID = RequestingModule->getTopLevelModule()->getIsFramework()
+                            ? diag::warn_non_modular_include_in_framework_module
+                            : diag::warn_non_modular_include_in_module;
     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
         << File.getName();
   }
@@ -763,13 +764,13 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
     while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
       UmbrellaModule = UmbrellaModule->Parent;
 
-    if (UmbrellaModule->InferSubmodules) {
+    if (UmbrellaModule->getInferSubmodules()) {
       FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);
 
       // Infer submodules for each of the directories we found between
       // the directory of the umbrella header and the directory where
       // the actual header is located.
-      bool Explicit = UmbrellaModule->InferExplicitSubmodules;
+      bool Explicit = UmbrellaModule->getInferExplicitSubmodules();
 
       for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
         // Find or create the module that corresponds to this directory name.
@@ -785,7 +786,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
 
         // If inferred submodules export everything they import, add a
         // wildcard to the set of exports.
-        if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
+        if (UmbrellaModule->getInferExportWildcard() && Result->Exports.empty())
           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
       }
 
@@ -800,7 +801,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
 
       // If inferred submodules export everything they import, add a
       // wildcard to the set of exports.
-      if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
+      if (UmbrellaModule->getInferExportWildcard() && Result->Exports.empty())
         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
     } else {
       // Record each of the directories we stepped through as being part of
@@ -897,7 +898,7 @@ bool ModuleMap::isHeaderUnavailableInModule(
              UmbrellaModule->Parent)
         UmbrellaModule = UmbrellaModule->Parent;
 
-      if (UmbrellaModule->InferSubmodules) {
+      if (UmbrellaModule->getInferSubmodules()) {
         for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
           // Find or create the module that corresponds to this directory name.
           SmallString<32> NameBuf;
@@ -948,15 +949,15 @@ Module *ModuleMap::findModule(StringRef Name) const {
 Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
   if (Module *SubM = Parent->findSubmodule(Name))
     return SubM;
-  if (!Parent->InferSubmodules)
+  if (!Parent->getInferSubmodules())
     return nullptr;
   Module *Result = new (ModulesAlloc.Allocate())
       Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
-             Parent->InferExplicitSubmodules, 0);
-  Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
-  Result->InferSubmodules = Parent->InferSubmodules;
-  Result->InferExportWildcard = Parent->InferExportWildcard;
-  if (Result->InferExportWildcard)
+             Parent->getInferExplicitSubmodules(), 0);
+  Result->setInferExplicitSubmodules(Parent->getInferExplicitSubmodules());
+  Result->setInferSubmodules(Parent->getInferSubmodules());
+  Result->setInferExportWildcard(Parent->getInferExportWildcard());
+  if (Result->getInferExportWildcard())
     Result->Exports.push_back(Module::ExportDecl(nullptr, true));
   return Result;
 }
@@ -1120,7 +1121,8 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
 /// For a framework module, infer the framework against which we
 /// should link.
 static void inferFrameworkLink(Module *Mod) {
-  assert(Mod->IsFramework && "Can only infer linking for framework modules");
+  assert(Mod->getIsFramework() &&
+         "Can only infer linking for framework modules");
   assert(!Mod->isSubFramework() &&
          "Can only infer linking for top-level frameworks");
 
@@ -1192,7 +1194,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
                          std::make_pair(*ParentDir, InferredDirectory())).first;
         }
 
-        if (inferred->second.InferModules) {
+        if (inferred->second.getInferModules()) {
           // We're allowed to infer for this directory, but make sure it's okay
           // to infer this particular module.
           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
@@ -1238,10 +1240,12 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
     ModuleScopeIDs[Result] = CurrentModuleScopeID;
   }
 
-  Result->IsSystem |= Attrs.IsSystem;
-  Result->IsExternC |= Attrs.IsExternC;
-  Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
-  Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
+  Result->setIsSystem(int(Result->getIsSystem()) | (Attrs.IsSystem));
+  Result->setIsExternC(int(Result->getIsExternC()) | (Attrs.IsExternC));
+  Result->setConfigMacrosExhaustive(int(Result->getConfigMacrosExhaustive()) |
+                                    (Attrs.IsExhaustive));
+  Result->setNoUndeclaredIncludes(int(Result->getNoUndeclaredIncludes()) |
+                                  (Attrs.NoUndeclaredIncludes));
   Result->Directory = FrameworkDir;
 
   // Chop off the first framework bit, as that is implied.
@@ -1257,8 +1261,8 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
 
   // module * { export * }
-  Result->InferSubmodules = true;
-  Result->InferExportWildcard = true;
+  Result->setInferSubmodules(true);
+  Result->setInferExportWildcard(true);
 
   // Look for subframeworks.
   std::error_code EC;
@@ -1602,7 +1606,7 @@ ModuleMap::getContainingModuleMapFile(const Module *Module) const {
 }
 
 FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
-  if (M->IsInferred) {
+  if (M->getIsInferred()) {
     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
     return InferredModuleAllowedBy.find(M)->second;
   }
@@ -1615,7 +1619,7 @@ ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
 }
 
 void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
-  M->IsInferred = true;
+  M->setIsInferred(true);
   InferredModuleAllowedBy[M] = ModMapFID;
 }
 
@@ -1694,7 +1698,8 @@ bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
 
 bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
   auto *Top = Mod->getTopLevelModule();
-  auto Unresolved = std::move(Top->UnresolvedDirectUses);
+  auto Unresolved =
+      SmallVector<ModuleId, 2>(std::move(Top->UnresolvedDirectUses));
   Top->UnresolvedDirectUses.clear();
   for (auto &UDU : Unresolved) {
     Module *DirectUse = resolveModuleId(UDU, Top, Complain);
@@ -1836,7 +1841,7 @@ void ModuleMapLoader::diagnosePrivateModules(SourceLocation StartLoc) {
       if (StartLoc.isValid())
         FixItInitBegin = StartLoc;
 
-      if (ActiveModule->Parent->IsFramework)
+      if (ActiveModule->Parent->getIsFramework())
         FixedPrivModDecl.append("framework ");
       FixedPrivModDecl.append("module ");
       FixedPrivModDecl.append(Canonical);
@@ -1909,7 +1914,7 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
     //  - If the Existing module was loaded from an AST file and we've found its
     //    original source module map, or we cannot determine Existing's
     //    definition location.
-    bool LoadedFromASTFile = Existing->IsFromModuleFile;
+    bool LoadedFromASTFile = Existing->getIsFromModuleFile();
     if (LoadedFromASTFile) {
       OptionalFileEntryRef ExistingModMapFile =
           Map.getContainingModuleMapFile(Existing);
@@ -1926,7 +1931,7 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
         LoadedFromASTFile = false;
     }
     //  - If we previously inferred this module from different module map file.
-    bool Inferred = Existing->IsInferred;
+    bool Inferred = Existing->getIsInferred();
     //  - If we're building a framework that vends a module map, we might've
     //    previously seen the one in intermediate products and now the system
     //    one.
@@ -1942,7 +1947,7 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
     //        that \c Existing is part of a framework iff the redefinition of FW
     //        we have just skipped had it too. Once we do that, stop checking
     //        the local framework qualifier and only rely on \c Existing.
-    bool PartOfFramework = MD.Framework || Existing->isPartOfFramework();
+    bool PartOfFramework = MD.getFramework() || Existing->isPartOfFramework();
     //  - If we're building a (preprocessed) module and we've just loaded the
     //    module map file from which it was created.
     bool ParsedAsMainInput =
@@ -1974,27 +1979,27 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
 
   // Start defining this module.
   if (ShadowingModule) {
-    ActiveModule =
-        Map.createShadowedModule(ModuleName, MD.Framework, ShadowingModule);
+    ActiveModule = Map.createShadowedModule(ModuleName, MD.getFramework(),
+                                            ShadowingModule);
   } else {
-    ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
-                                               MD.Framework, MD.Explicit);
+    ActiveModule = Map.findOrCreateModuleFirst(
+        ModuleName, ActiveModule, MD.getFramework(), MD.getExplicit());
   }
 
   ActiveModule->DefinitionLoc = ModuleNameLoc;
   if (MD.Attrs.IsSystem || IsSystem)
-    ActiveModule->IsSystem = true;
+    ActiveModule->setIsSystem(true);
   if (MD.Attrs.IsExternC)
-    ActiveModule->IsExternC = true;
+    ActiveModule->setIsExternC(true);
   if (MD.Attrs.NoUndeclaredIncludes)
-    ActiveModule->NoUndeclaredIncludes = true;
+    ActiveModule->setNoUndeclaredIncludes(true);
   ActiveModule->Directory = Directory;
 
   StringRef MapFileName(
       SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
   if (MapFileName.ends_with("module.private.modulemap") ||
       MapFileName.ends_with("module_private.map")) {
-    ActiveModule->ModuleMapIsPrivate = true;
+    ActiveModule->setModuleMapIsPrivate(true);
   }
 
   // Private modules named as FooPrivate, Foo.Private or similar are likely a
@@ -2007,7 +2012,7 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
                        StartLoc) &&
       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
                        StartLoc) &&
-      ActiveModule->ModuleMapIsPrivate)
+      ActiveModule->getModuleMapIsPrivate())
     diagnosePrivateModules(MD.Location);
 
   for (const modulemap::Decl &Decl : MD.Decls) {
@@ -2040,13 +2045,13 @@ void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
 
   // If the active module is a top-level framework, and there are no link
   // libraries, automatically link against the framework.
-  if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
+  if (ActiveModule->getIsFramework() && !ActiveModule->isSubFramework() &&
       ActiveModule->LinkLibraries.empty())
     inferFrameworkLink(ActiveModule);
 
   // If the module meets all requirements but is still unavailable, mark the
   // whole tree as unavailable to prevent it from building.
-  if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
+  if (!ActiveModule->getIsAvailable() && !ActiveModule->getIsUnimportable() &&
       ActiveModule->Parent) {
     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
     ActiveModule->getTopLevelModule()->MissingHeaders.append(
@@ -2315,7 +2320,7 @@ void ModuleMapLoader::handleConfigMacros(
   // TODO: Is this really the behavior we want for multiple config_macros
   //       declarations? If any of them are exhaustive then all of them are.
   if (CMD.Exhaustive) {
-    ActiveModule->ConfigMacrosExhaustive = true;
+    ActiveModule->setConfigMacrosExhaustive(true);
   }
   ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
                                     CMD.Macros.begin(), CMD.Macros.end());
@@ -2336,20 +2341,21 @@ void ModuleMapLoader::handleInferredModuleDecl(
   SourceLocation StarLoc = MD.Id.front().second;
 
   // Inferred modules must be submodules.
-  if (!ActiveModule && !MD.Framework) {
+  if (!ActiveModule && !MD.getFramework()) {
     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
     return;
   }
 
   if (ActiveModule) {
     // Inferred modules must have umbrella directories.
-    if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
+    if (ActiveModule->getIsAvailable() &&
+        !ActiveModule->getEffectiveUmbrellaDir()) {
       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
       return;
     }
 
     // Check for redefinition of an inferred module.
-    if (ActiveModule->InferSubmodules) {
+    if (ActiveModule->getInferSubmodules()) {
       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
       if (ActiveModule->InferredSubmoduleLoc.isValid())
         Diags.Report(ActiveModule->InferredSubmoduleLoc,
@@ -2358,24 +2364,24 @@ void ModuleMapLoader::handleInferredModuleDecl(
     }
 
     // Check for the 'framework' keyword, which is not permitted here.
-    if (MD.Framework) {
+    if (MD.getFramework()) {
       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
       return;
     }
-  } else if (MD.Explicit) {
+  } else if (MD.getExplicit()) {
     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
     return;
   }
 
   if (ActiveModule) {
     // Note that we have an inferred submodule.
-    ActiveModule->InferSubmodules = true;
+    ActiveModule->setInferSubmodules(true);
     ActiveModule->InferredSubmoduleLoc = StarLoc;
-    ActiveModule->InferExplicitSubmodules = MD.Explicit;
+    ActiveModule->setInferExplicitSubmodules(MD.getExplicit());
   } else {
     // We'll be inferring framework modules for this directory.
     auto &InfDir = Map.InferredDirectories[Directory];
-    InfDir.InferModules = true;
+    InfDir.setInferModules(true);
     InfDir.Attrs = MD.Attrs;
     InfDir.ModuleMapFID = ModuleMapFID;
     // FIXME: Handle the 'framework' keyword.
@@ -2412,7 +2418,7 @@ void ModuleMapLoader::handleInferredModuleDecl(
               }
 
               if (ED.Wildcard && ED.Id.size() == 0)
-                ActiveModule->InferExportWildcard = true;
+                ActiveModule->setInferExportWildcard(true);
               else
                 Diags.Report(ED.Id.front().second,
                              diag::err_mmap_expected_export_wildcard);
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index 4ca33cb86ddd3..0fc6f81d09598 100644
--- a/clang/lib/Lex/ModuleMapFile.cpp
+++ b/clang/lib/Lex/ModuleMapFile.cpp
@@ -122,13 +122,13 @@ struct ModuleMapFileParser {
 
   SourceLocation consumeToken();
   void skipUntil(MMToken::TokenKind K);
-  bool parseModuleId(ModuleId &Id);
+  template <typename ModuleIdT> bool parseModuleId(ModuleIdT &Id);
   bool parseOptionalAttributes(ModuleAttributes &Attrs);
 
   SourceLocation getLocation() const { return Tok.getLocation(); };
 };
 
-std::string formatModuleId(const ModuleId &Id) {
+std::string formatModuleId(llvm::ArrayRef<ModuleId::value_type> Id) {
   std::string result;
   {
     llvm::raw_string_ostream OS(result);
@@ -253,13 +253,13 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
   ModuleDecl MDecl;
 
   SourceLocation ExplicitLoc;
-  MDecl.Explicit = false;
-  MDecl.Framework = false;
+  MDecl.setExplicit(false);
+  MDecl.setFramework(false);
 
   // Parse 'explicit' keyword, if present.
   if (Tok.is(MMToken::ExplicitKeyword)) {
     MDecl.Location = ExplicitLoc = consumeToken();
-    MDecl.Explicit = true;
+    MDecl.setExplicit(true);
   }
 
   // Parse 'framework' keyword, if present.
@@ -267,7 +267,7 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
     SourceLocation FrameworkLoc = consumeToken();
     if (!MDecl.Location.isValid())
       MDecl.Location = FrameworkLoc;
-    MDecl.Framework = true;
+    MDecl.setFramework(true);
   }
 
   // Parse 'module' keyword.
@@ -286,7 +286,7 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
   if (Tok.is(MMToken::Star)) {
     SourceLocation StarLoc = consumeToken();
     MDecl.Id.push_back({"*", StarLoc});
-    if (TopLevel && !MDecl.Framework) {
+    if (TopLevel && !MDecl.getFramework()) {
       Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
       HadError = true;
       return std::nullopt;
@@ -305,10 +305,10 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
 
         HadError = true;
       }
-    } else if (MDecl.Id.size() == 1 && MDecl.Explicit) {
+    } else if (MDecl.Id.size() == 1 && MDecl.getExplicit()) {
       // Top-level modules can't be explicit.
       Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
-      MDecl.Explicit = false;
+      MDecl.setExplicit(false);
       HadError = true;
     }
   }
@@ -1032,7 +1032,8 @@ void ModuleMapFileParser::skipUntil(MMToken::TokenKind K) {
 ///     identifier '.' module-id
 ///
 /// \returns true if an error occurred, false otherwise.
-bool ModuleMapFileParser::parseModuleId(ModuleId &Id) {
+template <typename ModuleIdT>
+bool ModuleMapFileParser::parseModuleId(ModuleIdT &Id) {
   Id.clear();
   do {
     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 3d991c411378e..3d3b7325b9588 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -50,6 +50,7 @@
 #include <cassert>
 #include <cstddef>
 #include <cstring>
+#include <memory>
 #include <optional>
 #include <string>
 #include <utility>
@@ -566,9 +567,16 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
   // SkipExcludedConditionalBlock() recursively, SkippingRangeStateTy should
   // change to do a second lookup in endLexPass function instead of reusing the
   // lookup pointer.
-  assert(!SkippingExcludedConditionalBlock &&
+  assert(!getSkippingExcludedConditionalBlock() &&
          "calling SkipExcludedConditionalBlock recursively");
-  llvm::SaveAndRestore SARSkipping(SkippingExcludedConditionalBlock, true);
+  auto SARSkipping = [PackedFlagOwner = this] {
+    const bool PackedFlagOld =
+        PackedFlagOwner->getSkippingExcludedConditionalBlock();
+    PackedFlagOwner->setSkippingExcludedConditionalBlock(true);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setSkippingExcludedConditionalBlock(PackedFlagOld);
+    });
+  }();
 
   ++NumSkipped;
   assert(!CurTokenLexer && "Conditional PP block cannot appear in a macro!");
@@ -583,7 +591,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
 
   // Enter raw mode to disable identifier lookup (and thus macro expansion),
   // disabling warnings, etc.
-  CurPPLexer->LexingRawMode = true;
+  CurPPLexer->setLexingRawMode(true);
   Token Tok;
   SourceLocation endLoc;
 
@@ -672,19 +680,24 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
           if (II->getName()[0] == 'm') { // module
             // HandleModuleContextualKeyword changes the lexer state, so we need
             // to save RawLexingMode
-            llvm::SaveAndRestore RestoreLexingRawMode(CurPPLexer->LexingRawMode,
-                                                      false);
+            auto RestoreLexingRawMode = [PackedFlagOwner_ = CurPPLexer] {
+              const bool PackedFlagOld_ = PackedFlagOwner_->getLexingRawMode();
+              PackedFlagOwner_->setLexingRawMode(false);
+              return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+                PackedFlagOwner_->setLexingRawMode(PackedFlagOld_);
+              });
+            }();
             if (HandleModuleContextualKeyword(Tok)) {
               // We just parsed a # character at the start of a line, so we're
               // in directive mode.  Tell the lexer this so any newlines we see
               // will be converted into an EOD token (this terminates the
               // macro).
-              CurPPLexer->ParsingPreprocessorDirective = true;
+              CurPPLexer->setParsingPreprocessorDirectiveFlag(true);
               SourceLocation StartLoc = Tok.getLocation();
               SourceLocation End = DiscardUntilEndOfDirective().getEnd();
               Diag(StartLoc, diag::err_pp_cond_span_module_decl)
                   << SourceRange(StartLoc, End);
-              CurPPLexer->ParsingPreprocessorDirective = false;
+              CurPPLexer->setParsingPreprocessorDirectiveFlag(false);
               // Restore comment saving mode.
               if (CurLexer)
                 CurLexer->resetExtendedTokenMode();
@@ -718,7 +731,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
     // We just parsed a # character at the start of a line, so we're in
     // directive mode.  Tell the lexer this so any newlines we see will be
     // converted into an EOD token (this terminates the macro).
-    CurPPLexer->ParsingPreprocessorDirective = true;
+    CurPPLexer->setParsingPreprocessorDirectiveFlag(true);
     if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
 
     assert(Tok.is(tok::hash));
@@ -731,7 +744,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
     // If this isn't an identifier directive (e.g. is "# 1\n" or "#\n", or
     // something bogus), skip it.
     if (Tok.isNot(tok::raw_identifier)) {
-      CurPPLexer->ParsingPreprocessorDirective = false;
+      CurPPLexer->setParsingPreprocessorDirectiveFlag(false);
       // Restore comment saving mode.
       if (CurLexer) CurLexer->resetExtendedTokenMode();
       continue;
@@ -747,7 +760,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
     char FirstChar = RI[0];
     if (FirstChar >= 'a' && FirstChar <= 'z' &&
         FirstChar != 'i' && FirstChar != 'e') {
-      CurPPLexer->ParsingPreprocessorDirective = false;
+      CurPPLexer->setParsingPreprocessorDirectiveFlag(false);
       // Restore comment saving mode.
       if (CurLexer) CurLexer->resetExtendedTokenMode();
       continue;
@@ -764,7 +777,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
       std::string DirectiveStr = getSpelling(Tok);
       size_t IdLen = DirectiveStr.size();
       if (IdLen >= 20) {
-        CurPPLexer->ParsingPreprocessorDirective = false;
+        CurPPLexer->setParsingPreprocessorDirectiveFlag(false);
         // Restore comment saving mode.
         if (CurLexer) CurLexer->resetExtendedTokenMode();
         continue;
@@ -801,9 +814,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
           SkippingRangeState.endLexPass(Hashptr);
           // Restore the value of LexingRawMode so that trailing comments
           // are handled correctly, if we've reached the outermost block.
-          CurPPLexer->LexingRawMode = false;
+          CurPPLexer->setLexingRawMode(false);
           endLoc = CheckEndOfDirective("endif");
-          CurPPLexer->LexingRawMode = true;
+          CurPPLexer->setLexingRawMode(true);
           if (Callbacks)
             Callbacks->Endif(Tok.getLocation(), CondInfo.IfLoc);
           break;
@@ -832,9 +845,9 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
           CondInfo.FoundNonSkip = true;
           // Restore the value of LexingRawMode so that trailing comments
           // are handled correctly.
-          CurPPLexer->LexingRawMode = false;
+          CurPPLexer->setLexingRawMode(false);
           endLoc = CheckEndOfDirective("else");
-          CurPPLexer->LexingRawMode = true;
+          CurPPLexer->setLexingRawMode(true);
           if (Callbacks)
             Callbacks->Else(Tok.getLocation(), CondInfo.IfLoc);
           break;
@@ -862,15 +875,16 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
         } else {
           // Restore the value of LexingRawMode so that identifiers are
           // looked up, etc, inside the #elif expression.
-          assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
-          CurPPLexer->LexingRawMode = false;
+          assert(CurPPLexer->getLexingRawMode() &&
+                 "We have to be skipping here!");
+          CurPPLexer->setLexingRawMode(false);
           IdentifierInfo *IfNDefMacro = nullptr;
           DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
           // Stop if Lexer became invalid after hitting code completion token.
           if (!CurPPLexer)
             return;
           const bool CondValue = DER.Conditional;
-          CurPPLexer->LexingRawMode = true;
+          CurPPLexer->setLexingRawMode(true);
           if (Callbacks) {
             Callbacks->Elif(
                 Tok.getLocation(), DER.ExprRange,
@@ -914,11 +928,12 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
         } else {
           // Restore the value of LexingRawMode so that identifiers are
           // looked up, etc, inside the #elif[n]def expression.
-          assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
-          CurPPLexer->LexingRawMode = false;
+          assert(CurPPLexer->getLexingRawMode() &&
+                 "We have to be skipping here!");
+          CurPPLexer->setLexingRawMode(false);
           Token MacroNameTok;
           ReadMacroName(MacroNameTok);
-          CurPPLexer->LexingRawMode = true;
+          CurPPLexer->setLexingRawMode(true);
 
           // If the macro name token is tok::eod, there was an error that was
           // already reported.
@@ -958,7 +973,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
       SuggestTypoedDirective(Tok, Directive);
     }
 
-    CurPPLexer->ParsingPreprocessorDirective = false;
+    CurPPLexer->setParsingPreprocessorDirectiveFlag(false);
     // Restore comment saving mode.
     if (CurLexer) CurLexer->resetExtendedTokenMode();
   }
@@ -966,7 +981,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
   // Finally, if we are out of the conditional (saw an #endif or ran off the end
   // of the file, just stop skipping and return to lexing whatever came after
   // the #if block.
-  CurPPLexer->LexingRawMode = false;
+  CurPPLexer->setLexingRawMode(false);
 
   // The last skipped range isn't actually skipped yet if it's truncated
   // by the end of the preamble; we'll resume parsing after the preamble.
@@ -1111,7 +1126,7 @@ OptionalFileEntryRef Preprocessor::LookupFile(
                 ? HeaderInfo.getModuleMap().getBuiltinDir()
                 : MainFileDir;
         Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
-        BuildSystemModule = getCurrentModule()->IsSystem;
+        BuildSystemModule = getCurrentModule()->getIsSystem();
       } else if ((FileEnt = SourceMgr.getFileEntryRefForID(
                       SourceMgr.getMainFileID()))) {
         auto CWD = FileMgr.getOptionalDirectoryRef(".");
@@ -1297,11 +1312,12 @@ void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result,
       return HandleDefineDirective(Result,
                                    /*ImmediatelyAfterHeaderGuard=*/false);
     }
-    if (SkippingUntilPCHThroughHeader &&
+    if (getSkippingUntilPCHThroughHeader() &&
         II->getPPKeywordID() == tok::pp_include) {
       return HandleIncludeDirective(HashLoc, Result);
     }
-    if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
+    if (getSkippingUntilPragmaHdrStop() &&
+        II->getPPKeywordID() == tok::pp_pragma) {
       Lex(Result);
       auto *II = Result.getIdentifierInfo();
       if (II && II->getName() == "hdrstop")
@@ -1321,7 +1337,7 @@ void Preprocessor::HandleDirective(Token &Result) {
   // We just parsed a # or @ character at the start of a line, so we're in
   // directive mode.  Tell the lexer this so any newlines we see will be
   // converted into an EOD token (which terminates the directive).
-  CurPPLexer->ParsingPreprocessorDirective = true;
+  CurPPLexer->setParsingPreprocessorDirectiveFlag(true);
   if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
 
   bool ImmediatelyAfterTopLevelIfndef =
@@ -1381,7 +1397,7 @@ void Preprocessor::HandleDirective(Token &Result) {
   // and reset to previous state when returning from this function.
   ResetMacroExpansionHelper helper(this);
 
-  if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
+  if (getSkippingUntilPCHThroughHeader() || getSkippingUntilPragmaHdrStop())
     return HandleSkippedDirectiveWhileUsingPCH(Result,
                                                Introducer.getLocation());
 
@@ -2432,9 +2448,9 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
       IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
       LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
 
-  if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
+  if (usingPCHWithThroughHeader() && getSkippingUntilPCHThroughHeader()) {
     if (File && isPCHThroughHeader(&File->getFileEntry()))
-      SkippingUntilPCHThroughHeader = false;
+      setSkippingUntilPCHThroughHeader(false);
     return {ImportAction::None};
   }
 
@@ -2462,7 +2478,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
   // If we've reached the max allowed include depth, it is usually due to an
   // include cycle. Don't enter already processed files again as it can lead to
   // reaching the max allowed include depth again.
-  if (Action == Enter && HasReachedMaxIncludeDepth && File &&
+  if (Action == Enter && getHasReachedMaxIncludeDepth() && File &&
       alreadyIncluded(*File))
     Action = IncludeLimitReached;
 
@@ -2783,7 +2799,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
   // Check that we don't have infinite #include recursion.
   if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
     Diag(FilenameTok, diag::err_pp_include_too_deep);
-    HasReachedMaxIncludeDepth = true;
+    setHasReachedMaxIncludeDepth(true);
     return {ImportAction::None};
   }
 
@@ -3080,7 +3096,7 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
   // Ensure we consume the rest of the macro body if errors occur.
   llvm::scope_exit _([&]() {
     // The flag indicates if we are still waiting for 'eod'.
-    if (CurLexer->ParsingPreprocessorDirective)
+    if (CurLexer->getParsingPreprocessorDirectiveFlag())
       DiscardUntilEndOfDirective();
   });
 
@@ -3351,7 +3367,7 @@ void Preprocessor::HandleDefineDirective(
   }
 
   // When skipping just warn about macros that do not match.
-  if (SkippingUntilPCHThroughHeader) {
+  if (getSkippingUntilPCHThroughHeader()) {
     const MacroInfo *OtherMI = getMacroInfo(MacroNameTok.getIdentifierInfo());
     if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,
                              /*Syntactic=*/LangOpts.MicrosoftExt))
@@ -3653,7 +3669,7 @@ void Preprocessor::HandleEndifDirective(Token &EndifToken) {
   if (CurPPLexer->getConditionalStackDepth() == 0)
     CurPPLexer->MIOpt.ExitTopLevelConditional();
 
-  assert(!CondInfo.WasSkipping && !CurPPLexer->LexingRawMode &&
+  assert(!CondInfo.WasSkipping && !CurPPLexer->getLexingRawMode() &&
          "This code should only be reachable in the non-skipping case!");
 
   if (Callbacks)
@@ -4204,8 +4220,13 @@ void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc,
 /// lexed module name are replaced by annot_module_name token.
 void Preprocessor::HandleCXXImportDirective(Token ImportTok) {
   assert(getLangOpts().CPlusPlusModules && ImportTok.is(tok::kw_import));
-  llvm::SaveAndRestore<bool> SaveImportingCXXModules(
-      this->ImportingCXXNamedModules, true);
+  auto SaveImportingCXXModules = [PackedFlagOwner = this] {
+    const bool PackedFlagOld = PackedFlagOwner->getImportingCXXNamedModules();
+    PackedFlagOwner->setImportingCXXNamedModules(true);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setImportingCXXNamedModules(PackedFlagOld);
+    });
+  }();
 
   Token Tok;
   if (LexHeaderName(Tok)) {
@@ -4423,7 +4444,7 @@ void Preprocessor::HandleCXXModuleDirective(Token ModuleTok) {
 
   bool IsGMFIntroducer = DirToks.size() == 2 && DirToks[0].is(tok::kw_module) &&
                          DirToks[1].is(tok::semi);
-  bool IsSynthesizedGMF = IsGMFIntroducer && HasSynthesizedGMF &&
+  bool IsSynthesizedGMF = IsGMFIntroducer && getHasSynthesizedGMF() &&
                           CurPPLexer->getFileID() == getPredefinesFileID();
 
   if (!IncludeMacroStack.empty() && !IsSynthesizedGMF) {
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index eb614cba959a4..0244f62f8d9e1 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -30,11 +30,13 @@
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include <cassert>
+#include <memory>
 
 using namespace clang;
 
@@ -885,7 +887,13 @@ Preprocessor::DirectiveEvalResult
 Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,
                                           Token &Tok, bool &EvaluatedDefined,
                                           bool CheckForEoD) {
-  SaveAndRestore PPDir(ParsingIfOrElifDirective, true);
+  auto PPDir = [PackedFlagOwner = this] {
+    const bool PackedFlagOld = PackedFlagOwner->getParsingIfOrElifDirective();
+    PackedFlagOwner->setParsingIfOrElifDirective(true);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setParsingIfOrElifDirective(PackedFlagOld);
+    });
+  }();
   // Save the current state of 'DisableMacroExpansion' and reset it to false. If
   // 'DisableMacroExpansion' is true, then we must be in a macro argument list
   // in which case a directive is undefined behavior.  We want macros to be able
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index 552902e70f094..0dd9453939474 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -654,9 +654,9 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
     // mode (#if COMMENT) in which case we have to return it to that mode and
     // return EOD.
     FoundLexer = ISI.ThePPLexer;
-    FoundLexer->LexingRawMode = true;
-    LexerWasInPPMode = FoundLexer->ParsingPreprocessorDirective;
-    FoundLexer->ParsingPreprocessorDirective = true;
+    FoundLexer->setLexingRawMode(true);
+    LexerWasInPPMode = FoundLexer->getParsingPreprocessorDirectiveFlag();
+    FoundLexer->setParsingPreprocessorDirectiveFlag(true);
     break;
   }
 
@@ -678,14 +678,14 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
   if (Tok.is(tok::eod)) {
     assert(FoundLexer && "Can't get end of line without an active lexer");
     // Restore the lexer back to normal mode instead of raw mode.
-    FoundLexer->LexingRawMode = false;
+    FoundLexer->setLexingRawMode(false);
 
     // If the lexer was already in preprocessor mode, just return the EOD token
     // to finish the preprocessor line.
     if (LexerWasInPPMode) return;
 
     // Otherwise, switch out of PP mode and return the next lexed token.
-    FoundLexer->ParsingPreprocessorDirective = false;
+    FoundLexer->setParsingPreprocessorDirectiveFlag(false);
     return Lex(Tok);
   }
 
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index f55e9196bcd61..2f1d6ae13f7df 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -240,7 +240,7 @@ void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II,
     if (MI && NewMI != MI &&
         !MI->isIdenticalTo(*NewMI, *this, /*Syntactically=*/true))
       IsAmbiguous = true;
-    IsSystemMacro &= Active->getOwningModule()->IsSystem ||
+    IsSystemMacro &= Active->getOwningModule()->getIsSystem() ||
                      SourceMgr.isInSystemHeader(NewMI->getDefinitionLoc());
     MI = NewMI;
   }
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index 078842ab08c5e..61f3526923620 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -36,6 +36,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -130,19 +131,24 @@ namespace {
 // and return them to the stream to be read later.
 // Currently used when reading _Pragma/__pragma directives.
 struct TokenCollector {
+  TokenCollector(Preprocessor &Self, bool Collect, Token &Tok)
+      : Self(Self),
+        Tokens(decltype(this->Tokens)::withFlags(unsigned(Collect))), Tok(Tok) {
+  }
   Preprocessor &Self;
-  bool Collect;
-  SmallVector<Token, 3> Tokens;
+  bool getCollect() const { return Tokens.getFlag(0); }
+  void setCollect(bool Value) { Tokens.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<Token, 3> Tokens;
   Token &Tok;
 
   void lex() {
-    if (Collect)
+    if (getCollect())
       Tokens.push_back(Tok);
     Self.Lex(Tok);
   }
 
   void revert() {
-    assert(Collect && "did not collect tokens");
+    assert(getCollect() && "did not collect tokens");
     assert(!Tokens.empty() && "collected unexpected number of tokens");
 
     // Push the ( "string" ) tokens into the token stream.
@@ -175,8 +181,8 @@ void Preprocessor::HandlePragmaDirective(PragmaIntroducer Introducer) {
   PragmaHandlers->HandlePragma(*this, Introducer, Tok);
 
   // If the pragma handler didn't read the rest of the line, consume it now.
-  if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
-   || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
+  if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective()) ||
+      (CurPPLexer && CurPPLexer->getParsingPreprocessorDirectiveFlag()))
     DiscardUntilEndOfDirective();
 }
 
@@ -204,7 +210,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
   // In Case #2, we check the syntax now, but then put the tokens back into the
   // token stream for later consumption.
 
-  TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok};
+  TokenCollector Toks(*this, getInMacroArgPreExpansion(), Tok);
 
   // Remember the pragma token location.
   SourceLocation PragmaLoc = Tok.getLocation();
@@ -252,7 +258,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
   }
 
   // If we're expanding a macro argument, put the tokens back.
-  if (InMacroArgPreExpansion) {
+  if (getInMacroArgPreExpansion()) {
     Toks.revert();
     return;
   }
@@ -355,7 +361,7 @@ void clang::prepare_PragmaString(SmallVectorImpl<char> &StrVal) {
 void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
   // During macro pre-expansion, check the syntax now but put the tokens back
   // into the token stream for later consumption. Same as Handle_Pragma.
-  TokenCollector Toks = {*this, InMacroArgPreExpansion, {}, Tok};
+  TokenCollector Toks(*this, getInMacroArgPreExpansion(), Tok);
 
   // Remember the pragma token location.
   SourceLocation PragmaLoc = Tok.getLocation();
@@ -386,7 +392,7 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
   }
 
   // If we're expanding a macro argument, put the tokens back.
-  if (InMacroArgPreExpansion) {
+  if (getInMacroArgPreExpansion()) {
     Toks.revert();
     return;
   }
@@ -445,9 +451,11 @@ void Preprocessor::HandlePragmaPoison() {
     // This avoids errors on code like:
     //   #pragma GCC poison X
     //   #pragma GCC poison X
-    if (CurPPLexer) CurPPLexer->LexingRawMode = true;
+    if (CurPPLexer)
+      CurPPLexer->setLexingRawMode(true);
     LexUnexpandedToken(Tok);
-    if (CurPPLexer) CurPPLexer->LexingRawMode = false;
+    if (CurPPLexer)
+      CurPPLexer->setLexingRawMode(false);
 
     // If we reached the end of line, we're done.
     if (Tok.is(tok::eod)) return;
@@ -822,7 +830,7 @@ void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
     DiscardUntilEndOfDirective();
   }
 
-  CurLexer->LexingRawMode = true;
+  CurLexer->setLexingRawMode(true);
 
   auto TryConsumeIdentifier = [&](StringRef Ident) -> bool {
     if (Tok.getKind() != tok::raw_identifier ||
@@ -852,7 +860,7 @@ void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
 
     // We hit something directive-shaped; check to see if this is the end
     // of the module build.
-    CurLexer->ParsingPreprocessorDirective = true;
+    CurLexer->setParsingPreprocessorDirectiveFlag(true);
     CurLexer->Lex(Tok);
     if (TryConsumeIdentifier("pragma") && TryConsumeIdentifier("clang") &&
         TryConsumeIdentifier("module")) {
@@ -870,7 +878,7 @@ void Preprocessor::HandlePragmaModuleBuild(Token &Tok) {
     }
   }
 
-  CurLexer->LexingRawMode = false;
+  CurLexer->setLexingRawMode(false);
 
   // Load the extracted text as a preprocessed module.
   assert(CurLexer->getBuffer().begin() <= Start &&
@@ -910,7 +918,7 @@ void Preprocessor::HandlePragmaHdrstop(Token &Tok) {
     CurLexer->cutOffLexing();
   }
   if (usingPCHWithPragmaHdrStop())
-    SkippingUntilPragmaHdrStop = false;
+    setSkippingUntilPragmaHdrStop(false);
 }
 
 bool Preprocessor::isPragmaSetPPStateMacro(IdentifierInfo *MacroName) {
@@ -1206,7 +1214,7 @@ struct PragmaDebugHandler : public PragmaHandler {
             llvm::errs() << "\n";
           }
           for (Module *Sub : M->submodules()) {
-            if (!VisibleOnly || ImportLoc.isInvalid() || Sub->IsExplicit)
+            if (!VisibleOnly || ImportLoc.isInvalid() || Sub->getIsExplicit())
               visit(Sub, VisibleOnly);
           }
         }
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 84907adc5d744..96b77d3f80dca 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -103,7 +103,7 @@ Preprocessor::Preprocessor(const PreprocessorOptions &PPOpts,
   OwnsHeaderSearch = OwnsHeaders;
 
   // Only record check points if we might highlight diagnostic snippets.
-  RecordCheckPoints = getDiagnostics().getShowColors();
+  setRecordCheckPoints(getDiagnostics().getShowColors());
 
   // Default to discarding comments.
   KeepComments = false;
@@ -115,11 +115,11 @@ Preprocessor::Preprocessor(const PreprocessorOptions &PPOpts,
   MacroExpansionInDirectivesOverride = false;
   InMacroArgs = false;
   ArgMacro = nullptr;
-  InMacroArgPreExpansion = false;
+  setInMacroArgPreExpansion(false);
   NumCachedTokenLexers = 0;
   PragmasEnabled = true;
-  ParsingIfOrElifDirective = false;
-  PreprocessedOutput = false;
+  setParsingIfOrElifDirective(false);
+  setPreprocessedOutputFlag(false);
 
   // We haven't read anything from the external source.
   ReadMacrosFromExternalSource = false;
@@ -163,16 +163,16 @@ Preprocessor::Preprocessor(const PreprocessorOptions &PPOpts,
 
   // Default incremental processing to -fincremental-extensions, clients can
   // override with `enableIncrementalProcessing` if desired.
-  IncrementalProcessing = LangOpts.IncrementalExtensions;
+  setIncrementalProcessing(LangOpts.IncrementalExtensions);
 
   // If using a PCH where a #pragma hdrstop is expected, start skipping tokens.
   if (usingPCHWithPragmaHdrStop())
-    SkippingUntilPragmaHdrStop = true;
+    setSkippingUntilPragmaHdrStop(true);
 
   // If using a PCH with a through header, start skipping tokens.
   if (!this->PPOpts.PCHThroughHeader.empty() &&
       !this->PPOpts.ImplicitPCHInclude.empty())
-    SkippingUntilPCHThroughHeader = true;
+    setSkippingUntilPCHThroughHeader(true);
 
   if (this->PPOpts.GeneratePreamble)
     PreambleConditionalStack.startRecording();
@@ -626,9 +626,10 @@ void Preprocessor::EnterMainSourceFile() {
       std::optional<StringRef> Input =
           getSourceManager().getBufferDataOrNone(MainFileID);
       if (!isPreprocessedModuleFile() && Input)
-        MainFileIsPreprocessedModuleFile =
-            clang::isPreprocessedModuleFile(*Input);
-      if (Input && !MainFileIsPreprocessedModuleFile && hasDeferredGMFInputs())
+        setMainFileIsPreprocessedModuleFile(
+            clang::isPreprocessedModuleFile(*Input));
+      if (Input && !getMainFileIsPreprocessedModuleFile() &&
+          hasDeferredGMFInputs())
         MainFileModuleUnitKind = scanInputForCXX20ModuleUnit(*Input);
       auto Tracer = std::make_unique<NoTrivialPPDirectiveTracer>(*this);
       DirTracer = Tracer.get();
@@ -645,7 +646,7 @@ void Preprocessor::EnterMainSourceFile() {
   // GMF, synthesize the introducer before the main file and use the same
   // deferred-input path.
   if (hasDeferredGMFInputs()) {
-    if (PredefinesWereReplaced) {
+    if (getPredefinesWereReplaced()) {
       // Loading an implicit PCH replaces Predefines with the directives
       // suggested by ASTReader. For a module unit, those are the only implicit
       // inputs that still need to be processed in the GMF.
@@ -661,7 +662,7 @@ void Preprocessor::EnterMainSourceFile() {
     if (MainFileModuleUnitKind ==
         ModuleUnitKind::NamedModuleWithoutGlobalModuleFragment) {
       Predefines += "# 1 \"<implicit-global-module-fragment>\" 1\nmodule;\n";
-      HasSynthesizedGMF = true;
+      setHasSynthesizedGMF(true);
     } else if (MainFileModuleUnitKind == ModuleUnitKind::NotModuleUnit) {
       DeferredGMFInputs.clear();
     }
@@ -697,8 +698,8 @@ void Preprocessor::EnterMainSourceFile() {
   }
 
   // Skip tokens from the Predefines and if needed the main file.
-  if ((usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) ||
-      (usingPCHWithPragmaHdrStop() && SkippingUntilPragmaHdrStop))
+  if ((usingPCHWithThroughHeader() && getSkippingUntilPCHThroughHeader()) ||
+      (usingPCHWithPragmaHdrStop() && getSkippingUntilPragmaHdrStop()))
     SkipTokensWhileUsingPCH();
 }
 
@@ -753,8 +754,8 @@ bool Preprocessor::usingPCHWithPragmaHdrStop() {
 /// main file is reached, it's a fatal error.
 void Preprocessor::SkipTokensWhileUsingPCH() {
   bool ReachedMainFileEOF = false;
-  bool UsingPCHThroughHeader = SkippingUntilPCHThroughHeader;
-  bool UsingPragmaHdrStop = SkippingUntilPragmaHdrStop;
+  bool UsingPCHThroughHeader = getSkippingUntilPCHThroughHeader();
+  bool UsingPragmaHdrStop = getSkippingUntilPragmaHdrStop();
   Token Tok;
   while (true) {
     bool InPredefines =
@@ -764,9 +765,9 @@ void Preprocessor::SkipTokensWhileUsingPCH() {
       ReachedMainFileEOF = true;
       break;
     }
-    if (UsingPCHThroughHeader && !SkippingUntilPCHThroughHeader)
+    if (UsingPCHThroughHeader && !getSkippingUntilPCHThroughHeader())
       break;
-    if (UsingPragmaHdrStop && !SkippingUntilPragmaHdrStop)
+    if (UsingPragmaHdrStop && !getSkippingUntilPragmaHdrStop())
       break;
   }
   if (ReachedMainFileEOF) {
@@ -966,7 +967,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
   // Handle module contextual keywords.
   if (getLangOpts().CPlusPlusModules && CurLexer &&
       !CurLexer->isLexingRawMode() && !CurLexer->isPragmaLexer() &&
-      !CurLexer->ParsingPreprocessorDirective &&
+      !CurLexer->getParsingPreprocessorDirectiveFlag() &&
       Identifier.isModuleContextualKeyword() &&
       HandleModuleContextualKeyword(Identifier)) {
     HandleDirective(Identifier);
@@ -1068,7 +1069,7 @@ void Preprocessor::Lex(Token &Result) {
     }
   }
 
-  if (RecordCheckPoints && CurLexer &&
+  if (getRecordCheckPoints() && CurLexer &&
       ++CheckPointCounter == CheckPointStepSize) {
     CheckPoints[CurLexer->getFileID()].push_back(CurLexer->BufferPtr);
     CheckPointCounter = 0;
@@ -1085,7 +1086,7 @@ void Preprocessor::Lex(Token &Result) {
   if (LexLevel == 0 && !PendingDestroyLexers.empty())
     PendingDestroyLexers.clear();
 
-  if ((LexLevel == 0 || PreprocessToken) &&
+  if ((LexLevel == 0 || getPreprocessTokenFlag()) &&
       !Result.getFlag(Token::IsReinjected)) {
     if (LexLevel == 0)
       ++TokenCount;
@@ -1123,7 +1124,7 @@ bool Preprocessor::LexHeaderName(Token &FilenameTok, bool AllowMacroExpansion) {
   if (CurPPLexer) {
     // Avoid nested header-name lexing when macro expansion recurses
     // __has_include(__has_include))
-    if (CurPPLexer->ParsingFilename)
+    if (CurPPLexer->getParsingFilename())
       LexUnexpandedToken(FilenameTok);
     else
       CurPPLexer->LexIncludeFilename(FilenameTok);
@@ -1406,8 +1407,14 @@ bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
 
   assert(CurPPLexer && "CurPPLexer must not be null");
 
-  llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
-      CurPPLexer->ParsingPreprocessorDirective, true);
+  auto SavedParsingPreprocessorDirective = [PackedFlagOwner_ = CurPPLexer] {
+    const bool PackedFlagOld_ =
+        PackedFlagOwner_->getParsingPreprocessorDirectiveFlag();
+    PackedFlagOwner_->setParsingPreprocessorDirectiveFlag(true);
+    return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+      PackedFlagOwner_->setParsingPreprocessorDirectiveFlag(PackedFlagOld_);
+    });
+  }();
 
   if (II->isModuleKeyword()) {
     if (auto NextTok = peekNextPPToken()) {
@@ -1423,8 +1430,13 @@ bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
   }
 
   if (II->isImportKeyword()) {
-    llvm::SaveAndRestore<bool> SavedParsingFilename(CurPPLexer->ParsingFilename,
-                                                    true);
+    auto SavedParsingFilename = [PackedFlagOwner_ = CurPPLexer] {
+      const bool PackedFlagOld_ = PackedFlagOwner_->getParsingFilename();
+      PackedFlagOwner_->setParsingFilename(true);
+      return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+        PackedFlagOwner_->setParsingFilename(PackedFlagOld_);
+      });
+    }();
     if (auto NextTok = peekNextPPToken()) {
       if (NextTok->is(tok::raw_identifier))
         LookUpIdentifierInfo(*NextTok);
diff --git a/clang/lib/Lex/PreprocessorLexer.cpp b/clang/lib/Lex/PreprocessorLexer.cpp
index 3f483c56f8b12..d3dc44b4befb1 100644
--- a/clang/lib/Lex/PreprocessorLexer.cpp
+++ b/clang/lib/Lex/PreprocessorLexer.cpp
@@ -29,19 +29,19 @@ PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid)
 /// After the preprocessor has parsed a \#include, lex and
 /// (potentially) macro expand the filename.
 void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) {
-  assert(ParsingFilename == false && "reentered LexIncludeFilename");
+  assert(getParsingFilename() == false && "reentered LexIncludeFilename");
 
   // We are now parsing a filename!
-  ParsingFilename = true;
+  setParsingFilename(true);
 
   // Lex the filename.
-  if (LexingRawMode)
+  if (getLexingRawMode())
     IndirectLex(FilenameTok);
   else
     PP->Lex(FilenameTok);
 
   // We should have obtained the filename now.
-  ParsingFilename = false;
+  setParsingFilename(false);
 }
 
 /// getFileEntry - Return the FileEntry corresponding to this FileID.  Like
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 6b478ec2e36f6..832030bbac9d8 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -134,7 +134,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
     return FnD;
   }
 
-  if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) &&
+  if (getSkipFunctionBodies() && (!FnD || Actions.canSkipFunctionBody(FnD)) &&
       trySkippingFunctionBody()) {
     Actions.ActOnSkippedFunctionBody(FnD);
     return FnD;
@@ -335,10 +335,10 @@ struct Parser::ReenterClassScopeRAII : ReenterTemplateScopeRAII {
 
   ReenterClassScopeRAII(Parser &P, ParsingClass &Class)
       : ReenterTemplateScopeRAII(P, Class.TagOrTemplate,
-                                 /*Enter=*/!Class.TopLevelClass),
+                                 /*Enter=*/!Class.isTopLevelClass()),
         Class(Class) {
     // If this is the top-level class, we're still within its scope.
-    if (Class.TopLevelClass)
+    if (Class.isTopLevelClass())
       return;
 
     // Re-enter the class scope itself.
@@ -347,7 +347,7 @@ struct Parser::ReenterClassScopeRAII : ReenterTemplateScopeRAII {
                                                   Class.TagOrTemplate);
   }
   ~ReenterClassScopeRAII() {
-    if (Class.TopLevelClass)
+    if (Class.isTopLevelClass())
       return;
 
     P.Actions.ActOnFinishDelayedMemberDeclarations(P.getCurScope(),
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 4024928718444..47fc609654320 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2701,7 +2701,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
               ThisVarDecl->getType()->getCanonicalTypeInternal(),
               ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
               /*Braced=*/false);
-      CalledSignatureHelp = true;
+      setCalledSignatureHelp(true);
       return PreferredType;
     };
     auto SetPreferredType = [&] {
@@ -2720,12 +2720,13 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     bool SawError = ParseExpressionList(Exprs, ExpressionStarts);
 
     if (SawError) {
-      if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+      if (ThisVarDecl && PP.isCodeCompletionReached() &&
+          !getCalledSignatureHelp()) {
         Actions.CodeCompletion().ProduceConstructorSignatureHelp(
             ThisVarDecl->getType()->getCanonicalTypeInternal(),
             ThisDecl->getLocation(), Exprs, T.getOpenLocation(),
             /*Braced=*/false);
-        CalledSignatureHelp = true;
+        setCalledSignatureHelp(true);
       }
       Actions.ActOnInitializerError(ThisDecl);
       SkipUntil(tok::r_paren, StopAtSemi);
@@ -5265,7 +5266,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
 
   // Parse the fixed underlying type.
   if (Tok.is(tok::colon) &&
-      (!ParsingGenericAssociationType || IsCXXTypeAhead())) {
+      (!getParsingGenericAssociationType() || IsCXXTypeAhead())) {
     // This might be an enum-base or part of some unrelated enclosing context.
     //
     // 'enum E : base' is permitted in two circumstances:
@@ -5295,7 +5296,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
       // not make sense as one. In C++11, it's an error if this happens.
       if (getLangOpts().CPlusPlus11)
         Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield);
-    } else if (CanHaveEnumBase || !ColonIsSacred) {
+    } else if (CanHaveEnumBase || !getColonIsSacred()) {
       SourceLocation ColonLoc = ConsumeToken();
 
       // Parse a type-specifier-seq as a type. We can't just ParseTypeName here,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 4cf445d68bdbe..379e846a7ae45 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1546,8 +1546,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
     return true;
   case tok::colon:
     return CouldBeBitfield || // enum E { ... }   :         2;
-           ColonIsSacred ||
-           ParsingGenericAssociationType; // _Generic(..., enum E :     2);
+           getColonIsSacred() ||
+           getParsingGenericAssociationType(); // _Generic(..., enum E :     2);
   // Microsoft compatibility
   case tok::kw___cdecl:      // struct foo {...} __cdecl      x;
   case tok::kw___fastcall:   // struct foo {...} __fastcall   x;
@@ -2613,7 +2613,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
     ParseTrailingRequiresClauseWithScope(DeclaratorInfo);
   } else {
     ParseOptionalCXX11VirtSpecifierSeq(
-        VS, getCurrentClass().IsInterface,
+        VS, getCurrentClass().isInterface(),
         DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
     if (!VS.isUnset())
       MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo,
@@ -2642,7 +2642,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
   // virt-specifier *after* the GNU attributes.
   if (BitfieldSize.isUnset() && VS.isUnset()) {
     ParseOptionalCXX11VirtSpecifierSeq(
-        VS, getCurrentClass().IsInterface,
+        VS, getCurrentClass().isInterface(),
         DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
     if (!VS.isUnset()) {
       // If we saw any GNU-style attributes that are known to GCC followed by a
@@ -3355,8 +3355,11 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
   // CWG2760
   // Default member initializers used to initialize a base or member subobject
   // [...] are considered to be part of the function body
-  Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
-      IsFieldInitialization;
+  [&] {
+    auto PackedFlagValue_ = IsFieldInitialization;
+    return Actions.ExprEvalContexts.back()
+        .setInImmediateEscalatingFunctionContext(PackedFlagValue_);
+  }();
 
   if (TryConsumeToken(tok::equal, EqualLoc)) {
     if (Tok.is(tok::kw_delete)) {
@@ -3588,7 +3591,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
         NonNestedClass = false;
 
         // The Microsoft extension __interface does not permit nested classes.
-        if (getCurrentClass().IsInterface) {
+        if (getCurrentClass().isInterface()) {
           Diag(RecordLoc, diag::err_invalid_member_in_interface)
               << /*ErrorType=*/6
               << (isa<NamedDecl>(TagDecl)
@@ -3952,14 +3955,14 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
           Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp(
               ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,
               T.getOpenLocation(), /*Braced=*/false);
-      CalledSignatureHelp = true;
+      setCalledSignatureHelp(true);
       return PreferredType;
     };
     if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] {
           PreferredType.enterFunctionArgument(Tok.getLocation(),
                                               RunSignatureHelp);
         })) {
-      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+      if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
         RunSignatureHelp();
       SkipUntil(tok::r_paren, StopAtSemi);
       return true;
@@ -4276,7 +4279,7 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
 
   ParsingClass *Victim = ClassStack.top();
   ClassStack.pop();
-  if (Victim->TopLevelClass) {
+  if (Victim->isTopLevelClass()) {
     // Deallocate all of the nested classes of this class,
     // recursively: we don't need to keep any of this information.
     DeallocateParsedClasses(Victim);
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index d42ffc2ccf0a6..b64b8e37ef3bd 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -146,7 +146,8 @@ ExprResult Parser::ParseArrayBoundExpression() {
       Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
   // If we parse the bound of a VLA... we parse a non-constant
   // constant-expression!
-  Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;
+  Actions.ExprEvalContexts.back().setInConditionallyConstantEvaluateContext(
+      true);
   // For a VLA type inside an unevaluated operator like:
   //
   //   sizeof(typeof(*(int (*)[N])array))
@@ -164,7 +165,7 @@ ExprResult Parser::ParseArrayBoundExpression() {
        Iter != Actions.ExprEvalContexts.rend(); ++Iter) {
     if (!Iter->isUnevaluated())
       break;
-    Iter->InConditionallyConstantEvaluateContext = true;
+    Iter->setInConditionallyConstantEvaluateContext(true);
   }
   return ParseConstantExpressionInExprEvalContext(
       TypoCorrectionTypeBehavior::AllowNonTypes);
@@ -173,7 +174,7 @@ ExprResult Parser::ParseArrayBoundExpression() {
 ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
   EnterExpressionEvaluationContext ConstantEvaluated(
       Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-  Actions.currentEvaluationContext().IsCaseExpr = true;
+  Actions.currentEvaluationContext().setIsCaseExpr(true);
 
   ExprResult LHS(
       ParseCastExpression(CastParseKind::AnyCastExpr, false,
@@ -921,7 +922,7 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,
         }
       }
 
-      else if ((!ColonIsSacred && Next.is(tok::colon)) ||
+      else if ((!getColonIsSacred() && Next.is(tok::colon)) ||
                Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,
                             tok::l_brace)) {
         // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
@@ -1874,7 +1875,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
         QualType PreferredType =
             Actions.CodeCompletion().ProduceCallSignatureHelp(
                 LHS.get(), ArgExprs, PT.getOpenLocation());
-        CalledSignatureHelp = true;
+        setCalledSignatureHelp(true);
         return PreferredType;
       };
       bool ExpressionListIsInvalid = false;
@@ -1888,7 +1889,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
             // the CodeCompleteCall handler inside the parser. So call it here
             // to make sure we get overload suggestions even when we are in the
             // middle of a parameter.
-            if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+            if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
               RunSignatureHelp();
           }
         }
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 3745ea53fc6d0..daa1bb331234f 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -422,8 +422,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
 
     // If we get foo:bar, this is almost certainly a typo for foo::bar.  Recover
     // and emit a fixit hint for it.
-    if (Next.is(tok::colon) && !ColonIsSacred &&
-        !ParsingGenericAssociationType) {
+    if (Next.is(tok::colon) && !getColonIsSacred() &&
+        !getParsingGenericAssociationType()) {
       if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, IdInfo,
                                             EnteringContext) &&
           // If the token after the colon isn't an identifier, it's still an
@@ -454,7 +454,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
         return false;
       }
 
-      if (ColonIsSacred) {
+      if (getColonIsSacred()) {
         const Token &Next2 = GetLookAheadToken(2);
         if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) ||
             Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) {
@@ -483,7 +483,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
       SourceLocation ScopeBeginLoc = SS.getBeginLoc();
 
       bool IsCorrectedToColon = false;
-      bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
+      bool *CorrectionFlagPtr =
+          getColonIsSacred() ? &IsCorrectedToColon : nullptr;
       if (Actions.ActOnCXXNestedNameSpecifier(
               getCurScope(), IdInfo, EnteringContext, SS, CorrectionFlagPtr,
               OnlyNamespace)) {
@@ -1843,7 +1844,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
             Actions.CodeCompletion().ProduceConstructorSignatureHelp(
                 TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(),
                 Exprs, T.getOpenLocation(), /*Braced=*/false);
-      CalledSignatureHelp = true;
+      setCalledSignatureHelp(true);
       return PreferredType;
     };
 
@@ -1852,7 +1853,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
             PreferredType.enterFunctionArgument(Tok.getLocation(),
                                                 RunSignatureHelp);
           })) {
-        if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+        if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
           RunSignatureHelp();
         SkipUntil(tok::r_paren, StopAtSemi);
         return ExprError();
@@ -3050,14 +3051,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
                   DeclaratorInfo.getEndLoc(), ConstructorArgs,
                   ConstructorLParen,
                   /*Braced=*/false);
-        CalledSignatureHelp = true;
+        setCalledSignatureHelp(true);
         return PreferredType;
       };
       if (ParseExpressionList(ConstructorArgs, [&] {
             PreferredType.enterFunctionArgument(Tok.getLocation(),
                                                 RunSignatureHelp);
           })) {
-        if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+        if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
           RunSignatureHelp();
         SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
         return ExprError();
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index e63509147fc91..d2513f1d8e624 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -2026,7 +2026,7 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
 }
 
 Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
-  if (!Finished) {
+  if (!getFinished()) {
     finish(P.Tok.getLocation());
     if (P.isEofOrEom()) {
       P.Diag(P.Tok, diag::err_objc_missing_end)
@@ -2039,7 +2039,7 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
 }
 
 void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
-  assert(!Finished);
+  assert(!getFinished());
   P.Actions.ObjC().DefaultSynthesizeProperties(P.getCurScope(), Dcl,
                                                AtEnd.getBegin());
   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
@@ -2048,7 +2048,7 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
 
   P.Actions.ObjC().ActOnAtEnd(P.getCurScope(), AtEnd);
 
-  if (HasCFunction)
+  if (getHasCFunction())
     for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
       P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
                                  false/*c-functions*/);
@@ -2064,7 +2064,7 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
   // (e.g. a nested @interface ended the @implementation early), so stop being
   // the current @implementation now rather than in the destructor.
   P.CurParsedObjCImpl = PrevParsedObjCImpl;
-  Finished = true;
+  setFinished(true);
 }
 
 Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
@@ -2393,7 +2393,8 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
 }
 
 void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
-  if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
+  if (getSkipFunctionBodies() &&
+      (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
       trySkippingFunctionBody()) {
     Actions.ActOnSkippedFunctionBody(MDecl);
     return;
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index eb9106b673045..4d57234e8512d 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -1239,13 +1239,14 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
         OpenACCWaitParseInfo Info =
             ParseOpenACCWaitArgument(ClauseLoc,
                                      /*IsDirective=*/false);
-        if (Info.Failed) {
+        if (Info.getFailed()) {
           Parens.skipToEnd();
           return OpenACCCanContinue();
         }
 
-        ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,
-                                    std::move(Info.QueueIdExprs));
+        ParsedClause.setWaitDetails(
+            Info.DevNumExpr, Info.QueuesLoc,
+            SmallVector<Expr *>(std::move(Info.QueueIdExprs)));
         break;
       }
       default:
@@ -1290,12 +1291,12 @@ Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
         Loc);
     if (Res.first.isInvalid() &&
         Res.second == OpenACCParseCanContinue::Cannot) {
-      Result.Failed = true;
+      Result.setFailed(true);
       return Result;
     }
 
     if (ExpectAndConsume(tok::colon)) {
-      Result.Failed = true;
+      Result.setFailed(true);
       return Result;
     }
 
@@ -1325,7 +1326,7 @@ Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
 
   if (Res.first.isInvalid() &&
       Res.second == OpenACCParseCanContinue::Cannot) {
-    Result.Failed = true;
+    Result.setFailed(true);
     return Result;
   }
 
@@ -1334,7 +1335,7 @@ Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
 
   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
     if (ExpectAndConsume(tok::comma)) {
-      Result.Failed = true;
+      Result.setFailed(true);
       return Result;
     }
 
@@ -1346,7 +1347,7 @@ Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
 
     if (Res.first.isInvalid() &&
         Res.second == OpenACCParseCanContinue::Cannot) {
-      Result.Failed = true;
+      Result.setFailed(true);
       return Result;
     }
 
@@ -1539,7 +1540,7 @@ Parser::ParseOpenACCDirective() {
     case OpenACCDirectiveKind::Wait:
       // OpenACC has an optional paren-wrapped 'wait-argument'.
       WaitInfo = ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true);
-      if (WaitInfo.Failed)
+      if (WaitInfo.getFailed())
         T.skipToEnd();
       else
         T.consumeClose();
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 95c26f35fff03..29c7520562b39 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -365,14 +365,14 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
           Actions.CodeCompletion().ProduceConstructorSignatureHelp(
               OmpPrivParm->getType()->getCanonicalTypeInternal(),
               OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
-      CalledSignatureHelp = true;
+      setCalledSignatureHelp(true);
       return PreferredType;
     };
     if (ParseExpressionList(Exprs, [&] {
           PreferredType.enterFunctionArgument(Tok.getLocation(),
                                               RunSignatureHelp);
         })) {
-      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+      if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
         RunSignatureHelp();
       Actions.ActOnInitializerError(OmpPrivParm);
       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
@@ -3895,7 +3895,7 @@ bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
 
           if (FrExpr || !AttrExprs.empty())
             InteropInfo.Prefs.emplace_back(FrExpr, AttrExprs);
-          InteropInfo.HasPreferAttrs = true;
+          InteropInfo.setPreferAttrs(true);
         } else {
           // OMP 5.1: flat foreign-runtime-id (string or int). Stored as a
           // pref-spec with Fr=expr and no attr() entries.
@@ -3943,8 +3943,8 @@ bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
 
   // As of OpenMP 5.1,there are two interop-types, "target" and
   // "targetsync". Either or both are allowed for a single interop.
-  InteropInfo.IsTarget = IsTarget;
-  InteropInfo.IsTargetSync = IsTargetSync;
+  InteropInfo.setIsTarget(IsTarget);
+  InteropInfo.setIsTargetSync(IsTargetSync);
 
   return HasError;
 }
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 14bea6a1a7948..4808206098d0b 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1944,8 +1944,8 @@ void Parser::ParseForRangeInitializerAfterColon(ForRangeInit &FRI,
   // P2718R0 - Lifetime extension in range-based for loops.
   if (getLangOpts().CPlusPlus23) {
     auto &LastRecord = Actions.currentEvaluationContext();
-    LastRecord.InLifetimeExtendingContext = true;
-    LastRecord.RebuildDefaultArgOrDefaultInit = true;
+    LastRecord.setInLifetimeExtendingContext(true);
+    LastRecord.setRebuildDefaultArgOrDefaultInit(true);
   }
 
   if (FRI.ExpansionStmt) {
@@ -2620,7 +2620,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
 }
 
 bool Parser::trySkippingFunctionBody() {
-  assert(SkipFunctionBodies &&
+  assert(getSkipFunctionBodies() &&
          "Should only be called when SkipFunctionBodies is enabled");
   if (!PP.isCodeCompletionEnabled()) {
     SkipFunctionBody();
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index ef6920fdc485c..cdda54e59f63a 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1392,7 +1392,7 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
   auto RunSignatureHelp = [&] {
     if (!Template)
       return QualType();
-    CalledSignatureHelp = true;
+    setCalledSignatureHelp(true);
     return Actions.CodeCompletion().ProduceTemplateArgumentSignatureHelp(
         Template, TemplateArgs, OpenLoc);
   };
@@ -1405,7 +1405,7 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
       Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
 
     if (Arg.isInvalid()) {
-      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+      if (PP.isCodeCompletionReached() && !getCalledSignatureHelp())
         RunSignatureHelp();
       return true;
     }
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index a4581538fbcec..0ed7acc16af59 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1573,7 +1573,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
     //     enum E : int { 4 };     // bit-field
     //   };
     if (getLangOpts().CPlusPlus11 && NextToken().is(tok::l_brace)) {
-      if (ParsingGenericAssociationType) {
+      if (getParsingGenericAssociationType()) {
         RevertingTentativeParsingAction PA(*this);
         ConsumeAnyToken(); // skip keyword
         ConsumeBrace();    // skip l_brace
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index c5d6a17fbfcd3..fd612b2b99872 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -73,10 +73,9 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
     : PP(pp),
       PreferredType(&actions.getASTContext(), pp.isCodeCompletionEnabled()),
       Actions(actions), Diags(PP.getDiagnostics()), StackHandler(Diags),
-      GreaterThanIsOperator(true), ColonIsSacred(false),
-      ParsingGenericAssociationType(false), InMessageExpression(false),
+      GreaterThanIsOperator(true), InMessageExpression(false),
       ParsingInObjCContainer(false), TemplateParameterDepth(0) {
-  SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
+  setSkipFunctionBodies(pp.isCodeCompletionEnabled() || skipFunctionBodies);
   Tok = Token::createEof();
   Actions.CurScope = nullptr;
   NumCachedScopes = 0;
@@ -1263,7 +1262,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
     D.complete(DP);
     D.getMutableDeclSpec().abort();
 
-    if (SkipFunctionBodies && (!DP || Actions.canSkipFunctionBody(DP)) &&
+    if (getSkipFunctionBodies() && (!DP || Actions.canSkipFunctionBody(DP)) &&
         trySkippingFunctionBody()) {
       BodyScope.Exit();
       return Actions.ActOnSkippedFunctionBody(DP);
@@ -1294,7 +1293,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
     if (FuncDecl) {
       // Consume the tokens and store them for later parsing.
       StashAwayMethodOrFunctionBodyTokens(FuncDecl);
-      CurParsedObjCImpl->HasCFunction = true;
+      CurParsedObjCImpl->setHasCFunction(true);
       return FuncDecl;
     }
     // FIXME: Should we really fall through here?
@@ -1397,7 +1396,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
     ParseLexedAttributeList(*LateParsedAttrs, Res, /*EnterScope=*/false,
                             /*OnDefinition=*/true);
 
-  if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) &&
+  if (getSkipFunctionBodies() && (!Res || Actions.canSkipFunctionBody(Res)) &&
       trySkippingFunctionBody()) {
     BodyScope.Exit();
     Actions.ActOnSkippedFunctionBody(Res);
diff --git a/clang/lib/Sema/CoroutineStmtBuilder.h b/clang/lib/Sema/CoroutineStmtBuilder.h
index 42499a32fc167..7abc0541a9b38 100644
--- a/clang/lib/Sema/CoroutineStmtBuilder.h
+++ b/clang/lib/Sema/CoroutineStmtBuilder.h
@@ -18,6 +18,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/SemaInternal.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace clang {
 
@@ -25,10 +26,11 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
   Sema &S;
   FunctionDecl &FD;
   sema::FunctionScopeInfo &Fn;
-  bool IsValid = true;
+  bool getIsValid() const { return !ParamMovesVector.getFlag(0); }
+  void setIsValid(bool Value) { ParamMovesVector.setFlag(0, !Value); }
   SourceLocation Loc;
-  SmallVector<Stmt *, 4> ParamMovesVector;
-  const bool IsPromiseDependentType;
+  llvm::SmallVectorWithFlags<Stmt *, 4, 2> ParamMovesVector;
+  bool getIsPromiseDependentType() const { return ParamMovesVector.getFlag(1); }
   CXXRecordDecl *PromiseRecordDecl = nullptr;
 
 public:
@@ -50,7 +52,7 @@ class CoroutineStmtBuilder : public CoroutineBodyStmt::CtorArgs {
   /// name lookup.
   bool buildDependentStatements();
 
-  bool isInvalid() const { return !this->IsValid; }
+  bool isInvalid() const { return !this->getIsValid(); }
 
 private:
   bool makePromiseStmt();
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index bbe6f644609bf..bc159668ea2ab 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -22,6 +22,7 @@
 #include "clang/Sema/SemaAMDGPU.h"
 #include "clang/Sema/SemaInternal.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 using namespace clang;
 
 namespace {
@@ -41,7 +42,7 @@ class JumpScopeChecker {
 
   /// Permissive - True when recovering from errors, in which case precautions
   /// are taken to handle incomplete scope information.
-  const bool Permissive;
+  bool getPermissive() const { return MustTailStmts.getFlag(0); }
 
   /// GotoScope - This is a record that we use to keep track of all of the
   /// scopes that are introduced by VLAs and other things that scope jumps like
@@ -75,7 +76,7 @@ class JumpScopeChecker {
 
   SmallVector<Stmt*, 4> IndirectJumps;
   SmallVector<LabelDecl *, 4> IndirectJumpTargets;
-  SmallVector<AttributedStmt *, 4> MustTailStmts;
+  llvm::SmallVectorWithFlags<AttributedStmt *, 4> MustTailStmts;
 
 public:
   JumpScopeChecker(Stmt *Body, Sema &S);
@@ -102,10 +103,12 @@ class JumpScopeChecker {
 };
 } // end anonymous namespace
 
-#define CHECK_PERMISSIVE(x) (assert(Permissive || !(x)), (Permissive && (x)))
+#define CHECK_PERMISSIVE(x)                                                    \
+  (assert(getPermissive() || !(x)), (getPermissive() && (x)))
 
 JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s)
-    : S(s), Permissive(s.hasAnyUnrecoverableErrorsInThisFunction()) {
+    : S(s), MustTailStmts(decltype(this->MustTailStmts)::withFlags(
+                unsigned(bool(s.hasAnyUnrecoverableErrorsInThisFunction())))) {
   // Add a scope entry for function scope.
   Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation()));
 
diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp
index d089836fa36dd..b8182c06aaa67 100644
--- a/clang/lib/Sema/ScopeInfo.cpp
+++ b/clang/lib/Sema/ScopeInfo.cpp
@@ -253,7 +253,7 @@ bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const {
     return ExplicitObjectParameter->getType()
         .getNonReferenceType()
         .isConstQualified();
-  return !Mutable;
+  return !getMutable();
 }
 
 FunctionScopeInfo::~FunctionScopeInfo() { }
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index bae41a6e6f5cf..5a94bb96bf8fa 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -113,10 +113,10 @@ DarwinSDKInfo *
 Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
                                               StringRef Platform) {
   auto *SDKInfo = getDarwinSDKInfoForAvailabilityChecking();
-  if (!SDKInfo && !WarnedDarwinSDKInfoMissing) {
+  if (!SDKInfo && !getWarnedDarwinSDKInfoMissing()) {
     Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking)
         << Platform;
-    WarnedDarwinSDKInfoMissing = true;
+    setWarnedDarwinSDKInfoMissing(true);
   }
   return SDKInfo;
 }
@@ -314,7 +314,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
       X86Ptr(std::make_unique<SemaX86>(*this)),
       MSPointerToMemberRepresentationMethod(
           LangOpts.getMSPointerToMemberRepresentationMethod()),
-      MSStructPragmaOn(false), VtorDispStack(LangOpts.getVtorDispMode()),
+      VtorDispStack(LangOpts.getVtorDispMode()),
       AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
       DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
       CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
@@ -326,14 +326,13 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
       FullyCheckedComparisonCategories(
           static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
       StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
-      GlobalNewDeleteDeclared(false), DisableTypoCorrection(false),
-      TyposCorrected(0), IsBuildingRecoveryCallExpr(false),
-      CurrentInstantiationScope(nullptr), NonInstantiationEntries(0),
-      ArgPackSubstIndex(std::nullopt), SatisfactionCache(Context) {
+      TyposCorrected(0), CurrentInstantiationScope(nullptr),
+      NonInstantiationEntries(0), ArgPackSubstIndex(std::nullopt),
+      SatisfactionCache(Context) {
   assert(pp.TUKind == TUKind);
   TUScope = nullptr;
 
-  LoadedExternalKnownNamespaces = false;
+  setLoadedExternalKnownNamespaces(false);
   for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
     ObjC().NSNumberLiteralMethods[I] = nullptr;
 
@@ -1438,9 +1437,9 @@ void Sema::ActOnEndOfTranslationUnit() {
       return false;
     };
 
-    CurrentModule->NamedModuleHasInit =
+    CurrentModule->setNamedModuleHasInit(
         DoesModNeedInit(CurrentModule) ||
-        llvm::any_of(CurrentModule->submodules(), DoesModNeedInit);
+        llvm::any_of(CurrentModule->submodules(), DoesModNeedInit));
   }
 
   if (TUKind == TU_ClangModule) {
@@ -2711,7 +2710,7 @@ CapturingScopeInfo *Sema::getEnclosingLambdaOrBlock() const {
     if (auto *CSI = dyn_cast<CapturingScopeInfo>(Scope)) {
       auto *LSI = dyn_cast<LambdaScopeInfo>(CSI);
       if (LSI && LSI->Lambda && !LSI->Lambda->Encloses(CurContext) &&
-          LSI->AfterParameterList) {
+          LSI->getAfterParameterList()) {
         // We have switched contexts due to template instantiation.
         // FIXME: We should swap out the FunctionScopes during code synthesis
         // so that we don't need to check for this.
@@ -2738,7 +2737,8 @@ LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
   }
   auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
   if (CurLSI && CurLSI->Lambda && CurLSI->CallOperator &&
-      !CurLSI->Lambda->Encloses(CurContext) && CurLSI->AfterParameterList) {
+      !CurLSI->Lambda->Encloses(CurContext) &&
+      CurLSI->getAfterParameterList()) {
     // We have switched contexts due to template instantiation.
     assert(!CodeSynthesisContexts.empty());
     return nullptr;
@@ -2805,12 +2805,12 @@ bool Sema::areDocumentationDiagsEnabled(SourceLocation Loc) {
     {
       // Answer as if Loc were not in a system header.
       ForceSystemWarningsRAII ShowSystemWarnings(Diags);
-      DocDiagsEnabledIgnoringSystem = computeDocumentationDiagsAt(Loc);
+      setDocDiagsEnabledIgnoringSystem(computeDocumentationDiagsAt(Loc));
     }
     DocDiagsExactComputed = 0;
   }
 
-  if (!DocDiagsEnabledIgnoringSystem)
+  if (!getDocDiagsEnabledIgnoringSystem())
     return false;
 
   DiagStateSystemClass SysClass = Diags.getDiagStateSystemClassForLoc(Loc);
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index cc2af8feb3794..c5d3de5895265 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -24,6 +24,7 @@
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 using namespace clang;
 using namespace sema;
@@ -77,11 +78,11 @@ static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
 
 namespace {
 struct EffectiveContext {
-  EffectiveContext() : Inner(nullptr), Dependent(false) {}
+  EffectiveContext() : Inner(nullptr) {}
 
   explicit EffectiveContext(DeclContext *DC)
-    : Inner(DC),
-      Dependent(DC->isDependentContext()) {
+      : Inner(DC), Records(decltype(this->Records)::withFlags(
+                       unsigned(bool(DC->isDependentContext())))) {
 
     // An implicit deduction guide is semantically in the context enclosing the
     // class template, but for access purposes behaves like the constructor
@@ -135,7 +136,7 @@ struct EffectiveContext {
     }
   }
 
-  bool isDependent() const { return Dependent; }
+  bool isDependent() const { return getDependent(); }
 
   bool includesClass(const CXXRecordDecl *R) const {
     R = R->getCanonicalDecl();
@@ -152,8 +153,9 @@ struct EffectiveContext {
 
   DeclContext *Inner;
   SmallVector<FunctionDecl*, 4> Functions;
-  SmallVector<CXXRecordDecl*, 4> Records;
-  bool Dependent;
+  llvm::SmallVectorWithFlags<CXXRecordDecl *, 4> Records;
+  bool getDependent() const { return Records.getFlag(0); }
+  void setDependent(bool Value) { Records.setFlag(0, Value); }
 };
 
 /// Like sema::AccessedEntity, but kindly lets us scribble all over
@@ -1168,20 +1170,25 @@ struct ProtectedFriendContext {
   const EffectiveContext &EC;
   TemplateSpecCandidateSet *FailedTSC;
   const CXXRecordDecl *NamingClass;
-  bool CheckDependent;
-  bool EverDependent;
+  bool getCheckDependent() const { return CurPath.getFlag(0); }
+  void setCheckDependent(bool Value) { CurPath.setFlag(0, Value); }
+  bool getEverDependent() const { return CurPath.getFlag(1); }
+  bool setEverDependent(bool Value) {
+    CurPath.setFlag(1, Value);
+    return Value;
+  }
 
   /// The path down to the current base class.
-  SmallVector<const CXXRecordDecl*, 20> CurPath;
+  llvm::SmallVectorWithFlags<const CXXRecordDecl *, 20, 2> CurPath;
 
   ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
                          const CXXRecordDecl *InstanceContext,
                          const CXXRecordDecl *NamingClass,
                          TemplateSpecCandidateSet *FailedTSC)
       : S(S), EC(EC), FailedTSC(FailedTSC), NamingClass(NamingClass),
-        CheckDependent(InstanceContext->isDependentContext() ||
-                       NamingClass->isDependentContext()),
-        EverDependent(false) {}
+        CurPath(decltype(this->CurPath)::withFlags(
+            unsigned(bool(InstanceContext->isDependentContext() ||
+                          NamingClass->isDependentContext())))) {}
 
   /// Check classes in the current path for friendship, starting at
   /// the given index.
@@ -1191,7 +1198,9 @@ struct ProtectedFriendContext {
       switch (GetFriendKind(S, EC, CurPath[I], FailedTSC)) {
       case AR_accessible:   return true;
       case AR_inaccessible: continue;
-      case AR_dependent:    EverDependent = true; continue;
+      case AR_dependent:
+        setEverDependent(true);
+        continue;
       }
     }
     return false;
@@ -1209,8 +1218,8 @@ struct ProtectedFriendContext {
     if (Cur == NamingClass)
       return checkFriendshipAlongPath(PrivateDepth);
 
-    if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
-      EverDependent = true;
+    if (getCheckDependent() && MightInstantiateTo(Cur, NamingClass))
+      setEverDependent(true);
 
     // Recurse into the base classes.
     for (const auto &I : Cur->bases()) {
@@ -1227,7 +1236,7 @@ struct ProtectedFriendContext {
         RD = Rec;
       } else {
         assert(T->isDependentType() && "non-dependent base wasn't a record?");
-        EverDependent = true;
+        setEverDependent(true);
         continue;
       }
 
@@ -1290,7 +1299,8 @@ static AccessResult GetProtectedFriendKind(
 
   ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass, FailedTSC);
   if (PRC.findFriendship(InstanceContext)) return AR_accessible;
-  if (PRC.EverDependent) return AR_dependent;
+  if (PRC.getEverDependent())
+    return AR_dependent;
   return AR_inaccessible;
 }
 
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 35d14a4444595..4e15fcce1478b 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -88,7 +88,7 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
 }
 
 void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
-  if (MSStructPragmaOn)
+  if (getMSStructPragmaOn())
     RD->addAttr(MSStructAttr::CreateImplicit(Context));
 
   // FIXME: We should merge AddAlignmentAttributesForRecord with
@@ -657,7 +657,7 @@ void Sema::DiagnoseUnterminatedPragmaAlignPack() {
 }
 
 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
-  MSStructPragmaOn = (Kind == PMSST_ON);
+  setMSStructPragmaOn((Kind == PMSST_ON));
 }
 
 void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
@@ -1212,7 +1212,7 @@ void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc,
     if (PragmaAttributeStack[Index].Namespace == Namespace) {
       for (const PragmaAttributeEntry &Entry :
            PragmaAttributeStack[Index].Entries) {
-        if (!Entry.IsUsed) {
+        if (!Entry.getIsUsed()) {
           assert(Entry.Attribute && "Expected an attribute");
           Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
               << *Entry.Attribute;
@@ -1256,7 +1256,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
       }
       if (!Applies)
         continue;
-      Entry.IsUsed = true;
+      Entry.setIsUsed(true);
       PragmaAttributeCurrentTargetDecl = D;
       ParsedAttributesView Attrs;
       Attrs.addAtEnd(Attribute);
@@ -1302,7 +1302,7 @@ void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) {
     return;
   }
 
-  MSPragmaOptimizeIsOn = IsOn;
+  setMSPragmaOptimizeIsOn(IsOn);
 }
 
 void Sema::ActOnPragmaMSFunction(
@@ -1341,7 +1341,7 @@ void Sema::AddSectionMSAllocText(FunctionDecl *FD) {
 void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) {
   // Don't modify the function attributes if it's "on". "on" resets the
   // optimizations to the ones listed on the command line
-  if (!MSPragmaOptimizeIsOn)
+  if (!getMSPragmaOptimizeIsOn())
     AddOptnoneAttributeIfNoConflicts(FD, FD->getBeginLoc());
 }
 
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 40f26dc53315a..feeb5815f9f1f 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -553,7 +553,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
   case AR_Deprecated:
     if (ObjCPropertyAccess)
       diag = diag::warn_property_method_deprecated;
-    else if (S.currentEvaluationContext().IsCaseExpr)
+    else if (S.currentEvaluationContext().getIsCaseExpr())
       diag = diag::warn_deprecated_switch_case;
     else
       diag = diag::warn_deprecated;
diff --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp
index e16ec2883b89c..c7771aef1a42a 100644
--- a/clang/lib/Sema/SemaBase.cpp
+++ b/clang/lib/Sema/SemaBase.cpp
@@ -64,7 +64,7 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc,
       getDiagnostics().getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
   bool ShouldDefer = getLangOpts().CUDA && getLangOpts().GPUDeferDiag &&
                      DiagnosticIDs::isDeferrable(DiagID) &&
-                     (SemaRef.DeferDiags || !IsError);
+                     (SemaRef.getDeferDiags() || !IsError);
   // Even without -fgpu-defer-diag, defer device-side errors inside an
   // implicit-H+D explicit instantiation so end-of-TU classification can
   // choose between surfacing them or emitting a trap body.
@@ -75,7 +75,7 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc,
     ShouldDefer = true;
   auto SetIsLastErrorImmediate = [&](bool Flag) {
     if (IsError)
-      SemaRef.IsLastErrorImmediate = Flag;
+      SemaRef.setIsLastErrorImmediate(Flag);
   };
   if (!ShouldDefer) {
     SetIsLastErrorImmediate(true);
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 090030ea82503..ff6dd7a5813db 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -968,7 +968,7 @@ SemaBase::SemaDiagnosticBuilder SemaCUDA::DiagIfDeviceCode(SourceLocation Loc,
       // mode until the function is known-emitted.
       if (!getLangOpts().CUDAIsDevice)
         return SemaDiagnosticBuilder::K_Nop;
-      if (SemaRef.IsLastErrorImmediate &&
+      if (SemaRef.getIsLastErrorImmediate() &&
           getDiagnostics().getDiagnosticIDs()->isNote(DiagID))
         return SemaDiagnosticBuilder::K_Immediate;
       if (isImplicitHDExplicitInstantiation(CurFunContext))
@@ -1001,7 +1001,7 @@ Sema::SemaDiagnosticBuilder SemaCUDA::DiagIfHostCode(SourceLocation Loc,
       // mode until the function is known-emitted.
       if (getLangOpts().CUDAIsDevice)
         return SemaDiagnosticBuilder::K_Nop;
-      if (SemaRef.IsLastErrorImmediate &&
+      if (SemaRef.getIsLastErrorImmediate() &&
           getDiagnostics().getDiagnosticIDs()->isNote(DiagID))
         return SemaDiagnosticBuilder::K_Immediate;
       return (SemaRef.getEmissionStatus(CurFunContext) ==
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 51506c62d4e35..6eedc84ba29b8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -88,6 +88,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -114,6 +115,7 @@
 #include <cstdint>
 #include <functional>
 #include <limits>
+#include <memory>
 #include <optional>
 #include <string>
 #include <tuple>
@@ -13112,8 +13114,14 @@ static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
 
   // Set context flag for overflow behavior type assignment analysis, use RAII
   // pattern to handle nested assignments.
-  llvm::SaveAndRestore OBTAssignmentContext(
-      S.InOverflowBehaviorAssignmentContext, true);
+  auto OBTAssignmentContext = [PackedFlagOwner_ = std::addressof(S)] {
+    const bool PackedFlagOld_ =
+        PackedFlagOwner_->getInOverflowBehaviorAssignmentContext();
+    PackedFlagOwner_->setInOverflowBehaviorAssignmentContext(true);
+    return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+      PackedFlagOwner_->setInOverflowBehaviorAssignmentContext(PackedFlagOld_);
+    });
+  }();
 
   AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
 
@@ -14674,12 +14682,12 @@ bool Sema::CheckOverflowBehaviorTypeConversion(Expr *E, QualType T,
           Target->isUnsignedIntegerType()) {
         // For unsigned wrap to unsigned conversions, use pedantic version
         unsigned DiagId =
-            InOverflowBehaviorAssignmentContext
+            getInOverflowBehaviorAssignmentContext()
                 ? diag::warn_impcast_overflow_behavior_assignment_pedantic
                 : diag::warn_impcast_overflow_behavior_pedantic;
         DiagnoseImpCast(*this, E, T, CC, DiagId);
       } else {
-        unsigned DiagId = InOverflowBehaviorAssignmentContext
+        unsigned DiagId = getInOverflowBehaviorAssignmentContext()
                               ? diag::warn_impcast_overflow_behavior_assignment
                               : diag::warn_impcast_overflow_behavior;
         DiagnoseImpCast(*this, E, T, CC, DiagId);
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index b592e7075afc5..65edc246997d7 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -604,8 +604,8 @@ class ConstraintSatisfactionChecker {
         return nullptr;
       auto &Satisfaction = Checker.Satisfaction;
       auto &Cached = Iter->second.Satisfaction;
-      Satisfaction.ContainsErrors = Cached.ContainsErrors;
-      Satisfaction.IsSatisfied = Cached.IsSatisfied;
+      Satisfaction.setContainsErrors(Cached.containsErrors());
+      Satisfaction.setIsSatisfied(Cached.isSatisfied());
       Satisfaction.Details.insert(Satisfaction.Details.begin() +
                                       PreviousDetailsSize,
                                   Cached.Details.begin(), Cached.Details.end());
@@ -615,8 +615,8 @@ class ConstraintSatisfactionChecker {
     ExprResult cache(ExprResult E) {
       UnsubstitutedConstraintSatisfactionCacheResult Cache;
       auto &Satisfaction = Checker.Satisfaction;
-      Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
-      Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
+      Cache.Satisfaction.setContainsErrors(Satisfaction.containsErrors());
+      Cache.Satisfaction.setIsSatisfied(Satisfaction.isSatisfied());
       Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
                                         Satisfaction.Details.begin() +
                                             PreviousDetailsSize,
@@ -714,8 +714,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
   llvm::FoldingSetNodeID ID;
   if (Template &&
       DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, &MLTAL)) {
-    Satisfaction.IsSatisfied = false;
-    Satisfaction.ContainsErrors = true;
+    Satisfaction.setIsSatisfied(false);
+    Satisfaction.setContainsErrors(true);
     return ExprEmpty();
   }
   SatisfactionStackRAII StackRAII(S, Template, ID);
@@ -810,7 +810,7 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
   if (S.SubstTemplateArgumentsInParameterMapping(
           Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
           SubstArgs)) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     if (Trap.hasErrorOccurred())
       consumeSFINAEFailure(Info, Satisfaction);
     return std::nullopt;
@@ -872,7 +872,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
   std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
       SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
   if (!SubstitutedArgs) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     return ExprError();
   }
 
@@ -900,8 +900,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
   // diagnostics. SO, add a failure detail that will cause us to make this
   // overload set not viable.
   if (SubstitutedAtomicExpr.get()->containsErrors()) {
-    Satisfaction.IsSatisfied = false;
-    Satisfaction.ContainsErrors = true;
+    Satisfaction.setIsSatisfied(false);
+    Satisfaction.setContainsErrors(true);
 
     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
     Satisfaction.Details.emplace_back(
@@ -912,8 +912,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
   }
 
   if (SubstitutedAtomicExpr.get()->isValueDependent()) {
-    Satisfaction.IsSatisfied = true;
-    Satisfaction.ContainsErrors = false;
+    Satisfaction.setIsSatisfied(true);
+    Satisfaction.setContainsErrors(false);
     return SubstitutedAtomicExpr;
   }
 
@@ -935,8 +935,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
 
   assert(EvalResult.Val.isInt() &&
          "evaluating bool expression didn't produce int");
-  Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
-  if (!Satisfaction.IsSatisfied)
+  Satisfaction.setIsSatisfied(EvalResult.Val.getInt().getBoolValue());
+  if (!Satisfaction.isSatisfied())
     Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
 
   return SubstitutedAtomicExpr;
@@ -971,7 +971,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
           static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
           MLTAL, SubstitutedOutermost);
   if (!SubstitutedArgs) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     return ExprError();
   }
 
@@ -988,15 +988,15 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
     return ExprEmpty();
 
   if (*NumExpansions == 0) {
-    Satisfaction.IsSatisfied = Conjunction;
+    Satisfaction.setIsSatisfied(Conjunction);
     return ExprEmpty();
   }
 
   ExprResult Out;
   for (unsigned I = 0; I < *NumExpansions; I++) {
     Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
-    Satisfaction.IsSatisfied = false;
-    Satisfaction.ContainsErrors = false;
+    Satisfaction.setIsSatisfied(false);
+    Satisfaction.setContainsErrors(false);
     ExprResult Expr =
         ConstraintSatisfactionChecker(S, Template, TopLevelConceptId,
                                       TemplateNameLoc, UnsignedOrNone(I),
@@ -1014,13 +1014,13 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
                                      Constraint.getBeginLoc(),
                                      FPOptionsOverride{});
     }
-    if (!Conjunction && Satisfaction.IsSatisfied) {
+    if (!Conjunction && Satisfaction.isSatisfied()) {
       Satisfaction.Details.erase(Satisfaction.Details.begin() +
                                      EffectiveDetailEndIndex,
                                  Satisfaction.Details.end());
       break;
     }
-    if (Satisfaction.IsSatisfied != Conjunction)
+    if (Satisfaction.isSatisfied() != Conjunction)
       return Out;
   }
 
@@ -1050,7 +1050,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
       SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
 
   if (!SubstitutedArgs) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     return ExprError();
   }
 
@@ -1076,7 +1076,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
   } else if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs,
                                       OutArgs) ||
              Trap.hasErrorOccurred()) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     if (Trap.hasErrorOccurred())
       consumeSFINAEFailure(Info, Satisfaction);
     return ExprError();
@@ -1140,7 +1140,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
   // ConceptIdConstraint is only relevant for diagnostics,
   // so if the normalized constraint is satisfied, we should not
   // substitute into the constraint.
-  if (Satisfaction.IsSatisfied)
+  if (Satisfaction.isSatisfied())
     return E;
 
   ParameterMappingInstantiationCache PMCache(
@@ -1163,26 +1163,27 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
 
   ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
 
-  if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
+  if (Conjunction &&
+      (!Satisfaction.isSatisfied() || Satisfaction.containsErrors()))
     return LHS;
 
-  if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
-      !Satisfaction.ContainsErrors)
+  if (!Conjunction && !LHS.isInvalid() && Satisfaction.isSatisfied() &&
+      !Satisfaction.containsErrors())
     return LHS;
 
-  Satisfaction.ContainsErrors = false;
-  Satisfaction.IsSatisfied = false;
+  Satisfaction.setContainsErrors(false);
+  Satisfaction.setIsSatisfied(false);
 
   ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
 
-  if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
-      !Satisfaction.ContainsErrors)
+  if (!Conjunction && !RHS.isInvalid() && Satisfaction.isSatisfied() &&
+      !Satisfaction.containsErrors())
     Satisfaction.Details.erase(Satisfaction.Details.begin() +
                                    EffectiveDetailEndIndex,
                                Satisfaction.Details.end());
 
   if (!BuildExpression)
-    return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
+    return Satisfaction.containsErrors() ? ExprError() : ExprEmpty();
 
   if (!LHS.isUsable())
     return RHS;
@@ -1229,7 +1230,7 @@ static bool CheckConstraintSatisfaction(
     *ConvertedExpr = nullptr;
 
   if (AssociatedConstraints.empty()) {
-    Satisfaction.IsSatisfied = true;
+    Satisfaction.setIsSatisfied(true);
     return false;
   }
 
@@ -1240,7 +1241,7 @@ static bool CheckConstraintSatisfaction(
   // attempted later and diagnosed, such as function template specializations,
   // but that's not the case for concept specializations.
   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
-    Satisfaction.IsSatisfied = true;
+    Satisfaction.setIsSatisfied(true);
     return false;
   }
 
@@ -1267,7 +1268,7 @@ static bool CheckConstraintSatisfaction(
   const NormalizedConstraint *C =
       S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
   if (!C) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     return true;
   }
 
@@ -1301,7 +1302,7 @@ bool Sema::CheckConstraintSatisfaction(
         return TemplateIDRange.printToString(getSourceManager());
       });
   if (AssociatedConstraints.empty()) {
-    OutSatisfaction.IsSatisfied = true;
+    OutSatisfaction.setIsSatisfied(true);
     return false;
   }
   const auto *Template = dyn_cast_if_present<const NamedDecl *>(Entity);
@@ -1313,7 +1314,7 @@ bool Sema::CheckConstraintSatisfaction(
   // Invalid templates could make their way here. Substituting them could result
   // in dependent expressions.
   if (Template->isInvalidDecl()) {
-    OutSatisfaction.IsSatisfied = false;
+    OutSatisfaction.setIsSatisfied(false);
     return true;
   }
 
@@ -1504,7 +1505,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
   if (FD->isDependentContext() ||
       FD->getTemplatedKind() ==
           FunctionDecl::TK_FunctionTemplateSpecialization) {
-    Satisfaction.IsSatisfied = true;
+    Satisfaction.setIsSatisfied(true);
     return false;
   }
 
@@ -1701,7 +1702,7 @@ bool Sema::EnsureTemplateArgumentListConstraints(
   TD->getAssociatedConstraints(AssociatedConstraints);
   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
                                   TemplateIDRange, Satisfaction) ||
-      !Satisfaction.IsSatisfied) {
+      !Satisfaction.isSatisfied()) {
     SmallString<128> TemplateArgString;
     TemplateArgString = " ";
     TemplateArgString += getTemplateArgumentBindingsText(
@@ -1725,7 +1726,7 @@ static bool CheckFunctionConstraintsWithoutInstantiation(
   SmallVector<AssociatedConstraint, 3> TemplateAC;
   Template->getAssociatedConstraints(TemplateAC);
   if (TemplateAC.empty()) {
-    Satisfaction.IsSatisfied = true;
+    Satisfaction.setIsSatisfied(true);
     return false;
   }
 
@@ -1776,7 +1777,7 @@ bool Sema::CheckFunctionTemplateConstraints(
   SmallVector<AssociatedConstraint, 3> TemplateAC;
   Template->getAssociatedConstraints(TemplateAC);
   if (TemplateAC.empty()) {
-    Satisfaction.IsSatisfied = true;
+    Satisfaction.setIsSatisfied(true);
     return false;
   }
 
@@ -2056,7 +2057,7 @@ void Sema::DiagnoseUnsatisfiedConstraint(
     const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
     bool First) {
 
-  assert(!Satisfaction.IsSatisfied &&
+  assert(!Satisfaction.isSatisfied() &&
          "Attempted to diagnose a satisfied constraint");
   ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
 }
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index d68a9ec2d8f35..48c4449605035 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1261,38 +1261,39 @@ CoroutineStmtBuilder::CoroutineStmtBuilder(Sema &S, FunctionDecl &FD,
                                            sema::FunctionScopeInfo &Fn,
                                            Stmt *Body)
     : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),
-      IsPromiseDependentType(
-          !Fn.CoroutinePromise ||
-          Fn.CoroutinePromise->getType()->isDependentType()) {
+      ParamMovesVector(decltype(this->ParamMovesVector)::withFlags(
+          (unsigned(bool(!Fn.CoroutinePromise ||
+                         Fn.CoroutinePromise->getType()->isDependentType()))
+           << 1))) {
   this->Body = buildCoroutineBody(Body, S.getASTContext());
 
   for (auto KV : Fn.CoroutineParameterMoves)
     this->ParamMovesVector.push_back(KV.second);
   this->ParamMoves = this->ParamMovesVector;
 
-  if (!IsPromiseDependentType) {
+  if (!getIsPromiseDependentType()) {
     PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();
     assert(PromiseRecordDecl && "Type should have already been checked");
   }
-  this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();
+  this->setIsValid(makePromiseStmt() && makeInitialAndFinalSuspend());
 }
 
 bool CoroutineStmtBuilder::buildStatements() {
-  assert(this->IsValid && "coroutine already invalid");
-  this->IsValid = makeReturnObject();
-  if (this->IsValid && !IsPromiseDependentType)
+  assert(this->getIsValid() && "coroutine already invalid");
+  this->setIsValid(makeReturnObject());
+  if (this->getIsValid() && !getIsPromiseDependentType())
     buildDependentStatements();
-  return this->IsValid;
+  return this->getIsValid();
 }
 
 bool CoroutineStmtBuilder::buildDependentStatements() {
-  assert(this->IsValid && "coroutine already invalid");
-  assert(!this->IsPromiseDependentType &&
+  assert(this->getIsValid() && "coroutine already invalid");
+  assert(!this->getIsPromiseDependentType() &&
          "coroutine cannot have a dependent promise type");
-  this->IsValid = makeOnException() && makeOnFallthrough() &&
-                  makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
-                  makeNewAndDeleteExpr();
-  return this->IsValid;
+  this->setIsValid(makeOnException() && makeOnFallthrough() &&
+                   makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&
+                   makeNewAndDeleteExpr());
+  return this->getIsValid();
 }
 
 bool CoroutineStmtBuilder::makePromiseStmt() {
@@ -1339,7 +1340,7 @@ static bool diagReturnOnAllocFailure(Sema &S, Expr *E,
 }
 
 bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
-  assert(!IsPromiseDependentType &&
+  assert(!getIsPromiseDependentType() &&
          "cannot make statement while the promise type is dependent");
 
   // [dcl.fct.def.coroutine]p10
@@ -1427,7 +1428,7 @@ static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc,
 
 bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // Form and check allocation and deallocation calls.
-  assert(!IsPromiseDependentType &&
+  assert(!getIsPromiseDependentType() &&
          "cannot make statement while the promise type is dependent");
   QualType PromiseType = Fn.CoroutinePromise->getType();
 
@@ -1756,7 +1757,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 }
 
 bool CoroutineStmtBuilder::makeOnFallthrough() {
-  assert(!IsPromiseDependentType &&
+  assert(!getIsPromiseDependentType() &&
          "cannot make statement while the promise type is dependent");
 
   // [dcl.fct.def.coroutine]/p6
@@ -1813,7 +1814,7 @@ bool CoroutineStmtBuilder::makeOnFallthrough() {
 
 bool CoroutineStmtBuilder::makeOnException() {
   // Try to form 'p.unhandled_exception();'
-  assert(!IsPromiseDependentType &&
+  assert(!getIsPromiseDependentType() &&
          "cannot make statement while the promise type is dependent");
 
   const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;
@@ -1878,7 +1879,7 @@ static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn) {
 }
 
 bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {
-  assert(!IsPromiseDependentType &&
+  assert(!getIsPromiseDependentType() &&
          "cannot make statement while the promise type is dependent");
   assert(this->ReturnValue && "ReturnValue must be already formed");
 
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4f6e65c1c4708..33fb334c02c5e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -71,6 +71,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include <algorithm>
 #include <cstring>
+#include <memory>
 #include <optional>
 #include <unordered_map>
 
@@ -14460,8 +14461,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
   // we should destroy the first Temp before constructing the second.
 
   // Set context flag for OverflowBehaviorType initialization analysis
-  llvm::SaveAndRestore OBTAssignmentContext(InOverflowBehaviorAssignmentContext,
-                                            true);
+  auto OBTAssignmentContext = [PackedFlagOwner_ = this] {
+    const bool PackedFlagOld_ =
+        PackedFlagOwner_->getInOverflowBehaviorAssignmentContext();
+    PackedFlagOwner_->setInOverflowBehaviorAssignmentContext(true);
+    return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+      PackedFlagOwner_->setInOverflowBehaviorAssignmentContext(PackedFlagOld_);
+    });
+  }();
   ExprResult Result =
       ActOnFinishFullExpr(Init, VDecl->getLocation(),
                           /*DiscardedValue*/ false, VDecl->isConstexpr());
@@ -16454,8 +16461,8 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) {
   // where we would set the CurContext to the lambda operator before
   // substituting into it. In this case the flag needs to be true such that
   // tryCaptureVariable can correctly handle potential captures thereof.
-  LSI->AfterParameterList = CurContext == CallOperator;
-  LSI->BeforeCompoundStatement = false;
+  LSI->setAfterParameterList(CurContext == CallOperator);
+  LSI->setBeforeCompoundStatement(false);
 
   // GLTemplateParameterList is necessary for getCurGenericLambda() which is
   // used at the point of dealing with potential captures.
@@ -16478,7 +16485,7 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) {
   DeclarationNameInfo DNI = CallOperator->getNameInfo();
 
   LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
-  LSI->Mutable = !CallOperator->isConst();
+  LSI->setMutable(!CallOperator->isConst());
   if (CallOperator->isExplicitObjectMemberFunction())
     LSI->ExplicitObjectParameter = CallOperator->getParamDecl(0);
 
@@ -17037,7 +17044,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
         // In C++11, we don't use 'auto' deduction rules for lambda call
         // operators because we don't support return type deduction.
         auto *LSI = getCurLambda();
-        if (LSI->HasImplicitReturnType) {
+        if (LSI->getHasImplicitReturnType()) {
           deduceClosureReturnType(*LSI);
 
           // C++11 [expr.prim.lambda]p4:
@@ -20058,7 +20065,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
       if (S.CheckFunctionConstraints(Method, Satisfaction))
         SatisfactionStatus.push_back(false);
       else
-        SatisfactionStatus.push_back(Satisfaction.IsSatisfied);
+        SatisfactionStatus.push_back(Satisfaction.isSatisfied());
     }
   }
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index cd9771526bee3..b3d518b30dcc2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -50,6 +50,7 @@
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/SaveAndRestore.h"
@@ -3821,23 +3822,24 @@ namespace {
     llvm::SmallPtrSetImpl<QualType> &BaseClasses;
     // Vector of decls to be removed from the Decl set prior to visiting the
     // nodes.  These Decls may have been initialized in the prior initializer.
-    llvm::SmallVector<ValueDecl*, 4> DeclsToRemove;
+    llvm::SmallVectorWithFlags<ValueDecl *, 4> DeclsToRemove;
     // If non-null, add a note to the warning pointing back to the constructor.
     const CXXConstructorDecl *Constructor;
     // Variables to hold state when processing an initializer list.  When
     // InitList is true, special case initialization of FieldDecls matching
     // InitListFieldDecl.
-    bool InitList;
+    bool getInitList() const { return DeclsToRemove.getFlag(0); }
+    void setInitList(bool Value) { DeclsToRemove.setFlag(0, Value); }
     FieldDecl *InitListFieldDecl;
     llvm::SmallVector<unsigned, 4> InitFieldIndex;
 
   public:
     typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
     UninitializedFieldVisitor(Sema &S,
-                              llvm::SmallPtrSetImpl<ValueDecl*> &Decls,
+                              llvm::SmallPtrSetImpl<ValueDecl *> &Decls,
                               llvm::SmallPtrSetImpl<QualType> &BaseClasses)
-      : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
-        Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {}
+        : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
+          Constructor(nullptr), InitListFieldDecl(nullptr) {}
 
     // Returns true if the use of ME is not an uninitialized use.
     bool IsInitListMemberExprInitialized(MemberExpr *ME,
@@ -3937,7 +3939,7 @@ namespace {
 
       const bool IsReference = FoundVD->getType()->isReferenceType();
 
-      if (InitList && !AddressOf && FoundVD == InitListFieldDecl) {
+      if (getInitList() && !AddressOf && FoundVD == InitListFieldDecl) {
         // Special checking for initializer lists.
         if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) {
           return;
@@ -4031,12 +4033,12 @@ namespace {
       InitListExpr *ILE = dyn_cast<InitListExpr>(E);
 
       if (ILE && Field) {
-        InitList = true;
+        setInitList(true);
         InitListFieldDecl = Field;
         InitFieldIndex.clear();
         CheckInitListExpr(ILE);
       } else {
-        InitList = false;
+        setInitList(false);
         Visit(E);
       }
 
@@ -6705,7 +6707,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
       if (BC->getTrailingRequiresClause()) {
         ConstraintSatisfaction Satisfaction;
         if (CheckFunctionConstraints(BC, Satisfaction) ||
-            !Satisfaction.IsSatisfied)
+            !Satisfaction.isSatisfied())
           continue;
       }
       findInheritingConstructor(Class->getLocation(), BC, S);
@@ -6776,7 +6778,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
           // specialization.
           ConstraintSatisfaction Satisfaction;
           if (CheckFunctionConstraints(MD, Satisfaction) ||
-              !Satisfaction.IsSatisfied)
+              !Satisfaction.isSatisfied())
             continue;
         }
       }
@@ -8637,12 +8639,13 @@ class DefaultedComparisonAnalyzer
 
 /// A list of statements.
 struct StmtListResult {
-  bool IsInvalid = false;
-  llvm::SmallVector<Stmt*, 16> Stmts;
+  bool getIsInvalid() const { return Stmts.getFlag(0); }
+  void setIsInvalid(bool Value) { Stmts.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<Stmt *, 16> Stmts;
 
   bool add(const StmtResult &S) {
-    IsInvalid |= S.isInvalid();
-    if (IsInvalid)
+    setIsInvalid(int(getIsInvalid()) | (S.isInvalid()));
+    if (getIsInvalid())
       return true;
     Stmts.push_back(S.get());
     return false;
@@ -8674,7 +8677,7 @@ class DefaultedComparisonSynthesizer
     Sema::CompoundScopeRAII CompoundScope(S);
 
     StmtListResult Stmts = visit();
-    if (Stmts.IsInvalid)
+    if (Stmts.getIsInvalid())
       return StmtError();
 
     ExprResult RetVal;
@@ -8691,7 +8694,7 @@ class DefaultedComparisonSynthesizer
       // Join the comparisons with '&&'s and return the result. Use a right
       // fold (traversing the conditions right-to-left), because that
       // short-circuits more naturally.
-      auto OldStmts = std::move(Stmts.Stmts);
+      auto OldStmts = llvm::SmallVector<Stmt *, 16>(std::move(Stmts.Stmts));
       Stmts.Stmts.clear();
       ExprResult CmpSoFar;
       // Finish a particular comparison chain.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e29caaab8e3f3..0f111ca79359f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -64,6 +64,7 @@
 #include "clang/Sema/SemaPseudoObject.h"
 #include "clang/Sema/Template.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/Support/ConvertUTF.h"
@@ -71,6 +72,7 @@
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/TypeSize.h"
 #include <limits>
+#include <memory>
 #include <optional>
 
 using namespace clang;
@@ -301,7 +303,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
         // A diagnostic will have already been generated (non-constant
         // constraint expression, for example)
         return true;
-      if (!Satisfaction.IsSatisfied) {
+      if (!Satisfaction.isSatisfied()) {
         Diag(Loc,
              diag::err_reference_to_function_with_unsatisfied_constraints)
             << D;
@@ -2130,7 +2132,7 @@ static Decl *getPredefinedExprDecl(Sema &S, DeclContext *DC) {
       while (LSI != E && !isa<LambdaScopeInfo>(*LSI))
         ++LSI;
       assert(LSI != E && "Should be in a lambda scope info");
-      if (dyn_cast<LambdaScopeInfo>(*LSI)->BeforeCompoundStatement)
+      if (dyn_cast<LambdaScopeInfo>(*LSI)->getBeforeCompoundStatement())
         DC = DC->getParent();
       ++LSI;
     }
@@ -4903,7 +4905,7 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
   // Adds overload of TransformToPotentiallyEvaluated for TypeSourceInfo to
   // properly deal with VLAs in nested calls of sizeof and typeof.
   if (currentEvaluationContext().isUnevaluated() &&
-      currentEvaluationContext().InConditionallyConstantEvaluateContext &&
+      currentEvaluationContext().getInConditionallyConstantEvaluateContext() &&
       (ExprKind == UETT_SizeOf || ExprKind == UETT_CountOf) &&
       TInfo->getType()->isVariablyModifiedType())
     TInfo = TransformToPotentiallyEvaluated(TInfo);
@@ -5737,8 +5739,11 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
           ? ExpressionEvaluationContext::ImmediateFunctionContext
           : ExpressionEvaluationContext::PotentiallyEvaluated,
       Param);
-  ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer =
-      SkipImmediateInvocations;
+  [&] {
+    auto PackedFlagValue_ = SkipImmediateInvocations;
+    return ExprEvalContexts.back()
+        .setIsCurrentlyCheckingDefaultArgumentOrInitializer(PackedFlagValue_);
+  }();
   runWithSufficientStackSpace(CallLoc, [&] {
     MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables=*/true);
   });
@@ -5884,8 +5889,12 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
             CallLoc, Param, CurContext};
       // Pass down lifetime extending flag, and collect temporaries in
       // CreateMaterializeTemporaryExpr when we rewrite the call argument.
-      currentEvaluationContext().InLifetimeExtendingContext =
-          parentEvaluationContext().InLifetimeExtendingContext;
+      [&] {
+        auto PackedFlagValue_ =
+            parentEvaluationContext().getInLifetimeExtendingContext();
+        return currentEvaluationContext().setInLifetimeExtendingContext(
+            PackedFlagValue_);
+      }();
       EnsureImmediateInvocationInDefaultArgs Immediate(*this);
       ExprResult Res;
       runWithSufficientStackSpace(CallLoc, [&] {
@@ -5998,12 +6007,19 @@ ExprResult Sema::BuildCXXDefaultInitInternal(SourceLocation Loc,
       (V.HasImmediateCalls || (NeedRebuild && ContainsAnyTemporaries))) {
     ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field,
                                                                    CurContext};
-    ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer =
-        NestedDefaultChecking;
+    [&] {
+      auto PackedFlagValue_ = NestedDefaultChecking;
+      return ExprEvalContexts.back()
+          .setIsCurrentlyCheckingDefaultArgumentOrInitializer(PackedFlagValue_);
+    }();
     // Pass down lifetime extending flag, and collect temporaries in
     // CreateMaterializeTemporaryExpr when we rewrite the initializer.
-    currentEvaluationContext().InLifetimeExtendingContext =
-        parentEvaluationContext().InLifetimeExtendingContext;
+    [&] {
+      auto PackedFlagValue_ =
+          parentEvaluationContext().getInLifetimeExtendingContext();
+      return currentEvaluationContext().setInLifetimeExtendingContext(
+          PackedFlagValue_);
+    }();
 
     EnsureImmediateInvocationInDefaultArgs Immediate(*this);
     ExprResult Res;
@@ -17188,7 +17204,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
   else
     CurContext = Block;
 
-  getCurBlock()->HasImplicitReturnType = true;
+  getCurBlock()->setHasImplicitReturnType(true);
 
   // Enter a new evaluation context to insulate the block from any
   // cleanups from the enclosing full-expression.
@@ -17252,7 +17268,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
   if (RetTy != Context.DependentTy) {
     CurBlock->ReturnType = RetTy;
     CurBlock->TheDecl->setBlockMissingReturnType(false);
-    CurBlock->HasImplicitReturnType = false;
+    CurBlock->setHasImplicitReturnType(false);
   }
 
   // Push block parameters from the declarator if we had them.
@@ -17333,7 +17349,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
 
   maybeAddDeclWithEffects(BD);
 
-  if (BSI->HasImplicitReturnType)
+  if (BSI->getHasImplicitReturnType())
     deduceClosureReturnType(*BSI);
 
   QualType RetTy = Context.VoidTy;
@@ -17479,7 +17495,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
   PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo(&WP, BD, BlockTy);
 
   BlockExpr *Result = new (Context)
-      BlockExpr(BD, BlockTy, BSI->ContainsUnexpandedParameterPack);
+      BlockExpr(BD, BlockTy, BSI->getContainsUnexpandedParameterPack());
 
   // If the block isn't obviously global, i.e. it captures anything at
   // all, then we need to do a few things in the surrounding context:
@@ -18490,19 +18506,29 @@ Sema::PushExpressionEvaluationContext(
   // Discarded statements and immediate contexts nested in other
   // discarded statements or immediate context are themselves
   // a discarded statement or an immediate context, respectively.
-  ExprEvalContexts.back().InDiscardedStatement =
-      parentEvaluationContext().isDiscardedStatementContext();
+  [&] {
+    auto PackedFlagValue_ =
+        parentEvaluationContext().isDiscardedStatementContext();
+    return ExprEvalContexts.back().setInDiscardedStatement(PackedFlagValue_);
+  }();
 
   // C++23 [expr.const]/p15
   // An expression or conversion is in an immediate function context if [...]
   // it is a subexpression of a manifestly constant-evaluated expression or
   // conversion.
   const auto &Prev = parentEvaluationContext();
-  ExprEvalContexts.back().InImmediateFunctionContext =
-      Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated();
+  [&] {
+    auto PackedFlagValue_ =
+        Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated();
+    return ExprEvalContexts.back().setInImmediateFunctionContext(
+        PackedFlagValue_);
+  }();
 
-  ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
-      Prev.InImmediateEscalatingFunctionContext;
+  [&] {
+    auto PackedFlagValue_ = Prev.getInImmediateEscalatingFunctionContext();
+    return ExprEvalContexts.back().setInImmediateEscalatingFunctionContext(
+        PackedFlagValue_);
+  }();
 
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
@@ -18531,7 +18557,7 @@ void Sema::PushExpressionEvaluationContextForFunction(
       parentEvaluationContext();
   Sema::ExpressionEvaluationContextRecord &Current = currentEvaluationContext();
 
-  Current.InDiscardedStatement = false;
+  Current.setInDiscardedStatement(false);
 
   if (FD) {
 
@@ -18543,16 +18569,16 @@ void Sema::PushExpressionEvaluationContextForFunction(
     // function is entered, we need to reset this tracking, since the entered
     // function might be not an immediate function.
 
-    Current.InImmediateEscalatingFunctionContext =
-        getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
+    Current.setInImmediateEscalatingFunctionContext(
+        getLangOpts().CPlusPlus20 && FD->isImmediateEscalating());
 
     if (isLambdaMethod(FD))
-      Current.InImmediateFunctionContext =
+      Current.setInImmediateFunctionContext(
           FD->isConsteval() ||
           (isLambdaMethod(FD) && (Parent.isConstantEvaluated() ||
-                                  Parent.isImmediateFunctionContext()));
+                                  Parent.isImmediateFunctionContext())));
     else
-      Current.InImmediateFunctionContext = FD->isConsteval();
+      Current.setInImmediateFunctionContext(FD->isConsteval());
   }
 }
 
@@ -18628,7 +18654,7 @@ void Sema::CheckUnusedVolatileAssignment(Expr *E) {
 
 void Sema::MarkExpressionAsImmediateEscalating(Expr *E) {
   assert(getLangOpts().CPlusPlus20 &&
-         ExprEvalContexts.back().InImmediateEscalatingFunctionContext &&
+         ExprEvalContexts.back().getInImmediateEscalatingFunctionContext() &&
          "Cannot mark an immediate escalating expression outside of an "
          "immediate escalating context");
   if (auto *Call = dyn_cast<CallExpr>(E->IgnoreImplicit());
@@ -18651,7 +18677,7 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
   if (isUnevaluatedContext() || !E.isUsable() || !Decl ||
       !Decl->isImmediateFunction() || isAlwaysConstantEvaluatedContext() ||
       isCheckingDefaultArgumentOrInitializer() ||
-      RebuildingImmediateInvocation || isImmediateFunctionContext())
+      getRebuildingImmediateInvocation() || isImmediateFunctionContext())
     return E;
 
   /// Opportunistically remove the callee from ReferencesToConsteval if we can.
@@ -18681,7 +18707,7 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
   };
 
   if (!E.get()->isValueDependent() &&
-      ExprEvalContexts.back().InImmediateEscalatingFunctionContext &&
+      ExprEvalContexts.back().getInImmediateEscalatingFunctionContext() &&
       !CheckConstantExpressionAndKeepResult()) {
     MarkExpressionAsImmediateEscalating(E.get());
     return E;
@@ -18880,7 +18906,8 @@ HandleImmediateInvocations(Sema &SemaRef,
                            Sema::ExpressionEvaluationContextRecord &Rec) {
   if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
        Rec.ReferenceToConsteval.size() == 0) ||
-      Rec.isImmediateFunctionContext() || SemaRef.RebuildingImmediateInvocation)
+      Rec.isImmediateFunctionContext() ||
+      SemaRef.getRebuildingImmediateInvocation())
     return;
 
   // An expression or conversion is 'manifestly constant-evaluated' if it is:
@@ -18912,8 +18939,14 @@ HandleImmediateInvocations(Sema &SemaRef,
 
     /// Prevent sema calls during the tree transform from adding pointers that
     /// are already in the sets.
-    llvm::SaveAndRestore DisableIITracking(
-        SemaRef.RebuildingImmediateInvocation, true);
+    auto DisableIITracking = [PackedFlagOwner_ = std::addressof(SemaRef)] {
+      const bool PackedFlagOld_ =
+          PackedFlagOwner_->getRebuildingImmediateInvocation();
+      PackedFlagOwner_->setRebuildingImmediateInvocation(true);
+      return llvm::scope_exit([PackedFlagOwner_, PackedFlagOld_] {
+        PackedFlagOwner_->setRebuildingImmediateInvocation(PackedFlagOld_);
+      });
+    }();
 
     /// Prevent diagnostic during tree transfrom as they are duplicates
     Sema::TentativeAnalysisScope DisableDiag(SemaRef);
@@ -18962,9 +18995,9 @@ HandleImmediateInvocations(Sema &SemaRef,
         Rec.Context ==
             Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed;
     if (SemaRef.inTemplateInstantiation() && IsPotentiallyEvaluated)
-      ImmediateEscalating = Rec.InImmediateEscalatingFunctionContext;
+      ImmediateEscalating = Rec.getInImmediateEscalatingFunctionContext();
 
-    if (!Rec.InImmediateEscalatingFunctionContext ||
+    if (!Rec.getInImmediateEscalatingFunctionContext() ||
         (SemaRef.inTemplateInstantiation() && !ImmediateEscalating)) {
       SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address)
           << ND << isa<CXXRecordDecl>(ND) << FD->isConsteval();
@@ -19019,8 +19052,8 @@ void Sema::PopExpressionEvaluationContext() {
 
   // Append the collected materialized temporaries into previous context before
   // exit if the previous also is a lifetime extending context.
-  if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
-      parentEvaluationContext().InLifetimeExtendingContext &&
+  if (getLangOpts().CPlusPlus23 && Rec.getInLifetimeExtendingContext() &&
+      parentEvaluationContext().getInLifetimeExtendingContext() &&
       !Rec.ForRangeLifetimeExtendTemps.empty()) {
     parentEvaluationContext().ForRangeLifetimeExtendTemps.append(
         Rec.ForRangeLifetimeExtendTemps);
@@ -20188,7 +20221,7 @@ bool Sema::tryCaptureVariable(
     // NOT the lambda but its parent. So move away the current LSI before
     // aligning DC and FunctionScopeIndexToStopAt.
     if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]);
-        FSIndex && LSI && !LSI->AfterParameterList)
+        FSIndex && LSI && !LSI->getAfterParameterList())
       --FSIndex;
     assert(MaxFunctionScopesIndex <= FSIndex &&
            "FunctionScopeIndexToStopAt should be no greater than FSIndex into "
@@ -20231,9 +20264,9 @@ bool Sema::tryCaptureVariable(
           FunctionScopes[FunctionScopesIndex]);
 
     bool IsInScopeDeclarationContext =
-        !LSI || LSI->AfterParameterList || CurContext == LSI->CallOperator;
+        !LSI || LSI->getAfterParameterList() || CurContext == LSI->CallOperator;
 
-    if (LSI && !LSI->AfterParameterList) {
+    if (LSI && !LSI->getAfterParameterList()) {
       // This allows capturing parameters from a default value which does not
       // seems correct
       if (isa<ParmVarDecl>(Var) && !Var->getDeclContext()->isFunctionOrMethod())
@@ -21170,7 +21203,7 @@ static void FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter(
         continue;
 
       if (LSI->Lambda && !LSI->Lambda->Encloses(SemaRef.CurContext) &&
-          LSI->AfterParameterList)
+          LSI->getAfterParameterList())
         return false;
 
       const auto *MD = LSI->CallOperator;
@@ -21263,7 +21296,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
     if (!isUnevaluatedContext() && !isConstantEvaluatedContext() &&
         !isImmediateFunctionContext() &&
         !isCheckingDefaultArgumentOrInitializer() &&
-        FD->isImmediateFunction() && !RebuildingImmediateInvocation &&
+        FD->isImmediateFunction() && !getRebuildingImmediateInvocation() &&
         !FD->isDependentContext())
       ExprEvalContexts.back().ReferenceToConsteval.insert(E);
   }
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 916c5308508f1..833fc2cc282f8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -48,6 +48,7 @@
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/TypeSize.h"
@@ -1469,7 +1470,7 @@ void Sema::MarkThisReferenced(CXXThisExpr *This) {
         continue;
 
       if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext) &&
-          LSI->AfterParameterList)
+          LSI->getAfterParameterList())
         return false;
 
       // If this lambda captures 'this' by value, then 'this' is dependent iff
@@ -3480,7 +3481,7 @@ Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
 }
 
 void Sema::DeclareGlobalNewDelete() {
-  if (GlobalNewDeleteDeclared)
+  if (getGlobalNewDeleteDeclared())
     return;
 
   // The implicitly declared new and delete operators
@@ -3572,7 +3573,7 @@ void Sema::DeclareGlobalNewDelete() {
     StdAlignValT = AlignValT;
   }
 
-  GlobalNewDeleteDeclared = true;
+  setGlobalNewDeleteDeclared(true);
 
   QualType VoidPtr = Context.getPointerType(Context.VoidTy);
   QualType SizeT = Context.getSizeType();
@@ -3882,8 +3883,8 @@ class MismatchingNewDeleteDetector {
   /// translation unit. False, if this is the initial analysis at the point
   /// delete-expression was encountered.
   explicit MismatchingNewDeleteDetector(bool EndOfTU)
-      : Field(nullptr), IsArrayForm(false), EndOfTU(EndOfTU),
-        HasUndefinedConstructors(false) {}
+      : Field(nullptr), NewExprs(decltype(this->NewExprs)::withFlags(
+                            (unsigned(EndOfTU) << 1))) {}
 
   /// Checks whether pointee of a delete-expression is initialized with
   /// matching form of new-expression.
@@ -3903,14 +3904,16 @@ class MismatchingNewDeleteDetector {
   MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm);
   FieldDecl *Field;
   /// List of mismatching new-expressions used for initialization of the pointee
-  llvm::SmallVector<const CXXNewExpr *, 4> NewExprs;
+  llvm::SmallVectorWithFlags<const CXXNewExpr *, 4, 3> NewExprs;
   /// Indicates whether delete-expression was in array form.
-  bool IsArrayForm;
+  bool getIsArrayForm() const { return NewExprs.getFlag(0); }
+  void setIsArrayForm(bool Value) { NewExprs.setFlag(0, Value); }
 
 private:
-  const bool EndOfTU;
+  bool getEndOfTU() const { return NewExprs.getFlag(1); }
   /// Indicates that there is at least one constructor without body.
-  bool HasUndefinedConstructors;
+  bool getHasUndefinedConstructors() const { return NewExprs.getFlag(2); }
+  void setHasUndefinedConstructors(bool Value) { NewExprs.setFlag(2, Value); }
   /// Returns \c CXXNewExpr from given initialization expression.
   /// \param E Expression used for initializing pointee in delete-expression.
   /// E can be a single-element \c InitListExpr consisting of new-expression.
@@ -3946,6 +3949,14 @@ class MismatchingNewDeleteDetector {
   /// Checks whether member is initialized with mismatching form of \c new by
   /// in-class initializer.
   MismatchResult analyzeInClassInitializer();
+
+public:
+  MismatchingNewDeleteDetector(const MismatchingNewDeleteDetector &) = default;
+  MismatchingNewDeleteDetector(MismatchingNewDeleteDetector &&) = default;
+  MismatchingNewDeleteDetector &
+  operator=(const MismatchingNewDeleteDetector &) = delete;
+  MismatchingNewDeleteDetector &
+  operator=(MismatchingNewDeleteDetector &&) = delete;
 };
 }
 
@@ -3953,7 +3964,7 @@ MismatchingNewDeleteDetector::MismatchResult
 MismatchingNewDeleteDetector::analyzeDeleteExpr(const CXXDeleteExpr *DE) {
   NewExprs.clear();
   assert(DE && "Expected delete-expression");
-  IsArrayForm = DE->isArrayForm();
+  setIsArrayForm(DE->isArrayForm());
   const Expr *E = DE->getArgument()->IgnoreParenImpCasts();
   if (const MemberExpr *ME = dyn_cast<const MemberExpr>(E)) {
     return analyzeMemberExpr(ME);
@@ -3981,7 +3992,7 @@ bool MismatchingNewDeleteDetector::hasMatchingNewInCtorInit(
   const CXXNewExpr *NE = nullptr;
   if (Field == CI->getMember() &&
       (NE = getNewExprFromInitListOrExpr(CI->getInit()))) {
-    if (NE->isArray() == IsArrayForm)
+    if (NE->isArray() == getIsArrayForm())
       return true;
     else
       NewExprs.push_back(NE);
@@ -3995,8 +4006,8 @@ bool MismatchingNewDeleteDetector::hasMatchingNewInCtor(
     return false;
   const FunctionDecl *Definition = CD;
   if (!CD->isThisDeclarationADefinition() && !CD->isDefined(Definition)) {
-    HasUndefinedConstructors = true;
-    return EndOfTU;
+    setHasUndefinedConstructors(true);
+    return getEndOfTU();
   }
   for (const auto *CI : cast<const CXXConstructorDecl>(Definition)->inits()) {
     if (hasMatchingNewInCtorInit(CI))
@@ -4010,9 +4021,9 @@ MismatchingNewDeleteDetector::analyzeInClassInitializer() {
   assert(Field != nullptr && "This should be called only for members");
   const Expr *InitExpr = Field->getInClassInitializer();
   if (!InitExpr)
-    return EndOfTU ? NoMismatch : AnalyzeLater;
+    return getEndOfTU() ? NoMismatch : AnalyzeLater;
   if (const CXXNewExpr *NE = getNewExprFromInitListOrExpr(InitExpr)) {
-    if (NE->isArray() != IsArrayForm) {
+    if (NE->isArray() != getIsArrayForm()) {
       NewExprs.push_back(NE);
       return MemberInitMismatches;
     }
@@ -4025,14 +4036,14 @@ MismatchingNewDeleteDetector::analyzeField(FieldDecl *Field,
                                            bool DeleteWasArrayForm) {
   assert(Field != nullptr && "Analysis requires a valid class member.");
   this->Field = Field;
-  IsArrayForm = DeleteWasArrayForm;
+  setIsArrayForm(DeleteWasArrayForm);
   const CXXRecordDecl *RD = cast<const CXXRecordDecl>(Field->getParent());
   for (const auto *CD : RD->ctors()) {
     if (hasMatchingNewInCtor(CD))
       return NoMismatch;
   }
-  if (HasUndefinedConstructors)
-    return EndOfTU ? NoMismatch : AnalyzeLater;
+  if (getHasUndefinedConstructors())
+    return getEndOfTU() ? NoMismatch : AnalyzeLater;
   if (!NewExprs.empty())
     return MemberInitMismatches;
   return Field->hasInClassInitializer() ? analyzeInClassInitializer()
@@ -4043,7 +4054,7 @@ MismatchingNewDeleteDetector::MismatchResult
 MismatchingNewDeleteDetector::analyzeMemberExpr(const MemberExpr *ME) {
   assert(ME != nullptr && "Expected a member expression");
   if (FieldDecl *F = dyn_cast<FieldDecl>(ME->getMemberDecl()))
-    return analyzeField(F, IsArrayForm);
+    return analyzeField(F, getIsArrayForm());
   return NoMismatch;
 }
 
@@ -4051,7 +4062,7 @@ bool MismatchingNewDeleteDetector::hasMatchingVarInit(const DeclRefExpr *D) {
   const CXXNewExpr *NE = nullptr;
   if (const VarDecl *VD = dyn_cast<const VarDecl>(D->getDecl())) {
     if (VD->hasInit() && (NE = getNewExprFromInitListOrExpr(VD->getInit())) &&
-        NE->isArray() != IsArrayForm) {
+        NE->isArray() != getIsArrayForm()) {
       NewExprs.push_back(NE);
     }
   }
@@ -4063,7 +4074,7 @@ DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc,
                             const MismatchingNewDeleteDetector &Detector) {
   SourceLocation EndOfDelete = SemaRef.getLocForEndOfToken(DeleteLoc);
   FixItHint H;
-  if (!Detector.IsArrayForm)
+  if (!Detector.getIsArrayForm())
     H = FixItHint::CreateInsertion(EndOfDelete, "[]");
   else {
     SourceLocation RSquare = Lexer::findLocationAfterToken(
@@ -4073,11 +4084,11 @@ DiagnoseMismatchedNewDelete(Sema &SemaRef, SourceLocation DeleteLoc,
       H = FixItHint::CreateRemoval(SourceRange(EndOfDelete, RSquare));
   }
   SemaRef.Diag(DeleteLoc, diag::warn_mismatched_delete_new)
-      << Detector.IsArrayForm << H;
+      << Detector.getIsArrayForm() << H;
 
   for (const auto *NE : Detector.NewExprs)
     SemaRef.Diag(NE->getExprLoc(), diag::note_allocated_here)
-        << Detector.IsArrayForm;
+        << Detector.getIsArrayForm();
 }
 
 void Sema::AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE) {
@@ -7778,7 +7789,8 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
   while (isa_and_nonnull<CapturedDecl>(DC))
     DC = DC->getParent();
   assert(
-      (CurrentLSI->CallOperator == DC || !CurrentLSI->AfterParameterList) &&
+      (CurrentLSI->CallOperator == DC ||
+       !CurrentLSI->getAfterParameterList()) &&
       "The current call operator must be synchronized with Sema's CurContext");
 #endif // NDEBUG
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 4fe7ed151e918..1e193ddd457eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -37,6 +37,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -3022,10 +3023,11 @@ template <typename T> constexpr uint64_t barrierFlagValue(T Flag) {
 /// the entry points.
 class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
   Sema &SemaRef;
-  bool DiagnoseAvailability;
+  bool getDiagnoseAvailability() const { return DeclsToScan.getFlag(0); }
+  void setDiagnoseAvailability(bool Value) { DeclsToScan.setFlag(0, Value); }
 
   // Stack of functions to be scaned
-  llvm::SmallVector<const FunctionDecl *, 8> DeclsToScan;
+  llvm::SmallVectorWithFlags<const FunctionDecl *, 8, 2> DeclsToScan;
 
   // Tracks which environments functions have been scanned in.
   //
@@ -3059,7 +3061,10 @@ class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
   // True if scanning a function that was already scanned in a different
   // shader stage context. Suppress stage-independent diagnostics because
   // they were reported during the first scan.
-  bool ReportOnlyShaderStageIssues;
+  bool getReportOnlyShaderStageIssues() const { return DeclsToScan.getFlag(1); }
+  void setReportOnlyShaderStageIssues(bool Value) {
+    DeclsToScan.setFlag(1, Value);
+  }
 
   // Helper methods for dealing with current stage context / environment
   void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {
@@ -3125,9 +3130,10 @@ class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {
 
 public:
   DiagnoseHLSLAvailability(Sema &SemaRef, bool DiagnoseAvailability)
-      : SemaRef(SemaRef), DiagnoseAvailability(DiagnoseAvailability),
+      : SemaRef(SemaRef), DeclsToScan(decltype(this->DeclsToScan)::withFlags(
+                              unsigned(DiagnoseAvailability))),
         CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),
-        CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}
+        CurrentShaderStageBit(0) {}
 
   // AST traversal methods
   void RunOnTranslationUnit(const TranslationUnitDecl *TU);
@@ -3205,7 +3211,7 @@ void DiagnoseHLSLAvailability::DiagnoseBarrierGroupSemantic(
 void DiagnoseHLSLAvailability::DiagnoseBarrierScope(Expr *SemanticArg,
                                                     uint64_t MemoryFlags,
                                                     uint64_t SemanticFlags) {
-  if (ReportOnlyShaderStageIssues)
+  if (getReportOnlyShaderStageIssues())
     return;
 
   const uint64_t DeviceScopeMemory =
@@ -3275,7 +3281,7 @@ void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
   assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
          "expected DeclRefExpr or MemberExpr");
 
-  if (DiagnoseAvailability)
+  if (getDiagnoseAvailability())
     if (const AvailabilityAttr *AA = FindAvailabilityAttr(FD))
       CheckDeclAvailability(
           FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
@@ -3381,7 +3387,7 @@ void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
     if (WasAlreadyScannedInCurrentStage(ScannedStages))
       continue;
 
-    ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
+    setReportOnlyShaderStageIssues(!NeverBeenScanned(ScannedStages));
 
     AddToScannedFunctions(FD);
     TraverseStmt(FD->getBody());
@@ -3451,7 +3457,7 @@ void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
     // Do not report shader-stage-independent issues if scanning a function
     // that was already scanned in a different shader stage context (they would
     // be duplicate)
-    if (ReportOnlyShaderStageIssues)
+    if (getReportOnlyShaderStageIssues())
       return;
 
   } else {
@@ -5902,13 +5908,13 @@ void SemaHLSL::deduceAddressSpace(VarDecl *Decl) {
   bool IsVulkan = getASTContext().getTargetInfo().getTriple().getOS() ==
                   llvm::Triple::Vulkan;
   if (IsVulkan && Decl->hasAttr<HLSLVkPushConstantAttr>()) {
-    if (HasDeclaredAPushConstant)
+    if (getHasDeclaredAPushConstant())
       SemaRef.Diag(Decl->getLocation(), diag::err_hlsl_push_constant_unique);
 
     LangAS ImplAS = LangAS::hlsl_push_constant;
     Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);
     Decl->setType(Type);
-    HasDeclaredAPushConstant = true;
+    setHasDeclaredAPushConstant(true);
     return;
   }
 
@@ -6644,12 +6650,13 @@ class InitListTransformer {
   // Is wrapping the destination type iterator required? This is only used for
   // incomplete array types where we loop over the destination type since we
   // don't know the full number of elements from the declaration.
-  bool Wrap;
+  bool getWrap() const { return ArgExprs.getFlag(0); }
+  void setWrap(bool Value) { ArgExprs.setFlag(0, Value); }
 
   bool castInitializer(Expr *E) {
     assert(DstIt && "This should always be something!");
     if (DstIt == DestTypes.end()) {
-      if (!Wrap) {
+      if (!getWrap()) {
         ArgExprs.push_back(E);
         // This is odd, but it isn't technically a failure due to conversion, we
         // handle mismatched counts of arguments differently.
@@ -6839,15 +6846,16 @@ class InitListTransformer {
 
 public:
   llvm::SmallVector<QualType, 16> DestTypes;
-  llvm::SmallVector<Expr *, 16> ArgExprs;
+  llvm::SmallVectorWithFlags<Expr *, 16> ArgExprs;
   InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)
       : S(SemaRef), Ctx(SemaRef.getASTContext()),
-        Wrap(Entity.getType()->isIncompleteArrayType()) {
+        ArgExprs(decltype(this->ArgExprs)::withFlags(
+            unsigned(bool(Entity.getType()->isIncompleteArrayType())))) {
     InitTy = Entity.getType().getNonReferenceType();
     // When we're generating initializer lists for incomplete array types we
     // need to wrap around both when building the initializers and when
     // generating the final initializer lists.
-    if (Wrap) {
+    if (getWrap()) {
       assert(InitTy->isIncompleteArrayType());
       const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);
       InitTy = IAT->getElementType();
@@ -6862,7 +6870,7 @@ class InitListTransformer {
     assert(!ArgExprs.empty() &&
            "Call buildInitializerList to generate argument expressions.");
     ArgIt = ArgExprs.begin();
-    if (!Wrap)
+    if (!getWrap())
       return generateInitListsImpl(InitTy);
     llvm::SmallVector<Expr *> Inits;
     while (ArgIt != ArgExprs.end())
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0c9a92cdd0c32..2102fea757c54 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -573,13 +573,13 @@ static void buildLambdaScopeReturnType(Sema &S, LambdaScopeInfo *LSI,
                                        CXXMethodDecl *CallOperator,
                                        bool ExplicitResultType) {
   if (ExplicitResultType) {
-    LSI->HasImplicitReturnType = false;
+    LSI->setHasImplicitReturnType(false);
     LSI->ReturnType = CallOperator->getReturnType();
     if (!LSI->ReturnType->isDependentType() && !LSI->ReturnType->isVoidType())
       S.RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType,
                             diag::err_lambda_incomplete_result);
   } else {
-    LSI->HasImplicitReturnType = true;
+    LSI->setHasImplicitReturnType(true);
   }
 }
 
@@ -597,8 +597,8 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
   LSI->CaptureDefaultLoc = CaptureDefaultLoc;
   LSI->IntroducerRange = IntroducerRange;
-  LSI->ExplicitParams = ExplicitParams;
-  LSI->Mutable = Mutable;
+  LSI->setExplicitParams(ExplicitParams);
+  LSI->setMutable(Mutable);
 }
 
 void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -751,7 +751,7 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns,
 }
 
 void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
-  assert(CSI.HasImplicitReturnType);
+  assert(CSI.getHasImplicitReturnType());
   // If it was ever a placeholder, it had to been deduced to DependentTy.
   assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType());
   assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) &&
@@ -1135,7 +1135,7 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
   LSI->CaptureDefaultLoc = Intro.DefaultLoc;
   LSI->IntroducerRange = Intro.Range;
-  LSI->AfterParameterList = false;
+  LSI->setAfterParameterList(false);
 
   assert(LSI->NumExplicitTemplateParams == 0);
 
@@ -1395,7 +1395,9 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
       LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
   }
   finishLambdaExplicitCaptures(LSI);
-  LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
+  LSI->setContainsUnexpandedParameterPack(
+      LSI->getContainsUnexpandedParameterPack() |
+      (ContainsUnexpandedParameterPack));
   PopDeclContext();
 }
 
@@ -1403,7 +1405,7 @@ void Sema::ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
                                         SourceLocation MutableLoc) {
 
   LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
-  LSI->Mutable = MutableLoc.isValid();
+  LSI->setMutable(MutableLoc.isValid());
   ContextRAII Context(*this, LSI->CallOperator, /*NewThisContext*/ false);
 
   // C++11 [expr.prim.lambda]p9:
@@ -1449,10 +1451,13 @@ void Sema::ActOnLambdaClosureParameters(
     AddTemplateParametersToLambdaCallOperator(LSI->CallOperator, LSI->Lambda,
                                               TemplateParams);
     LSI->Lambda->setLambdaIsGeneric(true);
-    LSI->ContainsUnexpandedParameterPack |=
-        TemplateParams->containsUnexpandedParameterPack();
+    [&] {
+      auto PackedFlagValue = TemplateParams->containsUnexpandedParameterPack();
+      return LSI->setContainsUnexpandedParameterPack(
+          LSI->getContainsUnexpandedParameterPack() | PackedFlagValue);
+    }();
   }
-  LSI->AfterParameterList = true;
+  LSI->setAfterParameterList(true);
 }
 
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
@@ -1461,7 +1466,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
 
   LambdaScopeInfo *LSI = getCurrentLambdaScopeUnsafe(*this);
   LSI->CallOperator->setConstexprKind(DS.getConstexprSpecifier());
-  LSI->BeforeCompoundStatement = false;
+  LSI->setBeforeCompoundStatement(false);
 
   SmallVector<ParmVarDecl *, 8> Params;
   bool ExplicitResultType;
@@ -1486,7 +1491,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
 
   if (ParamInfo.isFunctionDeclarator() != 0) {
     const auto &FTI = ParamInfo.getFunctionTypeInfo();
-    LSI->ExplicitParams = FTI.getLParenLoc().isValid();
+    LSI->setExplicitParams(FTI.getLParenLoc().isValid());
     if (!FTIHasSingleVoidParameter(FTI)) {
       Params.reserve(Params.size());
       for (unsigned I = 0; I < FTI.NumParams; ++I) {
@@ -2219,10 +2224,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc,
   CXXRecordDecl *Class = LSI->Lambda;
   CXXMethodDecl *CallOperator = LSI->CallOperator;
   SourceRange IntroducerRange = LSI->IntroducerRange;
-  bool ExplicitParams = LSI->ExplicitParams;
-  bool ExplicitResultType = !LSI->HasImplicitReturnType;
+  bool ExplicitParams = LSI->getExplicitParams();
+  bool ExplicitResultType = !LSI->getHasImplicitReturnType();
   CleanupInfo LambdaCleanup = LSI->Cleanup;
-  bool ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
+  bool ContainsUnexpandedParameterPack =
+      LSI->getContainsUnexpandedParameterPack();
   bool IsGenericLambda = Class->isGenericLambda();
 
   CallOperator->setLexicalDeclContext(Class);
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h b/clang/lib/Sema/SemaLifetimeSafety.h
index 3db298b6fec85..eaf97298d6e19 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -21,6 +21,7 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <string>
 
 namespace clang::lifetimes {
@@ -524,13 +525,14 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
 
 private:
   struct LifetimeBoundMacroCache {
-    bool IsBuilt = false;
-    SmallVector<const IdentifierInfo *> Candidates;
+    bool getIsBuilt() const { return Candidates.getFlag(0); }
+    void setIsBuilt(bool Value) { Candidates.setFlag(0, Value); }
+    llvm::SmallVectorWithFlags<const IdentifierInfo *> Candidates;
   };
 
   void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &Cache,
                                     ArrayRef<TokenValue> Tokens) {
-    if (Cache.IsBuilt)
+    if (Cache.getIsBuilt())
       return;
 
     const Preprocessor &PP = S.getPreprocessor();
@@ -552,7 +554,7 @@ class LifetimeSafetySemaHelperImpl : public LifetimeSafetySemaHelper {
         }
       }
     }
-    Cache.IsBuilt = true;
+    Cache.setIsBuilt(true);
   }
 
   StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index bc8a30d4e9dad..9b24f8c513c9b 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4811,7 +4811,7 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
 
 void TypoCorrectionConsumer::addNamespaces(
     const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces) {
-  SearchNamespaces = true;
+  setSearchNamespaces(true);
 
   for (auto KNPair : KnownNamespaces)
     Namespaces.addNameSpecifier(KNPair.first);
@@ -4873,7 +4873,7 @@ bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) {
   CXXScopeSpec *TempSS = SS.get();
 retry_lookup:
   LookupPotentialTypoResult(SemaRef, Result, Name, S, TempSS, TempMemberContext,
-                            EnteringContext,
+                            getEnteringContext(),
                             CorrectionValidator->IsObjCIvarLookup,
                             Name == Typo && !Candidate.WillReplaceSpecifier());
   switch (Result.getResultKind()) {
@@ -4892,7 +4892,7 @@ bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) {
       TempMemberContext = nullptr;
       goto retry_lookup;
     }
-    if (SearchNamespaces)
+    if (getSearchNamespaces())
       QualifiedResults.push_back(Candidate);
     break;
 
@@ -4907,7 +4907,7 @@ bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) {
       Candidate.addCorrectionDecl(TRD);
     checkCorrectionVisibility(SemaRef, Candidate);
     if (!isCandidateViable(*CorrectionValidator, Candidate)) {
-      if (SearchNamespaces)
+      if (getSearchNamespaces())
         QualifiedResults.push_back(Candidate);
       break;
     }
@@ -5321,7 +5321,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
     const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
 
   if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking ||
-      DisableTypoCorrection)
+      getDisableTypoCorrection())
     return nullptr;
 
   // In Microsoft mode, don't perform typo correction in a template member
@@ -5444,9 +5444,9 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
   // to search those namespaces.
   if (SearchNamespaces) {
     // Load any externally-known namespaces.
-    if (ExternalSource && !LoadedExternalKnownNamespaces) {
+    if (ExternalSource && !getLoadedExternalKnownNamespaces()) {
       SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;
-      LoadedExternalKnownNamespaces = true;
+      setLoadedExternalKnownNamespaces(true);
       ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces);
       for (auto *N : ExternalKnownNamespaces)
         KnownNamespaces[N] = true;
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 7dbb38bbe078e..e2266bad6da22 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -52,7 +52,7 @@ static void checkModuleImportContext(Sema &S, Module *M,
     S.Diag(cast<Decl>(DC)->getBeginLoc(),
            diag::note_module_import_not_at_top_level)
         << DC;
-  } else if (!M->IsExternC && ExternCLoc.isValid()) {
+  } else if (!M->getIsExternC() && ExternCLoc.isValid()) {
     S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
       << M->getFullModuleName();
     S.Diag(ExternCLoc, diag::note_extern_c_begins_here);
@@ -481,7 +481,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
   // implementation unit importing its interface).  Make this module visible
   // and return the import decl to be added to the current TU.
   if (Interface) {
-    HadImportedNamedModules = true;
+    setHadImportedNamedModules(true);
 
     makeTransitiveImportsVisible(getASTContext(), VisibleModules, Interface,
                                  Mod, ModuleLoc,
@@ -726,7 +726,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
       getCurrentModule()->Imports.push_back(Mod);
   }
 
-  HadImportedNamedModules = true;
+  setHadImportedNamedModules(true);
 
   return Import;
 }
@@ -1617,7 +1617,7 @@ void Sema::checkReferenceToTULocalFromOtherTU(
     FunctionDecl *FD, SourceLocation PointOfInstantiation) {
   // Checking if a declaration have any reference to TU-local entities in other
   // TU is expensive. Try to avoid it as much as possible.
-  if (!FD || !HadImportedNamedModules)
+  if (!FD || !getHadImportedNamedModules())
     return;
 
   PendingCheckReferenceForTULocal.push_back(
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a3be416d2da24..bbbeeb66beaf4 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/Sema/SemaOpenMP.h"
 #include "clang/AST/ASTConsumer.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "TreeTransform.h"
 #include "clang/AST/ASTContext.h"
@@ -202,15 +203,42 @@ class DSAStackTy {
     /// 'ordered' clause, the second one is true if the regions has 'ordered'
     /// clause, false otherwise.
     std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
-    bool RegionHasOrderConcurrent = false;
+    bool getRegionHasOrderConcurrent() const {
+      return IteratorVarDecls.getFlag(0);
+    }
+    void setRegionHasOrderConcurrent(bool Value) {
+      IteratorVarDecls.setFlag(0, Value);
+    }
     unsigned AssociatedLoops = 1;
-    bool HasMutipleLoops = false;
+    bool getHasMutipleLoops() const { return IteratorVarDecls.getFlag(1); }
+    bool setHasMutipleLoops(bool Value) {
+      IteratorVarDecls.setFlag(1, Value);
+      return Value;
+    }
     const Decl *PossiblyLoopCounter = nullptr;
-    bool NowaitRegion = false;
-    bool UntiedRegion = false;
-    bool CancelRegion = false;
-    bool LoopStart = false;
-    bool BodyComplete = false;
+    bool getNowaitRegion() const { return IteratorVarDecls.getFlag(2); }
+    void setNowaitRegion(bool Value) { IteratorVarDecls.setFlag(2, Value); }
+    bool getUntiedRegion() const { return IteratorVarDecls.getFlag(3); }
+    void setUntiedRegion(bool Value) { IteratorVarDecls.setFlag(3, Value); }
+    bool getCancelRegion() const {
+      return ImplicitDefaultFirstprivateFDs.getFlag(0);
+    }
+    bool setCancelRegion(bool Value) {
+      ImplicitDefaultFirstprivateFDs.setFlag(0, Value);
+      return Value;
+    }
+    bool getLoopStart() const {
+      return ImplicitDefaultFirstprivateFDs.getFlag(1);
+    }
+    void setLoopStart(bool Value) {
+      ImplicitDefaultFirstprivateFDs.setFlag(1, Value);
+    }
+    bool getBodyComplete() const {
+      return ImplicitDefaultFirstprivateFDs.getFlag(2);
+    }
+    void setBodyComplete(bool Value) {
+      ImplicitDefaultFirstprivateFDs.setFlag(2, Value);
+    }
     SourceLocation PrevScanLocation;
     SourceLocation PrevOrderedLocation;
     SourceLocation InnerTeamsRegionLoc;
@@ -240,10 +268,10 @@ class DSAStackTy {
           : FD(FD), StackLevel(StackLevel), VD(VD) {}
     };
     /// List of captured fields
-    llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
+    llvm::SmallVectorWithFlags<ImplicitDefaultFDInfoTy, 8, 3>
         ImplicitDefaultFirstprivateFDs;
     Expr *DeclareMapperVar = nullptr;
-    SmallVector<VarDecl *, 16> IteratorVarDecls;
+    llvm::SmallVectorWithFlags<VarDecl *, 16, 4> IteratorVarDecls;
     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
                  Scope *CurScope, SourceLocation Loc)
         : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -262,10 +290,16 @@ class DSAStackTy {
   /// from current directive.
   OpenMPClauseKind ClauseKindMode = OMPC_unknown;
   Sema &SemaRef;
-  bool ForceCapturing = false;
+  bool getForceCapturing() const { return ConstructTraits.getFlag(0); }
+  void setForceCapturing(bool Value) { ConstructTraits.setFlag(0, Value); }
   /// true if all the variables in the target executable directives must be
   /// captured by reference.
-  bool ForceCaptureByReferenceInTargetExecutable = false;
+  bool getForceCaptureByReferenceInTargetExecutableFlag() const {
+    return ConstructTraits.getFlag(1);
+  }
+  void setForceCaptureByReferenceInTargetExecutableFlag(bool Value) {
+    ConstructTraits.setFlag(1, Value);
+  }
   CriticalsWithHintsTy Criticals;
   unsigned IgnoredStackElements = 0;
 
@@ -363,7 +397,7 @@ class DSAStackTy {
   SmallVector<SourceLocation, 2> TargetLocations;
   SourceLocation AtomicLocation;
   /// Vector of declare variant construct traits.
-  SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
+  llvm::SmallVectorWithFlags<llvm::omp::TraitProperty, 8, 2> ConstructTraits;
 
 public:
   explicit DSAStackTy(Sema &S) : SemaRef(S) {}
@@ -404,18 +438,18 @@ class DSAStackTy {
 
   bool isBodyComplete() const {
     const SharingMapTy *Top = getTopOfStackOrNull();
-    return Top && Top->BodyComplete;
+    return Top && Top->getBodyComplete();
   }
-  void setBodyComplete() { getTopOfStack().BodyComplete = true; }
+  void setBodyComplete() { getTopOfStack().setBodyComplete(true); }
 
-  bool isForceVarCapturing() const { return ForceCapturing; }
-  void setForceVarCapturing(bool V) { ForceCapturing = V; }
+  bool isForceVarCapturing() const { return getForceCapturing(); }
+  void setForceVarCapturing(bool V) { setForceCapturing(V); }
 
   void setForceCaptureByReferenceInTargetExecutable(bool V) {
-    ForceCaptureByReferenceInTargetExecutable = V;
+    setForceCaptureByReferenceInTargetExecutableFlag(V);
   }
   bool isForceCaptureByReferenceInTargetExecutable() const {
-    return ForceCaptureByReferenceInTargetExecutable;
+    return getForceCaptureByReferenceInTargetExecutableFlag();
   }
 
   void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
@@ -468,19 +502,19 @@ class DSAStackTy {
   void loopInit() {
     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
            "Expected loop-based directive.");
-    getTopOfStack().LoopStart = true;
+    getTopOfStack().setLoopStart(true);
   }
   /// Start capturing of the variables in the loop context.
   void loopStart() {
     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
            "Expected loop-based directive.");
-    getTopOfStack().LoopStart = false;
+    getTopOfStack().setLoopStart(false);
   }
   /// true, if variables are captured, false otherwise.
   bool isLoopStarted() const {
     assert(isOpenMPLoopDirective(getCurrentDirective()) &&
            "Expected loop-based directive.");
-    return !getTopOfStack().LoopStart;
+    return !getTopOfStack().getLoopStart();
   }
   /// Marks (or clears) declaration as possibly loop counter.
   void resetPossibleLoopCounter(const Decl *D = nullptr) {
@@ -925,44 +959,53 @@ class DSAStackTy {
   }
   /// Marks current region as having an 'order' clause.
   void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
-    getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
+    [&] {
+      auto PackedFlagValue = HasOrderConcurrent;
+      return getTopOfStack().setRegionHasOrderConcurrent(PackedFlagValue);
+    }();
   }
   /// Returns true, if parent region is order (has associated
   /// 'order' clause), false - otherwise.
   bool isParentOrderConcurrent() const {
     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
-      return Parent->RegionHasOrderConcurrent;
+      return Parent->getRegionHasOrderConcurrent();
     return false;
   }
   /// Marks current region as nowait (it has a 'nowait' clause).
   void setNowaitRegion(bool IsNowait = true) {
-    getTopOfStack().NowaitRegion = IsNowait;
+    [&] {
+      auto PackedFlagValue = IsNowait;
+      return getTopOfStack().setNowaitRegion(PackedFlagValue);
+    }();
   }
   /// Returns true, if parent region is nowait (has associated
   /// 'nowait' clause), false - otherwise.
   bool isParentNowaitRegion() const {
     if (const SharingMapTy *Parent = getSecondOnStackOrNull())
-      return Parent->NowaitRegion;
+      return Parent->getNowaitRegion();
     return false;
   }
   /// Marks current region as untied (it has a 'untied' clause).
   void setUntiedRegion(bool IsUntied = true) {
-    getTopOfStack().UntiedRegion = IsUntied;
+    [&] {
+      auto PackedFlagValue = IsUntied;
+      return getTopOfStack().setUntiedRegion(PackedFlagValue);
+    }();
   }
   /// Return true if current region is untied.
   bool isUntiedRegion() const {
     const SharingMapTy *Top = getTopOfStackOrNull();
-    return Top ? Top->UntiedRegion : false;
+    return Top ? Top->getUntiedRegion() : false;
   }
   /// Marks parent region as cancel region.
   void setParentCancelRegion(bool Cancel = true) {
     if (SharingMapTy *Parent = getSecondOnStackOrNull())
-      Parent->CancelRegion |= Cancel;
+      Parent->setCancelRegion(Parent->getCancelRegion() | (Cancel));
   }
   /// Return true if current region has inner cancel construct.
   bool isCancelRegion() const {
     const SharingMapTy *Top = getTopOfStackOrNull();
-    return Top ? Top->CancelRegion : false;
+    return Top ? Top->getCancelRegion() : false;
   }
 
   /// Mark that parent region already has scan directive.
@@ -1000,7 +1043,7 @@ class DSAStackTy {
   void setAssociatedLoops(unsigned Val) {
     getTopOfStack().AssociatedLoops = Val;
     if (Val > 1)
-      getTopOfStack().HasMutipleLoops = true;
+      getTopOfStack().setHasMutipleLoops(true);
   }
   /// Return collapse value for region.
   unsigned getAssociatedLoops() const {
@@ -1010,7 +1053,7 @@ class DSAStackTy {
   /// Returns true if the construct is associated with multiple loops.
   bool hasMutipleLoops() const {
     const SharingMapTy *Top = getTopOfStackOrNull();
-    return Top ? Top->HasMutipleLoops : false;
+    return Top ? Top->getHasMutipleLoops() : false;
   }
 
   /// Marks current target region as one with closely nested teams
@@ -8231,7 +8274,7 @@ static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info) {
   for (const OMPInteropPref &P : Info.Prefs) {
     const Expr *E = P.Fr;
     if (!E) {
-      assert(Info.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
+      assert(Info.hasPreferAttrs() && "null Fr requires OMP 6.0 syntax");
     } else if (!isDependent(E)) {
       if (!E->isIntegerConstantExpr(S.getASTContext()) &&
           !isa<StringLiteral>(E)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 2ca12f7a172e7..c4da77e1652e6 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -44,6 +44,7 @@
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
@@ -7587,7 +7588,7 @@ void Sema::AddOverloadCandidate(
     ConstraintSatisfaction Satisfaction;
     if (CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
-        !Satisfaction.IsSatisfied) {
+        !Satisfaction.isSatisfied()) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
       return;
@@ -8153,7 +8154,7 @@ void Sema::AddMethodCandidate(
     ConstraintSatisfaction Satisfaction;
     if (CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
-        !Satisfaction.IsSatisfied) {
+        !Satisfaction.isSatisfied()) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
       return;
@@ -8700,7 +8701,7 @@ void Sema::AddConversionCandidate(
   if (Conversion->getTrailingRequiresClause()) {
     ConstraintSatisfaction Satisfaction;
     if (CheckFunctionConstraints(Conversion, Satisfaction) ||
-        !Satisfaction.IsSatisfied) {
+        !Satisfaction.isSatisfied()) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
       return;
@@ -8995,7 +8996,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
     ConstraintSatisfaction Satisfaction;
     if (CheckFunctionConstraints(Conversion, Satisfaction, /*Loc*/ {},
                                  /*ForOverloadResolution*/ true) ||
-        !Satisfaction.IsSatisfied) {
+        !Satisfaction.isSatisfied()) {
       Candidate.Viable = false;
       Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
       return;
@@ -9609,12 +9610,17 @@ class BuiltinOperatorOverloadBuilder {
   // Whether a candidate whose parameters are all arithmetic, vector or matrix
   // types can be viable. It is viable if there is an arithmetic or enumeral
   // candidate type, and every argument might convert to such a type.
-  bool ArithmeticCandidatesMayBeViable;
+  bool getArithmeticCandidatesMayBeViable() const {
+    return ArithmeticTypes.getFlag(0);
+  }
+  void setArithmeticCandidatesMayBeViable(bool Value) {
+    ArithmeticTypes.setFlag(0, Value);
+  }
   SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
   OverloadCandidateSet &CandidateSet;
 
   static constexpr int ArithmeticTypesCap = 26;
-  SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
+  llvm::SmallVectorWithFlags<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
 
   // Define some indices used to iterate over the arithmetic types in
   // ArithmeticTypes.  The "promoted arithmetic types" are the arithmetic
@@ -9755,13 +9761,13 @@ class BuiltinOperatorOverloadBuilder {
       OverloadCandidateSet &CandidateSet)
       : S(S), Args(Args),
         VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
-        ArithmeticCandidatesMayBeViable(
-            HasArithmeticOrEnumeralCandidateType &&
-            llvm::all_of(CandidateTypes,
-                         [](const BuiltinCandidateTypeSet &Types) {
-                           return Types.mayConvertToArithmetic();
-                         })),
-        CandidateTypes(CandidateTypes), CandidateSet(CandidateSet) {
+        CandidateTypes(CandidateTypes), CandidateSet(CandidateSet),
+        ArithmeticTypes(decltype(this->ArithmeticTypes)::withFlags(unsigned(
+            bool(HasArithmeticOrEnumeralCandidateType &&
+                 llvm::all_of(CandidateTypes,
+                              [](const BuiltinCandidateTypeSet &Types) {
+                                return Types.mayConvertToArithmetic();
+                              }))))) {
     InitArithmeticTypes();
   }
 
@@ -9785,7 +9791,7 @@ class BuiltinOperatorOverloadBuilder {
   //       VQ T&      operator--(VQ T&);
   //       T          operator--(VQ T&, int);
   void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) {
@@ -9859,7 +9865,7 @@ class BuiltinOperatorOverloadBuilder {
   //       T         operator+(T);
   //       T         operator-(T);
   void addUnaryPlusOrMinusArithmeticOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Arith = FirstPromotedArithmeticType;
@@ -9889,7 +9895,7 @@ class BuiltinOperatorOverloadBuilder {
   //
   //        T         operator~(T);
   void addUnaryTildePromotedIntegralOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Int = FirstPromotedIntegralType;
@@ -10112,7 +10118,7 @@ class BuiltinOperatorOverloadBuilder {
   //   between types L and R.
   // Our candidates ignore the first parameter.
   void addGenericBinaryArithmeticOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Left = FirstPromotedArithmeticType;
@@ -10140,7 +10146,7 @@ class BuiltinOperatorOverloadBuilder {
   ///  * (M2.getElementType(), M2) -> M2
   ///  * (M2, M2) -> M2 // Only if M2 is not part of CandidateTypes[0].
   void addMatrixBinaryArithmeticOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (QualType M1 : CandidateTypes[0].matrix_types()) {
@@ -10205,7 +10211,7 @@ class BuiltinOperatorOverloadBuilder {
   //   where LR is the result of the usual arithmetic conversions
   //   between types L and R.
   void addBinaryBitwiseArithmeticOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Left = FirstPromotedIntegralType;
@@ -10370,7 +10376,7 @@ class BuiltinOperatorOverloadBuilder {
   //        VQ L&      operator+=(VQ L&, R);
   //        VQ L&      operator-=(VQ L&, R);
   void addAssignmentArithmeticOverloads(bool isEqualOp) {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
@@ -10424,7 +10430,7 @@ class BuiltinOperatorOverloadBuilder {
   //        VQ L&       operator^=(VQ L&, R);
   //        VQ L&       operator|=(VQ L&, R);
   void addAssignmentIntegralOverloads() {
-    if (!ArithmeticCandidatesMayBeViable)
+    if (!getArithmeticCandidatesMayBeViable())
       return;
 
     for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
@@ -11530,7 +11536,7 @@ bool OverloadCandidate::NotValidBecauseConstraintExprHasError() const {
          static_cast<TemplateDeductionResult>(DeductionFailure.Result) ==
              TemplateDeductionResult::ConstraintsNotSatisfied &&
          static_cast<CNSInfo *>(DeductionFailure.Data)
-             ->Satisfaction.ContainsErrors;
+             ->Satisfaction.containsErrors();
 }
 
 void OverloadCandidateSet::AddDeferredTemplateCandidate(
@@ -11950,7 +11956,7 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
     ConstraintSatisfaction Satisfaction;
     if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
       return false;
-    if (!Satisfaction.IsSatisfied) {
+    if (!Satisfaction.isSatisfied()) {
       if (Complain) {
         if (InOverloadResolution) {
           SmallString<128> TemplateArgString;
@@ -13803,7 +13809,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
 
     assert(Cand->Specialization &&
            "Non-matching built-in candidates are not added to Cands.");
-    Cand->NoteDeductionFailure(S, ForTakingAddress, CandidateSetKind);
+    Cand->NoteDeductionFailure(S, getForTakingAddress(), CandidateSetKind);
   }
 
   if (I != E)
@@ -13856,7 +13862,8 @@ class AddressOfFunctionResolver {
   const QualType& TargetType;
   QualType TargetFunctionType; // Extracted function type from target type
 
-  bool Complain;
+  bool getComplain() const { return Matches.getFlag(0); }
+  void setComplain(bool Value) { Matches.setFlag(0, Value); }
   //DeclAccessPair& ResultFunctionAccessPair;
   ASTContext& Context;
 
@@ -13868,21 +13875,22 @@ class AddressOfFunctionResolver {
   OverloadExpr::FindResult OvlExprInfo;
   OverloadExpr *OvlExpr;
   TemplateArgumentListInfo OvlExplicitTemplateArgs;
-  SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+  llvm::SmallVectorWithFlags<std::pair<DeclAccessPair, FunctionDecl *>, 4>
+      Matches;
   TemplateSpecCandidateSet FailedCandidates;
 
 public:
   AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
                             const QualType &TargetType, bool Complain)
       : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
-        Complain(Complain), Context(S.getASTContext()),
+        Context(S.getASTContext()),
         TargetTypeIsNonStaticMemberFunction(
             !!TargetType->getAs<MemberPointerType>()),
         FoundNonTemplateFunction(false),
-        StaticMemberFunctionFromBoundPointer(false),
-        HasComplained(false),
+        StaticMemberFunctionFromBoundPointer(false), HasComplained(false),
         OvlExprInfo(OverloadExpr::find(SourceExpr)),
         OvlExpr(OvlExprInfo.Expression),
+        Matches(decltype(this->Matches)::withFlags(unsigned(Complain))),
         FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
     ExtractUnqualifiedFunctionTypeFromTargetType();
 
@@ -14069,8 +14077,8 @@ class AddressOfFunctionResolver {
       // If any candidate has a placeholder return type, trigger its deduction
       // now.
       if (completeFunctionType(S, FunDecl, SourceExpr->getBeginLoc(),
-                               Complain)) {
-        HasComplained |= Complain;
+                               getComplain())) {
+        HasComplained |= getComplain();
         return false;
       }
 
@@ -14149,7 +14157,7 @@ class AddressOfFunctionResolver {
             << Matches[0].second->getDeclName(),
         S.PDiag(diag::note_ovl_candidate)
             << (unsigned)oc_function << (unsigned)ocs_described_template,
-        Complain, TargetFunctionType);
+        getComplain(), TargetFunctionType);
 
     if (Result != MatchesCopy.end()) {
       // Make it the first and only element
@@ -14157,7 +14165,7 @@ class AddressOfFunctionResolver {
       Matches[0].second = cast<FunctionDecl>(*Result);
       Matches.resize(1);
     } else
-      HasComplained |= Complain;
+      HasComplained |= getComplain();
   }
 
   void EliminateAllTemplateMatches() {
@@ -14197,12 +14205,18 @@ class AddressOfFunctionResolver {
         Results.push_back(Matches[I]);
       }
     }
-    std::swap(Matches, Results);
+    SmallVector<std::pair<DeclAccessPair, FunctionDecl *>, 4> PreviousMatches;
+    PreviousMatches = std::move(Matches);
+    Matches.assign(std::move(Results));
+    Results = std::move(PreviousMatches);
   }
 
   void EliminateSuboptimalCudaMatches() {
+    SmallVector<std::pair<DeclAccessPair, FunctionDecl *>, 4> CudaMatches;
+    CudaMatches = std::move(Matches);
     S.CUDA().EraseUnwantedMatches(S.getCurFunctionDecl(/*AllowLambda=*/true),
-                                  Matches);
+                                  CudaMatches);
+    Matches.assign(std::move(CudaMatches));
   }
 
 public:
@@ -14868,11 +14882,11 @@ class BuildRecoveryCallExprRAII {
 
 public:
   BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S), SatStack(S) {
-    assert(SemaRef.IsBuildingRecoveryCallExpr == false);
-    SemaRef.IsBuildingRecoveryCallExpr = true;
+    assert(SemaRef.getIsBuildingRecoveryCallExpr() == false);
+    SemaRef.setIsBuildingRecoveryCallExpr(true);
   }
 
-  ~BuildRecoveryCallExprRAII() { SemaRef.IsBuildingRecoveryCallExpr = false; }
+  ~BuildRecoveryCallExprRAII() { SemaRef.setIsBuildingRecoveryCallExpr(false); }
 };
 }
 
@@ -14894,7 +14908,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
   //
   // template <typename T> auto foo(T t) -> decltype(foo(t)) {}
   // template <typename T> auto foo(T t) -> decltype(foo(&t)) {}
-  if (SemaRef.IsBuildingRecoveryCallExpr)
+  if (SemaRef.getIsBuildingRecoveryCallExpr())
     return ExprResult();
   BuildRecoveryCallExprRAII RCE(SemaRef);
 
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index 66736670984ef..0d2a1ac19614b 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -37,6 +37,7 @@
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaObjC.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 using namespace clang;
 using namespace sema;
@@ -186,12 +187,13 @@ namespace {
     Sema &S;
     unsigned ResultIndex;
     SourceLocation GenericLoc;
-    bool IsUnique;
-    SmallVector<Expr *, 4> Semantics;
+    bool getIsUnique() const { return Semantics.getFlag(0); }
+    void setIsUnique(bool Value) { Semantics.setFlag(0, Value); }
+    llvm::SmallVectorWithFlags<Expr *, 4> Semantics;
 
     PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
-      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
-        GenericLoc(genericLoc), IsUnique(IsUnique) {}
+        : S(S), ResultIndex(PseudoObjectExpr::NoResult), GenericLoc(genericLoc),
+          Semantics(decltype(Semantics)::withFlags(unsigned(IsUnique))) {}
 
     virtual ~PseudoOpBuilder() {}
 
@@ -367,7 +369,7 @@ OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
     new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
                                     e->getValueKind(), e->getObjectKind(),
                                     e);
-  if (IsUnique)
+  if (getIsUnique())
     captured->setIsUnique(true);
 
   // Make sure we bind that in the semantics.
diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp
index e180b3655bd73..1d40a4bddf348 100644
--- a/clang/lib/Sema/SemaSYCL.cpp
+++ b/clang/lib/Sema/SemaSYCL.cpp
@@ -19,6 +19,7 @@
 #include "clang/Sema/Attr.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 using namespace clang;
 
@@ -668,11 +669,12 @@ OutlinedFunctionDecl *BuildSYCLKernelEntryPointOutline(Sema &SemaRef,
 
 class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
   SemaSYCL &SemaSYCLRef;
-  bool IsValid = true;
+  bool getIsValid() const { return !ObjectAccessPath.getFlag(0); }
+  void setIsValid(bool Value) { ObjectAccessPath.setFlag(0, !Value); }
   using ObjectAccess =
       llvm::PointerUnion<const ParmVarDecl *, const CXXBaseSpecifier *,
                          const FieldDecl *>;
-  SmallVector<ObjectAccess, 4> ObjectAccessPath;
+  llvm::SmallVectorWithFlags<ObjectAccess, 4> ObjectAccessPath;
 
   void emitObjectAccessPathNotes() {
     for (auto Parent : llvm::reverse(ObjectAccessPath)) {
@@ -748,7 +750,7 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
       // kernel parameter types contained within the referenced type
       // might not be relevant once the programmer addresses the
       // invalid use of a reference.
-      IsValid = false;
+      setIsValid(false);
       return false;
     }
     return true;
@@ -759,7 +761,7 @@ class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
     ObjectAccessPath.pop_back();
   }
 
-  bool isInvalid() { return !IsValid; }
+  bool isInvalid() { return !getIsValid(); }
 };
 
 bool verifyKernelParams(FunctionDecl *FD, SemaSYCL &SemaSYCLRef) {
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index a3e3e403188c7..4a7ac65930e03 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3725,7 +3725,7 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
       CurLambda && hasDeducedReturnType(CurLambda->CallOperator);
 
   if (ExprEvalContexts.back().isDiscardedStatementContext() &&
-      (HasDeducedReturnType || CurCap->HasImplicitReturnType)) {
+      (HasDeducedReturnType || CurCap->getHasImplicitReturnType())) {
     if (RetValExp) {
       ExprResult ER =
           ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false);
@@ -3757,7 +3757,7 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
       return StmtError();
     }
     CurCap->ReturnType = FnRetType = FD->getReturnType();
-  } else if (CurCap->HasImplicitReturnType) {
+  } else if (CurCap->getHasImplicitReturnType()) {
     // For blocks/lambdas with implicit return types, we check each return
     // statement individually, and deduce the common return type when the block
     // or lambda is completed.
@@ -3874,14 +3874,14 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
   // If we need to check for the named return value optimization,
   // or if we need to infer the return type,
   // save the return statement in our scope for later processing.
-  if (CurCap->HasImplicitReturnType || NRVOCandidate)
+  if (CurCap->getHasImplicitReturnType() || NRVOCandidate)
     FunctionScopes.back()->Returns.push_back(Result);
 
   if (FunctionScopes.back()->FirstReturnLoc.isInvalid())
     FunctionScopes.back()->FirstReturnLoc = ReturnLoc;
 
   if (auto *CurBlock = dyn_cast<BlockScopeInfo>(CurCap);
-      CurBlock && CurCap->HasImplicitReturnType && RetValExp &&
+      CurBlock && CurCap->getHasImplicitReturnType() && RetValExp &&
       RetValExp->containsErrors())
     CurBlock->TheDecl->setInvalidDecl();
 
@@ -4003,7 +4003,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
       //  each return statement. [...] if the type deduced is not the same in
       //  each deduction, the program is ill-formed.
       const LambdaScopeInfo *LambdaSI = getCurLambda();
-      if (LambdaSI && LambdaSI->HasImplicitReturnType)
+      if (LambdaSI && LambdaSI->getHasImplicitReturnType())
         Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)
             << Info.SecondArg << Info.FirstArg << true /*IsLambda*/;
       else
@@ -4889,7 +4889,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
 
   PushExpressionEvaluationContext(
       ExpressionEvaluationContext::PotentiallyEvaluated);
-  ExprEvalContexts.back().InImmediateEscalatingFunctionContext = false;
+  ExprEvalContexts.back().setInImmediateEscalatingFunctionContext(false);
 }
 
 void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5a61cb852d15e..b0fe4a55901be 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -42,10 +42,12 @@
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include <memory>
 
 #include <optional>
 using namespace clang;
@@ -4023,7 +4025,7 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
           ClassTemplate->getDeclContext(),
           ClassTemplate->getTemplatedDecl()->getBeginLoc(),
           ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted,
-          CTAI.StrictPackMatch, nullptr);
+          CTAI.getStrictPackMatch(), nullptr);
       ClassTemplate->AddSpecialization(Decl, InsertToken);
       if (ClassTemplate->isOutOfLine())
         Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
@@ -4973,7 +4975,7 @@ ExprResult Sema::CheckConceptTemplateId(
         SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
                     TemplateArgs->getRAngleLoc()),
         Satisfaction, CL);
-    Satisfaction.ContainsErrors = Error;
+    Satisfaction.setContainsErrors(Error);
   }
 
   if (Error)
@@ -5214,10 +5216,11 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
   return TNK_Non_template;
 }
 
-bool Sema::CheckTemplateTypeArgument(
-    TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL,
-    SmallVectorImpl<TemplateArgument> &SugaredConverted,
-    SmallVectorImpl<TemplateArgument> &CanonicalConverted) {
+bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+                                     TemplateArgumentLoc &AL,
+                                     CheckTemplateArgumentInfo &CTAI) {
+  auto &SugaredConverted = CTAI.SugaredConverted;
+  auto &CanonicalConverted = CTAI.CanonicalConverted;
   const TemplateArgument &Arg = AL.getArgument();
   QualType ArgType;
   TypeSourceInfo *TSI = nullptr;
@@ -5594,8 +5597,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
                                  CheckTemplateArgumentKind CTAK) {
   // Check template type parameters.
   if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
-    return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI.SugaredConverted,
-                                     CTAI.CanonicalConverted);
+    return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI);
 
   const TemplateArgument &Arg = ArgLoc.getArgument();
   // Check non-type template parameters.
@@ -5619,7 +5621,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
       return AT && AT->isDecltypeAuto() == DecltypeAuto &&
              AT->getDeducedType().isNull();
     };
-    if (CTAI.PartialOrdering &&
+    if (CTAI.getPartialOrdering() &&
         isUndeducedAuto(NTTPType, /*DecltypeAuto=*/false) &&
         isUndeducedAuto(getTypeOfConstantTemplateParameter(Arg),
                         /*DecltypeAuto=*/true))
@@ -5659,7 +5661,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
       TemplateArgument SugaredResult, CanonicalResult;
       ExprResult Res = CheckTemplateArgument(
           NTTP, NTTPType, E, SugaredResult, CanonicalResult,
-          /*StrictCheck=*/CTAI.MatchingTTP || CTAI.PartialOrdering, CTAK);
+          /*StrictCheck=*/CTAI.getMatchingTTP() || CTAI.getPartialOrdering(),
+          CTAK);
       // If the current template argument causes an error, give up now.
       if (Res.isInvalid())
         return nullptr;
@@ -5740,7 +5743,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
         TemplateArgument SugaredResult, CanonicalResult;
         E = CheckTemplateArgument(
             NTTP, NTTPType, E.get(), SugaredResult, CanonicalResult,
-            /*StrictCheck=*/CTAI.PartialOrdering, CTAK_Specified);
+            /*StrictCheck=*/CTAI.getPartialOrdering(), CTAK_Specified);
         if (E.isInvalid())
           return true;
 
@@ -5833,16 +5836,19 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
     llvm_unreachable("Should never see a NULL template argument here");
 
   case TemplateArgument::Template:
-  case TemplateArgument::TemplateExpansion:
-    if (CheckTemplateTemplateArgument(TempParm, Params, ArgLoc,
-                                      CTAI.PartialOrdering,
-                                      &CTAI.StrictPackMatch))
+  case TemplateArgument::TemplateExpansion: {
+    bool StrictPackMatch = CTAI.getStrictPackMatch();
+    bool InvalidArgument = CheckTemplateTemplateArgument(
+        TempParm, Params, ArgLoc, CTAI.getPartialOrdering(), &StrictPackMatch);
+    CTAI.setStrictPackMatch(StrictPackMatch);
+    if (InvalidArgument)
       return true;
 
     CTAI.SugaredConverted.push_back(Arg);
     CTAI.CanonicalConverted.push_back(
         Context.getCanonicalTemplateArgument(Arg));
     break;
+  }
 
   case TemplateArgument::Expression:
   case TemplateArgument::Type: {
@@ -6033,7 +6039,7 @@ bool Sema::CheckTemplateArgumentList(
           !(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param);
       bool ArgIsExpansion = ArgLoc.getArgument().isPackExpansion();
 
-      if (ArgIsExpansion && CTAI.MatchingTTP) {
+      if (ArgIsExpansion && CTAI.getMatchingTTP()) {
         SmallVector<TemplateArgument, 4> Args(ParamEnd - Param);
         for (TemplateParameterList::iterator First = Param; Param != ParamEnd;
              ++Param) {
@@ -6043,8 +6049,20 @@ bool Sema::CheckTemplateArgumentList(
               getExpandedPackSize(*Param))
             Arg = Arg.getPackExpansionPattern();
           TemplateArgumentLoc NewArgLoc(Arg, ArgLoc.getLocInfo());
-          SaveAndRestore _1(CTAI.PartialOrdering, false);
-          SaveAndRestore _2(CTAI.MatchingTTP, true);
+          auto _1 = [PackedFlagOwner = std::addressof(CTAI)] {
+            const bool PackedFlagOld = PackedFlagOwner->getPartialOrdering();
+            PackedFlagOwner->setPartialOrdering(false);
+            return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+              PackedFlagOwner->setPartialOrdering(PackedFlagOld);
+            });
+          }();
+          auto _2 = [PackedFlagOwner = std::addressof(CTAI)] {
+            const bool PackedFlagOld = PackedFlagOwner->getMatchingTTP();
+            PackedFlagOwner->setMatchingTTP(true);
+            return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+              PackedFlagOwner->setMatchingTTP(PackedFlagOld);
+            });
+          }();
           if (CheckTemplateArgument(*Param, NewArgLoc, Template, TemplateLoc,
                                     RAngleLoc, SugaredArgumentPack.size(), CTAI,
                                     CTAK_Specified))
@@ -6059,7 +6077,13 @@ bool Sema::CheckTemplateArgumentList(
             TemplateArgument::CreatePackCopy(Context, Args),
             TemplateArgumentLocInfo(Context, ArgLoc.getLocation()));
       } else {
-        SaveAndRestore _1(CTAI.PartialOrdering, false);
+        auto _1 = [PackedFlagOwner = std::addressof(CTAI)] {
+          const bool PackedFlagOld = PackedFlagOwner->getPartialOrdering();
+          PackedFlagOwner->setPartialOrdering(false);
+          return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+            PackedFlagOwner->setPartialOrdering(PackedFlagOld);
+          });
+        }();
         if (CheckTemplateArgument(*Param, ArgLoc, Template, TemplateLoc,
                                   RAngleLoc, SugaredArgumentPack.size(), CTAI,
                                   CTAK_Specified))
@@ -6089,7 +6113,7 @@ bool Sema::CheckTemplateArgumentList(
       // We're now done with this argument.
       ++ArgIdx;
 
-      if (ArgIsExpansion && (CTAI.MatchingTTP || NonPackParameter)) {
+      if (ArgIsExpansion && (CTAI.getMatchingTTP() || NonPackParameter)) {
         // Directly convert the remaining arguments, because we don't know what
         // parameters they'll match up with.
 
@@ -6206,9 +6230,27 @@ bool Sema::CheckTemplateArgumentList(
     if (Inst.isInvalid())
       return true;
 
-    SaveAndRestore _1(CTAI.PartialOrdering, false);
-    SaveAndRestore _2(CTAI.MatchingTTP, false);
-    SaveAndRestore _3(CTAI.StrictPackMatch, {});
+    auto _1 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getPartialOrdering();
+      PackedFlagOwner->setPartialOrdering(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setPartialOrdering(PackedFlagOld);
+      });
+    }();
+    auto _2 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getMatchingTTP();
+      PackedFlagOwner->setMatchingTTP(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setMatchingTTP(PackedFlagOld);
+      });
+    }();
+    auto _3 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getStrictPackMatch();
+      PackedFlagOwner->setStrictPackMatch(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setStrictPackMatch(PackedFlagOld);
+      });
+    }();
     // Check the default template argument.
     if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
                               CTAI, CTAK_Specified))
@@ -6232,7 +6274,7 @@ bool Sema::CheckTemplateArgumentList(
   // pack expansions; they might be empty. This can happen even if
   // PartialTemplateArgs is false (the list of arguments is complete but
   // still dependent).
-  if (CTAI.MatchingTTP ||
+  if (CTAI.getMatchingTTP() ||
       (CurrentInstantiationScope &&
        CurrentInstantiationScope->getPartiallySubstitutedPack())) {
     while (ArgIdx < NumArgs &&
@@ -9041,7 +9083,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
     // this explicit specialization or friend declaration.
     Specialization = ClassTemplateSpecializationDecl::Create(
         Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
-        ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
+        ClassTemplate, CTAI.CanonicalConverted, CTAI.getStrictPackMatch(),
+        PrevDecl);
     Specialization->setTemplateArgsAsWritten(TemplateArgs);
     SetNestedNameSpecifier(*this, Specialization, SS);
     if (TemplateParameterLists.size() > 0) {
@@ -9980,7 +10023,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
           (CheckFunctionConstraints(Method, Satisfaction,
                                     /*UsageLoc=*/Member->getLocation(),
                                     /*ForOverloadResolution=*/true) ||
-           !Satisfaction.IsSatisfied))
+           !Satisfaction.isSatisfied()))
         continue;
 
       Candidates.addDecl(Candidate);
@@ -10498,7 +10541,8 @@ DeclResult Sema::ActOnExplicitInstantiation(
     // this explicit specialization.
     Specialization = ClassTemplateSpecializationDecl::Create(
         Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
-        ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
+        ClassTemplate, CTAI.CanonicalConverted, CTAI.getStrictPackMatch(),
+        PrevDecl);
     SetNestedNameSpecifier(*this, Specialization, SS);
 
     // A MSInheritanceAttr attached to the previous declaration must be
@@ -10564,7 +10608,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
   if (!Def)
     InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK,
                                            /*Complain=*/true,
-                                           CTAI.StrictPackMatch);
+                                           CTAI.getStrictPackMatch());
   else if (TSK == TSK_ExplicitInstantiationDefinition) {
     MarkVTableUsed(TemplateNameLoc, Specialization, true);
     Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
@@ -11046,7 +11090,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
             if (Method->getTrailingRequiresClause() &&
                 (CheckFunctionConstraints(Method, S, D.getIdentifierLoc(),
                                           /*ForOverloadResolution=*/true) ||
-                 !S.IsSatisfied)) {
+                 !S.isSatisfied())) {
               C.Viable = false;
               C.FailureKind = ovl_fail_constraints_not_satisfied;
             }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 90724e1d01cb2..cae5be74468fe 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -48,15 +48,18 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include <algorithm>
 #include <cassert>
+#include <memory>
 #include <optional>
 #include <tuple>
 #include <type_traits>
@@ -870,8 +873,9 @@ class PackDeductionScope {
                      bool DeducePackIfNotAlreadyDeduced = false,
                      bool FinishingDeduction = false)
       : S(S), TemplateParams(TemplateParams), Deduced(Deduced), Info(Info),
-        DeducePackIfNotAlreadyDeduced(DeducePackIfNotAlreadyDeduced),
-        FinishingDeduction(FinishingDeduction) {
+        Packs(decltype(this->Packs)::withFlags(
+            (unsigned(DeducePackIfNotAlreadyDeduced) << 1) |
+            (unsigned(FinishingDeduction) << 3))) {
     unsigned NumNamedPacks = addPacks(Pattern);
     finishConstruction(NumNamedPacks);
   }
@@ -889,9 +893,9 @@ class PackDeductionScope {
   void addPack(unsigned Index) {
     // Save the deduced template argument for the parameter pack expanded
     // by this pack expansion, then clear out the deduction.
-    DeducedFromEarlierParameter = !Deduced[Index].isNull();
+    setDeducedFromEarlierParameter(!Deduced[Index].isNull());
     DeducedPack Pack(Index);
-    if (!FinishingDeduction) {
+    if (!getFinishingDeduction()) {
       Pack.Saved = Deduced[Index];
       Deduced[Index] = TemplateArgument();
     }
@@ -985,12 +989,12 @@ class PackDeductionScope {
     for (unsigned I = 0; I != NumNamedPacks; ++I) {
       if (Packs[I].Index >= Info.getNumExplicitArgs()) {
         IsExpanded = false;
-        IsPartiallyExpanded = false;
+        setIsPartiallyExpanded(false);
         break;
       }
       if (PartialPackDepthIndex ==
             std::make_pair(Info.getDeducedDepth(), Packs[I].Index)) {
-        IsPartiallyExpanded = true;
+        setIsPartiallyExpanded(true);
       }
     }
 
@@ -998,7 +1002,7 @@ class PackDeductionScope {
     // If we partially expanded, this is the number of partial arguments.
     // FIXME: `&& FixedNumExpansions` is a workaround for UB described in
     // https://github.com/llvm/llvm-project/issues/100095
-    if (IsPartiallyExpanded)
+    if (getIsPartiallyExpanded())
       PackElements += NumPartialPackArgs;
     else if (IsExpanded && FixedNumExpansions)
       PackElements += *FixedNumExpansions;
@@ -1037,12 +1041,12 @@ class PackDeductionScope {
   /// Determine whether this pack has already been deduced from a previous
   /// argument.
   bool isDeducedFromEarlierParameter() const {
-    return DeducedFromEarlierParameter;
+    return getDeducedFromEarlierParameter();
   }
 
   /// Determine whether this pack has already been partially expanded into a
   /// sequence of (prior) function parameters / template arguments.
-  bool isPartiallyExpanded() { return IsPartiallyExpanded; }
+  bool isPartiallyExpanded() { return getIsPartiallyExpanded(); }
 
   /// Determine whether this pack expansion scope has a known, fixed arity.
   /// This happens if it involves a pack from an outer template that has
@@ -1061,7 +1065,7 @@ class PackDeductionScope {
     // Capture the deduced template arguments for each parameter pack expanded
     // by this pack expansion, add them to the list of arguments we've deduced
     // for that pack, then clear out the deduced argument.
-    if (!FinishingDeduction) {
+    if (!getFinishingDeduction()) {
       for (auto &Pack : Packs) {
         DeducedTemplateArgument &DeducedArg = Deduced[Pack.Index];
         if (!Pack.New.empty() || !DeducedArg.isNull()) {
@@ -1084,13 +1088,13 @@ class PackDeductionScope {
   /// producing the argument packs and checking for consistency with prior
   /// deductions.
   TemplateDeductionResult finish() {
-    if (FinishingDeduction)
+    if (getFinishingDeduction())
       return TemplateDeductionResult::Success;
     // Build argument packs for each of the parameter packs expanded by this
     // pack expansion.
     for (auto &Pack : Packs) {
       // Put back the old value for this pack.
-      if (!FinishingDeduction)
+      if (!getFinishingDeduction())
         Deduced[Pack.Index] = Pack.Saved;
 
       // Always make sure the size of this pack is correct, even if we didn't
@@ -1144,7 +1148,7 @@ class PackDeductionScope {
       // Check the new pack matches any previous value.
       DeducedTemplateArgument OldPack = *Loc;
       DeducedTemplateArgument Result = checkDeducedTemplateArguments(
-          S.Context, OldPack, NewPack, DeducePackIfNotAlreadyDeduced);
+          S.Context, OldPack, NewPack, getDeducePackIfNotAlreadyDeduced());
 
       Info.AggregateDeductionCandidateHasMismatchedArity =
           OldPack.getKind() == TemplateArgument::Pack &&
@@ -1188,14 +1192,18 @@ class PackDeductionScope {
   SmallVectorImpl<DeducedTemplateArgument> &Deduced;
   TemplateDeductionInfo &Info;
   unsigned PackElements = 0;
-  bool IsPartiallyExpanded = false;
-  bool DeducePackIfNotAlreadyDeduced = false;
-  bool DeducedFromEarlierParameter = false;
-  bool FinishingDeduction = false;
+  bool getIsPartiallyExpanded() const { return Packs.getFlag(0); }
+  void setIsPartiallyExpanded(bool Value) { Packs.setFlag(0, Value); }
+  bool getDeducePackIfNotAlreadyDeduced() const { return Packs.getFlag(1); }
+  void setDeducePackIfNotAlreadyDeduced(bool Value) { Packs.setFlag(1, Value); }
+  bool getDeducedFromEarlierParameter() const { return Packs.getFlag(2); }
+  void setDeducedFromEarlierParameter(bool Value) { Packs.setFlag(2, Value); }
+  bool getFinishingDeduction() const { return Packs.getFlag(3); }
+  void setFinishingDeduction(bool Value) { Packs.setFlag(3, Value); }
   /// The number of expansions, if we have a fully-expanded pack in this scope.
   UnsignedOrNone FixedNumExpansions = std::nullopt;
 
-  SmallVector<DeducedPack, 2> Packs;
+  llvm::SmallVectorWithFlags<DeducedPack, 2, 4> Packs;
 };
 
 } // namespace
@@ -1496,8 +1504,13 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
   // We iterate over this later, so we have to use MapVector to ensure
   // determinism.
   struct MatchValue {
-    SmallVector<DeducedTemplateArgument, 8> Deduced;
-    bool HasDeducedAnyParam;
+    llvm::SmallVectorWithFlags<DeducedTemplateArgument, 8> Deduced;
+    bool getHasDeducedAnyParam() const { return Deduced.getFlag(0); }
+    void setHasDeducedAnyParam(bool Value) { Deduced.setFlag(0, Value); }
+
+    MatchValue(SmallVector<DeducedTemplateArgument, 8> Deduced,
+               bool HasDeducedAnyParam)
+        : Deduced(unsigned(HasDeducedAnyParam), std::move(Deduced)) {}
   };
   llvm::MapVector<const CXXRecordDecl *, MatchValue> Matches;
 
@@ -1563,8 +1576,11 @@ DeduceTemplateBases(Sema &S, const CXXRecordDecl *RD,
   if (Matches.size() > 1)
     return TemplateDeductionResult::MiscellaneousDeductionFailure;
 
-  std::swap(Matches.front().second.Deduced, Deduced);
-  if (bool HasDeducedAnyParamCopy = Matches.front().second.HasDeducedAnyParam;
+  Deduced.assign(
+      std::make_move_iterator(Matches.front().second.Deduced.begin()),
+      std::make_move_iterator(Matches.front().second.Deduced.end()));
+  if (bool HasDeducedAnyParamCopy =
+          Matches.front().second.getHasDeducedAnyParam();
       HasDeducedAnyParamCopy && HasDeducedAnyParam)
     *HasDeducedAnyParam = HasDeducedAnyParamCopy;
   return TemplateDeductionResult::Success;
@@ -2959,8 +2975,20 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
     TemplateArgumentLoc ArgLoc =
         S.getTrivialTemplateArgumentLoc(Arg, QualType(), Info.getLocation());
 
-    SaveAndRestore _1(CTAI.MatchingTTP, false);
-    SaveAndRestore _2(CTAI.StrictPackMatch, false);
+    auto _1 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getMatchingTTP();
+      PackedFlagOwner->setMatchingTTP(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setMatchingTTP(PackedFlagOld);
+      });
+    }();
+    auto _2 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getStrictPackMatch();
+      PackedFlagOwner->setStrictPackMatch(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setStrictPackMatch(PackedFlagOld);
+      });
+    }();
     // Check the template argument, converting it as necessary.
     auto Res = S.CheckTemplateArgument(
         Param, ArgLoc, Template, Template->getLocation(),
@@ -2969,7 +2997,7 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
             ? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound
                                               : Sema::CTAK_Deduced)
             : Sema::CTAK_Specified);
-    if (CTAI.StrictPackMatch)
+    if (CTAI.getStrictPackMatch())
       Info.setStrictPackMatch();
     return Res;
   };
@@ -3160,9 +3188,27 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments(
                            : TemplateDeductionResult::Incomplete;
     }
 
-    SaveAndRestore _1(CTAI.PartialOrdering, false);
-    SaveAndRestore _2(CTAI.MatchingTTP, false);
-    SaveAndRestore _3(CTAI.StrictPackMatch, false);
+    auto _1 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getPartialOrdering();
+      PackedFlagOwner->setPartialOrdering(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setPartialOrdering(PackedFlagOld);
+      });
+    }();
+    auto _2 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getMatchingTTP();
+      PackedFlagOwner->setMatchingTTP(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setMatchingTTP(PackedFlagOld);
+      });
+    }();
+    auto _3 = [PackedFlagOwner = std::addressof(CTAI)] {
+      const bool PackedFlagOld = PackedFlagOwner->getStrictPackMatch();
+      PackedFlagOwner->setStrictPackMatch(false);
+      return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+        PackedFlagOwner->setStrictPackMatch(PackedFlagOld);
+      });
+    }();
     // Check whether we can actually use the default argument.
     if (S.CheckTemplateArgument(
             Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(),
@@ -3239,7 +3285,7 @@ CheckDeducedArgumentConstraints(Sema &S, NamedDecl *Template,
   if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
                                     Info.getLocation(),
                                     Info.AssociatedConstraintsSatisfaction) ||
-      !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+      !Info.AssociatedConstraintsSatisfaction.isSatisfied()) {
     Info.reset(
         TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs),
         TemplateArgumentList::CreateCopy(S.Context, CanonicalDeducedArgs));
@@ -4010,7 +4056,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
             Info.getLocation(),
             FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
             CTAI.CanonicalConverted, Info.AssociatedConstraintsSatisfaction) ||
-        !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+        !Info.AssociatedConstraintsSatisfaction.isSatisfied()) {
       Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(
                                          Context, CTAI.CanonicalConverted));
       return TemplateDeductionResult::ConstraintsNotSatisfied;
@@ -4057,7 +4103,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
     if (CheckFunctionTemplateConstraints(
             Info.getLocation(), Specialization, CTAI.CanonicalConverted,
             Info.AssociatedConstraintsSatisfaction) ||
-        !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+        !Info.AssociatedConstraintsSatisfaction.isSatisfied()) {
       Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(
                                          Context, CTAI.CanonicalConverted));
       return TemplateDeductionResult::ConstraintsNotSatisfied;
@@ -4263,7 +4309,7 @@ bool Sema::DeduceTemplateArguments(
     if (CheckConstraintSatisfaction(PatternCTD, Constraints, DeducedArgs,
                                     SourceRange(Loc),
                                     Info.AssociatedConstraintsSatisfaction) ||
-        !Info.AssociatedConstraintsSatisfaction.IsSatisfied ||
+        !Info.AssociatedConstraintsSatisfaction.isSatisfied() ||
         Trap.hasErrorOccurred()) {
       SmallVector<TemplateArgument, 4> CanonicalCandidateArgs;
       CanonicalCandidateArgs.reserve(CandidateArgs.size());
@@ -5396,7 +5442,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
           Concept, AssociatedConstraint(Concept->getConstraintExpr()), MLTAL,
           TypeLoc.getLocalSourceRange(), Satisfaction))
     return true;
-  if (!Satisfaction.IsSatisfied) {
+  if (!Satisfaction.isSatisfied()) {
     std::string Buf;
     llvm::raw_string_ostream OS(Buf);
     OS << "'" << Concept->getName();
@@ -6763,7 +6809,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
       return false;
     PArgs = std::move(CTAI.SugaredConverted);
     if (StrictPackMatch)
-      *StrictPackMatch |= CTAI.StrictPackMatch;
+      *StrictPackMatch |= CTAI.getStrictPackMatch();
   }
 
   // Determine whether P1 is at least as specialized as P2.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 036642f22bd8c..6309606a18e8e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1788,7 +1788,7 @@ namespace {
     ExprResult TransformLambdaExpr(LambdaExpr *E) {
       // Do not rebuild lambdas to avoid creating a new type.
       // Lambdas have already been processed inside their eval contexts.
-      if (SemaRef.RebuildingImmediateInvocation)
+      if (SemaRef.getRebuildingImmediateInvocation())
         return E;
       LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
                                     /*InstantiatingLambdaOrBlock=*/true);
@@ -2837,7 +2837,7 @@ TemplateInstantiator::TransformNestedRequirement(
 
   auto NestedReqWithDiag = [&C, this](Expr *E,
                                       ConstraintSatisfaction Satisfaction) {
-    Satisfaction.IsSatisfied = false;
+    Satisfaction.setIsSatisfied(false);
     SmallString<128> Entity;
     llvm::raw_svector_ostream OS(Entity);
     E->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
@@ -2891,7 +2891,7 @@ TemplateInstantiator::TransformNestedRequirement(
   // FIXME: const correctness
   // MLTAL might be dependent.
   if (!NewConstraint) {
-    if (!Satisfaction.IsSatisfied)
+    if (!Satisfaction.isSatisfied())
       return NestedReqWithDiag(Constraint, Satisfaction);
 
     NewConstraint = Constraint;
@@ -4229,7 +4229,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
         if (Function->getTrailingRequiresClause()) {
           ConstraintSatisfaction Satisfaction;
           if (CheckFunctionConstraints(Function, Satisfaction) ||
-              !Satisfaction.IsSatisfied) {
+              !Satisfaction.isSatisfied()) {
             continue;
           }
         }
@@ -4796,7 +4796,7 @@ LocalInstantiationScope::getInstantiationOfIfExists(const Decl *D) {
     } while (CheckD);
 
     // If we aren't combined with our outer scope, we're done.
-    if (!Current->CombineWithOuterScope)
+    if (!Current->getCombineWithOuterScope())
       break;
   }
 
@@ -4844,7 +4844,7 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
 #ifndef NDEBUG
     // It should not be present in any surrounding scope either.
     LocalInstantiationScope *Current = this;
-    while (Current->CombineWithOuterScope && Current->Outer) {
+    while (Current->getCombineWithOuterScope() && Current->Outer) {
       Current = Current->Outer;
       assert(!Current->LocalDecls.contains(D) &&
              "Instantiated local in inner and outer scopes");
@@ -4869,7 +4869,7 @@ void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
 #ifndef NDEBUG
   // This should be the first time we've been told about this decl.
   for (LocalInstantiationScope *Current = this;
-       Current && Current->CombineWithOuterScope; Current = Current->Outer)
+       Current && Current->getCombineWithOuterScope(); Current = Current->Outer)
     assert(!Current->LocalDecls.contains(D) &&
            "Creating local pack after instantiation of local");
 #endif
@@ -4920,7 +4920,7 @@ NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
       return Current->PartiallySubstitutedPack;
     }
 
-    if (!Current->CombineWithOuterScope)
+    if (!Current->getCombineWithOuterScope())
       break;
   }
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b4881d0c6db5c..737459155d16e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -32,7 +32,7 @@
 #include "clang/Sema/SemaOpenMP.h"
 #include "clang/Sema/SemaSwift.h"
 #include "clang/Sema/Template.h"
-#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/Support/TimeProfiler.h"
 #include <optional>
 
@@ -578,8 +578,8 @@ static void instantiateOMPDeclareVariantAttr(
     NeedDeviceAddrExprs.push_back(ER.get());
   }
   for (OMPInteropInfo &II : Attr.appendArgs()) {
-    OMPInteropInfo Info(II.IsTarget, II.IsTargetSync);
-    Info.HasPreferAttrs = II.HasPreferAttrs;
+    OMPInteropInfo Info(II.isTarget(), II.isTargetSync());
+    Info.setPreferAttrs(II.hasPreferAttrs());
     for (const OMPInteropPref &P : II.Prefs) {
       Expr *SubstFr = nullptr;
       if (P.Fr) {
@@ -2784,7 +2784,10 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   // merged with the local instantiation scope for the function template
   // itself.
   LocalInstantiationScope Scope(SemaRef);
-  llvm::SaveAndRestore RAII(EvaluateConstraints, false);
+  llvm::scope_exit RAII([this, Old = getEvaluateConstraintsFlag()] {
+    setEvaluateConstraintsFlag(Old);
+  });
+  setEvaluateConstraintsFlag(false);
 
   TemplateParameterList *TempParams = D->getTemplateParameters();
   TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
@@ -3854,7 +3857,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
       // with the corresponding auto-typed parameter as it might reference
       // other parameters.
       if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs,
-                                      EvaluateConstraints))
+                                      getEvaluateConstraintsFlag()))
         return nullptr;
     }
   }
@@ -4842,7 +4845,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
       ClassTemplateSpecializationDecl::Create(
           SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
           D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted,
-          CTAI.StrictPackMatch, PrevDecl);
+          CTAI.getStrictPackMatch(), PrevDecl);
   InstD->setTemplateArgsAsWritten(InstTemplateArgs);
 
   // Add this partial specialization to the set of class template partial
@@ -5148,7 +5151,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
     return nullptr;
 
   Expr *InstRequiresClause = L->getRequiresClause();
-  if (InstRequiresClause && EvaluateConstraints) {
+  if (InstRequiresClause && getEvaluateConstraintsFlag()) {
     ExprResult E =
         SemaRef.SubstConstraintExpr(InstRequiresClause, TemplateArgs);
     if (E.isInvalid())
@@ -5166,7 +5169,10 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
 bool TemplateDeclInstantiator::SubstTemplateParameterLists(
     ArrayRef<TemplateParameterList *> TPLs,
     SmallVectorImpl<TemplateParameterList *> &InstTPLs) {
-  llvm::SaveAndRestore RAII(EvaluateConstraints, false);
+  llvm::scope_exit RAII([this, Old = getEvaluateConstraintsFlag()] {
+    setEvaluateConstraintsFlag(Old);
+  });
+  setEvaluateConstraintsFlag(false);
   for (TemplateParameterList *L : TPLs) {
     TemplateParameterList *InstParams = SubstTemplateParams(L);
     if (!InstParams)
@@ -5447,7 +5453,7 @@ TypeSourceInfo *TemplateDeclInstantiator::SubstFunctionType(
 
   TypeSourceInfo *NewTInfo = SemaRef.SubstFunctionDeclType(
       OldTInfo, TemplateArgs, D->getTypeSpecStartLoc(), D->getDeclName(),
-      ThisContext, ThisTypeQuals, EvaluateConstraints);
+      ThisContext, ThisTypeQuals, getEvaluateConstraintsFlag());
   if (!NewTInfo)
     return nullptr;
 
@@ -5505,7 +5511,7 @@ TypeSourceInfo *TemplateDeclInstantiator::SubstFunctionType(
         ParmVarDecl *Parm = SemaRef.SubstParmVarDecl(
             OldParam, TemplateArgs, /*indexAdjustment=*/0,
             /*NumExpansions=*/std::nullopt,
-            /*ExpectParameterPack=*/false, EvaluateConstraints);
+            /*ExpectParameterPack=*/false, getEvaluateConstraintsFlag());
         if (!Parm)
           return nullptr;
         Params.push_back(Parm);
@@ -6343,8 +6349,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
 VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
     VarTemplateDecl *VarTemplate, VarDecl *FromVar,
     const TemplateArgumentList *PartialSpecArgs,
-    SmallVectorImpl<TemplateArgument> &Converted,
-    SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs,
+    ArrayRef<TemplateArgument> Converted, SourceLocation PointOfInstantiation,
+    LateInstantiatedAttrVec *LateAttrs,
     LocalInstantiationScope *StartingScope) {
   if (FromVar->isInvalidDecl())
     return nullptr;
@@ -6569,10 +6575,18 @@ void Sema::InstantiateVariableInitializer(
   EnterExpressionEvaluationContext Evaluated(
       *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var,
       ExpressionEvaluationContextRecord::EK_VariableInit);
-  currentEvaluationContext().InLifetimeExtendingContext =
-      parentEvaluationContext().InLifetimeExtendingContext;
-  currentEvaluationContext().RebuildDefaultArgOrDefaultInit =
-      parentEvaluationContext().RebuildDefaultArgOrDefaultInit;
+  [&] {
+    auto PackedFlagValue_ =
+        parentEvaluationContext().getInLifetimeExtendingContext();
+    return currentEvaluationContext().setInLifetimeExtendingContext(
+        PackedFlagValue_);
+  }();
+  [&] {
+    auto PackedFlagValue_ =
+        parentEvaluationContext().getRebuildDefaultArgOrDefaultInit();
+    return currentEvaluationContext().setRebuildDefaultArgOrDefaultInit(
+        PackedFlagValue_);
+  }();
 
   // Set DeclForInitializer for this variable so DiagIfReachable can properly
   // suppress runtime diagnostics for constexpr/static member variables
@@ -7408,7 +7422,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
             // argument deduction in the process of rebuilding immediate
             // expressions. (Because the default argument that involves a lambda
             // is untransformed and thus could be dependent at this point.)
-            assert(SemaRef.RebuildingImmediateInvocation ||
+            assert(SemaRef.getRebuildingImmediateInvocation() ||
                    CodeSynthesisContexts.back().Kind ==
                        CodeSynthesisContext::BuildingDeductionGuides);
             // Return a nullptr as a sentinel value, we handle it properly in
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 2d6e75bd77b40..d0c7498f6e494 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -491,7 +491,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
       }
 
       if (!EnclosingStmtExpr) {
-        CSI->ContainsUnexpandedParameterPack = true;
+        CSI->setContainsUnexpandedParameterPack(true);
         return false;
       }
     } else {
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3d444bfabc8c3..c2a7b041943ca 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -43,6 +43,7 @@
 #include "clang/Sema/Template.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -200,7 +201,7 @@ namespace {
 
     /// A list of attributes to diagnose the uselessness of when the
     /// processing is complete.
-    SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
+    llvm::SmallVectorWithFlags<ParsedAttr *, 2, 3> ignoredTypeAttrs;
 
     /// Attributes corresponding to AttributedTypeLocs that we have not yet
     /// populated.
@@ -210,7 +211,10 @@ namespace {
     // properly.
     using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;
     SmallVector<TypeAttrPair, 8> AttrsForTypes;
-    bool AttrsForTypesSorted = true;
+    bool getAttrsForTypesSorted() const { return !ignoredTypeAttrs.getFlag(0); }
+    void setAttrsForTypesSorted(bool Value) {
+      ignoredTypeAttrs.setFlag(0, !Value);
+    }
 
     /// MacroQualifiedTypes mapping to macro expansion locations that will be
     /// stored in a MacroQualifiedTypeLoc.
@@ -218,17 +222,24 @@ namespace {
 
     /// Flag to indicate we parsed a noderef attribute. This is used for
     /// validating that noderef was used on a pointer or array.
-    bool parsedNoDeref;
+    bool getParsedNoDerefFlag() const { return ignoredTypeAttrs.getFlag(1); }
+    void setParsedNoDerefFlag(bool Value) {
+      ignoredTypeAttrs.setFlag(1, Value);
+    }
 
     // Flag to indicate that we already parsed a HLSL parameter modifier
     // attribute. This prevents double-mutating the type.
-    bool ParsedHLSLParamMod;
+    bool getParsedHLSLParamModFlag() const {
+      return ignoredTypeAttrs.getFlag(2);
+    }
+    void setParsedHLSLParamModFlag(bool Value) {
+      ignoredTypeAttrs.setFlag(2, Value);
+    }
 
   public:
     TypeProcessingState(Sema &sema, Declarator &declarator)
         : sema(sema), declarator(declarator),
-          chunkIndex(declarator.getNumTypeObjects()), parsedNoDeref(false),
-          ParsedHLSLParamMod(false) {}
+          chunkIndex(declarator.getNumTypeObjects()) {}
 
     Sema &getSema() const {
       return sema;
@@ -288,7 +299,7 @@ namespace {
       QualType T =
           sema.Context.getAttributedType(A, ModifiedType, EquivType);
       AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});
-      AttrsForTypesSorted = false;
+      setAttrsForTypesSorted(false);
       return T;
     }
 
@@ -318,16 +329,16 @@ namespace {
           if (A.first == AttrTy)
             A.first = NewAttrTy;
         }
-        AttrsForTypesSorted = false;
+        setAttrsForTypesSorted(false);
       }
       return T;
     }
 
     /// Extract and remove the Attr* for a given attributed type.
     const Attr *takeAttrForAttributedType(const AttributedType *AT) {
-      if (!AttrsForTypesSorted) {
+      if (!getAttrsForTypesSorted()) {
         llvm::stable_sort(AttrsForTypes, llvm::less_first());
-        AttrsForTypesSorted = true;
+        setAttrsForTypesSorted(true);
       }
 
       // FIXME: This is quadratic if we have lots of reuses of the same
@@ -363,13 +374,15 @@ namespace {
       LocsForMacros[MQT] = Loc;
     }
 
-    void setParsedNoDeref(bool parsed) { parsedNoDeref = parsed; }
+    void setParsedNoDeref(bool parsed) { setParsedNoDerefFlag(parsed); }
 
-    bool didParseNoDeref() const { return parsedNoDeref; }
+    bool didParseNoDeref() const { return getParsedNoDerefFlag(); }
 
-    void setParsedHLSLParamMod(bool Parsed) { ParsedHLSLParamMod = Parsed; }
+    void setParsedHLSLParamMod(bool Parsed) {
+      setParsedHLSLParamModFlag(Parsed);
+    }
 
-    bool didParseHLSLParamMod() const { return ParsedHLSLParamMod; }
+    bool didParseHLSLParamMod() const { return getParsedHLSLParamModFlag(); }
 
     ~TypeProcessingState() {
       if (savedAttrs.empty())
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 25e9113aeb7a4..f85f1eb1b6513 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4172,12 +4172,12 @@ class TreeTransform {
                                LambdaScopeInfo *LSI) {
     for (ParmVarDecl *PVD : LSI->CallOperator->parameters()) {
       if (Expr *Init = PVD->getInit())
-        LSI->ContainsUnexpandedParameterPack |=
-            Init->containsUnexpandedParameterPack();
+        LSI->addUnexpandedParameterPack(
+            Init->containsUnexpandedParameterPack());
       else if (PVD->hasUninstantiatedDefaultArg())
-        LSI->ContainsUnexpandedParameterPack |=
+        LSI->addUnexpandedParameterPack(
             PVD->getUninstantiatedDefaultArg()
-                ->containsUnexpandedParameterPack();
+                ->containsUnexpandedParameterPack());
     }
     return getSema().BuildLambdaExpr(StartLoc, EndLoc);
   }
@@ -4550,10 +4550,10 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
       getSema(), EnterExpressionEvaluationContext::InitList,
       Construct->isListInitialization());
 
-  getSema().currentEvaluationContext().InLifetimeExtendingContext =
-      getSema().parentEvaluationContext().InLifetimeExtendingContext;
-  getSema().currentEvaluationContext().RebuildDefaultArgOrDefaultInit =
-      getSema().parentEvaluationContext().RebuildDefaultArgOrDefaultInit;
+  getSema().currentEvaluationContext().setInLifetimeExtendingContext(
+      getSema().parentEvaluationContext().getInLifetimeExtendingContext());
+  getSema().currentEvaluationContext().setRebuildDefaultArgOrDefaultInit(
+      getSema().parentEvaluationContext().getRebuildDefaultArgOrDefaultInit());
   SmallVector<Expr*, 8> NewArgs;
   bool ArgChanged = false;
   if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(),
@@ -6165,7 +6165,8 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
       SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
 
   // If we have a VLA then it won't be a constant.
-  SemaRef.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;
+  SemaRef.ExprEvalContexts.back().setInConditionallyConstantEvaluateContext(
+      true);
 
   // Prefer the expression from the TypeLoc;  the other may have been uniqued.
   Expr *origSize = TL.getSizeExpr();
@@ -8854,19 +8855,19 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
     if (LSI) {
       if (auto *TD = dyn_cast<TypeDecl>(Transformed)) {
         if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
-          LSI->ContainsUnexpandedParameterPack |=
-              TN->getUnderlyingType()->containsUnexpandedParameterPack();
+          LSI->addUnexpandedParameterPack(
+              TN->getUnderlyingType()->containsUnexpandedParameterPack());
         } else {
-          LSI->ContainsUnexpandedParameterPack |=
+          LSI->addUnexpandedParameterPack(
               getSema()
                   .getASTContext()
                   .getTypeDeclType(TD)
-                  ->containsUnexpandedParameterPack();
+                  ->containsUnexpandedParameterPack());
         }
       }
       if (auto *VD = dyn_cast<VarDecl>(Transformed))
-        LSI->ContainsUnexpandedParameterPack |=
-            VD->getType()->containsUnexpandedParameterPack();
+        LSI->addUnexpandedParameterPack(
+            VD->getType()->containsUnexpandedParameterPack());
     }
 
     Decls.push_back(Transformed);
@@ -9472,8 +9473,8 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
   // P2718R0 - Lifetime extension in range-based for loops.
   if (getSema().getLangOpts().CPlusPlus23) {
     auto &LastRecord = getSema().currentEvaluationContext();
-    LastRecord.InLifetimeExtendingContext = true;
-    LastRecord.RebuildDefaultArgOrDefaultInit = true;
+    LastRecord.setInLifetimeExtendingContext(true);
+    LastRecord.setRebuildDefaultArgOrDefaultInit(true);
   }
   StmtResult Init =
       S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult();
@@ -9605,8 +9606,8 @@ StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtPattern(
   if (S->isDependent() || S->isIterating()) {
     EnterExpressionEvaluationContext ExprEvalCtx(
         SemaRef, SemaRef.currentEvaluationContext().Context);
-    SemaRef.currentEvaluationContext().InLifetimeExtendingContext = true;
-    SemaRef.currentEvaluationContext().RebuildDefaultArgOrDefaultInit = true;
+    SemaRef.currentEvaluationContext().setInLifetimeExtendingContext(true);
+    SemaRef.currentEvaluationContext().setRebuildDefaultArgOrDefaultInit(true);
 
     if (S->isDependent()) {
       // The expansion initializer should not be in the context of the expansion
@@ -9726,8 +9727,8 @@ StmtResult TreeTransform<Derived>::TransformCXXExpansionStmtInstantiation(
   {
     EnterExpressionEvaluationContext ExprEvalCtx(
         SemaRef, SemaRef.currentEvaluationContext().Context);
-    SemaRef.currentEvaluationContext().InLifetimeExtendingContext = true;
-    SemaRef.currentEvaluationContext().RebuildDefaultArgOrDefaultInit = true;
+    SemaRef.currentEvaluationContext().setInLifetimeExtendingContext(true);
+    SemaRef.currentEvaluationContext().setRebuildDefaultArgOrDefaultInit(true);
     if (TransformStmts(PreambleStmts, S->getPreambleStmts()))
       return StmtError();
 
@@ -11457,7 +11458,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPInitClause(OMPInitClause *C) {
     }
     InteropInfo.Prefs.emplace_back(NewFr, std::move(NewAttrs));
   }
-  InteropInfo.HasPreferAttrs = C->hasPreferAttrs();
+  InteropInfo.setPreferAttrs(C->hasPreferAttrs());
   return getDerived().RebuildOMPInitClause(IVR.get(), InteropInfo,
                                            C->getBeginLoc(), C->getLParenLoc(),
                                            C->getVarLoc(), C->getEndLoc());
@@ -16457,8 +16458,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
         // But rule out cases e.g.
         //    [...C = Pack()] {}
         if (NewC.EllipsisLoc.isInvalid())
-          LSI->ContainsUnexpandedParameterPack |=
-              Init.get()->containsUnexpandedParameterPack();
+          LSI->addUnexpandedParameterPack(
+              Init.get()->containsUnexpandedParameterPack());
       }
 
       if (Invalid)
@@ -16526,7 +16527,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
     // This is not an init-capture; however it contains an unexpanded pack e.g.
     //  ([Pack] {}(), ...)
     if (auto *VD = dyn_cast<VarDecl>(CapturedVar); VD && !C->isPackExpansion())
-      LSI->ContainsUnexpandedParameterPack |= VD->isParameterPack();
+      LSI->addUnexpandedParameterPack(VD->isParameterPack());
 
     // Capture the transformed variable.
     getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind,
@@ -16542,8 +16543,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   if (TPL) {
     getSema().AddTemplateParametersToLambdaCallOperator(NewCallOperator, Class,
                                                         TPL);
-    LSI->ContainsUnexpandedParameterPack |=
-        TPL->containsUnexpandedParameterPack();
+    LSI->addUnexpandedParameterPack(TPL->containsUnexpandedParameterPack());
   }
 
   TypeLocBuilder NewCallOpTLBuilder;
@@ -16553,8 +16553,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
       getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc);
   if (NewCallOpType.isNull())
     return ExprError();
-  LSI->ContainsUnexpandedParameterPack |=
-      NewCallOpType->containsUnexpandedParameterPack();
+  LSI->addUnexpandedParameterPack(
+      NewCallOpType->containsUnexpandedParameterPack());
   TypeSourceInfo *NewCallOpTSI =
       NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
 
@@ -16572,7 +16572,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
     TRC.ConstraintExpr = E.get();
   }
 
-  LSI->BeforeCompoundStatement = false;
+  LSI->setBeforeCompoundStatement(false);
   getSema().CompleteLambdaCallOperator(
       NewCallOperator, E->getCallOperator()->getLocation(),
       E->getCallOperator()->getInnerLocStart(), TRC, NewCallOpTSI,
@@ -17978,7 +17978,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
     blockScope->TheDecl->setParams(params);
 
   if (!oldBlock->blockMissingReturnType()) {
-    blockScope->HasImplicitReturnType = false;
+    blockScope->setHasImplicitReturnType(false);
     blockScope->ReturnType = exprResultType;
   }
 
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e6f6be496e5e5..32c0bc7f8eead 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -753,8 +753,8 @@ bool PCHValidator::ReadDiagnosticOptions(DiagnosticOptions &DiagOpts,
   // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that
   // contains the union of their flags.
   return checkDiagnosticMappings(*Diags, ExistingDiags, ModuleFilename,
-                                 TopM->IsSystem, SystemHeaderWarningsInModule,
-                                 Complain);
+                                 TopM->getIsSystem(),
+                                 SystemHeaderWarningsInModule, Complain);
 }
 
 /// Collect the macro definitions provided by the given preprocessor
@@ -1077,7 +1077,7 @@ readULEBKeyDataLength(const unsigned char *&P) {
 void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener,
                                            bool TakeOwnership) {
   DeserializationListener = Listener;
-  OwnsDeserializationListener = TakeOwnership;
+  setOwnsDeserializationListener(TakeOwnership);
 }
 
 unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
@@ -2378,9 +2378,9 @@ unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
 
 HeaderFileInfoTrait::internal_key_type
 HeaderFileInfoTrait::GetInternalKey(external_key_type ekey) {
-  internal_key_type ikey = {ekey.getSize(),
-                            M.HasTimestamps ? ekey.getModificationTime() : 0,
-                            ekey.getName(), /*Imported*/ false};
+  internal_key_type ikey = {
+      ekey.getSize(), M.getHasTimestamps() ? ekey.getModificationTime() : 0,
+      ekey.getName(), /*Imported*/ false};
   return ikey;
 }
 
@@ -2900,14 +2900,14 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
   uint64_t StoredContentHash = FI.ContentHash;
 
   // For standard C++ modules, we don't need to check the inputs.
-  bool SkipChecks = F.StandardCXXModule;
+  bool SkipChecks = F.getStandardCXXModule();
 
   const HeaderSearchOptions &HSOpts =
       PP.getHeaderSearchInfo().getHeaderSearchOpts();
 
   // The option ForceCheckCXX20ModulesInputFiles is only meaningful for C++20
   // modules.
-  if (F.StandardCXXModule && HSOpts.ForceCheckCXX20ModulesInputFiles) {
+  if (F.getStandardCXXModule() && HSOpts.ForceCheckCXX20ModulesInputFiles) {
     SkipChecks = false;
     Overridden = false;
   }
@@ -2954,7 +2954,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
   }
 
   auto HasInputContentChanged = [&](Change OriginalChange) {
-    assert(ValidateASTInputFilesContent &&
+    assert(getValidateASTInputFilesContent() &&
            "We should only check the content of the inputs with "
            "ValidateASTInputFilesContent enabled.");
 
@@ -2988,7 +2988,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
 
       // In case the modification time changes but not the content,
       // accept the cached file as legit.
-      if (ValidateASTInputFilesContent)
+      if (getValidateASTInputFilesContent())
         return HasInputContentChanged(MTimeChange);
 
       return MTimeChange;
@@ -3001,15 +3001,16 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
   // When ForceCheckCXX20ModulesInputFiles and ValidateASTInputFilesContent
   // enabled, it is better to check the contents of the inputs. Since we can't
   // get correct modified time information for inputs from overriden inputs.
-  if (HSOpts.ForceCheckCXX20ModulesInputFiles && ValidateASTInputFilesContent &&
-      F.StandardCXXModule && FileChange.Kind == Change::None)
+  if (HSOpts.ForceCheckCXX20ModulesInputFiles &&
+      getValidateASTInputFilesContent() && F.getStandardCXXModule() &&
+      FileChange.Kind == Change::None)
     FileChange = HasInputContentChanged(FileChange);
 
   // When we have StoredTime equal to zero and ValidateASTInputFilesContent,
   // it is better to check the content of the input files because we cannot rely
   // on the file modification time, which will be the same (zero) for these
   // files.
-  if (!StoredTime && ValidateASTInputFilesContent &&
+  if (!StoredTime && getValidateASTInputFilesContent() &&
       FileChange.Kind == Change::None)
     FileChange = HasInputContentChanged(FileChange);
 
@@ -3339,15 +3340,15 @@ ASTReader::ReadControlBlock(ModuleFile &F,
         // so we verify all input files.  Otherwise, verify only user input
         // files.
 
-        unsigned N = ValidateSystemInputs ? NumInputs : NumUserInputs;
-        F.InputFilesValidationStatus = ValidateSystemInputs
+        unsigned N = getValidateSystemInputs() ? NumInputs : NumUserInputs;
+        F.InputFilesValidationStatus = getValidateSystemInputs()
                                            ? InputFilesValidation::AllFiles
                                            : InputFilesValidation::UserFiles;
         auto [_, WasValidated] = wasValidatedInBuildSession(F, HSOpts);
         if (WasValidated) {
-          N = ForceValidateUserInputs ? NumUserInputs : 0;
+          N = getForceValidateUserInputs() ? NumUserInputs : 0;
           F.InputFilesValidationStatus =
-              ForceValidateUserInputs
+              getForceValidateUserInputs()
                   ? InputFilesValidation::UserFiles
                   : InputFilesValidation::SkippedInBuildSession;
         }
@@ -3429,8 +3430,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
             return Result;
           }
 
-          if (DisableValidation ||
-              (AllowConfigurationMismatch && Result == ConfigurationMismatch))
+          if (DisableValidation || (getAllowConfigurationMismatch() &&
+                                    Result == ConfigurationMismatch))
             Result = Success;
 
           // If we can't load the module, exit early since we likely
@@ -3484,7 +3485,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
             canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
           return OutOfDate;
 
-        if (!AllowASTWithCompilerErrors) {
+        if (!getAllowASTWithCompilerErrors()) {
           Diag(diag::err_ast_file_with_compiler_errors)
               << moduleKindForDiagnostic(F.Kind) << F.FileName;
           return HadErrors;
@@ -3496,14 +3497,14 @@ ASTReader::ReadControlBlock(ModuleFile &F,
         Diags.UnrecoverableErrorOccurred = true;
       }
 
-      F.RelocatablePCH = Record[4];
+      F.setRelocatablePCH(Record[4]);
       // Relative paths in a relocatable PCH are relative to our sysroot.
-      if (F.RelocatablePCH)
+      if (F.getRelocatablePCH())
         F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
 
-      F.StandardCXXModule = Record[5];
+      F.setStandardCXXModule(Record[5]);
 
-      F.HasTimestamps = Record[6];
+      F.setHasTimestamps(Record[6]);
 
       const std::string &CurBranch = getClangFullRepositoryVersion();
       StringRef ASTBranch = Blob;
@@ -4340,7 +4341,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
 
       // For standard C++20 module, we will only reads the instantiations
       // if it is the main file.
-      if (!F.StandardCXXModule || F.Kind == MK_MainFile) {
+      if (!F.getStandardCXXModule() || F.Kind == MK_MainFile) {
         for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
           PendingInstantiations.push_back(
               {ReadDeclID(F, Record, I),
@@ -5054,12 +5055,12 @@ bool ASTReader::loadGlobalIndex() {
   if (GlobalIndex)
     return false;
 
-  if (TriedLoadingGlobalIndex || !UseGlobalIndex ||
+  if (getTriedLoadingGlobalIndex() || !getUseGlobalIndex() ||
       !PP.getLangOpts().Modules)
     return true;
 
   // Try to load the global index.
-  TriedLoadingGlobalIndex = true;
+  setTriedLoadingGlobalIndex(true);
   StringRef SpecificModuleCachePath =
       getPreprocessor().getHeaderSearchInfo().getSpecificModuleCachePath();
   std::pair<GlobalModuleIndex *, llvm::Error> Result =
@@ -5076,8 +5077,8 @@ bool ASTReader::loadGlobalIndex() {
 }
 
 bool ASTReader::isGlobalIndexUnavailable() const {
-  return PP.getLangOpts().Modules && UseGlobalIndex &&
-         !hasGlobalIndex() && TriedLoadingGlobalIndex;
+  return PP.getLangOpts().Modules && getUseGlobalIndex() && !hasGlobalIndex() &&
+         getTriedLoadingGlobalIndex();
 }
 
 /// Given a cursor at the start of an AST file, scan ahead and drop the
@@ -5185,7 +5186,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(ModuleFileName FileName,
     }
 
     // The AST block should always have a definition for the main module.
-    if (F.isModule() && !F.DidReadTopLevelSubmodule) {
+    if (F.isModule() && !F.getDidReadTopLevelSubmodule()) {
       Error(diag::err_module_file_missing_top_level_submodule, F.FileName);
       return Failure;
     }
@@ -5543,7 +5544,7 @@ ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy,
   // If F was directly imported by another module, it's implicitly validated by
   // the importing module.
   if (DisableValidation || WasImportedBy ||
-      (AllowConfigurationMismatch && Result == ConfigurationMismatch))
+      (getAllowConfigurationMismatch() && Result == ConfigurationMismatch))
     return Success;
 
   if (Result == Failure) {
@@ -6578,7 +6579,7 @@ Module *ASTReader::getSubmodule(uint32_t GlobalID) {
           }
         }
 
-        F.DidReadTopLevelSubmodule = true;
+        F.setDidReadTopLevelSubmodule(true);
         CurrentModule->setASTFileNameAndKey(F.FileName, F.FileKey);
         CurrentModule->PresumedModuleMapFile = F.ModuleMapPath;
       }
@@ -6592,17 +6593,17 @@ Module *ASTReader::getSubmodule(uint32_t GlobalID) {
       // duplicate locations for the same module map file.
       CurrentModule->DefinitionLoc = DefinitionLoc;
       CurrentModule->Signature = F.Signature;
-      CurrentModule->IsFromModuleFile = true;
+      CurrentModule->setIsFromModuleFile(true);
       if (InferredAllowedBy.isValid())
         ModMap.setInferredModuleAllowedBy(CurrentModule, InferredAllowedBy);
-      CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
-      CurrentModule->IsExternC = IsExternC;
-      CurrentModule->InferSubmodules = InferSubmodules;
-      CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
-      CurrentModule->InferExportWildcard = InferExportWildcard;
-      CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive;
-      CurrentModule->ModuleMapIsPrivate = ModuleMapIsPrivate;
-      CurrentModule->NamedModuleHasInit = NamedModuleHasInit;
+      CurrentModule->setIsSystem(IsSystem || CurrentModule->getIsSystem());
+      CurrentModule->setIsExternC(IsExternC);
+      CurrentModule->setInferSubmodules(InferSubmodules);
+      CurrentModule->setInferExplicitSubmodules(InferExplicitSubmodules);
+      CurrentModule->setInferExportWildcard(InferExportWildcard);
+      CurrentModule->setConfigMacrosExhaustive(ConfigMacrosExhaustive);
+      CurrentModule->setModuleMapIsPrivate(ModuleMapIsPrivate);
+      CurrentModule->setNamedModuleHasInit(NamedModuleHasInit);
 
       if (!ParentModule && !F.BaseDirectory.empty()) {
         if (auto Dir = FileMgr.getOptionalDirectoryRef(F.BaseDirectory))
@@ -6630,9 +6631,9 @@ Module *ASTReader::getSubmodule(uint32_t GlobalID) {
       // imported module file.
       CurrentModule->Requirements.clear();
       CurrentModule->MissingHeaders.clear();
-      CurrentModule->IsUnimportable =
-          ParentModule && ParentModule->IsUnimportable;
-      CurrentModule->IsAvailable = !CurrentModule->IsUnimportable;
+      CurrentModule->setIsUnimportable(ParentModule &&
+                                       ParentModule->getIsUnimportable());
+      CurrentModule->setIsAvailable(!CurrentModule->getIsUnimportable());
       break;
     }
 
@@ -6742,7 +6743,7 @@ Module *ASTReader::getSubmodule(uint32_t GlobalID) {
       if (!ContextObj)
         break;
       // Standard C++ module has its own way to initialize variables.
-      if (!F.StandardCXXModule || F.Kind == MK_MainFile) {
+      if (!F.getStandardCXXModule() || F.Kind == MK_MainFile) {
         SmallVector<GlobalDeclID, 16> Inits;
         for (unsigned I = 0; I < Record.size(); /*in loop*/)
           Inits.push_back(ReadDeclID(F, Record, I));
@@ -11479,8 +11480,13 @@ void ASTReader::FinishedDeserializing() {
     {
       // Guard variable to avoid recursively entering the process of passing
       // decls to consumer.
-      SaveAndRestore GuardPassingDeclsToConsumer(CanPassDeclsToConsumer,
-                                                 /*NewValue=*/false);
+      auto GuardPassingDeclsToConsumer = [PackedFlagOwner = this] {
+        const bool PackedFlagOld = PackedFlagOwner->getCanPassDeclsToConsumer();
+        PackedFlagOwner->setCanPassDeclsToConsumer(false);
+        return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+          PackedFlagOwner->setCanPassDeclsToConsumer(PackedFlagOld);
+        });
+      }();
 
       // Propagate exception specification and deduced type updates along
       // redeclaration chains.
@@ -11580,12 +11586,15 @@ ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache,
                 PP.getHeaderSearchInfo()),
       DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
       DisableValidationKind(DisableValidationKind),
-      AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
-      AllowConfigurationMismatch(AllowConfigurationMismatch),
-      ValidateSystemInputs(ValidateSystemInputs),
-      ForceValidateUserInputs(ForceValidateUserInputs),
-      ValidateASTInputFilesContent(ValidateASTInputFilesContent),
-      UseGlobalIndex(UseGlobalIndex), CurrSwitchCaseStmts(&SwitchCaseStmts) {
+      CurrSwitchCaseStmts(&SwitchCaseStmts),
+      PreloadedDeclIDs(decltype(this->PreloadedDeclIDs)::withFlags(
+          unsigned(ForceValidateUserInputs) |
+          (unsigned(ValidateASTInputFilesContent) << 1) |
+          (unsigned(UseGlobalIndex) << 2))),
+      CommentsCursors(decltype(this->CommentsCursors)::withFlags(
+          (unsigned(AllowASTWithCompilerErrors) << 1) |
+          (unsigned(AllowConfigurationMismatch) << 2) |
+          (unsigned(ValidateSystemInputs) << 3))) {
   SourceMgr.setExternalSLocEntrySource(this);
 
   PathBuf.reserve(256);
@@ -11604,7 +11613,7 @@ ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache,
 }
 
 ASTReader::~ASTReader() {
-  if (OwnsDeserializationListener)
+  if (getOwnsDeserializationListener())
     delete DeserializationListener;
 }
 
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index d7d650ef02192..c8b38f7c48bc2 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -57,6 +57,7 @@
 #include "clang/Serialization/ModuleFile.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/iterator_range.h"
@@ -67,6 +68,7 @@
 #include <cassert>
 #include <cstdint>
 #include <cstring>
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -4449,13 +4451,18 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
 void ASTReader::PassInterestingDeclsToConsumer() {
   assert(Consumer);
 
-  if (!CanPassDeclsToConsumer)
+  if (!getCanPassDeclsToConsumer())
     return;
 
   // Guard variable to avoid recursively redoing the process of passing
   // decls to consumer.
-  SaveAndRestore GuardPassingDeclsToConsumer(CanPassDeclsToConsumer,
-                                             /*NewValue=*/false);
+  auto GuardPassingDeclsToConsumer = [PackedFlagOwner = this] {
+    const bool PackedFlagOld = PackedFlagOwner->getCanPassDeclsToConsumer();
+    PackedFlagOwner->setCanPassDeclsToConsumer(false);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setCanPassDeclsToConsumer(PackedFlagOld);
+    });
+  }();
 
   // Ensure that we've loaded all potentially-interesting declarations
   // that need to be eagerly loaded.
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 26aee27c65e82..9217cca0635bc 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -837,10 +837,10 @@ void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
 static ConstraintSatisfaction
 readConstraintSatisfaction(ASTRecordReader &Record) {
   ConstraintSatisfaction Satisfaction;
-  Satisfaction.IsSatisfied = Record.readInt();
-  Satisfaction.ContainsErrors = Record.readInt();
+  Satisfaction.setIsSatisfied(Record.readInt());
+  Satisfaction.setContainsErrors(Record.readInt());
   const ASTContext &C = Record.getContext();
-  if (!Satisfaction.IsSatisfied) {
+  if (!Satisfaction.isSatisfied()) {
     unsigned NumDetailRecords = Record.readInt();
     for (unsigned i = 0; i != NumDetailRecords; ++i) {
       auto Kind = Record.readInt();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 0afba1c84fd62..da9ef3b84cb33 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -94,6 +94,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitstream/BitCodes.h"
 #include "llvm/Bitstream/BitstreamWriter.h"
@@ -1479,8 +1480,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
                                        CLANG_VERSION_MINOR,
                                        !isysroot.empty(),
                                        isWritingStdCXXNamedModules(),
-                                       IncludeTimestamps,
-                                       ASTHasCompilerErrors};
+                                       getIncludeTimestamps(),
+                                       getASTHasCompilerErrors()};
     Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
                               getClangFullRepositoryVersion());
   }
@@ -1605,11 +1606,11 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
       Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding
       AddSourceLocation(M.ImportLoc, Record);
       AddStringBlob(M.ModuleName, Record, Blob);
-      Record.push_back(M.StandardCXXModule);
+      Record.push_back(M.getStandardCXXModule());
 
       // We don't want to hard code the information about imported modules
       // in the C++20 named modules.
-      if (M.StandardCXXModule) {
+      if (M.getStandardCXXModule()) {
         Record.push_back(0);
         Record.push_back(0);
         Record.push_back(0);
@@ -1744,7 +1745,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
   // If we're building an implicit module with a context hash, the importer is
   // guaranteed to have the same macros defined on the command line. Skip
   // writing them.
-  bool SkipMacros = BuildingImplicitModule && !HSOpts.DisableModuleHash;
+  bool SkipMacros = getBuildingImplicitModule() && !HSOpts.DisableModuleHash;
   bool WriteMacros = !SkipMacros;
   Record.push_back(WriteMacros);
   if (WriteMacros) {
@@ -2127,12 +2128,14 @@ namespace {
       data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded,
                 ArrayRef<ModuleMap::KnownHeader> KnownHeaders,
                 UnresolvedModule Unresolved)
-          : HFI(HFI), AlreadyIncluded(AlreadyIncluded),
-            KnownHeaders(KnownHeaders), Unresolved(Unresolved) {}
+          : HFI(HFI), KnownHeaders(decltype(this->KnownHeaders)::withFlags(
+                          unsigned(AlreadyIncluded), KnownHeaders)),
+            Unresolved(Unresolved) {}
 
       HeaderFileInfo HFI;
-      bool AlreadyIncluded;
-      SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders;
+      bool getAlreadyIncluded() const { return KnownHeaders.getFlag(0); }
+      void setAlreadyIncluded(bool Value) { KnownHeaders.setFlag(0, Value); }
+      llvm::SmallVectorWithFlags<ModuleMap::KnownHeader, 1> KnownHeaders;
       UnresolvedModule Unresolved;
     };
     using data_type_ref = const data_type &;
@@ -2180,11 +2183,11 @@ namespace {
       endian::Writer LE(Out, llvm::endianness::little);
       uint64_t Start = Out.tell(); (void)Start;
 
-      unsigned char Flags = (Data.AlreadyIncluded << 6)
-                          | (Data.HFI.isImport << 5)
-                          | (Writer.isWritingStdCXXNamedModules() ? 0 :
-                             Data.HFI.isPragmaOnce << 4)
-                          | (Data.HFI.DirInfo << 1);
+      unsigned char Flags =
+          (Data.getAlreadyIncluded() << 6) | (Data.HFI.isImport << 5) |
+          (Writer.isWritingStdCXXNamedModules() ? 0
+                                                : Data.HFI.isPragmaOnce << 4) |
+          (Data.HFI.DirInfo << 1);
       LE.write<uint8_t>(Flags);
 
       if (Data.HFI.LazyControllingMacro.isID())
@@ -2246,7 +2249,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
       for (const auto &U : M->MissingHeaders) {
         // Check that we were given enough information to build a module
         // without this file existing on disk.
-        if (!U.Size || (!U.ModTime && IncludeTimestamps)) {
+        if (!U.Size || (!U.ModTime && getIncludeTimestamps())) {
           PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header)
               << WritingModule->getFullModuleName() << U.Size.has_value()
               << U.FileName;
@@ -2262,7 +2265,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
         SavedStrings.push_back(FilenameDup.data());
 
         HeaderFileInfoTrait::key_type Key = {
-            FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0};
+            FilenameDup, *U.Size, getIncludeTimestamps() ? *U.ModTime : 0};
         HeaderFileInfoTrait::data_type Data = {
             Empty, false, {}, {M, ModuleMap::headerKindToRole(U.Kind)}};
         // FIXME: Deal with cases where there are multiple unresolved header
@@ -3141,7 +3144,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {
 
     ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
     FileID UnadjustedInferredFID;
-    if (Mod->IsInferred)
+    if (Mod->getIsInferred())
       UnadjustedInferredFID = ModMap.getModuleMapFileIDForUniquing(Mod);
     int InferredFID = getAdjustedFileID(UnadjustedInferredFID).getOpaqueValue();
 
@@ -3153,16 +3156,16 @@ void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {
                                          (RecordData::value_type)Mod->Kind,
                                          DefinitionLoc,
                                          (RecordData::value_type)InferredFID,
-                                         Mod->IsFramework,
-                                         Mod->IsExplicit,
-                                         Mod->IsSystem,
-                                         Mod->IsExternC,
-                                         Mod->InferSubmodules,
-                                         Mod->InferExplicitSubmodules,
-                                         Mod->InferExportWildcard,
-                                         Mod->ConfigMacrosExhaustive,
-                                         Mod->ModuleMapIsPrivate,
-                                         Mod->NamedModuleHasInit};
+                                         Mod->getIsFramework(),
+                                         Mod->getIsExplicit(),
+                                         Mod->getIsSystem(),
+                                         Mod->getIsExternC(),
+                                         Mod->getInferSubmodules(),
+                                         Mod->getInferExplicitSubmodules(),
+                                         Mod->getInferExportWildcard(),
+                                         Mod->getConfigMacrosExhaustive(),
+                                         Mod->getModuleMapIsPrivate(),
+                                         Mod->getNamedModuleHasInit()};
       Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
     }
 
@@ -3272,7 +3275,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {
 
     // Emit the reachable initializers.
     // The initializer may only be unreachable in reduced BMI.
-    if (Context && !GeneratingReducedBMI) {
+    if (Context && !getGeneratingReducedBMI()) {
       RecordData Inits;
       for (Decl *D : Context->getModuleInitializers(Mod))
         if (wasDeclEmitted(D))
@@ -3495,13 +3498,13 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
     return 0;
 
   // In reduced BMI, we don't care the declarations in functions.
-  if (GeneratingReducedBMI && DC->isFunctionOrMethod())
+  if (getGeneratingReducedBMI() && DC->isFunctionOrMethod())
     return 0;
 
   uint64_t Offset = Stream.GetCurrentBitNo();
   SmallVector<DeclID, 128> KindDeclPairs;
   for (const auto *D : DC->decls()) {
-    if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
+    if (getDoneWritingDeclsAndTypesFlag() && !wasDeclEmitted(D))
       continue;
 
     // We don't need to write decls with internal linkage into reduced BMI.
@@ -3509,7 +3512,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
     // the program illegal. However, there are too many use of static inline
     // functions in the global module fragment and it will be breaking change
     // to forbid that. So we have to allow to emit such declarations from GMF.
-    if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() &&
+    if (getGeneratingReducedBMI() && !D->isFromExplicitGlobalModule() &&
         IsInternalDeclFromFileContext(D))
       continue;
 
@@ -4779,7 +4782,8 @@ void ASTWriter::GenerateNameLookupTable(
     // Also in reduced BMI, we'd like to avoid writing unreachable
     // declarations in GMF, so we need to avoid writing declarations
     // that entirely external or unreachable.
-    if (GeneratingReducedBMI && isLookupResultNotInteresting(*this, Result))
+    if (getGeneratingReducedBMI() &&
+        isLookupResultNotInteresting(*this, Result))
       continue;
     // We also skip empty results. If any of the results could be external and
     // the currently available results are empty, then all of the results are
@@ -5004,12 +5008,12 @@ void ASTWriter::WriteDeclContextVisibleBlock(
         if (ND->isFromASTFile())
           continue;
 
-        if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))
+        if (getDoneWritingDeclsAndTypesFlag() && !wasDeclEmitted(ND))
           continue;
 
         // We don't need to force emitting internal decls into reduced BMI.
         // See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
-        if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() &&
+        if (getGeneratingReducedBMI() && !ND->isFromExplicitGlobalModule() &&
             IsInternalDeclFromFileContext(ND))
           continue;
 
@@ -5242,7 +5246,7 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
 /// Write the state of 'pragma ms_struct' at the end of the module.
 void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {
   RecordData Record;
-  Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);
+  Record.push_back(SemaRef.getMSStructPragmaOn() ? PMSST_ON : PMSST_OFF);
   Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);
 }
 
@@ -5457,7 +5461,8 @@ void ASTWriter::AddStringBlob(StringRef Str, RecordDataImpl &Record,
 }
 
 bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
-  assert(WritingAST && "can't prepare path for output when not writing AST");
+  assert(getWritingAST() &&
+         "can't prepare path for output when not writing AST");
 
   // Leave special file names as they are.
   StringRef PathStr(Path.data(), Path.size());
@@ -5541,9 +5546,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
                      bool IncludeTimestamps, bool BuildingImplicitModule,
                      bool GeneratingReducedBMI)
     : Stream(Stream), Buffer(Buffer), ModCache(ModCache),
-      CodeGenOpts(CodeGenOpts), IncludeTimestamps(IncludeTimestamps),
-      BuildingImplicitModule(BuildingImplicitModule),
-      GeneratingReducedBMI(GeneratingReducedBMI) {
+      CodeGenOpts(CodeGenOpts),
+      Redeclarations(decltype(this->Redeclarations)::withFlags(
+          (unsigned(GeneratingReducedBMI) << 1))),
+      PendingEmittingVTables(decltype(this->PendingEmittingVTables)::withFlags(
+          unsigned(IncludeTimestamps) |
+          (unsigned(BuildingImplicitModule) << 1))) {
   for (const auto &Ext : Extensions) {
     if (auto Writer = Ext->createExtensionWriter(*this))
       ModuleFileExtensionWriters.push_back(std::move(Writer));
@@ -5553,12 +5561,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
 ASTWriter::~ASTWriter() = default;
 
 const LangOptions &ASTWriter::getLangOpts() const {
-  assert(WritingAST && "can't determine lang opts when not writing AST");
+  assert(getWritingAST() && "can't determine lang opts when not writing AST");
   return PP->getLangOpts();
 }
 
 time_t ASTWriter::getTimestampForOutput(time_t ModTime) const {
-  return IncludeTimestamps ? ModTime : 0;
+  return getIncludeTimestamps() ? ModTime : 0;
 }
 
 ASTFileSignature
@@ -5566,13 +5574,14 @@ ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,
                     StringRef OutputFile, Module *WritingModule,
                     StringRef isysroot) {
   llvm::TimeTraceScope scope("WriteAST", OutputFile);
-  WritingAST = true;
+  setWritingAST(true);
 
   Sema *SemaPtr = dyn_cast<Sema *>(Subject);
   Preprocessor &PPRef =
       SemaPtr ? SemaPtr->getPreprocessor() : *cast<Preprocessor *>(Subject);
 
-  ASTHasCompilerErrors = PPRef.getDiagnostics().hasUncompilableErrorOccurred();
+  setASTHasCompilerErrors(
+      PPRef.getDiagnostics().hasUncompilableErrorOccurred());
 
   // Emit the file header.
   Stream.Emit((unsigned)'C', 8);
@@ -5589,7 +5598,7 @@ ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,
   this->WritingModule = nullptr;
   this->BaseDirectory.clear();
 
-  WritingAST = false;
+  setWritingAST(false);
 
   return Signature;
 }
@@ -5710,7 +5719,7 @@ void ASTWriter::computeNonAffectingInputFiles() {
 void ASTWriter::prepareLazyUpdates() {
   // In C++20 named modules with reduced BMI, we only apply the update
   // if these updates are touched.
-  if (!GeneratingReducedBMI)
+  if (!getGeneratingReducedBMI())
     return;
 
   DeclUpdateMap DeclUpdatesTmp;
@@ -5796,7 +5805,7 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
     if (D->isFromASTFile())
       continue;
 
-    if (GeneratingReducedBMI) {
+    if (getGeneratingReducedBMI()) {
       if (D->isFromExplicitGlobalModule())
         continue;
 
@@ -5822,7 +5831,7 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
     GetDeclRef(D);
   }
 
-  if (GeneratingReducedBMI)
+  if (getGeneratingReducedBMI())
     return;
 
   // Writing all of the tentative definitions in this file, in
@@ -5989,7 +5998,7 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
     Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
                       UnusedLocalTypedefNameCandidates);
 
-  if (!GeneratingReducedBMI) {
+  if (!getGeneratingReducedBMI()) {
     // Write the record containing pending implicit instantiations.
     RecordData PendingInstantiations;
     for (const auto &I : SemaRef.PendingInstantiations) {
@@ -6461,11 +6470,11 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
     }
   } while (!DeclUpdates.empty());
 
-  DoneWritingDeclsAndTypes = true;
+  setDoneWritingDeclsAndTypesFlag(true);
 
   // DelayedNamespace is only meaningful in reduced BMI.
   // See the comments of DelayedNamespace for details.
-  assert(DelayedNamespace.empty() || GeneratingReducedBMI);
+  assert(DelayedNamespace.empty() || getGeneratingReducedBMI());
   RecordData DelayedNamespaceRecord;
   for (NamespaceDecl *NS : DelayedNamespace) {
     LookupBlockOffsets Offsets;
@@ -6789,7 +6798,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(ASTContext &Context,
 
     // Add a trailing update record, if any. These must go last because we
     // lazily load their attached statement.
-    if (!GeneratingReducedBMI || !CanElideDeclDef(D)) {
+    if (!getGeneratingReducedBMI() || !CanElideDeclDef(D)) {
       if (HasUpdatedBody) {
         const auto *Def = cast<FunctionDecl>(D);
         Record.push_back(
@@ -7113,7 +7122,7 @@ TypeID ASTWriter::GetOrCreateTypeID(ASTContext &Context, QualType T) {
 
     TypeIdx &Idx = TypeIdxs[T];
     if (Idx.getValue() == 0) {
-      if (DoneWritingDeclsAndTypes) {
+      if (getDoneWritingDeclsAndTypesFlag()) {
         assert(0 && "New type seen after serializing all the types to emit!");
         return TypeIdx();
       }
@@ -7167,7 +7176,8 @@ void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {
 }
 
 LocalDeclID ASTWriter::GetDeclRef(const Decl *D) {
-  assert(WritingAST && "Cannot request a declaration ID before AST writing");
+  assert(getWritingAST() &&
+         "Cannot request a declaration ID before AST writing");
 
   if (!D) {
     return LocalDeclID();
@@ -7187,7 +7197,7 @@ LocalDeclID ASTWriter::GetDeclRef(const Decl *D) {
   assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
   LocalDeclID &ID = DeclIDs[D];
   if (ID.isInvalid()) {
-    if (DoneWritingDeclsAndTypes) {
+    if (getDoneWritingDeclsAndTypesFlag()) {
       assert(0 && "New decl seen after serializing all the decls to emit!");
       return LocalDeclID();
     }
@@ -7217,7 +7227,7 @@ LocalDeclID ASTWriter::getDeclID(const Decl *D) {
 bool ASTWriter::wasDeclEmitted(const Decl *D) const {
   assert(D);
 
-  assert(DoneWritingDeclsAndTypes &&
+  assert(getDoneWritingDeclsAndTypesFlag() &&
          "wasDeclEmitted should only be called after writing declarations");
 
   if (D->isFromASTFile())
@@ -7225,13 +7235,13 @@ bool ASTWriter::wasDeclEmitted(const Decl *D) const {
 
   bool Emitted = DeclIDs.contains(D);
   assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) ||
-          GeneratingReducedBMI) &&
+          getGeneratingReducedBMI()) &&
          "The declaration within modules can only be omitted in reduced BMI.");
   return Emitted;
 }
 
 void ASTWriter::getLazyUpdates(const Decl *D) {
-  if (!GeneratingReducedBMI)
+  if (!getGeneratingReducedBMI())
     return;
 
   if (auto *Iter = DeclUpdatesLazy.find(D); Iter != DeclUpdatesLazy.end()) {
@@ -7742,7 +7752,7 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
 void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
   assert(D->isCompleteDefinition());
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
     // We are interested when a PCH decl is modified.
     if (RD->isFromASTFile()) {
@@ -7790,7 +7800,7 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
 
   assert(DC == DC->getPrimaryContext() && "added to non-primary context");
   assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {
     // We're adding a visible declaration to a predefined decl context. Ensure
     // that we write out all of its lookup results so we don't get a nasty
@@ -7814,14 +7824,14 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
 
   // A decl coming from PCH was modified.
   assert(RD->isCompleteDefinition());
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   DeclUpdates[RD].push_back(
       DeclUpdate(DeclUpdateKind::CXXAddedImplicitMember, D));
 }
 
 void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
+  assert(!getDoneWritingDeclsAndTypesFlag() && "Already done writing updates!");
   if (!Chain) return;
   Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
     // If we don't already know the exception specification for this redecl
@@ -7836,7 +7846,7 @@ void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
 
 void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!Chain) return;
   Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
     DeclUpdates[D].push_back(
@@ -7848,7 +7858,7 @@ void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
                                        const FunctionDecl *Delete,
                                        Expr *ThisArg) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   assert(Delete && "Not given an operator delete");
   if (!Chain) return;
   Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
@@ -7861,7 +7871,7 @@ void ASTWriter::ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                            const FunctionDecl *GlobDelete) {
   if (Chain && Chain->isProcessingUpdateRecords())
     return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   assert(GlobDelete && "Not given an operator delete");
   if (!Chain)
     return;
@@ -7875,7 +7885,7 @@ void ASTWriter::ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
                                             const FunctionDecl *ArrayDelete) {
   if (Chain && Chain->isProcessingUpdateRecords())
     return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   assert(ArrayDelete && "Not given an operator delete");
   if (!Chain)
     return;
@@ -7889,7 +7899,7 @@ void ASTWriter::ResolvedOperatorGlobArrayDelete(
     const CXXDestructorDecl *DD, const FunctionDecl *GlobArrayDelete) {
   if (Chain && Chain->isProcessingUpdateRecords())
     return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   assert(GlobArrayDelete && "Not given an operator delete");
   if (!Chain)
     return;
@@ -7901,7 +7911,7 @@ void ASTWriter::ResolvedOperatorGlobArrayDelete(
 
 void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return; // Declaration not imported from PCH.
 
@@ -7916,7 +7926,7 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
 
 void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -7925,7 +7935,7 @@ void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {
 
 void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -7939,7 +7949,7 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
 
 void ASTWriter::InstantiationRequested(const ValueDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -7956,7 +7966,7 @@ void ASTWriter::InstantiationRequested(const ValueDecl *D) {
 
 void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -7965,7 +7975,7 @@ void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
 }
 
 void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -7976,7 +7986,7 @@ void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {
 void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                              const ObjCInterfaceDecl *IFD) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!IFD->isFromASTFile())
     return; // Declaration not imported from PCH.
 
@@ -7987,7 +7997,7 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
 
 void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
 
   // If there is *any* declaration of the entity that's not from an AST file,
   // we can skip writing the update record. We make sure that isUsed() triggers
@@ -8001,7 +8011,7 @@ void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
 
 void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -8011,7 +8021,7 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
 
 void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -8022,7 +8032,7 @@ void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {
 void ASTWriter::DeclarationMarkedOpenMPIndirectCall(const Decl *D) {
   if (Chain && Chain->isProcessingUpdateRecords())
     return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -8033,7 +8043,7 @@ void ASTWriter::DeclarationMarkedOpenMPIndirectCall(const Decl *D) {
 void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
                                                      const Attr *Attr) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!D->isFromASTFile())
     return;
 
@@ -8043,7 +8053,7 @@ void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
 
 void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   assert(!D->isUnconditionallyVisible() && "expected a hidden declaration");
   DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::DeclExported, M));
 }
@@ -8051,7 +8061,7 @@ void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
 void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
                                        const RecordDecl *Record) {
   if (Chain && Chain->isProcessingUpdateRecords()) return;
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
   if (!Record->isFromASTFile())
     return;
   DeclUpdates[Record].push_back(
@@ -8060,7 +8070,7 @@ void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
 
 void ASTWriter::AddedCXXTemplateSpecialization(
     const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
 
   if (!TD->getFirstDecl()->isFromASTFile())
     return;
@@ -8072,7 +8082,7 @@ void ASTWriter::AddedCXXTemplateSpecialization(
 
 void ASTWriter::AddedCXXTemplateSpecialization(
     const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
 
   if (!TD->getFirstDecl()->isFromASTFile())
     return;
@@ -8084,7 +8094,7 @@ void ASTWriter::AddedCXXTemplateSpecialization(
 
 void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                                const FunctionDecl *D) {
-  assert(!WritingAST && "Already writing the AST!");
+  assert(!getWritingAST() && "Already writing the AST!");
 
   if (!TD->getFirstDecl()->isFromASTFile())
     return;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 2f5b9ed925097..9e2082c03f3fa 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -3118,7 +3118,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
   assert(ID >= FirstDeclID && "invalid decl ID");
 
   RecordData Record;
-  ASTDeclWriter W(*this, Context, Record, GeneratingReducedBMI);
+  ASTDeclWriter W(*this, Context, Record, getGeneratingReducedBMI());
 
   // Build a record for this declaration
   W.Visit(D);
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index 8bc7e1782c2d9..99d168451ec88 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -30,11 +30,11 @@ PCHGenerator::PCHGenerator(
     bool AllowASTWithErrors, bool IncludeTimestamps,
     bool BuildingImplicitModule, bool GeneratingReducedBMI)
     : PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()),
-      Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
-      Writer(Stream, this->Buffer->Data, ModCache, CodeGenOpts, Extensions,
+      Buffer(std::move(Buffer)),
+      Writer(Stream, Stream.getBuffer(), ModCache, CodeGenOpts, Extensions,
              IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI),
       AllowASTWithErrors(AllowASTWithErrors) {
-  this->Buffer->IsComplete = false;
+  this->Buffer->setIsComplete(false);
 }
 
 PCHGenerator::~PCHGenerator() {
@@ -84,7 +84,9 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
 
   Buffer->Signature = Writer.WriteAST(Subject, OutputFile, Module, isysroot);
 
-  Buffer->IsComplete = true;
+  Stream.FlushToWord();
+  Buffer->Data.assign(std::move(Stream.getBuffer()));
+  Buffer->setIsComplete(true);
 }
 
 ASTMutationListener *PCHGenerator::GetASTMutationListener() {
@@ -131,7 +133,7 @@ void CXX20ModulesGenerator::HandleTranslationUnit(ASTContext &Ctx) {
     return;
   }
 
-  *OS << getBufferPtr()->Data;
+  *OS << StringRef(getBufferPtr()->Data.data(), getBufferPtr()->Data.size());
   OS->flush();
 }
 
diff --git a/clang/lib/Serialization/PCHContainerOperations.cpp b/clang/lib/Serialization/PCHContainerOperations.cpp
index 4aedb7debcff2..fa4f568b551c0 100644
--- a/clang/lib/Serialization/PCHContainerOperations.cpp
+++ b/clang/lib/Serialization/PCHContainerOperations.cpp
@@ -35,14 +35,14 @@ class RawPCHContainerGenerator : public ASTConsumer {
   ~RawPCHContainerGenerator() override = default;
 
   void HandleTranslationUnit(ASTContext &Ctx) override {
-    if (Buffer->IsComplete) {
+    if (Buffer->getIsComplete()) {
       // Make sure it hits disk now.
-      *OS << Buffer->Data;
+      *OS << StringRef(Buffer->Data.data(), Buffer->Data.size());
       OS->flush();
     }
     // Free the space of the temporary buffer.
     llvm::SmallVector<char, 0> Empty;
-    Buffer->Data = std::move(Empty);
+    Buffer->Data.assign(std::move(Empty));
   }
 };
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 3997da0ba5dc5..d3de442a25041 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -22,6 +22,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
@@ -216,20 +217,25 @@ static void describeUninitializedArgumentInCall(const CallEvent &Call,
 namespace {
 class FindUninitializedField {
 public:
-  using FieldChainTy = SmallVector<const FieldDecl *, 10>;
-  FieldChainTy FieldChain;
+  struct FieldChainTy : ArrayRef<const FieldDecl *> {
+    explicit FieldChainTy(ArrayRef<const FieldDecl *> Fields)
+        : ArrayRef(Fields) {}
+  };
+  llvm::SmallVectorWithFlags<const FieldDecl *, 10> FieldChain;
 
 private:
   StoreManager &StoreMgr;
   MemRegionManager &MrMgr;
   Store store;
-  bool FindNotUninitialized;
+  bool getFindNotUninitialized() const { return FieldChain.getFlag(0); }
+  void setFindNotUninitialized(bool Value) { FieldChain.setFlag(0, Value); }
 
 public:
   FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
                          Store s, bool FindNotUninitialized = false)
-      : StoreMgr(storeMgr), MrMgr(mrMgr), store(s),
-        FindNotUninitialized(FindNotUninitialized) {}
+      : FieldChain(decltype(this->FieldChain)::withFlags(
+            unsigned(FindNotUninitialized))),
+        StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
 
   bool Find(const TypedValueRegion *R) {
     QualType T = R->getValueType();
@@ -243,18 +249,18 @@ class FindUninitializedField {
         FieldChain.push_back(I);
         T = I->getType();
         if (T->isStructureType()) {
-          if (FindNotUninitialized ? !Find(FR) : Find(FR))
-            return !FindNotUninitialized;
+          if (getFindNotUninitialized() ? !Find(FR) : Find(FR))
+            return !getFindNotUninitialized();
         } else {
           SVal V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
-          if (FindNotUninitialized ? !V.isUndef() : V.isUndef())
-            return !FindNotUninitialized;
+          if (getFindNotUninitialized() ? !V.isUndef() : V.isUndef())
+            return !getFindNotUninitialized();
         }
         FieldChain.pop_back();
       }
     }
 
-    return FindNotUninitialized;
+    return getFindNotUninitialized();
   }
 };
 } // namespace
@@ -363,7 +369,8 @@ bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, SVal V,
         std::string Msg = llvm::formatv(
             "{0}{1} function call argument {2} an uninitialized value{3}; {4}",
             (ArgumentNumber + 1), llvm::getOrdinalSuffix(ArgumentNumber + 1),
-            ParamT->isPointerType() ? "points to" : "is", F.FieldChain,
+            ParamT->isPointerType() ? "points to" : "is",
+            FindUninitializedField::FieldChainTy(F.FieldChain),
             DescribeArgument(/*ArgIsStruct=*/true));
         auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
         R->addRange(Call.getArgSourceRange(ArgumentNumber));
@@ -423,7 +430,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(
       if (ExplodedNode *N = C.generateErrorNode()) {
         std::string Msg = llvm::formatv(
             "Passed-by-value struct argument contains uninitialized data{0}",
-            F.FieldChain);
+            FindUninitializedField::FieldChainTy(F.FieldChain));
 
         // Generate a report for this bug.
         auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 19aeebf588eeb..741f7fc74fba1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -29,6 +29,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Unicode.h"
 #include <optional>
 
@@ -1193,10 +1194,15 @@ class PluralMisuseChecker : public Checker<check::ASTCodeBody> {
     // This functions like a stack. We push on any IfStmt or
     // ConditionalOperator that matches the condition
     // and pop it off when we leave that statement
-    llvm::SmallVector<const clang::Stmt *, 8> MatchingStatements;
+    llvm::SmallVectorWithFlags<const clang::Stmt *, 8> MatchingStatements;
     // This is true when we are the direct-child of a
     // matching statement
-    bool InMatchingStatement = false;
+    bool getInMatchingStatement() const {
+      return MatchingStatements.getFlag(0);
+    }
+    void setInMatchingStatement(bool Value) {
+      MatchingStatements.setFlag(0, Value);
+    }
 
   public:
     explicit MethodCrawler(BugReporter &InBR, const CheckerBase *Checker,
@@ -1269,7 +1275,7 @@ bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
 // string. Raise a diagnostic when this is in a statement that matches
 // the condition.
 bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(CallExpr *CE) {
-  if (InMatchingStatement) {
+  if (getInMatchingStatement()) {
     if (const FunctionDecl *FD = CE->getDirectCallee()) {
       std::string NormalizedName =
           StringRef(FD->getNameInfo().getAsString()).lower();
@@ -1299,7 +1305,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
 
   if (odInfo->isStr("NSBundle") &&
       ME->getSelector().getAsString() == "localizedStringForKey:value:table:") {
-    if (InMatchingStatement) {
+    if (getInMatchingStatement()) {
       reportPluralMisuseError(ME);
     }
   }
@@ -1319,11 +1325,11 @@ bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) {
   MatchingStatements.pop_back();
   if (!MatchingStatements.empty()) {
     if (MatchingStatements.back() != nullptr) {
-      InMatchingStatement = true;
+      setInMatchingStatement(true);
       return true;
     }
   }
-  InMatchingStatement = false;
+  setInMatchingStatement(false);
   return true;
 }
 
@@ -1334,10 +1340,10 @@ bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(IfStmt *I) {
   Condition = Condition->IgnoreParenImpCasts();
   if (isCheckingPlurality(Condition)) {
     MatchingStatements.push_back(I);
-    InMatchingStatement = true;
+    setInMatchingStatement(true);
   } else {
     MatchingStatements.push_back(nullptr);
-    InMatchingStatement = false;
+    setInMatchingStatement(false);
   }
 
   return true;
@@ -1350,11 +1356,11 @@ bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
   MatchingStatements.pop_back();
   if (!MatchingStatements.empty()) {
     if (MatchingStatements.back() != nullptr)
-      InMatchingStatement = true;
+      setInMatchingStatement(true);
     else
-      InMatchingStatement = false;
+      setInMatchingStatement(false);
   } else {
-    InMatchingStatement = false;
+    setInMatchingStatement(false);
   }
   return true;
 }
@@ -1364,10 +1370,10 @@ bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
   const Expr *Condition = C->getCond()->IgnoreParenImpCasts();
   if (isCheckingPlurality(Condition)) {
     MatchingStatements.push_back(C);
-    InMatchingStatement = true;
+    setInMatchingStatement(true);
   } else {
     MatchingStatements.push_back(nullptr);
-    InMatchingStatement = false;
+    setInMatchingStatement(false);
   }
   return true;
 }
diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index db307d3ac549f..f2b43ce3711d3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -23,6 +23,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 using namespace ento;
@@ -476,7 +477,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
     CheckerContext &Ctx;
     ProgramStateRef State;
     const StackFrame *PoppedFrame;
-    const bool TopFrame;
+    bool getTopFrame() const { return V.getFlag(0); }
 
     /// Look for stack variables referring to popped stack variables.
     /// Returns true only if it found some dangling stack variables
@@ -509,7 +510,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
       if (isa<StackArgumentsSpaceRegion>(ReferrerMemSpace) &&
           // Not a simple ptr (int*) but something deeper, e.g. int**
           isa<SymbolicRegion>(Referrer->getBaseRegion()) &&
-          ReferrerStackSpace->getStackFrame() == PoppedFrame && TopFrame) {
+          ReferrerStackSpace->getStackFrame() == PoppedFrame && getTopFrame()) {
         // Output parameter of a top-level function
         V.emplace_back(Referrer, Referred);
         return true;
@@ -527,7 +528,9 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
     }
 
   public:
-    SmallVector<std::pair<const MemRegion *, const MemRegion *>, 10> V;
+    llvm::SmallVectorWithFlags<std::pair<const MemRegion *, const MemRegion *>,
+                               10>
+        V;
     // ExcludedRegions are skipped from reporting.
     // I.e., if a referrer in this set, skip the related bug report.
     // It is useful to avoid false positive for the variables that were
@@ -536,7 +539,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
 
     CallBack(CheckerContext &CC, bool TopFrame)
         : Ctx(CC), State(CC.getState()), PoppedFrame(CC.getStackFrame()),
-          TopFrame(TopFrame) {}
+          V(decltype(this->V)::withFlags(unsigned(TopFrame))) {}
 
     bool HandleBinding(StoreManager &SMgr, Store S, const MemRegion *Region,
                        SVal Val) override {
diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
index 285d4a40157db..f2d4f991c3516 100644
--- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -291,13 +291,16 @@ IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle &Style,
                                                     ? llvm::Regex::NoFlags
                                                     : llvm::Regex::IgnoreCase);
   }
-  IsMainFile = FileName.ends_with(".c") || FileName.ends_with(".cc") ||
-               FileName.ends_with(".cpp") || FileName.ends_with(".c++") ||
-               FileName.ends_with(".cxx") || FileName.ends_with(".m") ||
-               FileName.ends_with(".mm");
+  setIsMainFile(FileName.ends_with(".c") || FileName.ends_with(".cc") ||
+                FileName.ends_with(".cpp") || FileName.ends_with(".c++") ||
+                FileName.ends_with(".cxx") || FileName.ends_with(".m") ||
+                FileName.ends_with(".mm"));
   if (!Style.IncludeIsMainSourceRegex.empty()) {
     llvm::Regex MainFileRegex(Style.IncludeIsMainSourceRegex);
-    IsMainFile |= MainFileRegex.match(FileName);
+    [&] {
+      auto PackedFlagValue = MainFileRegex.match(FileName);
+      return setIsMainFile(getIsMainFile() | PackedFlagValue);
+    }();
   }
 }
 
@@ -309,7 +312,8 @@ int IncludeCategoryManager::getIncludePriority(StringRef IncludeName,
       Ret = Style.IncludeCategories[i].Priority;
       break;
     }
-  if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
+  if (CheckMainHeader && getIsMainFile() && Ret > 0 &&
+      isMainHeader(IncludeName))
     Ret = 0;
   return Ret;
 }
@@ -324,7 +328,8 @@ int IncludeCategoryManager::getSortIncludePriority(StringRef IncludeName,
         Ret = Style.IncludeCategories[i].Priority;
       break;
     }
-  if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
+  if (CheckMainHeader && getIsMainFile() && Ret > 0 &&
+      isMainHeader(IncludeName))
     Ret = 0;
   return Ret;
 }
diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
index 152e568e00384..2ca1013b93ce2 100644
--- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -162,18 +162,18 @@ int main(int argc, const char **argv) {
   /// Class to store bundler options in standard (non-cl::opt) data structures
   // Avoid using cl::opt variables after these assignments when possible
   OffloadBundlerConfig BundlerConfig;
-  BundlerConfig.AllowMissingBundles = AllowMissingBundles;
-  BundlerConfig.CheckInputArchive = CheckInputArchive;
-  BundlerConfig.PrintExternalCommands = PrintExternalCommands;
-  BundlerConfig.HipOpenmpCompatible = HipOpenmpCompatible;
+  BundlerConfig.setAllowMissingBundles(AllowMissingBundles);
+  BundlerConfig.setCheckInputArchive(CheckInputArchive);
+  BundlerConfig.setPrintExternalCommands(PrintExternalCommands);
+  BundlerConfig.setHipOpenmpCompatible(HipOpenmpCompatible);
   BundlerConfig.BundleAlignment = BundleAlignment;
   BundlerConfig.FilesType = FilesType;
   BundlerConfig.ObjcopyPath = "";
   // Do not override the default value Compress and Verbose in BundlerConfig.
   if (Compress.getNumOccurrences() > 0)
-    BundlerConfig.Compress = Compress;
+    BundlerConfig.setCompress(Compress);
   if (Verbose.getNumOccurrences() > 0)
-    BundlerConfig.Verbose = Verbose;
+    BundlerConfig.setVerbose(Verbose);
   if (CompressionLevel.getNumOccurrences() > 0)
     BundlerConfig.CompressionLevel = CompressionLevel;
 
@@ -187,7 +187,7 @@ int main(int argc, const char **argv) {
   BundlerConfig.HostInputIndex = ~0u;
 
   /// Whether not having host target is allowed.
-  BundlerConfig.AllowNoHost = false;
+  BundlerConfig.setAllowNoHost(false);
 
   auto reportError = [argv](Error E) {
     logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
@@ -283,7 +283,7 @@ int main(int argc, const char **argv) {
     });
   }
 
-  if (BundlerConfig.CheckInputArchive) {
+  if (BundlerConfig.getCheckInputArchive()) {
     if (!Unbundle) {
       return reportError(createStringError(
           errc::invalid_argument, "-check-input-archive cannot be used while "
@@ -415,12 +415,12 @@ int main(int argc, const char **argv) {
   // HIP uses clang-offload-bundler to bundle device-only compilation results
   // for multiple GPU archs, therefore allow no host target if all entries
   // are for HIP.
-  BundlerConfig.AllowNoHost = HIPOnly;
+  BundlerConfig.setAllowNoHost(HIPOnly);
 
   // Host triple is not really needed for unbundling operation, so do not
   // treat missing host triple as error if we do unbundling.
   if ((Unbundle && HostTargetNum > 1) ||
-      (!Unbundle && HostTargetNum != 1 && !BundlerConfig.AllowNoHost)) {
+      (!Unbundle && HostTargetNum != 1 && !BundlerConfig.getAllowNoHost())) {
     return reportError(createStringError(
         errc::invalid_argument,
         "expecting exactly one host target but got " + Twine(HostTargetNum)));
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 4c6ff23de71df..056ddc81374b9 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -508,9 +508,9 @@ class FullDeps {
         for (auto &&ModID : ModuleIDs) {
           auto &MD = Modules[ModID];
           JOS.object([&] {
-            if (MD.IsInStableDirectories)
+            if (MD.getIsInStableDirectories())
               JOS.attribute("is-in-stable-directories",
-                            MD.IsInStableDirectories);
+                            MD.getIsInStableDirectories());
             JOS.attributeArray("clang-module-deps",
                                toJSONSorted(JOS, MD.ClangModuleDeps));
             JOS.attribute("clang-modulemap-file",
@@ -529,8 +529,11 @@ class FullDeps {
                   JOS.value(FileDep);
               });
             });
-            JOS.attributeArray("link-libraries",
-                               toJSONSorted(JOS, MD.LinkLibraries));
+            JOS.attributeArray(
+                "link-libraries",
+                toJSONSorted(JOS, SmallVector<Module::LinkLibrary, 2>(
+                                      MD.LinkLibraries.begin(),
+                                      MD.LinkLibraries.end())));
             JOS.attribute("name", StringRef(MD.ID.ModuleName));
           });
         }
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index 077cd69ce4e2c..23c730f98af5a 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -19,6 +19,7 @@
 #include "clang/Frontend/Utils.h"
 #include "clang/Options/Options.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/DataLayout.h"
@@ -102,7 +103,8 @@ struct AssemblerInvocation {
   std::string DwarfDebugFlags;
   std::string DwarfDebugProducer;
   std::string DebugCompilationDir;
-  llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
+  llvm::SmallVectorWithFlags<std::pair<std::string, std::string>, 0, 2>
+      DebugPrefixMap;
   llvm::DebugCompressionType CompressDebugSections =
       llvm::DebugCompressionType::None;
   std::string MainFileName;
@@ -121,10 +123,12 @@ struct AssemblerInvocation {
     FT_Obj   ///< Object file output.
   };
   FileType OutputType;
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned ShowHelp : 1;
-  LLVM_PREFERRED_TYPE(bool)
-  unsigned ShowVersion : 1;
+  unsigned getShowHelp() const { return DebugPrefixMap.getFlag(0); }
+  void setShowHelp(unsigned Value) { DebugPrefixMap.setFlag(0, (Value & 1)); }
+  unsigned getShowVersion() const { return DebugPrefixMap.getFlag(1); }
+  void setShowVersion(unsigned Value) {
+    DebugPrefixMap.setFlag(1, (Value & 1));
+  }
 
   /// @}
   /// @name Transliterate Options
@@ -352,8 +356,8 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
     } else
       Opts.OutputType = FileType(OutputType);
   }
-  Opts.ShowHelp = Args.hasArg(OPT_help);
-  Opts.ShowVersion = Args.hasArg(OPT_version);
+  Opts.setShowHelp(Args.hasArg(OPT_help));
+  Opts.setShowVersion(Args.hasArg(OPT_version));
 
   // Transliterate Options
   Opts.OutputAsmVariant =
@@ -704,7 +708,7 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
   if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
     return 1;
 
-  if (Asm.ShowHelp) {
+  if (Asm.getShowHelp()) {
     getDriverOptTable().printHelp(
         llvm::outs(), "clang -cc1as [options] file...",
         "Clang Integrated Assembler", /*ShowHidden=*/false,
@@ -716,7 +720,7 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
   // Honor -version.
   //
   // FIXME: Use a better -version message?
-  if (Asm.ShowVersion) {
+  if (Asm.getShowVersion()) {
     llvm::cl::PrintVersionMessage();
     return 0;
   }
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index af96812e9ebd9..82e907aa3bec0 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -139,9 +139,9 @@ static T checkEnvVar(const char *EnvOptSet, const char *EnvOptFile,
 }
 
 static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
-  TheDriver.CCPrintOptions =
+  TheDriver.setCCPrintOptions(
       checkEnvVar<bool>("CC_PRINT_OPTIONS", "CC_PRINT_OPTIONS_FILE",
-                        TheDriver.CCPrintOptionsFilename);
+                        TheDriver.CCPrintOptionsFilename));
   if (checkEnvVar<bool>("CC_PRINT_HEADERS", "CC_PRINT_HEADERS_FILE",
                         TheDriver.CCPrintHeadersFilename)) {
     TheDriver.CCPrintHeadersFormat = HIFMT_Textual;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 8d246d41f31f6..e66452a8c6d1c 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -47,6 +47,7 @@
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/Compiler.h"
@@ -291,14 +292,14 @@ bool CursorVisitor::visitFileRegion() {
   unsigned Offset = Begin.second;
   unsigned Length = End.second - Begin.second;
 
-  if (!VisitDeclsOnly && !VisitPreprocessorLast)
+  if (!getVisitDeclsOnly() && !getVisitPreprocessorLast())
     if (visitPreprocessedEntitiesInRegion())
       return true; // visitation break.
 
   if (visitDeclsFromFileRegion(File, Offset, Length))
     return true; // visitation break.
 
-  if (!VisitDeclsOnly && VisitPreprocessorLast)
+  if (!getVisitDeclsOnly() && getVisitPreprocessorLast())
     return visitPreprocessedEntitiesInRegion();
 
   return false;
@@ -535,7 +536,8 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
     CXTranslationUnit TU = getCursorTU(Cursor);
     ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
 
-    int VisitOrder[2] = {VisitPreprocessorLast, !VisitPreprocessorLast};
+    int VisitOrder[2] = {getVisitPreprocessorLast(),
+                         !getVisitPreprocessorLast()};
     for (unsigned I = 0; I != 2; ++I) {
       if (VisitOrder[I]) {
         if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
@@ -7906,7 +7908,12 @@ class AnnotateTokensWorker {
   unsigned PreprocessingTokIdx;
   CursorVisitor AnnotateVis;
   SourceManager &SrcMgr;
-  bool HasContextSensitiveKeywords;
+  bool getHasContextSensitiveKeywords() const {
+    return PostChildrenInfos.getFlag(0);
+  }
+  void setHasContextSensitiveKeywords(bool Value) {
+    PostChildrenInfos.setFlag(0, Value);
+  }
 
   struct PostChildrenAction {
     CXCursor cursor;
@@ -7921,7 +7928,7 @@ class AnnotateTokensWorker {
     unsigned BeforeChildrenTokenIdx;
     PostChildrenActions ChildActions;
   };
-  SmallVector<PostChildrenInfo, 8> PostChildrenInfos;
+  llvm::SmallVectorWithFlags<PostChildrenInfo, 8> PostChildrenInfos;
 
   CXToken &getTok(unsigned Idx) {
     assert(Idx < NumTokens);
@@ -7958,8 +7965,7 @@ class AnnotateTokensWorker {
                     /*VisitIncludedEntities=*/false, RegionOfInterest,
                     /*VisitDeclsOnly=*/false,
                     AnnotateTokensPostChildrenVisitor),
-        SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()),
-        HasContextSensitiveKeywords(false) {}
+        SrcMgr(cxtu::getASTUnit(TU)->getSourceManager()) {}
 
   void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
   enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
@@ -7975,7 +7981,7 @@ class AnnotateTokensWorker {
   /// Determine whether the annotator saw any cursors that have
   /// context-sensitive keywords.
   bool hasContextSensitiveKeywords() const {
-    return HasContextSensitiveKeywords;
+    return getHasContextSensitiveKeywords();
   }
 
   ~AnnotateTokensWorker() { assert(PostChildrenInfos.empty()); }
@@ -8126,13 +8132,13 @@ enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
   if (IsIgnoredChildCursor(cursor))
     return CXChildVisit_Continue;
 
-  if (!HasContextSensitiveKeywords) {
+  if (!getHasContextSensitiveKeywords()) {
     // Objective-C properties can have context-sensitive keywords.
     if (cursor.kind == CXCursor_ObjCPropertyDecl) {
       if (const ObjCPropertyDecl *Property =
               dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
-        HasContextSensitiveKeywords =
-            Property->getPropertyAttributesAsWritten() != 0;
+        setHasContextSensitiveKeywords(
+            Property->getPropertyAttributesAsWritten() != 0);
     }
     // Objective-C methods can have context-sensitive keywords.
     else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
@@ -8140,11 +8146,11 @@ enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
       if (const ObjCMethodDecl *Method =
               dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
         if (Method->getObjCDeclQualifier())
-          HasContextSensitiveKeywords = true;
+          setHasContextSensitiveKeywords(true);
         else {
           for (const auto *P : Method->parameters()) {
             if (P->getObjCDeclQualifier()) {
-              HasContextSensitiveKeywords = true;
+              setHasContextSensitiveKeywords(true);
               break;
             }
           }
@@ -8156,7 +8162,7 @@ enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
       if (const CXXMethodDecl *Method =
               dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
         if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
-          HasContextSensitiveKeywords = true;
+          setHasContextSensitiveKeywords(true);
       }
     }
     // C++ classes can have context-sensitive keywords.
@@ -8166,7 +8172,7 @@ enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor,
              cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
       if (const Decl *D = getCursorDecl(cursor))
         if (D->hasAttr<FinalAttr>())
-          HasContextSensitiveKeywords = true;
+          setHasContextSensitiveKeywords(true);
     }
   }
 
@@ -9501,7 +9507,7 @@ int clang_Module_isSystem(CXModule CXMod) {
   if (!CXMod)
     return 0;
   Module *Mod = static_cast<Module *>(CXMod);
-  return Mod->IsSystem;
+  return Mod->getIsSystem();
 }
 
 unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit TU,
diff --git a/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h
index 1b359d2920e11..e0e46c571b1be 100644
--- a/clang/tools/libclang/CursorVisitor.h
+++ b/clang/tools/libclang/CursorVisitor.h
@@ -14,6 +14,7 @@
 #include "Index_Internal.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/TypeLocVisitor.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <optional>
 
 namespace clang {
@@ -97,11 +98,13 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
 
   /// Whether we should visit the preprocessing record entries last,
   /// after visiting other declarations.
-  bool VisitPreprocessorLast;
+  bool getVisitPreprocessorLast() const { return WorkListCache.getFlag(0); }
+  void setVisitPreprocessorLast(bool Value) { WorkListCache.setFlag(0, Value); }
 
   /// Whether we should visit declarations or preprocessing record
   /// entries that are #included inside the \arg RegionOfInterest.
-  bool VisitIncludedEntities;
+  bool getVisitIncludedEntities() const { return WorkListCache.getFlag(1); }
+  void setVisitIncludedEntities(bool Value) { WorkListCache.setFlag(1, Value); }
 
   /// When valid, a source range to which the cursor should restrict
   /// its search.
@@ -109,7 +112,8 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
 
   /// Whether we should only visit declarations and not preprocessing
   /// record entries.
-  bool VisitDeclsOnly;
+  bool getVisitDeclsOnly() const { return WorkListCache.getFlag(2); }
+  void setVisitDeclsOnly(bool Value) { WorkListCache.setFlag(2, Value); }
 
   // FIXME: Eventually remove.  This part of a hack to support proper
   // iteration over all Decls contained lexically within an ObjC container.
@@ -120,7 +124,7 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
 
   // Cache of pre-allocated worklists for data-recursion walk of Stmts.
   SmallVector<VisitorWorkList *, 5> WorkListFreeList;
-  SmallVector<VisitorWorkList *, 5> WorkListCache;
+  llvm::SmallVectorWithFlags<VisitorWorkList *, 5, 3> WorkListCache;
 
   using DeclVisitor<CursorVisitor, bool>::Visit;
   using TypeLocVisitor<CursorVisitor, bool>::Visit;
@@ -162,10 +166,12 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
                 PostChildrenVisitorTy PostChildrenVisitor = nullptr)
       : TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor),
         PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData),
-        VisitPreprocessorLast(VisitPreprocessorLast),
-        VisitIncludedEntities(VisitIncludedPreprocessingEntries),
-        RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly),
-        DI_current(nullptr), FileDI_current(nullptr) {
+        RegionOfInterest(RegionOfInterest), DI_current(nullptr),
+        FileDI_current(nullptr),
+        WorkListCache(decltype(WorkListCache)::withFlags(
+            unsigned(VisitPreprocessorLast) |
+            (unsigned(VisitIncludedPreprocessingEntries) << 1) |
+            (unsigned(VisitDeclsOnly) << 2))) {
     Parent.kind = CXCursor_NoDeclFound;
     Parent.data[0] = nullptr;
     Parent.data[1] = nullptr;
@@ -193,7 +199,9 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
 
   bool visitPreprocessedEntitiesInRegion();
 
-  bool shouldVisitIncludedEntities() const { return VisitIncludedEntities; }
+  bool shouldVisitIncludedEntities() const {
+    return getVisitIncludedEntities();
+  }
 
   template <typename InputIterator>
   bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp
index 0fd2eb36898ea..a72f7881e583b 100644
--- a/clang/tools/libclang/Indexing.cpp
+++ b/clang/tools/libclang/Indexing.cpp
@@ -28,6 +28,7 @@
 #include "clang/Lex/PPConditionalDirectiveRecord.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/VirtualFileSystem.h"
@@ -148,11 +149,12 @@ class ParsedSrcLocationsTracker {
   /// constructed.
   llvm::DenseSet<PPRegion> ParsedRegionsSnapshot;
   /// Regions that were queried during this instance lifetime.
-  SmallVector<PPRegion, 32> NewParsedRegions;
+  llvm::SmallVectorWithFlags<PPRegion, 32> NewParsedRegions;
 
   /// Caching the last queried region.
   PPRegion LastRegion;
-  bool LastIsParsed;
+  bool getLastIsParsed() const { return NewParsedRegions.getFlag(0); }
+  void setLastIsParsed(bool Value) { NewParsedRegions.setFlag(0, Value); }
 
 public:
   /// Creates snapshot of \p ParsedRegionsStorage.
@@ -173,17 +175,17 @@ class ParsedSrcLocationsTracker {
 
     // Check common case, consecutive functions in the same region.
     if (LastRegion == region)
-      return LastIsParsed;
+      return getLastIsParsed();
 
     LastRegion = region;
     // Source locations can't be revisited during single TU parsing.
     // That means if we hit the same region again, it's a different location in
     // the same region and so the "is parsed" value from the snapshot is still
     // correct.
-    LastIsParsed = ParsedRegionsSnapshot.count(region);
-    if (!LastIsParsed)
+    setLastIsParsed(ParsedRegionsSnapshot.count(region));
+    if (!getLastIsParsed())
       NewParsedRegions.emplace_back(std::move(region));
-    return LastIsParsed;
+    return getLastIsParsed();
   }
 
   /// Updates ParsedRegionsStorage with newly parsed regions.
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 59aac4c507772..f7ae892860428 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -887,9 +887,9 @@ namespace {
       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
          << getLowerName() << "_end(); I != E; ++I) {\n";
-      OS << "      if (I->IsTarget && I->IsTargetSync)\n";
+      OS << "      if (I->isTarget() && I->isTargetSync())\n";
       OS << "        OS << \" Target_TargetSync\";\n";
-      OS << "      else if (I->IsTarget)\n";
+      OS << "      else if (I->isTarget())\n";
       OS << "        OS << \" Target\";\n";
       OS << "      else\n";
       OS << "        OS << \" TargetSync\";\n";
@@ -906,7 +906,7 @@ namespace {
       OS << "      bool IsTarget = Record.readBool();\n";
       OS << "      bool IsTargetSync = Record.readBool();\n";
       OS << "      OMPInteropInfo Info(IsTarget, IsTargetSync);\n";
-      OS << "      Info.HasPreferAttrs = Record.readBool();\n";
+      OS << "      Info.setPreferAttrs(Record.readBool());\n";
       OS << "      unsigned prefsSize = Record.readInt();\n";
       OS << "      Info.Prefs.reserve(prefsSize);\n";
       OS << "      for (unsigned J = 0; J < prefsSize; ++J) {\n";
@@ -928,9 +928,9 @@ namespace {
       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
          << getLowerName() << "_end(); I != E; ++I) {\n";
-      OS << "      Record.writeBool(I->IsTarget);\n";
-      OS << "      Record.writeBool(I->IsTargetSync);\n";
-      OS << "      Record.writeBool(I->HasPreferAttrs);\n";
+      OS << "      Record.writeBool(I->isTarget());\n";
+      OS << "      Record.writeBool(I->isTargetSync());\n";
+      OS << "      Record.writeBool(I->hasPreferAttrs());\n";
       OS << "      Record.push_back(I->Prefs.size());\n";
       OS << "      for (auto &P : I->Prefs) {\n";
       OS << "        Record.writeBool(P.Fr != nullptr);\n";
diff --git a/clang/utils/TableGen/HLSLEmitter.cpp b/clang/utils/TableGen/HLSLEmitter.cpp
index c37b7bf27df19..49bcd3bfbee21 100644
--- a/clang/utils/TableGen/HLSLEmitter.cpp
+++ b/clang/utils/TableGen/HLSLEmitter.cpp
@@ -15,6 +15,7 @@
 #include "TableGenBackends.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -238,19 +239,23 @@ struct OverloadContext {
   TypeInfo RetType;
 
   /// Per-argument metadata describing type and variation behavior.
-  SmallVector<TypeInfo, 4> Args;
+  llvm::SmallVectorWithFlags<TypeInfo, 4, 4> Args;
 
   /// Whether to emit the function as constexpr.
-  bool IsConstexpr = false;
+  bool getIsConstexpr() const { return Args.getFlag(0); }
+  void setIsConstexpr(bool Value) { Args.setFlag(0, Value); }
 
   /// Whether to emit the __attribute__((convergent)) annotation.
-  bool IsConvergent = false;
+  bool getIsConvergent() const { return Args.getFlag(1); }
+  void setIsConvergent(bool Value) { Args.setFlag(1, Value); }
 
   /// Whether any fixed arg has a 16-bit integer type (e.g. int16_t).
-  bool Uses16BitType = false;
+  bool getUses16BitType() const { return Args.getFlag(2); }
+  void setUses16BitType(bool Value) { Args.setFlag(2, Value); }
 
   /// Whether any fixed arg has a conditionally-16-bit type (half).
-  bool UsesConditionally16BitType = false;
+  bool getUsesConditionally16BitType() const { return Args.getFlag(3); }
+  void setUsesConditionally16BitType(bool Value) { Args.setFlag(3, Value); }
 
   explicit OverloadContext(raw_ostream &OS) : OS(OS) {}
 };
@@ -277,10 +282,10 @@ static void emitDeclaration(const OverloadContext &Ctx, StringRef RetType,
 
   if (!HasBody)
     OS << "_HLSL_BUILTIN_ALIAS(" << Ctx.Builtin << ")\n";
-  if (Ctx.IsConvergent)
+  if (Ctx.getIsConvergent())
     OS << "__attribute__((convergent)) ";
   if (HasBody)
-    OS << (Ctx.IsConstexpr ? "constexpr " : "inline ");
+    OS << (Ctx.getIsConstexpr() ? "constexpr " : "inline ");
   OS << RetType << " " << Ctx.FuncName << "(";
 
   {
@@ -355,15 +360,17 @@ static void buildOverloadContext(const Record *R, OverloadContext &Ctx) {
   Ctx.DetailFunc = R->getValueAsString("DetailFunc");
   Ctx.Body = R->getValueAsString("Body");
   Ctx.FuncName = R->getValueAsString("Name");
-  Ctx.IsConstexpr = R->getValueAsBit("IsConstexpr");
-  Ctx.IsConvergent = R->getValueAsBit("IsConvergent");
+  Ctx.setIsConstexpr(R->getValueAsBit("IsConstexpr"));
+  Ctx.setIsConvergent(R->getValueAsBit("IsConvergent"));
 
   // Note use of 16-bit fixed types in the overload context.
   auto Update16BitFlags = [&Ctx](const Record *Rec) {
     const Record *ElemTy = getElementTypeRecord(Rec);
-    Ctx.Uses16BitType |= ElemTy->getValueAsBit("Is16Bit");
-    Ctx.UsesConditionally16BitType |=
-        ElemTy->getValueAsBit("IsConditionally16Bit");
+    Ctx.setUses16BitType(int(Ctx.getUses16BitType()) |
+                         (ElemTy->getValueAsBit("Is16Bit")));
+    Ctx.setUsesConditionally16BitType(
+        int(Ctx.getUsesConditionally16BitType()) |
+        (ElemTy->getValueAsBit("IsConditionally16Bit")));
   };
 
   // Resolve return and argument types.
@@ -423,7 +430,8 @@ static void buildWorklist(const Record *R,
   // This is for HLSLBuiltin records that don't use Varying types.
   if (VaryingTypeRecords.empty()) {
     TypeWorkItem Item;
-    SetAvailability(Item, Ctx.Uses16BitType, Ctx.UsesConditionally16BitType);
+    SetAvailability(Item, Ctx.getUses16BitType(),
+                    Ctx.getUsesConditionally16BitType());
     Worklist.push_back(Item);
     return;
   }
@@ -437,8 +445,8 @@ static void buildWorklist(const Record *R,
   for (const Record *ElemTy : VaryingTypeRecords) {
     TypeWorkItem Item;
     Item.ElemType = ElemTy->getValueAsString("Name");
-    bool Is16Bit = Ctx.Uses16BitType || ElemTy->getValueAsBit("Is16Bit");
-    bool IsCond16Bit = Ctx.UsesConditionally16BitType ||
+    bool Is16Bit = Ctx.getUses16BitType() || ElemTy->getValueAsBit("Is16Bit");
+    bool IsCond16Bit = Ctx.getUsesConditionally16BitType() ||
                        ElemTy->getValueAsBit("IsConditionally16Bit");
     SetAvailability(Item, Is16Bit, IsCond16Bit);
     Worklist.push_back(Item);
diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index e567a27032d12..ccfeb97c7c305 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -28,6 +28,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
@@ -326,24 +327,28 @@ class Intrinsic {
   std::string TargetGuard;
   /// Set if the Unavailable bit is 1. This means we don't generate a body,
   /// just an "unavailable" attribute on a declaration.
-  bool IsUnavailable;
+  bool getIsUnavailable() const { return ImmChecks.getFlag(0); }
+  void setIsUnavailable(bool Value) { ImmChecks.setFlag(0, Value); }
   /// Is this intrinsic safe for big-endian? or does it need its arguments
   /// reversing?
-  bool BigEndianSafe;
+  bool getBigEndianSafe() const { return ImmChecks.getFlag(1); }
+  void setBigEndianSafe(bool Value) { ImmChecks.setFlag(1, Value); }
 
   /// The types of return value [0] and parameters [1..].
   std::vector<Type> Types;
 
-  SmallVector<ImmCheck, 2> ImmChecks;
+  llvm::SmallVectorWithFlags<ImmCheck, 2, 4> ImmChecks;
   /// The index of the key type passed to CGBuiltin.cpp for polymorphic calls.
   int PolymorphicKeyType;
   /// The local variables defined.
   std::map<std::string, Variable, std::less<>> Variables;
   /// NeededEarly - set if any other intrinsic depends on this intrinsic.
-  bool NeededEarly;
+  bool getNeededEarlyFlag() const { return ImmChecks.getFlag(2); }
+  void setNeededEarlyFlag(bool Value) { ImmChecks.setFlag(2, Value); }
   /// UseMacro - set if we should implement using a macro or unset for a
   ///            function.
-  bool UseMacro;
+  bool getUseMacro() const { return ImmChecks.getFlag(3); }
+  void setUseMacro(bool Value) { ImmChecks.setFlag(3, Value); }
   /// The set of intrinsics that this intrinsic uses/requires.
   std::set<Intrinsic *> Dependencies;
   /// The "base type", which is Type('d', OutTS). InBaseType is only
@@ -358,7 +363,7 @@ class Intrinsic {
   std::stringstream OS;
 
   bool isBigEndianSafe() const {
-    if (BigEndianSafe)
+    if (getBigEndianSafe())
       return true;
 
     for (const auto &T : Types){
@@ -375,9 +380,10 @@ class Intrinsic {
             bool IsUnavailable, bool BigEndianSafe)
       : R(R), Name(Name.str()), OutTS(OutTS), InTS(InTS), CK(CK), Body(Body),
         ArchGuard(ArchGuard.str()), TargetGuard(TargetGuard.str()),
-        IsUnavailable(IsUnavailable), BigEndianSafe(BigEndianSafe),
-        PolymorphicKeyType(0), NeededEarly(false), UseMacro(false),
-        BaseType(OutTS, "."), InBaseType(InTS, "."), Emitter(Emitter) {
+        ImmChecks(decltype(ImmChecks)::withFlags(
+            unsigned(IsUnavailable) | (unsigned(BigEndianSafe) << 1))),
+        PolymorphicKeyType(0), BaseType(OutTS, "."), InBaseType(InTS, "."),
+        Emitter(Emitter) {
     // Modify the TypeSpec per-argument to get a concrete Type, and create
     // known variables for each.
     // Types[0] is the return value.
@@ -404,7 +410,7 @@ class Intrinsic {
       // taking a scalar float16_t must be implemented as macros.
       if (Type.isImmediate() || Type.isPointer() ||
           (Type.isScalar() && Type.isHalf()))
-        UseMacro = true;
+        setUseMacro(true);
     }
 
     int ArgIdx, Kind, TypeArgIdx;
@@ -488,7 +494,7 @@ class Intrinsic {
 
   bool hasBody() const { return Body && !Body->empty(); }
 
-  void setNeededEarly() { NeededEarly = true; }
+  void setNeededEarly() { setNeededEarlyFlag(true); }
 
   bool operator<(const Intrinsic &Other) const {
     // Sort lexicographically on a three-tuple (ArchGuard, TargetGuard, Name)
@@ -1204,7 +1210,7 @@ void Intrinsic::initVariables() {
 }
 
 void Intrinsic::emitPrototype(StringRef NamePrefix) {
-  if (UseMacro) {
+  if (getUseMacro()) {
     OS << "#define ";
   } else {
     OS << "__ai ";
@@ -1225,7 +1231,7 @@ void Intrinsic::emitPrototype(StringRef NamePrefix) {
     assert(Variables.find(Name) != Variables.end());
     Variable &V = Variables[Name];
 
-    if (!UseMacro)
+    if (!getUseMacro())
       OS << V.getType().str() << " ";
     OS << V.getName();
   }
@@ -1234,7 +1240,7 @@ void Intrinsic::emitPrototype(StringRef NamePrefix) {
 }
 
 void Intrinsic::emitOpeningBrace() {
-  if (UseMacro)
+  if (getUseMacro())
     OS << " __extension__ ({";
   else
     OS << " {";
@@ -1242,14 +1248,14 @@ void Intrinsic::emitOpeningBrace() {
 }
 
 void Intrinsic::emitClosingBrace() {
-  if (UseMacro)
+  if (getUseMacro())
     OS << "})";
   else
     OS << "}";
 }
 
 void Intrinsic::emitNewLine() {
-  if (UseMacro)
+  if (getUseMacro())
     OS << " \\\n";
   else
     OS << "\n";
@@ -1318,7 +1324,7 @@ void Intrinsic::emitReturnReversal() {
 void Intrinsic::emitShadowedArgs() {
   // Macro arguments are not type-checked like inline function arguments,
   // so assign them to local temporaries to get the right type checking.
-  if (!UseMacro)
+  if (!getUseMacro())
     return;
 
   for (unsigned I = 0; I < getNumParams(); ++I) {
@@ -1464,7 +1470,7 @@ void Intrinsic::emitBody(StringRef CallPrefix) {
 void Intrinsic::emitReturn() {
   if (RetVar.getType().isVoid())
     return;
-  if (UseMacro)
+  if (getUseMacro())
     OS << "  " << RetVar.getName() << ";";
   else
     OS << "  return " << RetVar.getName() << ";";
@@ -1887,7 +1893,7 @@ std::string Intrinsic::generate() {
 
   // If we're needed early, create a non-swapping variant for
   // big-endian.
-  if (NeededEarly) {
+  if (getNeededEarlyFlag()) {
     generateImpl(false, "__noswap_", "__noswap_");
   }
   OS << "#endif\n\n";
@@ -1905,7 +1911,7 @@ void Intrinsic::generateImpl(bool ReverseArguments,
   //
   // indexBody() should have set up the Dependencies set by now.
   for (auto *I : Dependencies)
-    if (I->UseMacro) {
+    if (I->getUseMacro()) {
       VariablePostfix = "_" + utostr(Emitter.getUniqueNumber());
       break;
     }
@@ -1914,7 +1920,7 @@ void Intrinsic::generateImpl(bool ReverseArguments,
 
   emitPrototype(NamePrefix);
 
-  if (IsUnavailable) {
+  if (getIsUnavailable()) {
     OS << " __attribute__((unavailable));";
   } else {
     emitOpeningBrace();
diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index 0f770a3202538..4f237dc864a2e 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -25,6 +25,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/raw_ostream.h"
@@ -181,9 +182,10 @@ class Intrinsic {
 
   uint64_t Flags;
 
-  SmallVector<ImmCheck, 2> ImmChecks;
+  llvm::SmallVectorWithFlags<ImmCheck, 2> ImmChecks;
 
-  bool SetsFPMR;
+  bool getSetsFPMR() const { return ImmChecks.getFlag(0); }
+  void setSetsFPMR(bool Value) { ImmChecks.setFlag(0, Value); }
 
 public:
   Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
@@ -292,7 +294,7 @@ class Intrinsic {
 
 private:
   std::string getMergeSuffix() const { return MergeSuffix; }
-  StringRef getFPMSuffix() const { return SetsFPMR ? "_fpm" : ""; }
+  StringRef getFPMSuffix() const { return getSetsFPMR() ? "_fpm" : ""; }
   std::string mangleName(ClassKind LocalCK) const;
   std::string mangleLLVMName() const;
   std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
@@ -1041,7 +1043,7 @@ Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
     std::tie(Mod, NumVectors) = getProtoModifier(Proto, I);
     SVEType T(BaseTypeSpec, Mod, NumVectors);
     Types.push_back(T);
-    SetsFPMR = T.isFpm();
+    setSetsFPMR(T.isFpm());
 
     // Add range checks for immediates
     if (I > 0) {
@@ -1060,7 +1062,7 @@ Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
   this->Flags |= Emitter.encodeMergeType(MergeTy);
   if (hasSplat())
     this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
-  if (SetsFPMR)
+  if (getSetsFPMR())
     this->Flags |= Emitter.getEnumValueForFlag("SetsFPMR");
 }
 
diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h
index 2673e61b1a915..926c54dbf38b2 100644
--- a/flang/include/flang/Lower/CallInterface.h
+++ b/flang/include/flang/Lower/CallInterface.h
@@ -30,6 +30,7 @@
 #include "flang/Common/reference.h"
 #include "flang/Evaluate/characteristics.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <optional>
 
 namespace Fortran::semantics {
@@ -230,7 +231,7 @@ class CallInterface {
   /// Is the Fortran result passed as an extra MLIR argument ?
   bool mustPassResult() const { return passedResult.has_value(); }
   /// Must the MLIR result be saved with a fir.save_result ?
-  bool mustSaveResult() const { return saveResult; }
+  bool mustSaveResult() const { return passedArguments.getFlag(0); }
 
   /// Can the associated procedure be called via an implicit interface?
   bool canBeCalledViaImplicitInterface() const {
@@ -258,9 +259,9 @@ class CallInterface {
   llvm::SmallVector<FirPlaceHolder> outputs;
   llvm::SmallVector<FirPlaceHolder> inputs;
   mlir::func::FuncOp func;
-  llvm::SmallVector<PassedEntity> passedArguments;
+  // Flag 0 records whether the caller must save the result.
+  llvm::SmallVectorWithFlags<PassedEntity> passedArguments;
   std::optional<PassedEntity> passedResult;
-  bool saveResult = false;
 
   Fortran::lower::AbstractConverter &converter;
   /// Store characteristic once created, it is required for further information
diff --git a/flang/include/flang/Lower/PFTBuilder.h b/flang/include/flang/Lower/PFTBuilder.h
index 981a78068c658..57decbdbd2ac7 100644
--- a/flang/include/flang/Lower/PFTBuilder.h
+++ b/flang/include/flang/Lower/PFTBuilder.h
@@ -26,6 +26,7 @@
 #include "flang/Semantics/scope.h"
 #include "flang/Semantics/semantics.h"
 #include "flang/Semantics/symbol.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -420,15 +421,28 @@ struct Evaluation : EvaluationVariant {
   // Additional branch targets for multiway branches (computed GO TO,
   // arithmetic IF). Empty for single-target branches; the first target is in
   // controlSuccessor and the remaining ones are stored here in source order.
-  llvm::SmallVector<Evaluation *, 0> extraControlSuccessors;
+  llvm::SmallVectorWithFlags<Evaluation *, 0, 4> extraControlSuccessors;
   Evaluation *constructExit{nullptr};    // set for constructs
-  bool isNewBlock{false};                // evaluation begins a new basic block
+  bool getIsNewBlock() const { return extraControlSuccessors.getFlag(0); }
+  bool setIsNewBlock(bool Value) {
+    extraControlSuccessors.setFlag(0, Value);
+    return Value;
+  } // evaluation begins a new basic block
   ControlFlow controlFlow{ControlFlow::Structured};
-  bool negateCondition{false}; // If[Then]Stmt condition must be negated
-  bool activeConstruct{false}; // temporarily set for some constructs
+  bool getNegateCondition() const { return extraControlSuccessors.getFlag(1); }
+  void setNegateCondition(bool Value) {
+    extraControlSuccessors.setFlag(1, Value);
+  } // If[Then]Stmt condition must be negated
+  bool getActiveConstruct() const { return extraControlSuccessors.getFlag(2); }
+  void setActiveConstruct(bool Value) {
+    extraControlSuccessors.setFlag(2, Value);
+  } // temporarily set for some constructs
   // The enclosing evaluation-list traversal should skip this evaluation once
   // because directive lowering already consumed it.
-  bool skipNextLowering{false};
+  bool getSkipNextLowering() const { return extraControlSuccessors.getFlag(3); }
+  void setSkipNextLowering(bool Value) {
+    extraControlSuccessors.setFlag(3, Value);
+  }
   mlir::Block *block{nullptr}; // isNewBlock block (ActionStmt, ConstructStmt)
   int printIndex{0}; // (ActionStmt, ConstructStmt) evaluation index for dumps
 };
@@ -794,17 +808,31 @@ struct FunctionLikeUnit : public ProgramUnit {
   /// The primary entry point symbol is Null for an anonymous program.
   /// A named program symbol has MainProgramDetails. Other symbols have
   /// SubprogramDetails. Evaluations are filled in for alternate entries.
-  llvm::SmallVector<std::pair<const semantics::Symbol *, Evaluation *>, 1>
+  llvm::SmallVectorWithFlags<std::pair<const semantics::Symbol *, Evaluation *>,
+                             1, 4>
       entryPointList{std::pair{nullptr, nullptr}};
   /// Current index into entryPointList. Index 0 is the primary entry point.
   int activeEntry = 0;
   /// Primary result for function subprograms with alternate entries. This
   /// is one of the largest result values, not necessarily the first one.
   const semantics::Symbol *primaryResult{nullptr};
-  bool hasIeeeAccess{false};
-  bool mayModifyHaltingMode{false};
-  bool mayModifyRoundingMode{false};
-  bool mayModifyUnderflowMode{false};
+  bool getHasIeeeAccess() const { return entryPointList.getFlag(0); }
+  void setHasIeeeAccess(bool Value) { entryPointList.setFlag(0, Value); }
+  bool getMayModifyHaltingMode() const { return entryPointList.getFlag(1); }
+  bool setMayModifyHaltingMode(bool Value) {
+    entryPointList.setFlag(1, Value);
+    return Value;
+  }
+  bool getMayModifyRoundingMode() const { return entryPointList.getFlag(2); }
+  bool setMayModifyRoundingMode(bool Value) {
+    entryPointList.setFlag(2, Value);
+    return Value;
+  }
+  bool getMayModifyUnderflowMode() const { return entryPointList.getFlag(3); }
+  bool setMayModifyUnderflowMode(bool Value) {
+    entryPointList.setFlag(3, Value);
+    return Value;
+  }
   /// Terminal basic block (if any)
   mlir::Block *finalBlock{};
   HostAssociations hostAssociations;
diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index a429c3c33bed4..c84451e9c6595 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cstddef>
 #include <memory>
 #include <utility>
@@ -204,12 +205,13 @@ struct AliasAnalysis {
     /// the same derived-type variable and tracks pointer dereferences for
     /// pointer/target aliasing (Fortran 2018 8.5.7, 15.5.2.13).
     struct AccessPath {
-      llvm::SmallVector<PathStep, 4> steps;
+      llvm::SmallVectorWithFlags<PathStep, 4> steps;
 
       /// Whether the path is approximate (e.g. contains array indexing or
       /// went through PackArrayOp). An approximate path cannot yield
       /// MustAlias.
-      bool isApproximate{false};
+      bool isApproximate() const { return steps.getFlag(0); }
+      void setIsApproximate(bool value) { steps.setFlag(0, value); }
 
       /// Return true if any step is a PointerDeref.
       bool hasPointerDeref() const {
@@ -218,9 +220,7 @@ struct AliasAnalysis {
         });
       }
 
-      bool operator==(const AccessPath &o) const {
-        return isApproximate == o.isApproximate && steps == o.steps;
-      }
+      bool operator==(const AccessPath &o) const { return steps == o.steps; }
       bool operator!=(const AccessPath &o) const { return !(*this == o); }
 
       void print(llvm::raw_ostream &os) const;
@@ -288,16 +288,34 @@ struct AliasAnalysis {
     Attributes attributes;
     /// Have we lost precision following the source such that
     /// even an exact match cannot be MustAlias?
-    bool approximateSource;
+    bool getApproximateSource() const { return scopedOrigins.getFlag(0); }
+    void setApproximateSource(bool Value) { scopedOrigins.setFlag(0, Value); }
     /// The structured access path from the root variable.
     AccessPath accessPath;
     /// Source object is used in an internal procedure via host association.
-    bool isCapturedInInternalProcedure{false};
+    bool getIsCapturedInInternalProcedure() const {
+      return scopedOrigins.getFlag(1);
+    }
+    void setIsCapturedInInternalProcedure(bool Value) {
+      scopedOrigins.setFlag(1, Value);
+    }
     /// Per-declare checkpoints collected as getSource() walked through
     /// [hl]fir.declare operations, ordered from leaf-closest (front) to
     /// root-closest (back). Empty when no declare was crossed (e.g. the
     /// walk terminated at Unknown).
-    llvm::SmallVector<ScopedOrigin, 4> scopedOrigins;
+    llvm::SmallVectorWithFlags<ScopedOrigin, 4, 2> scopedOrigins;
+
+    Source() = default;
+    Source(SourceOrigin origin, SourceKind kind, mlir::Type valueType,
+           Attributes attributes, bool approximateSource,
+           AccessPath accessPath = {},
+           bool isCapturedInInternalProcedure = false,
+           llvm::SmallVector<ScopedOrigin, 4> scopedOrigins = {})
+        : origin(origin), kind(kind), valueType(valueType),
+          attributes(attributes), accessPath(std::move(accessPath)),
+          scopedOrigins(unsigned(approximateSource) |
+                            (unsigned(isCapturedInInternalProcedure) << 1),
+                        std::move(scopedOrigins)) {}
 
     /// Print information about the memory source to `os`.
     void print(llvm::raw_ostream &os) const;
@@ -581,11 +599,19 @@ class AliasAnalysisRecursiveEffectsCache {
   };
 
   struct Summary {
-    bool hasUnknownWrite = false;
-    bool hasUnknownRead = false;
+    bool getHasUnknownWrite() const { return calls.getFlag(0); }
+    bool setHasUnknownWrite(bool Value) {
+      calls.setFlag(0, Value);
+      return Value;
+    }
+    bool getHasUnknownRead() const { return calls.getFlag(1); }
+    bool setHasUnknownRead(bool Value) {
+      calls.setFlag(1, Value);
+      return Value;
+    }
     llvm::SmallVector<mlir::Value, 16> writeLocations;
     llvm::SmallVector<mlir::Value, 16> readLocations;
-    llvm::SmallVector<CallInfo, 4> calls;
+    llvm::SmallVectorWithFlags<CallInfo, 4, 2> calls;
   };
 
   /// Populate `out` with the effects of `op` itself and, if op has
diff --git a/flang/include/flang/Optimizer/Builder/TemporaryStorage.h b/flang/include/flang/Optimizer/Builder/TemporaryStorage.h
index e1edc5912ae97..ca764d44fe564 100644
--- a/flang/include/flang/Optimizer/Builder/TemporaryStorage.h
+++ b/flang/include/flang/Optimizer/Builder/TemporaryStorage.h
@@ -21,6 +21,7 @@
 
 #include "flang/Common/idioms.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace fir {
 class FirOpBuilder;
@@ -122,9 +123,15 @@ class ArrayTemp {
   bool canBeFetchedAfterPush() const { return true; }
 
 private:
-  const bool allocateOnHeap;
+  bool getAllocateOnHeap() const { return typeParams.getFlag(0); }
   mlir::Value temp;
-  llvm::SmallVector<mlir::Value> typeParams;
+  llvm::SmallVectorWithFlags<mlir::Value> typeParams;
+
+public:
+  ArrayTemp(const ArrayTemp &) = default;
+  ArrayTemp(ArrayTemp &&) = default;
+  ArrayTemp &operator=(const ArrayTemp &) = delete;
+  ArrayTemp &operator=(ArrayTemp &&) = delete;
 };
 
 /// Structure to hold the value of a single entity.
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index e52e690ab4b64..aef5fcddef6e7 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Lower/Bridge.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "flang/Evaluate/tools.h"
 #include "flang/Lower/Allocatable.h"
@@ -101,7 +102,8 @@ struct IncrementLoopInfo {
       : loopVariableSym{&sym}, lowerExpr{Fortran::semantics::GetExpr(lower)},
         upperExpr{Fortran::semantics::GetExpr(upper)},
         stepExpr{Fortran::semantics::GetExpr(step)},
-        isConcurrent{isConcurrent} {}
+        sharedSymList(
+            decltype(this->sharedSymList)::withFlags(unsigned(isConcurrent))) {}
 
   IncrementLoopInfo(IncrementLoopInfo &&) = default;
   IncrementLoopInfo &operator=(IncrementLoopInfo &&x) = default;
@@ -124,19 +126,25 @@ struct IncrementLoopInfo {
   const Fortran::lower::SomeExpr *upperExpr;
   const Fortran::lower::SomeExpr *stepExpr;
   const Fortran::lower::SomeExpr *maskExpr = nullptr;
-  bool isConcurrent;
+  bool getIsConcurrent() const { return sharedSymList.getFlag(0); }
+  void setIsConcurrent(bool Value) { sharedSymList.setFlag(0, Value); }
   llvm::SmallVector<const Fortran::semantics::Symbol *> localSymList;
   llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
   llvm::SmallVector<const Fortran::semantics::Symbol *> reduceSymList;
   llvm::SmallVector<fir::ReduceOperationEnum> reduceOperatorList;
-  llvm::SmallVector<const Fortran::semantics::Symbol *> sharedSymList;
+  llvm::SmallVectorWithFlags<const Fortran::semantics::Symbol *,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 const Fortran::semantics::Symbol *>::value,
+                             2>
+      sharedSymList;
   mlir::Value loopVariable = nullptr;
 
   // Data members for structured loops.
   mlir::Operation *loopOp = nullptr;
 
   // Data members for unstructured loops.
-  bool hasRealControl = false;
+  bool getHasRealControl() const { return sharedSymList.getFlag(1); }
+  void setHasRealControl(bool Value) { sharedSymList.setFlag(1, Value); }
   mlir::Value tripVariable = nullptr;
   mlir::Value stepVariable = nullptr;
   mlir::Block *headerBlock = nullptr; // loop entry and test block
@@ -1845,7 +1853,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   getActiveAncestor(const Fortran::lower::pft::Evaluation &eval) {
     Fortran::lower::pft::Evaluation *ancestor = eval.parentConstruct;
     for (; ancestor; ancestor = ancestor->parentConstruct)
-      if (ancestor->activeConstruct)
+      if (ancestor->getActiveConstruct())
         break;
     return ancestor;
   }
@@ -2040,11 +2048,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   void pushActiveConstruct(Fortran::lower::pft::Evaluation &eval,
                            Fortran::lower::StatementContext &stmtCtx) {
     activeConstructStack.push_back(ConstructContext{eval, stmtCtx});
-    eval.activeConstruct = true;
+    eval.setActiveConstruct(true);
   }
   void popActiveConstruct() {
     assert(!activeConstructStack.empty() && "invalid active construct stack");
-    activeConstructStack.back().eval.activeConstruct = false;
+    activeConstructStack.back().eval.setActiveConstruct(false);
     if (activeConstructStack.back().pushedScope)
       localSymbols.popScope();
     activeConstructStack.pop_back();
@@ -2952,8 +2960,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       if (unstructuredContext) {
         maybeStartBlock(preheaderBlock);
         maybeWrapAndRecalc();
-        info.hasRealControl = info.loopVariableSym->GetType()->IsNumeric(
-            Fortran::common::TypeCategory::Real);
+        info.setHasRealControl(info.loopVariableSym->GetType()->IsNumeric(
+            Fortran::common::TypeCategory::Real));
         info.headerBlock = headerBlock;
         info.bodyBlock = bodyBlock;
         info.exitBlock = exitBlock;
@@ -2993,7 +3001,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     // Introduce a `do concurrent` scope to bind symbols corresponding to local,
     // local_init, and reduce region arguments.
     if (!incrementLoopNestInfo.empty() &&
-        incrementLoopNestInfo.back().isConcurrent)
+        incrementLoopNestInfo.back().getIsConcurrent())
       localSymbols.pushScope();
 
     // Increment loop begin code. (Infinite/while code was already generated.)
@@ -3031,7 +3039,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         attachAccessGroupAttrToDoLoopOperations(loopOp);
 
     if (!incrementLoopNestInfo.empty() &&
-        incrementLoopNestInfo.back().isConcurrent)
+        incrementLoopNestInfo.back().getIsConcurrent())
       localSymbols.popScope();
 
     // Add attribute(s) on operations in fir::DoLoopOp if necessary
@@ -3047,7 +3055,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                               const IncrementLoopInfo &info,
                               bool *isConst = nullptr) {
     mlir::Location loc = toLocation();
-    mlir::Type controlType = info.isStructured() && info.isConcurrent
+    mlir::Type controlType = info.isStructured() && info.getIsConcurrent()
                                  ? builder->getIndexType()
                                  : info.getLoopVariableType();
     Fortran::lower::StatementContext stmtCtx;
@@ -3060,7 +3068,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
     if (isConst)
       *isConst = true;
-    if (info.hasRealControl)
+    if (info.getHasRealControl())
       return builder->createRealConstant(loc, controlType, 1u);
     return builder->createIntegerConstant(loc, controlType, 1); // step
   }
@@ -3096,11 +3104,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     bool genDoConcurrent = false;
 
     for (IncrementLoopInfo &info : incrementLoopNestInfo) {
-      genDoConcurrent = info.isStructured() && info.isConcurrent;
+      genDoConcurrent = info.isStructured() && info.getIsConcurrent();
 
       if (!genDoConcurrent)
         info.loopVariable = genLoopVariableAddress(loc, *info.loopVariableSym,
-                                                   info.isConcurrent);
+                                                   info.getIsConcurrent());
 
       if (!getLoweringOptions().getIntegerWrapAround()) {
         iofBackup = builder->getIntegerOverflowFlags();
@@ -3150,7 +3158,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
       // Unstructured loop preheader - initialize tripVariable and loopVariable.
       mlir::Value tripCount;
-      if (info.hasRealControl) {
+      if (info.getHasRealControl()) {
         auto diff1 =
             mlir::arith::SubFOp::create(*builder, loc, upperValue, lowerValue);
         auto diff2 =
@@ -3216,7 +3224,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
       for (IncrementLoopInfo &info : llvm::reverse(incrementLoopNestInfo)) {
         info.loopVariable = genLoopVariableAddress(loc, *info.loopVariableSym,
-                                                   info.isConcurrent);
+                                                   info.getIsConcurrent());
       }
 
       builder->setInsertionPointToEnd(loopWrapperOp.getBody());
@@ -3279,7 +3287,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       IncrementLoopInfo &info = *it;
       if (info.isStructured()) {
         // End fir.do_concurent.loop.
-        if (info.isConcurrent) {
+        if (info.getIsConcurrent()) {
           builder->setInsertionPointAfter(info.loopOp->getParentOp());
           continue;
         }
@@ -3325,7 +3333,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         step = fir::LoadOp::create(*builder, loc, info.stepVariable);
       else
         step = genControlValue(info.stepExpr, info);
-      if (info.hasRealControl)
+      if (info.getHasRealControl())
         value = mlir::arith::AddFOp::create(*builder, loc, value, step);
       else
         value =
@@ -3358,9 +3366,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         };
         setCurrentPosition(e.position);
         if (auto *s = e.getIf<Fortran::parser::IfThenStmt>()) {
-          topIfOp = currentIfOp = genIfOp(genIfCondition(s, e.negateCondition));
+          topIfOp = currentIfOp =
+              genIfOp(genIfCondition(s, e.getNegateCondition()));
         } else if (auto *s = e.getIf<Fortran::parser::IfStmt>()) {
-          topIfOp = currentIfOp = genIfOp(genIfCondition(s, e.negateCondition));
+          topIfOp = currentIfOp =
+              genIfOp(genIfCondition(s, e.getNegateCondition()));
         } else if (auto *s = e.getIf<Fortran::parser::ElseIfStmt>()) {
           builder->setInsertionPointToStart(
               &currentIfOp.getElseRegion().front());
@@ -3420,10 +3430,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       setCurrentPosition(e.position);
       if (auto *s = e.getIf<Fortran::parser::IfThenStmt>()) {
         maybeStartBlock(e.block);
-        genIfBranch(genIfCondition(s, e.negateCondition));
+        genIfBranch(genIfCondition(s, e.getNegateCondition()));
       } else if (auto *s = e.getIf<Fortran::parser::IfStmt>()) {
         maybeStartBlock(e.block);
-        genIfBranch(genIfCondition(s, e.negateCondition));
+        genIfBranch(genIfCondition(s, e.getNegateCondition()));
       } else if (auto *s = e.getIf<Fortran::parser::ElseIfStmt>()) {
         startBlock(e.block);
         genIfBranch(genIfCondition(s));
@@ -4369,8 +4379,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     builder->restoreInsertionPoint(insertPt);
 
     // Register if a target region was found
-    ompDeviceCodeFound =
-        ompDeviceCodeFound || Fortran::lower::isOpenMPTargetConstruct(omp);
+    setOmpDeviceCodeFound(getOmpDeviceCodeFound() ||
+                          Fortran::lower::isOpenMPTargetConstruct(omp));
   }
 
   void genFIR(const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl) {
@@ -4378,10 +4388,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
     // Register if a declare target construct intended for a target device was
     // found
-    ompDeviceCodeFound =
-        ompDeviceCodeFound ||
+    setOmpDeviceCodeFound(
+        getOmpDeviceCodeFound() ||
         Fortran::lower::isOpenMPDeviceDeclareTarget(
-            *this, bridge.getSemanticsContext(), getEval(), ompDecl);
+            *this, bridge.getSemanticsContext(), getEval(), ompDecl));
     Fortran::lower::gatherOpenMPDeferredDeclareTargets(
         *this, bridge.getSemanticsContext(), getEval(), ompDecl,
         ompDeferredDeclareTarget);
@@ -6318,8 +6328,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                           ? eval.getFirstNestedEvaluation().block
                           : eval.block);
 
-    if (eval.skipNextLowering) {
-      eval.skipNextLowering = false;
+    if (eval.getSkipNextLowering()) {
+      eval.setSkipNextLowering(false);
       return;
     }
 
@@ -6418,7 +6428,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     mlir::Location loc = toLocation();
     mlir::Location endLoc =
         toLocation(Fortran::lower::pft::stmtSourceLoc(funit.endStmt));
-    if (funit.hasIeeeAccess) {
+    if (funit.getHasIeeeAccess()) {
       // Subject to F18 Clause 17.1p3, 17.3p3 states: If a flag is signaling
       // on entry to a procedure [...], the processor will set it to quiet
       // on entry and restore it to signaling on return. If a flag signals
@@ -6436,7 +6446,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         fir::CallOp::create(*builder, endLoc, raiseExcept, exceptSet);
       });
     }
-    if (funit.mayModifyHaltingMode) {
+    if (funit.getMayModifyHaltingMode()) {
       // F18 Clause 17.6p1: In a procedure [...], the processor shall not
       // change the halting mode on entry, and on return shall ensure that
       // the halting mode is the same as it was on entry.
@@ -6454,7 +6464,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         fir::CallOp::create(*builder, endLoc, enableExcept, exceptSet);
       });
     }
-    if (funit.mayModifyRoundingMode) {
+    if (funit.getMayModifyRoundingMode()) {
       // F18 Clause 17.4p5: In a procedure [...], the processor shall not
       // change the rounding modes on entry, and on return shall ensure that
       // the rounding modes are the same as they were on entry.
@@ -6468,7 +6478,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         fir::CallOp::create(*builder, endLoc, setRounding, roundingMode);
       });
     }
-    if ((funit.mayModifyUnderflowMode) &&
+    if ((funit.getMayModifyUnderflowMode()) &&
         (bridge.getTargetCharacteristics().hasSubnormalFlushingControl(
             /*any=*/true))) {
       // F18 Clause 17.5p2: In a procedure [...], the processor shall not
@@ -6718,7 +6728,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           evaluationList) {
     mlir::Region *region = &builder->getRegion();
     for (Fortran::lower::pft::Evaluation &eval : evaluationList) {
-      if (eval.isNewBlock)
+      if (eval.getIsNewBlock())
         eval.block = builder->createBlock(region);
       if (eval.isConstruct() || eval.isDirective()) {
         if (Fortran::lower::pft::isWrappableConstruct(
@@ -6728,7 +6738,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           if (eval.hasNestedEvaluations()) {
             Fortran::lower::pft::Evaluation &constructStmt =
                 eval.getFirstNestedEvaluation();
-            if (constructStmt.isNewBlock)
+            if (constructStmt.getIsNewBlock())
               constructStmt.block = builder->createBlock(region);
           }
         } else if (eval.lowerAsUnstructured()) {
@@ -6737,7 +6747,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           // A structured construct that is a target starts a new block.
           Fortran::lower::pft::Evaluation &constructStmt =
               eval.getFirstNestedEvaluation();
-          if (constructStmt.isNewBlock)
+          if (constructStmt.getIsNewBlock())
             constructStmt.block = builder->createBlock(region);
         }
       }
@@ -7126,11 +7136,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       bool deferredDeviceFuncFound =
           Fortran::lower::markOpenMPDeferredDeclareTargetFunctions(
               getModuleOp().getOperation(), ompDeferredDeclareTarget, *this);
-      ompDeviceCodeFound = ompDeviceCodeFound || deferredDeviceFuncFound;
+      setOmpDeviceCodeFound(getOmpDeviceCodeFound() || deferredDeviceFuncFound);
     }
 
     // Set the module attribute related to OpenMP requires directives
-    if (ompDeviceCodeFound) {
+    if (getOmpDeviceCodeFound()) {
       for (const Fortran::semantics::Symbol *sym : globalOmpRequiresSymbol)
         Fortran::lower::genOpenMPRequires(getModuleOp().getOperation(), sym);
     }
@@ -7229,7 +7239,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   llvm::DenseMap<const Fortran::lower::SomeExpr *, std::string> literalNamesMap;
 
   /// Storage for Constant expressions used as keys for literalNamesMap.
-  llvm::SmallVector<std::unique_ptr<Fortran::lower::SomeExpr>>
+  llvm::SmallVectorWithFlags<std::unique_ptr<Fortran::lower::SomeExpr>>
       literalExprsStorage;
 
   /// A counter for uniquing names in `literalNamesMap`.
@@ -7237,7 +7247,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
   /// Whether an OpenMP target region or declare target function/subroutine
   /// intended for device offloading has been detected
-  bool ompDeviceCodeFound = false;
+  bool getOmpDeviceCodeFound() const { return literalExprsStorage.getFlag(0); }
+  void setOmpDeviceCodeFound(bool Value) {
+    literalExprsStorage.setFlag(0, Value);
+  }
 
   /// Keeps track of symbols defined as declare target that could not be
   /// processed at the time of lowering the declare target construct, such
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index ee6ee38f165f9..09d4706695da8 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -570,7 +570,7 @@ Fortran::lower::CallerInterface::getDummySymbol(
 mlir::Type Fortran::lower::CallerInterface::getResultStorageType() const {
   if (passedResult)
     return fir::dyn_cast_ptrEleTy(inputs[passedResult->firArgument].type);
-  assert(saveResult && !outputs.empty());
+  assert(mustSaveResult() && !outputs.empty());
   return outputs[0].type;
 }
 
@@ -1484,7 +1484,7 @@ class Fortran::lower::CallInterfaceImpl {
     interface.passedResult =
         PassedEntity{p, entity, emptyValue(), emptyValue()};
   }
-  void setSaveResult() { interface.saveResult = true; }
+  void setSaveResult() { interface.passedArguments.setFlag(0, true); }
   int nextPassedArgPosition() { return interface.passedArguments.size(); }
 
   static FirValue emptyValue() {
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index b1f29bb23361f..4f03e7beda399 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -12,6 +12,7 @@
 
 #include "ClauseProcessor.h"
 #include "Utils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "flang/Lower/ConvertCall.h"
 #include "flang/Lower/ConvertExprToHLFIR.h"
@@ -1230,34 +1231,39 @@ class TypeInfo {
   llvm::ArrayRef<int64_t> getShape() const { return shape; }
 
   // Is the type inside a box?
-  bool isBox() const { return inBox; }
+  bool isBox() const { return getInBox(); }
 
-  bool isBoxChar() const { return inBoxChar; }
+  bool isBoxChar() const { return getInBoxChar(); }
 
 private:
   void typeScan(mlir::Type type);
 
   std::optional<fir::CharacterType::LenType> charLen;
-  llvm::SmallVector<int64_t> shape;
-  bool inBox = false;
-  bool inBoxChar = false;
+  llvm::SmallVectorWithFlags<
+      int64_t, llvm::CalculateSmallVectorDefaultInlinedElements<int64_t>::value,
+      2>
+      shape;
+  bool getInBox() const { return shape.getFlag(0); }
+  void setInBox(bool Value) { shape.setFlag(0, Value); }
+  bool getInBoxChar() const { return shape.getFlag(1); }
+  void setInBoxChar(bool Value) { shape.setFlag(1, Value); }
 };
 
 void TypeInfo::typeScan(mlir::Type ty) {
   if (auto sty = mlir::dyn_cast<fir::SequenceType>(ty)) {
     assert(shape.empty() && !sty.getShape().empty());
-    shape = llvm::SmallVector<int64_t>(sty.getShape());
+    shape.assign(llvm::SmallVector<int64_t>(sty.getShape()));
     typeScan(sty.getEleTy());
   } else if (auto bty = mlir::dyn_cast<fir::BoxType>(ty)) {
-    inBox = true;
+    setInBox(true);
     typeScan(bty.getEleTy());
   } else if (auto cty = mlir::dyn_cast<fir::ClassType>(ty)) {
-    inBox = true;
+    setInBox(true);
     typeScan(cty.getEleTy());
   } else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
     charLen = cty.getLen();
   } else if (auto cty = mlir::dyn_cast<fir::BoxCharType>(ty)) {
-    inBoxChar = true;
+    setInBoxChar(true);
     typeScan(cty.getEleTy());
   } else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
     typeScan(hty.getEleTy());
@@ -1271,7 +1277,7 @@ void TypeInfo::typeScan(mlir::Type ty) {
     assert(ty.isIntOrIndexOrFloat() || mlir::isa<mlir::ComplexType>(ty) ||
            mlir::isa<fir::LogicalType>(ty) || mlir::isa<fir::RecordType>(ty) ||
            mlir::isa<fir::BoxProcType>(ty) ||
-           (inBox && mlir::isa<mlir::NoneType>(ty)));
+           (getInBox() && mlir::isa<mlir::NoneType>(ty)));
   }
 }
 
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 98561803ea8bb..89db551a9ce8c 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -72,11 +72,12 @@ DataSharingProcessor::DataSharingProcessor(
     bool shouldCollectPreDeterminedSymbols, bool useDelayedPrivatization,
     lower::SymMap &symTable, bool isTargetPrivatization,
     llvm::ArrayRef<const semantics::Symbol *> metadirectiveLoopIVs)
-    : converter(converter), semaCtx(semaCtx),
+    : loopIVs(decltype(this->loopIVs)::withFlags(
+          (unsigned(shouldCollectPreDeterminedSymbols) << 1) |
+          (unsigned(useDelayedPrivatization) << 2))),
+      converter(converter), semaCtx(semaCtx),
       firOpBuilder(converter.getFirOpBuilder()), clauses(clauses), eval(eval),
-      shouldCollectPreDeterminedSymbols(shouldCollectPreDeterminedSymbols),
-      useDelayedPrivatization(useDelayedPrivatization), symTable(symTable),
-      isTargetPrivatization(isTargetPrivatization),
+      symTable(symTable), isTargetPrivatization(isTargetPrivatization),
       isMetadirectiveLoop(!metadirectiveLoopIVs.empty()) {}
 
 DataSharingProcessor::DataSharingProcessor(lower::AbstractConverter &converter,
@@ -128,7 +129,7 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) {
 void DataSharingProcessor::insertDeallocs() {
   for (const semantics::Symbol *sym : allPrivatizedSymbols)
     if (semantics::IsAllocatable(sym->GetUltimate())) {
-      if (!useDelayedPrivatization) {
+      if (!getUseDelayedPrivatization()) {
         converter.createHostAssociateVarCloneDealloc(*sym);
         continue;
       }
@@ -336,10 +337,10 @@ void DataSharingProcessor::collectSymbolsForPrivatization() {
   // standard lastprivate copy-back suppressed (see copyLastPrivateSymbol /
   // insertLastPrivateCompare) in favor of the conditional copy-back.
   for (auto *sym : explicitlyPrivatizedSymbols)
-    if (!isException(sym) && (conditionalLpUsesPrivateCopy ||
+    if (!isException(sym) && (getConditionalLpUsesPrivateCopyFlag() ||
                               !conditionalLastPrivatizedSymbols.contains(sym)))
       allPrivatizedSymbols.insert(sym);
-  if (conditionalLpUsesPrivateCopy)
+  if (getConditionalLpUsesPrivateCopyFlag())
     for (auto *sym : conditionalLastPrivatizedSymbols)
       if (!isException(sym))
         allPrivatizedSymbols.insert(sym);
@@ -373,7 +374,7 @@ void DataSharingProcessor::insertBarrier(
   if (!needBarrier())
     return;
 
-  if (useDelayedPrivatization) {
+  if (getUseDelayedPrivatization()) {
     if (clauseOps)
       clauseOps->privateNeedsBarrier =
           mlir::UnitAttr::get(&converter.getMLIRContext());
@@ -655,7 +656,7 @@ void DataSharingProcessor::collectImplicitSymbols() {
 }
 
 void DataSharingProcessor::collectPreDeterminedSymbols() {
-  if (shouldCollectPreDeterminedSymbols)
+  if (getShouldCollectPreDeterminedSymbols())
     collectSymbols(semantics::Symbol::Flag::OmpPreDetermined);
 }
 
@@ -664,7 +665,7 @@ void DataSharingProcessor::collectPreDeterminedSymbols() {
 // enclosing context, to avoid updating the wrong symbol.
 void DataSharingProcessor::collectIndirectReferences() {
   // For compound constructs, collect the symbols only for the last leaf.
-  if (!shouldCollectPreDeterminedSymbols)
+  if (!getShouldCollectPreDeterminedSymbols())
     return;
 
   const semantics::Scope *curScope = getCurrentScope(semaCtx, eval);
@@ -749,7 +750,7 @@ void DataSharingProcessor::privatizeSymbol(
     const semantics::Symbol *symToPrivatize,
     mlir::omp::PrivateClauseOps *clauseOps,
     std::optional<llvm::omp::Directive> dir) {
-  if (!useDelayedPrivatization) {
+  if (!getUseDelayedPrivatization()) {
     cloneSymbol(symToPrivatize);
     copyFirstPrivateSymbol(symToPrivatize);
     return;
@@ -759,7 +760,7 @@ void DataSharingProcessor::privatizeSymbol(
                                   mlir::omp::PrivateClauseOps>(
       converter, firOpBuilder, symTable, allPrivatizedSymbols,
       mightHaveReadHostSym, symToPrivatize, clauseOps, dir,
-      forceHeapAllocationForPrivateDynamicArrays);
+      getForceHeapAllocationForPrivateDynamicArraysFlag());
 }
 } // namespace omp
 } // namespace lower
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
index 73044c304800b..276063867da2e 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
@@ -19,6 +19,7 @@
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/symbol.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <variant>
 
 namespace mlir {
@@ -34,7 +35,10 @@ namespace omp {
 class DataSharingProcessor {
 private:
   mlir::OpBuilder::InsertPoint lastPrivIP;
-  llvm::SmallVector<mlir::Value> loopIVs;
+  llvm::SmallVectorWithFlags<
+      mlir::Value,
+      llvm::CalculateSmallVectorDefaultInlinedElements<mlir::Value>::value, 4>
+      loopIVs;
   // Symbols in private, firstprivate, and/or lastprivate clauses.
   llvm::SetVector<const semantics::Symbol *> explicitlyPrivatizedSymbols;
   llvm::SetVector<const semantics::Symbol *> defaultSymbols;
@@ -46,16 +50,32 @@ class DataSharingProcessor {
   // nonmonotonic schedule can execute chunks out of order.  When false the list
   // item is bound directly to the reduction struct (used by sections, which are
   // lexically ordered and never need the private copy).
-  bool conditionalLpUsesPrivateCopy = false;
+  bool getConditionalLpUsesPrivateCopyFlag() const {
+    return loopIVs.getFlag(0);
+  }
+  void setConditionalLpUsesPrivateCopyFlag(bool Value) {
+    loopIVs.setFlag(0, Value);
+  }
 
   lower::AbstractConverter &converter;
   semantics::SemanticsContext &semaCtx;
   fir::FirOpBuilder &firOpBuilder;
   omp::List<omp::Clause> clauses;
   lower::pft::Evaluation &eval;
-  bool shouldCollectPreDeterminedSymbols;
-  bool useDelayedPrivatization;
-  bool forceHeapAllocationForPrivateDynamicArrays = false;
+  bool getShouldCollectPreDeterminedSymbols() const {
+    return loopIVs.getFlag(1);
+  }
+  void setShouldCollectPreDeterminedSymbols(bool Value) {
+    loopIVs.setFlag(1, Value);
+  }
+  bool getUseDelayedPrivatization() const { return loopIVs.getFlag(2); }
+  void setUseDelayedPrivatization(bool Value) { loopIVs.setFlag(2, Value); }
+  bool getForceHeapAllocationForPrivateDynamicArraysFlag() const {
+    return loopIVs.getFlag(3);
+  }
+  void setForceHeapAllocationForPrivateDynamicArraysFlag(bool Value) {
+    loopIVs.setFlag(3, Value);
+  }
   llvm::SmallPtrSet<const semantics::Symbol *, 16> mightHaveReadHostSym;
   lower::SymMap &symTable;
   bool isTargetPrivatization;
@@ -130,7 +150,7 @@ class DataSharingProcessor {
   void pushLoopIV(mlir::Value iv) { loopIVs.push_back(iv); }
 
   void setForceHeapAllocationForPrivateDynamicArrays(bool value = true) {
-    forceHeapAllocationForPrivateDynamicArrays = value;
+    setForceHeapAllocationForPrivateDynamicArraysFlag(value);
   }
 
   const llvm::SetVector<const semantics::Symbol *> &
@@ -139,7 +159,7 @@ class DataSharingProcessor {
   }
 
   llvm::ArrayRef<const semantics::Symbol *> getDelayedPrivSymbols() const {
-    return useDelayedPrivatization
+    return getUseDelayedPrivatization()
                ? allPrivatizedSymbols.getArrayRef()
                : llvm::ArrayRef<const semantics::Symbol *>();
   }
@@ -154,7 +174,7 @@ class DataSharingProcessor {
   }
 
   void setConditionalLpUsesPrivateCopy(bool v) {
-    conditionalLpUsesPrivateCopy = v;
+    setConditionalLpUsesPrivateCopyFlag(v);
   }
 };
 
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 57978826c5d01..e674c0c3559be 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Lower/OpenMP.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "Atomic.h"
 #include "ClauseProcessor.h"
@@ -334,17 +335,17 @@ class HostEvalInfo {
   ///          evaluated in the host device.
   bool apply(mlir::omp::LoopNestOperands &clauseOps,
              llvm::SmallVectorImpl<const semantics::Symbol *> &ivOut) {
-    if (iv.empty() || loopNestApplied) {
-      loopNestApplied = true;
+    if (iv.empty() || getLoopNestApplied()) {
+      setLoopNestApplied(true);
       return false;
     }
 
-    loopNestApplied = true;
+    setLoopNestApplied(true);
     clauseOps.loopLowerBounds = ops.loopLowerBounds;
     clauseOps.loopUpperBounds = ops.loopUpperBounds;
     clauseOps.loopSteps = ops.loopSteps;
     clauseOps.collapseNumLoops = ops.collapseNumLoops;
-    ivOut.append(iv);
+    ivOut.append(iv.begin(), iv.end());
     return true;
   }
 
@@ -354,12 +355,12 @@ class HostEvalInfo {
   /// \returns whether an update was performed. If not, these clauses were not
   ///          evaluated in the host device.
   bool apply(mlir::omp::ParallelOperands &clauseOps) {
-    if (ops.numThreadsVars.empty() || parallelApplied) {
-      parallelApplied = true;
+    if (ops.numThreadsVars.empty() || getParallelApplied()) {
+      setParallelApplied(true);
       return false;
     }
 
-    parallelApplied = true;
+    setParallelApplied(true);
     clauseOps.numThreadsVars = ops.numThreadsVars;
     return true;
   }
@@ -382,8 +383,15 @@ class HostEvalInfo {
 
 private:
   mlir::omp::HostEvaluatedOperands ops;
-  llvm::SmallVector<const semantics::Symbol *> iv;
-  bool loopNestApplied = false, parallelApplied = false;
+  llvm::SmallVectorWithFlags<const semantics::Symbol *,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 const semantics::Symbol *>::value,
+                             2>
+      iv;
+  bool getLoopNestApplied() const { return iv.getFlag(0); }
+  void setLoopNestApplied(bool Value) { iv.setFlag(0, Value); }
+  bool getParallelApplied() const { return iv.getFlag(1); }
+  void setParallelApplied(bool Value) { iv.setFlag(1, Value); }
 };
 
 /// A base class to help iterate over OpenMP constructs based on an expected
@@ -629,10 +637,14 @@ class HostEvalVisitor : public TargetSPMDVisitor {
     case OMPD_distribute:
     case OMPD_distribute_simd:
     case OMPD_do:
-    case OMPD_do_simd:
+    case OMPD_do_simd: {
+      llvm::SmallVector<const semantics::Symbol *> InductionVariables;
+      InductionVariables = std::move(hostEvalInfo.iv);
       cp.processCollapse(loc, eval, hostEvalInfo.ops, hostEvalInfo.ops,
-                         hostEvalInfo.iv);
+                         InductionVariables);
+      hostEvalInfo.iv.assign(std::move(InductionVariables));
       return {};
+    }
 
     case OMPD_teams:
       cp.processThreadLimit(stmtCtx, hostEvalInfo.ops);
@@ -646,11 +658,15 @@ class HostEvalVisitor : public TargetSPMDVisitor {
       cp.processThreadLimit(stmtCtx, hostEvalInfo.ops);
       [[fallthrough]];
     case OMPD_target_teams_distribute:
-    case OMPD_target_teams_distribute_simd:
+    case OMPD_target_teams_distribute_simd: {
+      llvm::SmallVector<const semantics::Symbol *> InductionVariables;
+      InductionVariables = std::move(hostEvalInfo.iv);
       cp.processCollapse(loc, eval, hostEvalInfo.ops, hostEvalInfo.ops,
-                         hostEvalInfo.iv);
+                         InductionVariables);
+      hostEvalInfo.iv.assign(std::move(InductionVariables));
       cp.processNumTeams(stmtCtx, hostEvalInfo.ops);
       return {};
+    }
 
     case OMPD_teams_loop:
       cp.processThreadLimit(stmtCtx, hostEvalInfo.ops);
@@ -658,10 +674,14 @@ class HostEvalVisitor : public TargetSPMDVisitor {
     case OMPD_target_teams_loop:
       cp.processNumTeams(stmtCtx, hostEvalInfo.ops);
       [[fallthrough]];
-    case OMPD_loop:
+    case OMPD_loop: {
+      llvm::SmallVector<const semantics::Symbol *> InductionVariables;
+      InductionVariables = std::move(hostEvalInfo.iv);
       cp.processCollapse(loc, eval, hostEvalInfo.ops, hostEvalInfo.ops,
-                         hostEvalInfo.iv);
+                         InductionVariables);
+      hostEvalInfo.iv.assign(std::move(InductionVariables));
       return {};
+    }
 
     case OMPD_teams_workdistribute:
       cp.processThreadLimit(stmtCtx, hostEvalInfo.ops);
@@ -7058,23 +7078,23 @@ struct SplicedAssociatedEvaluations {
     // A saved successor may also have been spliced. Restore in reverse order
     // so every insertion point is back in the parent list before it is used.
     for (auto &entry : llvm::reverse(evaluations)) {
-      entry.first->skipNextLowering = true;
+      entry.first->setSkipNextLowering(true);
       parentList->splice(entry.second, nested, entry.first);
     }
     if (entryEvaluation) {
-      entryEvaluation->isNewBlock = true;
+      entryEvaluation->setIsNewBlock(true);
       entryEvaluation->block = entryBlock;
     }
   }
 
   void suppressEntryBlock(lower::pft::Evaluation &evaluation) {
-    assert(!entryEvaluation && evaluation.isNewBlock && evaluation.block &&
+    assert(!entryEvaluation && evaluation.getIsNewBlock() && evaluation.block &&
            "invalid associated entry evaluation");
     // Do not let either cloned loop arm enter a function-region block. The
     // metadirective selection will be placed in this block for an active ENTRY.
     entryEvaluation = &evaluation;
     entryBlock = evaluation.block;
-    evaluation.isNewBlock = false;
+    evaluation.setIsNewBlock(false);
     evaluation.block = nullptr;
   }
 
@@ -7199,13 +7219,13 @@ static lower::pft::Evaluation *spliceAssociatedDoEval(
     auto entryIt =
         llvm::find_if(llvm::make_range(firstAssociatedIt, loopIt),
                       [](lower::pft::Evaluation &candidate) {
-                        return candidate.isNewBlock && candidate.block;
+                        return candidate.getIsNewBlock() && candidate.block;
                       });
     if (entryIt != loopIt) {
       splicedEvaluations->suppressEntryBlock(*entryIt);
     } else {
       lower::pft::Evaluation &doStmt = loopIt->getFirstNestedEvaluation();
-      if (doStmt.isNewBlock && doStmt.block)
+      if (doStmt.getIsNewBlock() && doStmt.block)
         splicedEvaluations->suppressEntryBlock(doStmt);
     }
   }
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 536ba708b1916..09975768f8644 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -177,19 +177,19 @@ class PFTBuilder {
       return;
     lower::pft::FunctionLikeUnit *proc =
         evaluationListStack.back()->back().getOwningProcedure();
-    proc->hasIeeeAccess = true;
+    proc->setHasIeeeAccess(true);
     if (!procName.starts_with("ieee_set_"))
       return;
     if (procName.starts_with("ieee_set_modes_") ||
         procName.starts_with("ieee_set_status_"))
-      proc->mayModifyHaltingMode = proc->mayModifyRoundingMode =
-          proc->mayModifyUnderflowMode = true;
+      proc->setMayModifyHaltingMode(proc->setMayModifyRoundingMode(
+          proc->setMayModifyUnderflowMode(true)));
     else if (procName.starts_with("ieee_set_halting_mode_"))
-      proc->mayModifyHaltingMode = true;
+      proc->setMayModifyHaltingMode(true);
     else if (procName.starts_with("ieee_set_rounding_mode_"))
-      proc->mayModifyRoundingMode = true;
+      proc->setMayModifyRoundingMode(true);
     else if (procName.starts_with("ieee_set_underflow_mode_"))
-      proc->mayModifyUnderflowMode = true;
+      proc->setMayModifyUnderflowMode(true);
   }
 
   /// Convert an IfStmt into an IfConstruct, retaining the IfStmt as the
@@ -860,7 +860,7 @@ class PFTBuilder {
                    "expected goto or cycle statement");
             ifBodyList.erase(branchStmtIt);
             lower::pft::Evaluation &ifStmt = *ifBodyList.begin();
-            ifStmt.negateCondition = true;
+            ifStmt.setNegateCondition(true);
             ifStmt.lexicalSuccessor = firstStmt(&*successorIt);
             lower::pft::EvaluationList::iterator endIfStmtIt =
                 std::prev(ifBodyList.end());
@@ -962,7 +962,7 @@ class PFTBuilder {
       sourceEvaluation.extraControlSuccessors.push_back(&targetEvaluation);
     // Record the reverse edge beside the forward one.
     (*incomingBranches)[&targetEvaluation].insert(&sourceEvaluation);
-    targetEvaluation.isNewBlock = true;
+    targetEvaluation.setIsNewBlock(true);
     // If this is a branch into the body of a construct (usually illegal,
     // but allowed in some legacy cases), then the targetEvaluation and its
     // ancestors must be marked as unstructured.
@@ -985,7 +985,7 @@ class PFTBuilder {
           // this to be done when the construct is analyzed.
           if (eval->constructExit && (eval->isA<parser::DoConstruct>() ||
                                       eval->isA<parser::IfConstruct>()))
-            eval->constructExit->isNewBlock = true;
+            eval->constructExit->setIsNewBlock(true);
         }
     }
   }
@@ -1000,7 +1000,7 @@ class PFTBuilder {
 
   /// Mark the successor of an Evaluation as a new block.
   void markSuccessorAsNewBlock(lower::pft::Evaluation &eval) {
-    eval.nonNopSuccessor().isNewBlock = true;
+    eval.nonNopSuccessor().setIsNewBlock(true);
   }
 
   template <typename A>
@@ -1093,7 +1093,7 @@ class PFTBuilder {
           },
           [&](const parser::GotoStmt &s) { markBranchTarget(eval, s.v); },
           [&](const parser::IfStmt &) {
-            eval.lexicalSuccessor->isNewBlock = true;
+            eval.lexicalSuccessor->setIsNewBlock(true);
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::ReturnStmt &) {
@@ -1127,7 +1127,7 @@ class PFTBuilder {
             // Consult the same classification the assigned GO TO uses, so the
             // two agree on which statements may be branched to.
             if (semanticsContext.IsRecordedBranchTarget(target->position)) {
-              target->isNewBlock = true;
+              target->setIsNewBlock(true);
               for (lower::pft::Evaluation *parent = target->parentConstruct;
                    parent; parent = parent->parentConstruct) {
                 parent->markUnstructured();
@@ -1135,7 +1135,7 @@ class PFTBuilder {
                 if (parent->constructExit &&
                     (parent->isA<parser::DoConstruct>() ||
                      parent->isA<parser::IfConstruct>()))
-                  parent->constructExit->isNewBlock = true;
+                  parent->constructExit->setIsNewBlock(true);
               }
             }
           },
@@ -1174,7 +1174,7 @@ class PFTBuilder {
 
           // The first executable statement after an EntryStmt is a new block.
           [&](const parser::EntryStmt &) {
-            eval.lexicalSuccessor->isNewBlock = true;
+            eval.lexicalSuccessor->setIsNewBlock(true);
           },
 
           // Construct statements
@@ -1189,12 +1189,12 @@ class PFTBuilder {
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::CaseStmt &) {
-            eval.isNewBlock = true;
+            eval.setIsNewBlock(true);
             lastConstructStmtEvaluation->controlSuccessor = &eval;
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::EndSelectStmt &) {
-            eval.isNewBlock = true;
+            eval.setIsNewBlock(true);
             lastConstructStmtEvaluation = nullptr;
           },
           [&](const parser::ChangeTeamStmt &s) {
@@ -1212,7 +1212,7 @@ class PFTBuilder {
               eval.markUnstructured(); // infinite loop
               return;
             }
-            eval.nonNopSuccessor().isNewBlock = true;
+            eval.nonNopSuccessor().setIsNewBlock(true);
             eval.controlSuccessor = &evaluationList.back();
             if (const auto *bounds =
                     std::get_if<parser::LoopControl::Bounds>(&loopControl->u)) {
@@ -1235,7 +1235,7 @@ class PFTBuilder {
               return;
             // The loop is unstructured, which wasn't known for all cases when
             // visiting the NonLabelDoStmt.
-            parentConstruct->constructExit->isNewBlock = true;
+            parentConstruct->constructExit->setIsNewBlock(true);
             const auto &doStmt = *doEval.getIf<parser::NonLabelDoStmt>();
             const auto &loopControl =
                 std::get<std::optional<parser::LoopControl>>(doStmt.t);
@@ -1247,30 +1247,34 @@ class PFTBuilder {
               // If there is a mask, the EndDoStmt starts a new block.
               const auto &header =
                   std::get<parser::ConcurrentHeader>(concurrent->t);
-              eval.isNewBlock |=
-                  std::get<std::optional<parser::ScalarLogicalExpr>>(header.t)
-                      .has_value();
+              [&] {
+                auto PackedFlagValue =
+                    std::get<std::optional<parser::ScalarLogicalExpr>>(header.t)
+                        .has_value();
+                return eval.setIsNewBlock(eval.getIsNewBlock() |
+                                          PackedFlagValue);
+              }();
             }
           },
           [&](const parser::IfThenStmt &s) {
             insertConstructName(s, parentConstruct);
-            eval.lexicalSuccessor->isNewBlock = true;
+            eval.lexicalSuccessor->setIsNewBlock(true);
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::ElseIfStmt &) {
-            eval.isNewBlock = true;
-            eval.lexicalSuccessor->isNewBlock = true;
+            eval.setIsNewBlock(true);
+            eval.lexicalSuccessor->setIsNewBlock(true);
             lastConstructStmtEvaluation->controlSuccessor = &eval;
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::ElseStmt &) {
-            eval.isNewBlock = true;
+            eval.setIsNewBlock(true);
             lastConstructStmtEvaluation->controlSuccessor = &eval;
             lastConstructStmtEvaluation = nullptr;
           },
           [&](const parser::EndIfStmt &) {
             if (parentConstruct->lowerAsUnstructured())
-              parentConstruct->constructExit->isNewBlock = true;
+              parentConstruct->constructExit->setIsNewBlock(true);
             if (lastConstructStmtEvaluation) {
               lastConstructStmtEvaluation->controlSuccessor =
                   parentConstruct->constructExit;
@@ -1282,7 +1286,7 @@ class PFTBuilder {
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::SelectRankCaseStmt &) {
-            eval.isNewBlock = true;
+            eval.setIsNewBlock(true);
             lastConstructStmtEvaluation->controlSuccessor = &eval;
             lastConstructStmtEvaluation = &eval;
           },
@@ -1291,7 +1295,7 @@ class PFTBuilder {
             lastConstructStmtEvaluation = &eval;
           },
           [&](const parser::TypeGuardStmt &) {
-            eval.isNewBlock = true;
+            eval.setIsNewBlock(true);
             lastConstructStmtEvaluation->controlSuccessor = &eval;
             lastConstructStmtEvaluation = &eval;
           },
@@ -1373,7 +1377,7 @@ class PFTBuilder {
       initialEval = &initialEval->getFirstNestedEvaluation();
     else if (initialEval->isA<Fortran::parser::EntryStmt>())
       initialEval = initialEval->lexicalSuccessor;
-    initialEval->isNewBlock = true;
+    initialEval->setIsNewBlock(true);
 
     // All function entry points share a single result container.
     // Find one of the largest results.
@@ -1499,7 +1503,7 @@ class PFTDumper {
                       const lower::pft::Evaluation &eval,
                       const std::string &indentString, int indent = 1) {
     llvm::StringRef name = evaluationName(eval);
-    llvm::StringRef newBlock = eval.isNewBlock ? "^" : "";
+    llvm::StringRef newBlock = eval.getIsNewBlock() ? "^" : "";
     // "!" marks an unstructured evaluation. "~" marks one that is structured
     // on the outside but has unstructured internals.
     llvm::StringRef bang = eval.hasUnstructuredInternals()
@@ -1512,7 +1516,7 @@ class PFTDumper {
       outputStream << "<<" << newBlock << name << bang << ">>";
     else
       outputStream << newBlock << name << bang;
-    if (eval.negateCondition)
+    if (eval.getNegateCondition())
       outputStream << " [negate]";
     if (eval.constructExit) {
       outputStream << " -> " << eval.constructExit->printIndex;
diff --git a/flang/lib/Lower/Support/PrivateReductionUtils.cpp b/flang/lib/Lower/Support/PrivateReductionUtils.cpp
index 8008730ba065f..3d69bf227086d 100644
--- a/flang/lib/Lower/Support/PrivateReductionUtils.cpp
+++ b/flang/lib/Lower/Support/PrivateReductionUtils.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Lower/Support/PrivateReductionUtils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "flang/Lower/AbstractConverter.h"
 #include "flang/Lower/Allocatable.h"
@@ -257,17 +258,18 @@ static void initializeIfDerivedTypeBox(fir::FirOpBuilder &builder,
     fir::runtime::genDerivedTypeInitializeClone(builder, loc, newBox, moldBox);
 }
 
-static void getLengthParameters(fir::FirOpBuilder &builder, mlir::Location loc,
-                                mlir::Value moldArg,
-                                llvm::SmallVectorImpl<mlir::Value> &lenParams) {
+static llvm::SmallVector<mlir::Value>
+getLengthParameters(fir::FirOpBuilder &builder, mlir::Location loc,
+                    mlir::Value moldArg) {
+  llvm::SmallVector<mlir::Value> lenParams;
   // We pass derived types unboxed and so are not self-contained entities.
   // Assume that unboxed derived types won't need length paramters.
   if (!hlfir::isFortranEntity(moldArg))
-    return;
+    return lenParams;
 
   hlfir::genLengthParameters(loc, builder, hlfir::Entity{moldArg}, lenParams);
   if (lenParams.empty())
-    return;
+    return lenParams;
 
   // The verifier for EmboxOp doesn't allow length parameters when the the
   // character already has static LEN. genLengthParameters may still return them
@@ -277,6 +279,7 @@ static void getLengthParameters(fir::FirOpBuilder &builder, mlir::Location loc,
 
   if (strTy && strTy.hasConstantLen())
     lenParams.resize(0);
+  return lenParams;
 }
 
 static bool
@@ -329,9 +332,10 @@ class PopulateInitAndCleanupRegionsHelper {
         argType{argType}, scalarInitValue{scalarInitValue},
         allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
         initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
-        sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds},
-        isDoConcurrent{isDoConcurrent},
-        forceHeapAllocation{forceHeapAllocation} {
+        sym{sym},
+        lenParams(decltype(this->lenParams)::withFlags(
+            unsigned(cannotHaveLowerBounds) | (unsigned(isDoConcurrent) << 1) |
+            (unsigned(forceHeapAllocation) << 2))) {
     valType = fir::unwrapRefType(argType);
   }
 
@@ -371,17 +375,27 @@ class PopulateInitAndCleanupRegionsHelper {
   const Fortran::semantics::Symbol *sym;
 
   /// Any length parameters which have been fetched for the type
-  mlir::SmallVector<mlir::Value> lenParams;
+  llvm::SmallVectorWithFlags<
+      mlir::Value,
+      llvm::CalculateSmallVectorDefaultInlinedElements<mlir::Value>::value, 3>
+      lenParams;
 
   /// If the source variable being privatized definitely can't have non-default
   /// lower bounds then we don't need to generate code to read them.
-  bool cannotHaveNonDefaultLowerBounds;
+  bool getCannotHaveNonDefaultLowerBounds() const {
+    return lenParams.getFlag(0);
+  }
+  void setCannotHaveNonDefaultLowerBounds(bool Value) {
+    lenParams.setFlag(0, Value);
+  }
 
-  bool isDoConcurrent;
-  bool forceHeapAllocation;
+  bool getIsDoConcurrent() const { return lenParams.getFlag(1); }
+  void setIsDoConcurrent(bool Value) { lenParams.setFlag(1, Value); }
+  bool getForceHeapAllocation() const { return lenParams.getFlag(2); }
+  void setForceHeapAllocation(bool Value) { lenParams.setFlag(2, Value); }
 
   void createYield(mlir::Value ret) {
-    if (isDoConcurrent)
+    if (getIsDoConcurrent())
       fir::YieldOp::create(builder, loc, ret);
     else
       mlir::omp::YieldOp::create(builder, loc, ret);
@@ -506,7 +520,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedScalar(
 
   if (!shouldAllocateOnStack)
     createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
-                        isDoConcurrent);
+                        getIsDoConcurrent());
 
   if (ifUnallocated)
     builder.setInsertionPointAfter(ifUnallocated);
@@ -523,7 +537,7 @@ bool PopulateInitAndCleanupRegionsHelper::shouldAllocateTempOnStack(
   // On the GPU, always allocate on the stack unless the user explicitly
   // specifies otherwise since heap allocations are very expensive.
   bool isGPU = offloadMod && offloadMod.getIsGPU();
-  if (isGPU && forceHeapAllocation)
+  if (isGPU && getForceHeapAllocation())
     return false;
   if (isGPU && enableGPUHeapAlloc) {
     // Check if it is adjustable array
@@ -540,7 +554,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
     fir::BaseBoxType boxTy, bool needsInitialization) {
   bool isAllocatableOrPointer =
       mlir::isa<fir::HeapType, fir::PointerType>(boxTy.getEleTy());
-  getLengthParameters(builder, loc, getLoadedMoldArg(), lenParams);
+  lenParams.assign(getLengthParameters(builder, loc, getLoadedMoldArg()));
 
   fir::IfOp ifUnallocated{nullptr};
   if (isAllocatableOrPointer) {
@@ -554,8 +568,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
   // Special case for (possibly allocatable) arrays of polymorphic types
   // e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
   if (source.isPolymorphic()) {
-    fir::ShapeShiftOp shape =
-        getShapeShift(builder, loc, source, cannotHaveNonDefaultLowerBounds);
+    fir::ShapeShiftOp shape = getShapeShift(
+        builder, loc, source, getCannotHaveNonDefaultLowerBounds());
     mlir::Type arrayType = source.getElementOrSequenceType();
     mlir::Value allocatedArray = fir::AllocMemOp::create(
         builder, loc, arrayType, /*typeparams=*/mlir::ValueRange{},
@@ -571,7 +585,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
     createYield(allocatedPrivVarArg);
     mlir::OpBuilder::InsertionGuard guard(builder);
     createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
-                        isDoConcurrent);
+                        getIsDoConcurrent());
     return;
   }
 
@@ -588,7 +602,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
     if (needsDealloc) {
       mlir::OpBuilder::InsertionGuard guard(builder);
       createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
-                          isDoConcurrent);
+                          getIsDoConcurrent());
     } else {
       assert(!isAllocatableOrPointer &&
              "Pointer-like arrays must be heap allocated");
@@ -599,8 +613,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
   // Put the temporary inside of a box:
   // hlfir::genVariableBox doesn't handle non-default lower bounds
   mlir::Value box;
-  fir::ShapeShiftOp shapeShift = getShapeShift(builder, loc, getLoadedMoldArg(),
-                                               cannotHaveNonDefaultLowerBounds);
+  fir::ShapeShiftOp shapeShift = getShapeShift(
+      builder, loc, getLoadedMoldArg(), getCannotHaveNonDefaultLowerBounds());
   mlir::Type boxType = getLoadedMoldArg().getType();
   if (mlir::isa<fir::BaseBoxType>(temp.getType()))
     // the box created by the declare form createTempFromMold is missing
@@ -646,7 +660,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxchar(
   mlir::Value boxChar = charExprHelper.createEmboxChar(privateAddr, len);
 
   createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
-                      isDoConcurrent);
+                      getIsDoConcurrent());
 
   builder.setInsertionPointToEnd(initBlock);
   createYield(boxChar);
@@ -685,7 +699,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupUnboxedDerivedType(
 
   if (sym && hasFinalization(*sym))
     createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
-                        isDoConcurrent);
+                        getIsDoConcurrent());
 
   builder.setInsertionPointToEnd(initBlock);
   createYield(allocatedPrivVarArg);
@@ -733,7 +747,7 @@ void PopulateInitAndCleanupRegionsHelper::populateByRefInitAndCleanupRegions() {
     }
 
     // TODO: don't do this unless it is needed
-    getLengthParameters(builder, loc, getLoadedMoldArg(), lenParams);
+    lenParams.assign(getLengthParameters(builder, loc, getLoadedMoldArg()));
 
     if (isPrivatization(kind) &&
         mlir::isa<fir::PointerType>(boxTy.getEleTy())) {
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 9e568af786910..7162940eb37d6 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -226,11 +226,11 @@ static fir::AliasAnalysis::Source mergeRegionBranchPredecessorSources(
   // as true if any of the sources are true.
   bool mergedApprox =
       llvm::any_of(sources, [](const fir::AliasAnalysis::Source &s) {
-        return s.approximateSource;
+        return s.getApproximateSource();
       });
   bool mergedCaptured =
       llvm::any_of(sources, [](const fir::AliasAnalysis::Source &s) {
-        return s.isCapturedInInternalProcedure;
+        return s.getIsCapturedInInternalProcedure();
       });
 
   fir::AliasAnalysis::SourceKind mergedKind;
@@ -317,10 +317,10 @@ static fir::AliasAnalysis::Source mergeRegionBranchPredecessorSources(
   fir::AliasAnalysis::Source::AccessPath mergedPath;
   if (allPathsSame) {
     mergedPath = sources[0].accessPath;
-    mergedPath.isApproximate |= mergedApprox;
+    mergedPath.setIsApproximate(mergedPath.isApproximate() || mergedApprox);
   } else {
     mergedPath = {};
-    mergedPath.isApproximate = true;
+    mergedPath.setIsApproximate(true);
   }
 
   mlir::Type mergedTy = allTypesSame ? sources[0].valueType : fallbackType;
@@ -358,15 +358,16 @@ static fir::AliasAnalysis::Source mergeRegionBranchPredecessorSources(
         unsigned idx = it->second;
         auto &mergedScopedOrigin = mergedScopedOrigins[idx];
         if (mergedScopedOrigin.isData != scopedOrigin.isData ||
-            mergedScopedOrigin.accessPath.steps !=
-                scopedOrigin.accessPath.steps) {
+            llvm::ArrayRef(mergedScopedOrigin.accessPath.steps) !=
+                llvm::ArrayRef(scopedOrigin.accessPath.steps)) {
           // Mark as not-seen so the entry is dropped after this pred.
           continue;
         }
         mergedScopedOrigin.attributes |= scopedOrigin.attributes;
         mergedScopedOrigin.approximateSource |= scopedOrigin.approximateSource;
-        mergedScopedOrigin.accessPath.isApproximate |=
-            scopedOrigin.accessPath.isApproximate;
+        mergedScopedOrigin.accessPath.setIsApproximate(
+            mergedScopedOrigin.accessPath.isApproximate() ||
+            scopedOrigin.accessPath.isApproximate());
         seenThisPred[idx] = true;
       }
       // Drop entries this predecessor did not match. Iterate in reverse
@@ -413,7 +414,7 @@ void AliasAnalysis::Source::AccessPath::print(llvm::raw_ostream &os) const {
     }
   }
   os << "]";
-  if (isApproximate)
+  if (isApproximate())
     os << "(~)";
 }
 
@@ -776,7 +777,8 @@ AliasResult AliasAnalysis::alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
     }
   }
 
-  bool approximateSource = lhsSrc.approximateSource || rhsSrc.approximateSource;
+  bool approximateSource =
+      lhsSrc.getApproximateSource() || rhsSrc.getApproximateSource();
   LLVM_DEBUG(llvm::dbgs() << "\nAliasAnalysis::alias\n";
              llvm::dbgs() << "  lhs: " << lhs << "\n";
              llvm::dbgs() << "  lhsSrc: " << lhsSrc << "\n";
@@ -1120,7 +1122,7 @@ ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
   // procedures may be captured or passed. As this is tricky to analyze, always
   // consider such variables may be accessed in any calls.
   if (varSrc.kind == fir::AliasAnalysis::SourceKind::HostAssoc ||
-      varSrc.isCapturedInInternalProcedure)
+      varSrc.getIsCapturedInInternalProcedure())
     return ModRefResult::getModAndRef();
   // At that stage, it has been ruled out that local (including the saved ones)
   // and dummy cannot be indirectly accessed in the call.
@@ -1240,8 +1242,8 @@ void AliasAnalysisRecursiveEffectsCache::buildSummary(mlir::Operation *op,
     // conservatively assume both Mod and Ref (this mirrors the uncached
     // AliasAnalysis::getModRef which returns ModAndRef in this case).
     if (!isRecursive) {
-      out.hasUnknownWrite = true;
-      out.hasUnknownRead = true;
+      out.setHasUnknownWrite(true);
+      out.setHasUnknownRead(true);
     }
     return;
   }
@@ -1264,9 +1266,9 @@ void AliasAnalysisRecursiveEffectsCache::buildSummary(mlir::Operation *op,
 
     if (!v) {
       if (isRead)
-        out.hasUnknownRead = true;
+        out.setHasUnknownRead(true);
       if (isWrite)
-        out.hasUnknownWrite = true;
+        out.setHasUnknownWrite(true);
       continue;
     }
 
@@ -1297,8 +1299,8 @@ AliasAnalysisRecursiveEffectsCache::getModRefFromSummary(mlir::Operation *op,
   }
 
   const Summary &s = it->second;
-  bool mod = s.hasUnknownWrite;
-  bool ref = s.hasUnknownRead;
+  bool mod = s.getHasUnknownWrite();
+  bool ref = s.getHasUnknownRead();
 
   if (!mod) {
     for (mlir::Value v : s.writeLocations) {
@@ -1566,7 +1568,7 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
   // Access path steps collected during the backward walk (leaf-to-root order).
   // Reversed into the final AccessPath at the end, unless the box-load branch
   // composes the full path directly.
-  llvm::SmallVector<Source::PathStep, 4> pathSteps;
+  llvm::SmallVectorWithFlags<Source::PathStep, 4> pathSteps;
   Source::AccessPath accessPath;
   bool accessPathFinalized{false};
 
@@ -1686,9 +1688,9 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
                                     /*getLastInstantiationPoint=*/false,
                                     collectScopedOrigins);
             attributes |= boxSrc.attributes;
-            approximateSource |= boxSrc.approximateSource;
+            approximateSource |= boxSrc.getApproximateSource();
             isCapturedInInternalProcedure |=
-                boxSrc.isCapturedInInternalProcedure;
+                boxSrc.getIsCapturedInInternalProcedure();
 
             if (getLastInstantiationPoint) {
               if (!instantiationPoint)
@@ -1707,8 +1709,8 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
             accessPath.steps.push_back(derefStep);
             for (int i = pathSteps.size() - 1; i >= 0; --i)
               accessPath.steps.push_back(pathSteps[i]);
-            accessPath.isApproximate =
-                boxSrc.accessPath.isApproximate || approximateSource;
+            accessPath.setIsApproximate(boxSrc.accessPath.isApproximate() ||
+                                        approximateSource);
             accessPathFinalized = true;
 
             // Rebase each forwarded ScopedOrigin from the inner walk's
@@ -1720,7 +1722,9 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
                 scopedOrigin.accessPath.steps.push_back(derefStep);
                 for (int i = pathSteps.size() - 1; i >= 0; --i)
                   scopedOrigin.accessPath.steps.push_back(pathSteps[i]);
-                scopedOrigin.accessPath.isApproximate |= approximateSource;
+                scopedOrigin.accessPath.setIsApproximate(
+                    scopedOrigin.accessPath.isApproximate() ||
+                    approximateSource);
                 if (isPointerBox)
                   scopedOrigin.attributes.set(Attribute::Pointer);
                 scopedOrigin.approximateSource |= approximateSource;
@@ -1873,7 +1877,7 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
             scopedOrigin.declValue = opResult;
             scopedOrigin.accessPath.steps.assign(pathSteps.rbegin(),
                                                  pathSteps.rend());
-            scopedOrigin.accessPath.isApproximate = approximateSource;
+            scopedOrigin.accessPath.setIsApproximate(approximateSource);
             scopedOrigin.attributes = attributes;
             scopedOrigin.approximateSource = approximateSource;
             scopedOrigin.isData = followingData;
@@ -2068,10 +2072,13 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
                                             collectScopedOrigins));
           regionBranchReturn = mergeRegionBranchPredecessorSources(
               predSources, v, ty, followingData);
-          regionBranchReturn->attributes |= attributes;
-          regionBranchReturn->approximateSource |= approximateSource;
-          regionBranchReturn->isCapturedInInternalProcedure |=
-              isCapturedInInternalProcedure;
+          auto &returnSource = *regionBranchReturn;
+          returnSource.attributes |= attributes;
+          returnSource.setApproximateSource(
+              int(returnSource.getApproximateSource()) | (approximateSource));
+          returnSource.setIsCapturedInInternalProcedure(
+              int(returnSource.getIsCapturedInInternalProcedure()) |
+              (isCapturedInInternalProcedure));
           // Prepend the outer (leaf-closer) scopedOrigins -- declares
           // already crossed between leaf and this region-branch op --
           // to the merged predecessors' snapshots. The inner snapshots'
@@ -2085,7 +2092,7 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
             combined.append(scopedOrigins.begin(), scopedOrigins.end());
             combined.append(regionBranchReturn->scopedOrigins.begin(),
                             regionBranchReturn->scopedOrigins.end());
-            regionBranchReturn->scopedOrigins = std::move(combined);
+            regionBranchReturn->scopedOrigins.assign(std::move(combined));
           }
           breakFromLoop = true;
         })
@@ -2129,7 +2136,7 @@ AliasAnalysis::getSourceImpl(mlir::Value v, bool getLastInstantiationPoint,
   if (!accessPathFinalized) {
     std::reverse(pathSteps.begin(), pathSteps.end());
     accessPath.steps = std::move(pathSteps);
-    accessPath.isApproximate = approximateSource;
+    accessPath.setIsApproximate(approximateSource);
   }
 
   if (type == SourceKind::Global) {
@@ -2234,7 +2241,7 @@ fir::AliasAnalysis::Source fir::AliasAnalysis::buildSourceAtDeclare(
   // "declare-as-root, original-query-as-leaf".
   source.accessPath = scopedOrigin.accessPath;
   source.attributes = scopedOrigin.attributes;
-  source.approximateSource = scopedOrigin.approximateSource;
+  source.setApproximateSource(scopedOrigin.approximateSource);
   source.origin.isData = scopedOrigin.isData;
   return source;
 }
diff --git a/flang/lib/Optimizer/Builder/TemporaryStorage.cpp b/flang/lib/Optimizer/Builder/TemporaryStorage.cpp
index 0233fc9f023de..42998e348cb52 100644
--- a/flang/lib/Optimizer/Builder/TemporaryStorage.cpp
+++ b/flang/lib/Optimizer/Builder/TemporaryStorage.cpp
@@ -145,8 +145,7 @@ fir::factory::ArrayTemp::ArrayTemp(mlir::Location loc,
                                    llvm::ArrayRef<mlir::Value> lowerBounds,
                                    llvm::ArrayRef<mlir::Value> lengths,
                                    bool allocateOnHeap, llvm::StringRef name)
-    : allocateOnHeap{allocateOnHeap},
-      typeParams{lengths.begin(), lengths.end()} {
+    : typeParams(unsigned(allocateOnHeap), lengths.begin(), lengths.end()) {
   assert(extents.size() == lowerBounds.size() &&
          "extents and lowerBounds must have the same size");
   assert(extents.size() == declaredType.getDimension() &&
@@ -194,22 +193,22 @@ void fir::factory::ArrayTemp::pushValue(mlir::Location loc,
   // Match HomogeneousScalarStack: derived types go through the runtime path.
   if (!entity.hasIntrinsicType())
     TODO(loc, "creating ArrayTemp for derived types");
-  mlir::Value addr =
-      genArrayTempElementAddr(loc, builder, temp, indices, typeParams);
+  mlir::Value addr = genArrayTempElementAddr(
+      loc, builder, temp, indices, llvm::ArrayRef<mlir::Value>(typeParams));
   hlfir::AssignOp::create(builder, loc, value, addr);
 }
 
 mlir::Value fir::factory::ArrayTemp::fetch(mlir::Location loc,
                                            fir::FirOpBuilder &builder,
                                            mlir::ValueRange indices) {
-  mlir::Value addr =
-      genArrayTempElementAddr(loc, builder, temp, indices, typeParams);
+  mlir::Value addr = genArrayTempElementAddr(
+      loc, builder, temp, indices, llvm::ArrayRef<mlir::Value>(typeParams));
   return hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{addr});
 }
 
 void fir::factory::ArrayTemp::destroy(mlir::Location loc,
                                       fir::FirOpBuilder &builder) {
-  if (allocateOnHeap) {
+  if (getAllocateOnHeap()) {
     auto declare = temp.getDefiningOp<hlfir::DeclareOp>();
     assert(declare && "temp must have been declared");
     fir::FreeMemOp::create(builder, loc, declare.getMemref());
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
index dcc40c7b25c5c..d82dc9ac4c531 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
@@ -30,6 +30,7 @@
 #include "mlir/IR/IRMapping.h"
 #include "mlir/Transforms/DialectConversion.h"
 #include "mlir/Transforms/RegionUtils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/Debug.h"
 #include <unordered_set>
@@ -297,7 +298,7 @@ class OrderedAssignmentRewriter {
   /// Construct stack in the current run. This allows setting back the insertion
   /// point correctly when leaving a node that requires a fir.do_loop or fir.if
   /// operation.
-  llvm::SmallVector<mlir::Operation *> constructStack;
+  llvm::SmallVectorWithFlags<mlir::Operation *> constructStack;
   /// Current where loop nest, if any.
   std::optional<hlfir::LoopNest> whereLoopNest;
 
@@ -322,7 +323,8 @@ class OrderedAssignmentRewriter {
   /// When allocating temporary storage inlined, indicate if the storage should
   /// be heap or stack allocated. Temporary allocated with the runtime are heap
   /// allocated by the runtime.
-  bool allocateOnHeap = true;
+  bool getAllocateOnHeap() const { return !constructStack.getFlag(0); }
+  void setAllocateOnHeap(bool Value) { constructStack.setFlag(0, !Value); }
 };
 } // namespace
 
@@ -1239,10 +1241,10 @@ void OrderedAssignmentRewriter::generateSaveEntity(
         auto sequenceType = mlir::cast<fir::SequenceType>(
             builder.getVarLenSeqTy(entityType, /*rank=*/loopNest.size()));
         temp = insertSavedEntity(
-            region,
-            fir::factory::ArrayTemp{loc, builder, sequenceType, tempExtents,
-                                    tempLowerBounds,
-                                    /*lengths=*/{}, allocateOnHeap, tempName});
+            region, fir::factory::ArrayTemp{loc, builder, sequenceType,
+                                            tempExtents, tempLowerBounds,
+                                            /*lengths=*/{}, getAllocateOnHeap(),
+                                            tempName});
       } else if (loopShapeCanBePreComputed && fir::isa_trivial(entityType)) {
         mlir::Value loopExtent =
             computeLoopNestIterationNumber(loc, builder, loopNest);
@@ -1251,7 +1253,7 @@ void OrderedAssignmentRewriter::generateSaveEntity(
         temp = insertSavedEntity(region,
                                  fir::factory::HomogeneousScalarStack{
                                      loc, builder, sequenceType, loopExtent,
-                                     /*lenParams=*/{}, allocateOnHeap,
+                                     /*lenParams=*/{}, getAllocateOnHeap(),
                                      /*stackThroughLoops=*/true, tempName});
       } else {
         // If the number of iteration is not known, or if the values at each
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
index c99304df57c35..bb1e57c2ead49 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp
@@ -13,6 +13,7 @@
 #include "flang/Optimizer/Dialect/FortranVariableInterface.h"
 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
 #include "mlir/IR/OperationSupport.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Debug.h"
 
 #define DEBUG_TYPE "flang-ordered-assignment"
@@ -180,7 +181,9 @@ class Scheduler {
 public:
   Scheduler(hlfir::OrderedAssignmentTreeOpInterface root,
             bool tryFusingAssignments)
-      : root{root}, tryFusingAssignments{tryFusingAssignments} {}
+      : root{root}, independentEvaluationEffects(
+                        decltype(this->independentEvaluationEffects)::withFlags(
+                            (unsigned(tryFusingAssignments) << 2))) {}
 
   /// Start scheduling an assignment. Gather the write side effect from the
   /// assignment.
@@ -266,10 +269,19 @@ class Scheduler {
   llvm::SmallVector<hlfir::DetailedEffectInstance> parentEvaluationEffects;
   /// Same as parentEvaluationEffects, but for the current "leaf group" being
   /// analyzed scheduled.
-  llvm::SmallVector<hlfir::DetailedEffectInstance> independentEvaluationEffects;
+  llvm::SmallVectorWithFlags<hlfir::DetailedEffectInstance,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 hlfir::DetailedEffectInstance>::value,
+                             3>
+      independentEvaluationEffects;
 
   /// Were any region saved for the current assignment?
-  bool savedAnyRegionForCurrentAssignment = false;
+  bool getSavedAnyRegionForCurrentAssignment() const {
+    return independentEvaluationEffects.getFlag(0);
+  }
+  void setSavedAnyRegionForCurrentAssignment(bool Value) {
+    independentEvaluationEffects.setFlag(0, Value);
+  }
 
   // Schedule being built.
   hlfir::Schedule schedule;
@@ -280,11 +292,24 @@ class Scheduler {
 
   /// Is schedule.back() a schedule that is only saving region with read
   /// effects?
-  bool currentRunIsReadOnly = false;
+  bool getCurrentRunIsReadOnly() const {
+    return independentEvaluationEffects.getFlag(1);
+  }
+  void setCurrentRunIsReadOnly(bool Value) {
+    independentEvaluationEffects.setFlag(1, Value);
+  }
 
   /// Option to tell if the scheduler should try fusing to assignments in the
   /// same loops.
-  const bool tryFusingAssignments;
+  bool getTryFusingAssignments() const {
+    return independentEvaluationEffects.getFlag(2);
+  }
+
+public:
+  Scheduler(const Scheduler &) = default;
+  Scheduler(Scheduler &&) = default;
+  Scheduler &operator=(const Scheduler &) = delete;
+  Scheduler &operator=(Scheduler &&) = delete;
 };
 } // namespace
 
@@ -783,7 +808,7 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion,
 void Scheduler::saveEvaluation(
     mlir::Region &yieldRegion,
     llvm::ArrayRef<hlfir::DetailedEffectInstance> effects, bool anyWrite) {
-  savedAnyRegionForCurrentAssignment = true;
+  setSavedAnyRegionForCurrentAssignment(true);
   auto &state = regionStates[&yieldRegion];
   if (state.modifiedInRun) {
     // The region was modified in a previous run, but we now realize we need its
@@ -807,13 +832,13 @@ void Scheduler::saveEvaluation(
     // could try to prove the effects do not conflict with the previous
     // schedule.
     schedule.emplace_back(hlfir::Run{});
-    currentRunIsReadOnly = false;
-  } else if (!currentRunIsReadOnly) {
+    setCurrentRunIsReadOnly(false);
+  } else if (!getCurrentRunIsReadOnly()) {
     // For now, do not try to fuse an evaluation with a previous
     // run that contains any write effects. One could try to prove
     // that "effects" do not conflict with the current run assignments.
     schedule.emplace_back(hlfir::Run{});
-    currentRunIsReadOnly = true;
+    setCurrentRunIsReadOnly(true);
   }
   // Otherwise, save the yielded entity in the current run, that already
   // saving other read only entities.
@@ -833,7 +858,7 @@ void Scheduler::saveEvaluation(
 bool Scheduler::canFuseAssignmentWithPreviousRun() {
   // If a region was saved for the current assignment, the previous
   // run is already known to conflict. Skip the analysis.
-  if (savedAnyRegionForCurrentAssignment || schedule.empty())
+  if (getSavedAnyRegionForCurrentAssignment() || schedule.empty())
     return false;
   auto &previousRunEffects = schedule.back().memoryEffects;
   return !conflict(previousRunEffects, assignEffects).isAny() &&
@@ -873,8 +898,8 @@ void Scheduler::finishSchedulingAssignment(hlfir::RegionAssignOp assign,
                                            bool leafRegionsMayOnlyRead) {
   // Schedule the assignment in a new run, unless it can be fused with the
   // previous run (if enabled and proven safe).
-  currentRunIsReadOnly = false;
-  bool fuse = tryFusingAssignments && canFuseAssignmentWithPreviousRun();
+  setCurrentRunIsReadOnly(false);
+  bool fuse = getTryFusingAssignments() && canFuseAssignmentWithPreviousRun();
   if (!fuse) {
     // If we cannot fuse, we are about to start a new run.
     // Check if any parent region was modified in a previous run and needs to be
@@ -921,7 +946,7 @@ void Scheduler::finishSchedulingAssignment(hlfir::RegionAssignOp assign,
   assignEvaluateEffects.clear();
   parentEvaluationEffects.clear();
   independentEvaluationEffects.clear();
-  savedAnyRegionForCurrentAssignment = false;
+  setSavedAnyRegionForCurrentAssignment(false);
   LLVM_DEBUG(logAssignmentEvaluation(llvm::dbgs(), schedule.size(), assign));
 }
 
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index 5be6ec35a3972..b5f40aba38dfc 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -71,6 +71,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/Casting.h"
@@ -196,8 +197,9 @@ class FIRToMemRef : public fir::impl::FIRToMemRefBase<FIRToMemRef> {
   struct SliceInfo {
     SmallVector<Value> shapeVec;
     SmallVector<Value> shiftVec;
-    SmallVector<Value> sliceVec;
-    bool hasProjectedSlice = false;
+    llvm::SmallVectorWithFlags<Value> sliceVec;
+    bool getHasProjectedSlice() const { return sliceVec.getFlag(0); }
+    void setHasProjectedSlice(bool Value) { sliceVec.setFlag(0, Value); }
     // Constant value of the first projected-slice field, if any.
     std::optional<std::int64_t> projectedSliceStart;
   };
@@ -477,7 +479,7 @@ void FIRToMemRef::collectSliceInfoFrom(OpTy op, SliceInfo &info) const {
 
     if (auto sliceOp = getSliceOp(op.getSlice())) {
       if (hasProjectedSlice(sliceOp)) {
-        info.hasProjectedSlice = true;
+        info.setHasProjectedSlice(true);
         info.projectedSliceStart = getProjectedSliceStartIfConstant(sliceOp);
       }
       auto triples = sliceOp.getTriples();
@@ -826,7 +828,7 @@ FIRToMemRef::getMemrefIndices(fir::ArrayCoorOp arrayCoorOp, Operation *memref,
   }
 
   SmallVector<Value> &shiftVec = sliceInfo.shiftVec;
-  SmallVector<Value> &sliceVec = sliceInfo.sliceVec;
+  auto &sliceVec = sliceInfo.sliceVec;
   SmallVector<Value> sliceLbs, sliceStrides;
   for (size_t i = 0; i < sliceVec.size(); i += 3) {
     sliceLbs.push_back(castTypeToIndexType(sliceVec[i], rewriter));
@@ -992,7 +994,7 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
   else if (auto rebox = firMemref.getDefiningOp<fir::ReboxOp>())
     collectSliceInfoFrom(rebox, sliceInfo);
 
-  if (!sliceInfo.hasProjectedSlice && sliceInfo.shapeVec.empty()) {
+  if (!sliceInfo.getHasProjectedSlice() && sliceInfo.shapeVec.empty()) {
     auto shapeVal = arrayCoorOp.getShape();
     if (shapeVal &&
         mlir::isa<fir::ShapeType, fir::ShapeShiftType>(shapeVal.getType())) {
@@ -1025,7 +1027,7 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
   // each load/store touches exactly sizeof(T) bytes.
   auto srcTy = cast<MemRefType>((*converted).getType());
   std::optional<int64_t> complexPartIdx;
-  if (sliceInfo.hasProjectedSlice) {
+  if (sliceInfo.getHasProjectedSlice()) {
     if (auto complexTy = dyn_cast<mlir::ComplexType>(srcTy.getElementType())) {
       if (!sliceInfo.projectedSliceStart ||
           (*sliceInfo.projectedSliceStart != 0 &&
@@ -1088,8 +1090,8 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
       shapeVec.empty() || (firMemrefIsBox && !firMemrefIsEmbox);
   if (descriptorOwnsLayout) {
     // Plain `!fir.ref` without recoverable shape extents cannot use fir.box_*.
-    if (shapeVec.empty() && !sliceInfo.hasProjectedSlice && !isDescriptor &&
-        !isRebox)
+    if (shapeVec.empty() && !sliceInfo.getHasProjectedSlice() &&
+        !isDescriptor && !isRebox)
       return failure();
 
     // Complex %re/%im: memref_stride = box_dims_byte_stride / sizeof(T),
diff --git a/flang/unittests/Optimizer/AliasAnalysisCacheTest.cpp b/flang/unittests/Optimizer/AliasAnalysisCacheTest.cpp
index 4d1abfff7e258..8e34d1947aa71 100644
--- a/flang/unittests/Optimizer/AliasAnalysisCacheTest.cpp
+++ b/flang/unittests/Optimizer/AliasAnalysisCacheTest.cpp
@@ -18,6 +18,25 @@
 #include "flang/Optimizer/Dialect/FIROps.h"
 #include "flang/Optimizer/Support/InitFIR.h"
 
+TEST(AliasAnalysisAccessPathTest, ApproximationParticipatesInPathEquality) {
+  using Path = fir::AliasAnalysis::Source::AccessPath;
+  using Step = fir::AliasAnalysis::Source::PathStep;
+  Path exact;
+  exact.steps.assign(8, Step{Step::Kind::PointerDeref, {}});
+  Path approximate = exact;
+  approximate.setIsApproximate(true);
+  EXPECT_NE(exact, approximate);
+  // Comparing just the steps must continue to ignore approximation.
+  EXPECT_EQ(llvm::ArrayRef(exact.steps), llvm::ArrayRef(approximate.steps));
+
+  Path moved = std::move(approximate);
+  EXPECT_TRUE(moved.isApproximate());
+  moved.steps.clear();
+  EXPECT_TRUE(moved.isApproximate());
+  moved.setIsApproximate(false);
+  EXPECT_FALSE(moved.isApproximate());
+}
+
 struct AliasAnalysisCacheTest : public testing::Test {
 public:
   void SetUp() override {
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 2f2b6094fbc2c..dd391817f0fff 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -56,7 +56,7 @@ SectionChunk::SectionChunk(ObjFile *f, const coff_section *h, Kind k)
   // files will be built with -ffunction-sections or /Gy, so most things worth
   // stripping will be in a comdat.
   if (file)
-    live = !file->symtab.ctx.config.doGC || !isCOMDAT();
+    live = !file->symtab.ctx.config.getDoGC() || !isCOMDAT();
   else
     live = true;
 }
@@ -844,7 +844,7 @@ void StringChunk::writeTo(uint8_t *buf) const {
 }
 
 ImportThunkChunk::ImportThunkChunk(COFFLinkerContext &ctx, Defined *s)
-    : NonSectionCodeChunk(ImportThunkKind), live(!ctx.config.doGC),
+    : NonSectionCodeChunk(ImportThunkKind), live(!ctx.config.getDoGC()),
       impSymbol(s), ctx(ctx) {}
 
 ImportThunkChunkX64::ImportThunkChunkX64(COFFLinkerContext &ctx, Defined *s)
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 7546da219c440..5e55aa28c5f94 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -121,13 +122,19 @@ struct Configuration {
   llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
   bool machineInferred = false;
   size_t wordsize;
-  bool verbose = false;
+  bool getVerbose() const { return dtltoCompilerArgs.getFlag(0); }
+  bool setVerbose(bool Value) {
+    dtltoCompilerArgs.setFlag(0, Value);
+    return Value;
+  }
   WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
   bool noEntry = false;
   std::string outputFile;
   std::string importName;
-  bool demangle = true;
-  bool doGC = true;
+  bool getDemangle() const { return !dtltoCompilerArgs.getFlag(1); }
+  void setDemangle(bool Value) { dtltoCompilerArgs.setFlag(1, !Value); }
+  bool getDoGC() const { return !dtltoCompilerArgs.getFlag(2); }
+  void setDoGC(bool Value) { dtltoCompilerArgs.setFlag(2, !Value); }
   ICFLevel doICF = ICFLevel::None;
   bool tailMerge;
   bool relocatable = true;
@@ -145,7 +152,7 @@ struct Configuration {
   bool showSummary = false;
   bool printSearchPaths = false;
   unsigned debugTypes = static_cast<unsigned>(DebugType::None);
-  llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> mllvmOpts;
   std::vector<std::string> natvisFiles;
   llvm::StringMap<std::string> namedStreams;
   llvm::SmallString<128> pdbAltPath;
@@ -158,12 +165,18 @@ struct Configuration {
   std::vector<Symbol *> gcroot;
 
   llvm::StringSet<> noDefaultLibs;
-  bool noDefaultLibAll = false;
+  bool getNoDefaultLibAll() const { return dtltoCompilerArgs.getFlag(3); }
+  bool setNoDefaultLibAll(bool Value) {
+    dtltoCompilerArgs.setFlag(3, Value);
+    return Value;
+  }
 
   // True if we are creating a DLL.
-  bool dll = false;
+  bool getDll() const { return dtltoCompilerPrependArgs.getFlag(0); }
+  void setDll(bool Value) { dtltoCompilerPrependArgs.setFlag(0, Value); }
   StringRef implib;
-  bool noimplib = false;
+  bool getNoimplib() const { return dtltoCompilerPrependArgs.getFlag(1); }
+  void setNoimplib(bool Value) { dtltoCompilerPrependArgs.setFlag(1, Value); }
   llvm::StringSet<> delayLoads;
   std::map<std::string, int> dllOrder;
   Symbol *arm64ECIcallHelper = nullptr;
@@ -198,22 +211,30 @@ struct Configuration {
   StringRef dtltoDistributor;
 
   // Used for /thinlto-distributor-arg:<arg>
-  llvm::SmallVector<llvm::StringRef, 0> dtltoDistributorArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoDistributorArgs;
 
   // Used for /thinlto-remote-compiler:<path>
   StringRef dtltoCompiler;
 
   // Used for /thinlto-remote-compiler-prepend-arg:<arg>
-  llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerPrependArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoCompilerPrependArgs;
 
   // Used for /thinlto-remote-compiler-arg:<arg>
-  llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoCompilerArgs;
 
   // Used for /fat-lto-objects
-  bool fatLTOObjects = false;
+  bool getFatLTOObjects() const { return dtltoCompilerPrependArgs.getFlag(2); }
+  void setFatLTOObjects(bool Value) {
+    dtltoCompilerPrependArgs.setFlag(2, Value);
+  }
 
   // Used for /opt:[no]ltodebugpassmanager
-  bool ltoDebugPassManager = false;
+  bool getLtoDebugPassManager() const {
+    return dtltoCompilerPrependArgs.getFlag(3);
+  }
+  void setLtoDebugPassManager(bool Value) {
+    dtltoCompilerPrependArgs.setFlag(3, Value);
+  }
 
   // Used for /merge:from=to (e.g. /merge:.rdata=.text)
   std::map<StringRef, StringRef> merge;
@@ -230,7 +251,8 @@ struct Configuration {
   ManifestKind manifest = Default;
   int manifestID = 1;
   llvm::SetVector<StringRef> manifestDependencies;
-  bool manifestUAC = true;
+  bool getManifestUAC() const { return !dtltoDistributorArgs.getFlag(0); }
+  void setManifestUAC(bool Value) { dtltoDistributorArgs.setFlag(0, !Value); }
   std::vector<std::string> manifestInput;
   StringRef manifestLevel = "'asInvoker'";
   StringRef manifestUIAccess = "'false'";
@@ -255,7 +277,11 @@ struct Configuration {
   std::string mapFile;
 
   // Used for /mapinfo.
-  bool mapInfo = false;
+  bool getMapInfo() const { return dtltoDistributorArgs.getFlag(1); }
+  bool setMapInfo(bool Value) {
+    dtltoDistributorArgs.setFlag(1, Value);
+    return Value;
+  }
 
   // Used for /thinlto-index-only:
   llvm::StringRef thinLTOIndexOnlyArg;
@@ -278,13 +304,23 @@ struct Configuration {
   llvm::StringRef ltoObjPath;
 
   // Used for /lto-cs-profile-generate:
-  bool ltoCSProfileGenerate = false;
+  bool getLtoCSProfileGenerate() const {
+    return dtltoDistributorArgs.getFlag(2);
+  }
+  void setLtoCSProfileGenerate(bool Value) {
+    dtltoDistributorArgs.setFlag(2, Value);
+  }
 
   // Used for /lto-cs-profile-path
   llvm::StringRef ltoCSProfileFile;
 
   // Used for /lto-pgo-warn-mismatch:
-  bool ltoPGOWarnMismatch = true;
+  bool getLtoPGOWarnMismatch() const {
+    return !dtltoDistributorArgs.getFlag(3);
+  }
+  void setLtoPGOWarnMismatch(bool Value) {
+    dtltoDistributorArgs.setFlag(3, !Value);
+  }
 
   // Used for /lto-sample-profile:
   llvm::StringRef ltoSampleProfileName;
@@ -293,7 +329,8 @@ struct Configuration {
   llvm::MapVector<std::pair<const SectionChunk *, const SectionChunk *>,
                   uint64_t>
       callGraphProfile;
-  bool callGraphProfileSort = false;
+  bool getCallGraphProfileSort() const { return mllvmOpts.getFlag(0); }
+  void setCallGraphProfileSort(bool Value) { mllvmOpts.setFlag(0, Value); }
 
   // Used for /print-symbol-order:
   StringRef printSymbolOrder;
@@ -354,14 +391,20 @@ struct Configuration {
   bool pseudoRelocs = false;
   bool stdcallFixup = false;
   bool writeCheckSum = false;
-  bool prefetchInputs = false;
+  bool getPrefetchInputs() const { return mllvmOpts.getFlag(1); }
+  bool setPrefetchInputs(bool Value) {
+    mllvmOpts.setFlag(1, Value);
+    return Value;
+  }
   EmitKind emit = EmitKind::Obj;
-  bool allowDuplicateWeak = false;
+  bool getAllowDuplicateWeak() const { return mllvmOpts.getFlag(2); }
+  void setAllowDuplicateWeak(bool Value) { mllvmOpts.setFlag(2, Value); }
   BuildIDHash buildIDHash = BuildIDHash::None;
   llvm::StringRef optRemarksFilename;
   llvm::StringRef optRemarksPasses;
   llvm::StringRef optRemarksFormat;
-  bool optRemarksWithHotness = false;
+  bool getOptRemarksWithHotness() const { return mllvmOpts.getFlag(3); }
+  void setOptRemarksWithHotness(bool Value) { mllvmOpts.setFlag(3, Value); }
   std::optional<uint64_t> optRemarksHotnessThreshold = 0;
 };
 
diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp
index 0999c918eb04f..17f321ec788c8 100644
--- a/lld/COFF/DebugTypes.cpp
+++ b/lld/COFF/DebugTypes.cpp
@@ -236,7 +236,7 @@ void TpiSource::remapRecord(MutableArrayRef<uint8_t> rec,
         reinterpret_cast<TypeIndex *>(contents.data() + ref.Offset), ref.Count);
     for (TypeIndex &ti : indices) {
       if (!remapTypeIndex(ti, ref.Kind)) {
-        if (ctx.config.verbose) {
+        if (ctx.config.getVerbose()) {
           uint16_t kind =
               reinterpret_cast<const RecordPrefix *>(rec.data())->RecordKind;
           StringRef fname = file ? file->getName() : "<unknown PDB>";
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index ecbb5e9fff4e1..b00b2e6b4a43d 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -282,7 +282,7 @@ InputFile *LinkerDriver::addObjectFile(COFFLinkerContext &ctx,
     }
   }
 
-  if (ctx.config.fatLTOObjects) {
+  if (ctx.config.getFatLTOObjects()) {
     Expected<MemoryBufferRef> fatLTOData =
         IRObjectFile::findBitcodeInObject(*coffObj);
 
@@ -408,7 +408,7 @@ void LinkerDriver::handleReproFile(StringRef path, InputOpt inputOpt) {
 
 void LinkerDriver::enqueuePath(StringRef path, bool lazy, InputOpt inputOpt) {
   auto future = std::make_shared<std::future<MBErrPair>>(
-      createFutureForFile(std::string(path), ctx.config.prefetchInputs));
+      createFutureForFile(std::string(path), ctx.config.getPrefetchInputs()));
   std::string pathStr = std::string(path);
   enqueueTask([=]() {
     llvm::TimeTraceScope timeScope("File: ", path);
@@ -429,7 +429,7 @@ void LinkerDriver::enqueuePath(StringRef path, bool lazy, InputOpt inputOpt) {
           mb = std::move(*retryMb);
           // Prefetch memory pages in the background as we will need them soon
           // enough.
-          if (ctx.config.prefetchInputs)
+          if (ctx.config.getPrefetchInputs())
             mb->willNeedIfMmap();
         }
       } else {
@@ -528,7 +528,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
             "could not get the filename for the member defining symbol " +
                 toCOFFString(ctx, sym));
   auto future = std::make_shared<std::future<MBErrPair>>(
-      createFutureForFile(childName, ctx.config.prefetchInputs));
+      createFutureForFile(childName, ctx.config.getPrefetchInputs()));
   enqueueTask([=]() {
     auto mbOrErr = future->get();
     if (mbOrErr.second)
@@ -751,7 +751,7 @@ StringRef LinkerDriver::findLib(StringRef filename) {
 // consideration. This never returns the same path (in that case,
 // it returns std::nullopt).
 std::optional<StringRef> LinkerDriver::findLibIfNew(StringRef filename) {
-  if (ctx.config.noDefaultLibAll)
+  if (ctx.config.getNoDefaultLibAll())
     return std::nullopt;
   if (!visitedLibs.insert(filename.lower()).second)
     return std::nullopt;
@@ -927,8 +927,8 @@ void LinkerDriver::addLibSearchPaths() {
 
 uint64_t LinkerDriver::getDefaultImageBase() {
   if (ctx.config.is64())
-    return ctx.config.dll ? 0x180000000 : 0x140000000;
-  return ctx.config.dll ? 0x10000000 : 0x400000;
+    return ctx.config.getDll() ? 0x180000000 : 0x140000000;
+  return ctx.config.getDll() ? 0x10000000 : 0x400000;
 }
 
 static std::string rewritePath(StringRef s) {
@@ -1069,8 +1069,8 @@ std::string LinkerDriver::getImportName(bool asLib) {
   } else {
     out.assign(ctx.config.importName);
     if (!sys::path::has_extension(out))
-      sys::path::replace_extension(out,
-                                   (ctx.config.dll || asLib) ? ".dll" : ".exe");
+      sys::path::replace_extension(
+          out, (ctx.config.getDll() || asLib) ? ".dll" : ".exe");
   }
 
   return std::string(out);
@@ -1491,7 +1491,7 @@ void LinkerDriver::pullArm64ECIcallHelper() {
 // than MinGW in the case that nothing is explicitly exported.
 void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
   if (!args.hasArg(OPT_export_all_symbols)) {
-    if (!ctx.config.dll)
+    if (!ctx.config.getDll())
       return;
 
     if (ctx.symtab.hadExplicitExports ||
@@ -1777,8 +1777,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   // Handle /verbose
   if (args.hasArg(OPT_verbose))
-    config->verbose = true;
-  ctx.e.verbose = config->verbose;
+    config->setVerbose(true);
+  ctx.e.verbose = config->getVerbose();
 
   // Handle /force or /force:unresolved
   if (args.hasArg(OPT_force, OPT_force_unresolved))
@@ -1851,7 +1851,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   }
 
   // Handle /demangle
-  config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no, true);
+  config->setDemangle(args.hasFlag(OPT_demangle, OPT_demangle_no, true));
 
   // Handle /debugtype
   config->debugTypes = parseDebugTypes(ctx, args);
@@ -1903,7 +1903,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   // Handle /dll
   if (args.hasArg(OPT_dll)) {
-    config->dll = true;
+    config->setDll(true);
     config->manifestID = 2;
   }
 
@@ -1953,7 +1953,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   // Handle /nodefaultlib
   if (args.hasArg(OPT_nodefaultlib_all))
-    config->noDefaultLibAll = true;
+    config->setNoDefaultLibAll(true);
 
   // Handle /base
   if (auto *arg = args.getLastArg(OPT_base))
@@ -2035,7 +2035,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   if (auto *arg = args.getLastArg(OPT_implib))
     config->implib = arg->getValue();
 
-  config->noimplib = args.hasArg(OPT_noimplib);
+  config->setNoimplib(args.hasArg(OPT_noimplib));
 
   if (args.hasArg(OPT_profile))
     doGC = true;
@@ -2091,11 +2091,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
 
   if (!icfLevel)
     icfLevel = doGC ? ICFLevel::All : ICFLevel::None;
-  config->doGC = doGC;
+  config->setDoGC(doGC);
   config->doICF = *icfLevel;
   config->tailMerge =
       (tailMerge == 1 && config->doICF != ICFLevel::None) || tailMerge == 2;
-  config->ltoDebugPassManager = ltoDebugPM;
+  config->setLtoDebugPassManager(ltoDebugPM);
 
   // Handle /lldsavetemps
   if (args.hasArg(OPT_lldsavetemps)) {
@@ -2221,8 +2221,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   config->dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor);
 
   // Handle /thinlto-distributor-arg:<arg>
-  config->dtltoDistributorArgs =
-      args::getStrings(args, OPT_thinlto_distributor_arg);
+  config->dtltoDistributorArgs.assign(
+      args::getStrings(args, OPT_thinlto_distributor_arg));
 
   // Handle /thinlto-remote-compiler:<path>
   config->dtltoCompiler = args.getLastArgValue(OPT_thinlto_remote_compiler);
@@ -2231,16 +2231,16 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
                 "/thinlto-distributor is specified.";
 
   // Handle /thinlto-remote-compiler-prepend-arg:<arg>
-  config->dtltoCompilerPrependArgs =
-      args::getStrings(args, OPT_thinlto_remote_compiler_prepend_arg);
+  config->dtltoCompilerPrependArgs.assign(
+      args::getStrings(args, OPT_thinlto_remote_compiler_prepend_arg));
 
   // Handle /thinlto-remote-compiler-arg:<arg>
-  config->dtltoCompilerArgs =
-      args::getStrings(args, OPT_thinlto_remote_compiler_arg);
+  config->dtltoCompilerArgs.assign(
+      args::getStrings(args, OPT_thinlto_remote_compiler_arg));
 
   // Handle /fat-lto-objects
-  config->fatLTOObjects =
-      args.hasFlag(OPT_fat_lto_objects, OPT_fat_lto_objects_no, false);
+  config->setFatLTOObjects(
+      args.hasFlag(OPT_fat_lto_objects, OPT_fat_lto_objects_no, false));
 
   // Handle /dwodir
   config->dwoDir = args.getLastArgValue(OPT_dwodir);
@@ -2256,18 +2256,18 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   config->thinLTOObjectSuffixReplace =
       getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace);
   config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path);
-  config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
+  config->setLtoCSProfileGenerate(args.hasArg(OPT_lto_cs_profile_generate));
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
   config->ltoSampleProfileName = args.getLastArgValue(OPT_lto_sample_profile);
   // Handle miscellaneous boolean flags.
-  config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
-                                            OPT_lto_pgo_warn_mismatch_no, true);
+  config->setLtoPGOWarnMismatch(args.hasFlag(
+      OPT_lto_pgo_warn_mismatch, OPT_lto_pgo_warn_mismatch_no, true));
   config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
   config->allowIsolation =
       args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
   config->incremental =
       args.hasFlag(OPT_incremental, OPT_incremental_no,
-                   !config->doGC && config->doICF == ICFLevel::None &&
+                   !config->getDoGC() && config->doICF == ICFLevel::None &&
                        !args.hasArg(OPT_order) && !args.hasArg(OPT_profile));
   config->integrityCheck =
       args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
@@ -2284,19 +2284,19 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   for (auto *arg : args.filtered(OPT_swaprun))
     parseSwaprun(arg->getValue());
   config->terminalServerAware =
-      !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
+      !config->getDll() && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
   config->autoImport =
       args.hasFlag(OPT_auto_import, OPT_auto_import_no, config->mingw);
   config->pseudoRelocs = args.hasFlag(
       OPT_runtime_pseudo_reloc, OPT_runtime_pseudo_reloc_no, config->mingw);
-  config->callGraphProfileSort = args.hasFlag(
-      OPT_call_graph_profile_sort, OPT_call_graph_profile_sort_no, true);
+  config->setCallGraphProfileSort(args.hasFlag(
+      OPT_call_graph_profile_sort, OPT_call_graph_profile_sort_no, true));
   config->stdcallFixup =
       args.hasFlag(OPT_stdcall_fixup, OPT_stdcall_fixup_no, config->mingw);
   config->warnStdcallFixup = !args.hasArg(OPT_stdcall_fixup);
-  config->allowDuplicateWeak =
-      args.hasFlag(OPT_lld_allow_duplicate_weak,
-                   OPT_lld_allow_duplicate_weak_no, config->mingw);
+  config->setAllowDuplicateWeak(args.hasFlag(OPT_lld_allow_duplicate_weak,
+                                             OPT_lld_allow_duplicate_weak_no,
+                                             config->mingw));
 
   if (args.hasFlag(OPT_inferasanlibs, OPT_inferasanlibs_no, false))
     Warn(ctx) << "ignoring '/inferasanlibs', this flag is not supported";
@@ -2311,7 +2311,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     config->incremental = false;
   }
 
-  if (config->incremental && config->doGC) {
+  if (config->incremental && config->getDoGC()) {
     Warn(ctx) << "ignoring '/incremental' because REF is enabled; use "
                  "'/opt:noref' to "
                  "disable";
@@ -2326,12 +2326,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   }
 
   if (args.hasFlag(OPT_prefetch_inputs, OPT_prefetch_inputs_no, false))
-    config->prefetchInputs = true;
+    config->setPrefetchInputs(true);
 
   config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
   config->optRemarksPasses = args.getLastArgValue(OPT_opt_remarks_passes);
   config->optRemarksFormat = args.getLastArgValue(OPT_opt_remarks_format);
-  config->optRemarksWithHotness = args.hasArg(OPT_opt_remarks_with_hotness);
+  config->setOptRemarksWithHotness(args.hasArg(OPT_opt_remarks_with_hotness));
   if (auto *arg = args.getLastArg(OPT_opt_remarks_hotness_threshold)) {
     auto resultOrErr = remarks::parseHotnessThresholdOption(arg->getValue());
     if (!resultOrErr)
@@ -2523,7 +2523,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // Handle generation of import library from a def file.
   if (!args.hasArg(OPT_INPUT, OPT_wholearchive_file)) {
     ctx.forEachSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
-    if (!config->noimplib)
+    if (!config->getNoimplib())
       createImportLibrary(/*asLib=*/true);
     return;
   }
@@ -2584,7 +2584,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   if (config->outputFile.empty()) {
     config->outputFile = getOutputPath(
         (*args.filtered(OPT_INPUT, OPT_wholearchive_file).begin())->getValue(),
-        config->dll, config->driver);
+        config->getDll(), config->driver);
   }
 
   // Fail early if an output file is not writable.
@@ -2601,7 +2601,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     for (auto *arg : args.filtered(OPT_map_info)) {
       std::string s = StringRef(arg->getValue()).lower();
       if (s == "exports")
-        config->mapInfo = true;
+        config->setMapInfo(true);
       else
         Err(ctx) << "unknown option: /mapinfo:" << s;
     }
@@ -2875,7 +2875,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   });
 
   // Identify unreferenced COMDAT sections.
-  if (config->doGC) {
+  if (config->getDoGC()) {
     if (config->mingw) {
       // markLive doesn't traverse .eh_frame, but the personality function is
       // only reached that way. The proper solution would be to parse and
@@ -2925,11 +2925,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // Windows specific -- when we are creating a .dll file, we also
   // need to create a .lib file. In MinGW mode, we only do that when the
   // -implib option is given explicitly, for compatibility with GNU ld.
-  if (config->dll || !ctx.symtab.exports.empty() ||
+  if (config->getDll() || !ctx.symtab.exports.empty() ||
       (ctx.config.machine == ARM64X && !ctx.hybridSymtab->exports.empty())) {
     llvm::TimeTraceScope timeScope("Create .lib exports");
     ctx.forEachActiveSymtab([](SymbolTable &symtab) { symtab.fixupExports(); });
-    if (!config->noimplib && (!config->mingw || !config->implib.empty()))
+    if (!config->getNoimplib() && (!config->mingw || !config->implib.empty()))
       createImportLibrary(/*asLib=*/false);
     ctx.forEachActiveSymtab(
         [](SymbolTable &symtab) { symtab.assignExportOrdinals(); });
@@ -2979,11 +2979,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     if (args.hasArg(OPT_call_graph_ordering_file))
       Err(ctx) << "/order and /call-graph-order-file may not be used together";
     parseOrderFile(arg->getValue());
-    config->callGraphProfileSort = false;
+    config->setCallGraphProfileSort(false);
   }
 
   // Handle /call-graph-ordering-file and /call-graph-profile-sort (default on).
-  if (config->callGraphProfileSort) {
+  if (config->getCallGraphProfileSort()) {
     llvm::TimeTraceScope timeScope("Call graph");
     if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file))
       parseCallGraphFile(arg->getValue());
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 265ddee6d8557..6d3422891d5c7 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -328,7 +328,7 @@ void LinkerDriver::parseManifest(StringRef arg) {
 // Results are directly written to Config.
 void LinkerDriver::parseManifestUAC(StringRef arg) {
   if (arg.equals_insensitive("no")) {
-    ctx.config.manifestUAC = false;
+    ctx.config.setManifestUAC(false);
     return;
   }
   for (;;) {
@@ -441,7 +441,7 @@ std::string LinkerDriver::createDefaultXml() {
   os << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
      << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"
      << "          manifestVersion=\"1.0\">\n";
-  if (ctx.config.manifestUAC) {
+  if (ctx.config.getManifestUAC()) {
     os << "  <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n"
        << "    <security>\n"
        << "      <requestedPrivileges>\n"
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index fd4858581ed54..7a1e314dfa186 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -87,7 +87,7 @@ static void checkAndSetWeakAlias(SymbolTable &symtab, InputFile *f,
         // Weak aliases as produced by GCC are named in the form
         // .weak.<weaksymbol>.<othersymbol>, where <othersymbol> is the name
         // of another symbol emitted near the weak symbol.
-        if (symtab.ctx.config.allowDuplicateWeak) {
+        if (symtab.ctx.config.getAllowDuplicateWeak()) {
           auto isAbsZero = [](Symbol *sym) -> bool {
             return isa<DefinedAbsolute>(sym) &&
                    dyn_cast<DefinedAbsolute>(sym)->getVA() == 0;
@@ -1228,7 +1228,7 @@ void ObjFile::enqueuePdbFile(StringRef path, ObjFile *fromFile) {
 
 ImportFile::ImportFile(COFFLinkerContext &ctx, MemoryBufferRef m)
     : InputFile(ctx.getSymtab(getMachineType(m)), ImportKind, m),
-      live(!ctx.config.doGC) {}
+      live(!ctx.config.getDoGC()) {}
 
 MachineTypes ImportFile::getMachineType(MemoryBufferRef m) {
   uint16_t machine =
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index 0e335d647175c..8c813baaf71fd 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -88,16 +88,16 @@ lto::Config BitcodeCompiler::createConfig() {
   assert(optLevelOrNone && "Invalid optimization level!");
   c.CGOptLevel = *optLevelOrNone;
   c.AlwaysEmitRegularLTOObj = !ctx.config.ltoObjPath.empty();
-  c.DebugPassManager = ctx.config.ltoDebugPassManager;
+  c.DebugPassManager = ctx.config.getLtoDebugPassManager();
   c.CSIRProfile = std::string(ctx.config.ltoCSProfileFile);
-  c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate;
-  c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch;
+  c.RunCSIRInstr = ctx.config.getLtoCSProfileGenerate();
+  c.PGOWarnMismatch = ctx.config.getLtoPGOWarnMismatch();
   c.SampleProfile = ctx.config.ltoSampleProfileName;
   c.TimeTraceEnabled = ctx.config.timeTraceEnabled;
   c.TimeTraceGranularity = ctx.config.timeTraceGranularity;
   c.RemarksFilename = ctx.config.optRemarksFilename;
   c.RemarksPasses = ctx.config.optRemarksPasses;
-  c.RemarksWithHotness = ctx.config.optRemarksWithHotness;
+  c.RemarksWithHotness = ctx.config.getOptRemarksWithHotness();
   c.RemarksHotnessThreshold = ctx.config.optRemarksHotnessThreshold;
   c.RemarksFormat = ctx.config.optRemarksFormat;
 
@@ -153,8 +153,10 @@ BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {
         llvm::lto::LTO::LTOKind::LTOK_Default, nullptr,
         ctx.config.thinLTOEmitImportsFiles, ctx.config.thinLTOIndexOnly,
         ctx.config.outputFile, ctx.config.dtltoDistributor,
-        ctx.config.dtltoDistributorArgs, ctx.config.dtltoCompiler,
-        ctx.config.dtltoCompilerPrependArgs, ctx.config.dtltoCompilerArgs,
+        ArrayRef<StringRef>(ctx.config.dtltoDistributorArgs),
+        ctx.config.dtltoCompiler,
+        ArrayRef<StringRef>(ctx.config.dtltoCompilerPrependArgs),
+        ArrayRef<StringRef>(ctx.config.dtltoCompilerArgs),
         createAddBufferFn(files, file_names),
         !ctx.config.saveTempsArgs.empty());
 }
diff --git a/lld/COFF/MapFile.cpp b/lld/COFF/MapFile.cpp
index 90ebacbe48d44..d1d6ffce065ff 100644
--- a/lld/COFF/MapFile.cpp
+++ b/lld/COFF/MapFile.cpp
@@ -319,7 +319,7 @@ void lld::coff::writeMapFile(COFFLinkerContext &ctx) {
     os << staticSymStr[sym] << '\n';
 
   // Print out the exported functions
-  if (ctx.config.mapInfo) {
+  if (ctx.config.getMapInfo()) {
     os << "\n";
     os << " Exports\n";
     os << "\n";
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index ea5bdbc0be489..61566f2e74f50 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -1120,7 +1120,7 @@ StringRef SymbolTable::findDefaultEntry() {
 }
 
 WindowsSubsystem SymbolTable::inferSubsystem() {
-  if (ctx.config.dll)
+  if (ctx.config.getDll())
     return IMAGE_SUBSYSTEM_WINDOWS_GUI;
   if (ctx.config.mingw)
     return IMAGE_SUBSYSTEM_WINDOWS_CUI;
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index ba4f95d14bc64..a03c6b7033b1e 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -25,7 +25,7 @@ static_assert(sizeof(SymbolUnion) <= 48,
 // Returns a symbol name for an error message.
 std::string maybeDemangleSymbol(const COFFLinkerContext &ctx,
                                 StringRef symName) {
-  if (ctx.config.demangle) {
+  if (ctx.config.getDemangle()) {
     std::string prefix;
     StringRef prefixless = symName;
     if (prefixless.consume_front("__imp_"))
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 3cab426df55cf..48e3c437836ea 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1113,7 +1113,7 @@ void Writer::createSections() {
   for (Chunk *c : ctx.driver.getChunks()) {
     auto *sc = dyn_cast<SectionChunk>(c);
     if (sc && !sc->live) {
-      if (ctx.config.verbose)
+      if (ctx.config.getVerbose())
         sc->printDiscardedMessage();
       continue;
     }
@@ -1888,7 +1888,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
     coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
   if (!config->is64())
     coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
-  if (config->dll)
+  if (config->getDll())
     coff->Characteristics |= IMAGE_FILE_DLL;
   if (config->driverUponly)
     coff->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY;
@@ -2797,7 +2797,7 @@ void Writer::sortCRTSectionChunks(std::vector<Chunk *> &chunks) {
   };
   llvm::stable_sort(chunks, sectionChunkOrder);
 
-  if (ctx.config.verbose) {
+  if (ctx.config.getVerbose()) {
     for (auto &c : chunks) {
       auto sc = dyn_cast<SectionChunk>(c);
       Log(ctx) << "  " << sc->file->mb.getBufferIdentifier().str()
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 5d0c5dbd0065c..347ac7257fb25 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -375,7 +375,7 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       rs.handleTlsDesc(R_TLSDESC, R_GOT, type, offset, addend, sym);
       continue;
     case R_AARCH64_TLSDESC_CALL:
-      if (!ctx.arg.shared)
+      if (!ctx.arg.getShared())
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
@@ -405,7 +405,7 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     rs.process(expr, type, offset, sym, addend);
   }
 
-  if (ctx.arg.branchToBranch)
+  if (ctx.arg.getBranchToBranch())
     llvm::stable_sort(sec.relocs(),
                       [](auto &l, auto &r) { return l.offset < r.offset; });
 }
@@ -841,7 +841,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     break;
   case R_AARCH64_TLSLE_ADD_TPREL_HI12:
     checkUInt(ctx, loc, val, 24, rel);
-    if (ctx.arg.relax && (val >> 12) == 0) {
+    if (ctx.arg.getRelax() && (val >> 12) == 0) {
       uint32_t inst = read32le(loc);
       // The W-form zero-extends Xd, so only the X-form is a nop.
       if ((inst & (1u << 31)) && (inst & 0x1f) == ((inst >> 5) & 0x1f)) {
@@ -985,7 +985,7 @@ void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
 AArch64Relaxer::AArch64Relaxer(Ctx &ctx, ArrayRef<Relocation> relocs,
                                uint64_t secAddr, uint8_t *buf)
     : ctx(ctx) {
-  if (!ctx.arg.relax)
+  if (!ctx.arg.getRelax())
     return;
   // For a given symbol R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC
   // relaxation is all-or-nothing. We can't relax only some of them, as there
@@ -1018,7 +1018,7 @@ bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel,
   // to
   // NOP
   // ADR xn, sym
-  if (!ctx.arg.relax || addRel.type != R_AARCH64_ADD_ABS_LO12_NC)
+  if (!ctx.arg.getRelax() || addRel.type != R_AARCH64_ADD_ABS_LO12_NC)
     return false;
   // Check if the relocations apply to consecutive instructions.
   if (adrpRel.offset + 4 != addRel.offset)
@@ -1090,7 +1090,7 @@ bool AArch64Relaxer::isLegalAdrpLdrRelaxationCandidate(
   // GOT references to absolute symbols can't be relaxed to use ADRP/ADD in
   // position-independent code because these instructions produce a relative
   // address.
-  if (ctx.arg.isPic && !cast<Defined>(sym).section)
+  if (ctx.arg.getIsPic() && !cast<Defined>(sym).section)
     return false;
   // Check if the address difference is within 4GB range.
   int64_t val =
@@ -1112,7 +1112,7 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
   // ADRP xn, sym
   // ADD xn, xn, :lo_12: sym
 
-  if (!ctx.arg.relax || adrpRel.type != R_AARCH64_ADR_GOT_PAGE ||
+  if (!ctx.arg.getRelax() || adrpRel.type != R_AARCH64_ADR_GOT_PAGE ||
       ldrRel.type != R_AARCH64_LD64_GOT_LO12_NC)
     return false;
 
@@ -1343,7 +1343,7 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) {
   // PAuthABI, which requires v8.3-A, we can use the non-hint space
   // instructions.
 
-  if (ctx.arg.zPacPlt) {
+  if (ctx.arg.getZPacPlt()) {
     if (ctx.aarch64PauthAbiCoreInfo && ctx.aarch64PauthAbiCoreInfo->isValid())
       pacEntryKind = PEK_Auth;
     else
@@ -1553,7 +1553,7 @@ void elf::createTaggedSymbols(Ctx &ctx) {
 
 void elf::setAArch64TargetInfo(Ctx &ctx) {
   if ((ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) ||
-      ctx.arg.zPacPlt)
+      ctx.arg.getZPacPlt())
     ctx.target.reset(new AArch64BtiPac(ctx));
   else
     ctx.target.reset(new AArch64(ctx));
diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index e1f73b991f1f3..a47642f6d5a47 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -133,7 +133,7 @@ uint32_t ARM::calcEFlags() const {
   else if (ctx.arg.armVFPArgs == ARMVFPArgKind::VFP)
     abiFloatType = EF_ARM_ABI_FLOAT_HARD;
 
-  if (!ctx.arg.isLE && ctx.arg.armBe8)
+  if (!ctx.arg.getIsLE() && ctx.arg.getArmBe8())
     armBE8 = EF_ARM_BE8;
 
   // We don't currently use any features incompatible with EF_ARM_EABI_VER5,
@@ -273,7 +273,7 @@ void ARM::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 
     // Platform-specific relocations:
     case R_ARM_TARGET1:
-      expr = ctx.arg.target1Rel ? R_PC : R_ABS;
+      expr = ctx.arg.getTarget1Rel() ? R_PC : R_ABS;
       break;
     case R_ARM_TARGET2:
       if (ctx.arg.target2 == Target2Policy::Rel)
@@ -315,7 +315,8 @@ void ARM::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 }
 
 RelType ARM::getDynRel(RelType type) const {
-  if ((type == R_ARM_ABS32) || (type == R_ARM_TARGET1 && !ctx.arg.target1Rel))
+  if ((type == R_ARM_ABS32) ||
+      (type == R_ARM_TARGET1 && !ctx.arg.getTarget1Rel()))
     return R_ARM_ABS32;
   return R_ARM_NONE;
 }
@@ -1399,7 +1400,7 @@ void elf::processArmCmseSymbols(Ctx &ctx) {
       continue;
     // If input object build attributes do not support CMSE, error and disable
     // further scanning for <sym>, __acle_se_<sym> pairs.
-    if (!ctx.arg.armCMSESupport) {
+    if (!ctx.arg.getArmCMSESupport()) {
       Err(ctx) << "CMSE is only supported by ARMv8-M architecture or later";
       ctx.arg.cmseImplib = false;
       break;
@@ -1621,7 +1622,7 @@ template <typename ELFT> void elf::writeARMCmseImportLib(Ctx &ctx) {
   eHdr->e_entry = 0;
   eHdr->e_shoff = sectionHeaderOff;
   eHdr->e_ident[EI_CLASS] = ELFCLASS32;
-  eHdr->e_ident[EI_DATA] = ctx.arg.isLE ? ELFDATA2LSB : ELFDATA2MSB;
+  eHdr->e_ident[EI_DATA] = ctx.arg.getIsLE() ? ELFDATA2LSB : ELFDATA2MSB;
   eHdr->e_ident[EI_VERSION] = EV_CURRENT;
   eHdr->e_ident[EI_OSABI] = ctx.arg.osabi;
   eHdr->e_ident[EI_ABIVERSION] = 0;
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 6c65b74b716f2..3ec9c2fb12a65 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -40,7 +40,7 @@ class LoongArch final : public TargetInfo {
   template <class ELFT, class RelTy>
   void scanSectionImpl(InputSectionBase &, Relocs<RelTy>, unsigned shard);
   void scanSection(InputSectionBase &sec, unsigned shard) override {
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       elf::scanSection1<LoongArch, ELF64LE>(*this, sec, shard);
     else
       elf::scanSection1<LoongArch, ELF32LE>(*this, sec, shard);
@@ -233,7 +233,7 @@ LoongArch::LoongArch(Ctx &ctx) : TargetInfo(ctx) {
   relativeRel = R_LARCH_RELATIVE;
   iRelativeRel = R_LARCH_IRELATIVE;
 
-  if (ctx.arg.is64) {
+  if (ctx.arg.getIs64()) {
     symbolicRel = R_LARCH_64;
     tlsModuleIndexRel = R_LARCH_TLS_DTPMOD64;
     tlsOffsetRel = R_LARCH_TLS_DTPREL64;
@@ -258,7 +258,7 @@ LoongArch::LoongArch(Ctx &ctx) : TargetInfo(ctx) {
 }
 
 static uint32_t getEFlags(Ctx &ctx, const InputFile *f) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader().e_flags;
   return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags;
 }
@@ -338,7 +338,7 @@ int64_t LoongArch::getImplicitAddend(const uint8_t *buf, RelType type) const {
     return read64le(buf);
   case R_LARCH_RELATIVE:
   case R_LARCH_IRELATIVE:
-    return ctx.arg.is64 ? read64le(buf) : read32le(buf);
+    return ctx.arg.getIs64() ? read64le(buf) : read32le(buf);
   case R_LARCH_NONE:
   case R_LARCH_JUMP_SLOT:
     // These relocations are defined as not having an implicit addend.
@@ -351,7 +351,7 @@ int64_t LoongArch::getImplicitAddend(const uint8_t *buf, RelType type) const {
 }
 
 void LoongArch::writeGotPlt(uint8_t *buf, const Symbol &s) const {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     write64le(buf, ctx.in.plt->getVA());
   else
     write32le(buf, ctx.in.plt->getVA());
@@ -359,7 +359,7 @@ void LoongArch::writeGotPlt(uint8_t *buf, const Symbol &s) const {
 
 void LoongArch::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
   if (ctx.arg.writeAddends) {
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       write64le(buf, s.getVA(ctx));
     else
       write32le(buf, s.getVA(ctx));
@@ -386,17 +386,17 @@ void LoongArch::writePltHeader(uint8_t *buf) const {
   //   ld.[wd]   $t0, $t0, Wordsize               ; t0 = link_map
   //   jr        $t3
   uint32_t offset = ctx.in.gotPlt->getVA() - ctx.in.plt->getVA();
-  uint32_t sub = ctx.arg.is64 ? SUB_D : SUB_W;
-  uint32_t ld = ctx.arg.is64 ? LD_D : LD_W;
-  uint32_t addi = ctx.arg.is64 ? ADDI_D : ADDI_W;
-  uint32_t srli = ctx.arg.is64 ? SRLI_D : SRLI_W;
+  uint32_t sub = ctx.arg.getIs64() ? SUB_D : SUB_W;
+  uint32_t ld = ctx.arg.getIs64() ? LD_D : LD_W;
+  uint32_t addi = ctx.arg.getIs64() ? ADDI_D : ADDI_W;
+  uint32_t srli = ctx.arg.getIs64() ? SRLI_D : SRLI_W;
   write32le(buf + 0, insn(PCADDU12I, R_T2, hi20(offset), 0));
   write32le(buf + 4, insn(sub, R_T1, R_T1, R_T3));
   write32le(buf + 8, insn(ld, R_T3, R_T2, lo12(offset)));
   write32le(buf + 12,
             insn(addi, R_T1, R_T1, lo12(-ctx.target->pltHeaderSize - 12)));
   write32le(buf + 16, insn(addi, R_T0, R_T2, lo12(offset)));
-  write32le(buf + 20, insn(srli, R_T1, R_T1, ctx.arg.is64 ? 1 : 2));
+  write32le(buf + 20, insn(srli, R_T1, R_T1, ctx.arg.getIs64() ? 1 : 2));
   write32le(buf + 24, insn(ld, R_T0, R_T0, ctx.arg.wordsize));
   write32le(buf + 28, insn(JIRL, R_ZERO, R_T3, 0));
 }
@@ -413,7 +413,7 @@ void LoongArch::writePlt(uint8_t *buf, const Symbol &sym,
   uint32_t offset = sym.getGotPltVA(ctx) - pltEntryAddr;
   write32le(buf + 0, insn(PCADDU12I, R_T3, hi20(offset), 0));
   write32le(buf + 4,
-            insn(ctx.arg.is64 ? LD_D : LD_W, R_T3, R_T3, lo12(offset)));
+            insn(ctx.arg.getIs64() ? LD_D : LD_W, R_T3, R_T3, lo12(offset)));
   write32le(buf + 8, insn(JIRL, R_T1, R_T3, 0));
   write32le(buf + 12, insn(ANDI, R_ZERO, R_ZERO, 0));
 }
@@ -679,7 +679,7 @@ void LoongArch::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
                        addend, sym);
       continue;
     case R_LARCH_TLS_DESC_CALL:
-      if (!ctx.arg.shared)
+      if (!ctx.arg.getShared())
         sec.addReloc(
             {sym.isPreemptible ? R_GOT : R_TPREL, type, offset, addend, &sym});
       continue;
@@ -702,7 +702,7 @@ void LoongArch::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     // Relaxation hints:
     case R_LARCH_TLS_LE_ADD_R:
     case R_LARCH_RELAX:
-      if (ctx.arg.relax)
+      if (ctx.arg.getRelax())
         sec.addReloc({R_RELAX_HINT, type, offset, addend, &sym});
       continue;
     case R_LARCH_ALIGN:
@@ -1081,8 +1081,8 @@ bool LoongArch::synthesizeAlignAux(uint64_t &dot, InputSection *sec) {
 // output relocation section is updated with all the newly synthesized ALIGN
 // relocations.
 bool LoongArch::synthesizeAlign(uint64_t &dot, InputSection *sec) {
-  assert(ctx.arg.relocatable);
-  if (ctx.arg.is64)
+  assert(ctx.arg.getRelocatable());
+  if (ctx.arg.getIs64())
     return synthesizeAlignAux<ELF64LE>(dot, sec);
   return synthesizeAlignAux<ELF32LE>(dot, sec);
 }
@@ -1137,7 +1137,7 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
   if (rHi20.type == R_LARCH_GOT_PC_HI20 &&
       (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() ||
        rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() ||
-       (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section) ||
+       (ctx.arg.getIsPic() && !cast<Defined>(*rHi20.sym).section) ||
        rHi20.addend != 0 || rLo12.addend != 0))
     return;
 
@@ -1450,7 +1450,7 @@ void LoongArch::tlsdescToIe(uint8_t *loc, const Relocation &rel,
     relocateNoSym(loc, R_LARCH_TLS_IE_PC_HI20, val);
     break;
   case R_LARCH_TLS_DESC_CALL:
-    write32le(loc, insn(ctx.arg.is64 ? LD_D : LD_W, R_A0, R_A0,
+    write32le(loc, insn(ctx.arg.getIs64() ? LD_D : LD_W, R_A0, R_A0,
                         0)); // ld.[wd] $a0, $a0, %ie_pc_lo12
     relocateNoSym(loc, R_LARCH_TLS_IE_PC_LO12, val);
     break;
@@ -1522,7 +1522,7 @@ bool LoongArch::tryGotToPCRel(uint8_t *loc, const Relocation &rHi20,
   // GOT references to absolute symbols can't be relaxed to use PCALAU12I/ADDI
   // in position-independent code because these instructions produce a relative
   // address.
-  if ((ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section))
+  if ((ctx.arg.getIsPic() && !cast<Defined>(*rHi20.sym).section))
     return false;
 
   // Check if the addends of the both relocations are zero.
@@ -1531,7 +1531,7 @@ bool LoongArch::tryGotToPCRel(uint8_t *loc, const Relocation &rHi20,
 
   const uint32_t currInsn = read32le(loc);
   const uint32_t nextInsn = read32le(loc + 4);
-  const uint32_t ldOpcode = ctx.arg.is64 ? LD_D : LD_W;
+  const uint32_t ldOpcode = ctx.arg.getIs64() ? LD_D : LD_W;
   // Check if the first instruction is PCALAU12I and the second instruction is
   // LD.
   if ((currInsn & 0xfe000000) != PCALAU12I ||
@@ -1562,7 +1562,7 @@ bool LoongArch::tryGotToPCRel(uint8_t *loc, const Relocation &rHi20,
   write32le(loc, insn(PCALAU12I, getD5(currInsn), 0, 0));
   relocate(loc, newRHi20, pageDelta);
   // addi.w/d $a0, $a0, %pc_lo12
-  write32le(loc + 4, insn(ctx.arg.is64 ? ADDI_D : ADDI_W, getD5(nextInsn),
+  write32le(loc + 4, insn(ctx.arg.getIs64() ? ADDI_D : ADDI_W, getD5(nextInsn),
                           getJ5(nextInsn), 0));
   relocate(loc + 4, newRLo12, SignExtend64(symLocal, 64));
   return true;
@@ -1601,7 +1601,7 @@ static bool pairForGotRels(ArrayRef<Relocation> relocs) {
 }
 
 void LoongArch::relocateAlloc(InputSection &sec, uint8_t *buf) const {
-  const unsigned bits = ctx.arg.is64 ? 64 : 32;
+  const unsigned bits = ctx.arg.getIs64() ? 64 : 32;
   uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff;
   bool isExtreme = false;
   const MutableArrayRef<Relocation> relocs = sec.relocs();
diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp
index 308a0f75e588d..500e3fc47db7e 100644
--- a/lld/ELF/Arch/Mips.cpp
+++ b/lld/ELF/Arch/Mips.cpp
@@ -126,7 +126,7 @@ template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const {
 }
 
 template <class ELFT> void MIPS<ELFT>::initTargetSpecificSections() {
-  if (!ctx.arg.shared && ctx.hasDynsym) {
+  if (!ctx.arg.getShared() && ctx.getHasDynsym()) {
     ctx.in.mipsRldMap = std::make_unique<RldMapSection>(ctx);
     ctx.inputSections.push_back(ctx.in.mipsRldMap.get());
   }
@@ -373,7 +373,7 @@ template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {
     write32(ctx, buf + 20, 0x0018c082); // srl   $24, $24, 2
   }
 
-  uint32_t jalrInst = ctx.arg.zHazardplt ? 0x0320fc09 : 0x0320f809;
+  uint32_t jalrInst = ctx.arg.getZHazardplt() ? 0x0320fc09 : 0x0320f809;
   write32(ctx, buf + 24, jalrInst);   // jalr.hb $25 or jalr $25
   write32(ctx, buf + 28, 0x2718fffe); // subu  $24, $24, 2
 
@@ -409,8 +409,8 @@ void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,
 
   uint32_t loadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000;
   uint32_t jrInst = isMipsR6(ctx)
-                        ? (ctx.arg.zHazardplt ? 0x03200409 : 0x03200009)
-                        : (ctx.arg.zHazardplt ? 0x03200408 : 0x03200008);
+                        ? (ctx.arg.getZHazardplt() ? 0x03200409 : 0x03200009)
+                        : (ctx.arg.getZHazardplt() ? 0x03200408 : 0x03200008);
   uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000;
 
   write32(ctx, buf, 0x3c0f0000);   // lui   $15, %hi(.got.plt entry)
@@ -533,7 +533,7 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case (R_MIPS_64 << 8) | R_MIPS_REL32:
     return read64(ctx, buf);
   case R_MIPS_COPY:
-    return ctx.arg.is64 ? read64(ctx, buf) : read32(ctx, buf);
+    return ctx.arg.getIs64() ? read64(ctx, buf) : read32(ctx, buf);
   case R_MIPS_NONE:
   case R_MIPS_JUMP_SLOT:
   case R_MIPS_JALR:
@@ -639,7 +639,7 @@ static RelType getMipsN32RelType(Ctx &ctx, RelTy *&rel, RelTy *end) {
   uint64_t offset = rel->r_offset;
   int n = 0;
   while (rel != end && rel->r_offset == offset)
-    type |= (rel++)->getType(ctx.arg.isMips64EL) << (8 * n++);
+    type |= (rel++)->getType(ctx.arg.getIsMips64EL()) << (8 * n++);
   return type;
 }
 
@@ -679,18 +679,18 @@ void MIPS<ELFT>::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     const RelTy &rel = *it;
     uint64_t offset = rel.r_offset;
     if constexpr (ELFT::Is64Bits) {
-      type = it->getType(ctx.arg.isMips64EL);
+      type = it->getType(ctx.arg.getIsMips64EL());
       ++it;
     } else {
       if (ctx.arg.mipsN32Abi) {
         type = getMipsN32RelType(ctx, it, rels.end());
       } else {
-        type = it->getType(ctx.arg.isMips64EL);
+        type = it->getType(ctx.arg.getIsMips64EL());
         ++it;
       }
     }
 
-    uint32_t symIdx = rel.getSymbol(ctx.arg.isMips64EL);
+    uint32_t symIdx = rel.getSymbol(ctx.arg.getIsMips64EL());
     Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);
     RelExpr expr = getRelExpr(type, sym, sec.content().data() + rel.r_offset);
     if (expr == R_NONE)
@@ -714,8 +714,8 @@ void MIPS<ELFT>::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
         // the relocation table, so we need to do linear search. *sigh*
         bool found = false;
         for (auto *ri = &rel; ri != rels.end(); ++ri) {
-          if (ri->getType(ctx.arg.isMips64EL) == pairTy &&
-              ri->getSymbol(ctx.arg.isMips64EL) == symIdx) {
+          if (ri->getType(ctx.arg.getIsMips64EL()) == pairTy &&
+              ri->getSymbol(ctx.arg.getIsMips64EL()) == symIdx) {
             addend += getImplicitAddend(buf + ri->r_offset, pairTy);
             found = true;
             break;
@@ -793,7 +793,7 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
     // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode
     // is updated addend (not a GOT index). In that case write high 16 bits
     // to store a correct addend value.
-    if (ctx.arg.relocatable) {
+    if (ctx.arg.getRelocatable()) {
       writeValue(ctx, loc, val + 0x8000, 16, 16);
     } else {
       checkInt(ctx, loc, val, 16, rel);
@@ -801,7 +801,7 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
     }
     break;
   case R_MICROMIPS_GOT16:
-    if (ctx.arg.relocatable) {
+    if (ctx.arg.getRelocatable()) {
       writeShuffle<e>(ctx, loc, val + 0x8000, 16, 16);
     } else {
       checkInt(ctx, loc, val, 16, rel);
@@ -1058,7 +1058,7 @@ template <class ELFT> void OptionsSection<ELFT>::writeTo(uint8_t *buf) {
   options->kind = ODK_REGINFO;
   options->size = getSize();
 
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     reginfo.ri_gp_value = ctx.in.mipsGot->getGp();
   memcpy(buf + sizeof(Elf_Mips_Options), &reginfo, sizeof(reginfo));
 }
@@ -1090,7 +1090,7 @@ ReginfoSection<ELFT>::ReginfoSection(Ctx &ctx)
 }
 
 template <class ELFT> void ReginfoSection<ELFT>::writeTo(uint8_t *buf) {
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     reginfo.ri_gp_value = ctx.in.mipsGot->getGp();
   memcpy(buf, &reginfo, sizeof(reginfo));
 }
diff --git a/lld/ELF/Arch/MipsArchTree.cpp b/lld/ELF/Arch/MipsArchTree.cpp
index 9158859045087..7172ff47e9759 100644
--- a/lld/ELF/Arch/MipsArchTree.cpp
+++ b/lld/ELF/Arch/MipsArchTree.cpp
@@ -69,7 +69,7 @@ static void checkFlags(Ctx &ctx, ArrayRef<FileFlags> files) {
   bool fp = files[0].flags & EF_MIPS_FP64;
 
   for (const FileFlags &f : files) {
-    if (ctx.arg.is64 && f.flags & EF_MIPS_MICROMIPS)
+    if (ctx.arg.getIs64() && f.flags & EF_MIPS_MICROMIPS)
       Err(ctx) << f.file << ": microMIPS 64-bit is not supported";
 
     uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
@@ -299,7 +299,7 @@ template <class ELFT> uint32_t elf::calcMipsEFlags(Ctx &ctx) {
     // If we don't have any input files, we'll have to rely on the information
     // we can derive from emulation information, since this at least gets us
     // ABI.
-    if (ctx.arg.emulation.empty() || ctx.arg.is64)
+    if (ctx.arg.emulation.empty() || ctx.arg.getIs64())
       return 0;
     return ctx.arg.mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
   }
diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp
index e09ecb5c2cff6..8053f5ec774a2 100644
--- a/lld/ELF/Arch/PPC.cpp
+++ b/lld/ELF/Arch/PPC.cpp
@@ -77,18 +77,18 @@ static uint16_t lo(uint32_t v) { return v; }
 static uint16_t ha(uint32_t v) { return (v + 0x8000) >> 16; }
 
 static uint32_t readFromHalf16(Ctx &ctx, const uint8_t *loc) {
-  return read32(ctx, ctx.arg.isLE ? loc : loc - 2);
+  return read32(ctx, ctx.arg.getIsLE() ? loc : loc - 2);
 }
 
 static void writeFromHalf16(Ctx &ctx, uint8_t *loc, uint32_t insn) {
-  write32(ctx, ctx.arg.isLE ? loc : loc - 2, insn);
+  write32(ctx, ctx.arg.getIsLE() ? loc : loc - 2, insn);
 }
 
 void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
   // Create canonical PLT entries for non-PIE code. Compilers don't generate
   // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
   uint32_t glink = ctx.in.plt->getVA(); // VA of .glink
-  if (!ctx.arg.isPic) {
+  if (!ctx.arg.getIsPic()) {
     for (const Symbol *sym :
          cast<PPC32GlinkSection>(*ctx.in.plt).canonical_plts) {
       writePPC32PltCallStub(ctx, buf, glink, sym->getGotPltVA(ctx), nullptr, 0);
@@ -116,7 +116,7 @@ void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
   // itself) and calls _dl_runtime_resolve() (in glibc).
   uint32_t got = ctx.in.got->getVA();
   const uint8_t *end = buf + 64;
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     uint32_t afterBcl = 4 * ctx.in.plt->getNumEntries() + 12;
     uint32_t gotBcl = got + 4 - (glink + afterBcl);
     write32(ctx, buf + 0,
@@ -179,7 +179,7 @@ PPC::PPC(Ctx &ctx) : TargetInfo(ctx) {
   gotPltHeaderEntriesNum = 0;
   pltHeaderSize = 0;
   pltEntrySize = 4;
-  ipltEntrySize = ctx.arg.isPic ? 32 : 16;
+  ipltEntrySize = ctx.arg.getIsPic() ? 32 : 16;
 
   needsThunks = true;
 
@@ -367,7 +367,7 @@ void PPC::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       rs.handleTlsIe(R_GOT_OFF, type, offset, addend, sym);
       continue;
     case R_PPC_TLS:
-      if (!ctx.arg.shared && !sym.isPreemptible)
+      if (!ctx.arg.getShared() && !sym.isPreemptible)
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
@@ -378,7 +378,7 @@ void PPC::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       continue;
     case R_PPC_TLSGD:
     case R_PPC_TLSLD:
-      if (!ctx.arg.shared) {
+      if (!ctx.arg.getShared()) {
         sec.addReloc({sym.isPreemptible ? R_GOT_OFF : R_TPREL, type, offset,
                       addend, &sym});
         ++it; // Skip REL24
@@ -408,7 +408,7 @@ void PPC::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 }
 
 void PPC::scanSection(InputSectionBase &sec, unsigned shard) {
-  if (ctx.arg.isLE)
+  if (ctx.arg.getIsLE())
     elf::scanSection1<PPC, ELF32LE>(*this, sec, shard);
   else
     elf::scanSection1<PPC, ELF32BE>(*this, sec, shard);
diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index 17ee2f723e7b2..291e463bc5e2a 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -247,7 +247,7 @@ unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(Ctx &ctx, uint8_t stOther) {
 }
 
 void elf::writePrefixedInst(Ctx &ctx, uint8_t *loc, uint64_t insn) {
-  insn = ctx.arg.isLE ? insn << 32 | insn >> 32 : insn;
+  insn = ctx.arg.getIsLE() ? insn << 32 | insn >> 32 : insn;
   write64(ctx, loc, insn);
 }
 
@@ -380,7 +380,7 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
 // Returns true if the relaxation is performed.
 static bool tryRelaxPPC64TocIndirection(Ctx &ctx, const Relocation &rel,
                                         uint8_t *bufLoc) {
-  assert(ctx.arg.tocOptimize);
+  assert(ctx.arg.getTocOptimize());
   if (rel.addend < 0)
     return false;
 
@@ -393,8 +393,8 @@ static bool tryRelaxPPC64TocIndirection(Ctx &ctx, const Relocation &rel,
   int64_t addend;
   auto *tocISB = cast<InputSectionBase>(defSym->section);
   std::tie(d, addend) =
-      ctx.arg.isLE ? getRelaTocSymAndAddend<ELF64LE>(tocISB, rel.addend)
-                   : getRelaTocSymAndAddend<ELF64BE>(tocISB, rel.addend);
+      ctx.arg.getIsLE() ? getRelaTocSymAndAddend<ELF64LE>(tocISB, rel.addend)
+                        : getRelaTocSymAndAddend<ELF64BE>(tocISB, rel.addend);
 
   // Only non-preemptable defined symbols can be relaxed.
   if (!d || d->isPreemptible)
@@ -567,16 +567,16 @@ static int64_t getTotalDisp(uint64_t prefixedInsn, uint32_t accessInsn) {
 // little-endian it is pointing to the start of the word. These 2 helpers are to
 // simplify reading and writing in that context.
 static void writeFromHalf16(Ctx &ctx, uint8_t *loc, uint32_t insn) {
-  write32(ctx, ctx.arg.isLE ? loc : loc - 2, insn);
+  write32(ctx, ctx.arg.getIsLE() ? loc : loc - 2, insn);
 }
 
 static uint32_t readFromHalf16(Ctx &ctx, const uint8_t *loc) {
-  return read32(ctx, ctx.arg.isLE ? loc : loc - 2);
+  return read32(ctx, ctx.arg.getIsLE() ? loc : loc - 2);
 }
 
 static uint64_t readPrefixedInst(Ctx &ctx, const uint8_t *loc) {
   uint64_t fullInstr = read64(ctx, loc);
-  return ctx.arg.isLE ? (fullInstr << 32 | fullInstr >> 32) : fullInstr;
+  return ctx.arg.getIsLE() ? (fullInstr << 32 | fullInstr >> 32) : fullInstr;
 }
 
 PPC64::PPC64(Ctx &ctx) : TargetInfo(ctx) {
@@ -1119,7 +1119,7 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
   RelocScan rs(ctx, &sec, shard);
   sec.relocations.reserve(rels.size());
   bool optimizeTlsGdLd =
-      !missingTlsGdLdMarker<RelTy>(sec, rels) && !ctx.arg.shared;
+      !missingTlsGdLdMarker<RelTy>(sec, rels) && !ctx.arg.getShared();
   for (auto it = rels.begin(); it != rels.end(); ++it) {
     RelType type = it->getType(false);
     uint32_t symIdx = it->getSymbol(false);
@@ -1129,7 +1129,7 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
         rs.maybeReportUndefined(cast<Undefined>(sym), offset))
       continue;
     int64_t addend = rs.getAddend<ELFT>(*it, type);
-    if (ctx.arg.isPic && type == R_PPC64_TOC)
+    if (ctx.arg.getIsPic() && type == R_PPC64_TOC)
       addend += getPPC64TocBase(ctx);
 
     RelExpr expr;
@@ -1188,7 +1188,7 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     // TOC-relative relocations:
     case R_PPC64_TOC16:
     case R_PPC64_TOC16_DS:
-      sec.file->ppc64SmallCodeModelTocRelocs = true;
+      sec.file->setPpc64SmallCodeModelTocRelocs(true);
       expr = R_GOTREL;
       break;
     case R_PPC64_TOC16_HI:
@@ -1250,7 +1250,7 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       rs.handleTlsIe(R_GOT_PC, type, offset, addend, sym);
       continue;
     case R_PPC64_TLS:
-      if (!ctx.arg.shared && !sym.isPreemptible)
+      if (!ctx.arg.getShared() && !sym.isPreemptible)
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
@@ -1354,7 +1354,7 @@ void PPC64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 }
 
 void PPC64::scanSection(InputSectionBase &sec, unsigned shard) {
-  if (ctx.arg.isLE)
+  if (ctx.arg.getIsLE())
     elf::scanSection1<PPC64, ELF64LE>(*this, sec, shard);
   else
     elf::scanSection1<PPC64, ELF64BE>(*this, sec, shard);
@@ -1466,7 +1466,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_PPC64_ADDR16_HA:
   case R_PPC64_REL16_HA:
   case R_PPC64_TPREL16_HA:
-    if (ctx.arg.tocOptimize && shouldTocOptimize && ha(val) == 0)
+    if (ctx.arg.getTocOptimize() && shouldTocOptimize && ha(val) == 0)
       writeFromHalf16(ctx, loc, NOP);
     else {
       checkInt(ctx, loc, val + 0x8000, 32, rel);
@@ -1532,7 +1532,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     // When the high-adjusted part of a toc relocation evaluates to 0, it is
     // changed into a nop. The lo part then needs to be updated to use the
     // toc-pointer register r2, as the base register.
-    if (ctx.arg.tocOptimize && shouldTocOptimize && ha(val) == 0) {
+    if (ctx.arg.getTocOptimize() && shouldTocOptimize && ha(val) == 0) {
       uint32_t insn = readFromHalf16(ctx, loc);
       if (isInstructionUpdateForm(insn))
         Err(ctx) << getErrorLoc(ctx, loc)
@@ -1557,7 +1557,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     uint32_t insn = readFromHalf16(ctx, loc);
     uint16_t mask = isDQFormInstruction(insn) ? 0xf : 0x3;
     checkAlignment(ctx, loc, lo(val), mask + 1, rel);
-    if (ctx.arg.tocOptimize && shouldTocOptimize && ha(val) == 0) {
+    if (ctx.arg.getTocOptimize() && shouldTocOptimize && ha(val) == 0) {
       // When the high-adjusted part of a toc relocation evaluates to 0, it is
       // changed into a nop. The lo part then needs to be updated to use the toc
       // pointer register r2, as the base register.
@@ -1682,7 +1682,7 @@ bool PPC64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
 RelExpr PPC64::adjustGotPcExpr(RelType type, int64_t addend,
                                const uint8_t *loc) const {
   if ((type == R_PPC64_GOT_PCREL34 || type == R_PPC64_PCREL_OPT) &&
-      ctx.arg.pcRelOptimize) {
+      ctx.arg.getPcRelOptimize()) {
     // It only makes sense to optimize pld since paddi means that the address
     // of the object in the GOT is required rather than the object itself.
     if ((readPrefixedInst(ctx, loc) & 0xfc000000) == 0xe4000000)
@@ -1789,7 +1789,7 @@ void PPC64::relocateAlloc(InputSection &sec, uint8_t *buf) const {
       // entry, there may be R_PPC64_TOC16_HA not paired with
       // R_PPC64_TOC16_LO_DS. Don't relax. This loses some relaxation
       // opportunities but is safe.
-      if (ctx.arg.tocOptimize &&
+      if (ctx.arg.getTocOptimize() &&
           !ctx.ppc64noTocRelax.contains({rel.sym, rel.addend}) &&
           tryRelaxPPC64TocIndirection(ctx, rel, loc))
         continue;
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 13c919c195e2e..4c55e324709ee 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -133,7 +133,7 @@ RISCV::RISCV(Ctx &ctx) : TargetInfo(ctx) {
   pltRel = R_RISCV_JUMP_SLOT;
   relativeRel = R_RISCV_RELATIVE;
   iRelativeRel = R_RISCV_IRELATIVE;
-  if (ctx.arg.is64) {
+  if (ctx.arg.getIs64()) {
     symbolicRel = R_RISCV_64;
     tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64;
     tlsOffsetRel = R_RISCV_TLS_DTPREL64;
@@ -159,7 +159,7 @@ RISCV::RISCV(Ctx &ctx) : TargetInfo(ctx) {
 }
 
 static uint32_t getEFlags(Ctx &ctx, InputFile *f) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader().e_flags;
   return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags;
 }
@@ -206,25 +206,25 @@ int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
     return read64le(buf);
   case R_RISCV_RELATIVE:
   case R_RISCV_IRELATIVE:
-    return ctx.arg.is64 ? read64le(buf) : read32le(buf);
+    return ctx.arg.getIs64() ? read64le(buf) : read32le(buf);
   case R_RISCV_NONE:
   case R_RISCV_JUMP_SLOT:
     // These relocations are defined as not having an implicit addend.
     return 0;
   case R_RISCV_TLSDESC:
-    return ctx.arg.is64 ? read64le(buf + 8) : read32le(buf + 4);
+    return ctx.arg.getIs64() ? read64le(buf + 8) : read32le(buf + 4);
   }
 }
 
 void RISCV::writeGotHeader(uint8_t *buf) const {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     write64le(buf, ctx.in.dynamic->getVA());
   else
     write32le(buf, ctx.in.dynamic->getVA());
 }
 
 void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     write64le(buf, ctx.in.plt->getVA());
   else
     write32le(buf, ctx.in.plt->getVA());
@@ -232,7 +232,7 @@ void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
 
 void RISCV::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
   if (ctx.arg.writeAddends) {
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       write64le(buf, s.getVA(ctx));
     else
       write32le(buf, s.getVA(ctx));
@@ -264,7 +264,7 @@ void RISCV::writePltHeader(uint8_t *buf) const {
   bool lpad =
       ctx.arg.andFeatures & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED;
   uint32_t offset = ctx.in.gotPlt->getVA() - ctx.in.plt->getVA();
-  uint32_t load = ctx.arg.is64 ? LD : LW;
+  uint32_t load = ctx.arg.getIs64() ? LD : LW;
   uint32_t auipcReg = lpad ? X_T3 : X_T2;
   uint32_t workReg = lpad ? X_T2 : X_T3;
 
@@ -274,7 +274,7 @@ void RISCV::writePltHeader(uint8_t *buf) const {
   write32le(buf + 12, itype(ADDI, X_T1, X_T1,
                             -ctx.target->pltHeaderSize - (lpad ? 16 : 12)));
   write32le(buf + 16, itype(ADDI, X_T0, auipcReg, lo12(offset)));
-  write32le(buf + 20, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
+  write32le(buf + 20, itype(SRLI, X_T1, X_T1, ctx.arg.getIs64() ? 1 : 2));
   write32le(buf + 24, itype(load, X_T0, X_T0, ctx.arg.wordsize));
   write32le(buf + 28, itype(JALR, X_X0, workReg, 0));
 }
@@ -303,7 +303,7 @@ void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
     write32le(buf + 0, utype(AUIPC, X_X0, 0)); // lpad 0
   write32le(buf + 0 + auipcOffset, utype(AUIPC, rd, hi20(offset)));
   write32le(buf + 4 + auipcOffset,
-            itype(ctx.arg.is64 ? LD : LW, rd, rd, lo12(offset)));
+            itype(ctx.arg.getIs64() ? LD : LW, rd, rd, lo12(offset)));
   write32le(buf + 8 + auipcOffset, itype(JALR, X_T1, rd, 0));
   if (!lpad)
     write32le(buf + 12, itype(ADDI, X_X0, X_X0, 0));
@@ -438,11 +438,11 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       // TLS symbol, so we cannot use handleTlsDesc (which sets NEEDS_TLSDESC).
       // For TLSDESC->IE, use R_TPREL as well, but relocateAlloc uses isToLe
       // (from HI20) to select the correct transform.
-      sec.addReloc({ctx.arg.shared ? R_TLSDESC_PC : R_TPREL, type, offset,
+      sec.addReloc({ctx.arg.getShared() ? R_TLSDESC_PC : R_TPREL, type, offset,
                     addend, &sym});
       continue;
     case R_RISCV_TLSDESC_CALL:
-      if (!ctx.arg.shared)
+      if (!ctx.arg.getShared())
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
@@ -452,7 +452,7 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       continue;
     case R_RISCV_TPREL_ADD:
     case R_RISCV_RELAX:
-      if (ctx.arg.relax)
+      if (ctx.arg.getRelax())
         sec.addReloc({R_RELAX_HINT, type, offset, addend, &sym});
       continue;
 
@@ -514,7 +514,7 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 }
 
 void RISCV::scanSection(InputSectionBase &sec, unsigned shard) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     elf::scanSection1<RISCV, ELF64LE>(*this, sec, shard);
   else
     elf::scanSection1<RISCV, ELF32LE>(*this, sec, shard);
@@ -722,7 +722,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     return;
   case R_RISCV_TLSDESC:
     // The addend is stored in the second word.
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       write64le(loc + 8, val);
     else
       write32le(loc + 4, val);
@@ -747,7 +747,7 @@ static void tlsdescToIe(Ctx &ctx, uint8_t *loc, const Relocation &rel,
     write32le(loc, utype(AUIPC, X_A0, hi20(val))); // auipc a0,<hi20>
     break;
   case R_RISCV_TLSDESC_CALL:
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       write32le(loc, itype(LD, X_A0, X_A0, lo12(val))); // ld a0,<lo12>(a0)
     else
       write32le(loc, itype(LW, X_A0, X_A0, lo12(val))); // lw a0,<lo12>(a0)
@@ -947,7 +947,7 @@ static void relaxCall(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->writes.push_back(0xa001); // c.j
     remove = 6;
   } else if (remove >= 6 && rvc && isInt<12>(displace) && rd == X_RA &&
-             !ctx.arg.is64) { // RV32C only
+             !ctx.arg.getIs64()) { // RV32C only
     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
@@ -1269,8 +1269,8 @@ bool RISCV::synthesizeAlignAux(uint64_t &dot, InputSection *sec) {
 // output relocation section is updated with all the newly synthesized ALIGN
 // relocations.
 bool RISCV::synthesizeAlign(uint64_t &dot, InputSection *sec) {
-  assert(ctx.arg.relocatable);
-  if (ctx.arg.is64)
+  assert(ctx.arg.getRelocatable());
+  if (ctx.arg.getIs64())
     return synthesizeAlignAux<ELF64LE>(dot, sec);
   return synthesizeAlignAux<ELF32LE>(dot, sec);
 }
diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp
index 7797990571def..27b36e5eb46b6 100644
--- a/lld/ELF/Arch/SPARCV9.cpp
+++ b/lld/ELF/Arch/SPARCV9.cpp
@@ -199,7 +199,7 @@ void SPARCV9::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       continue;
     case R_SPARC_TLS_IE_LD:
     case R_SPARC_TLS_IE_LDX:
-      if (!ctx.arg.shared && !sym.isPreemptible)
+      if (!ctx.arg.getShared() && !sym.isPreemptible)
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
diff --git a/lld/ELF/Arch/SystemZ.cpp b/lld/ELF/Arch/SystemZ.cpp
index b76baf464a5e7..2fd1cd033c1fe 100644
--- a/lld/ELF/Arch/SystemZ.cpp
+++ b/lld/ELF/Arch/SystemZ.cpp
@@ -205,7 +205,7 @@ void SystemZ::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     // R_390_TLS_GDCALL/LDCALL (at the instruction start) for the same brasl.
     // When optimizing TLS, skip PLT32DBL before maybeReportUndefined would
     // flag __tls_get_offset as undefined.
-    if (type == R_390_PLT32DBL && !ctx.arg.shared &&
+    if (type == R_390_PLT32DBL && !ctx.arg.getShared() &&
         std::next(it) != rels.end()) {
       RelType nextType = std::next(it)->getType(false);
       if (nextType == R_390_TLS_GDCALL || nextType == R_390_TLS_LDCALL)
@@ -345,7 +345,7 @@ void SystemZ::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     // TLS DTPREL relocations:
     case R_390_TLS_LDO32:
     case R_390_TLS_LDO64:
-      if (ctx.arg.shared)
+      if (ctx.arg.getShared())
         sec.addReloc({R_DTPREL, type, offset, addend, &sym});
       else
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
@@ -426,7 +426,7 @@ void SystemZ::relaxTlsGdCall(uint8_t *loc, const Relocation &rel) const {
 RelExpr SystemZ::adjustGotPcExpr(RelType type, int64_t addend,
                                  const uint8_t *loc) const {
   // Only R_390_GOTENT with addend 2 can be relaxed.
-  if (!ctx.arg.relax || addend != 2 || type != R_390_GOTENT)
+  if (!ctx.arg.getRelax() || addend != 2 || type != R_390_GOTENT)
     return R_GOT_PC;
   const uint16_t op = read16be(loc - 2);
 
diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp
index 5b95ccdf50e46..0519d4b95e001 100644
--- a/lld/ELF/Arch/X86.cpp
+++ b/lld/ELF/Arch/X86.cpp
@@ -130,7 +130,7 @@ RelType X86::getDynRel(RelType type) const {
 }
 
 void X86::writePltHeader(uint8_t *buf) const {
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     const uint8_t v[] = {
         0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
         0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
@@ -154,7 +154,7 @@ void X86::writePltHeader(uint8_t *buf) const {
 void X86::writePlt(uint8_t *buf, const Symbol &sym,
                    uint64_t pltEntryAddr) const {
   unsigned relOff = ctx.in.relaPlt->entsize * sym.getPltIdx(ctx);
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     const uint8_t inst[] = {
         0xff, 0xa3, 0, 0, 0, 0, // jmp *foo at GOT(%ebx)
         0x68, 0,    0, 0, 0,    // pushl $reloc_offset
@@ -269,8 +269,8 @@ void X86::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
         ++it;
       continue;
     case R_386_TLS_LDO_32:
-      sec.addReloc(
-          {ctx.arg.shared ? R_DTPREL : R_TPREL, type, offset, addend, &sym});
+      sec.addReloc({ctx.arg.getShared() ? R_DTPREL : R_TPREL, type, offset,
+                    addend, &sym});
       continue;
     case R_386_TLS_GOTDESC:
       ctx.in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
@@ -279,7 +279,7 @@ void X86::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     case R_386_TLS_DESC_CALL:
       // For executables, TLSDESC is optimized to IE or LE. Use R_TPREL as the
       // rewrites for this relocation are identical.
-      if (!ctx.arg.shared)
+      if (!ctx.arg.getShared())
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
 
@@ -607,7 +607,7 @@ void IntelIBT::writeGotPlt(uint8_t *buf, const Symbol &s) const {
 
 void IntelIBT::writePlt(uint8_t *buf, const Symbol &sym,
                         uint64_t /*pltEntryAddr*/) const {
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     const uint8_t inst[] = {
         0xf3, 0x0f, 0x1e, 0xfb,       // endbr32
         0xff, 0xa3, 0,    0,    0, 0, // jmp *name at GOT(%ebx)
@@ -780,8 +780,8 @@ void RetpolineNoPic::writePlt(uint8_t *buf, const Symbol &sym,
 }
 
 void elf::setX86TargetInfo(Ctx &ctx) {
-  if (ctx.arg.zRetpolineplt) {
-    if (ctx.arg.isPic)
+  if (ctx.arg.getZRetpolineplt()) {
+    if (ctx.arg.getIsPic())
       ctx.target.reset(new RetpolinePic(ctx));
     else
       ctx.target.reset(new RetpolineNoPic(ctx));
diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp
index c1d1db1d0133c..75be3bbf15f08 100644
--- a/lld/ELF/Arch/X86_64.cpp
+++ b/lld/ELF/Arch/X86_64.cpp
@@ -86,7 +86,7 @@ X86_64::X86_64(Ctx &ctx) : TargetInfo(ctx) {
   pltRel = R_X86_64_JUMP_SLOT;
   relativeRel = R_X86_64_RELATIVE;
   iRelativeRel = R_X86_64_IRELATIVE;
-  symbolicRel = ctx.arg.is64 ? R_X86_64_64 : R_X86_64_32;
+  symbolicRel = ctx.arg.getIs64() ? R_X86_64_64 : R_X86_64_32;
   tlsDescRel = R_X86_64_TLSDESC;
   tlsGotRel = R_X86_64_TPOFF64;
   tlsModuleIndexRel = R_X86_64_DTPMOD64;
@@ -515,7 +515,7 @@ bool X86_64::relaxOnce(int pass) const {
   // If the max VA is under 2^31, GOTPCRELX relocations cannot overflow. In
   // -pie/-shared, the condition can be relaxed to test the max VA difference as
   // there is no R_RELAX_GOT_PC_NOPIC.
-  if (isUInt<31>(maxVA) || (isUInt<31>(maxVA - minVA) && ctx.arg.isPic))
+  if (isUInt<31>(maxVA) || (isUInt<31>(maxVA - minVA) && ctx.arg.getIsPic()))
     return false;
 
   SmallVector<InputSection *, 0> storage;
@@ -737,13 +737,13 @@ void X86_64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
       continue;
     case R_X86_64_DTPOFF32:
     case R_X86_64_DTPOFF64:
-      sec.addReloc(
-          {ctx.arg.shared ? R_DTPREL : R_TPREL, type, offset, addend, &sym});
+      sec.addReloc({ctx.arg.getShared() ? R_DTPREL : R_TPREL, type, offset,
+                    addend, &sym});
       continue;
     case R_X86_64_TLSDESC_CALL:
       // For executables, TLSDESC is optimized to IE or LE. Use R_TPREL as the
       // rewrites for this relocation are identical.
-      if (!ctx.arg.shared)
+      if (!ctx.arg.getShared())
         sec.addReloc({R_TPREL, type, offset, addend, &sym});
       continue;
     case R_X86_64_GOTPC32_TLSDESC:
@@ -766,13 +766,13 @@ void X86_64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
     rs.process(expr, type, offset, sym, addend);
   }
 
-  if (ctx.arg.branchToBranch)
+  if (ctx.arg.getBranchToBranch())
     llvm::stable_sort(sec.relocs(),
                       [](auto &l, auto &r) { return l.offset < r.offset; });
 }
 
 void X86_64::scanSection(InputSectionBase &sec, unsigned shard) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     elf::scanSection1<X86_64, ELF64LE>(*this, sec, shard);
   else // ilp32
     elf::scanSection1<X86_64, ELF32LE>(*this, sec, shard);
@@ -1320,7 +1320,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
   // GOTPCRELX with addend != -4. Such an instruction does not load the full GOT
   // entry, so we cannot relax the relocation. E.g. movl x at GOTPCREL+4(%rip),
   // %rax (addend=0) loads the high 32 bits of the GOT entry.
-  if (!ctx.arg.relax || addend != -4 ||
+  if (!ctx.arg.getRelax() || addend != -4 ||
       (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX &&
        type != R_X86_64_CODE_4_GOTPCRELX))
     return R_GOT_PC;
@@ -1344,7 +1344,7 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
 
   // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
   // If PIC then no relaxation is available.
-  return ctx.arg.isPic ? R_GOT_PC : R_RELAX_GOT_PC_NOPIC;
+  return ctx.arg.getIsPic() ? R_GOT_PC : R_RELAX_GOT_PC_NOPIC;
 }
 
 // A subset of relaxations can only be applied for no-PIC. This method
@@ -1444,7 +1444,7 @@ static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) {
   if (op != 0xff) {
     // We are relaxing a rip relative to an absolute, so compensate
     // for the old -4 addend.
-    assert(!rel.sym->file->ctx.arg.isPic);
+    assert(!rel.sym->file->ctx.arg.getIsPic());
     relaxGotNoPic(loc, val + 4, op, modRm,
                   rel.type == R_X86_64_CODE_4_GOTPCRELX);
     return;
@@ -1475,7 +1475,7 @@ static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) {
 // B) Or a load of a stack pointer offset with an lea to r10 or r11.
 bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
                                               uint8_t stOther) const {
-  if (!ctx.arg.is64) {
+  if (!ctx.arg.getIs64()) {
     ErrAlways(ctx) << "target doesn't support split stacks";
     return false;
   }
@@ -1755,8 +1755,8 @@ void RetpolineZNow::writePlt(uint8_t *buf, const Symbol &sym,
 }
 
 void elf::setX86_64TargetInfo(Ctx &ctx) {
-  if (ctx.arg.zRetpolineplt) {
-    if (ctx.arg.zNow)
+  if (ctx.arg.getZRetpolineplt()) {
+    if (ctx.arg.getZNow())
       ctx.target.reset(new RetpolineZNow(ctx));
     else
       ctx.target.reset(new Retpoline(ctx));
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index a43d5d509a80c..3cdd40b0b86c6 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/BinaryFormat/ELF.h"
@@ -189,17 +190,25 @@ struct VersionDefinition {
 // Deferred file-load job: one per input, expanded by loadFiles().
 struct LoadJob {
   enum Kind : uint8_t { Obj, Bitcode, Archive, Shared, Binary };
+  LoadJob(llvm::MemoryBufferRef mbref, llvm::StringRef path, Kind kind,
+          bool inWholeArchive, bool lazy, bool asNeeded, bool withLOption,
+          uint32_t groupId);
   llvm::MemoryBufferRef mbref;
   llvm::StringRef path;
   Kind kind;
-  bool inWholeArchive;
-  bool lazy;
-  bool asNeeded;
-  bool withLOption;
+  bool getInWholeArchive() const { return tarEntries.getFlag(0); }
+  void setInWholeArchive(bool Value) { tarEntries.setFlag(0, Value); }
+  bool getLazy() const { return tarEntries.getFlag(1); }
+  void setLazy(bool Value) { tarEntries.setFlag(1, Value); }
+  bool getAsNeeded() const { return tarEntries.getFlag(2); }
+  void setAsNeeded(bool Value) { tarEntries.setFlag(2, Value); }
+  bool getWithLOption() const { return tarEntries.getFlag(3); }
+  void setWithLOption(bool Value) { tarEntries.setFlag(3, Value); }
   uint32_t groupId;
   SmallVector<std::unique_ptr<InputFile>, 0> out;
   std::vector<std::unique_ptr<llvm::MemoryBuffer>> thinBufs;
-  SmallVector<std::pair<std::string, llvm::StringRef>, 0> tarEntries;
+  llvm::SmallVectorWithFlags<std::pair<std::string, llvm::StringRef>, 0, 4>
+      tarEntries;
 };
 
 class LinkerDriver {
@@ -300,23 +309,23 @@ struct Config {
   llvm::StringRef thinLTOPrefixReplaceNew;
   llvm::StringRef thinLTOPrefixReplaceNativeObject;
   std::string rpath;
-  llvm::SmallVector<VersionDefinition, 0> versionDefinitions;
+  llvm::SmallVectorWithFlags<VersionDefinition, 0, 4> versionDefinitions;
   std::optional<llvm::DenseSet<llvm::StringRef>> retainSymbols;
-  llvm::SmallVector<llvm::StringRef, 0> auxiliaryList;
-  llvm::SmallVector<llvm::StringRef, 0> filterList;
-  llvm::SmallVector<llvm::StringRef, 0> passPlugins;
-  llvm::SmallVector<llvm::StringRef, 0> searchPaths;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> auxiliaryList;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> filterList;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> passPlugins;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> searchPaths;
   llvm::SmallVector<llvm::StringRef, 0> symbolOrderingFile;
-  llvm::SmallVector<llvm::StringRef, 0> thinLTOModulesToCompile;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> thinLTOModulesToCompile;
   llvm::StringRef dtltoDistributor;
-  llvm::SmallVector<llvm::StringRef, 0> dtltoDistributorArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoDistributorArgs;
   llvm::StringRef dtltoCompiler;
-  llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerPrependArgs;
-  llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerArgs;
-  llvm::SmallVector<llvm::StringRef, 0> undefined;
-  llvm::SmallVector<SymbolVersion, 0> dynamicList;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoCompilerPrependArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> dtltoCompilerArgs;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> undefined;
+  llvm::SmallVectorWithFlags<SymbolVersion, 0, 4> dynamicList;
   llvm::SmallVector<uint8_t, 0> buildIdVector;
-  llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> mllvmOpts;
   llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
                   uint64_t>
       callGraphProfile;
@@ -329,27 +338,65 @@ struct Config {
   bool armHasBlx = false;
   bool armHasMovtMovw = false;
   bool armJ1J2BranchEncoding = false;
-  bool armCMSESupport = false;
+  bool getArmCMSESupport() const { return remapInputsWildcards.getFlag(0); }
+  bool setArmCMSESupport(bool Value) {
+    remapInputsWildcards.setFlag(0, Value);
+    return Value;
+  }
   bool asNeeded = false;
-  bool armBe8 = false;
+  bool getArmBe8() const { return remapInputsWildcards.getFlag(1); }
+  void setArmBe8(bool Value) { remapInputsWildcards.setFlag(1, Value); }
   BsymbolicKind bsymbolic = BsymbolicKind::None;
   CGProfileSortKind callGraphProfileSort;
   llvm::StringRef irpgoProfilePath;
-  bool bpStartupFunctionSort = false;
-  bool bpCompressionSortStartupFunctions = false;
-  bool bpFunctionOrderForCompression = false;
-  bool bpDataOrderForCompression = false;
-  llvm::SmallVector<BPCompressionSortSpec> bpCompressionSortSpecs;
-  bool bpVerboseSectionOrderer = false;
-  bool branchToBranch = false;
-  bool checkSections;
-  bool checkDynamicRelocs;
+  bool getBpStartupFunctionSort() const {
+    return remapInputsWildcards.getFlag(2);
+  }
+  void setBpStartupFunctionSort(bool Value) {
+    remapInputsWildcards.setFlag(2, Value);
+  }
+  bool getBpCompressionSortStartupFunctions() const {
+    return remapInputsWildcards.getFlag(3);
+  }
+  void setBpCompressionSortStartupFunctions(bool Value) {
+    remapInputsWildcards.setFlag(3, Value);
+  }
+  bool getBpFunctionOrderForCompression() const {
+    return packageMetadata.getFlag(0);
+  }
+  void setBpFunctionOrderForCompression(bool Value) {
+    packageMetadata.setFlag(0, Value);
+  }
+  bool getBpDataOrderForCompression() const {
+    return packageMetadata.getFlag(1);
+  }
+  void setBpDataOrderForCompression(bool Value) {
+    packageMetadata.setFlag(1, Value);
+  }
+  llvm::SmallVectorWithFlags<BPCompressionSortSpec,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 BPCompressionSortSpec>::value,
+                             4>
+      bpCompressionSortSpecs;
+  bool getBpVerboseSectionOrderer() const { return packageMetadata.getFlag(2); }
+  void setBpVerboseSectionOrderer(bool Value) {
+    packageMetadata.setFlag(2, Value);
+  }
+  bool getBranchToBranch() const { return packageMetadata.getFlag(3); }
+  void setBranchToBranch(bool Value) { packageMetadata.setFlag(3, Value); }
+  bool getCheckSections() const { return warnBackrefsExclude.getFlag(0); }
+  void setCheckSections(bool Value) { warnBackrefsExclude.setFlag(0, Value); }
+  bool getCheckDynamicRelocs() const { return warnBackrefsExclude.getFlag(1); }
+  void setCheckDynamicRelocs(bool Value) {
+    warnBackrefsExclude.setFlag(1, Value);
+  }
   std::optional<llvm::DebugCompressionType> compressDebugSections;
-  llvm::SmallVector<
-      std::tuple<llvm::GlobPattern, llvm::DebugCompressionType, unsigned>, 0>
+  llvm::SmallVectorWithFlags<
+      std::tuple<llvm::GlobPattern, llvm::DebugCompressionType, unsigned>, 0, 4>
       compressSections;
-  bool cref;
-  llvm::SmallVector<std::pair<llvm::GlobPattern, uint64_t>, 0>
+  bool getCref() const { return warnBackrefsExclude.getFlag(2); }
+  void setCref(bool Value) { warnBackrefsExclude.setFlag(2, Value); }
+  llvm::SmallVectorWithFlags<std::pair<llvm::GlobPattern, uint64_t>, 0, 4>
       deadRelocInNonAlloc;
   bool debugNames;
   bool demangle = true;
@@ -383,47 +430,97 @@ struct Config {
   bool mmapOutputFile;
   bool nmagic;
   bool noinhibitExec;
-  bool nostdlib;
-  bool oFormatBinary;
-  bool omagic;
-  bool optEB = false;
-  bool optEL = false;
-  bool optimizeBBJumps;
-  bool optRemarksWithHotness;
-  bool picThunk;
-  bool pie;
+  bool getNostdlib() const { return warnBackrefsExclude.getFlag(3); }
+  void setNostdlib(bool Value) { warnBackrefsExclude.setFlag(3, Value); }
+  bool getOFormatBinary() const { return shuffleSections.getFlag(0); }
+  void setOFormatBinary(bool Value) { shuffleSections.setFlag(0, Value); }
+  bool getOmagic() const { return shuffleSections.getFlag(1); }
+  void setOmagic(bool Value) { shuffleSections.setFlag(1, Value); }
+  bool getOptEB() const { return shuffleSections.getFlag(2); }
+  bool setOptEB(bool Value) {
+    shuffleSections.setFlag(2, Value);
+    return Value;
+  }
+  bool getOptEL() const { return shuffleSections.getFlag(3); }
+  bool setOptEL(bool Value) {
+    shuffleSections.setFlag(3, Value);
+    return Value;
+  }
+  bool getOptimizeBBJumps() const { return deadRelocInNonAlloc.getFlag(0); }
+  void setOptimizeBBJumps(bool Value) { deadRelocInNonAlloc.setFlag(0, Value); }
+  bool getOptRemarksWithHotness() const {
+    return deadRelocInNonAlloc.getFlag(1);
+  }
+  void setOptRemarksWithHotness(bool Value) {
+    deadRelocInNonAlloc.setFlag(1, Value);
+  }
+  bool getPicThunk() const { return deadRelocInNonAlloc.getFlag(2); }
+  void setPicThunk(bool Value) { deadRelocInNonAlloc.setFlag(2, Value); }
+  bool getPie() const { return deadRelocInNonAlloc.getFlag(3); }
+  void setPie(bool Value) { deadRelocInNonAlloc.setFlag(3, Value); }
   llvm::StringRef printGcSections;
-  bool printIcfSections;
-  bool printMemoryUsage;
+  bool getPrintIcfSections() const { return compressSections.getFlag(0); }
+  void setPrintIcfSections(bool Value) { compressSections.setFlag(0, Value); }
+  bool getPrintMemoryUsage() const { return compressSections.getFlag(1); }
+  void setPrintMemoryUsage(bool Value) { compressSections.setFlag(1, Value); }
   std::optional<uint64_t> randomizeSectionPadding;
-  bool rejectMismatch;
-  bool relax;
-  bool relaxGP;
-  bool relocatable;
-  bool resolveGroups;
-  bool relrGlibc = false;
+  bool getRejectMismatch() const { return compressSections.getFlag(2); }
+  void setRejectMismatch(bool Value) { compressSections.setFlag(2, Value); }
+  bool getRelax() const { return compressSections.getFlag(3); }
+  void setRelax(bool Value) { compressSections.setFlag(3, Value); }
+  bool getRelaxGP() const { return bpCompressionSortSpecs.getFlag(0); }
+  void setRelaxGP(bool Value) { bpCompressionSortSpecs.setFlag(0, Value); }
+  bool getRelocatable() const { return bpCompressionSortSpecs.getFlag(1); }
+  void setRelocatable(bool Value) { bpCompressionSortSpecs.setFlag(1, Value); }
+  bool getResolveGroups() const { return bpCompressionSortSpecs.getFlag(2); }
+  void setResolveGroups(bool Value) {
+    bpCompressionSortSpecs.setFlag(2, Value);
+  }
+  bool getRelrGlibc() const { return bpCompressionSortSpecs.getFlag(3); }
+  void setRelrGlibc(bool Value) { bpCompressionSortSpecs.setFlag(3, Value); }
   bool relrPackDynRelocs = false;
   llvm::DenseSet<llvm::StringRef> saveTempsArgs;
-  llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
-  bool singleRoRx;
-  bool singleXoRx;
-  bool shared;
-  bool symbolic;
+  llvm::SmallVectorWithFlags<std::pair<llvm::GlobPattern, uint32_t>, 0, 4>
+      shuffleSections;
+  bool getSingleRoRx() const { return mllvmOpts.getFlag(0); }
+  void setSingleRoRx(bool Value) { mllvmOpts.setFlag(0, Value); }
+  bool getSingleXoRx() const { return mllvmOpts.getFlag(1); }
+  void setSingleXoRx(bool Value) { mllvmOpts.setFlag(1, Value); }
+  bool getShared() const { return mllvmOpts.getFlag(2); }
+  void setShared(bool Value) { mllvmOpts.setFlag(2, Value); }
+  bool getSymbolic() const { return mllvmOpts.getFlag(3); }
+  void setSymbolic(bool Value) { mllvmOpts.setFlag(3, Value); }
   bool isStatic = false;
-  bool sysvHash = false;
-  bool target1Rel;
-  bool trace;
+  bool getSysvHash() const { return dynamicList.getFlag(0); }
+  bool setSysvHash(bool Value) {
+    dynamicList.setFlag(0, Value);
+    return Value;
+  }
+  bool getTarget1Rel() const { return dynamicList.getFlag(1); }
+  void setTarget1Rel(bool Value) { dynamicList.setFlag(1, Value); }
+  bool getTrace() const { return dynamicList.getFlag(2); }
+  void setTrace(bool Value) { dynamicList.setFlag(2, Value); }
   bool thinLTOEmitImportsFiles;
   bool thinLTOEmitIndexFiles;
-  bool thinLTOIndexOnly;
-  bool timeTraceEnabled;
-  bool tocOptimize;
-  bool pcRelOptimize;
-  bool undefinedVersion;
-  bool unique;
-  bool useAndroidRelrTags = false;
-  bool warnBackrefs;
-  llvm::SmallVector<llvm::GlobPattern, 0> warnBackrefsExclude;
+  bool getThinLTOIndexOnly() const { return dynamicList.getFlag(3); }
+  void setThinLTOIndexOnly(bool Value) { dynamicList.setFlag(3, Value); }
+  bool getTimeTraceEnabled() const { return undefined.getFlag(0); }
+  void setTimeTraceEnabled(bool Value) { undefined.setFlag(0, Value); }
+  bool getTocOptimize() const { return undefined.getFlag(1); }
+  void setTocOptimize(bool Value) { undefined.setFlag(1, Value); }
+  bool getPcRelOptimize() const { return undefined.getFlag(2); }
+  void setPcRelOptimize(bool Value) { undefined.setFlag(2, Value); }
+  bool getUndefinedVersion() const { return undefined.getFlag(3); }
+  void setUndefinedVersion(bool Value) { undefined.setFlag(3, Value); }
+  bool getUnique() const { return dtltoCompilerArgs.getFlag(0); }
+  void setUnique(bool Value) { dtltoCompilerArgs.setFlag(0, Value); }
+  bool getUseAndroidRelrTags() const { return dtltoCompilerArgs.getFlag(1); }
+  void setUseAndroidRelrTags(bool Value) {
+    dtltoCompilerArgs.setFlag(1, Value);
+  }
+  bool getWarnBackrefs() const { return dtltoCompilerArgs.getFlag(2); }
+  void setWarnBackrefs(bool Value) { dtltoCompilerArgs.setFlag(2, Value); }
+  llvm::SmallVectorWithFlags<llvm::GlobPattern, 0, 4> warnBackrefsExclude;
   bool warnCommon;
   bool warnMissingEntry;
   bool warnSymbolOrdering;
@@ -431,33 +528,78 @@ struct Config {
   bool zCombreloc;
   bool zCopyreloc;
   bool zDynamicUndefined;
-  bool zForceBti;
-  bool zForceIbt;
-  bool zGlobal;
-  bool zHazardplt;
-  bool zIfuncNoplt;
-  bool zInitfirst;
-  bool zInterpose;
-  bool zKeepDataSectionPrefix;
-  bool zKeepTextSectionPrefix;
-  bool zLrodataAfterBss;
-  bool zMarkPlt;
-  bool zNoBtCfi;
-  bool zNodefaultlib;
-  bool zNodelete;
-  bool zNodlopen;
-  bool zNow;
-  bool zOrigin;
-  bool zPacPlt;
-  bool zRelro;
-  bool zRodynamic;
-  bool zSectionHeader;
-  bool zShstk;
-  bool zStartStopGC;
+  bool getZForceBti() const { return dtltoCompilerArgs.getFlag(3); }
+  void setZForceBti(bool Value) { dtltoCompilerArgs.setFlag(3, Value); }
+  bool getZForceIbt() const { return dtltoCompilerPrependArgs.getFlag(0); }
+  void setZForceIbt(bool Value) { dtltoCompilerPrependArgs.setFlag(0, Value); }
+  bool getZGlobal() const { return dtltoCompilerPrependArgs.getFlag(1); }
+  void setZGlobal(bool Value) { dtltoCompilerPrependArgs.setFlag(1, Value); }
+  bool getZHazardplt() const { return dtltoCompilerPrependArgs.getFlag(2); }
+  void setZHazardplt(bool Value) { dtltoCompilerPrependArgs.setFlag(2, Value); }
+  bool getZIfuncNoplt() const { return dtltoCompilerPrependArgs.getFlag(3); }
+  void setZIfuncNoplt(bool Value) {
+    dtltoCompilerPrependArgs.setFlag(3, Value);
+  }
+  bool getZInitfirst() const { return dtltoDistributorArgs.getFlag(0); }
+  void setZInitfirst(bool Value) { dtltoDistributorArgs.setFlag(0, Value); }
+  bool getZInterpose() const { return dtltoDistributorArgs.getFlag(1); }
+  void setZInterpose(bool Value) { dtltoDistributorArgs.setFlag(1, Value); }
+  bool getZKeepDataSectionPrefix() const {
+    return dtltoDistributorArgs.getFlag(2);
+  }
+  void setZKeepDataSectionPrefix(bool Value) {
+    dtltoDistributorArgs.setFlag(2, Value);
+  }
+  bool getZKeepTextSectionPrefix() const {
+    return dtltoDistributorArgs.getFlag(3);
+  }
+  void setZKeepTextSectionPrefix(bool Value) {
+    dtltoDistributorArgs.setFlag(3, Value);
+  }
+  bool getZLrodataAfterBss() const {
+    return thinLTOModulesToCompile.getFlag(0);
+  }
+  void setZLrodataAfterBss(bool Value) {
+    thinLTOModulesToCompile.setFlag(0, Value);
+  }
+  bool getZMarkPlt() const { return thinLTOModulesToCompile.getFlag(1); }
+  void setZMarkPlt(bool Value) { thinLTOModulesToCompile.setFlag(1, Value); }
+  bool getZNoBtCfi() const { return thinLTOModulesToCompile.getFlag(2); }
+  void setZNoBtCfi(bool Value) { thinLTOModulesToCompile.setFlag(2, Value); }
+  bool getZNodefaultlib() const { return thinLTOModulesToCompile.getFlag(3); }
+  void setZNodefaultlib(bool Value) {
+    thinLTOModulesToCompile.setFlag(3, Value);
+  }
+  bool getZNodelete() const { return searchPaths.getFlag(0); }
+  void setZNodelete(bool Value) { searchPaths.setFlag(0, Value); }
+  bool getZNodlopen() const { return searchPaths.getFlag(1); }
+  void setZNodlopen(bool Value) { searchPaths.setFlag(1, Value); }
+  bool getZNow() const { return searchPaths.getFlag(2); }
+  void setZNow(bool Value) { searchPaths.setFlag(2, Value); }
+  bool getZOrigin() const { return searchPaths.getFlag(3); }
+  void setZOrigin(bool Value) { searchPaths.setFlag(3, Value); }
+  bool getZPacPlt() const { return passPlugins.getFlag(0); }
+  void setZPacPlt(bool Value) { passPlugins.setFlag(0, Value); }
+  bool getZRelro() const { return passPlugins.getFlag(1); }
+  bool setZRelro(bool Value) {
+    passPlugins.setFlag(1, Value);
+    return Value;
+  }
+  bool getZRodynamic() const { return passPlugins.getFlag(2); }
+  void setZRodynamic(bool Value) { passPlugins.setFlag(2, Value); }
+  bool getZSectionHeader() const { return passPlugins.getFlag(3); }
+  void setZSectionHeader(bool Value) { passPlugins.setFlag(3, Value); }
+  bool getZShstk() const { return filterList.getFlag(0); }
+  void setZShstk(bool Value) { filterList.setFlag(0, Value); }
+  bool getZStartStopGC() const { return filterList.getFlag(1); }
+  void setZStartStopGC(bool Value) { filterList.setFlag(1, Value); }
   uint8_t zStartStopVisibility;
-  bool zText;
-  bool zRetpolineplt;
-  bool zWxneeded;
+  bool getZText() const { return filterList.getFlag(2); }
+  void setZText(bool Value) { filterList.setFlag(2, Value); }
+  bool getZRetpolineplt() const { return filterList.getFlag(3); }
+  void setZRetpolineplt(bool Value) { filterList.setFlag(3, Value); }
+  bool getZWxneeded() const { return auxiliaryList.getFlag(0); }
+  void setZWxneeded(bool Value) { auxiliaryList.setFlag(0, Value); }
   ZicfilpPolicy zZicfilp;
   ZicfissPolicy zZicfiss;
   DiscardPolicy discard;
@@ -470,7 +612,8 @@ struct Config {
   UnresolvedPolicy unresolvedSymbolsInShlib;
   Target2Policy target2;
   GcsPolicy zGcs;
-  bool power10Stubs;
+  bool getPower10Stubs() const { return auxiliaryList.getFlag(1); }
+  void setPower10Stubs(bool Value) { auxiliaryList.setFlag(1, Value); }
   ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
   BuildIdKind buildId = BuildIdKind::None;
   SeparateSegmentKind zSeparate;
@@ -488,20 +631,23 @@ struct Config {
   StringRef thinLTOJobs;
   unsigned timeTraceGranularity;
   int32_t splitStackAdjustSize;
-  SmallVector<uint8_t, 0> packageMetadata;
+  llvm::SmallVectorWithFlags<uint8_t, 0, 4> packageMetadata;
 
   // The following config options do not directly correspond to any
   // particular command line options.
 
   // True if we need to pass through relocations in input files to the
   // output file. Usually false because we consume relocations.
-  bool copyRelocs;
+  bool getCopyRelocs() const { return auxiliaryList.getFlag(2); }
+  void setCopyRelocs(bool Value) { auxiliaryList.setFlag(2, Value); }
 
   // True if the target is ELF64. False if ELF32.
-  bool is64;
+  bool getIs64() const { return auxiliaryList.getFlag(3); }
+  void setIs64(bool Value) { auxiliaryList.setFlag(3, Value); }
 
   // True if the target is little-endian. False if big-endian.
-  bool isLE;
+  bool getIsLE() const { return versionDefinitions.getFlag(0); }
+  void setIsLE(bool Value) { versionDefinitions.setFlag(0, Value); }
 
   // endianness::little if isLE is true. endianness::big otherwise.
   llvm::endianness endianness;
@@ -518,7 +664,8 @@ struct Config {
   // name whatever that means. A fun hypothesis is that "EL" is short for
   // little-endian written in the little-endian order, but I don't know
   // if that's true.)
-  bool isMips64EL;
+  bool getIsMips64EL() const { return versionDefinitions.getFlag(1); }
+  void setIsMips64EL(bool Value) { versionDefinitions.setFlag(1, Value); }
 
   // Holds set of ELF header flags for the target.
   uint32_t eflags = 0;
@@ -537,10 +684,12 @@ struct Config {
   // Each ABI defines its relocation type. IsRela is true if target
   // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A
   // few 32-bit ABIs are using RELA too.
-  bool isRela;
+  bool getIsRela() const { return versionDefinitions.getFlag(2); }
+  void setIsRela(bool Value) { versionDefinitions.setFlag(2, Value); }
 
   // True if we are creating position-independent code.
-  bool isPic;
+  bool getIsPic() const { return versionDefinitions.getFlag(3); }
+  void setIsPic(bool Value) { versionDefinitions.setFlag(3, Value); }
 
   // 4 for ELF32, 8 for ELF64.
   int wordsize;
@@ -566,7 +715,8 @@ struct Config {
   // If an input file equals a key, remap it to the value.
   llvm::DenseMap<llvm::StringRef, llvm::StringRef> remapInputs;
   // If an input file matches a wildcard pattern, remap it to the value.
-  llvm::SmallVector<std::pair<llvm::GlobPattern, llvm::StringRef>, 0>
+  llvm::SmallVectorWithFlags<std::pair<llvm::GlobPattern, llvm::StringRef>, 0,
+                             4>
       remapInputsWildcards;
 };
 
@@ -592,8 +742,12 @@ struct UndefinedDiag {
     InputSectionBase *sec;
     uint64_t offset;
   };
-  SmallVector<Loc, 0> locs;
-  bool isWarning;
+  llvm::SmallVectorWithFlags<Loc, 0> locs;
+  bool getIsWarning() const { return locs.getFlag(0); }
+  void setIsWarning(bool Value) { locs.setFlag(0, Value); }
+
+  UndefinedDiag(Undefined *sym, SmallVector<Loc, 0> locs, bool isWarning)
+      : sym(sym), locs(unsigned(isWarning), std::move(locs)) {}
 };
 
 // Linker generated sections which can be used as inputs.
@@ -738,9 +892,11 @@ struct Ctx : CommonLinkerContext {
   SmallVector<UndefinedDiag, 0> undefErrs;
   // Symbols in a non-prevailing COMDAT group which should be changed to an
   // Undefined.
-  SmallVector<std::pair<Symbol *, unsigned>, 0> nonPrevailingSyms;
+  llvm::SmallVectorWithFlags<std::pair<Symbol *, unsigned>, 0>
+      nonPrevailingSyms;
   // A tuple of (reference, extractedFile, sym). Used by --why-extract=.
-  SmallVector<std::tuple<std::string, const InputFile *, const Symbol &>, 0>
+  llvm::SmallVectorWithFlags<
+      std::tuple<std::string, const InputFile *, const Symbol &>, 0, 4>
       whyExtractRecords;
   // A mapping from a symbol to an InputFile referencing it backward. Used by
   // --warn-backrefs.
@@ -756,14 +912,20 @@ struct Ctx : CommonLinkerContext {
   // Dummy Undefined for relocations without a symbol.
   Undefined *dummySym = nullptr;
   // True if symbols can be exported (isExported) or preemptible.
-  bool hasDynsym = false;
+  bool getHasDynsym() const { return whyExtractRecords.getFlag(0); }
+  void setHasDynsym(bool Value) { whyExtractRecords.setFlag(0, Value); }
   // True if there are TLS IE relocations. Set DF_STATIC_TLS if -shared.
   std::atomic<bool> hasTlsIe{false};
   // True if we need to reserve two .got entries for local-dynamic TLS model.
   std::atomic<bool> needsTlsLd{false};
   // True if all native vtable symbols have corresponding type info symbols
   // during LTO.
-  bool ltoAllVtablesHaveTypeInfos = false;
+  bool getLtoAllVtablesHaveTypeInfos() const {
+    return whyExtractRecords.getFlag(1);
+  }
+  void setLtoAllVtablesHaveTypeInfos(bool Value) {
+    whyExtractRecords.setFlag(1, Value);
+  }
   // Number of Vernaux entries (needed shared object names).
   uint32_t vernauxNum = 0;
 
@@ -790,12 +952,15 @@ struct Ctx : CommonLinkerContext {
 
   // True if performing the embedded unoptimized dynamic debugging relocatable
   // link.
-  bool inDynDbgLink = false;
+  bool getInDynDbgLink() const { return whyExtractRecords.getFlag(2); }
+  void setInDynDbgLink(bool Value) { whyExtractRecords.setFlag(2, Value); }
   // True if performing dynamic debugging style relocatable link rather than a
   // regular relocatable link.
-  bool dynDbgRelocatable = false;
+  bool getDynDbgRelocatable() const { return whyExtractRecords.getFlag(3); }
+  void setDynDbgRelocatable(bool Value) { whyExtractRecords.setFlag(3, Value); }
   // True if the link contains dynamic debugging.
-  bool hasDynDbg = false;
+  bool getHasDynDbg() const { return nonPrevailingSyms.getFlag(0); }
+  void setHasDynDbg(bool Value) { nonPrevailingSyms.setFlag(0, Value); }
   // Pointer to the output of the embedded unoptimized dynamic debugging
   // relocatable link.
   std::unique_ptr<llvm::FileOutputBuffer> dynDbgOutput;
diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp
index 78fd013bef22c..a458d9c701055 100644
--- a/lld/ELF/DWARF.cpp
+++ b/lld/ELF/DWARF.cpp
@@ -110,7 +110,7 @@ LLDDwarfObj<ELFT>::findAux(const InputSectionBase &sec, uint64_t pos,
 
   const ObjFile<ELFT> *file = sec.getFile<ELFT>();
   Ctx &ctx = sec.getCtx();
-  uint32_t symIndex = rel.getSymbol(ctx.arg.isMips64EL);
+  uint32_t symIndex = rel.getSymbol(ctx.arg.getIsMips64EL());
   const typename ELFT::Sym &sym = file->template getELFSyms<ELFT>()[symIndex];
   uint32_t secIndex = file->getSectionIndex(sym);
 
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 134aae9ef98ad..68473ed991e8a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -236,17 +236,11 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
   MemoryBufferRef mbref = *buffer;
 
   if (ctx.arg.formatBinary) {
-    loadJobs.push_back({mbref,
-                        path,
-                        LoadJob::Binary,
+    loadJobs.push_back({mbref, path, LoadJob::Binary,
                         /*inWholeArchive=*/false,
                         /*lazy=*/false,
                         /*asNeeded=*/false,
-                        /*withLOption=*/false,
-                        nextGroupId,
-                        {},
-                        {},
-                        {}});
+                        /*withLOption=*/false, nextGroupId});
   } else {
     auto magic = identify_magic(mbref.getBuffer());
     if (magic == file_magic::unknown) {
@@ -275,17 +269,8 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
       Err(ctx) << path << ": unknown file type";
       return;
     }
-    loadJobs.push_back({mbref,
-                        path,
-                        kind,
-                        inWholeArchive,
-                        inLib,
-                        ctx.arg.asNeeded,
-                        withLOption,
-                        nextGroupId,
-                        {},
-                        {},
-                        {}});
+    loadJobs.push_back({mbref, path, kind, inWholeArchive, inLib,
+                        ctx.arg.asNeeded, withLOption, nextGroupId});
   }
   if (!isInGroup)
     ++nextGroupId;
@@ -334,7 +319,7 @@ static void checkOptions(Ctx &ctx) {
       if (!ctx.arg.cmseOutputLib.empty())
         ErrAlways(ctx) << "--out-implib may not be used without --cmse-implib";
     }
-    if (ctx.arg.fixCortexA8 && !ctx.arg.isLE)
+    if (ctx.arg.fixCortexA8 && !ctx.arg.getIsLE())
       ErrAlways(ctx)
           << "--fix-cortex-a8 is not supported on big endian targets";
   } else {
@@ -346,7 +331,7 @@ static void checkOptions(Ctx &ctx) {
       ErrAlways(ctx) << "--out-implib is only supported on ARM targets";
     if (ctx.arg.fixCortexA8)
       ErrAlways(ctx) << "--fix-cortex-a8 is only supported on ARM targets";
-    if (ctx.arg.armBe8)
+    if (ctx.arg.getArmBe8())
       ErrAlways(ctx) << "--be8 is only supported on ARM targets";
   }
 
@@ -355,9 +340,9 @@ static void checkOptions(Ctx &ctx) {
       ErrAlways(ctx) << "--execute-only is only supported on AArch64 targets";
     if (ctx.arg.fixCortexA53Errata843419)
       ErrAlways(ctx) << "--fix-cortex-a53-843419 is only supported on AArch64";
-    if (ctx.arg.zPacPlt)
+    if (ctx.arg.getZPacPlt())
       ErrAlways(ctx) << "-z pac-plt only supported on AArch64";
-    if (ctx.arg.zForceBti)
+    if (ctx.arg.getZForceBti())
       ErrAlways(ctx) << "-z force-bti only supported on AArch64";
     if (ctx.arg.zBtiReport != ReportPolicy::None)
       ErrAlways(ctx) << "-z bti-report only supported on AArch64";
@@ -377,15 +362,15 @@ static void checkOptions(Ctx &ctx) {
         << "-z execute-only-report only supported on AArch64 and ARM";
 
   if (ctx.arg.emachine != EM_PPC64) {
-    if (ctx.arg.tocOptimize)
+    if (ctx.arg.getTocOptimize())
       ErrAlways(ctx) << "--toc-optimize is only supported on PowerPC64 targets";
-    if (ctx.arg.pcRelOptimize)
+    if (ctx.arg.getPcRelOptimize())
       ErrAlways(ctx)
           << "--pcrel-optimize is only supported on PowerPC64 targets";
   }
 
   if (ctx.arg.emachine != EM_RISCV) {
-    if (ctx.arg.relaxGP)
+    if (ctx.arg.getRelaxGP())
       ErrAlways(ctx) << "--relax-gp is only supported on RISC-V targets";
     if (ctx.arg.zZicfilpUnlabeledReport != ReportPolicy::None)
       ErrAlways(ctx) << "-z zicfilip-unlabeled-report is only supported on "
@@ -405,56 +390,56 @@ static void checkOptions(Ctx &ctx) {
       ctx.arg.zCetReport != ReportPolicy::None)
     ErrAlways(ctx) << "-z cet-report only supported on X86 and X86_64";
 
-  if (ctx.arg.zMarkPlt) {
+  if (ctx.arg.getZMarkPlt()) {
     if (ctx.arg.emachine != EM_X86_64)
       ErrAlways(ctx) << "-z mark-plt only supported on X86_64";
     // The PLT entry address is stored in the JUMP_SLOT relocation's addend, so
     // -z mark-plt requires RELA relocations. REL relocations have no addend
     // field and the .got.plt entry is already occupied by the lazy-binding
     // address, so the information would be silently lost.
-    else if (!ctx.arg.isRela)
+    else if (!ctx.arg.getIsRela())
       ErrAlways(ctx) << "-z mark-plt requires -z rela";
   }
 
-  if (ctx.arg.pie && ctx.arg.shared)
+  if (ctx.arg.getPie() && ctx.arg.getShared())
     ErrAlways(ctx) << "-shared and -pie may not be used together";
 
-  if (!ctx.arg.shared && !ctx.arg.filterList.empty())
+  if (!ctx.arg.getShared() && !ctx.arg.filterList.empty())
     ErrAlways(ctx) << "-F may not be used without -shared";
 
-  if (!ctx.arg.shared && !ctx.arg.auxiliaryList.empty())
+  if (!ctx.arg.getShared() && !ctx.arg.auxiliaryList.empty())
     ErrAlways(ctx) << "-f may not be used without -shared";
 
   if (ctx.arg.strip == StripPolicy::All && ctx.arg.emitRelocs)
     ErrAlways(ctx) << "--strip-all and --emit-relocs may not be used together";
 
-  if (ctx.arg.zText && ctx.arg.zIfuncNoplt)
+  if (ctx.arg.getZText() && ctx.arg.getZIfuncNoplt())
     ErrAlways(ctx) << "-z text and -z ifunc-noplt may not be used together";
 
-  if (ctx.arg.relocatable) {
-    if (ctx.arg.shared)
+  if (ctx.arg.getRelocatable()) {
+    if (ctx.arg.getShared())
       ErrAlways(ctx) << "-r and -shared may not be used together";
     if (ctx.arg.gdbIndex)
       ErrAlways(ctx) << "-r and --gdb-index may not be used together";
     if (ctx.arg.icf != ICFLevel::None)
       ErrAlways(ctx) << "-r and --icf may not be used together";
-    if (ctx.arg.pie)
+    if (ctx.arg.getPie())
       ErrAlways(ctx) << "-r and -pie may not be used together";
     if (ctx.arg.exportDynamic)
       ErrAlways(ctx) << "-r and --export-dynamic may not be used together";
     if (ctx.arg.debugNames)
       ErrAlways(ctx) << "-r and --debug-names may not be used together";
-    if (!ctx.arg.zSectionHeader)
+    if (!ctx.arg.getZSectionHeader())
       ErrAlways(ctx) << "-r and -z nosectionheader may not be used together";
   }
 
   if (ctx.arg.executeOnly) {
-    if (ctx.arg.singleRoRx && !ctx.script->hasSectionsCommand)
+    if (ctx.arg.getSingleRoRx() && !ctx.script->getHasSectionsCommand())
       ErrAlways(ctx)
           << "--execute-only and --no-rosegment cannot be used together";
   }
 
-  if (ctx.arg.zRetpolineplt && ctx.arg.zForceIbt)
+  if (ctx.arg.getZRetpolineplt() && ctx.arg.getZForceIbt())
     ErrAlways(ctx) << "-z force-ibt may not be used with -z retpolineplt";
 }
 
@@ -640,6 +625,14 @@ constexpr const char *saveTempsValues[] = {
     "resolution", "preopt",     "promote", "internalize",  "import",
     "opt",        "precodegen", "prelink", "combinedindex"};
 
+LoadJob::LoadJob(MemoryBufferRef mbref, StringRef path, Kind kind,
+                 bool inWholeArchive, bool lazy, bool asNeeded,
+                 bool withLOption, uint32_t groupId)
+    : mbref(mbref), path(path), kind(kind), groupId(groupId),
+      tarEntries(decltype(this->tarEntries)::withFlags(
+          unsigned(inWholeArchive) | (unsigned(lazy) << 1) |
+          (unsigned(asNeeded) << 2) | (unsigned(withLOption) << 3))) {}
+
 LinkerDriver::LinkerDriver(Ctx &ctx) : ctx(ctx) {}
 
 void LinkerDriver::waitForLTOCleanup() {
@@ -682,7 +675,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
     Msg(ctx) << getLLDVersion() << " (compatible with GNU linkers)";
 
-  if (const char *path = getReproduceOption(args); !ctx.inDynDbgLink && path) {
+  if (const char *path = getReproduceOption(args);
+      !ctx.getInDynDbgLink() && path) {
     // Note that --reproduce is a debug option so you can ignore it
     // if you are trying to understand the whole picture of the code.
     Expected<std::unique_ptr<TarWriter>> errOrWriter =
@@ -711,7 +705,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     return;
 
   // Initialize time trace profiler.
-  if (ctx.arg.timeTraceEnabled)
+  if (ctx.arg.getTimeTraceEnabled())
     timeTraceProfilerInitialize(ctx.arg.timeTraceGranularity, ctx.arg.progName);
 
   {
@@ -734,7 +728,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // writing the time trace data.
   waitForLTOCleanup();
 
-  if (ctx.arg.timeTraceEnabled) {
+  if (ctx.arg.getTimeTraceEnabled()) {
     checkError(ctx.e, timeTraceProfilerWrite(
                           args.getLastArgValue(OPT_time_trace_eq).str(),
                           ctx.arg.outputFile));
@@ -756,7 +750,7 @@ static void setUnresolvedSymbolPolicy(Ctx &ctx, opt::InputArgList &args) {
                                      : UnresolvedPolicy::Warn;
   // -shared implies --unresolved-symbols=ignore-all because missing
   // symbols are likely to be resolved at runtime.
-  bool diagRegular = !ctx.arg.shared, diagShlib = !ctx.arg.shared;
+  bool diagRegular = !ctx.arg.getShared(), diagShlib = !ctx.arg.getShared();
 
   for (const opt::Arg *arg : args) {
     switch (arg->getOption().getID()) {
@@ -890,13 +884,13 @@ static void parsePackageMetadata(Ctx &ctx, const opt::Arg &arg) {
       return;
     }
   }
-  ctx.arg.packageMetadata = std::move(decoded);
+  ctx.arg.packageMetadata.assign(std::move(decoded));
 }
 
 static StripPolicy getStrip(Ctx &ctx, opt::InputArgList &args) {
   if (args.hasArg(OPT_relocatable))
     return StripPolicy::None;
-  if (!ctx.arg.zSectionHeader)
+  if (!ctx.arg.getZSectionHeader())
     return StripPolicy::All;
 
   auto *arg = args.getLastArg(OPT_strip_all, OPT_strip_debug);
@@ -1071,14 +1065,14 @@ processCallGraphRelocations(Ctx &ctx, SmallVector<uint32_t, 32> &symbolIndices,
         ArrayRef<typename ELFT::Rela> relas =
             CHECK(obj.relas(sec), "could not retrieve cg profile rela section");
         for (const typename ELFT::Rela &rel : relas)
-          symbolIndices.push_back(rel.getSymbol(ctx.arg.isMips64EL));
+          symbolIndices.push_back(rel.getSymbol(ctx.arg.getIsMips64EL()));
         break;
       }
       if (sec.sh_type == SHT_REL) {
         ArrayRef<typename ELFT::Rel> rels =
             CHECK(obj.rels(sec), "could not retrieve cg profile rel section");
         for (const typename ELFT::Rel &rel : rels)
-          symbolIndices.push_back(rel.getSymbol(ctx.arg.isMips64EL));
+          symbolIndices.push_back(rel.getSymbol(ctx.arg.getIsMips64EL()));
         break;
       }
     }
@@ -1170,7 +1164,7 @@ static void ltoValidateAllVtablesHaveTypeInfos(Ctx &ctx,
         [&](StringRef s) { return pat->match(s); });
   }
 
-  ctx.ltoAllVtablesHaveTypeInfos = vtableSymbolsWithNoRTTI.empty();
+  ctx.setLtoAllVtablesHaveTypeInfos(vtableSymbolsWithNoRTTI.empty());
   // Check for unmatched RTTI symbols
   for (StringRef s : vtableSymbolsWithNoRTTI) {
     Msg(ctx) << "--lto-validate-all-vtables-have-type-infos: RTTI missing for "
@@ -1244,12 +1238,12 @@ static void parseBPOrdererOptions(Ctx &ctx, opt::InputArgList &args) {
   if (auto *arg = args.getLastArg(OPT_bp_compression_sort)) {
     StringRef s = arg->getValue();
     if (s == "function") {
-      ctx.arg.bpFunctionOrderForCompression = true;
+      ctx.arg.setBpFunctionOrderForCompression(true);
     } else if (s == "data") {
-      ctx.arg.bpDataOrderForCompression = true;
+      ctx.arg.setBpDataOrderForCompression(true);
     } else if (s == "both") {
-      ctx.arg.bpFunctionOrderForCompression = true;
-      ctx.arg.bpDataOrderForCompression = true;
+      ctx.arg.setBpFunctionOrderForCompression(true);
+      ctx.arg.setBpDataOrderForCompression(true);
     } else if (s != "none") {
       ErrAlways(ctx) << arg->getSpelling()
                      << ": expected [none|function|data|both]";
@@ -1261,7 +1255,7 @@ static void parseBPOrdererOptions(Ctx &ctx, opt::InputArgList &args) {
   if (auto *arg = args.getLastArg(OPT_bp_startup_sort)) {
     StringRef s = arg->getValue();
     if (s == "function") {
-      ctx.arg.bpStartupFunctionSort = true;
+      ctx.arg.setBpStartupFunctionSort(true);
     } else if (s != "none") {
       ErrAlways(ctx) << arg->getSpelling() << ": expected [none|function]";
     }
@@ -1270,17 +1264,18 @@ static void parseBPOrdererOptions(Ctx &ctx, opt::InputArgList &args) {
                         "--call-graph-ordering-file";
   }
 
-  ctx.arg.bpCompressionSortStartupFunctions =
+  ctx.arg.setBpCompressionSortStartupFunctions(
       args.hasFlag(OPT_bp_compression_sort_startup_functions,
-                   OPT_no_bp_compression_sort_startup_functions, false);
-  ctx.arg.bpVerboseSectionOrderer = args.hasArg(OPT_verbose_bp_section_orderer);
+                   OPT_no_bp_compression_sort_startup_functions, false));
+  ctx.arg.setBpVerboseSectionOrderer(
+      args.hasArg(OPT_verbose_bp_section_orderer));
 
   ctx.arg.irpgoProfilePath = args.getLastArgValue(OPT_irpgo_profile);
   if (ctx.arg.irpgoProfilePath.empty()) {
-    if (ctx.arg.bpStartupFunctionSort)
+    if (ctx.arg.getBpStartupFunctionSort())
       ErrAlways(ctx) << "--bp-startup-sort=function must be used with "
                         "--irpgo-profile";
-    if (ctx.arg.bpCompressionSortStartupFunctions)
+    if (ctx.arg.getBpCompressionSortStartupFunctions())
       ErrAlways(ctx)
           << "--bp-compression-sort-startup-functions must be used with "
              "--irpgo-profile";
@@ -1410,8 +1405,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.fatLTOObjects =
       args.hasFlag(OPT_fat_lto_objects, OPT_no_fat_lto_objects, false);
   ctx.arg.memtagMode = getMemtagMode(ctx, args);
-  ctx.arg.auxiliaryList = args::getStrings(args, OPT_auxiliary);
-  ctx.arg.armBe8 = args.hasArg(OPT_be8);
+  ctx.arg.auxiliaryList.assign(args::getStrings(args, OPT_auxiliary));
+  ctx.arg.setArmBe8(args.hasArg(OPT_be8));
   if (opt::Arg *arg = args.getLastArg(
           OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
           OPT_Bsymbolic_functions, OPT_Bsymbolic_non_weak, OPT_Bsymbolic)) {
@@ -1426,16 +1421,16 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   }
   ctx.arg.callGraphProfileSort = getCGProfileSortKind(ctx, args);
   parseBPOrdererOptions(ctx, args);
-  ctx.arg.checkSections =
-      args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
+  ctx.arg.setCheckSections(
+      args.hasFlag(OPT_check_sections, OPT_no_check_sections, true));
   ctx.arg.chroot = args.getLastArgValue(OPT_chroot);
   if (auto *arg = args.getLastArg(OPT_compress_debug_sections)) {
     ctx.arg.compressDebugSections =
         getCompressionType(ctx, arg->getValue(), "--compress-debug-sections");
   }
-  ctx.arg.cref = args.hasArg(OPT_cref);
-  ctx.arg.optimizeBBJumps =
-      args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false);
+  ctx.arg.setCref(args.hasArg(OPT_cref));
+  ctx.arg.setOptimizeBBJumps(
+      args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false));
   ctx.arg.debugNames = args.hasFlag(OPT_debug_names, OPT_no_debug_names, false);
   ctx.arg.demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
   ctx.arg.dependencyFile = args.getLastArgValue(OPT_dependency_file);
@@ -1444,13 +1439,13 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.disableVerify = args.hasArg(OPT_disable_verify);
   ctx.arg.discard = getDiscard(args);
   ctx.arg.dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor_eq);
-  ctx.arg.dtltoDistributorArgs =
-      args::getStrings(args, OPT_thinlto_distributor_arg);
+  ctx.arg.dtltoDistributorArgs.assign(
+      args::getStrings(args, OPT_thinlto_distributor_arg));
   ctx.arg.dtltoCompiler = args.getLastArgValue(OPT_thinlto_remote_compiler_eq);
-  ctx.arg.dtltoCompilerPrependArgs =
-      args::getStrings(args, OPT_thinlto_remote_compiler_prepend_arg);
-  ctx.arg.dtltoCompilerArgs =
-      args::getStrings(args, OPT_thinlto_remote_compiler_arg);
+  ctx.arg.dtltoCompilerPrependArgs.assign(
+      args::getStrings(args, OPT_thinlto_remote_compiler_prepend_arg));
+  ctx.arg.dtltoCompilerArgs.assign(
+      args::getStrings(args, OPT_thinlto_remote_compiler_arg));
   ctx.arg.dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
   ctx.arg.dynamicLinker = getDynamicLinker(ctx, args);
   ctx.arg.ehFrameHdr =
@@ -1470,7 +1465,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.exportDynamic =
       args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false) ||
       args.hasArg(OPT_shared);
-  ctx.arg.filterList = args::getStrings(args, OPT_filter);
+  ctx.arg.filterList.assign(args::getStrings(args, OPT_filter));
   ctx.arg.fini = args.getLastArgValue(OPT_fini, "_fini");
   ctx.arg.fixCortexA53Errata843419 =
       args.hasArg(OPT_fix_cortex_a53_843419) && !args.hasArg(OPT_relocatable);
@@ -1529,9 +1524,9 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.mmapOutputFile =
       args.hasFlag(OPT_mmap_output_file, OPT_no_mmap_output_file, false);
   ctx.arg.nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
-  ctx.arg.nostdlib = args.hasArg(OPT_nostdlib);
-  ctx.arg.oFormatBinary = isOutputFormatBinary(ctx, args);
-  ctx.arg.omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
+  ctx.arg.setNostdlib(args.hasArg(OPT_nostdlib));
+  ctx.arg.setOFormatBinary(isOutputFormatBinary(ctx, args));
+  ctx.arg.setOmagic(args.hasFlag(OPT_omagic, OPT_no_omagic, false));
   ctx.arg.optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
   ctx.arg.optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file);
 
@@ -1547,16 +1542,16 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   }
 
   ctx.arg.optRemarksPasses = args.getLastArgValue(OPT_opt_remarks_passes);
-  ctx.arg.optRemarksWithHotness = args.hasArg(OPT_opt_remarks_with_hotness);
+  ctx.arg.setOptRemarksWithHotness(args.hasArg(OPT_opt_remarks_with_hotness));
   ctx.arg.optRemarksFormat = args.getLastArgValue(OPT_opt_remarks_format);
   ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
   ctx.arg.orphanHandling = getOrphanHandling(ctx, args);
   ctx.arg.outputFile = args.getLastArgValue(OPT_o);
   if (auto *arg = args.getLastArg(OPT_package_metadata))
     parsePackageMetadata(ctx, *arg);
-  ctx.arg.pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
-  ctx.arg.printIcfSections =
-      args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
+  ctx.arg.setPie(args.hasFlag(OPT_pie, OPT_no_pie, false));
+  ctx.arg.setPrintIcfSections(
+      args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false));
   if (auto *arg =
           args.getLastArg(OPT_print_gc_sections, OPT_no_print_gc_sections,
                           OPT_print_gc_sections_eq)) {
@@ -1565,16 +1560,16 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
     else if (arg->getOption().matches(OPT_print_gc_sections_eq))
       ctx.arg.printGcSections = arg->getValue();
   }
-  ctx.arg.printMemoryUsage = args.hasArg(OPT_print_memory_usage);
+  ctx.arg.setPrintMemoryUsage(args.hasArg(OPT_print_memory_usage));
   ctx.arg.printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
   ctx.arg.printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order);
-  ctx.arg.rejectMismatch = !args.hasArg(OPT_no_warn_mismatch);
-  ctx.arg.relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
-  ctx.arg.relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false);
+  ctx.arg.setRejectMismatch(!args.hasArg(OPT_no_warn_mismatch));
+  ctx.arg.setRelax(args.hasFlag(OPT_relax, OPT_no_relax, true));
+  ctx.arg.setRelaxGP(args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false));
   ctx.arg.rpath = getRpath(args);
-  ctx.arg.relocatable = args.hasArg(OPT_relocatable);
-  ctx.arg.resolveGroups =
-      !args.hasArg(OPT_relocatable) || args.hasArg(OPT_force_group_allocation);
+  ctx.arg.setRelocatable(args.hasArg(OPT_relocatable));
+  ctx.arg.setResolveGroups(!args.hasArg(OPT_relocatable) ||
+                           args.hasArg(OPT_force_group_allocation));
 
   if (args.hasArg(OPT_save_temps)) {
     // --save-temps implies saving all temps.
@@ -1589,23 +1584,23 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
     }
   }
 
-  ctx.arg.searchPaths = args::getStrings(args, OPT_library_path);
+  ctx.arg.searchPaths.assign(args::getStrings(args, OPT_library_path));
   ctx.arg.sectionStartMap = getSectionStartMap(ctx, args);
-  ctx.arg.shared = args.hasArg(OPT_shared);
+  ctx.arg.setShared(args.hasArg(OPT_shared));
   if (args.hasArg(OPT_randomize_section_padding))
     ctx.arg.randomizeSectionPadding =
         args::getInteger(args, OPT_randomize_section_padding, 0);
-  ctx.arg.singleRoRx = !args.hasFlag(OPT_rosegment, OPT_no_rosegment, true);
-  ctx.arg.singleXoRx = !args.hasFlag(OPT_xosegment, OPT_no_xosegment, false);
+  ctx.arg.setSingleRoRx(!args.hasFlag(OPT_rosegment, OPT_no_rosegment, true));
+  ctx.arg.setSingleXoRx(!args.hasFlag(OPT_xosegment, OPT_no_xosegment, false));
   ctx.arg.soName = args.getLastArgValue(OPT_soname);
   ctx.arg.sortSection = getSortSection(ctx, args);
   ctx.arg.splitStackAdjustSize =
       args::getInteger(args, OPT_split_stack_adjust_size, 16384);
-  ctx.arg.zSectionHeader =
-      getZFlag(args, "sectionheader", "nosectionheader", true);
+  ctx.arg.setZSectionHeader(
+      getZFlag(args, "sectionheader", "nosectionheader", true));
   ctx.arg.strip = getStrip(ctx, args); // needs zSectionHeader
   ctx.arg.sysroot = args.getLastArgValue(OPT_sysroot);
-  ctx.arg.target1Rel = args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);
+  ctx.arg.setTarget1Rel(args.hasFlag(OPT_target1_rel, OPT_target1_abs, false));
   ctx.arg.target2 = getTarget2(ctx, args);
   ctx.arg.thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
   ctx.arg.thinLTOCachePolicy = CHECK(
@@ -1615,15 +1610,15 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.thinLTOEmitIndexFiles = args.hasArg(OPT_thinlto_emit_index_files) ||
                                   args.hasArg(OPT_thinlto_index_only) ||
                                   args.hasArg(OPT_thinlto_index_only_eq);
-  ctx.arg.thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||
-                             args.hasArg(OPT_thinlto_index_only_eq);
+  ctx.arg.setThinLTOIndexOnly(args.hasArg(OPT_thinlto_index_only) ||
+                              args.hasArg(OPT_thinlto_index_only_eq));
   ctx.arg.thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);
   ctx.arg.thinLTOObjectSuffixReplace =
       getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace_eq);
   std::tie(ctx.arg.thinLTOPrefixReplaceOld, ctx.arg.thinLTOPrefixReplaceNew,
            ctx.arg.thinLTOPrefixReplaceNativeObject) =
       getOldNewOptionsExtra(ctx, args, OPT_thinlto_prefix_replace_eq);
-  if (ctx.arg.thinLTOEmitIndexFiles && !ctx.arg.thinLTOIndexOnly) {
+  if (ctx.arg.thinLTOEmitIndexFiles && !ctx.arg.getThinLTOIndexOnly()) {
     if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))
       ErrAlways(ctx) << "--thinlto-object-suffix-replace is not supported with "
                         "--thinlto-emit-index-files";
@@ -1637,21 +1632,21 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
         << "--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
            "--thinlto-index-only=";
   }
-  ctx.arg.thinLTOModulesToCompile =
-      args::getStrings(args, OPT_thinlto_single_module_eq);
-  ctx.arg.timeTraceEnabled =
-      args.hasArg(OPT_time_trace_eq) && !ctx.e.disableOutput;
+  ctx.arg.thinLTOModulesToCompile.assign(
+      args::getStrings(args, OPT_thinlto_single_module_eq));
+  ctx.arg.setTimeTraceEnabled(args.hasArg(OPT_time_trace_eq) &&
+                              !ctx.e.disableOutput);
   ctx.arg.timeTraceGranularity =
       args::getInteger(args, OPT_time_trace_granularity, 500);
-  ctx.arg.trace = args.hasArg(OPT_trace);
-  ctx.arg.undefined = args::getStrings(args, OPT_undefined);
-  ctx.arg.undefinedVersion =
-      args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, false);
-  ctx.arg.unique = args.hasArg(OPT_unique);
-  ctx.arg.useAndroidRelrTags = args.hasFlag(
-      OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
-  ctx.arg.warnBackrefs =
-      args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
+  ctx.arg.setTrace(args.hasArg(OPT_trace));
+  ctx.arg.undefined.assign(args::getStrings(args, OPT_undefined));
+  ctx.arg.setUndefinedVersion(
+      args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, false));
+  ctx.arg.setUnique(args.hasArg(OPT_unique));
+  ctx.arg.setUseAndroidRelrTags(args.hasFlag(
+      OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false));
+  ctx.arg.setWarnBackrefs(
+      args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false));
   ctx.arg.warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
   ctx.arg.warnSymbolOrdering =
       args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
@@ -1667,52 +1662,52 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   }
   ctx.arg.zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   ctx.arg.zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
-  ctx.arg.zForceBti = hasZOption(args, "force-bti");
-  ctx.arg.zForceIbt = hasZOption(args, "force-ibt");
+  ctx.arg.setZForceBti(hasZOption(args, "force-bti"));
+  ctx.arg.setZForceIbt(hasZOption(args, "force-ibt"));
   ctx.arg.zZicfilp = getZZicfilp(ctx, args);
   ctx.arg.zZicfiss = getZZicfiss(ctx, args);
   ctx.arg.zGcs = getZGcs(ctx, args);
-  ctx.arg.zGlobal = hasZOption(args, "global");
+  ctx.arg.setZGlobal(hasZOption(args, "global"));
   ctx.arg.zGnustack = getZGnuStack(args);
-  ctx.arg.zHazardplt = hasZOption(args, "hazardplt");
-  ctx.arg.zIfuncNoplt = hasZOption(args, "ifunc-noplt");
-  ctx.arg.zInitfirst = hasZOption(args, "initfirst");
-  ctx.arg.zInterpose = hasZOption(args, "interpose");
-  ctx.arg.zKeepDataSectionPrefix = getZFlag(
-      args, "keep-data-section-prefix", "nokeep-data-section-prefix", false);
-  ctx.arg.zKeepTextSectionPrefix = getZFlag(
-      args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
-  ctx.arg.zLrodataAfterBss =
-      getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
-  ctx.arg.zMarkPlt = getZFlag(args, "mark-plt", "nomark-plt", false);
-  ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi");
-  ctx.arg.zNodefaultlib = hasZOption(args, "nodefaultlib");
-  ctx.arg.zNodelete = hasZOption(args, "nodelete");
-  ctx.arg.zNodlopen = hasZOption(args, "nodlopen");
-  ctx.arg.zNow = getZFlag(args, "now", "lazy", false);
-  ctx.arg.zOrigin = hasZOption(args, "origin");
-  ctx.arg.zPacPlt = getZFlag(args, "pac-plt", "nopac-plt", false);
-  ctx.arg.zRelro = getZFlag(args, "relro", "norelro", true);
-  ctx.arg.zRetpolineplt = hasZOption(args, "retpolineplt");
-  ctx.arg.zRodynamic = hasZOption(args, "rodynamic");
+  ctx.arg.setZHazardplt(hasZOption(args, "hazardplt"));
+  ctx.arg.setZIfuncNoplt(hasZOption(args, "ifunc-noplt"));
+  ctx.arg.setZInitfirst(hasZOption(args, "initfirst"));
+  ctx.arg.setZInterpose(hasZOption(args, "interpose"));
+  ctx.arg.setZKeepDataSectionPrefix(getZFlag(
+      args, "keep-data-section-prefix", "nokeep-data-section-prefix", false));
+  ctx.arg.setZKeepTextSectionPrefix(getZFlag(
+      args, "keep-text-section-prefix", "nokeep-text-section-prefix", false));
+  ctx.arg.setZLrodataAfterBss(
+      getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false));
+  ctx.arg.setZMarkPlt(getZFlag(args, "mark-plt", "nomark-plt", false));
+  ctx.arg.setZNoBtCfi(hasZOption(args, "nobtcfi"));
+  ctx.arg.setZNodefaultlib(hasZOption(args, "nodefaultlib"));
+  ctx.arg.setZNodelete(hasZOption(args, "nodelete"));
+  ctx.arg.setZNodlopen(hasZOption(args, "nodlopen"));
+  ctx.arg.setZNow(getZFlag(args, "now", "lazy", false));
+  ctx.arg.setZOrigin(hasZOption(args, "origin"));
+  ctx.arg.setZPacPlt(getZFlag(args, "pac-plt", "nopac-plt", false));
+  ctx.arg.setZRelro(getZFlag(args, "relro", "norelro", true));
+  ctx.arg.setZRetpolineplt(hasZOption(args, "retpolineplt"));
+  ctx.arg.setZRodynamic(hasZOption(args, "rodynamic"));
   ctx.arg.zSeparate = getZSeparate(args);
-  ctx.arg.zShstk = hasZOption(args, "shstk");
+  ctx.arg.setZShstk(hasZOption(args, "shstk"));
   ctx.arg.zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0);
-  ctx.arg.zStartStopGC =
-      getZFlag(args, "start-stop-gc", "nostart-stop-gc", true);
+  ctx.arg.setZStartStopGC(
+      getZFlag(args, "start-stop-gc", "nostart-stop-gc", true));
   ctx.arg.zStartStopVisibility = getZStartStopVisibility(ctx, args);
-  ctx.arg.zText = getZFlag(args, "text", "notext", true);
-  ctx.arg.zWxneeded = hasZOption(args, "wxneeded");
+  ctx.arg.setZText(getZFlag(args, "text", "notext", true));
+  ctx.arg.setZWxneeded(hasZOption(args, "wxneeded"));
   setUnresolvedSymbolPolicy(ctx, args);
-  ctx.arg.power10Stubs = args.getLastArgValue(OPT_power10_stubs_eq) != "no";
-  ctx.arg.branchToBranch = args.hasFlag(
-      OPT_branch_to_branch, OPT_no_branch_to_branch, ctx.arg.optimize >= 2);
+  ctx.arg.setPower10Stubs(args.getLastArgValue(OPT_power10_stubs_eq) != "no");
+  ctx.arg.setBranchToBranch(args.hasFlag(
+      OPT_branch_to_branch, OPT_no_branch_to_branch, ctx.arg.optimize >= 2));
 
   if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
     if (arg->getOption().matches(OPT_eb))
-      ctx.arg.optEB = true;
+      ctx.arg.setOptEB(true);
     else
-      ctx.arg.optEL = true;
+      ctx.arg.setOptEL(true);
   }
 
   for (opt::Arg *arg : args.filtered(OPT_remap_inputs)) {
@@ -1749,7 +1744,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
       ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first;
   }
 
-  if (ctx.arg.zForceBti) {
+  if (ctx.arg.getZForceBti()) {
     ctx.arg.zBtiReport = ReportPolicy::Warning;
     ctx.arg.zBtiReportSource = "-z force-bti";
   }
@@ -1873,7 +1868,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
                      << arg->getValue() << "'";
   }
 
-  ctx.arg.passPlugins = args::getStrings(args, OPT_load_pass_plugins);
+  ctx.arg.passPlugins.assign(args::getStrings(args, OPT_load_pass_plugins));
 
   // Parse -mllvm options.
   for (const auto *arg : args.filtered(OPT_mllvm)) {
@@ -1947,11 +1942,11 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   if (auto *arg = args.getLastArg(OPT_hash_style)) {
     StringRef s = arg->getValue();
     if (s == "sysv")
-      ctx.arg.sysvHash = true;
+      ctx.arg.setSysvHash(true);
     else if (s == "gnu")
       ctx.arg.gnuHash = true;
     else if (s == "both")
-      ctx.arg.sysvHash = ctx.arg.gnuHash = true;
+      ctx.arg.setSysvHash(ctx.arg.gnuHash = true);
     else
       ErrAlways(ctx) << "unknown --hash-style: " << s;
   }
@@ -1962,13 +1957,13 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   // Page alignment can be disabled by the -n (--nmagic) and -N (--omagic).
   // As PT_GNU_RELRO relies on Paging, do not create it when we have disabled
   // it. Also disable RELRO for -r.
-  if (ctx.arg.nmagic || ctx.arg.omagic || ctx.arg.relocatable)
-    ctx.arg.zRelro = false;
+  if (ctx.arg.nmagic || ctx.arg.getOmagic() || ctx.arg.getRelocatable())
+    ctx.arg.setZRelro(false);
 
   std::tie(ctx.arg.buildId, ctx.arg.buildIdVector) = getBuildId(ctx, args);
 
   if (getZFlag(args, "pack-relative-relocs", "nopack-relative-relocs", false)) {
-    ctx.arg.relrGlibc = true;
+    ctx.arg.setRelrGlibc(true);
     ctx.arg.relrPackDynRelocs = true;
   } else {
     std::tie(ctx.arg.androidPackDynRelocs, ctx.arg.relrPackDynRelocs) =
@@ -2019,8 +2014,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   // --export-dynamic-symbol-list specifies a list of --export-dynamic-symbol
   // patterns. --dynamic-list is --export-dynamic-symbol-list plus -Bsymbolic
   // like semantics.
-  ctx.arg.symbolic =
-      ctx.arg.bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list);
+  ctx.arg.setSymbolic(ctx.arg.bsymbolic == BsymbolicKind::All ||
+                      args.hasArg(OPT_dynamic_list));
   for (auto *arg :
        args.filtered(OPT_dynamic_list, OPT_export_dynamic_symbol_list))
     if (std::optional<MemoryBufferRef> buffer = readFile(ctx, arg->getValue()))
@@ -2043,14 +2038,14 @@ static void setConfigs(Ctx &ctx, opt::InputArgList &args) {
   ELFKind k = ctx.arg.ekind;
   uint16_t m = ctx.arg.emachine;
 
-  ctx.arg.copyRelocs = (ctx.arg.relocatable || ctx.arg.emitRelocs);
-  ctx.arg.is64 = (k == ELF64LEKind || k == ELF64BEKind);
-  ctx.arg.isLE = (k == ELF32LEKind || k == ELF64LEKind);
-  ctx.arg.endianness = ctx.arg.isLE ? endianness::little : endianness::big;
-  ctx.arg.isMips64EL = (k == ELF64LEKind && m == EM_MIPS);
-  ctx.arg.isPic = ctx.arg.pie || ctx.arg.shared;
-  ctx.arg.picThunk = args.hasArg(OPT_pic_veneer, ctx.arg.isPic);
-  ctx.arg.wordsize = ctx.arg.is64 ? 8 : 4;
+  ctx.arg.setCopyRelocs((ctx.arg.getRelocatable() || ctx.arg.emitRelocs));
+  ctx.arg.setIs64((k == ELF64LEKind || k == ELF64BEKind));
+  ctx.arg.setIsLE((k == ELF32LEKind || k == ELF64LEKind));
+  ctx.arg.endianness = ctx.arg.getIsLE() ? endianness::little : endianness::big;
+  ctx.arg.setIsMips64EL((k == ELF64LEKind && m == EM_MIPS));
+  ctx.arg.setIsPic(ctx.arg.getPie() || ctx.arg.getShared());
+  ctx.arg.setPicThunk(args.hasArg(OPT_pic_veneer, ctx.arg.getIsPic()));
+  ctx.arg.wordsize = ctx.arg.getIs64() ? 8 : 4;
 
   // ELF defines two different ways to store relocation addends as shown below:
   //
@@ -2066,7 +2061,7 @@ static void setConfigs(Ctx &ctx, opt::InputArgList &args) {
   // We pick the format for dynamic relocations according to the psABI for each
   // processor, but a contrary choice can be made if the dynamic loader
   // supports.
-  ctx.arg.isRela = getIsRela(ctx, args);
+  ctx.arg.setIsRela(getIsRela(ctx, args));
 
   // If the output uses REL relocations we must store the dynamic relocation
   // addends to the output sections. We also store addends for RELA relocations
@@ -2075,7 +2070,7 @@ static void setConfigs(Ctx &ctx, opt::InputArgList &args) {
   // any standard conforming tool can find it in r_addend.
   ctx.arg.writeAddends = args.hasFlag(OPT_apply_dynamic_relocs,
                                       OPT_no_apply_dynamic_relocs, false) ||
-                         !ctx.arg.isRela;
+                         !ctx.arg.getIsRela();
   // Validation of dynamic relocation addends is on by default for assertions
   // builds and disabled otherwise. This check is enabled when writeAddends is
   // true.
@@ -2084,26 +2079,27 @@ static void setConfigs(Ctx &ctx, opt::InputArgList &args) {
 #else
   bool checkDynamicRelocsDefault = false;
 #endif
-  ctx.arg.checkDynamicRelocs =
-      args.hasFlag(OPT_check_dynamic_relocations,
-                   OPT_no_check_dynamic_relocations, checkDynamicRelocsDefault);
-  ctx.arg.tocOptimize =
-      args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64);
-  ctx.arg.pcRelOptimize =
-      args.hasFlag(OPT_pcrel_optimize, OPT_no_pcrel_optimize, m == EM_PPC64);
+  ctx.arg.setCheckDynamicRelocs(args.hasFlag(OPT_check_dynamic_relocations,
+                                             OPT_no_check_dynamic_relocations,
+                                             checkDynamicRelocsDefault));
+  ctx.arg.setTocOptimize(
+      args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64));
+  ctx.arg.setPcRelOptimize(
+      args.hasFlag(OPT_pcrel_optimize, OPT_no_pcrel_optimize, m == EM_PPC64));
 
   if (!args.hasArg(OPT_hash_style)) {
     if (ctx.arg.emachine == EM_MIPS)
-      ctx.arg.sysvHash = true;
+      ctx.arg.setSysvHash(true);
     else
-      ctx.arg.sysvHash = ctx.arg.gnuHash = true;
+      ctx.arg.setSysvHash(ctx.arg.gnuHash = true);
   }
 
   // Set default entry point and output file if not specified by command line or
   // linker scripts.
   ctx.arg.warnMissingEntry =
-      (!ctx.arg.entry.empty() || (!ctx.arg.shared && !ctx.arg.relocatable));
-  if (ctx.arg.entry.empty() && !ctx.arg.relocatable)
+      (!ctx.arg.entry.empty() ||
+       (!ctx.arg.getShared() && !ctx.arg.getRelocatable()));
+  if (ctx.arg.entry.empty() && !ctx.arg.getRelocatable())
     ctx.arg.entry = ctx.arg.emachine == EM_MIPS ? "__start" : "_start";
   if (ctx.arg.outputFile.empty())
     ctx.arg.outputFile = "a.out";
@@ -2159,7 +2155,7 @@ void LinkerDriver::loadFiles() {
                                    job.kind == LoadJob::Bitcode
                                        ? file_magic::bitcode
                                        : file_magic::elf_relocatable,
-                                   "", 0, job.lazy));
+                                   "", 0, job.getLazy()));
         break;
       case LoadJob::Archive: {
         // Scan all archive members rather than using the archive symbol
@@ -2169,11 +2165,11 @@ void LinkerDriver::loadFiles() {
         // --warn-backrefs.
         auto members = getArchiveMembers(ctx, job);
         job.out.reserve(members.size());
-        bool lazy = !job.inWholeArchive;
+        bool lazy = !job.getInWholeArchive();
         for (const auto &[mb, offset] : members) {
           auto mm = identify_magic(mb.getBuffer());
           if (mm == file_magic::elf_relocatable || mm == file_magic::bitcode ||
-              job.inWholeArchive)
+              job.getInWholeArchive())
             job.out.push_back(makeFile(mb, mm, job.path, offset, lazy));
           else
             Warn(ctx) << job.path << ": archive member '"
@@ -2189,9 +2185,9 @@ void LinkerDriver::loadFiles() {
         StringRef bufPath = job.mbref.getBufferIdentifier();
         auto f = std::make_unique<SharedFile>(
             ctx, job.mbref,
-            job.withLOption ? path::filename(bufPath) : bufPath);
+            job.getWithLOption() ? path::filename(bufPath) : bufPath);
         f->init();
-        f->isNeeded = !job.asNeeded;
+        f->isNeeded = !job.getAsNeeded();
         job.out.push_back(std::move(f));
         break;
       }
@@ -2229,7 +2225,7 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
   std::vector<std::tuple<bool, bool, bool>> stack;
 
   // -r implies -Bstatic and has precedence over -Bdynamic.
-  ctx.arg.isStatic = ctx.arg.relocatable;
+  ctx.arg.isStatic = ctx.arg.getRelocatable();
 
   // Iterate over argv to process input files and positional arguments.
   std::optional<MemoryBufferRef> defaultScript;
@@ -2281,7 +2277,7 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
       ctx.arg.isStatic = true;
       break;
     case OPT_Bdynamic:
-      if (!ctx.arg.relocatable)
+      if (!ctx.arg.getRelocatable())
         ctx.arg.isStatic = false;
       break;
     case OPT_whole_archive:
@@ -2293,7 +2289,7 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
     case OPT_just_symbols:
       if (std::optional<MemoryBufferRef> mb = readFile(ctx, arg->getValue())) {
         files.push_back(createObjFile(ctx, *mb));
-        files.back()->justSymbols = true;
+        files.back()->setJustSymbols(true);
       }
       break;
     case OPT_in_implib:
@@ -2384,7 +2380,7 @@ static uint64_t getMaxPageSize(Ctx &ctx, opt::InputArgList &args) {
     ErrAlways(ctx) << "max-page-size: value isn't a power of 2";
     return ctx.target->defaultMaxPageSize;
   }
-  if (ctx.arg.nmagic || ctx.arg.omagic) {
+  if (ctx.arg.nmagic || ctx.arg.getOmagic()) {
     if (val != ctx.target->defaultMaxPageSize)
       Warn(ctx)
           << "-z max-page-size set, but paging disabled by omagic or nmagic";
@@ -2402,7 +2398,7 @@ static uint64_t getCommonPageSize(Ctx &ctx, opt::InputArgList &args) {
     ErrAlways(ctx) << "common-page-size: value isn't a power of 2";
     return ctx.target->defaultCommonPageSize;
   }
-  if (ctx.arg.nmagic || ctx.arg.omagic) {
+  if (ctx.arg.nmagic || ctx.arg.getOmagic()) {
     if (val != ctx.target->defaultCommonPageSize)
       Warn(ctx)
           << "-z common-page-size set, but paging disabled by omagic or nmagic";
@@ -2833,7 +2829,7 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
 
     // For defined symbols in non-relocatable output,
     // compute isExported and parse '@'.
-    if (!ctx.arg.relocatable)
+    if (!ctx.arg.getRelocatable())
       for (Symbol *sym : obj->getGlobalSymbols()) {
         if (!sym->isDefined())
           continue;
@@ -3109,9 +3105,10 @@ static void readSecurityNotes(Ctx &ctx) {
                      "GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED";
     }
 
-    if (ctx.arg.zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
+    if (ctx.arg.getZForceBti() &&
+        !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
       features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
-    } else if (ctx.arg.zForceIbt &&
+    } else if (ctx.arg.getZForceIbt() &&
                !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
       if (ctx.arg.zCetReport == ReportPolicy::None)
         Warn(ctx) << f
@@ -3119,8 +3116,9 @@ static void readSecurityNotes(Ctx &ctx) {
                      "GNU_PROPERTY_X86_FEATURE_1_IBT property";
       features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
     }
-    if (ctx.arg.zPacPlt && !(hasValidPauthAbiCoreInfo ||
-                             (features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC))) {
+    if (ctx.arg.getZPacPlt() &&
+        !(hasValidPauthAbiCoreInfo ||
+          (features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC))) {
       Warn(ctx) << f
                 << ": -z pac-plt: file does not have "
                    "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property and no valid "
@@ -3160,7 +3158,7 @@ static void readSecurityNotes(Ctx &ctx) {
   }
 
   // Force enable Shadow Stack.
-  if (ctx.arg.zShstk)
+  if (ctx.arg.getZShstk())
     ctx.arg.andFeatures |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
 
   // Force enable/disable GCS
@@ -3255,8 +3253,8 @@ static void linkDynamicDebug(Ctx &ctx, ArrayRef<WrappedSymbol> wrapped) {
   dctx.e.initialize(ctx.e.outs(), ctx.e.errs(), ctx.e.exitEarly,
                     ctx.e.disableOutput);
   initContext(dctx, script, ctx.arg.progName);
-  dctx.inDynDbgLink = true;
-  dctx.dynDbgRelocatable = !ctx.arg.relocatable;
+  dctx.setInDynDbgLink(true);
+  dctx.setDynDbgRelocatable(!ctx.arg.getRelocatable());
 
   for (auto *file : ctx.objectFiles) {
     auto *obj = cast<ObjFile<ELFT>>(file);
@@ -3274,7 +3272,7 @@ static void linkDynamicDebug(Ctx &ctx, ArrayRef<WrappedSymbol> wrapped) {
   std::vector<const char *> args{
       dctx.arg.progName.data(), "-r", "-o", "-",
       saveArg(Twine("-O") + Twine(ctx.arg.optimize))};
-  if (ctx.arg.resolveGroups)
+  if (ctx.arg.getResolveGroups())
     args.push_back("--force-group-allocation");
   for (const auto &ws : wrapped)
     args.push_back(saveArg(Twine("--wrap=") + ws.sym->getName()));
@@ -3308,22 +3306,22 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
 
   // ICF is incompatible with dynamic debugging: the inner ELF references outer
   // symbols that folding would merge away.
-  if (ctx.hasDynDbg && ctx.arg.icf != ICFLevel::None) {
+  if (ctx.getHasDynDbg() && ctx.arg.icf != ICFLevel::None) {
     Warn(ctx) << "ICF disabled because it is incompatible with dynamic "
                  "debugging";
     ctx.arg.icf = ICFLevel::None;
   }
 
   // Create dynamic sections for dynamic linking and static PIE.
-  ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic;
-  ctx.arg.exportDynamic &= ctx.hasDynsym;
+  ctx.setHasDynsym(!ctx.sharedFiles.empty() || ctx.arg.getIsPic());
+  ctx.arg.exportDynamic &= ctx.getHasDynsym();
 
   // Preemptibility of undefined symbols when ctx.hasDynsym is true. Default is
   // true for dynamic linking.
   ctx.arg.zDynamicUndefined =
       getZFlag(args, "dynamic-undefined-weak", "nodynamic-undefined-weak",
-               ctx.sharedFiles.size() || ctx.arg.shared) &&
-      ctx.hasDynsym;
+               ctx.sharedFiles.size() || ctx.arg.getShared()) &&
+      ctx.getHasDynsym();
 
   // If an entry symbol is in a static archive, pull out that file now.
   if (Symbol *sym = ctx.symtab->find(ctx.arg.entry))
@@ -3417,7 +3415,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   ctx.out.elfHeader = std::make_unique<OutputSection>(ctx, "", 0, SHF_ALLOC);
 
   // We need to create some reserved symbols such as _end. Create them.
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     addReservedSymbols(ctx);
 
   // Apply version scripts.
@@ -3425,7 +3423,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // For a relocatable output, version scripts don't make sense, and
   // parsing a symbol version string (e.g. dropping "@ver1" from a symbol
   // name "foo at ver1") rather do harm, so we don't call this if -r is given.
-  if (!ctx.arg.relocatable) {
+  if (!ctx.arg.getRelocatable()) {
     llvm::TimeTraceScope timeScope("Process symbol versions");
     ctx.symtab->scanVersionScript();
 
@@ -3439,8 +3437,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // --plugin-opt=emit-asm create output files in bitcode or assembly code,
   // respectively. When only certain thinLTO modules are specified for
   // compilation, the intermediate object file are the expected output.
-  const bool skipLinkedOutput = ctx.arg.thinLTOIndexOnly || ctx.arg.emitLLVM ||
-                                ctx.arg.ltoEmitAsm ||
+  const bool skipLinkedOutput = ctx.arg.getThinLTOIndexOnly() ||
+                                ctx.arg.emitLLVM || ctx.arg.ltoEmitAsm ||
                                 !ctx.arg.thinLTOModulesToCompile.empty();
 
   // Handle --lto-validate-all-vtables-have-type-infos.
@@ -3574,7 +3572,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   ctx.arg.imageBase = getImageBase(ctx, args);
 
   // This adds a .comment section containing a version string.
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     ctx.inputSections.push_back(createCommentSection(ctx));
 
   // Split SHF_MERGE and .eh_frame sections into pieces in preparation for garbage collection.
@@ -3588,7 +3586,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
     createTaggedSymbols(ctx);
   }
 
-  if (ctx.hasDynDbg) {
+  if (ctx.getHasDynDbg()) {
     llvm::TimeTraceScope timeScope("Link dynamic debugging");
     linkDynamicDebug<ELFT>(ctx, wrapped);
     if (errCount(ctx))
@@ -3602,7 +3600,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // Some input sections that are used for exception handling need to be moved
   // into synthetic sections. Do that now so that they aren't assigned to
   // output sections in the usual way.
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     combineEhSections(ctx);
 
   // Merge .hexagon.attributes sections.
diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index 62c42bdbb550d..038004650b89b 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -243,7 +243,8 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
   auto rai = ra.begin(), rae = ra.end(), rbi = rb.begin();
   for (; rai != rae; ++rai, ++rbi) {
     if (rai->r_offset != rbi->r_offset ||
-        rai->getType(ctx.arg.isMips64EL) != rbi->getType(ctx.arg.isMips64EL))
+        rai->getType(ctx.arg.getIsMips64EL()) !=
+            rbi->getType(ctx.arg.getIsMips64EL()))
       return false;
 
     uint64_t addA = getAddend<ELFT>(*rai);
@@ -540,7 +541,8 @@ template <class ELFT> void ICF<ELFT>::run() {
   Log(ctx) << "ICF needed " << cnt << " iterations";
 
   auto print = [&ctx = ctx]() -> ELFSyncStream {
-    return {ctx, ctx.arg.printIcfSections ? DiagLevel::Msg : DiagLevel::None};
+    return {ctx,
+            ctx.arg.getPrintIcfSections() ? DiagLevel::Msg : DiagLevel::None};
   };
   // Merge sections by the equivalence class.
   forEachClassRange(0, sections.size(), [&](size_t begin, size_t end) {
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index a1f921a875605..def63076a8a42 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -193,7 +193,7 @@ static void updateSupportedARMFeatures(Ctx &ctx,
     return;
   if (arch >= ARMBuildAttrs::CPUArch::v8_M_Base &&
       profile == ARMBuildAttrs::MicroControllerProfile)
-    ctx.arg.armCMSESupport = true;
+    ctx.arg.setArmCMSESupport(true);
 
   // The thumb PLT entries require Thumb2 which can be used on multiple archs.
   // For now, let's limit it to ones where ARM isn't available and we know have
@@ -300,7 +300,7 @@ template <class ELFT> static void doParseFile(Ctx &ctx, InputFile *file) {
     return;
 
   // Lazy object file
-  if (file->lazy) {
+  if (file->getLazy()) {
     if (auto *f = dyn_cast<BitcodeFile>(file)) {
       ctx.lazyBitcodeFiles.push_back(f);
       f->parseLazy();
@@ -310,7 +310,7 @@ template <class ELFT> static void doParseFile(Ctx &ctx, InputFile *file) {
     return;
   }
 
-  if (ctx.arg.trace)
+  if (ctx.arg.getTrace())
     Msg(ctx) << file;
 
   if (file->kind() == InputFile::ObjKind) {
@@ -574,7 +574,7 @@ handleAArch64BAAndGnuProperties(ObjFile<ELFT> *file, Ctx &ctx,
 template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
   object::ELFFile<ELFT> obj = this->getObj();
   // Read a section table. justSymbols is usually false.
-  if (this->justSymbols) {
+  if (this->getJustSymbols()) {
     initializeJustSymbols();
     initializeSymbols(obj);
     return;
@@ -608,7 +608,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
                            .second;
       if (keepGroup) {
         keptGroups.push_back(i);
-        if (!ctx.arg.resolveGroups)
+        if (!ctx.arg.getResolveGroups())
           sections[i] = createInputSection(
               i, sec, check(obj.getSectionName(sec, shstrtab)));
       } else {
@@ -623,7 +623,8 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
       continue;
     }
 
-    if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES && !ctx.arg.relocatable) {
+    if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES &&
+        !ctx.arg.getRelocatable()) {
       StringRef name = check(obj.getSectionName(sec, shstrtab));
       ArrayRef<char> data = CHECK2(
           this->getObj().template getSectionContentsAsArray<char>(sec), this);
@@ -647,7 +648,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
       if (check(obj.getSectionName(sec, shstrtab)) == dynDbgSecName) {
         sections[i] = &InputSection::discarded;
         dynDbgSec = std::make_unique<InputSection>(*this, sec, dynDbgSecName);
-        ctx.hasDynDbg = true;
+        ctx.setHasDynDbg(true);
       }
       continue;
     }
@@ -724,7 +725,7 @@ bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &sec, StringRef name) {
   // SHF_MERGE sections based both on their name and sh_entsize, but that seems
   // to be more trouble than it is worth. Instead, we just use the regular (-O1)
   // logic for -r.
-  if (ctx.arg.optimize == 0 && !ctx.arg.relocatable)
+  if (ctx.arg.optimize == 0 && !ctx.arg.getRelocatable())
     return false;
 
   // A mergeable section with size 0 is useless because they don't have
@@ -795,7 +796,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     // SHF_EXCLUDE'ed sections are discarded by the linker. However,
     // if -r is given, we'll let the final link discard such sections.
     // This is compatible with GNU.
-    if ((sec.sh_flags & SHF_EXCLUDE) && !ctx.arg.relocatable) {
+    if ((sec.sh_flags & SHF_EXCLUDE) && !ctx.arg.getRelocatable()) {
       if (type == SHT_LLVM_CALL_GRAPH_PROFILE)
         cgProfileSectionIndex = i;
       if (type == SHT_LLVM_ADDRSIG) {
@@ -839,7 +840,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     }
     switch (type) {
     case SHT_GROUP: {
-      if (!ctx.arg.relocatable)
+      if (!ctx.arg.getRelocatable())
         sections[i] = &InputSection::discarded;
       // Use the verdict parse() recorded for this group instead of repeating
       // the signature hashing and comdatGroups lookup.
@@ -874,7 +875,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
       // The concatenated output does not properly reflect the linking
       // semantics. In addition, since we do not use the bitcode wrapper format,
       // the concatenated raw bitcode would be invalid.
-      if (ctx.arg.relocatable && !ctx.arg.fatLTOObjects) {
+      if (ctx.arg.getRelocatable() && !ctx.arg.fatLTOObjects) {
         sections[i] = &InputSection::discarded;
         break;
       }
@@ -882,7 +883,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     default:
       this->sections[i] =
           createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
-      if (ctx.arg.rejectMismatch &&
+      if (ctx.arg.getRejectMismatch() &&
           !isKnownSpecificSectionType(type, sec.sh_flags))
         Err(ctx) << this->sections[i] << ": unknown section type 0x"
                  << Twine::utohexstr(type);
@@ -935,7 +936,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
       // `nullptr` for the normal case. However, if -r or --emit-relocs is
       // specified, we need to copy them to the output. (Some post link analysis
       // tools specify --emit-relocs to obtain the information.)
-      if (ctx.arg.copyRelocs) {
+      if (ctx.arg.getCopyRelocs()) {
         auto *isec = makeThreadLocal<InputSection>(
             *this, sec, check(obj.getSectionName(sec, shstrtab)));
         // If the relocated section is discarded (due to /DISCARD/ or
@@ -978,7 +979,8 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     handleAArch64BAAndGnuProperties<ELFT>(this, ctx, aarch64BAsubSections);
 
   for (ArrayRef<Elf_Word> entries : selectedGroups)
-    handleSectionGroup<ELFT>(this->sections, entries);
+    handleSectionGroup<ELFT>(ArrayRef<InputSectionBase *>(this->sections),
+                             entries);
 }
 
 template <typename ELFT>
@@ -1133,7 +1135,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
     // an error if we encounter an executable .note.GNU-stack to force the
     // user to explicitly request an executable stack.
     if (name == ".note.GNU-stack") {
-      if ((sec.sh_flags & SHF_EXECINSTR) && !ctx.arg.relocatable &&
+      if ((sec.sh_flags & SHF_EXECINSTR) && !ctx.arg.getRelocatable() &&
           ctx.arg.zGnustack != GnuStackKind::Exec) {
         Err(ctx) << this
                  << ": requires an executable stack, but -z execstack is not "
@@ -1160,12 +1162,12 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
     // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
     // for split stack will include a .note.GNU-split-stack section.
     if (name == ".note.GNU-split-stack") {
-      if (ctx.arg.relocatable) {
+      if (ctx.arg.getRelocatable()) {
         ErrAlways(ctx) << "cannot mix split-stack and non-split-stack in a "
                           "relocatable link";
         return &InputSection::discarded;
       }
-      this->splitStack = true;
+      this->setSplitStack(true);
       return &InputSection::discarded;
     }
 
@@ -1173,7 +1175,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
     // functions were compiled with the no_split_stack_attribute will
     // include a .note.GNU-no-split-stack section.
     if (name == ".note.GNU-no-split-stack") {
-      this->someNoSplitStack = true;
+      this->setSomeNoSplitStack(true);
       return &InputSection::discarded;
     }
 
@@ -1189,7 +1191,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
   // The linker merges EH (exception handling) frames and creates a
   // .eh_frame_hdr section for runtime. So we handle them with a special
   // class. For relocatable outputs, they are just passed through.
-  if (name == ".eh_frame" && !ctx.arg.relocatable)
+  if (name == ".eh_frame" && !ctx.arg.getRelocatable())
     return makeThreadLocal<EhInputSection>(*this, sec, name);
 
   if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name))
@@ -1301,10 +1303,10 @@ template <class ELFT> void ObjFile<ELFT>::initDynDbgSymbols() {
         setSymUsed(r.getSymbol(false));
     } else if (sh.sh_type == SHT_RELA) {
       for (const Elf_Rela &r : CHECK2(obj.relas(sh), &dbgObj))
-        setSymUsed(r.getSymbol(ctx.arg.isMips64EL));
+        setSymUsed(r.getSymbol(ctx.arg.getIsMips64EL()));
     } else {
       for (const Elf_Rel &r : CHECK2(obj.rels(sh), &dbgObj))
-        setSymUsed(r.getSymbol(ctx.arg.isMips64EL));
+        setSymUsed(r.getSymbol(ctx.arg.getIsMips64EL()));
     }
   }
 
@@ -1327,7 +1329,7 @@ template <class ELFT> void ObjFile<ELFT>::initDynDbgSymbols() {
 
 template <class ELFT>
 void ObjFile<ELFT>::initSectionsAndLocalSyms(bool ignoreComdats) {
-  if (!justSymbols)
+  if (!getJustSymbols())
     initializeSections(ignoreComdats, getObj());
 
   if (!firstGlobal)
@@ -1822,10 +1824,10 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName,
                          uint64_t offsetInArchive, bool lazy)
     : InputFile(ctx, BitcodeKind, mb) {
   this->archiveName = archiveName;
-  this->lazy = lazy;
+  this->setLazy(lazy);
 
   std::string path = mb.getBufferIdentifier().str();
-  if (ctx.arg.thinLTOIndexOnly)
+  if (ctx.arg.getThinLTOIndexOnly())
     path = replaceThinLTOSuffix(ctx, mb.getBufferIdentifier());
 
   // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
@@ -2017,7 +2019,10 @@ std::unique_ptr<ELFFileBase> elf::createObjFile(Ctx &ctx, MemoryBufferRef mb,
     llvm_unreachable("getELFKind");
   }
   f->init();
-  f->lazy = lazy;
+  [&] {
+    auto PackedFlagValue_ = lazy;
+    return f->setLazy(PackedFlagValue_);
+  }();
   return f;
 }
 
@@ -2035,7 +2040,7 @@ template <class ELFT> void ObjFile<ELFT>::parseLazy() {
       continue;
     symbols[i] = symtab->insert(CHECK2(eSyms[i].getName(stringTable), this));
     symbols[i]->resolve(ctx, LazySymbol{*this});
-    if (!lazy)
+    if (!getLazy())
       break;
   }
 }
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 5c4e060e2331b..d20c29715f66c 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -15,6 +15,7 @@
 #include "lld/Common/LLVM.h"
 #include "lld/Common/Reproduce.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/MemoryBufferRef.h"
@@ -54,7 +55,7 @@ class InputFile {
 protected:
   std::unique_ptr<Symbol *[]> symbols;
   size_t numSymbols = 0;
-  SmallVector<InputSectionBase *, 0> sections;
+  llvm::SmallVectorWithFlags<InputSectionBase *, 0, 3> sections;
 
 public:
   enum Kind : uint8_t {
@@ -108,7 +109,7 @@ class InputFile {
   }
 
   template <typename RelT> Symbol &getRelocTargetSym(const RelT &rel) const {
-    uint32_t symIndex = rel.getSymbol(ctx.arg.isMips64EL);
+    uint32_t symIndex = rel.getSymbol(ctx.arg.getIsMips64EL());
     return getSymbol(symIndex);
   }
 
@@ -138,10 +139,12 @@ class InputFile {
 
   // True if this is a relocatable object file/bitcode file in an ar archive
   // or between --start-lib and --end-lib.
-  bool lazy = false;
+  bool getLazy() const { return sections.getFlag(0); }
+  void setLazy(bool Value) { sections.setFlag(0, Value); }
 
   // True if this is an argument for --just-symbols. Usually false.
-  bool justSymbols = false;
+  bool getJustSymbols() const { return sections.getFlag(1); }
+  void setJustSymbols(bool Value) { sections.setFlag(1, Value); }
 
   // On PPC64 we need to keep track of which files contain small code model
   // relocations that access the .toc section. To minimize the chance of a
@@ -152,7 +155,11 @@ class InputFile {
   // code model relocations support immediates in the range [-0x8000, 0x7FFC],
   // making the addressable range relative to the toc pointer
   // [.got, .got + 0xFFFC].
-  bool ppc64SmallCodeModelTocRelocs = false;
+  bool getPpc64SmallCodeModelTocRelocs() const { return sections.getFlag(2); }
+  bool setPpc64SmallCodeModelTocRelocs(bool Value) {
+    sections.setFlag(2, Value);
+    return Value;
+  }
 
 public:
   // If not empty, this stores the name of the archive containing this file.
@@ -277,11 +284,13 @@ template <class ELFT> class ObjFile : public ELFFileBase {
 
   // True if the file defines functions compiled with
   // -fsplit-stack. Usually false.
-  bool splitStack = false;
+  bool getSplitStack() const { return keptGroups.getFlag(0); }
+  void setSplitStack(bool Value) { keptGroups.setFlag(0, Value); }
 
   // True if the file defines functions compiled with -fsplit-stack,
   // but had one or more functions with the no_split_stack attribute.
-  bool someNoSplitStack = false;
+  bool getSomeNoSplitStack() const { return keptGroups.getFlag(1); }
+  void setSomeNoSplitStack(bool Value) { keptGroups.setFlag(1, Value); }
 
   void initDwarf();
 
@@ -318,7 +327,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
 
   // Section indices of kept SHT_GROUP sections, recorded by parse() in
   // ascending order, to be used by the parallel initializeSections().
-  SmallVector<uint32_t, 0> keptGroups;
+  llvm::SmallVectorWithFlags<uint32_t, 0, 2> keptGroups;
 };
 
 class BitcodeFile : public InputFile {
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 13baaa5b8c2ad..0184d57e3931a 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -89,7 +89,7 @@ InputSectionBase::InputSectionBase(InputFile *file, StringRef name,
 // --force-group-allocation, the SHF_GROUP flag and section groups are retained.
 static uint64_t getFlags(Ctx &ctx, uint64_t flags) {
   flags &= ~(uint64_t)SHF_INFO_LINK;
-  if (ctx.arg.resolveGroups)
+  if (ctx.arg.getResolveGroups())
     flags &= ~(uint64_t)SHF_GROUP;
   return flags;
 }
@@ -437,9 +437,10 @@ InputSectionBase *InputSection::getRelocatedSection() const {
 
 template <class ELFT, class RelTy>
 void InputSection::copyRelocations(Ctx &ctx, uint8_t *buf) {
-  bool linkerRelax =
-      ctx.arg.relax && is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine);
-  if (!ctx.arg.relocatable && (linkerRelax || ctx.arg.branchToBranch)) {
+  bool linkerRelax = ctx.arg.getRelax() &&
+                     is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine);
+  if (!ctx.arg.getRelocatable() &&
+      (linkerRelax || ctx.arg.getBranchToBranch())) {
     // On LoongArch and RISC-V, relaxation might change relocations: copy
     // from internal ones that are updated by relaxation.
     InputSectionBase *sec = getRelocatedSection();
@@ -454,8 +455,9 @@ void InputSection::copyRelocations(Ctx &ctx, uint8_t *buf) {
       const ObjFile<ELFT> &file;
       Relocation operator()(const RelTy &rel) const {
         // RelExpr is not used so set to a dummy value.
-        return Relocation{R_NONE, rel.getType(ctx.arg.isMips64EL), rel.r_offset,
-                          getAddend<ELFT>(rel), &file.getRelocTargetSym(rel)};
+        return Relocation{R_NONE, rel.getType(ctx.arg.getIsMips64EL()),
+                          rel.r_offset, getAddend<ELFT>(rel),
+                          &file.getRelocTargetSym(rel)};
       }
     };
 
@@ -495,7 +497,7 @@ void InputSection::copyRelocations(Ctx &ctx, uint8_t *buf,
     // section, but for --emit-relocs it is a virtual address.
     p->r_offset = sec->getVA(rel.offset);
     p->setSymbolAndType(ctx.in.symTab->getSymbolIndex(sym), type,
-                        ctx.arg.isMips64EL);
+                        ctx.arg.getIsMips64EL());
 
     if (sym.type == STT_SECTION) {
       // We combine multiple section symbols into only one per
@@ -556,7 +558,7 @@ void InputSection::copyRelocations(Ctx &ctx, uint8_t *buf,
       // writeSections will update the implicit addend. Non-SHF_ALLOC sections
       // utilize relocateNonAlloc to process raw relocations and do not need
       // this sec->relocations change.
-      else if (ctx.arg.relocatable && (sec->flags & SHF_ALLOC) &&
+      else if (ctx.arg.getRelocatable() && (sec->flags & SHF_ALLOC) &&
                type != target.noneRel)
         sec->addReloc({R_ABS, type, rel.offset, addend, &sym});
     } else if (ctx.arg.emachine == EM_PPC && type == R_PPC_PLTREL24 &&
@@ -1069,7 +1071,7 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf,
   const InputFile *f = this->file;
   for (auto it = rels.begin(), end = rels.end(); it != end; ++it) {
     const RelTy &rel = *it;
-    const RelType type = rel.getType(ctx.arg.isMips64EL);
+    const RelType type = rel.getType(ctx.arg.getIsMips64EL());
     const uint64_t offset = rel.r_offset;
     uint8_t *bufLoc = buf + offset;
     int64_t addend = getAddend<ELFT>(rel);
@@ -1149,7 +1151,8 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf,
     // explicit addend, such as RELA, remain unchanged and we can stop here.
     // While content relocated by relocation types with an implicit addend, such
     // as REL, needs the implicit addend updated.
-    if (ctx.arg.relocatable && (RelTy::HasAddend || sym.type != STT_SECTION))
+    if (ctx.arg.getRelocatable() &&
+        (RelTy::HasAddend || sym.type != STT_SECTION))
       continue;
 
     // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
@@ -1196,7 +1199,8 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf,
 
 template <class ELFT>
 void InputSection::relocate(Ctx &ctx, uint8_t *buf, uint8_t *bufEnd) {
-  if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile<ELFT>()->splitStack))
+  if ((flags & SHF_EXECINSTR) &&
+      LLVM_UNLIKELY(getFile<ELFT>()->getSplitStack()))
     adjustSplitStackFunctionPrologues<ELFT>(ctx, buf, bufEnd);
 
   if (flags & SHF_ALLOC) {
@@ -1287,7 +1291,8 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(Ctx &ctx, uint8_t *buf,
     // conservative.
     if (Defined *d = dyn_cast<Defined>(rel.sym))
       if (InputSection *isec = cast_or_null<InputSection>(d->section))
-        if (!isec || !isec->getFile<ELFT>() || isec->getFile<ELFT>()->splitStack)
+        if (!isec || !isec->getFile<ELFT>() ||
+            isec->getFile<ELFT>()->getSplitStack())
           continue;
 
     if (enclosingPrologueAttempted(rel.offset, prologues))
@@ -1298,7 +1303,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(Ctx &ctx, uint8_t *buf,
       if (ctx.target->adjustPrologueForCrossSplitStack(buf + f->value, end,
                                                        f->stOther))
         continue;
-      if (!getFile<ELFT>()->someNoSplitStack)
+      if (!getFile<ELFT>()->getSomeNoSplitStack())
         Err(ctx)
             << this << ": " << f->getName() << " (with -fsplit-stack) calls "
             << rel.sym->getName()
@@ -1433,8 +1438,8 @@ void EhInputSection::preprocessRelocs(Relocs<RelTy> elfRels) {
   rels.reserve(elfRels.size());
   for (auto rel : elfRels) {
     uint64_t offset = rel.r_offset;
-    Symbol &sym = file->getSymbol(rel.getSymbol(ctx.arg.isMips64EL));
-    RelType type = rel.getType(ctx.arg.isMips64EL);
+    Symbol &sym = file->getSymbol(rel.getSymbol(ctx.arg.getIsMips64EL()));
+    RelType type = rel.getType(ctx.arg.getIsMips64EL());
     RelExpr expr = ctx.target->getRelExpr(type, sym, content().data() + offset);
     int64_t addend =
         RelTy::HasAddend
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index f5ce6f2c2fd4b..105385b847c72 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -100,9 +100,9 @@ static lto::Config createConfig(Ctx &ctx) {
 
   if (auto relocModel = getRelocModelFromCMModel())
     c.RelocModel = *relocModel;
-  else if (ctx.arg.relocatable)
+  else if (ctx.arg.getRelocatable())
     c.RelocModel = std::nullopt;
-  else if (ctx.arg.isPic)
+  else if (ctx.arg.getIsPic())
     c.RelocModel = Reloc::PIC_;
   else
     c.RelocModel = Reloc::Static;
@@ -125,7 +125,7 @@ static lto::Config createConfig(Ctx &ctx) {
   // Set up optimization remarks if we've been asked to.
   c.RemarksFilename = std::string(ctx.arg.optRemarksFilename);
   c.RemarksPasses = std::string(ctx.arg.optRemarksPasses);
-  c.RemarksWithHotness = ctx.arg.optRemarksWithHotness;
+  c.RemarksWithHotness = ctx.arg.getOptRemarksWithHotness();
   c.RemarksHotnessThreshold = ctx.arg.optRemarksHotnessThreshold;
   c.RemarksFormat = std::string(ctx.arg.optRemarksFormat);
 
@@ -141,14 +141,14 @@ static lto::Config createConfig(Ctx &ctx) {
   c.HasWholeProgramVisibility = ctx.arg.ltoWholeProgramVisibility;
   c.ValidateAllVtablesHaveTypeInfos =
       ctx.arg.ltoValidateAllVtablesHaveTypeInfos;
-  c.AllVtablesHaveTypeInfos = ctx.ltoAllVtablesHaveTypeInfos;
+  c.AllVtablesHaveTypeInfos = ctx.getLtoAllVtablesHaveTypeInfos();
   c.AlwaysEmitRegularLTOObj = !ctx.arg.ltoObjPath.empty();
   c.KeepSymbolNameCopies = false;
 
   for (const llvm::StringRef &name : ctx.arg.thinLTOModulesToCompile)
     c.ThinLTOModulesToCompile.emplace_back(name);
 
-  c.TimeTraceEnabled = ctx.arg.timeTraceEnabled;
+  c.TimeTraceEnabled = ctx.arg.getTimeTraceEnabled();
   c.TimeTraceGranularity = ctx.arg.timeTraceGranularity;
 
   c.CSIRProfile = std::string(ctx.arg.ltoCSProfileFile);
@@ -184,7 +184,7 @@ BitcodeCompiler::BitcodeCompiler(Ctx &ctx) : ctx(ctx) {
   // Initialize ltoObj.
   lto::ThinBackend backend;
   auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
-  if (ctx.arg.thinLTOIndexOnly) {
+  if (ctx.arg.getThinLTOIndexOnly()) {
     backend = lto::createWriteIndexesThinBackend(
         llvm::hardware_concurrency(ctx.arg.thinLTOJobs),
         std::string(ctx.arg.thinLTOPrefixReplaceOld),
@@ -212,10 +212,12 @@ BitcodeCompiler::BitcodeCompiler(Ctx &ctx) : ctx(ctx) {
         createConfig(ctx), ctx.arg.ltoPartitions, ltoModes[ctx.arg.ltoKind],
         onIndexWrite, ctx.arg.thinLTOEmitIndexFiles,
         ctx.arg.thinLTOEmitImportsFiles, ctx.arg.outputFile,
-        ctx.arg.dtltoDistributor, ctx.arg.dtltoDistributorArgs,
-        ctx.arg.dtltoCompiler, ctx.arg.dtltoCompilerPrependArgs,
-        ctx.arg.dtltoCompilerArgs, createAddBufferFn(files, filenames),
-        !ctx.arg.saveTempsArgs.empty());
+        ctx.arg.dtltoDistributor,
+        ArrayRef<StringRef>(ctx.arg.dtltoDistributorArgs),
+        ctx.arg.dtltoCompiler,
+        ArrayRef<StringRef>(ctx.arg.dtltoCompilerPrependArgs),
+        ArrayRef<StringRef>(ctx.arg.dtltoCompilerArgs),
+        createAddBufferFn(files, filenames), !ctx.arg.saveTempsArgs.empty());
   // Initialize usedStartStop.
   if (ctx.bitcodeFiles.empty())
     return;
@@ -238,7 +240,7 @@ void BitcodeCompiler::waitForLTOCleanup() {
 
 void BitcodeCompiler::add(BitcodeFile &f) {
   lto::InputFile &obj = *f.obj;
-  bool isExec = !ctx.arg.shared && !ctx.arg.relocatable;
+  bool isExec = !ctx.arg.getShared() && !ctx.arg.getRelocatable();
 
   if (ctx.arg.thinLTOEmitIndexFiles)
     thinIndices.insert(obj.getName());
@@ -268,10 +270,10 @@ void BitcodeCompiler::add(BitcodeFile &f) {
     // 4) Symbols that are defined in bitcode files and used for dynamic
     //    linking.
     // 5) Symbols that will be referenced after linker wrapping is performed.
-    r.VisibleToRegularObj = ctx.arg.relocatable || sym->isUsedInRegularObj ||
-                            sym->referencedAfterWrap ||
-                            (r.Prevailing && sym->isExported) ||
-                            usedStartStop.contains(objSym.getSectionName());
+    r.VisibleToRegularObj =
+        ctx.arg.getRelocatable() || sym->isUsedInRegularObj ||
+        sym->referencedAfterWrap || (r.Prevailing && sym->isExported) ||
+        usedStartStop.contains(objSym.getSectionName());
     // Identify symbols exported dynamically, and that therefore could be
     // referenced by a shared library not visible to the linker.
     r.ExportDynamic = sym->computeBinding(ctx) != STB_LOCAL &&
@@ -309,7 +311,7 @@ static void thinLTOCreateEmptyIndexFiles(Ctx &ctx) {
     linkedBitCodeFiles.insert(f->getName());
 
   for (BitcodeFile *f : ctx.lazyBitcodeFiles) {
-    if (!f->lazy)
+    if (!f->getLazy())
       continue;
     if (linkedBitCodeFiles.contains(f->getName()))
       continue;
@@ -367,7 +369,7 @@ SmallVector<std::unique_ptr<InputFile>, 0> BitcodeCompiler::compile() {
   if (ctx.arg.thinLTOEmitIndexFiles)
     thinLTOCreateEmptyIndexFiles(ctx);
 
-  if (ctx.arg.thinLTOIndexOnly) {
+  if (ctx.arg.getThinLTOIndexOnly()) {
     if (!ctx.arg.ltoObjPath.empty())
       saveBuffer(buf[0].second, ctx.arg.ltoObjPath);
 
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index c69b0616a2367..eb16739dd585a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -50,14 +50,14 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   // This is for --emit-relocs and -r. If .text.foo is emitted as .text.bar, we
   // want to emit .rela.text.foo as .rela.text.bar for consistency (this is not
   // technically required, but not doing it is odd). This code guarantees that.
-  if (LLVM_UNLIKELY(ctx.arg.copyRelocs)) {
+  if (LLVM_UNLIKELY(ctx.arg.getCopyRelocs())) {
     InputSectionBase *rel = nullptr;
     if (auto *isec = dyn_cast<InputSection>(s))
       rel = isec->getRelocatedSection();
     if (rel) {
       OutputSection *out = rel->getOutputSection();
       if (!out) {
-        assert(ctx.arg.relocatable && (rel->flags & SHF_LINK_ORDER));
+        assert(ctx.arg.getRelocatable() && (rel->flags & SHF_LINK_ORDER));
         return s->name;
       }
       StringSaver &ss = ctx.saver;
@@ -69,7 +69,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
     }
     // Use default LLD behavior for the embedded unoptimized dynamic debugging
     // relocatable link.
-    if (ctx.arg.relocatable && !ctx.dynDbgRelocatable)
+    if (ctx.arg.getRelocatable() && !ctx.getDynDbgRelocatable())
       return s->name;
   }
 
@@ -78,7 +78,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   if (s->name == "COMMON")
     return ".bss";
 
-  if (hasSectionsCommand)
+  if (getHasSectionsCommand())
     return s->name;
 
   // When no SECTIONS is specified, emulate GNU ld's internal linker scripts
@@ -99,7 +99,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   // profile inaccuracy. Techniques such as hugepage remapping can make
   // conservative decisions at the section granularity.
   if (isSectionPrefix(".text", s->name)) {
-    if (ctx.arg.zKeepTextSectionPrefix)
+    if (ctx.arg.getZKeepTextSectionPrefix())
       for (StringRef v : {".text.hot", ".text.unknown", ".text.unlikely",
                           ".text.startup", ".text.exit", ".text.split"})
         if (isSectionPrefix(v.substr(5), s->name.substr(5)))
@@ -107,7 +107,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
     return ".text";
   }
   if (isSectionPrefix(".ltext", s->name)) {
-    if (ctx.arg.zKeepTextSectionPrefix)
+    if (ctx.arg.getZKeepTextSectionPrefix())
       for (StringRef v : {".ltext.hot", ".ltext.unknown", ".ltext.unlikely",
                           ".ltext.startup", ".ltext.exit", ".ltext.split"})
         if (isSectionPrefix(v.substr(6), s->name.substr(6)))
@@ -134,7 +134,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   // Note .bss.rel.ro doesn't have hot / unlikely mapping. It's placed before
   // .bss so they get processed before `.bss` prefix is seen, just like
   // how `.data.rel.ro` should be processed before seeing the `.data` prefix.
-  if (ctx.arg.zKeepDataSectionPrefix)
+  if (ctx.arg.getZKeepDataSectionPrefix())
     for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
       StringRef secName = s->name;
       // If v is the prefix, trim it from secName. Otherwise just continue to
@@ -241,7 +241,7 @@ void LinkerScript::expandMemoryRegions(uint64_t size) {
 void LinkerScript::expandOutputSection(uint64_t size) {
   state->outSec->size += size;
   size_t regionSize = size;
-  if (state->outSec->inOverlay) {
+  if (state->outSec->getInOverlay()) {
     // Expand the overlay if necessary, and expand the region by the
     // corresponding amount.
     if (state->outSec->size > state->overlaySize) {
@@ -412,9 +412,10 @@ void LinkerScript::processInsertCommands() {
         });
     if (insertPos == sectionCommands.end()) {
       ErrAlways(ctx) << "unable to insert " << cmd.names[0]
-                     << (cmd.isAfter ? " after " : " before ") << cmd.where;
+                     << (cmd.getIsAfter() ? " after " : " before ")
+                     << cmd.where;
     } else {
-      if (cmd.isAfter)
+      if (cmd.getIsAfter())
         ++insertPos;
       sectionCommands.insert(insertPos, moves.begin(), moves.end());
     }
@@ -688,7 +689,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
       Err(ctx) << "undefined section class '" << cmd->classRef << "'";
       return ret;
     }
-    if (!scd->sc.assigned) {
+    if (!scd->sc.getAssigned()) {
       Err(ctx) << "section class '" << cmd->classRef << "' referenced by '"
                << outCmd.name << "' before class definition";
       return ret;
@@ -852,7 +853,7 @@ void LinkerScript::processSectionCommands() {
             s->parent = &sc->sc;
         }
       }
-      sc->sc.assigned = true;
+      sc->sc.setAssigned(true);
     }
   }
 
@@ -1031,7 +1032,7 @@ static OutputDesc *addInputSec(Ctx &ctx,
     if (sec->partition != isec->partition)
       continue;
 
-    if (ctx.arg.relocatable && (isec->flags & SHF_LINK_ORDER)) {
+    if (ctx.arg.getRelocatable() && (isec->flags & SHF_LINK_ORDER)) {
       // Merging two SHF_LINK_ORDER sections with different sh_link fields will
       // change their semantics, so we only merge them in -r links if they will
       // end up being linked to the same output section. The casts are fine
@@ -1066,7 +1067,7 @@ void LinkerScript::addOrphanSections() {
 
       if (name.empty())
         name = getOutputSectionName(s);
-      if (ctx.arg.unique) {
+      if (ctx.arg.getUnique()) {
         v.push_back(createSection(ctx, s, name));
       } else if (OutputSection *sec = findByName(sectionCommands, name)) {
         sec->recordSection(s);
@@ -1079,8 +1080,8 @@ void LinkerScript::addOrphanSections() {
     }
   };
 
-  const bool copyRelocs = ctx.arg.copyRelocs;
-  const bool relocatable = ctx.arg.relocatable;
+  const bool copyRelocs = ctx.arg.getCopyRelocs();
+  const bool relocatable = ctx.arg.getRelocatable();
   // Under --emit-relocs/-r, getOutputSectionName derives the name from the
   // relocated section, and saving it is not thread-safe. Otherwise, the names
   // can be precomputed in parallel.
@@ -1131,7 +1132,7 @@ void LinkerScript::addOrphanSections() {
   // before others, so that we can handle scripts which refers them,
   // for example: "foo = ABSOLUTE(ADDR(.text)));".
   // When SECTIONS command is present we just add all orphans to the end.
-  if (hasSectionsCommand)
+  if (getHasSectionsCommand())
     sectionCommands.insert(sectionCommands.end(), v.begin(), v.end());
   else
     sectionCommands.insert(sectionCommands.begin(), v.begin(), v.end());
@@ -1140,7 +1141,7 @@ void LinkerScript::addOrphanSections() {
 void LinkerScript::diagnoseOrphanHandling() const {
   llvm::TimeTraceScope timeScope("Diagnose orphan sections");
   if (ctx.arg.orphanHandling == OrphanHandlingPolicy::Place ||
-      !hasSectionsCommand)
+      !getHasSectionsCommand())
     return;
   for (const InputSectionBase *sec : orphanSections) {
     // .relro_padding is inserted before DATA_SEGMENT_RELRO_END, if present,
@@ -1182,7 +1183,7 @@ LinkerScript::findMemoryRegion(OutputSection *sec, MemoryRegion *hint) {
   // Non-allocatable sections are not part of the process image.
   if (!(sec->flags & SHF_ALLOC)) {
     bool hasInputOrByteCommand =
-        sec->hasInputSections ||
+        sec->getHasInputSections() ||
         llvm::any_of(sec->commands, [](SectionCommand *comm) {
           return ByteCommand::classof(comm);
         });
@@ -1257,7 +1258,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
   } else {
     // If there is an explicit address expression this takes precedence over
     // the memory region address.
-    if (state->memRegion && !(hasSectionsCommand && sec->addrExpr))
+    if (state->memRegion && !(getHasSectionsCommand() && sec->addrExpr))
       dot = state->memRegion->curPos;
     if (sec->addrExpr)
       setDot(sec->addrExpr, sec->location, false);
@@ -1272,7 +1273,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
   }
 
   state->outSec = sec;
-  if (!(sec->addrExpr && hasSectionsCommand)) {
+  if (!(sec->addrExpr && getHasSectionsCommand())) {
     // ALIGN is respected. sec->alignment is the max of ALIGN and the maximum of
     // input section alignments.
     const uint64_t pos = dot;
@@ -1307,11 +1308,12 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
   // We can call this method multiple times during the creation of
   // thunks and want to start over calculation each time.
   sec->size = 0;
-  if (sec->firstInOverlay)
+  if (sec->getFirstInOverlay())
     state->overlaySize = 0;
 
   bool synthesizeAlign =
-      ctx.arg.relocatable && ctx.arg.relax && (sec->flags & SHF_EXECINSTR) &&
+      ctx.arg.getRelocatable() && ctx.arg.getRelax() &&
+      (sec->flags & SHF_EXECINSTR) &&
       (ctx.arg.emachine == EM_LOONGARCH || ctx.arg.emachine == EM_RISCV);
   // We visited SectionsCommands from processSectionCommands to
   // layout sections. Now, we visit SectionsCommands again to fix
@@ -1387,13 +1389,13 @@ static bool isDiscardable(const OutputSection &sec) {
   // We do not want to remove OutputSections with expressions that reference
   // symbols even if the OutputSection is empty. We want to ensure that the
   // expressions can be evaluated and report an error if they cannot.
-  if (sec.expressionsUseSymbols)
+  if (sec.getExpressionsUseSymbols())
     return false;
 
   // OutputSections may be referenced by name in ADDR and LOADADDR expressions,
   // as an empty Section can has a valid VMA and LMA we keep the OutputSection
   // to maintain the integrity of the other Expression.
-  if (sec.usedInExpression)
+  if (sec.getUsedInExpression())
     return false;
 
   for (SectionCommand *cmd : sec.commands) {
@@ -1463,14 +1465,14 @@ void LinkerScript::adjustOutputSections() {
     // If sec has at least one input section and not discarded, remember its
     // flags to be inherited by subsequent output sections. (sec may contain
     // just one empty synthetic section.)
-    if (sec->hasInputSections && !discardable)
+    if (sec->getHasInputSections() && !discardable)
       flags = sec->flags;
 
     // We do not want to keep any special flags for output section
     // in case it is empty.
     if (isEmpty) {
       sec->flags =
-          flags & ((sec->nonAlloc ? 0 : (uint64_t)SHF_ALLOC) | SHF_WRITE);
+          flags & ((sec->getNonAlloc() ? 0 : (uint64_t)SHF_ALLOC) | SHF_WRITE);
       sec->sortRank = getSectionRank(ctx, *sec);
     }
 
@@ -1496,8 +1498,8 @@ void LinkerScript::adjustOutputSections() {
       sec->markDead();
       cmd = nullptr;
     } else {
-      seenRelro |=
-          sec->relro && !(sec->type == SHT_NOBITS && (sec->flags & SHF_TLS));
+      seenRelro |= sec->getRelro() &&
+                   !(sec->type == SHT_NOBITS && (sec->flags & SHF_TLS));
     }
   }
 
@@ -1570,13 +1572,13 @@ void LinkerScript::allocateHeaders(
       llvm::any_of(phdrsCommands, [](const PhdrsCommand &cmd) {
         return cmd.hasPhdrs || cmd.hasFilehdr;
       });
-  bool paged = !ctx.arg.omagic && !ctx.arg.nmagic;
+  bool paged = !ctx.arg.getOmagic() && !ctx.arg.nmagic;
   uint64_t headerSize = getHeaderSize(ctx);
 
   uint64_t base = 0;
   // If SECTIONS is present and the linkerscript is not explicit about program
   // headers, only allocate program headers if that would not add a page.
-  if (hasSectionsCommand && !hasExplicitHeaders)
+  if (getHasSectionsCommand() && !hasExplicitHeaders)
     base = alignDown(min, ctx.arg.maxPageSize);
   if ((paged || hasExplicitHeaders) && headerSize <= min - base) {
     min = alignDown(min - headerSize, ctx.arg.maxPageSize);
@@ -1610,7 +1612,7 @@ LinkerScript::AddressState::AddressState(const LinkerScript &script) {
 // that has changed its section or value (or nullptr if no symbol has changed).
 std::pair<const OutputSection *, const Defined *>
 LinkerScript::assignAddresses() {
-  if (hasSectionsCommand) {
+  if (getHasSectionsCommand()) {
     // With a linker script, assignment of addresses to headers is covered by
     // allocateHeaders().
     dot = ctx.arg.imageBase.value_or(0);
@@ -1625,7 +1627,7 @@ LinkerScript::assignAddresses() {
   OutputSection *changedOsec = nullptr;
   AddressState st(*this);
   state = &st;
-  errorOnMissingSection = true;
+  setErrorOnMissingSection(true);
   st.outSec = aether.get();
   recordedErrors.clear();
 
@@ -1850,7 +1852,7 @@ ExprValue LinkerScript::getSymbolValue(StringRef name, const Twine &loc) {
       return v;
     }
     if (isa<SharedSymbol>(sym))
-      if (!errorOnMissingSection)
+      if (!getErrorOnMissingSection())
         return {nullptr, false, 0, loc};
   }
 
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 80c4f564afabc..dd03d45078f09 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include <cstddef>
@@ -276,19 +277,27 @@ struct ByteCommand : SectionCommand {
 };
 
 struct InsertCommand {
-  SmallVector<StringRef, 0> names;
-  bool isAfter;
+  InsertCommand(SmallVector<StringRef, 0> names, bool isAfter, StringRef where)
+      : names(unsigned(isAfter), std::move(names)), where(where) {}
+  llvm::SmallVectorWithFlags<StringRef, 0> names;
+  bool getIsAfter() const { return names.getFlag(0); }
+  void setIsAfter(bool Value) { names.setFlag(0, Value); }
   StringRef where;
 };
 
 // A NOCROSSREFS/NOCROSSREFS_TO command that prohibits references between
 // certain output sections.
 struct NoCrossRefCommand {
-  SmallVector<StringRef, 0> outputSections;
+  llvm::SmallVectorWithFlags<StringRef, 0> outputSections;
+
+  NoCrossRefCommand() = default;
+  explicit NoCrossRefCommand(bool toFirst) {
+    outputSections.setFlag(0, toFirst);
+  }
 
   // When true, this describes a NOCROSSREFS_TO command that probits references
   // to the first output section from any of the other sections.
-  bool toFirst = false;
+  bool toFirst() const { return outputSections.getFlag(0); }
 };
 
 struct PhdrsCommand {
@@ -417,10 +426,16 @@ class LinkerScript final {
   // PHDRS command list.
   SmallVector<PhdrsCommand, 0> phdrsCommands;
 
-  bool hasSectionsCommand = false;
-  bool seenDataAlign = false;
-  bool seenRelroEnd = false;
-  bool errorOnMissingSection = false;
+  bool getHasSectionsCommand() const { return orphanSections.getFlag(0); }
+  void setHasSectionsCommand(bool Value) { orphanSections.setFlag(0, Value); }
+  bool getSeenDataAlign() const { return orphanSections.getFlag(1); }
+  void setSeenDataAlign(bool Value) { orphanSections.setFlag(1, Value); }
+  bool getSeenRelroEnd() const { return orphanSections.getFlag(2); }
+  void setSeenRelroEnd(bool Value) { orphanSections.setFlag(2, Value); }
+  bool getErrorOnMissingSection() const { return orphanSections.getFlag(3); }
+  void setErrorOnMissingSection(bool Value) {
+    orphanSections.setFlag(3, Value);
+  }
   SmallVector<SmallString<0>, 0> recordedErrors;
 
   // List of section patterns specified with KEEP commands. They will
@@ -444,7 +459,7 @@ class LinkerScript final {
   SmallVector<NoCrossRefCommand, 0> noCrossRefs;
 
   // Sections that will be warned/errored by --orphan-handling.
-  SmallVector<const InputSectionBase *, 0> orphanSections;
+  llvm::SmallVectorWithFlags<const InputSectionBase *, 0, 4> orphanSections;
 
   // Stores the mapping: PROVIDE symbol -> symbols referred in the PROVIDE
   // expression. For example, if the PROVIDE command is:
diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp
index 05ae25fc8efea..3261d2c3b50e6 100644
--- a/lld/ELF/MapFile.cpp
+++ b/lld/ELF/MapFile.cpp
@@ -45,7 +45,7 @@ static constexpr char indent16[] = "                "; // 16 spaces
 // Print out the first three columns of a line.
 static void writeHeader(Ctx &ctx, raw_ostream &os, uint64_t vma, uint64_t lma,
                         uint64_t size, uint64_t align) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align);
   else
     os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align);
@@ -154,7 +154,7 @@ static void writeMapFile(Ctx &ctx, raw_fd_ostream &os) {
   DenseMap<Symbol *, std::string> symStr = getSymbolStrings(ctx, syms);
 
   // Print out the header line.
-  int w = ctx.arg.is64 ? 16 : 8;
+  int w = ctx.arg.getIs64() ? 16 : 8;
   os << right_justify("VMA", w) << ' ' << right_justify("LMA", w)
      << "     Size Align Out     In      Symbol\n";
 
@@ -259,7 +259,7 @@ static void writeCref(Ctx &ctx, raw_fd_ostream &os) {
 }
 
 void elf::writeMapAndCref(Ctx &ctx) {
-  if (ctx.arg.mapFile.empty() && !ctx.arg.cref)
+  if (ctx.arg.mapFile.empty() && !ctx.arg.getCref())
     return;
 
   llvm::TimeTraceScope timeScope("Write map file");
@@ -275,6 +275,6 @@ void elf::writeMapAndCref(Ctx &ctx) {
 
   if (!ctx.arg.mapFile.empty())
     writeMapFile(ctx, os);
-  if (ctx.arg.cref)
+  if (ctx.arg.getCref())
     writeCref(ctx, os);
 }
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index f5179bb2c60d0..badb43806efb2 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -94,7 +94,7 @@ template <class ELFT>
 static uint64_t getAddend(Ctx &ctx, InputSectionBase &sec,
                           const typename ELFT::Rel &rel) {
   return ctx.target->getImplicitAddend(sec.content().begin() + rel.r_offset,
-                                       rel.getType(ctx.arg.isMips64EL));
+                                       rel.getType(ctx.arg.getIsMips64EL()));
 }
 
 template <class ELFT>
@@ -405,7 +405,7 @@ void MarkLive<ELFT, TrackWhyLive>::run() {
     scanEhFrameSection(*eh);
   // See markUsedSymbols.
   bool markUsed =
-      ctx.arg.copyRelocs &&
+      ctx.arg.getCopyRelocs() &&
       (ctx.arg.discard != DiscardPolicy::None || ctx.arg.retainSymbols);
   for (InputSectionBase *sec : ctx.inputSections) {
     if (sec->flags & SHF_GNU_RETAIN) {
@@ -454,7 +454,8 @@ void MarkLive<ELFT, TrackWhyLive>::run() {
     } else if (ctx.script->shouldKeep(sec)) {
       enqueue(sec, /*offset=*/0, /*sym=*/nullptr,
               {std::nullopt, "KEEP in linker script"});
-    } else if ((!ctx.arg.zStartStopGC || sec->name.starts_with("__libc_")) &&
+    } else if ((!ctx.arg.getZStartStopGC() ||
+                sec->name.starts_with("__libc_")) &&
                isValidCIdentifier(sec->name)) {
       // As a workaround for glibc libc.a before 2.34
       // (https://sourceware.org/PR27492), retain __libc_atexit and similar
@@ -622,7 +623,7 @@ template <class ELFT> void elf::markLive(Ctx &ctx) {
         if (s->isUsedInRegularObj && !s->isWeak())
           cast<SharedFile>(s->file)->isNeeded = true;
     // See markUsedSymbols.
-    if (ctx.arg.copyRelocs &&
+    if (ctx.arg.getCopyRelocs() &&
         (ctx.arg.discard != DiscardPolicy::None || ctx.arg.retainSymbols))
       parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
         for (InputSectionBase *sec : file->getSections())
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 7ae024e47a7e8..6c8bcdda7c667 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -117,7 +117,7 @@ void OutputSection::recordSection(InputSectionBase *isec) {
 // other InputSections.
 void OutputSection::commitSection(InputSection *isec) {
   if (LLVM_UNLIKELY(type != isec->type)) {
-    if (!hasInputSections && !typeIsSet) {
+    if (!getHasInputSections() && !getTypeIsSet()) {
       type = isec->type;
     } else if (isStaticRelSecType(type) && isStaticRelSecType(isec->type) &&
                (type == SHT_CREL) != (isec->type == SHT_CREL)) {
@@ -130,7 +130,7 @@ void OutputSection::commitSection(InputSection *isec) {
         name = ctx.saver.save(".crel" + name);
       }
     } else {
-      if (typeIsSet || !canMergeToProgbits(ctx, type) ||
+      if (getTypeIsSet() || !canMergeToProgbits(ctx, type) ||
           !canMergeToProgbits(ctx, isec->type)) {
         // The (NOLOAD) changes the section type to SHT_NOBITS, the intention is
         // that the contents at that address is provided by some other means.
@@ -145,14 +145,14 @@ void OutputSection::commitSection(InputSection *isec) {
                    << getELFSectionTypeName(ctx.arg.emachine, type);
         }
       }
-      if (!typeIsSet)
+      if (!getTypeIsSet())
         type = SHT_PROGBITS;
     }
   }
-  if (!hasInputSections) {
+  if (!getHasInputSections()) {
     // If IS is the first section to be added to this section,
     // initialize type, entsize and flags from isec.
-    hasInputSections = true;
+    setHasInputSections(true);
     entsize = isec->entsize;
     flags = isec->flags;
   } else {
@@ -174,7 +174,7 @@ void OutputSection::commitSection(InputSection *isec) {
   uint64_t andFlags = (flags & isec->flags) & andMask;
   uint64_t orFlags = (flags | isec->flags) & orMask;
   flags = andFlags | orFlags;
-  if (nonAlloc)
+  if (getNonAlloc())
     flags &= ~(uint64_t)SHF_ALLOC;
 
   addralign = std::max(addralign, isec->addralign);
@@ -288,7 +288,7 @@ static void sortByOrder(MutableArrayRef<InputSection *> in,
 }
 
 uint64_t elf::getHeaderSize(Ctx &ctx) {
-  if (ctx.arg.oFormatBinary)
+  if (ctx.arg.getOFormatBinary())
     return 0;
   return ctx.out.elfHeader->size + ctx.out.programHeaders->size;
 }
@@ -548,8 +548,8 @@ void OutputSection::writeTo(Ctx &ctx, uint8_t *buf, parallel::TaskGroup &tg) {
 
       // When in Arm BE8 mode, the linker has to convert the big-endian
       // instructions to little-endian, leaving the data big-endian.
-      if (ctx.arg.emachine == EM_ARM && !ctx.arg.isLE && ctx.arg.armBe8 &&
-          (flags & SHF_EXECINSTR))
+      if (ctx.arg.emachine == EM_ARM && !ctx.arg.getIsLE() &&
+          ctx.arg.getArmBe8() && (flags & SHF_EXECINSTR))
         convertArmInstructionstoBE8(ctx, isec, buf + isec->outSecOff);
 
       // Fill gaps between sections.
@@ -684,7 +684,7 @@ static size_t relToCrel(Ctx &ctx, raw_svector_ostream &os,
   for (auto rel : rels) {
     encodeOneCrel<typename ELFT::uint>(
         ctx, os, out, sec->getVA(rel.r_offset), file.getRelocTargetSym(rel),
-        rel.getType(ctx.arg.isMips64EL), getAddend<ELFT>(rel));
+        rel.getType(ctx.arg.getIsMips64EL()), getAddend<ELFT>(rel));
   }
   return rels.size();
 }
@@ -713,11 +713,11 @@ template <bool is64> void OutputSection::finalizeNonAllocCrel(Ctx &ctx) {
 
     // Convert REL[A] to CREL.
     if constexpr (is64) {
-      totalCount += ctx.arg.isLE
+      totalCount += ctx.arg.getIsLE()
                         ? relToCrel<ELF64LE>(ctx, os, out, relSec, sec)
                         : relToCrel<ELF64BE>(ctx, os, out, relSec, sec);
     } else {
-      totalCount += ctx.arg.isLE
+      totalCount += ctx.arg.getIsLE()
                         ? relToCrel<ELF32LE>(ctx, os, out, relSec, sec)
                         : relToCrel<ELF32BE>(ctx, os, out, relSec, sec);
     }
@@ -747,7 +747,7 @@ void OutputSection::finalize(Ctx &ctx) {
     return;
   }
 
-  if (!ctx.arg.copyRelocs || !isStaticRelSecType(type))
+  if (!ctx.arg.getCopyRelocs() || !isStaticRelSecType(type))
     return;
 
   // Skip if 'first' is synthetic, i.e. not a section created by --emit-relocs.
@@ -765,7 +765,7 @@ void OutputSection::finalize(Ctx &ctx) {
   flags |= SHF_INFO_LINK;
   // Finalize the content of non-alloc CREL.
   if (type == SHT_CREL) {
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       finalizeNonAllocCrel<true>(ctx);
     else
       finalizeNonAllocCrel<false>(ctx);
@@ -848,26 +848,6 @@ InputSection *elf::getFirstInputSection(const OutputSection *os) {
   return nullptr;
 }
 
-ArrayRef<InputSection *>
-elf::getInputSections(const OutputSection &os,
-                      SmallVector<InputSection *, 0> &storage) {
-  ArrayRef<InputSection *> ret;
-  storage.clear();
-  for (SectionCommand *cmd : os.commands) {
-    auto *isd = dyn_cast<InputSectionDescription>(cmd);
-    if (!isd)
-      continue;
-    if (ret.empty()) {
-      ret = isd->sections;
-    } else {
-      if (storage.empty())
-        storage.assign(ret.begin(), ret.end());
-      storage.insert(storage.end(), isd->sections.begin(), isd->sections.end());
-    }
-  }
-  return storage.empty() ? ret : ArrayRef(storage);
-}
-
 // Sorts input sections by section name suffixes, so that .foo.N comes
 // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
 // We want to keep the original order if the priorities are the same
@@ -884,7 +864,7 @@ std::array<uint8_t, 4> OutputSection::getFiller(Ctx &ctx) {
     return *filler;
   if (!(flags & SHF_EXECINSTR))
     return {0, 0, 0, 0};
-  if (ctx.arg.relocatable && ctx.arg.emachine == EM_RISCV) {
+  if (ctx.arg.getRelocatable() && ctx.arg.emachine == EM_RISCV) {
     // See RISCV::maybeSynthesizeAlign: Synthesized NOP bytes and ALIGN
     // relocations might be needed between two input sections. Use a NOP for the
     // filler.
@@ -892,13 +872,13 @@ std::array<uint8_t, 4> OutputSection::getFiller(Ctx &ctx) {
       return {1, 0, 1, 0};
     return {0x13, 0, 0, 0};
   }
-  if (ctx.arg.relocatable && ctx.arg.emachine == EM_LOONGARCH)
+  if (ctx.arg.getRelocatable() && ctx.arg.emachine == EM_LOONGARCH)
     return {0, 0, 0x40, 0x03};
   return ctx.target->trapInstr;
 }
 
 void OutputSection::checkDynRelAddends(Ctx &ctx) {
-  assert(ctx.arg.writeAddends && ctx.arg.checkDynamicRelocs);
+  assert(ctx.arg.writeAddends && ctx.arg.getCheckDynamicRelocs());
   assert(isStaticRelSecType(type));
   SmallVector<InputSection *, 0> storage;
   ArrayRef<InputSection *> sections = getInputSections(*this, storage);
@@ -927,7 +907,7 @@ void OutputSection::checkDynRelAddends(Ctx &ctx) {
       // With -z mark-plt, the JUMP_SLOT relocation's addend is the PLT entry
       // address, but the .got.plt entry it targets holds the lazy-binding
       // address instead, so the written value intentionally differs.
-      if (ctx.arg.zMarkPlt && rel.type == ctx.target->pltRel)
+      if (ctx.arg.getZMarkPlt() && rel.type == ctx.target->pltRel)
         continue;
       const uint8_t *relocTarget =
           ctx.bufferStart + relOsec->offset + (rel.r_offset - relOsec->addr);
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 77654f85ca78c..7afb0b65bc0aa 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -12,6 +12,7 @@
 #include "InputSection.h"
 #include "LinkerScript.h"
 #include "lld/Common/LLVM.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Parallel.h"
 
@@ -90,28 +91,48 @@ class OutputSection final : public SectionBase {
   uint64_t crelHeader = 0;
   SmallVector<char, 0> crelBody;
 
-  SmallVector<SectionCommand *, 0> commands;
+  llvm::SmallVectorWithFlags<SectionCommand *, 0, 4> commands;
   SmallVector<StringRef, 0> phdrs;
   std::optional<std::array<uint8_t, 4>> filler;
   ConstraintKind constraint = ConstraintKind::NoConstraint;
   std::string location;
   std::string memoryRegionName;
   std::string lmaRegionName;
-  bool nonAlloc = false;
-  bool typeIsSet = false;
-  bool expressionsUseSymbols = false;
-  bool usedInExpression = false;
-  bool inOverlay = false;
-  bool firstInOverlay = false;
+  bool getNonAlloc() const { return storage.getFlag(0); }
+  void setNonAlloc(bool Value) { storage.setFlag(0, Value); }
+  bool getTypeIsSet() const { return storage.getFlag(1); }
+  void setTypeIsSet(bool Value) { storage.setFlag(1, Value); }
+  bool getExpressionsUseSymbols() const { return storage.getFlag(2); }
+  bool setExpressionsUseSymbols(bool Value) {
+    storage.setFlag(2, Value);
+    return Value;
+  }
+  bool getUsedInExpression() const { return storage.getFlag(3); }
+  bool setUsedInExpression(bool Value) {
+    storage.setFlag(3, Value);
+    return Value;
+  }
+  bool getInOverlay() const { return commands.getFlag(0); }
+  void setInOverlay(bool Value) { commands.setFlag(0, Value); }
+  bool getFirstInOverlay() const { return commands.getFlag(1); }
+  bool setFirstInOverlay(bool Value) {
+    commands.setFlag(1, Value);
+    return Value;
+  }
 
   // Tracks whether the section has ever had an input section added to it, even
   // if the section was later removed (e.g. because it is a synthetic section
   // that wasn't needed). This is needed for orphan placement.
-  bool hasInputSections = false;
+  bool getHasInputSections() const { return commands.getFlag(2); }
+  void setHasInputSections(bool Value) { commands.setFlag(2, Value); }
 
   // The output section description is specified between DATA_SEGMENT_ALIGN and
   // DATA_RELRO_END.
-  bool relro = false;
+  bool getRelro() const { return commands.getFlag(3); }
+  bool setRelro(bool Value) {
+    commands.setFlag(3, Value);
+    return Value;
+  }
 
   template <bool is64> void finalizeNonAllocCrel(Ctx &);
   void finalize(Ctx &);
@@ -132,7 +153,7 @@ class OutputSection final : public SectionBase {
   CompressedData compressed;
 
 private:
-  SmallVector<InputSection *, 0> storage;
+  llvm::SmallVectorWithFlags<InputSection *, 0, 4> storage;
 };
 
 struct OutputDesc final : SectionCommand {
@@ -149,8 +170,9 @@ struct OutputDesc final : SectionCommand {
 // section descriptions. If referenced more than once, the sections can be
 // spilled to the next reference like --enable-non-contiguous-regions.
 struct SectionClass final : public SectionBase {
-  SmallVector<InputSectionDescription *, 0> commands;
-  bool assigned = false;
+  llvm::SmallVectorWithFlags<InputSectionDescription *, 0> commands;
+  bool getAssigned() const { return commands.getFlag(0); }
+  void setAssigned(bool Value) { commands.setFlag(0, Value); }
 
   SectionClass(StringRef name)
       : SectionBase(Class, nullptr, name, 0, 0, 0, 0, 0, 0) {}
@@ -168,9 +190,25 @@ struct SectionClassDesc : SectionCommand {
 int getPriority(StringRef s);
 
 InputSection *getFirstInputSection(const OutputSection *os);
-llvm::ArrayRef<InputSection *>
-getInputSections(const OutputSection &os,
-                 SmallVector<InputSection *, 0> &storage);
+template <typename StorageT>
+ArrayRef<InputSection *> getInputSections(const OutputSection &os,
+                                          StorageT &storage) {
+  ArrayRef<InputSection *> ret;
+  storage.clear();
+  for (SectionCommand *cmd : os.commands) {
+    auto *isd = dyn_cast<InputSectionDescription>(cmd);
+    if (!isd)
+      continue;
+    if (ret.empty()) {
+      ret = isd->sections;
+    } else {
+      if (storage.empty())
+        storage.assign(ret.begin(), ret.end());
+      storage.insert(storage.end(), isd->sections.begin(), isd->sections.end());
+    }
+  }
+  return storage.empty() ? ret : ArrayRef(storage);
+}
 
 uint64_t getHeaderSize(Ctx &);
 } // namespace lld::elf
diff --git a/lld/ELF/RelocScan.h b/lld/ELF/RelocScan.h
index ca55577e9ee71..79570dbfa3d6f 100644
--- a/lld/ELF/RelocScan.h
+++ b/lld/ELF/RelocScan.h
@@ -78,7 +78,7 @@ class RelocScan {
   void processR_PC(RelType type, uint64_t offset, int64_t addend, Symbol &sym) {
     if (LLVM_UNLIKELY(sym.isGnuIFunc()))
       sym.setFlags(HAS_DIRECT_RELOC);
-    if (sym.isPreemptible || (isAbsolute(sym) && ctx.arg.isPic))
+    if (sym.isPreemptible || (isAbsolute(sym) && ctx.arg.getIsPic()))
       processAux(R_PC, type, offset, sym, addend);
     else
       sec->addReloc({R_PC, type, offset, addend, &sym});
@@ -96,7 +96,7 @@ class RelocScan {
     if (sym.isPreemptible) {
       sym.setFlags(NEEDS_PLT);
       sec->addReloc({R_PLT_PC, type, offset, addend, &sym});
-    } else if (!(isAbsolute(sym) && ctx.arg.isPic)) {
+    } else if (!(isAbsolute(sym) && ctx.arg.getIsPic())) {
       sec->addReloc({R_PC, type, offset, addend, &sym});
     } else {
       processAux(R_PC, type, offset, sym, addend);
@@ -107,14 +107,14 @@ class RelocScan {
   template <bool enableIeToLe = true>
   void handleTlsIe(RelExpr ieExpr, RelType type, uint64_t offset,
                    int64_t addend, Symbol &sym) {
-    if (enableIeToLe && !ctx.arg.shared && !sym.isPreemptible) {
+    if (enableIeToLe && !ctx.arg.getShared() && !sym.isPreemptible) {
       // Optimize to Local Exec.
       sec->addReloc({R_TPREL, type, offset, addend, &sym});
     } else {
       sym.setFlags(NEEDS_TLSIE);
       // R_GOT (absolute GOT address) needs a RELATIVE dynamic relocation in
       // PIC when the relocation uses the full address (not just low page bits).
-      if (ieExpr == R_GOT && ctx.arg.isPic &&
+      if (ieExpr == R_GOT && ctx.arg.getIsPic() &&
           !ctx.target->usesOnlyLowPageBits(type))
         ctx.in.relaDyn->addRelativeReloc<true>(ctx.target->relativeRel, *sec,
                                                offset, sym, addend, type,
@@ -128,7 +128,7 @@ class RelocScan {
   // call should be skipped (i.e., caller should ++it).
   bool handleTlsLd(RelExpr sharedExpr, RelType type, uint64_t offset,
                    int64_t addend, Symbol &sym) {
-    if (ctx.arg.shared) {
+    if (ctx.arg.getShared()) {
       ctx.needsTlsLd.store(true, std::memory_order_relaxed);
       sec->addReloc({sharedExpr, type, offset, addend, &sym});
       return false;
@@ -143,7 +143,7 @@ class RelocScan {
   // ieExpr/leExpr to disable GD-to-IE/LE optimization (e.g. ARM, RISC-V).
   bool handleTlsGd(RelExpr sharedExpr, RelExpr ieExpr, RelExpr leExpr,
                    RelType type, uint64_t offset, int64_t addend, Symbol &sym) {
-    if (!ctx.arg.shared && ieExpr != R_NONE) {
+    if (!ctx.arg.getShared() && ieExpr != R_NONE) {
       if (sym.isPreemptible) {
         // Optimize to Initial Exec.
         sym.setFlags(NEEDS_TLSIE);
@@ -162,7 +162,7 @@ class RelocScan {
   // Handle TLSDESC relocation.
   void handleTlsDesc(RelExpr sharedExpr, RelExpr ieExpr, RelType type,
                      uint64_t offset, int64_t addend, Symbol &sym) {
-    if (ctx.arg.shared) {
+    if (ctx.arg.getShared()) {
       sym.setFlags(NEEDS_TLSDESC);
       sec->addReloc({sharedExpr, type, offset, addend, &sym});
     } else if (sym.isPreemptible) {
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index db5ba7d023b7f..39527bd5f4b43 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -620,14 +620,14 @@ static void reportUndefinedSymbol(Ctx &ctx, const UndefinedDiag &undef,
     msg << "\n>>> the vtable symbol may be undefined because the class is "
            "missing its key function "
            "(see https://lld.llvm.org/missingkeyfunction)";
-  if (ctx.arg.gcSections && ctx.arg.zStartStopGC &&
+  if (ctx.arg.gcSections && ctx.arg.getZStartStopGC() &&
       sym.getName().starts_with("__start_")) {
     msg << "\n>>> the encapsulation symbol needs to be retained under "
            "--gc-sections properly; consider -z nostart-stop-gc "
            "(see https://lld.llvm.org/ELF/start-stop-gc)";
   }
 
-  if (undef.isWarning)
+  if (undef.getIsWarning())
     Warn(ctx) << msg.str();
   else
     ctx.e.error(msg.str(), ErrorTag::SymbolNotFound, {sym.getName()});
@@ -694,7 +694,7 @@ bool RelocScan::maybeReportUndefined(Undefined &sym, uint64_t offset) {
 }
 
 bool RelocScan::checkTlsLe(uint64_t offset, Symbol &sym, RelType type) {
-  if (!ctx.arg.shared)
+  if (!ctx.arg.getShared())
     return false;
   auto diag = Err(ctx);
   diag << "relocation " << type << " against " << &sym
@@ -762,7 +762,7 @@ static void addPltEntry(Ctx &ctx, PltSection &plt, GotPltSection &gotPlt,
     return;
   }
   gotPlt.addEntry(sym);
-  if (sym.isPreemptible && ctx.arg.zMarkPlt && type == ctx.target->pltRel)
+  if (sym.isPreemptible && ctx.arg.getZMarkPlt() && type == ctx.target->pltRel)
     expr = R_PLT;
   rel.addReloc(
       {type, &gotPlt, sym.getGotPltOffset(ctx), isPreemptible, sym, 0, expr});
@@ -781,7 +781,7 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
 
   // Otherwise, the value is either a link-time constant or the load base
   // plus a constant.
-  if (!ctx.arg.isPic || isAbsolute(sym))
+  if (!ctx.arg.getIsPic() || isAbsolute(sym))
     ctx.in.got->addConstant({R_ABS, ctx.target->symbolicRel, off, 0, &sym});
   else
     addRelativeReloc(ctx, *ctx.in.got, off, sym, 0, R_ABS,
@@ -810,7 +810,7 @@ static void addGotAuthEntry(Ctx &ctx, Symbol &sym) {
 static void addTpOffsetGotEntry(Ctx &ctx, Symbol &sym) {
   ctx.in.got->addEntry(sym);
   uint64_t off = sym.getGotOffset(ctx);
-  if (!sym.isPreemptible && !ctx.arg.shared) {
+  if (!sym.isPreemptible && !ctx.arg.getShared()) {
     ctx.in.got->addConstant({R_TPREL, ctx.target->symbolicRel, off, 0, &sym});
     return;
   }
@@ -863,7 +863,7 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type,
   // These never do, except if the entire file is position dependent or if
   // only the low bits are used.
   if (e == R_GOT || e == R_PLT)
-    return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.isPic;
+    return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.getIsPic();
   // R_AARCH64_AUTH_ABS64 requires a dynamic relocation unless the symbol is
   // non-preemptible and undefined.
   if (e == RE_AARCH64_AUTH && (!sym.isUndefined() || sym.isPreemptible))
@@ -878,8 +878,8 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type,
   // IRELATIVE). Emitting dynamic relocations for -shared aligns with its -z
   // undefs default. Dynamic -no-pie linking and -pie allow flexibility.
   if (sym.isPreemptible)
-    return sym.isUndefined() && !ctx.arg.isPic;
-  if (!ctx.arg.isPic)
+    return sym.isUndefined() && !ctx.arg.getIsPic();
+  if (!ctx.arg.getIsPic())
     return true;
 
   // Constant when referencing a non-preemptible symbol.
@@ -951,7 +951,7 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
 
   // We were asked not to generate PLT entries for ifuncs. Instead, pass the
   // direct relocation on through.
-  if (LLVM_UNLIKELY(isIfunc) && ctx.arg.zIfuncNoplt) {
+  if (LLVM_UNLIKELY(isIfunc) && ctx.arg.getZIfuncNoplt()) {
     std::lock_guard<std::mutex> lock(ctx.relocMutex);
     sym.isExported = true;
     ctx.in.relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
@@ -1003,7 +1003,7 @@ void RelocScan::processAux(RelExpr expr, RelType type, uint64_t offset,
   // For MIPS, we don't implement GNU ld's DW_EH_PE_absptr to DW_EH_PE_pcrel
   // conversion. We still emit a dynamic relocation.
   bool canWrite = (sec->flags & SHF_WRITE) ||
-                  !(ctx.arg.zText ||
+                  !(ctx.arg.getZText() ||
                     (isa<EhInputSection>(sec) && ctx.arg.emachine != EM_MIPS));
   if (canWrite) {
     RelType rel = ctx.target->getDynRel(type);
@@ -1062,7 +1062,7 @@ void RelocScan::processAux(RelExpr expr, RelType type, uint64_t offset,
   // STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO.
   // Copy relocations/canonical PLT entries are unsupported for
   // R_AARCH64_AUTH_ABS64.
-  if (!ctx.arg.shared && sym.isShared() &&
+  if (!ctx.arg.getShared() && sym.isShared() &&
       !(ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64)) {
     if (!canDefineSymbolInExecutable(ctx, sym)) {
       auto diag = Err(ctx);
@@ -1114,7 +1114,7 @@ void RelocScan::processAux(RelExpr expr, RelType type, uint64_t offset,
     // * If a library definition gets preempted to the executable, it will have
     //   the wrong ebx value.
     if (sym.isFunc()) {
-      if (ctx.arg.pie && ctx.arg.emachine == EM_386) {
+      if (ctx.arg.getPie() && ctx.arg.emachine == EM_386) {
         auto diag = Err(ctx);
         diag << "symbol '" << &sym
              << "' cannot be preempted; recompile with -fPIE";
@@ -1252,7 +1252,7 @@ static bool handleNonPreemptibleIfunc(Ctx &ctx, Symbol &sym, uint16_t flags) {
   //
   // Note: IRELATIVE relocations are needed even in static executables; see
   // `addRelIpltSymbols`.
-  if (!sym.isGnuIFunc() || sym.isPreemptible || ctx.arg.zIfuncNoplt)
+  if (!sym.isGnuIFunc() || sym.isPreemptible || ctx.arg.getZIfuncNoplt())
     return false;
   // Skip unreferenced non-preemptible ifunc.
   if (!(flags & (NEEDS_GOT | NEEDS_GOT_AUTH | NEEDS_PLT | HAS_DIRECT_RELOC)))
@@ -1390,7 +1390,7 @@ void elf::postScanRelocations(Ctx &ctx) {
         ctx.in.relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *got,
                                        offsetOff, sym);
       } else {
-        if (ctx.arg.shared)
+        if (ctx.arg.getShared())
           ctx.in.relaDyn->addReloc({ctx.target->tlsModuleIndexRel, got, off});
         else
           // Write one to the GOT slot.
@@ -1414,7 +1414,7 @@ void elf::postScanRelocations(Ctx &ctx) {
 
   GotSection *got = ctx.in.got.get();
   if (ctx.needsTlsLd.load(std::memory_order_relaxed) && got->addTlsIndex()) {
-    if (ctx.arg.shared)
+    if (ctx.arg.getShared())
       ctx.in.relaDyn->addReloc(
           {ctx.target->tlsModuleIndexRel, got, got->getTlsIndexOff()});
     else
@@ -1435,7 +1435,7 @@ void elf::postScanRelocations(Ctx &ctx) {
   if (needsTlsIe)
     ctx.hasTlsIe.store(true, std::memory_order_relaxed);
 
-  if (ctx.arg.branchToBranch)
+  if (ctx.arg.getBranchToBranch())
     ctx.target->applyBranchToBranchOpt();
 }
 
@@ -1801,7 +1801,7 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *os,
                        isd->sections.back()->getSize() -
                        isd->sections.front()->outSecOff;
     if (os->size > ctx.target->getThunkSectionSpacing() && isdSize > 4096)
-      ts->roundUpSizeForErrata = true;
+      ts->setRoundUpSizeForErrata(true);
   }
   isd->thunkSections.push_back({ts, pass});
   return ts;
@@ -1820,7 +1820,7 @@ static bool isThunkSectionCompatible(InputSection *source, Thunk &thunk) {
 
   // Thunks in a different Overlay Output Section can't be reused
   // as we can't guarantee that the Overlay will be in memory.
-  return (sourceOS == targetOS || !targetOS->inOverlay);
+  return (sourceOS == targetOS || !targetOS->getInOverlay());
 }
 
 std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
@@ -2008,7 +2008,7 @@ bool ThunkCreator::createThunks(uint32_t pass,
 }
 
 static bool matchesRefTo(const NoCrossRefCommand &cmd, StringRef osec) {
-  if (cmd.toFirst)
+  if (cmd.toFirst())
     return cmd.outputSections[0] == osec;
   return llvm::is_contained(cmd.outputSections, osec);
 }
@@ -2017,7 +2017,7 @@ template <class ELFT, class Rels>
 static void scanCrossRefs(Ctx &ctx, const NoCrossRefCommand &cmd,
                           OutputSection *osec, InputSection *sec, Rels rels) {
   for (const auto &r : rels) {
-    Symbol &sym = sec->file->getSymbol(r.getSymbol(ctx.arg.isMips64EL));
+    Symbol &sym = sec->file->getSymbol(r.getSymbol(ctx.arg.getIsMips64EL()));
     // A legal cross-reference is when the destination output section is
     // nullptr, osec for a self-reference, or a section that is described by the
     // NOCROSSREFS/NOCROSSREFS_TO command.
@@ -2042,7 +2042,7 @@ template <class ELFT> void elf::checkNoCrossRefs(Ctx &ctx) {
   for (OutputSection *osec : ctx.outputSections) {
     for (const NoCrossRefCommand &noxref : ctx.script->noCrossRefs) {
       if (!llvm::is_contained(noxref.outputSections, osec->name) ||
-          (noxref.toFirst && noxref.outputSections[0] == osec->name))
+          (noxref.toFirst() && noxref.outputSections[0] == osec->name))
         continue;
       for (SectionCommand *cmd : osec->commands) {
         auto *isd = dyn_cast<InputSectionDescription>(cmd);
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 0c54fde488292..7e6962d960e4f 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -306,7 +306,7 @@ void ScriptParser::readDefsym() {
 
 void ScriptParser::readNoCrossRefs(bool to) {
   expect("(");
-  NoCrossRefCommand cmd{{}, to};
+  NoCrossRefCommand cmd(to);
   while (auto tok = till(")"))
     cmd.outputSections.push_back(unquote(tok));
   if (cmd.outputSections.size() < 2)
@@ -502,11 +502,11 @@ void ScriptParser::readOutputFormat() {
   if (!consume(")")) {
     expect(",");
     StringRef tmp = readName();
-    if (ctx.arg.optEB)
+    if (ctx.arg.getOptEB())
       s = tmp;
     expect(",");
     tmp = readName();
-    if (ctx.arg.optEL)
+    if (ctx.arg.getOptEL())
       s = tmp;
     consume(")");
   }
@@ -516,7 +516,7 @@ void ScriptParser::readOutputFormat() {
   ctx.arg.bfdname = s;
 
   if (s == "binary") {
-    ctx.arg.oFormatBinary = true;
+    ctx.arg.setOFormatBinary(true);
     return;
   }
 
@@ -573,7 +573,7 @@ void ScriptParser::readRegionAlias() {
 void ScriptParser::readSearchDir() {
   expect("(");
   StringRef name = readName();
-  if (!ctx.arg.nostdlib)
+  if (!ctx.arg.getNostdlib())
     ctx.arg.searchPaths.push_back(name);
   expect(")");
 }
@@ -605,14 +605,14 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
       osd->osec.lmaExpr = lmaExpr;
       // Use first section address for subsequent sections. Ensure the first
       // section, even if empty, is not discarded.
-      osd->osec.usedInExpression = true;
+      osd->osec.setUsedInExpression(true);
       addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
     }
     v.push_back(osd);
     prev = &osd->osec;
   }
   if (!v.empty())
-    static_cast<OutputDesc *>(v.front())->osec.firstInOverlay = true;
+    static_cast<OutputDesc *>(v.front())->osec.setFirstInOverlay(true);
   if (consume(">")) {
     StringRef regionName = readName();
     for (SectionCommand *od : v)
@@ -682,16 +682,16 @@ void ScriptParser::readSections() {
 
   // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
   // the relro fields should be cleared.
-  if (!ctx.script->seenRelroEnd)
+  if (!ctx.script->getSeenRelroEnd())
     for (SectionCommand *cmd : v)
       if (auto *osd = dyn_cast<OutputDesc>(cmd))
-        osd->osec.relro = false;
+        osd->osec.setRelro(false);
 
   ctx.script->sectionCommands.insert(ctx.script->sectionCommands.end(),
                                      v.begin(), v.end());
 
   if (atEOF() || !consume("INSERT")) {
-    ctx.script->hasSectionsCommand = true;
+    ctx.script->setHasSectionsCommand(true);
     return;
   }
 
@@ -955,7 +955,7 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
 
   if (consume("NOLOAD")) {
     cmd->type = SHT_NOBITS;
-    cmd->typeIsSet = true;
+    cmd->setTypeIsSet(true);
   } else if (consume("TYPE")) {
     expect("=");
     StringRef value = peek();
@@ -970,10 +970,10 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
       // Otherwise, read an expression.
       cmd->type = readExpr()().getValue();
     }
-    cmd->typeIsSet = true;
+    cmd->setTypeIsSet(true);
   } else {
     skip(); // This is "COPY", "INFO" or "OVERLAY".
-    cmd->nonAlloc = true;
+    cmd->setNonAlloc(true);
   }
   expect(")");
   return true;
@@ -1024,7 +1024,7 @@ static Expr checkAlignment(Ctx &ctx, Expr e, std::string &loc) {
 OutputDesc *ScriptParser::readOverlaySectionDescription() {
   OutputDesc *osd =
       ctx.script->createOutputSection(readName(), getCurrentLocation());
-  osd->osec.inOverlay = true;
+  osd->osec.setInOverlay(true);
   expect("{");
   while (auto tok = till("}"))
     readOutputSectionStmt(osd->osec, tok);
@@ -1037,7 +1037,8 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
       ctx.script->createOutputSection(unquote(outSec), getCurrentLocation());
   OutputSection *osec = &cmd->osec;
   // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
-  osec->relro = ctx.script->seenDataAlign && !ctx.script->seenRelroEnd;
+  osec->setRelro(ctx.script->getSeenDataAlign() &&
+                 !ctx.script->getSeenRelroEnd());
 
   size_t symbolsReferenced = ctx.script->referencedSymbols.size();
 
@@ -1087,7 +1088,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
   consume(",");
 
   if (ctx.script->referencedSymbols.size() > symbolsReferenced)
-    osec->expressionsUseSymbols = true;
+    osec->setExpressionsUseSymbols(true);
   return cmd;
 }
 
@@ -1190,7 +1191,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
 
   const char *oldS = prevTok.data();
   SymbolAssignment *cmd = nullptr;
-  bool savedSeenRelroEnd = ctx.script->seenRelroEnd;
+  bool savedSeenRelroEnd = ctx.script->getSeenRelroEnd();
   const StringRef op = peek();
   {
     SaveAndRestore saved(lexState, State::Expr);
@@ -1210,7 +1211,8 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
   }
 
   if (cmd) {
-    cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && ctx.script->seenRelroEnd;
+    cmd->dataSegmentRelroEnd =
+        !savedSeenRelroEnd && ctx.script->getSeenRelroEnd();
     cmd->commandString = StringRef(oldS, curTok.data() - oldS).str();
     squeezeSpaces(cmd->commandString);
     expect(";");
@@ -1495,7 +1497,7 @@ StringRef ScriptParser::readParenName() {
 
 static void checkIfExists(LinkerScript &script, const OutputSection &osec,
                           StringRef location) {
-  if (osec.location.empty() && script.errorOnMissingSection)
+  if (osec.location.empty() && script.getErrorOnMissingSection())
     script.recordError(location + ": undefined section " + osec.name);
 }
 
@@ -1541,7 +1543,7 @@ Expr ScriptParser::readPrimary() {
   if (tok == "ADDR") {
     StringRef name = readParenName();
     OutputSection *osec = &ctx.script->getOrCreateOutputSection(name)->osec;
-    osec->usedInExpression = true;
+    osec->setUsedInExpression(true);
     return [=, s = ctx.script]() -> ExprValue {
       checkIfExists(*s, *osec, location);
       return {osec, false, 0, location};
@@ -1583,7 +1585,7 @@ Expr ScriptParser::readPrimary() {
     expect(",");
     readExpr();
     expect(")");
-    ctx.script->seenDataAlign = true;
+    ctx.script->setSeenDataAlign(true);
     return [=, s = ctx.script] {
       uint64_t align = std::max(uint64_t(1), e().getValue());
       return (s->getDot() + align - 1) & -align;
@@ -1604,7 +1606,7 @@ Expr ScriptParser::readPrimary() {
     expect(",");
     readExpr();
     expect(")");
-    ctx.script->seenRelroEnd = true;
+    ctx.script->setSeenRelroEnd(true);
     return [&ctx = this->ctx] {
       return alignToPowerOf2(ctx.script->getDot(), ctx.arg.maxPageSize);
     };
@@ -1631,7 +1633,7 @@ Expr ScriptParser::readPrimary() {
   if (tok == "LOADADDR") {
     StringRef name = readParenName();
     OutputSection *osec = &ctx.script->getOrCreateOutputSection(name)->osec;
-    osec->usedInExpression = true;
+    osec->setUsedInExpression(true);
     return [=, s = ctx.script] {
       checkIfExists(*s, *osec, location);
       return osec->getLMA();
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index d9ced6f24bd8b..21bcf4120f002 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -49,7 +49,7 @@ void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
     // keep sym if it was defined, otherwise it's unused and can be dropped.
     sym->isUsedInRegularObj = false;
 
-  if (ctx.hasDynDbg) {
+  if (ctx.getHasDynDbg()) {
     if (sym->isDynDbgRef)
       wrap->isDynDbgRef = true;
     if (real->isDynDbgRef)
@@ -222,7 +222,7 @@ void SymbolTable::scanVersionScript() {
       found |= !findByVersion({(pat.name + "@" + v.name).toStringRef(buf),
                                pat.isExternCpp, /*hasWildCard=*/false})
                     .empty();
-      if (!found && !ctx.arg.undefinedVersion)
+      if (!found && !ctx.arg.getUndefinedVersion())
         Err(ctx) << "version script assignment of '" << ver << "' to symbol '"
                  << pat.name << "' failed: symbol not defined";
     };
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index e7b8153ca36b2..6fd6eab3ce11f 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -127,7 +127,7 @@ static uint64_t getSymVA(Ctx &ctx, const Symbol &sym, int64_t addend) {
         ((sym.stOther & STO_MIPS_MICROMIPS) || sym.hasFlag(NEEDS_COPY)))
       va |= 1;
 
-    if (d.isTls() && !ctx.arg.relocatable) {
+    if (d.isTls() && !ctx.arg.getRelocatable()) {
       // Use the address of the TLS segment's first section rather than the
       // segment's address, because segment addresses aren't initialized until
       // after sections are finalized. (e.g. Measuring the size of .rela.dyn
@@ -274,14 +274,14 @@ void Symbol::parseSymbolVersion(Ctx &ctx) {
   // so we do not report error in this case. We also do not error
   // if the symbol has a local version as it won't be in the dynamic
   // symbol table.
-  if (ctx.arg.shared && versionId != VER_NDX_LOCAL)
+  if (ctx.arg.getShared() && versionId != VER_NDX_LOCAL)
     ErrAlways(ctx) << file << ": symbol " << s << " has undefined version "
                    << verstr;
 }
 
 void Symbol::extract(Ctx &ctx) const {
-  assert(file->lazy);
-  file->lazy = false;
+  assert(file->getLazy());
+  file->setLazy(false);
   parseFile(ctx, file);
 }
 
@@ -368,14 +368,14 @@ bool elf::computeIsPreemptible(Ctx &ctx, const Symbol &sym) {
   if (!sym.isDefined())
     return !sym.isUndefined() || ctx.arg.zDynamicUndefined;
 
-  if (!ctx.arg.shared)
+  if (!ctx.arg.getShared())
     return false;
 
   // If -Bsymbolic or --dynamic-list is specified, or -Bsymbolic-functions is
   // specified and the symbol is STT_FUNC, the symbol is preemptible iff it is
   // in the dynamic list. -Bsymbolic-non-weak-functions is a non-weak subset of
   // -Bsymbolic-functions.
-  if (ctx.arg.symbolic ||
+  if (ctx.arg.getSymbolic() ||
       (ctx.arg.bsymbolic == BsymbolicKind::NonWeak &&
        sym.binding != STB_WEAK) ||
       (ctx.arg.bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
@@ -498,7 +498,8 @@ void Symbol::resolve(Ctx &ctx, const Undefined &other) {
     // A forms group 0. B form group 1. C and D (including their member object
     // files) form group 2. E forms group 3. I think that you can see how this
     // group assignment rule simulates the traditional linker's semantics.
-    bool backref = ctx.arg.warnBackrefs && file->groupId < other.file->groupId;
+    bool backref =
+        ctx.arg.getWarnBackrefs() && file->groupId < other.file->groupId;
     extract(ctx);
 
     if (!ctx.arg.whyExtract.empty())
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f59e676c2e6f5..9baf14fdbfd3f 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -55,11 +55,11 @@ using llvm::support::endian::write32le;
 using llvm::support::endian::write64le;
 
 static uint64_t readUint(Ctx &ctx, uint8_t *buf) {
-  return ctx.arg.is64 ? read64(ctx, buf) : read32(ctx, buf);
+  return ctx.arg.getIs64() ? read64(ctx, buf) : read32(ctx, buf);
 }
 
 static void writeUint(Ctx &ctx, uint8_t *buf, uint64_t val) {
-  if (ctx.arg.is64)
+  if (ctx.arg.getIs64())
     write64(ctx, buf, val);
   else
     write32(ctx, buf, val);
@@ -108,7 +108,7 @@ Defined *elf::addSyntheticLocal(Ctx &ctx, StringRef name, uint8_t type,
   if (ctx.in.symTab)
     ctx.in.symTab->addSymbol(s);
 
-  if (ctx.arg.emachine == EM_ARM && !ctx.arg.isLE && ctx.arg.armBe8 &&
+  if (ctx.arg.emachine == EM_ARM && !ctx.arg.getIsLE() && ctx.arg.getArmBe8() &&
       (section.flags & SHF_EXECINSTR))
     // Adding Linker generated mapping symbols to the arm specific mapping
     // symbols list.
@@ -177,7 +177,7 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
     write32(ctx, buf + offset + 0, featureAndType);      // Feature type
     write32(ctx, buf + offset + 4, 4);                   // Feature size
     write32(ctx, buf + offset + 8, ctx.arg.andFeatures); // Feature flags
-    if (ctx.arg.is64)
+    if (ctx.arg.getIs64())
       write32(ctx, buf + offset + 12, 0); // Padding
     offset += 16;
   }
@@ -193,7 +193,7 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
 size_t GnuPropertySection::getSize() const {
   uint32_t contentSize = 0;
   if (ctx.arg.andFeatures != 0)
-    contentSize += ctx.arg.is64 ? 16 : 12;
+    contentSize += ctx.arg.getIs64() ? 16 : 12;
   if (ctx.aarch64PauthAbiCoreInfo)
     contentSize += 4 + 4 + AArch64PauthAbiCoreInfo::size();
   assert(contentSize != 0);
@@ -395,7 +395,7 @@ void EhFrameSection::writeTo(uint8_t *buf) {
     return;
 
   // Write the .eh_frame_hdr section using cached FDE data from updateAllocSize.
-  bool large = hdr->large;
+  bool large = hdr->getLarge();
   int64_t ehFramePtr = getParent()->addr - hdr->getVA() - 4;
   auto writeField = [&](uint8_t *buf, uint64_t val) {
     large ? write64(ctx, buf, val) : write32(ctx, buf, val);
@@ -438,7 +438,7 @@ void EhFrameHeader::finalizeContents() {
   // Initially `large` is false; updateAllocSize may set it to true if addresses
   // exceed the 32-bit range, then call finalizeContents again.
   auto numFdes = ctx.in.ehFrame->numFdes;
-  size = 4 + (large ? 8 : 4) + 4 + numFdes * (large ? 16 : 8);
+  size = 4 + (getLarge() ? 8 : 4) + 4 + numFdes * (getLarge() ? 16 : 8);
 }
 
 bool EhFrameHeader::updateAllocSize(Ctx &ctx) {
@@ -486,7 +486,7 @@ bool EhFrameHeader::updateAllocSize(Ctx &ctx) {
              fdes.end());
   ehFrame->numFdes = fdes.size();
 
-  large = newLarge;
+  setLarge(newLarge);
 
   // Compute size.
   size_t oldSize = size;
@@ -906,7 +906,7 @@ void MipsGotSection::build() {
       // When building a shared library we still need a dynamic relocation
       // for the TP-relative offset as we don't know how much other data will
       // be allocated before us in the static TLS block.
-      if (!s->isPreemptible && !ctx.arg.shared)
+      if (!s->isPreemptible && !ctx.arg.getShared())
         addConstant({R_TPREL, ctx.target->symbolicRel, offset, 0, s});
       else
         ctx.in.relaDyn->addAddendOnlyRelocIfNonPreemptible(
@@ -916,7 +916,7 @@ void MipsGotSection::build() {
       Symbol *s = p.first;
       uint64_t off = p.second * ctx.arg.wordsize;
       if (s == nullptr) {
-        if (ctx.arg.shared)
+        if (ctx.arg.getShared())
           ctx.in.relaDyn->addReloc({ctx.target->tlsModuleIndexRel, this, off});
         else
           addConstant(
@@ -935,7 +935,7 @@ void MipsGotSection::build() {
           ctx.in.relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *this,
                                          offsetOff, *s);
         } else {
-          if (ctx.arg.shared)
+          if (ctx.arg.getShared())
             ctx.in.relaDyn->addReloc(
                 {ctx.target->tlsModuleIndexRel, this, off});
           else
@@ -972,7 +972,7 @@ void MipsGotSection::build() {
       for (size_t pi = 0; pi < pageCount; ++pi) {
         uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize;
         int64_t addend = int64_t(pi * 0x10000);
-        if (!ctx.arg.isPic || &got == primGot)
+        if (!ctx.arg.getIsPic() || &got == primGot)
           addConstant({RE_MIPS_OSEC_LOCAL_PAGE, ctx.target->relativeRel, offset,
                        addend, l.second.repSym});
         else
@@ -986,7 +986,7 @@ void MipsGotSection::build() {
       if (p.first.first == nullptr)
         addConstant({R_ADDEND, ctx.target->relativeRel, offset, p.first.second,
                      ctx.dummySym});
-      else if (!ctx.arg.isPic || &got == primGot)
+      else if (!ctx.arg.getIsPic() || &got == primGot)
         addConstant({R_ABS, ctx.target->relativeRel, offset, p.first.second,
                      p.first.first});
       else
@@ -1000,7 +1000,7 @@ void MipsGotSection::build() {
 bool MipsGotSection::isNeeded() const {
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
-  return !ctx.arg.relocatable;
+  return !ctx.arg.getRelocatable();
 }
 
 uint64_t MipsGotSection::getGp(const InputFile *f) const {
@@ -1112,7 +1112,7 @@ void IgotPltSection::writeTo(uint8_t *buf) {
 StringTableSection::StringTableSection(Ctx &ctx, StringRef name, bool dynamic)
     : SyntheticSection(ctx, name, SHT_STRTAB, dynamic ? (uint64_t)SHF_ALLOC : 0,
                        1),
-      dynamic(dynamic) {
+      strings(decltype(this->strings)::withFlags(unsigned(dynamic))) {
   // ELF string tables start with a NUL byte.
   strings.push_back("");
   stringMap.try_emplace(CachedHashStringRef(""), 0);
@@ -1162,7 +1162,7 @@ DynamicSection<ELFT>::DynamicSection(Ctx &ctx)
   // which passes -z rodynamic.
   // See "Special Section" in Chapter 4 in the following document:
   // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-  if (ctx.arg.emachine == EM_MIPS || ctx.arg.zRodynamic)
+  if (ctx.arg.emachine == EM_MIPS || ctx.arg.getZRodynamic())
     this->flags = SHF_ALLOC;
 }
 
@@ -1220,31 +1220,31 @@ DynamicSection<ELFT>::computeContents() {
   uint32_t dtFlags1 = 0;
   if (ctx.arg.bsymbolic == BsymbolicKind::All)
     dtFlags |= DF_SYMBOLIC;
-  if (ctx.arg.zGlobal)
+  if (ctx.arg.getZGlobal())
     dtFlags1 |= DF_1_GLOBAL;
-  if (ctx.arg.zInitfirst)
+  if (ctx.arg.getZInitfirst())
     dtFlags1 |= DF_1_INITFIRST;
-  if (ctx.arg.zInterpose)
+  if (ctx.arg.getZInterpose())
     dtFlags1 |= DF_1_INTERPOSE;
-  if (ctx.arg.zNodefaultlib)
+  if (ctx.arg.getZNodefaultlib())
     dtFlags1 |= DF_1_NODEFLIB;
-  if (ctx.arg.zNodelete)
+  if (ctx.arg.getZNodelete())
     dtFlags1 |= DF_1_NODELETE;
-  if (ctx.arg.zNodlopen)
+  if (ctx.arg.getZNodlopen())
     dtFlags1 |= DF_1_NOOPEN;
-  if (ctx.arg.pie)
+  if (ctx.arg.getPie())
     dtFlags1 |= DF_1_PIE;
-  if (ctx.arg.zNow) {
+  if (ctx.arg.getZNow()) {
     dtFlags |= DF_BIND_NOW;
     dtFlags1 |= DF_1_NOW;
   }
-  if (ctx.arg.zOrigin) {
+  if (ctx.arg.getZOrigin()) {
     dtFlags |= DF_ORIGIN;
     dtFlags1 |= DF_1_ORIGIN;
   }
-  if (!ctx.arg.zText)
+  if (!ctx.arg.getZText())
     dtFlags |= DF_TEXTREL;
-  if (ctx.hasTlsIe && ctx.arg.shared)
+  if (ctx.hasTlsIe && ctx.arg.getShared())
     dtFlags |= DF_STATIC_TLS;
 
   if (dtFlags)
@@ -1260,7 +1260,8 @@ DynamicSection<ELFT>::computeContents() {
   // systems (currently only Fuchsia OS) provide other means to give the
   // debugger this information. Such systems may choose make .dynamic read-only.
   // If the target is such a system (used -z rodynamic) don't write DT_DEBUG.
-  if (!ctx.arg.shared && !ctx.arg.relocatable && !ctx.arg.zRodynamic)
+  if (!ctx.arg.getShared() && !ctx.arg.getRelocatable() &&
+      !ctx.arg.getZRodynamic())
     addInt(DT_DEBUG, 0);
 
   if (ctx.in.relaDyn->isNeeded()) {
@@ -1268,7 +1269,7 @@ DynamicSection<ELFT>::computeContents() {
     entries.emplace_back(ctx.in.relaDyn->sizeDynamicTag,
                          addRelaSz(ctx, *ctx.in.relaDyn));
 
-    bool isRela = ctx.arg.isRela;
+    bool isRela = ctx.arg.getIsRela();
     addInt(isRela ? DT_RELAENT : DT_RELENT,
            isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
 
@@ -1283,11 +1284,11 @@ DynamicSection<ELFT>::computeContents() {
   }
   if (ctx.in.relrDyn && ctx.in.relrDyn->getParent() &&
       !ctx.in.relrDyn->relocs.empty()) {
-    addInSec(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
+    addInSec(ctx.arg.getUseAndroidRelrTags() ? DT_ANDROID_RELR : DT_RELR,
              *ctx.in.relrDyn);
-    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
+    addInt(ctx.arg.getUseAndroidRelrTags() ? DT_ANDROID_RELRSZ : DT_RELRSZ,
            ctx.in.relrDyn->getParent()->size);
-    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
+    addInt(ctx.arg.getUseAndroidRelrTags() ? DT_ANDROID_RELRENT : DT_RELRENT,
            sizeof(Elf_Relr));
   }
   if (ctx.in.relrAuthDyn && ctx.in.relrAuthDyn->getParent() &&
@@ -1330,10 +1331,10 @@ DynamicSection<ELFT>::computeContents() {
       addInSec(DT_PLTGOT, *ctx.in.gotPlt);
       break;
     }
-    addInt(DT_PLTREL, ctx.arg.isRela ? DT_RELA : DT_REL);
+    addInt(DT_PLTREL, ctx.arg.getIsRela() ? DT_RELA : DT_REL);
   }
 
-  if (ctx.arg.zMarkPlt && ctx.in.plt->isNeeded()) {
+  if (ctx.arg.getZMarkPlt() && ctx.in.plt->isNeeded()) {
     addInSec(DT_X86_64_PLT, *ctx.in.plt);
     addInt(DT_X86_64_PLTSZ, ctx.in.plt->getSize());
     addInt(DT_X86_64_PLTENT, ctx.target->pltEntrySize);
@@ -1342,7 +1343,7 @@ DynamicSection<ELFT>::computeContents() {
   if (ctx.arg.emachine == EM_AARCH64) {
     if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
       addInt(DT_AARCH64_BTI_PLT, 0);
-    if (ctx.arg.zPacPlt)
+    if (ctx.arg.getZPacPlt())
       addInt(DT_AARCH64_PAC_PLT, 0);
 
     if (hasMemtag(ctx)) {
@@ -1362,7 +1363,7 @@ DynamicSection<ELFT>::computeContents() {
   addInt(DT_SYMENT, sizeof(Elf_Sym));
   addInSec(DT_STRTAB, *ctx.in.dynStrTab);
   addInt(DT_STRSZ, ctx.in.dynStrTab->getSize());
-  if (!ctx.arg.zText)
+  if (!ctx.arg.getZText())
     addInt(DT_TEXTREL, 0);
   if (ctx.in.gnuHashTab && ctx.in.gnuHashTab->getParent())
     addInSec(DT_GNU_HASH, *ctx.in.gnuHashTab);
@@ -1417,7 +1418,7 @@ DynamicSection<ELFT>::computeContents() {
       addInt(DT_MIPS_GOTSYM, ctx.in.dynSymTab->getNumSymbols());
     addInSec(DT_PLTGOT, *ctx.in.mipsGot);
     if (ctx.in.mipsRldMap) {
-      if (!ctx.arg.pie)
+      if (!ctx.arg.getPie())
         addInSec(DT_MIPS_RLD_MAP, *ctx.in.mipsRldMap);
       // Store the offset to the .rld_map section
       // relative to the address of the tag.
@@ -1470,7 +1471,7 @@ int64_t DynamicReloc::computeAddend(Ctx &ctx) const {
   assert(!isFinal && "addend already computed");
   uint64_t ca = inputSec->getRelocTargetVA(
       ctx, Relocation{expr, type, 0, addend, sym}, getOffset());
-  return ctx.arg.is64 ? ca : SignExtend64<32>(ca);
+  return ctx.arg.getIs64() ? ca : SignExtend64<32>(ca);
 }
 
 uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
@@ -1592,11 +1593,11 @@ void RelocationBaseSection::computeRels() {
 template <class ELFT>
 RelocationSection<ELFT>::RelocationSection(Ctx &ctx, StringRef name,
                                            bool combreloc, unsigned concurrency)
-    : RelocationBaseSection(ctx, name, ctx.arg.isRela ? SHT_RELA : SHT_REL,
-                            ctx.arg.isRela ? DT_RELA : DT_REL,
-                            ctx.arg.isRela ? DT_RELASZ : DT_RELSZ, combreloc,
-                            concurrency) {
-  this->entsize = ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+    : RelocationBaseSection(ctx, name, ctx.arg.getIsRela() ? SHT_RELA : SHT_REL,
+                            ctx.arg.getIsRela() ? DT_RELA : DT_REL,
+                            ctx.arg.getIsRela() ? DT_RELASZ : DT_RELSZ,
+                            combreloc, concurrency) {
+  this->entsize = ctx.arg.getIsRela() ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 }
 
 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
@@ -1606,10 +1607,10 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
        llvm::concat<const DynamicReloc>(relativeRelocs, relocs)) {
     auto *p = reinterpret_cast<Elf_Rela *>(buf);
     p->r_offset = rel.r_offset;
-    p->setSymbolAndType(rel.r_sym, rel.type, ctx.arg.isMips64EL);
-    if (ctx.arg.isRela)
+    p->setSymbolAndType(rel.r_sym, rel.type, ctx.arg.getIsMips64EL());
+    if (ctx.arg.getIsRela())
       p->r_addend = rel.addend;
-    buf += ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+    buf += ctx.arg.getIsRela() ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   }
 }
 
@@ -1619,7 +1620,7 @@ RelrBaseSection::RelrBaseSection(Ctx &ctx, unsigned concurrency,
           ctx, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn",
           isAArch64Auth
               ? SHT_AARCH64_AUTH_RELR
-              : (ctx.arg.useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR),
+              : (ctx.arg.getUseAndroidRelrTags() ? SHT_ANDROID_RELR : SHT_RELR),
           SHF_ALLOC, ctx.arg.wordsize),
       relocsVec(concurrency) {}
 
@@ -1639,9 +1640,9 @@ template <class ELFT>
 AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
     Ctx &ctx, StringRef name, unsigned concurrency)
     : RelocationBaseSection(
-          ctx, name, ctx.arg.isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
-          ctx.arg.isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
-          ctx.arg.isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
+          ctx, name, ctx.arg.getIsRela() ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
+          ctx.arg.getIsRela() ? DT_ANDROID_RELA : DT_ANDROID_REL,
+          ctx.arg.getIsRela() ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
           /*combreloc=*/false, concurrency) {
   this->entsize = 1;
 }
@@ -1710,7 +1711,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
     Elf_Rela r;
     r.r_offset = rel.getOffset();
     r.setSymbolAndType(rel.getSymIndex(symTab), rel.type, false);
-    r.r_addend = ctx.arg.isRela ? rel.computeAddend(ctx) : 0;
+    r.r_addend = ctx.arg.getIsRela() ? rel.computeAddend(ctx) : 0;
     return r;
   };
   std::vector<Elf_Rela> relatives, nonRelatives;
@@ -1777,9 +1778,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
   for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
     auto j = i + 1;
     while (j != e && i->r_info == j->r_info &&
-           (!ctx.arg.isRela || i->r_addend == j->r_addend))
+           (!ctx.arg.getIsRela() || i->r_addend == j->r_addend))
       ++j;
-    if (j - i < 3 || (ctx.arg.isRela && i->r_addend != 0))
+    if (j - i < 3 || (ctx.arg.getIsRela() && i->r_addend != 0))
       ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), i, j);
     else
       nonRelativeGroups.emplace_back(i, j);
@@ -1792,7 +1793,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
   });
 
   unsigned hasAddendIfRela =
-      ctx.arg.isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
+      ctx.arg.getIsRela() ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
 
   uint64_t offset = 0;
   uint64_t addend = 0;
@@ -1809,7 +1810,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
         RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
     add(g[0].r_offset - offset);
     add(ctx.target->relativeRel);
-    if (ctx.arg.isRela) {
+    if (ctx.arg.getIsRela()) {
       add(g[0].r_addend - addend);
       addend = g[0].r_addend;
     }
@@ -1820,7 +1821,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
         RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
     add(ctx.arg.wordsize);
     add(ctx.target->relativeRel);
-    if (ctx.arg.isRela) {
+    if (ctx.arg.getIsRela()) {
       for (const auto &i : llvm::drop_begin(g)) {
         add(i.r_addend - addend);
         addend = i.r_addend;
@@ -1838,7 +1839,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
     for (Elf_Rela &r : ungroupedRelatives) {
       add(r.r_offset - offset);
       offset = r.r_offset;
-      if (ctx.arg.isRela) {
+      if (ctx.arg.getIsRela()) {
         add(r.r_addend - addend);
         addend = r.r_addend;
       }
@@ -1865,7 +1866,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
       add(r.r_offset - offset);
       offset = r.r_offset;
       add(r.r_info);
-      if (ctx.arg.isRela) {
+      if (ctx.arg.getIsRela()) {
         add(r.r_addend - addend);
         addend = r.r_addend;
       }
@@ -2144,7 +2145,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
   buf += sizeof(Elf_Sym);
 
   auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
-  bool relocatable = ctx.arg.relocatable;
+  bool relocatable = ctx.arg.getRelocatable();
   for (SymbolTableEntry &ent : symbols) {
     Symbol *sym = ent.sym;
     // Set st_name, st_info and st_other.
@@ -2199,7 +2200,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
           eSym->st_other |= STO_MIPS_MICROMIPS;
         }
       }
-      if (ctx.arg.relocatable)
+      if (ctx.arg.getRelocatable())
         if (auto *d = dyn_cast<Defined>(sym))
           if (isMipsPIC<ELFT>(d))
             eSym->st_other |= STO_MIPS_PIC;
@@ -2219,7 +2220,7 @@ void SymtabShndxSection::writeTo(uint8_t *buf) {
   // SHN_XINDEX, we need to write actual index, otherwise, we must write
   // SHN_UNDEF(0).
   buf += 4; // Ignore .symtab[0] entry.
-  bool relocatable = ctx.arg.relocatable;
+  bool relocatable = ctx.arg.getRelocatable();
   for (const SymbolTableEntry &entry : ctx.in.symTab->getSymbols()) {
     if (!getCommonSec(relocatable, entry.sym) &&
         getSymSectionIndex(entry.sym) == SHN_XINDEX)
@@ -2311,7 +2312,7 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
   buf += 16;
 
   // Write the 2-bit bloom filter.
-  const unsigned c = ctx.arg.is64 ? 64 : 32;
+  const unsigned c = ctx.arg.getIs64() ? 64 : 32;
   for (const Entry &sym : symbols) {
     // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in
     // the word using bits [0:5] and [26:31].
@@ -2479,7 +2480,8 @@ size_t PltSection::getSize() const {
 
 bool PltSection::isNeeded() const {
   // For -z retpolineplt, .iplt needs the .plt header.
-  return !entries.empty() || (ctx.arg.zRetpolineplt && ctx.in.iplt->isNeeded());
+  return !entries.empty() ||
+         (ctx.arg.getZRetpolineplt() && ctx.in.iplt->isNeeded());
 }
 
 // Used by ARM to add mapping symbols in the PLT section, which aid
@@ -3657,7 +3659,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
     verneeds.emplace_back();
     Verneed &vn = verneeds.back();
     vn.nameStrTab = ctx.in.dynStrTab->addString(f->soName);
-    bool isLibc = ctx.arg.relrGlibc && f->soName.starts_with("libc.so.");
+    bool isLibc = ctx.arg.getRelrGlibc() && f->soName.starts_with("libc.so.");
     bool isGlibc2 = false;
     for (unsigned i = 0; i != f->verneedInfo.size(); ++i) {
       if (f->verneedInfo[i].id == 0)
@@ -4113,7 +4115,7 @@ ThunkSection::ThunkSection(Ctx &ctx, OutputSection *os, uint64_t off)
 }
 
 size_t ThunkSection::getSize() const {
-  if (roundUpSizeForErrata)
+  if (getRoundUpSizeForErrata())
     return alignTo(size, 4096);
   return size;
 }
@@ -4187,7 +4189,7 @@ bool ThunkSection::assignOffsets() {
 // allocated and filled in by the dynamic linker.
 PPC64LongBranchTargetSection::PPC64LongBranchTargetSection(Ctx &ctx)
     : SyntheticSection(ctx, ".branch_lt",
-                       ctx.arg.isPic ? SHT_NOBITS : SHT_PROGBITS,
+                       ctx.arg.getIsPic() ? SHT_NOBITS : SHT_PROGBITS,
                        SHF_ALLOC | SHF_WRITE, 8) {}
 
 uint64_t PPC64LongBranchTargetSection::getEntryVA(const Symbol *sym,
@@ -4213,7 +4215,7 @@ void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) {
   // If linking non-pic we have the final addresses of the targets and they get
   // written to the table directly. For pic the dynamic linker will allocate
   // the section and fill it.
-  if (ctx.arg.isPic)
+  if (ctx.arg.getIsPic())
     return;
 
   for (auto entry : entries) {
@@ -4236,13 +4238,13 @@ bool PPC64LongBranchTargetSection::isNeeded() const {
   // only gets set to true once `finalizeSections()` is called after thunk
   // creation. Because of this, if we don't create any long-branch thunks we end
   // up with an empty .branch_lt section in the binary.
-  return !finalized || !entries.empty();
+  return !getFinalized() || !entries.empty();
 }
 
 static uint8_t getAbiVersion(Ctx &ctx) {
   // MIPS non-PIC executable gets ABI version 1.
   if (ctx.arg.emachine == EM_MIPS) {
-    if (!ctx.arg.isPic && !ctx.arg.relocatable &&
+    if (!ctx.arg.getIsPic() && !ctx.arg.getRelocatable() &&
         (ctx.arg.eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
       return 1;
     return 0;
@@ -4276,7 +4278,7 @@ template <typename ELFT> void elf::writeEhdr(Ctx &ctx, uint8_t *buf) {
   eHdr->e_phnum = ctx.phdrs.size();
   eHdr->e_shentsize = sizeof(typename ELFT::Shdr);
 
-  if (!ctx.arg.relocatable) {
+  if (!ctx.arg.getRelocatable()) {
     eHdr->e_phoff = sizeof(typename ELFT::Ehdr);
     eHdr->e_phentsize = sizeof(typename ELFT::Phdr);
   }
@@ -4299,7 +4301,7 @@ template <typename ELFT> void elf::writePhdrs(Ctx &ctx, uint8_t *buf) {
 }
 
 static bool needsInterpSection(Ctx &ctx) {
-  return !ctx.arg.relocatable && !ctx.arg.shared &&
+  return !ctx.arg.getRelocatable() && !ctx.arg.getShared() &&
          !ctx.arg.dynamicLinker.empty() && ctx.script->needsInterpSection();
 }
 
@@ -4315,8 +4317,8 @@ bool elf::hasMemtag(Ctx &ctx) {
 // This restriction could be removed in future by re-using some of the ideas
 // that ifuncs use in fully static executables.
 bool elf::canHaveMemtagGlobals(Ctx &ctx) {
-  return hasMemtag(ctx) &&
-         (ctx.arg.relocatable || ctx.arg.shared || needsInterpSection(ctx));
+  return hasMemtag(ctx) && (ctx.arg.getRelocatable() || ctx.arg.getShared() ||
+                            needsInterpSection(ctx));
 }
 
 constexpr char kMemtagAndroidNoteName[] = "Android";
@@ -4486,7 +4488,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
 
   auto add = [&](SyntheticSection &sec) { ctx.inputSections.push_back(&sec); };
 
-  if (ctx.arg.zSectionHeader)
+  if (ctx.arg.getZSectionHeader())
     ctx.in.shStrTab =
         std::make_unique<StringTableSection>(ctx, ".shstrtab", false);
 
@@ -4508,14 +4510,14 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   // .data.rel.ro.bss so that we match in the .data.rel.ro output section.
   // This makes sure our relro is contiguous.
   bool hasDataRelRo =
-      ctx.script->hasSectionsCommand && findSection(ctx, ".data.rel.ro");
+      ctx.script->getHasSectionsCommand() && findSection(ctx, ".data.rel.ro");
   ctx.in.bssRelRo = std::make_unique<BssSection>(
       ctx, hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
   add(*ctx.in.bssRelRo);
 
   ctx.target->initTargetSpecificSections();
 
-  StringRef relaDynName = ctx.arg.isRela ? ".rela.dyn" : ".rel.dyn";
+  StringRef relaDynName = ctx.arg.getIsRela() ? ".rela.dyn" : ".rel.dyn";
 
   const unsigned threadCount = ctx.arg.threadCount;
   do {
@@ -4531,7 +4533,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
     ctx.in.dynSymTab =
         std::make_unique<SymbolTableSection<ELFT>>(ctx, *ctx.in.dynStrTab);
 
-    if (ctx.arg.relocatable)
+    if (ctx.arg.getRelocatable())
       break;
     ctx.in.dynamic = std::make_unique<DynamicSection<ELFT>>(ctx);
 
@@ -4554,7 +4556,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
       ctx.in.relaDyn = std::make_unique<RelocationSection<ELFT>>(
           ctx, relaDynName, /*combreloc=*/true, threadCount);
 
-    if (ctx.hasDynsym) {
+    if (ctx.getHasDynsym()) {
       add(*ctx.in.dynSymTab);
 
       ctx.in.verSym = std::make_unique<VersionTableSection>(ctx);
@@ -4573,7 +4575,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
         add(*ctx.in.gnuHashTab);
       }
 
-      if (ctx.arg.sysvHash) {
+      if (ctx.arg.getSysvHash()) {
         ctx.in.hashTab = std::make_unique<HashTableSection>(ctx);
         add(*ctx.in.hashTab);
       }
@@ -4626,9 +4628,9 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   add(*ctx.in.igotPlt);
   // Add .relro_padding if DATA_SEGMENT_RELRO_END is used; otherwise, add the
   // section in the absence of PHDRS/SECTIONS commands.
-  if (ctx.arg.zRelro &&
-      ((!ctx.script->hasPhdrsCommands() && !ctx.script->hasSectionsCommand) ||
-       ctx.script->seenRelroEnd)) {
+  if (ctx.arg.getZRelro() && ((!ctx.script->hasPhdrsCommands() &&
+                               !ctx.script->getHasSectionsCommand()) ||
+                              ctx.script->getSeenRelroEnd())) {
     ctx.in.relroPadding = std::make_unique<RelroPaddingSection>(ctx);
     add(*ctx.in.relroPadding);
   }
@@ -4645,7 +4647,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   // We always need to add rel[a].plt to output if it has entries.
   // Even for static linking it can contain R_[*]_IRELATIVE relocations.
   ctx.in.relaPlt = std::make_unique<RelocationSection<ELFT>>(
-      ctx, ctx.arg.isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false,
+      ctx, ctx.arg.getIsRela() ? ".rela.plt" : ".rel.plt", /*sort=*/false,
       /*threadCount=*/1);
   add(*ctx.in.relaPlt);
 
@@ -4677,7 +4679,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   // section to control the executable-ness of the stack area, but that
   // is irrelevant these days. Stack area should always be non-executable
   // by default. So we emit this section unconditionally.
-  if (ctx.arg.relocatable) {
+  if (ctx.arg.getRelocatable()) {
     ctx.in.gnuStack = std::make_unique<GnuStackSection>(ctx);
     add(*ctx.in.gnuStack);
   }
@@ -4694,7 +4696,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
   if (ctx.dynDbgOutput) {
     ctx.in.dynDbg = std::make_unique<DynamicDebugSection>(ctx);
     add(*ctx.in.dynDbg);
-    if (!ctx.arg.relocatable) {
+    if (!ctx.arg.getRelocatable()) {
       ctx.in.dynDbgNote = std::make_unique<DynamicDebugNote>(ctx);
       add(*ctx.in.dynDbgNote);
     }
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 85596e1339545..89af2daf75161 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -28,6 +28,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/MC/StringTableBuilder.h"
@@ -105,8 +106,11 @@ class EhFrameHeader final : public SyntheticSection {
 
   // Cached FDE data computed by updateAllocSize, used by
   // EhFrameSection::writeTo.
-  SmallVector<EhFrameSection::FdeData, 0> fdes;
-  bool large = false; // Whether to use sdata8 encoding.
+  llvm::SmallVectorWithFlags<EhFrameSection::FdeData, 0> fdes;
+  bool getLarge() const { return fdes.getFlag(0); }
+  void setLarge(bool Value) {
+    fdes.setFlag(0, Value);
+  } // Whether to use sdata8 encoding.
   size_t size = 0;
 };
 
@@ -415,13 +419,19 @@ class StringTableSection final : public SyntheticSection {
   unsigned addString(StringRef s, bool hashIt = true);
   void writeTo(uint8_t *buf) override;
   size_t getSize() const override { return size; }
-  bool isDynamic() const { return dynamic; }
+  bool isDynamic() const { return getDynamic(); }
 
 private:
-  const bool dynamic;
+  bool getDynamic() const { return strings.getFlag(0); }
 
   llvm::DenseMap<llvm::CachedHashStringRef, unsigned> stringMap;
-  SmallVector<StringRef, 0> strings;
+  llvm::SmallVectorWithFlags<StringRef, 0> strings;
+
+public:
+  StringTableSection(const StringTableSection &) = default;
+  StringTableSection(StringTableSection &&) = default;
+  StringTableSection &operator=(const StringTableSection &) = delete;
+  StringTableSection &operator=(StringTableSection &&) = delete;
 };
 
 class DynamicReloc {
@@ -1247,10 +1257,14 @@ class ThunkSection final : public SyntheticSection {
 
   // When true, round up reported size of section to 4 KiB. See comment
   // in addThunkSection() for more details.
-  bool roundUpSizeForErrata = false;
+  bool getRoundUpSizeForErrata() const { return thunks.getFlag(0); }
+  bool setRoundUpSizeForErrata(bool Value) {
+    thunks.setFlag(0, Value);
+    return Value;
+  }
 
 private:
-  SmallVector<Thunk *, 0> thunks;
+  llvm::SmallVectorWithFlags<Thunk *, 0> thunks;
   size_t size = 0;
 };
 
@@ -1267,12 +1281,13 @@ class PPC64LongBranchTargetSection final : public SyntheticSection {
   size_t getSize() const override;
   void writeTo(uint8_t *buf) override;
   bool isNeeded() const override;
-  void finalizeContents() override { finalized = true; }
+  void finalizeContents() override { setFinalized(true); }
 
 private:
-  SmallVector<std::pair<const Symbol *, int64_t>, 0> entries;
+  llvm::SmallVectorWithFlags<std::pair<const Symbol *, int64_t>, 0> entries;
   llvm::DenseMap<std::pair<const Symbol *, int64_t>, uint32_t> entry_index;
-  bool finalized = false;
+  bool getFinalized() const { return entries.getFlag(0); }
+  void setFinalized(bool Value) { entries.setFlag(0, Value); }
 };
 
 // See the following link for the Android-specific loader code that operates on
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 89e4dbeed3109..abea5923caac2 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -152,7 +152,7 @@ RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend,
 static void relocateImpl(const TargetInfo &target, InputSectionBase &sec,
                          uint64_t secAddr, uint8_t *buf) {
   auto &ctx = target.ctx;
-  const unsigned bits = ctx.arg.is64 ? 64 : 32;
+  const unsigned bits = ctx.arg.getIs64() ? 64 : 32;
   for (const Relocation &rel : sec.relocs()) {
     uint8_t *loc = buf + rel.offset;
     const uint64_t val = SignExtend64(
@@ -177,5 +177,5 @@ uint64_t TargetInfo::getImageBase() const {
   // Use --image-base if set. Fall back to the target default if not.
   if (ctx.arg.imageBase)
     return *ctx.arg.imageBase;
-  return ctx.arg.isPic ? 0 : defaultImageBase;
+  return ctx.arg.getIsPic() ? 0 : defaultImageBase;
 }
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 88d66086a9dcf..020ff0e2d48f1 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -426,7 +426,7 @@ class HexagonThunk : public Thunk {
     alignment = 4;
   }
   uint32_t relOffset;
-  uint32_t size() override { return ctx.arg.isPic ? 12 : 8; }
+  uint32_t size() override { return ctx.arg.getIsPic() ? 12 : 8; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
 };
@@ -485,7 +485,7 @@ class PPC32LongThunk final : public Thunk {
 public:
   PPC32LongThunk(Ctx &ctx, Symbol &dest, int64_t addend)
       : Thunk(ctx, dest, addend) {}
-  uint32_t size() override { return ctx.arg.isPic ? 32 : 16; }
+  uint32_t size() override { return ctx.arg.getIsPic() ? 32 : 16; }
   void writeTo(uint8_t *buf) override;
   void addSymbols(ThunkSection &isec) override;
 };
@@ -1313,7 +1313,7 @@ InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
 void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t p,
                                 uint64_t gotPltVA, const InputFile *file,
                                 std::optional<int64_t> addend) {
-  if (!ctx.arg.isPic) {
+  if (!ctx.arg.getIsPic()) {
     write32(ctx, buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha
     write32(ctx, buf + 4, 0x816b0000 | (uint16_t)gotPltVA); // lwz r11,l(r11)
     write32(ctx, buf + 8, 0x7d6903a6);                      // mtctr r11
@@ -1373,7 +1373,7 @@ void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
   std::string buf;
   raw_string_ostream os(buf);
   os << format_hex_no_prefix(addend, 8);
-  if (!ctx.arg.isPic)
+  if (!ctx.arg.getIsPic())
     os << ".plt_call32.";
   else if (addend >= 0x8000)
     os << ".got2.plt_pic32.";
@@ -1385,7 +1385,7 @@ void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
 
 bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
                                         const Relocation &rel) const {
-  return !ctx.arg.isPic || (isec.file == file && rel.addend == addend);
+  return !ctx.arg.getIsPic() || (isec.file == file && rel.addend == addend);
 }
 
 void PPC32LongThunk::addSymbols(ThunkSection &isec) {
@@ -1397,7 +1397,7 @@ void PPC32LongThunk::writeTo(uint8_t *buf) {
   auto ha = [](uint32_t v) -> uint16_t { return (v + 0x8000) >> 16; };
   auto lo = [](uint32_t v) -> uint16_t { return v; };
   uint32_t d = destination.getVA(ctx, addend);
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     uint32_t off = d - (getThunkTargetSym()->getVA(ctx) + 8);
     write32(ctx, buf + 0, 0x7c0802a6);            // mflr r12,0
     write32(ctx, buf + 4, 0x429f0005);            // bcl r20,r31,.+4
@@ -1507,7 +1507,7 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
                      "R12 setup stub offset");
 
   int nextInstOffset;
-  if (ctx.arg.power10Stubs) {
+  if (ctx.arg.getPower10Stubs()) {
     const uint64_t imm = (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff);
     // pld 12, func at plt@pcrel or  paddi r12, 0, func at pcrel
     writePrefixedInst(ctx, buf,
@@ -1568,7 +1568,7 @@ void HexagonThunk::writeTo(uint8_t *buf) {
   uint64_t s = getHexagonThunkDestVA(ctx, destination, addend);
   uint64_t p = getThunkTargetSym()->getVA(ctx);
 
-  if (ctx.arg.isPic) {
+  if (ctx.arg.getIsPic()) {
     write32(ctx, buf + 0, 0x00004000); // {  immext(#0)
     ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p);
     write32(ctx, buf + 4, 0x6a49c00e); //    r14 = add(pc,##0) }
@@ -1606,7 +1606,7 @@ static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, const InputSection &sec,
   bool mayNeedLandingPad =
       (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) &&
       !isAArch64BTILandingPad(ctx, s, a);
-  if (ctx.arg.picThunk)
+  if (ctx.arg.getPicThunk())
     return std::make_unique<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad);
   if (sec.getParent()->flags & SHF_AARCH64_PURECODE)
     return std::make_unique<AArch64ABSXOLongThunk>(ctx, s, a,
@@ -1631,7 +1631,7 @@ static std::unique_ptr<Thunk> addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s,
   case R_ARM_PLT32:
   case R_ARM_JUMP24:
   case R_ARM_CALL:
-    if (ctx.arg.picThunk) {
+    if (ctx.arg.getPicThunk()) {
       if (thumb_target)
         return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
       return std::make_unique<ARMV4PILongThunk>(ctx, s, a);
@@ -1640,7 +1640,7 @@ static std::unique_ptr<Thunk> addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s,
       return std::make_unique<ARMV4ABSLongBXThunk>(ctx, s, a);
     return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
   case R_ARM_THM_CALL:
-    if (ctx.arg.picThunk) {
+    if (ctx.arg.getPicThunk()) {
       if (thumb_target)
         return std::make_unique<ThumbV4PILongThunk>(ctx, s, a);
       return std::make_unique<ThumbV4PILongBXThunk>(ctx, s, a);
@@ -1667,7 +1667,7 @@ static std::unique_ptr<Thunk> addThunkArmv5v6(Ctx &ctx, RelType reloc,
   case R_ARM_JUMP24:
   case R_ARM_CALL:
   case R_ARM_THM_CALL:
-    if (ctx.arg.picThunk)
+    if (ctx.arg.getPicThunk())
       return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
     return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
   }
@@ -1688,7 +1688,7 @@ static std::unique_ptr<Thunk> addThunkV6M(Ctx &ctx, const InputSection &isec,
   case R_ARM_THM_JUMP19:
   case R_ARM_THM_JUMP24:
   case R_ARM_THM_CALL:
-    if (ctx.arg.isPic) {
+    if (ctx.arg.getIsPic()) {
       if (!isPureCode)
         return std::make_unique<ThumbV6MPILongThunk>(ctx, s, a);
 
@@ -1740,13 +1740,13 @@ static std::unique_ptr<Thunk> addThunkArm(Ctx &ctx, const InputSection &isec,
   case R_ARM_PLT32:
   case R_ARM_JUMP24:
   case R_ARM_CALL:
-    if (ctx.arg.picThunk)
+    if (ctx.arg.getPicThunk())
       return std::make_unique<ARMV7PILongThunk>(ctx, s, a);
     return std::make_unique<ARMV7ABSLongThunk>(ctx, s, a);
   case R_ARM_THM_JUMP19:
   case R_ARM_THM_JUMP24:
   case R_ARM_THM_CALL:
-    if (ctx.arg.picThunk)
+    if (ctx.arg.getPicThunk())
       return std::make_unique<ThumbV7PILongThunk>(ctx, s, a);
     return std::make_unique<ThumbV7ABSLongThunk>(ctx, s, a);
   }
@@ -1827,7 +1827,7 @@ static std::unique_ptr<Thunk> addThunkPPC64(Ctx &ctx, RelType type, Symbol &s,
   if (type == R_PPC64_REL24_NOTOC)
     return std::make_unique<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/false);
 
-  if (ctx.arg.picThunk)
+  if (ctx.arg.getPicThunk())
     return std::make_unique<PPC64PILongBranchThunk>(ctx, s, a);
 
   return std::make_unique<PPC64PDLongBranchThunk>(ctx, s, a);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ae803184918d8..049687f089de6 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -221,7 +221,7 @@ void elf::addReservedSymbols(Ctx &ctx) {
                      STV_HIDDEN);
 
   // If linker script do layout we do not need to create any standard symbols.
-  if (ctx.script->hasSectionsCommand)
+  if (ctx.script->getHasSectionsCommand())
     return;
 
   auto add = [&](StringRef s, int64_t pos) {
@@ -312,7 +312,7 @@ template <class ELFT> void Writer<ELFT>::run() {
   for (OutputSection *sec : ctx.outputSections)
     sec->maybeCompress<ELFT>(ctx);
 
-  if (ctx.script->hasSectionsCommand)
+  if (ctx.script->getHasSectionsCommand())
     ctx.script->allocateHeaders(ctx.phdrs);
 
   // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
@@ -320,7 +320,7 @@ template <class ELFT> void Writer<ELFT>::run() {
   // we know the size of the sections.
   removeEmptyPTLoad(ctx, ctx.phdrs);
 
-  if (!ctx.arg.oFormatBinary)
+  if (!ctx.arg.getOFormatBinary())
     assignFileOffsets();
   else
     assignFileOffsetsBinary();
@@ -333,10 +333,10 @@ template <class ELFT> void Writer<ELFT>::run() {
   writeMapAndCref(ctx);
 
   // Handle --print-memory-usage option.
-  if (ctx.arg.printMemoryUsage)
+  if (ctx.arg.getPrintMemoryUsage())
     ctx.script->printMemoryUsage(ctx.e.outs());
 
-  if (ctx.arg.checkSections)
+  if (ctx.arg.getCheckSections())
     checkSections();
 
   // It does not make sense try to open the file if we have error already.
@@ -350,7 +350,7 @@ template <class ELFT> void Writer<ELFT>::run() {
     if (errCount(ctx))
       return;
 
-    if (!ctx.arg.oFormatBinary) {
+    if (!ctx.arg.getOFormatBinary()) {
       if (ctx.arg.zSeparate != SeparateSegmentKind::None)
         writeTrapInstr();
       writeHeader();
@@ -370,7 +370,7 @@ template <class ELFT> void Writer<ELFT>::run() {
     // Otherwise, with -o -, write to lld::outs() (the stdoutOS argument of
     // link()) instead of committing the buffer, which would write to the
     // process's stdout.
-    if (ctx.inDynDbgLink)
+    if (ctx.getInDynDbgLink())
       ctx.dynDbgOutput = std::move(buffer);
     else if (ctx.arg.outputFile == "-") {
       ctx.e.outs() << StringRef(
@@ -388,7 +388,7 @@ template <class ELFT> void Writer<ELFT>::run() {
 }
 
 static bool retainKeepsInSymtab(Ctx &ctx, const Symbol &sym) {
-  if (sym.hasFlag(USED) && ctx.arg.copyRelocs)
+  if (sym.hasFlag(USED) && ctx.arg.getCopyRelocs())
     return true;
   return ctx.arg.retainSymbols->contains(sym.getName());
 }
@@ -399,7 +399,7 @@ static bool shouldKeepInSymtab(Ctx &ctx, const Defined &sym) {
 
   // If --emit-reloc or -r is given, preserve symbols referenced by relocations
   // from live sections.
-  if (sym.hasFlag(USED) && ctx.arg.copyRelocs)
+  if (sym.hasFlag(USED) && ctx.arg.getCopyRelocs())
     return true;
 
   // Exclude local symbols pointing to .ARM.exidx sections.
@@ -477,7 +477,7 @@ static void demoteAndCopyLocalSymbols(Ctx &ctx) {
     // not attributed to another file's STT_FILE (matching GNU ld).
     // --discard-all discards STT_FILE symbols.
     auto &syms = symsVec[i];
-    if (ctx.arg.relocatable && ctx.arg.discard != DiscardPolicy::All &&
+    if (ctx.arg.getRelocatable() && ctx.arg.discard != DiscardPolicy::All &&
         !syms.empty() &&
         llvm::none_of(syms, [](Symbol *s) { return s->isFile(); })) {
       InputFile *file = ctx.objectFiles[i];
@@ -543,7 +543,7 @@ static bool isRelRoDataSection(Ctx &ctx, StringRef secName) {
     return true;
   // If -z keep-data-section-prefix is specified, additionally allow
   // '.data.rel.ro.hot' and '.data.rel.ro.unlikely'.
-  if (ctx.arg.zKeepDataSectionPrefix)
+  if (ctx.arg.getZKeepDataSectionPrefix())
     return secName == ".hot" || secName == ".unlikely";
   return false;
 }
@@ -555,9 +555,9 @@ static bool isRelRoDataSection(Ctx &ctx, StringRef secName) {
 // This function returns true if a section needs to be put into a
 // PT_GNU_RELRO segment.
 static bool isRelroSection(Ctx &ctx, const OutputSection *sec) {
-  if (!ctx.arg.zRelro)
+  if (!ctx.arg.getZRelro())
     return false;
-  if (sec->relro)
+  if (sec->getRelro())
     return true;
 
   uint64_t flags = sec->flags;
@@ -607,7 +607,7 @@ static bool isRelroSection(Ctx &ctx, const OutputSection *sec) {
   // However, if "-z now" is given, the lazy symbol resolution is
   // disabled, which enables us to put it into RELRO.
   if (sec == ctx.in.gotPlt->getParent())
-    return ctx.arg.zNow;
+    return ctx.arg.getZNow();
 
   if (ctx.in.relroPadding && sec == ctx.in.relroPadding->getParent())
     return true;
@@ -694,9 +694,9 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
     // pressure for absolute relocations referencing small data from -fno-pic
     // relocatable files.
     if (isLarge)
-      rank |= ctx.arg.zLrodataAfterBss ? RF_LARGE_ALT : 0;
+      rank |= ctx.arg.getZLrodataAfterBss() ? RF_LARGE_ALT : 0;
     else
-      rank |= ctx.arg.zLrodataAfterBss ? 0 : RF_LARGE;
+      rank |= ctx.arg.getZLrodataAfterBss() ? 0 : RF_LARGE;
 
     if (osec.name == ".interp")
       rank |= 1;
@@ -727,7 +727,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
     if (!(osec.flags & SHF_TLS))
       rank |= RF_NOT_TLS;
     if (isRelroSection(ctx, &osec))
-      osec.relro = true;
+      osec.setRelro(true);
     else
       rank |= RF_NOT_RELRO;
     // Place .ldata and .lbss after .bss. Making .bss closer to .text
@@ -735,7 +735,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
     // For -z lrodata-after-bss, place .lbss/.lrodata/.ldata after .bss.
     // .bss/.lbss being adjacent reuses the NOBITS size optimization.
     if (isLarge) {
-      rank |= ctx.arg.zLrodataAfterBss
+      rank |= ctx.arg.getZLrodataAfterBss()
                   ? (osec.type == SHT_NOBITS ? 1 : RF_LARGE_ALT)
                   : RF_LARGE;
     }
@@ -809,13 +809,14 @@ void PhdrEntry::add(OutputSection *sec) {
 // processed by the libc runtime. Other executables or DSOs use dynamic tags
 // instead.
 template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
-  if (ctx.arg.isPic)
+  if (ctx.arg.getIsPic())
     return;
 
   // __rela_iplt_{start,end} are initially defined relative to dummy section 0.
   // We'll override ctx.out.elfHeader with relaDyn later when we are sure that
   // .rela.dyn will be present in the output.
-  std::string name = ctx.arg.isRela ? "__rela_iplt_start" : "__rel_iplt_start";
+  std::string name =
+      ctx.arg.getIsRela() ? "__rela_iplt_start" : "__rel_iplt_start";
   ctx.sym.relaIpltStart =
       addOptionalRegular(ctx, name, ctx.out.elfHeader.get(), 0, STV_HIDDEN);
   name.replace(name.size() - 5, 5, "end");
@@ -932,7 +933,7 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
 // countLeadingZeros.
 static int getRankProximity(OutputSection *a, SectionCommand *b) {
   auto *osd = dyn_cast<OutputDesc>(b);
-  return (osd && osd->osec.hasInputSections)
+  return (osd && osd->osec.getHasInputSections())
              ? llvm::countl_zero(a->sortRank ^ osd->osec.sortRank)
              : -1;
 }
@@ -1002,7 +1003,7 @@ findOrphanPos(Ctx &ctx, SmallVectorImpl<SectionCommand *>::iterator b,
 
   auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
     auto *osd = dyn_cast<OutputDesc>(cmd);
-    return osd && osd->osec.hasInputSections;
+    return osd && osd->osec.getHasInputSections();
   };
 
   // Then, scan backward or forward through the script for a suitable insertion
@@ -1087,16 +1088,18 @@ static void maybeShuffle(Ctx &ctx,
 // that don't appear in the order file.
 static DenseMap<const InputSectionBase *, int> buildSectionOrder(Ctx &ctx) {
   DenseMap<const InputSectionBase *, int> sectionOrder;
-  if (ctx.arg.bpStartupFunctionSort || ctx.arg.bpFunctionOrderForCompression ||
-      ctx.arg.bpDataOrderForCompression ||
+  if (ctx.arg.getBpStartupFunctionSort() ||
+      ctx.arg.getBpFunctionOrderForCompression() ||
+      ctx.arg.getBpDataOrderForCompression() ||
       !ctx.arg.bpCompressionSortSpecs.empty()) {
     TimeTraceScope timeScope("Balanced Partitioning Section Orderer");
     sectionOrder = runBalancedPartitioning(
-        ctx, ctx.arg.bpStartupFunctionSort ? ctx.arg.irpgoProfilePath : "",
-        ctx.arg.bpCompressionSortSpecs, ctx.arg.bpFunctionOrderForCompression,
-        ctx.arg.bpDataOrderForCompression,
-        ctx.arg.bpCompressionSortStartupFunctions,
-        ctx.arg.bpVerboseSectionOrderer);
+        ctx, ctx.arg.getBpStartupFunctionSort() ? ctx.arg.irpgoProfilePath : "",
+        ctx.arg.bpCompressionSortSpecs,
+        ctx.arg.getBpFunctionOrderForCompression(),
+        ctx.arg.getBpDataOrderForCompression(),
+        ctx.arg.getBpCompressionSortStartupFunctions(),
+        ctx.arg.getBpVerboseSectionOrderer());
   } else if (!ctx.arg.callGraphProfile.empty()) {
     sectionOrder = computeCallGraphProfileOrder(ctx);
   }
@@ -1246,7 +1249,7 @@ static void sortSection(Ctx &ctx, OutputSection &osec,
       if (auto *isd = dyn_cast<InputSectionDescription>(b))
         sortISDBySectionOrder(ctx, isd, order, osec.flags & SHF_EXECINSTR);
 
-  if (ctx.script->hasSectionsCommand)
+  if (ctx.script->getHasSectionsCommand())
     return;
 
   if (name == ".init_array" || name == ".fini_array") {
@@ -1263,8 +1266,8 @@ static void sortSection(Ctx &ctx, OutputSection &osec,
     auto *isd = cast<InputSectionDescription>(osec.commands[0]);
     llvm::stable_sort(isd->sections,
                       [](const InputSection *a, const InputSection *b) -> bool {
-                        return a->file->ppc64SmallCodeModelTocRelocs &&
-                               !b->file->ppc64SmallCodeModelTocRelocs;
+                        return a->file->getPpc64SmallCodeModelTocRelocs() &&
+                               !b->file->getPpc64SmallCodeModelTocRelocs();
                       });
   }
 }
@@ -1285,7 +1288,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
 
   // Don't sort if using -r. It is not necessary and we want to preserve the
   // relative order for SHF_LINK_ORDER sections.
-  if (ctx.arg.relocatable) {
+  if (ctx.arg.getRelocatable()) {
     ctx.script->adjustOutputSections();
     return;
   }
@@ -1295,7 +1298,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
   for (SectionCommand *cmd : ctx.script->sectionCommands)
     if (auto *osd = dyn_cast<OutputDesc>(cmd))
       osd->osec.sortRank = getSectionRank(ctx, osd->osec);
-  if (!ctx.script->hasSectionsCommand) {
+  if (!ctx.script->getHasSectionsCommand()) {
     // OutputDescs are mostly contiguous, but may be interleaved with
     // SymbolAssignments in the presence of INSERT commands.
     auto mid = std::stable_partition(
@@ -1311,7 +1314,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
   ctx.script->processInsertCommands();
   ctx.script->adjustOutputSections();
 
-  if (ctx.script->hasSectionsCommand)
+  if (ctx.script->getHasSectionsCommand())
     sortOrphanSections();
 
   ctx.script->adjustSectionsAfterSorting();
@@ -1421,7 +1424,7 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
 
     // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
     // this processing inside the ARMExidxsyntheticsection::finalizeContents().
-    if (!ctx.arg.relocatable && ctx.arg.emachine == EM_ARM &&
+    if (!ctx.arg.getRelocatable() && ctx.arg.emachine == EM_ARM &&
         sec->type == SHT_ARM_EXIDX)
       continue;
 
@@ -1509,7 +1512,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   // After the first assignAddresses, only the loop below may change layout.
   if (ctx.arg.randomizeSectionPadding)
     randomizeSectionPadding(ctx);
-  if (ctx.arg.branchToBranch)
+  if (ctx.arg.getBranchToBranch())
     ctx.target->relaxCFIJumpTables();
   ctx.script->assignAddresses();
 
@@ -1527,7 +1530,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   // Iterate until a fixed point is reached, skipping relocatable links since
   // the final addresses are unavailable.
   uint32_t pass = 0, assignPasses = 0;
-  while (!ctx.arg.relocatable) {
+  while (!ctx.arg.getRelocatable()) {
     bool changed = ctx.target->needsThunks
                        ? tc.createThunks(pass, ctx.outputSections)
                        : ctx.target->relaxOnce(pass);
@@ -1628,16 +1631,17 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
     if (errCount(ctx))
       break;
   }
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     ctx.target->finalizeRelax(pass);
 
-  if (ctx.arg.relocatable)
+  if (ctx.arg.getRelocatable())
     for (OutputSection *sec : ctx.outputSections)
       sec->addr = 0;
 
-  uint64_t imageBase = ctx.script->hasSectionsCommand || ctx.arg.relocatable
-                           ? 0
-                           : ctx.target->getImageBase();
+  uint64_t imageBase =
+      ctx.script->getHasSectionsCommand() || ctx.arg.getRelocatable()
+          ? 0
+          : ctx.target->getImageBase();
   for (SectionCommand *cmd : ctx.script->sectionCommands) {
     auto *osd = dyn_cast<OutputDesc>(cmd);
     if (!osd)
@@ -1715,7 +1719,7 @@ static void fixSymbolsAfterShrinking(Ctx &ctx) {
 // relaxation pass does that.  It is only enabled when --optimize-bb-jumps
 // option is used.
 template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
-  assert(ctx.arg.optimizeBBJumps);
+  assert(ctx.arg.getOptimizeBBJumps());
   SmallVector<InputSection *, 0> storage;
 
   ctx.script->assignAddresses();
@@ -1755,7 +1759,7 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
 // Sections that finalizeAddressDependentContent may add to.
 static bool mayGrowLate(Ctx &ctx, SyntheticSection *sec) {
   // relaxOnce may add GOT entries that need relative relocations.
-  if (ctx.arg.isPic && ctx.in.got && ctx.in.got->hasDeferredEntries &&
+  if (ctx.arg.getIsPic() && ctx.in.got && ctx.in.got->hasDeferredEntries &&
       sec == (ctx.in.relrDyn
                   ? static_cast<SyntheticSection *>(ctx.in.relrDyn.get())
                   : ctx.in.relaDyn.get()))
@@ -1766,7 +1770,7 @@ static bool mayGrowLate(Ctx &ctx, SyntheticSection *sec) {
   if (ctx.in.relrAuthDyn && ctx.in.relrAuthDyn->isNeeded())
     return true;
   // PPC64PILongBranchThunk adds a relative relocation for its .branch_lt entry.
-  return ctx.in.ppc64LongBranchTarget && ctx.arg.picThunk;
+  return ctx.in.ppc64LongBranchTarget && ctx.arg.getPicThunk();
 }
 
 // In order to allow users to manipulate linker-synthesized sections,
@@ -1823,7 +1827,7 @@ static void removeUnusedSyntheticSections(Ctx &ctx) {
 
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::finalizeSections() {
-  if (!ctx.arg.relocatable) {
+  if (!ctx.arg.getRelocatable()) {
     ctx.out.preinitArray = findSection(ctx, ".preinit_array");
     ctx.out.initArray = findSection(ctx, ".init_array");
     ctx.out.finiArray = findSection(ctx, ".fini_array");
@@ -1855,14 +1859,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     // value/section does not matter but it has to be relative, so set its
     // st_shndx arbitrarily to 1 (ctx.out.elfHeader).
     if (ctx.arg.emachine == EM_RISCV) {
-      if (!ctx.arg.shared) {
+      if (!ctx.arg.getShared()) {
         OutputSection *sec = findSection(ctx, ".sdata");
         addOptionalRegular(ctx, "__global_pointer$",
                            sec ? sec : ctx.out.elfHeader.get(), 0x800,
                            STV_DEFAULT);
         // Set riscvGlobalPointer to be used by the optional global pointer
         // relaxation.
-        if (ctx.arg.relaxGP) {
+        if (ctx.arg.getRelaxGP()) {
           Symbol *s = ctx.symtab->find("__global_pointer$");
           if (s && s->isDefined())
             ctx.sym.riscvGlobalPointer = cast<Defined>(s);
@@ -1911,14 +1915,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 
   demoteAndCopyLocalSymbols(ctx);
 
-  if (ctx.arg.copyRelocs)
+  if (ctx.arg.getCopyRelocs())
     addSectionSymbols();
 
   // Change values of linker-script-defined symbols from placeholders (assigned
   // by declareSymbols) to actual definitions.
   ctx.script->processSymbolAssignments();
 
-  if (!ctx.arg.relocatable) {
+  if (!ctx.arg.getRelocatable()) {
     llvm::TimeTraceScope timeScope("Scan relocations");
     // Scan relocations. This must be done after every symbol is declared so
     // that we can correctly decide if a dynamic relocation is needed. This is
@@ -1929,7 +1933,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     // Process symbols referenced by the embedded unoptimized part of dynamic
     // debugging. Report references to undefined symbols and ensure that
     // references to shared symbols have PLT/GOT entries as appropriate.
-    if (ctx.hasDynDbg) {
+    if (ctx.getHasDynDbg()) {
       InputSection *unknownSec = make<InputSection>(
           ctx.internalFile, dynDbgSecName, 0, 0, 0, 0, ArrayRef<uint8_t>());
       for (Symbol *sym : ctx.symtab->getSymbols()) {
@@ -2018,7 +2022,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     for (Symbol *sym : ctx.symtab->getSymbols()) {
       if (!sym->isUsedInRegularObj || !includeInSymtab(ctx, *sym))
         continue;
-      if (!ctx.arg.relocatable)
+      if (!ctx.arg.getRelocatable())
         sym->binding = sym->computeBinding(ctx);
       if (ctx.in.symTab &&
           (!ctx.arg.retainSymbols || retainKeepsInSymtab(ctx, *sym)))
@@ -2033,7 +2037,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
             addVerneed(ctx, *sym);
       }
     }
-    if (ctx.in.symTab && !ctx.arg.relocatable)
+    if (ctx.in.symTab && !ctx.arg.getRelocatable())
       ctx.in.symTab->maybeAddSttFile();
   }
 
@@ -2076,7 +2080,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   // Binary and relocatable output does not have PHDRS.
   // The headers have to be created before finalize as that can influence the
   // image base and the dynamic section on mips includes the image base.
-  if (!ctx.arg.relocatable && !ctx.arg.oFormatBinary) {
+  if (!ctx.arg.getRelocatable() && !ctx.arg.getOFormatBinary()) {
     ctx.phdrs = ctx.script->hasPhdrsCommands() ? ctx.script->createPhdrs()
                                                : createPhdrs();
     if (ctx.arg.emachine == EM_ARM) {
@@ -2142,7 +2146,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     finalizeSynthetic(ctx, ctx.in.dynamic.get());
   }
 
-  if (!ctx.script->hasSectionsCommand && !ctx.arg.relocatable)
+  if (!ctx.script->getHasSectionsCommand() && !ctx.arg.getRelocatable())
     fixSectionAlignments();
 
   // This is used to:
@@ -2189,7 +2193,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   // Relaxation to delete inter-basic block jumps created by basic block
   // sections. Run after ctx.in.symTab is finalized as optimizeBasicBlockJumps
   // can relax jump instructions based on symbol offset.
-  if (ctx.arg.optimizeBBJumps)
+  if (ctx.arg.getOptimizeBBJumps())
     optimizeBasicBlockJumps();
 
   // Fill other section headers. The dynamic table is finalized
@@ -2200,7 +2204,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 
   ctx.script->checkFinalScriptConditions();
 
-  if (ctx.arg.emachine == EM_ARM && !ctx.arg.isLE && ctx.arg.armBe8) {
+  if (ctx.arg.emachine == EM_ARM && !ctx.arg.getIsLE() && ctx.arg.getArmBe8()) {
     addArmInputSectionMappingSymbols(ctx);
     sortArmMappingSymbols(ctx);
   }
@@ -2268,7 +2272,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
       Defined *startSym = addOptionalRegular(ctx, start, os, 0);
       Defined *stopSym = addOptionalRegular(ctx, end, os, -1);
       if (startSym || stopSym)
-        os->usedInExpression = true;
+        os->setUsedInExpression(true);
     } else {
       addOptionalRegular(ctx, start, ctx.out.elfHeader.get(), 0);
       addOptionalRegular(ctx, end, ctx.out.elfHeader.get(), 0);
@@ -2301,7 +2305,7 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection &osec) {
   Defined *stopSym = addOptionalRegular(ctx, ss.save("__stop_" + s), &osec, -1,
                                         ctx.arg.zStartStopVisibility);
   if (startSym || stopSym)
-    osec.usedInExpression = true;
+    osec.setUsedInExpression(true);
 }
 
 static bool needsPtLoad(OutputSection *sec) {
@@ -2318,7 +2322,7 @@ static bool needsPtLoad(OutputSection *sec) {
 
 // Adjust phdr flags according to certain options.
 static uint64_t computeFlags(Ctx &ctx, uint64_t flags) {
-  if (ctx.arg.omagic)
+  if (ctx.arg.getOmagic())
     return PF_R | PF_W | PF_X;
   if (ctx.arg.executeOnly && (flags & PF_X))
     return flags & ~PF_R;
@@ -2341,7 +2345,7 @@ SmallVector<std::unique_ptr<PhdrEntry>, 0> Writer<ELFT>::createPhdrs() {
 
   // nmagic or omagic output does not have PT_PHDR, PT_INTERP, or the readonly
   // PT_LOAD.
-  if (!ctx.arg.nmagic && !ctx.arg.omagic) {
+  if (!ctx.arg.nmagic && !ctx.arg.getOmagic()) {
     // The first phdr entry is PT_PHDR which describes the program header
     // itself.
     addHdr(PT_PHDR, PF_R)->add(ctx.out.programHeaders.get());
@@ -2402,11 +2406,11 @@ SmallVector<std::unique_ptr<PhdrEntry>, 0> Writer<ELFT>::createPhdrs() {
     uint64_t incompatible = flags ^ newFlags;
     if (!(newFlags & PF_W)) {
       // When --no-rosegment is specified, RO and RX sections are compatible.
-      if (ctx.arg.singleRoRx)
+      if (ctx.arg.getSingleRoRx())
         incompatible &= ~PF_X;
       // When --no-xosegment is specified (the default), XO and RX sections are
       // compatible.
-      if (ctx.arg.singleXoRx)
+      if (ctx.arg.getSingleXoRx())
         incompatible &= ~PF_R;
     }
     if (incompatible)
@@ -2417,7 +2421,7 @@ SmallVector<std::unique_ptr<PhdrEntry>, 0> Writer<ELFT>::createPhdrs() {
     if (load && !relroEnds.contains(sec) &&
         sec->memRegion == load->firstSec->memRegion &&
         (sameLMARegion || load->lastSec == ctx.out.programHeaders.get()) &&
-        (ctx.script->hasSectionsCommand || sec->type == SHT_NOBITS ||
+        (ctx.script->getHasSectionsCommand() || sec->type == SHT_NOBITS ||
          load->lastSec->type != SHT_NOBITS)) {
       load->p_flags |= newFlags;
     } else {
@@ -2481,14 +2485,14 @@ SmallVector<std::unique_ptr<PhdrEntry>, 0> Writer<ELFT>::createPhdrs() {
 
   // PT_OPENBSD_NOBTCFI is an OpenBSD-specific header to mark that the
   // executable is expected to violate branch-target CFI checks.
-  if (ctx.arg.zNoBtCfi)
+  if (ctx.arg.getZNoBtCfi())
     addHdr(PT_OPENBSD_NOBTCFI, PF_X);
 
   // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
   // is expected to perform W^X violations, such as calling mprotect(2) or
   // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on
   // OpenBSD.
-  if (ctx.arg.zWxneeded)
+  if (ctx.arg.getZWxneeded())
     addHdr(PT_OPENBSD_WXNEEDED, PF_X);
 
   if (OutputSection *cmd = findSection(ctx, ".note.gnu.property"))
@@ -2763,7 +2767,7 @@ static void checkOverlap(Ctx &ctx, StringRef name,
 
     // If both sections are in OVERLAY we allow the overlapping of virtual
     // addresses, because it is what OVERLAY was designed for.
-    if (isVirtualAddr && a.sec->inOverlay && b.sec->inOverlay)
+    if (isVirtualAddr && a.sec->getInOverlay() && b.sec->getInOverlay())
       continue;
 
     Err(ctx) << "section " << a.sec->name << " " << name
@@ -2797,14 +2801,14 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
   std::vector<SectionOffset> fileOffs;
   for (OutputSection *sec : ctx.outputSections)
     if (sec->size > 0 && sec->type != SHT_NOBITS &&
-        (!ctx.arg.oFormatBinary || (sec->flags & SHF_ALLOC)))
+        (!ctx.arg.getOFormatBinary() || (sec->flags & SHF_ALLOC)))
       fileOffs.push_back({sec, sec->offset});
   checkOverlap(ctx, "file", fileOffs, false);
 
   // When linking with -r there is no need to check for overlapping virtual/load
   // addresses since those addresses will only be assigned when the final
   // executable/shared object is created.
-  if (ctx.arg.relocatable)
+  if (ctx.arg.getRelocatable())
     return;
 
   // Checking for overlapping virtual and load addresses only needs to take
@@ -2859,9 +2863,9 @@ static uint64_t getEntryAddr(Ctx &ctx) {
 }
 
 static uint16_t getELFType(Ctx &ctx) {
-  if (ctx.arg.isPic)
+  if (ctx.arg.getIsPic())
     return ET_DYN;
-  if (ctx.arg.relocatable)
+  if (ctx.arg.getRelocatable())
     return ET_REL;
   return ET_EXEC;
 }
@@ -2909,7 +2913,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
 
 // Open a result file.
 template <class ELFT> void Writer<ELFT>::openFile() {
-  uint64_t maxSize = ctx.arg.is64 ? INT64_MAX : UINT32_MAX;
+  uint64_t maxSize = ctx.arg.getIs64() ? INT64_MAX : UINT32_MAX;
   if (fileSize != size_t(fileSize) || maxSize < fileSize) {
     std::string msg;
     raw_string_ostream s(msg);
@@ -2923,7 +2927,7 @@ template <class ELFT> void Writer<ELFT>::openFile() {
 
   unlinkAsync(ctx.arg.outputFile);
   unsigned flags = 0;
-  if (!ctx.arg.relocatable)
+  if (!ctx.arg.getRelocatable())
     flags |= FileOutputBuffer::F_executable;
   if (ctx.arg.mmapOutputFile)
     flags |= FileOutputBuffer::F_mmap;
@@ -3016,7 +3020,7 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
   }
 
   // Finally, check that all dynamic relocation addends were written correctly.
-  if (ctx.arg.checkDynamicRelocs && ctx.arg.writeAddends) {
+  if (ctx.arg.getCheckDynamicRelocs() && ctx.arg.writeAddends) {
     for (OutputSection *sec : ctx.outputSections)
       if (isStaticRelSecType(sec->type))
         sec->checkDynRelAddends(ctx);
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index a939d7789a758..2f482e32b95ad 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/BinaryFormat/MachO.h"
@@ -150,7 +151,10 @@ struct Configuration {
   bool stripSwiftForceLoad = false;
   bool warnDylibInstallName = false;
   bool ignoreOptimizationHints = false;
-  bool forceExactCpuSubtypeMatch = false;
+  bool getForceExactCpuSubtypeMatch() const { return passPlugins.getFlag(0); }
+  void setForceExactCpuSubtypeMatch(bool Value) {
+    passPlugins.setFlag(0, Value);
+  }
   uint32_t headerPad;
   uint32_t dylibCompatibilityVersion = 0;
   uint32_t dylibCurrentVersion = 0;
@@ -186,30 +190,35 @@ struct Configuration {
   bool demangle = false;
   bool deadStrip = false;
   bool interposable = false;
-  bool errorForArchMismatch = false;
-  bool ignoreAutoLink = false;
+  bool getErrorForArchMismatch() const { return passPlugins.getFlag(1); }
+  void setErrorForArchMismatch(bool Value) { passPlugins.setFlag(1, Value); }
+  bool getIgnoreAutoLink() const { return passPlugins.getFlag(2); }
+  void setIgnoreAutoLink(bool Value) { passPlugins.setFlag(2, Value); }
   int readWorkers = 0;
   // ld64 allows invalid auto link options as long as the link succeeds. LLD
   // does not, but there are cases in the wild where the invalid linker options
   // exist. This allows users to ignore the specific invalid options in the case
   // they can't easily fix them.
   llvm::StringSet<> ignoreAutoLinkOptions;
-  bool strictAutoLink = false;
+  bool getStrictAutoLink() const { return passPlugins.getFlag(3); }
+  void setStrictAutoLink(bool Value) { passPlugins.setFlag(3, Value); }
   PlatformInfo platformInfo;
   std::optional<PlatformInfo> secondaryPlatformInfo;
   NamespaceKind namespaceKind = NamespaceKind::twolevel;
   UndefinedSymbolTreatment undefinedSymbolTreatment =
       UndefinedSymbolTreatment::error;
   ICFLevel icfLevel = ICFLevel::none;
-  bool keepICFStabs = false;
+  bool getKeepICFStabs() const { return mllvmOpts.getFlag(0); }
+  void setKeepICFStabs(bool Value) { mllvmOpts.setFlag(0, Value); }
   ObjCStubsMode objcStubsMode = ObjCStubsMode::fast;
   llvm::MachO::HeaderFileType outputType;
   std::vector<llvm::StringRef> systemLibraryRoots;
   std::vector<llvm::StringRef> librarySearchPaths;
   std::vector<llvm::StringRef> frameworkSearchPaths;
-  bool warnDuplicateRpath = true;
-  llvm::SmallVector<llvm::StringRef, 0> runtimePaths;
-  llvm::SmallVector<llvm::StringRef, 0> allowableClients;
+  bool getWarnDuplicateRpath() const { return !mllvmOpts.getFlag(1); }
+  void setWarnDuplicateRpath(bool Value) { mllvmOpts.setFlag(1, !Value); }
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> runtimePaths;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> allowableClients;
   std::vector<std::string> astPaths;
   std::vector<Symbol *> explicitUndefineds;
   llvm::StringSet<> explicitDynamicLookups;
@@ -217,34 +226,80 @@ struct Configuration {
   // so use a vector instead of a map.
   std::vector<SectionAlign> sectionAlignments;
   std::vector<SegmentProtection> segmentProtections;
-  bool ltoDebugPassManager = false;
-  bool emitLLVM = false;
+  bool getLtoDebugPassManager() const { return mllvmOpts.getFlag(2); }
+  void setLtoDebugPassManager(bool Value) { mllvmOpts.setFlag(2, Value); }
+  bool getEmitLLVM() const { return mllvmOpts.getFlag(3); }
+  void setEmitLLVM(bool Value) { mllvmOpts.setFlag(3, Value); }
   llvm::StringRef codegenDataGeneratePath;
-  bool csProfileGenerate = false;
+  bool getCsProfileGenerate() const {
+    return bpCompressionSortSpecs.getFlag(0);
+  }
+  void setCsProfileGenerate(bool Value) {
+    bpCompressionSortSpecs.setFlag(0, Value);
+  }
   llvm::StringRef csProfilePath;
   bool pgoWarnMismatch;
   bool warnThinArchiveMissingMembers;
   bool warnMissingSubsectionsViaSymbols = false;
   bool disableVerify;
-  bool separateCstringLiteralSections;
-  bool tailMergeStrings;
+  bool getSeparateCstringLiteralSections() const {
+    return bpCompressionSortSpecs.getFlag(1);
+  }
+  void setSeparateCstringLiteralSections(bool Value) {
+    bpCompressionSortSpecs.setFlag(1, Value);
+  }
+  bool getTailMergeStrings() const { return bpCompressionSortSpecs.getFlag(2); }
+  void setTailMergeStrings(bool Value) {
+    bpCompressionSortSpecs.setFlag(2, Value);
+  }
   unsigned slopScale = 256;
 
-  bool callGraphProfileSort = false;
+  bool getCallGraphProfileSort() const {
+    return bpCompressionSortSpecs.getFlag(3);
+  }
+  void setCallGraphProfileSort(bool Value) {
+    bpCompressionSortSpecs.setFlag(3, Value);
+  }
   llvm::StringRef printSymbolOrder;
 
   llvm::StringRef irpgoProfilePath;
-  bool bpStartupFunctionSort = false;
-  bool bpCompressionSortStartupFunctions = false;
-  bool bpFunctionOrderForCompression = false;
-  bool bpDataOrderForCompression = false;
-  llvm::SmallVector<BPCompressionSortSpec> bpCompressionSortSpecs;
-  bool bpVerboseSectionOrderer = false;
+  bool getBpStartupFunctionSort() const { return allowableClients.getFlag(0); }
+  void setBpStartupFunctionSort(bool Value) {
+    allowableClients.setFlag(0, Value);
+  }
+  bool getBpCompressionSortStartupFunctions() const {
+    return allowableClients.getFlag(1);
+  }
+  void setBpCompressionSortStartupFunctions(bool Value) {
+    allowableClients.setFlag(1, Value);
+  }
+  bool getBpFunctionOrderForCompression() const {
+    return allowableClients.getFlag(2);
+  }
+  void setBpFunctionOrderForCompression(bool Value) {
+    allowableClients.setFlag(2, Value);
+  }
+  bool getBpDataOrderForCompression() const {
+    return allowableClients.getFlag(3);
+  }
+  void setBpDataOrderForCompression(bool Value) {
+    allowableClients.setFlag(3, Value);
+  }
+  llvm::SmallVectorWithFlags<BPCompressionSortSpec,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 BPCompressionSortSpec>::value,
+                             4>
+      bpCompressionSortSpecs;
+  bool getBpVerboseSectionOrderer() const { return runtimePaths.getFlag(0); }
+  void setBpVerboseSectionOrderer(bool Value) {
+    runtimePaths.setFlag(0, Value);
+  }
 
   SectionRenameMap sectionRenameMap;
   SegmentRenameMap segmentRenameMap;
 
-  bool hasExplicitExports = false;
+  bool getHasExplicitExports() const { return runtimePaths.getFlag(1); }
+  void setHasExplicitExports(bool Value) { runtimePaths.setFlag(1, Value); }
   SymbolPatterns exportedSymbols;
   SymbolPatterns unexportedSymbols;
   SymbolPatterns whyLive;
@@ -253,11 +308,16 @@ struct Configuration {
 
   SymtabPresence localSymbolsPresence = SymtabPresence::All;
   SymbolPatterns localSymbolPatterns;
-  llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
-  llvm::SmallVector<llvm::StringRef, 0> passPlugins;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> mllvmOpts;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> passPlugins;
 
-  bool zeroModTime = true;
-  bool generateUuid = true;
+  bool getZeroModTime() const { return !runtimePaths.getFlag(2); }
+  bool setZeroModTime(bool Value) {
+    runtimePaths.setFlag(2, !Value);
+    return Value;
+  }
+  bool getGenerateUuid() const { return !runtimePaths.getFlag(3); }
+  void setGenerateUuid(bool Value) { runtimePaths.setFlag(3, !Value); }
 
   llvm::StringRef osoPrefix;
 
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 0dfced91c511d..be13618272466 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -580,11 +580,11 @@ static DenseSet<StringRef> loadedObjectFrameworks;
 static void applyDylibMetadata(InputFile *file, bool isNeeded, bool isWeak,
                                bool isReexport) {
   if (auto *dylibFile = dyn_cast_or_null<DylibFile>(file)) {
-    dylibFile->forceNeeded |= isNeeded;
-    dylibFile->forceWeakImport |= isWeak;
+    dylibFile->setForceNeeded(dylibFile->getForceNeeded() | (isNeeded));
+    dylibFile->setForceWeakImport(dylibFile->getForceWeakImport() | (isWeak));
     if (isReexport) {
       config->hasReexports = true;
-      dylibFile->reexport = true;
+      dylibFile->setReexport(true);
     }
   }
 }
@@ -661,7 +661,7 @@ static void addFramework(StringRef name, bool isNeeded, bool isWeak,
 void macho::parseLCLinkerOption(
     llvm::SmallVectorImpl<StringRef> &LCLinkerOptions, InputFile *f,
     unsigned argc, StringRef data) {
-  if (config->ignoreAutoLink)
+  if (config->getIgnoreAutoLink())
     return;
 
   SmallVector<StringRef, 4> argv;
@@ -766,7 +766,7 @@ static bool markReexport(StringRef searchName, ArrayRef<StringRef> extensions) {
       StringRef filename = path::filename(dylibFile->getName());
       if (filename.consume_front(searchName) &&
           (filename.empty() || llvm::is_contained(extensions, filename))) {
-        dylibFile->reexport = true;
+        dylibFile->setReexport(true);
         return true;
       }
     }
@@ -1679,7 +1679,7 @@ static void createAliases() {
 
 static void handleExplicitExports() {
   static constexpr int kMaxWarnings = 3;
-  if (config->hasExplicitExports) {
+  if (config->getHasExplicitExports()) {
     std::atomic<uint64_t> warningsCount{0};
     parallelForEach(symtab->getSymbols(), [&warningsCount](Symbol *sym) {
       if (auto *defined = dyn_cast<Defined>(sym)) {
@@ -1732,7 +1732,7 @@ static SmallVector<StringRef, 0> getRuntimePaths(opt::InputArgList &args) {
     StringRef val = arg->getValue();
     if (seen.insert(val).second)
       vals.push_back(val);
-    else if (config->warnDuplicateRpath)
+    else if (config->getWarnDuplicateRpath())
       warn("duplicate -rpath '" + val + "' ignored [--warn-duplicate-rpath]");
   }
   return vals;
@@ -1957,7 +1957,10 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   config->printEachFile = args.hasArg(OPT_t);
   config->printWhyLoad = args.hasArg(OPT_why_load);
   config->omitDebugInfo = args.hasArg(OPT_S);
-  config->errorForArchMismatch = args.hasArg(OPT_arch_errors_fatal);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_arch_errors_fatal);
+    return config->setErrorForArchMismatch(PackedFlagValue);
+  }();
   if (const Arg *arg = args.getLastArg(OPT_bundle_loader)) {
     if (config->outputType != MH_BUNDLE)
       error("-bundle_loader can only be used with MachO bundle output");
@@ -2009,10 +2012,13 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
           "--thinlto-index-only=");
   }
-  config->warnDuplicateRpath =
-      args.hasFlag(OPT_warn_duplicate_rpath, OPT_no_warn_duplicate_rpath, true);
-  config->runtimePaths = getRuntimePaths(args);
-  config->allowableClients = getAllowableClients(args);
+  [&] {
+    auto PackedFlagValue = args.hasFlag(OPT_warn_duplicate_rpath,
+                                        OPT_no_warn_duplicate_rpath, true);
+    return config->setWarnDuplicateRpath(PackedFlagValue);
+  }();
+  config->runtimePaths.assign(getRuntimePaths(args));
+  config->allowableClients.assign(getAllowableClients(args));
   config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false);
   config->archMultiple = args.hasArg(OPT_arch_multiple);
   config->applicationExtension = args.hasFlag(
@@ -2032,7 +2038,10 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
       config->emitChainedFixups || args.hasArg(OPT_init_offsets);
   config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args);
   config->icfLevel = getICFLevel(args);
-  config->keepICFStabs = args.hasArg(OPT_keep_icf_stabs);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_keep_icf_stabs);
+    return config->setKeepICFStabs(PackedFlagValue);
+  }();
   config->dedupStrings =
       args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true);
   config->dedupSymbolStrings = !args.hasArg(OPT_no_deduplicate_symbol_strings);
@@ -2043,21 +2052,41 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   config->warnDylibInstallName = args.hasFlag(
       OPT_warn_dylib_install_name, OPT_no_warn_dylib_install_name, false);
   config->ignoreOptimizationHints = args.hasArg(OPT_ignore_optimization_hints);
-  config->callGraphProfileSort = args.hasFlag(
-      OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);
+  [&] {
+    auto PackedFlagValue = args.hasFlag(OPT_call_graph_profile_sort,
+                                        OPT_no_call_graph_profile_sort, true);
+    return config->setCallGraphProfileSort(PackedFlagValue);
+  }();
   config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order_eq);
-  config->forceExactCpuSubtypeMatch =
-      getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH");
+  [&] {
+    auto PackedFlagValue = getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH");
+    return config->setForceExactCpuSubtypeMatch(PackedFlagValue);
+  }();
   config->objcStubsMode = getObjCStubsMode(args);
-  config->ignoreAutoLink = args.hasArg(OPT_ignore_auto_link);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_ignore_auto_link);
+    return config->setIgnoreAutoLink(PackedFlagValue);
+  }();
   for (const Arg *arg : args.filtered(OPT_ignore_auto_link_option))
     config->ignoreAutoLinkOptions.insert(arg->getValue());
-  config->strictAutoLink = args.hasArg(OPT_strict_auto_link);
-  config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
-  config->emitLLVM = args.hasArg(OPT_lto_emit_llvm);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_strict_auto_link);
+    return config->setStrictAutoLink(PackedFlagValue);
+  }();
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_lto_debug_pass_manager);
+    return config->setLtoDebugPassManager(PackedFlagValue);
+  }();
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_lto_emit_llvm);
+    return config->setEmitLLVM(PackedFlagValue);
+  }();
   config->codegenDataGeneratePath =
       args.getLastArgValue(OPT_codegen_data_generate_path);
-  config->csProfileGenerate = args.hasArg(OPT_cs_profile_generate);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_cs_profile_generate);
+    return config->setCsProfileGenerate(PackedFlagValue);
+  }();
   config->csProfilePath = args.getLastArgValue(OPT_cs_profile_path);
   config->pgoWarnMismatch =
       args.hasFlag(OPT_pgo_warn_mismatch, OPT_no_pgo_warn_mismatch, true);
@@ -2067,13 +2096,22 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   config->warnMissingSubsectionsViaSymbols =
       args.hasFlag(OPT_warn_missing_subsections_via_symbols,
                    OPT_no_warn_missing_subsections_via_symbols, false);
-  config->generateUuid = !args.hasArg(OPT_no_uuid);
+  [&] {
+    auto PackedFlagValue = !args.hasArg(OPT_no_uuid);
+    return config->setGenerateUuid(PackedFlagValue);
+  }();
   config->disableVerify = args.hasArg(OPT_disable_verify);
-  config->separateCstringLiteralSections =
-      args.hasFlag(OPT_separate_cstring_literal_sections,
-                   OPT_no_separate_cstring_literal_sections, false);
-  config->tailMergeStrings =
-      args.hasFlag(OPT_tail_merge_strings, OPT_no_tail_merge_strings, false);
+  [&] {
+    auto PackedFlagValue =
+        args.hasFlag(OPT_separate_cstring_literal_sections,
+                     OPT_no_separate_cstring_literal_sections, false);
+    return config->setSeparateCstringLiteralSections(PackedFlagValue);
+  }();
+  [&] {
+    auto PackedFlagValue =
+        args.hasFlag(OPT_tail_merge_strings, OPT_no_tail_merge_strings, false);
+    return config->setTailMergeStrings(PackedFlagValue);
+  }();
   if (auto *arg = args.getLastArg(OPT_slop_scale_eq)) {
     StringRef v(arg->getValue());
     unsigned slop = 0;
@@ -2085,7 +2123,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
 
   auto IncompatWithCGSort = [&](StringRef firstArgStr) {
     // Throw an error only if --call-graph-profile-sort is explicitly specified
-    if (config->callGraphProfileSort)
+    if (config->getCallGraphProfileSort())
       if (const Arg *arg = args.getLastArgNoClaim(OPT_call_graph_profile_sort))
         error(firstArgStr + " is incompatible with " + arg->getSpelling());
   };
@@ -2098,27 +2136,30 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
 
   if (const Arg *arg = args.getLastArg(OPT_irpgo_profile_sort)) {
     config->irpgoProfilePath = arg->getValue();
-    config->bpStartupFunctionSort = true;
+    config->setBpStartupFunctionSort(true);
     IncompatWithCGSort(arg->getSpelling());
   }
-  config->bpCompressionSortStartupFunctions =
-      args.hasFlag(OPT_bp_compression_sort_startup_functions,
-                   OPT_no_bp_compression_sort_startup_functions, false);
+  [&] {
+    auto PackedFlagValue =
+        args.hasFlag(OPT_bp_compression_sort_startup_functions,
+                     OPT_no_bp_compression_sort_startup_functions, false);
+    return config->setBpCompressionSortStartupFunctions(PackedFlagValue);
+  }();
   if (const Arg *arg = args.getLastArg(OPT_bp_startup_sort)) {
     StringRef startupSortStr = arg->getValue();
     if (startupSortStr == "function") {
-      config->bpStartupFunctionSort = true;
+      config->setBpStartupFunctionSort(true);
     } else if (startupSortStr != "none") {
       error("unknown value `" + startupSortStr + "` for " + arg->getSpelling());
     }
     if (startupSortStr != "none")
       IncompatWithCGSort(arg->getSpelling());
   }
-  if (!config->bpStartupFunctionSort &&
-      config->bpCompressionSortStartupFunctions)
+  if (!config->getBpStartupFunctionSort() &&
+      config->getBpCompressionSortStartupFunctions())
     error("--bp-compression-sort-startup-functions must be used with "
           "--bp-startup-sort=function");
-  if (config->irpgoProfilePath.empty() && config->bpStartupFunctionSort)
+  if (config->irpgoProfilePath.empty() && config->getBpStartupFunctionSort())
     error("--bp-startup-sort=function must be used with "
           "--irpgo-profile");
   auto addCompressionSortSpec = [&](StringRef value) {
@@ -2168,12 +2209,12 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   if (const Arg *arg = args.getLastArg(OPT_bp_compression_sort)) {
     StringRef compressionSortStr = arg->getValue();
     if (compressionSortStr == "function") {
-      config->bpFunctionOrderForCompression = true;
+      config->setBpFunctionOrderForCompression(true);
     } else if (compressionSortStr == "data") {
-      config->bpDataOrderForCompression = true;
+      config->setBpDataOrderForCompression(true);
     } else if (compressionSortStr == "both") {
-      config->bpFunctionOrderForCompression = true;
-      config->bpDataOrderForCompression = true;
+      config->setBpFunctionOrderForCompression(true);
+      config->setBpDataOrderForCompression(true);
     } else if (compressionSortStr != "none") {
       error("unknown value `" + compressionSortStr + "` for " +
             arg->getSpelling());
@@ -2181,7 +2222,10 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     if (compressionSortStr != "none")
       IncompatWithCGSort(arg->getSpelling());
   }
-  config->bpVerboseSectionOrderer = args.hasArg(OPT_verbose_bp_section_orderer);
+  [&] {
+    auto PackedFlagValue = args.hasArg(OPT_verbose_bp_section_orderer);
+    return config->setBpVerboseSectionOrderer(PackedFlagValue);
+  }();
 
   for (const Arg *arg : args.filtered(OPT_alias)) {
     config->aliasedSymbols.push_back(
@@ -2189,9 +2233,12 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   }
 
   if (const char *zero = getenv("ZERO_AR_DATE"))
-    config->zeroModTime = strcmp(zero, "0") != 0;
+    [&] {
+      auto PackedFlagValue = strcmp(zero, "0") != 0;
+      return config->setZeroModTime(PackedFlagValue);
+    }();
   if (args.getLastArg(OPT_reproducible))
-    config->zeroModTime = true;
+    config->setZeroModTime(true);
 
   std::array<PlatformType, 4> encryptablePlatforms{
       PLATFORM_IOS, PLATFORM_WATCHOS, PLATFORM_TVOS, PLATFORM_XROS};
@@ -2304,14 +2351,17 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     config->segmentProtections.push_back({segName, maxProt, initProt});
   }
 
-  config->hasExplicitExports =
-      args.hasArg(OPT_no_exported_symbols) ||
-      args.hasArgNoClaim(OPT_exported_symbol, OPT_exported_symbols_list);
+  [&] {
+    auto PackedFlagValue =
+        args.hasArg(OPT_no_exported_symbols) ||
+        args.hasArgNoClaim(OPT_exported_symbol, OPT_exported_symbols_list);
+    return config->setHasExplicitExports(PackedFlagValue);
+  }();
   handleSymbolPatterns(args, config->exportedSymbols, OPT_exported_symbol,
                        OPT_exported_symbols_list);
   handleSymbolPatterns(args, config->unexportedSymbols, OPT_unexported_symbol,
                        OPT_unexported_symbols_list);
-  if (config->hasExplicitExports && !config->unexportedSymbols.empty())
+  if (config->getHasExplicitExports() && !config->unexportedSymbols.empty())
     error("cannot use both -exported_symbol* and -unexported_symbol* options");
 
   if (args.hasArg(OPT_no_exported_symbols) && !config->exportedSymbols.empty())
@@ -2439,7 +2489,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
       config->mllvmOpts.emplace_back(arg->getValue());
     }
 
-    config->passPlugins = args::getStrings(args, OPT_load_pass_plugins);
+    config->passPlugins.assign(args::getStrings(args, OPT_load_pass_plugins));
 
     createSyntheticSections();
     createSyntheticSymbols();
@@ -2458,7 +2508,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     // If either --thinlto-index-only or --lto-emit-llvm is given, we should
     // not create object files. Index file creation is already done in
     // compileBitcodeFiles, so we are done if that's the case.
-    if (config->thinLTOIndexOnly || config->emitLLVM)
+    if (config->thinLTOIndexOnly || config->getEmitLLVM())
       return errorCount() == 0;
 
     // LTO may emit a non-hidden (extern) object file symbol even if the
@@ -2500,7 +2550,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     if (!config->codegenDataGeneratePath.empty())
       codegenDataGenerate();
 
-    if (config->callGraphProfileSort)
+    if (config->getCallGraphProfileSort())
       priorityBuilder.extractCallGraphProfile();
 
     if (config->deadStrip)
@@ -2554,7 +2604,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     timeTraceProfilerCleanup();
   }
 
-  if (errorCount() != 0 || config->strictAutoLink)
+  if (errorCount() != 0 || config->getStrictAutoLink())
     for (const auto &warning : missingAutolinkWarnings)
       warn(warning);
 
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index e097d2ce302c3..0ed3de9731900 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -354,7 +354,7 @@ StringRef macho::rerootPath(StringRef path) {
 }
 
 uint32_t macho::getModTime(StringRef path) {
-  if (config->zeroModTime)
+  if (config->getZeroModTime())
     return 0;
 
   fs::file_status stat;
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 09ab6b17cfda9..72eefba931f42 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -192,7 +192,7 @@ static bool compatWithTargetArch(const InputFile *file, const Header *hdr) {
   if (hdr->cputype != cpuType) {
     Architecture arch =
         getArchitectureFromCpuType(hdr->cputype, hdr->cpusubtype);
-    auto msg = config->errorForArchMismatch
+    auto msg = config->getErrorForArchMismatch()
                    ? static_cast<void (*)(const Twine &)>(error)
                    : warn;
 
@@ -395,7 +395,7 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
                segname == segment_names::text) {
       splitEhFrames(data, *sections.back());
     } else if (segname == segment_names::llvm) {
-      if (config->callGraphProfileSort && name == section_names::cgProfile)
+      if (config->getCallGraphProfileSort() && name == section_names::cgProfile)
         checkError(parseCallGraph(data, callGraph));
       // ld64 does not appear to emit contents from sections within the __LLVM
       // segment. Symbols within those sections point to bitcode metadata
@@ -1829,8 +1829,10 @@ void DylibFile::loadReexport(StringRef path, DylibFile *umbrella,
 
 DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
                      bool isBundleLoader, bool explicitlyLinked)
-    : InputFile(DylibKind, mb), refState(RefState::Unreferenced),
-      explicitlyLinked(explicitlyLinked), isBundleLoader(isBundleLoader) {
+    : InputFile(DylibKind, mb),
+      rpaths(decltype(this->rpaths)::withFlags(
+          unsigned(explicitlyLinked) | (unsigned(isBundleLoader) << 1))),
+      refState(RefState::Unreferenced) {
   assert(!isBundleLoader || !umbrella);
   if (umbrella == nullptr)
     umbrella = this;
@@ -1856,7 +1858,7 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
     message(toString(this));
   inputFiles.insert(this);
 
-  deadStrippable = hdr->flags & MH_DEAD_STRIPPABLE_DYLIB;
+  setDeadStrippable(hdr->flags & MH_DEAD_STRIPPABLE_DYLIB);
 
   if (!checkCompatibility(this))
     return;
@@ -2001,7 +2003,7 @@ static bool isTargetPlatformArchCompatible(
   if (is_contained(interfaceTargets, target))
     return true;
 
-  if (config->forceExactCpuSubtypeMatch)
+  if (config->getForceExactCpuSubtypeMatch())
     return false;
 
   ArchitectureSet archSet;
@@ -2016,8 +2018,10 @@ static bool isTargetPlatformArchCompatible(
 
 DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
                      bool isBundleLoader, bool explicitlyLinked)
-    : InputFile(DylibKind, interface), refState(RefState::Unreferenced),
-      explicitlyLinked(explicitlyLinked), isBundleLoader(isBundleLoader) {
+    : InputFile(DylibKind, interface),
+      rpaths(decltype(this->rpaths)::withFlags(
+          unsigned(explicitlyLinked) | (unsigned(isBundleLoader) << 1))),
+      refState(RefState::Unreferenced) {
   // FIXME: Add test for the missing TBD code path.
 
   if (umbrella == nullptr)
@@ -2110,8 +2114,8 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
 }
 
 DylibFile::DylibFile(DylibFile *umbrella)
-    : InputFile(DylibKind, MemoryBufferRef{}), refState(RefState::Unreferenced),
-      explicitlyLinked(false), isBundleLoader(false) {
+    : InputFile(DylibKind, MemoryBufferRef{}),
+      refState(RefState::Unreferenced) {
   if (umbrella == nullptr)
     umbrella = this;
   this->umbrella = umbrella;
@@ -2129,7 +2133,7 @@ void DylibFile::parseReexports(const InterfaceFile &interface) {
 }
 
 bool DylibFile::isExplicitlyLinked() const {
-  if (!explicitlyLinked)
+  if (!getExplicitlyLinkedFlag())
     return false;
 
   // If this dylib was explicitly linked, but at least one of the symbols
@@ -2363,7 +2367,7 @@ static Expected<InputFile *>
 loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
                   uint64_t offsetInArchive, bool forceHidden, bool compatArch,
                   bool lazy) {
-  if (config->zeroModTime)
+  if (config->getZeroModTime())
     modTime = 0;
 
   switch (identify_magic(mb.getBuffer())) {
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index f1cebd10bf76e..4b105526a97b4 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -11,6 +11,7 @@
 
 #include "MachOStructs.h"
 #include "Target.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "lld/Common/DWARF.h"
 #include "lld/Common/LLVM.h"
@@ -235,34 +236,45 @@ class DylibFile final : public InputFile {
   void parseReexports(const llvm::MachO::InterfaceFile &interface);
   bool isReferenced() const { return numReferencedSymbols > 0; }
   bool isExplicitlyLinked() const;
-  void setExplicitlyLinked() { explicitlyLinked = true; }
+  void setExplicitlyLinked() { setExplicitlyLinkedFlag(true); }
 
   static bool classof(const InputFile *f) { return f->kind() == DylibKind; }
 
   StringRef installName;
   DylibFile *exportingFile = nullptr;
   DylibFile *umbrella;
-  SmallVector<StringRef, 2> rpaths;
-  SmallVector<StringRef> allowableClients;
+  llvm::SmallVectorWithFlags<StringRef, 2, 2> rpaths;
+  llvm::SmallVectorWithFlags<
+      StringRef,
+      llvm::CalculateSmallVectorDefaultInlinedElements<StringRef>::value, 4>
+      allowableClients;
   uint32_t compatibilityVersion = 0;
   uint32_t currentVersion = 0;
   int64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
   unsigned numReferencedSymbols = 0;
   RefState refState;
-  bool reexport = false;
-  bool forceNeeded = false;
-  bool forceWeakImport = false;
-  bool deadStrippable = false;
+  bool getReexport() const { return allowableClients.getFlag(0); }
+  void setReexport(bool Value) { allowableClients.setFlag(0, Value); }
+  bool getForceNeeded() const { return allowableClients.getFlag(1); }
+  void setForceNeeded(bool Value) { allowableClients.setFlag(1, Value); }
+  bool getForceWeakImport() const { return allowableClients.getFlag(2); }
+  void setForceWeakImport(bool Value) { allowableClients.setFlag(2, Value); }
+  bool getDeadStrippable() const { return allowableClients.getFlag(3); }
+  void setDeadStrippable(bool Value) { allowableClients.setFlag(3, Value); }
 
 private:
-  bool explicitlyLinked = false; // Access via isExplicitlyLinked().
+  bool getExplicitlyLinkedFlag() const { return rpaths.getFlag(0); }
+  void setExplicitlyLinkedFlag(bool Value) {
+    rpaths.setFlag(0, Value);
+  } // Access via isExplicitlyLinked().
 
 public:
   // An executable can be used as a bundle loader that will load the output
   // file being linked, and that contains symbols referenced, but not
   // implemented in the bundle. When used like this, it is very similar
   // to a dylib, so we've used the same class to represent it.
-  bool isBundleLoader;
+  bool getIsBundleLoader() const { return rpaths.getFlag(1); }
+  void setIsBundleLoader(bool Value) { rpaths.setFlag(1, Value); }
 
   // Synthetic Dylib objects created by $ld$previous symbols in this dylib.
   // Usually empty. These synthetic dylibs won't have synthetic dylibs
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 6ea4b0ddd58e4..19d77715faf0d 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -63,7 +63,7 @@ void lld::macho::addInputSection(InputSection *inputSection) {
     isec->parent = osec;
     inputSections.push_back(isec);
   } else if (auto *isec = dyn_cast<CStringInputSection>(inputSection)) {
-    bool useSectionName = config->separateCstringLiteralSections ||
+    bool useSectionName = config->getSeparateCstringLiteralSections() ||
                           isec->getName() == section_names::objcMethname;
     auto *osec = in.getOrCreateCStringSection(
         useSectionName ? isec->getName() : section_names::cString);
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index 701d81cd5d027..6a55479d366a7 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -55,9 +55,9 @@ static lto::Config createConfig() {
 
   c.TimeTraceEnabled = config->timeTraceEnabled;
   c.TimeTraceGranularity = config->timeTraceGranularity;
-  c.DebugPassManager = config->ltoDebugPassManager;
+  c.DebugPassManager = config->getLtoDebugPassManager();
   c.CSIRProfile = std::string(config->csProfilePath);
-  c.RunCSIRInstr = config->csProfileGenerate;
+  c.RunCSIRInstr = config->getCsProfileGenerate();
   c.PGOWarnMismatch = config->pgoWarnMismatch;
   c.DisableVerify = config->disableVerify;
   c.OptLevel = config->ltoo;
@@ -70,7 +70,7 @@ static lto::Config createConfig() {
     checkError(c.addSaveTemps(config->outputFile.str() + ".",
                               /*UseInputModulePath=*/true));
 
-  if (config->emitLLVM) {
+  if (config->getEmitLLVM()) {
     llvm::StringRef outputFile = config->outputFile;
     c.PreCodeGenModuleHook = [outputFile](size_t task, const Module &m) {
       if (std::unique_ptr<raw_fd_ostream> os = openLTOOutputFile(outputFile))
diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp
index dea47c76a385e..4f77a26116e45 100644
--- a/lld/MachO/SectionPriorities.cpp
+++ b/lld/MachO/SectionPriorities.cpp
@@ -372,17 +372,19 @@ void macho::PriorityBuilder::parseOrderFile(StringRef path) {
 DenseMap<const InputSection *, int>
 macho::PriorityBuilder::buildInputSectionPriorities() {
   DenseMap<const InputSection *, int> sectionPriorities;
-  if (config->bpStartupFunctionSort || config->bpFunctionOrderForCompression ||
-      config->bpDataOrderForCompression ||
+  if (config->getBpStartupFunctionSort() ||
+      config->getBpFunctionOrderForCompression() ||
+      config->getBpDataOrderForCompression() ||
       !config->bpCompressionSortSpecs.empty()) {
     TimeTraceScope timeScope("Balanced Partitioning Section Orderer");
     sectionPriorities = runBalancedPartitioning(
-        config->bpStartupFunctionSort ? config->irpgoProfilePath : "",
-        config->bpCompressionSortSpecs, config->bpFunctionOrderForCompression,
-        config->bpDataOrderForCompression,
-        config->bpCompressionSortStartupFunctions,
-        config->bpVerboseSectionOrderer);
-  } else if (config->callGraphProfileSort) {
+        config->getBpStartupFunctionSort() ? config->irpgoProfilePath : "",
+        config->bpCompressionSortSpecs,
+        config->getBpFunctionOrderForCompression(),
+        config->getBpDataOrderForCompression(),
+        config->getBpCompressionSortStartupFunctions(),
+        config->getBpVerboseSectionOrderer());
+  } else if (config->getCallGraphProfileSort()) {
     // Sort sections by the profile data provided by __LLVM,__cg_profile
     // sections.
     //
diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h
index cdeef93475222..6409e4f6b0e54 100644
--- a/lld/MachO/Symbols.h
+++ b/lld/MachO/Symbols.h
@@ -276,7 +276,7 @@ class DylibSymbol : public Symbol {
   // Symbols from weak libraries/frameworks are also weakly-referenced.
   bool isWeakRef() const override {
     return refState == RefState::Weak ||
-           (file && getFile()->umbrella->forceWeakImport);
+           (file && getFile()->umbrella->getForceWeakImport());
   }
   bool isReferenced() const { return refState != RefState::Unreferenced; }
   bool isTlv() const override { return tlv; }
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index cc7aaa2c7ee9f..5edeee940d7a6 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -1234,7 +1234,7 @@ void SymtabSection::emitStabs() {
 
       // Constant-folded symbols go in the executable's symbol table, but don't
       // get a stabs entry unless --keep-icf-stabs flag is specified.
-      if (!config->keepICFStabs &&
+      if (!config->getKeepICFStabs() &&
           defined->identicalCodeFoldingKind != Symbol::ICFFoldKind::None)
         continue;
 
@@ -1761,7 +1761,7 @@ void DeduplicatedCStringSection::finalizeContents() {
         assert(isec.align != 0);
         auto align = getStringPieceAlignment(isec, piece);
         auto [it, wasInserted] = strToAlignment.try_emplace(s, align);
-        if (config->tailMergeStrings && wasInserted)
+        if (config->getTailMergeStrings() && wasInserted)
           deduplicatedStrs.push_back(s);
         if (!wasInserted && it->second < align)
           it->second = align;
@@ -1812,8 +1812,8 @@ void DeduplicatedCStringSection::finalizeContents() {
     auto s = isec.getCachedHashStringRef(pieceIdx);
     // Any string can be tail merged with itself with an offset of zero
     uint64_t tailMergeOffset = 0;
-    auto mergeIt =
-        config->tailMergeStrings ? tailMergeMap.find(s) : tailMergeMap.end();
+    auto mergeIt = config->getTailMergeStrings() ? tailMergeMap.find(s)
+                                                 : tailMergeMap.end();
     if (mergeIt != tailMergeMap.end()) {
       auto &[superString, offset] = mergeIt->second;
       // s can be tail merged with superString. Do not layout s. Instead layout
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index b97203d656ebd..2e522bba4b10e 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -862,7 +862,7 @@ template <class LP> void Writer::createLoadCommands() {
     llvm_unreachable("unhandled output file type");
   }
 
-  if (config->generateUuid) {
+  if (config->getGenerateUuid()) {
     uuidCommand = make<LCUuid>();
     in.header->addLoadCommand(uuidCommand);
   }
@@ -896,11 +896,11 @@ template <class LP> void Writer::createLoadCommands() {
                       dylibFiles[i]->extraDylibs.end());
 
   for (DylibFile *dylibFile : dylibFiles) {
-    if (dylibFile->isBundleLoader) {
+    if (dylibFile->getIsBundleLoader()) {
       dylibFile->ordinal = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE;
       // Shortcut since bundle-loader does not re-export the symbols.
 
-      dylibFile->reexport = false;
+      dylibFile->setReexport(false);
       continue;
     }
 
@@ -912,8 +912,8 @@ template <class LP> void Writer::createLoadCommands() {
     // FIXME: `isReferenced()` is currently computed before dead code
     // stripping, so references from dead code keep a dylib alive. This
     // matches ld64, but it's something we should do better.
-    if (!dylibFile->isReferenced() && !dylibFile->forceNeeded &&
-        (!dylibFile->isExplicitlyLinked() || dylibFile->deadStrippable ||
+    if (!dylibFile->isReferenced() && !dylibFile->getForceNeeded() &&
+        (!dylibFile->isExplicitlyLinked() || dylibFile->getDeadStrippable() ||
          config->deadStripDylibs))
       continue;
 
@@ -945,13 +945,13 @@ template <class LP> void Writer::createLoadCommands() {
 
     ordinal = dylibFile->ordinal = dylibOrdinal++;
     LoadCommandType lcType = LC_LOAD_DYLIB;
-    if (dylibFile->reexport) {
-      if (dylibFile->forceWeakImport)
+    if (dylibFile->getReexport()) {
+      if (dylibFile->getForceWeakImport())
         warn(path::filename(dylibFile->getName()) +
              " is re-exported so cannot be weak-linked");
 
       lcType = LC_REEXPORT_DYLIB;
-    } else if (dylibFile->forceWeakImport ||
+    } else if (dylibFile->getForceWeakImport() ||
                dylibFile->refState == RefState::Weak) {
       lcType = LC_LOAD_WEAK_DYLIB;
     }
@@ -1358,7 +1358,7 @@ void Writer::writeOutputFile() {
   writeSections();
   applyOptimizationHints();
   buildFixupChains();
-  if (config->generateUuid)
+  if (config->getGenerateUuid())
     writeUuid();
   writeCodeSignature();
 
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 260df6f9b8e24..4dcbcd75f79be 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -10,6 +10,7 @@
 #define LLD_WASM_CONFIG_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
@@ -60,14 +61,27 @@ struct Config {
   bool disableVerify;
   bool emitRelocs;
   bool exportAll;
-  bool exportDynamic;
-  bool exportTable;
-  bool extendedConst;
-  bool growableTable;
-  bool gcSections;
+  bool getExportDynamic() const { return buildIdVector.getFlag(0); }
+  void setExportDynamic(bool Value) { buildIdVector.setFlag(0, Value); }
+  bool getExportTable() const { return buildIdVector.getFlag(1); }
+  bool setExportTable(bool Value) {
+    buildIdVector.setFlag(1, Value);
+    return Value;
+  }
+  bool getExtendedConst() const { return buildIdVector.getFlag(2); }
+  bool setExtendedConst(bool Value) {
+    buildIdVector.setFlag(2, Value);
+    return Value;
+  }
+  bool getGrowableTable() const { return buildIdVector.getFlag(3); }
+  void setGrowableTable(bool Value) { buildIdVector.setFlag(3, Value); }
+  bool getGcSections() const { return rpath.getFlag(0); }
+  void setGcSections(bool Value) { rpath.setFlag(0, Value); }
   llvm::StringSet<> keepSections;
-  bool cooperativeThreading;
-  bool libcallThreadContext;
+  bool getCooperativeThreading() const { return rpath.getFlag(1); }
+  void setCooperativeThreading(bool Value) { rpath.setFlag(1, Value); }
+  bool getLibcallThreadContext() const { return rpath.getFlag(2); }
+  void setLibcallThreadContext(bool Value) { rpath.setFlag(2, Value); }
   std::optional<std::pair<llvm::StringRef, llvm::StringRef>> memoryImport;
   std::optional<llvm::StringRef> memoryExport;
   bool sharedMemory;
@@ -97,7 +111,8 @@ struct Config {
   uint64_t initialHeap;
   uint64_t initialMemory;
   uint64_t maxMemory;
-  bool noGrowableMemory;
+  bool getNoGrowableMemory() const { return rpath.getFlag(3); }
+  void setNoGrowableMemory(bool Value) { rpath.setFlag(3, Value); }
   // The table offset at which to place function addresses.  We reserve zero
   // for the null function pointer.  This gets set to 1 for executables and 0
   // for shared libraries (since they always added to a dynamic offset at
@@ -109,7 +124,8 @@ struct Config {
   unsigned ltoo;
   llvm::CodeGenOptLevel ltoCgo;
   unsigned optimize;
-  bool ltoDebugPassManager;
+  bool getLtoDebugPassManager() const { return searchPaths.getFlag(0); }
+  void setLtoDebugPassManager(bool Value) { searchPaths.setFlag(0, Value); }
   UnresolvedPolicy unresolvedSymbols;
   BuildIdKind buildId = BuildIdKind::None;
 
@@ -130,14 +146,16 @@ struct Config {
   llvm::StringSet<> allowUndefinedSymbols;
   llvm::StringSet<> exportedSymbols;
   std::vector<llvm::StringRef> requiredExports;
-  llvm::SmallVector<llvm::StringRef, 0> searchPaths;
-  llvm::SmallVector<llvm::StringRef, 0> rpath;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0> searchPaths;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 4> rpath;
   llvm::CachePruningPolicy thinLTOCachePolicy;
   std::optional<std::vector<std::string>> features;
   std::optional<std::vector<std::string>> extraFeatures;
-  llvm::SmallVector<uint8_t, 0> buildIdVector;
+  llvm::SmallVectorWithFlags<uint8_t, 0, 4> buildIdVector;
 
-  bool isMultithreaded() const { return sharedMemory || cooperativeThreading; }
+  bool isMultithreaded() const {
+    return sharedMemory || getCooperativeThreading();
+  }
 };
 
 // The Ctx object hold all other (non-configuration) global state.
@@ -271,19 +289,27 @@ struct Ctx {
   WasmSym sym;
 
   // True if we are creating position-independent code.
-  bool isPic = false;
+  bool getIsPic() const { return whyExtractRecords.getFlag(0); }
+  void setIsPic(bool Value) { whyExtractRecords.setFlag(0, Value); }
 
   // True if we have an MVP input that uses __indirect_function_table and which
   // requires it to be allocated to table number 0.
-  bool legacyFunctionTable = false;
+  bool getLegacyFunctionTable() const { return whyExtractRecords.getFlag(1); }
+  void setLegacyFunctionTable(bool Value) {
+    whyExtractRecords.setFlag(1, Value);
+  }
 
   // Will be set to true if bss data segments should be emitted. In most cases
   // this is not necessary.
-  bool emitBssSegments = false;
+  bool getEmitBssSegments() const { return whyExtractRecords.getFlag(2); }
+  bool setEmitBssSegments(bool Value) {
+    whyExtractRecords.setFlag(2, Value);
+    return Value;
+  }
 
   // A tuple of (reference, extractedFile, sym). Used by --why-extract=.
-  llvm::SmallVector<std::tuple<std::string, const InputFile *, const Symbol &>,
-                    0>
+  llvm::SmallVectorWithFlags<
+      std::tuple<std::string, const InputFile *, const Symbol &>, 0, 3>
       whyExtractRecords;
 
   Ctx();
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 86ade0fc419b2..b9b3a217a0964 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -66,9 +66,9 @@ void Ctx::reset() {
   syntheticGlobals.clear();
   syntheticTables.clear();
   whyExtractRecords.clear();
-  isPic = false;
-  legacyFunctionTable = false;
-  emitBssSegments = false;
+  setIsPic(false);
+  setLegacyFunctionTable(false);
+  setEmitBssSegments(false);
   sym = WasmSym{};
 }
 
@@ -507,8 +507,8 @@ static void readConfigs(opt::InputArgList &args) {
   ctx.arg.emitRelocs = args.hasArg(OPT_emit_relocs);
   ctx.arg.entry = getEntry(args);
   ctx.arg.exportAll = args.hasArg(OPT_export_all);
-  ctx.arg.exportTable = args.hasArg(OPT_export_table);
-  ctx.arg.growableTable = args.hasArg(OPT_growable_table);
+  ctx.arg.setExportTable(args.hasArg(OPT_export_table));
+  ctx.arg.setGrowableTable(args.hasArg(OPT_growable_table));
   ctx.arg.noinhibitExec = args.hasArg(OPT_noinhibit_exec);
 
   if (args.hasArg(OPT_import_memory_with_name)) {
@@ -531,7 +531,7 @@ static void readConfigs(opt::InputArgList &args) {
   ctx.arg.soName = args.getLastArgValue(OPT_soname);
   ctx.arg.importTable = args.hasArg(OPT_import_table);
   ctx.arg.importUndefined = args.hasArg(OPT_import_undefined);
-  ctx.arg.cooperativeThreading = args.hasArg(OPT_cooperative_threading);
+  ctx.arg.setCooperativeThreading(args.hasArg(OPT_cooperative_threading));
   ctx.arg.ltoo = args::getInteger(args, OPT_lto_O, 2);
   if (ctx.arg.ltoo > 3)
     error("invalid optimization level for LTO: " + Twine(ctx.arg.ltoo));
@@ -543,14 +543,14 @@ static void readConfigs(opt::InputArgList &args) {
     error("invalid codegen optimization level for LTO: " + Twine(ltoCgo));
   ctx.arg.ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
   ctx.arg.ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
-  ctx.arg.ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
+  ctx.arg.setLtoDebugPassManager(args.hasArg(OPT_lto_debug_pass_manager));
   ctx.arg.mapFile = args.getLastArgValue(OPT_Map);
   ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
   ctx.arg.outputFile = args.getLastArgValue(OPT_o);
   ctx.arg.relocatable = args.hasArg(OPT_relocatable);
-  ctx.arg.rpath = args::getStrings(args, OPT_rpath);
-  ctx.arg.gcSections =
-      args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !ctx.arg.relocatable);
+  ctx.arg.rpath.assign(args::getStrings(args, OPT_rpath));
+  ctx.arg.setGcSections(
+      args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !ctx.arg.relocatable));
   for (auto *arg : args.filtered(OPT_keep_section))
     ctx.arg.keepSections.insert(arg->getValue());
   ctx.arg.mergeDataSegments =
@@ -560,7 +560,7 @@ static void readConfigs(opt::InputArgList &args) {
   ctx.arg.printGcSections =
       args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
   ctx.arg.saveTemps = args.hasArg(OPT_save_temps);
-  ctx.arg.searchPaths = args::getStrings(args, OPT_library_path);
+  ctx.arg.searchPaths.assign(args::getStrings(args, OPT_library_path));
   ctx.arg.shared = args.hasArg(OPT_shared);
   ctx.arg.shlibSigCheck = !args.hasArg(OPT_no_shlib_sigcheck);
   ctx.arg.stripAll = args.hasArg(OPT_strip_all);
@@ -606,7 +606,7 @@ static void readConfigs(opt::InputArgList &args) {
   ctx.arg.initialHeap = args::getInteger(args, OPT_initial_heap, 0);
   ctx.arg.initialMemory = args::getInteger(args, OPT_initial_memory, 0);
   ctx.arg.maxMemory = args::getInteger(args, OPT_max_memory, 0);
-  ctx.arg.noGrowableMemory = args.hasArg(OPT_no_growable_memory);
+  ctx.arg.setNoGrowableMemory(args.hasArg(OPT_no_growable_memory));
   ctx.arg.zStackSize =
       args::getZOptionValue(args, OPT_z, "stack-size", WasmDefaultPageSize);
   ctx.arg.pageSize = args::getInteger(args, OPT_page_size, WasmDefaultPageSize);
@@ -617,14 +617,14 @@ static void readConfigs(opt::InputArgList &args) {
   if (ctx.arg.pie || ctx.arg.shared)
     ctx.arg.isStatic = false;
 
-  if (ctx.arg.maxMemory != 0 && ctx.arg.noGrowableMemory) {
+  if (ctx.arg.maxMemory != 0 && ctx.arg.getNoGrowableMemory()) {
     // Erroring out here is simpler than defining precedence rules.
     error("--max-memory is incompatible with --no-growable-memory");
   }
 
   // Default value of exportDynamic depends on `-shared`
-  ctx.arg.exportDynamic =
-      args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, ctx.arg.shared);
+  ctx.arg.setExportDynamic(
+      args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, ctx.arg.shared));
 
   // Parse wasm32/64.
   if (auto *arg = args.getLastArg(OPT_m)) {
@@ -675,7 +675,9 @@ static void readConfigs(opt::InputArgList &args) {
   if (args.hasArg(OPT_print_map))
     ctx.arg.mapFile = "-";
 
-  std::tie(ctx.arg.buildId, ctx.arg.buildIdVector) = getBuildId(args);
+  auto [BuildId, BuildIdVector] = getBuildId(args);
+  ctx.arg.buildId = BuildId;
+  ctx.arg.buildIdVector.assign(std::move(BuildIdVector));
 }
 
 // Some Config members do not directly correspond to any particular
@@ -683,10 +685,10 @@ static void readConfigs(opt::InputArgList &args) {
 // This function initialize such members. See Config.h for the details
 // of these values.
 static void setConfigs() {
-  ctx.isPic = ctx.arg.pie || ctx.arg.shared;
+  ctx.setIsPic(ctx.arg.pie || ctx.arg.shared);
 
-  if (ctx.isPic) {
-    if (ctx.arg.exportTable)
+  if (ctx.getIsPic()) {
+    if (ctx.arg.getExportTable())
       error("-shared/-pie is incompatible with --export-table");
     ctx.arg.importTable = true;
   } else {
@@ -703,9 +705,9 @@ static void setConfigs() {
   }
 
   if (ctx.arg.relocatable) {
-    if (ctx.arg.exportTable)
+    if (ctx.arg.getExportTable())
       error("--relocatable is incompatible with --export-table");
-    if (ctx.arg.growableTable)
+    if (ctx.arg.getGrowableTable())
       error("--relocatable is incompatible with --growable-table");
     // Ignore any --import-table, as it's redundant.
     ctx.arg.importTable = true;
@@ -725,10 +727,10 @@ static void setConfigs() {
   if (!ctx.arg.memoryExport.has_value() && !ctx.arg.memoryImport.has_value()) {
     ctx.arg.memoryExport = memoryName;
   }
-  if (ctx.arg.cooperativeThreading) {
+  if (ctx.arg.getCooperativeThreading()) {
     if (ctx.arg.sharedMemory)
       error("--cooperative-threading is incompatible with --shared-memory");
-    ctx.arg.libcallThreadContext = true;
+    ctx.arg.setLibcallThreadContext(true);
 
     // Cooperative threading requires the table is either imported or exported
     // or otherwise there's no way for embedders to read spawned functions from
@@ -736,7 +738,7 @@ static void setConfigs() {
     // imported (e.g in `isPic` mode) then export the table instead to ensure
     // that it's visible to the outside world.
     if (!ctx.arg.importTable)
-      ctx.arg.exportTable = true;
+      ctx.arg.setExportTable(true);
   }
 }
 
@@ -758,13 +760,13 @@ static void checkOptions(opt::InputArgList &args) {
   if (ctx.arg.outputFile.empty() && !ctx.arg.thinLTOIndexOnly)
     error("no output file specified");
 
-  if (ctx.arg.importTable && ctx.arg.exportTable)
+  if (ctx.arg.importTable && ctx.arg.getExportTable())
     error("--import-table and --export-table may not be used together");
 
   if (ctx.arg.relocatable) {
     if (!ctx.arg.entry.empty())
       error("entry point specified for relocatable output file");
-    if (ctx.arg.gcSections)
+    if (ctx.arg.getGcSections())
       error("-r and --gc-sections may not be used together");
     if (ctx.arg.compressRelocations)
       error("-r -and --compress-relocations may not be used together");
@@ -782,7 +784,7 @@ static void checkOptions(opt::InputArgList &args) {
     warn("-Bsymbolic is only meaningful when combined with -shared");
   }
 
-  if (ctx.isPic) {
+  if (ctx.getIsPic()) {
     if (ctx.arg.globalBase)
       error("--global-base may not be used with -shared/-pie");
     if (ctx.arg.tableBase)
@@ -918,10 +920,11 @@ static void createSyntheticSymbols() {
 
   bool is64 = ctx.arg.is64.value_or(false);
 
-  auto stack_pointer_name =
-      ctx.arg.libcallThreadContext ? "__init_stack_pointer" : "__stack_pointer";
-  if (ctx.isPic) {
-    if (ctx.arg.libcallThreadContext) {
+  auto stack_pointer_name = ctx.arg.getLibcallThreadContext()
+                                ? "__init_stack_pointer"
+                                : "__stack_pointer";
+  if (ctx.getIsPic()) {
+    if (ctx.arg.getLibcallThreadContext()) {
       ctx.sym.stackPointer = createUndefinedGlobal(
           stack_pointer_name,
           ctx.arg.is64.value_or(false) ? &globalTypeI64 : &globalTypeI32);
@@ -943,14 +946,14 @@ static void createSyntheticSymbols() {
     ctx.sym.tableBase->markLive();
   } else {
     // For non-PIC code
-    ctx.sym.stackPointer =
-        createGlobalVariable(stack_pointer_name, !ctx.arg.libcallThreadContext);
+    ctx.sym.stackPointer = createGlobalVariable(
+        stack_pointer_name, !ctx.arg.getLibcallThreadContext());
   }
 
   if (ctx.arg.isMultithreaded()) {
     // TLS symbols are all hidden/dso-local
     auto tls_base_name =
-        ctx.arg.libcallThreadContext ? "__init_tls_base" : "__tls_base";
+        ctx.arg.getLibcallThreadContext() ? "__init_tls_base" : "__tls_base";
     ctx.sym.tlsBase = createGlobalVariable(tls_base_name, true,
                                            WASM_SYMBOL_VISIBILITY_HIDDEN);
     ctx.sym.tlsSize = createGlobalVariable("__tls_size", false,
@@ -961,7 +964,7 @@ static void createSyntheticSymbols() {
         "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(is64 ? i64ArgSignature : i32ArgSignature,
                                 "__wasm_init_tls"));
-    if (ctx.arg.libcallThreadContext) {
+    if (ctx.arg.getLibcallThreadContext()) {
       ctx.sym.tlsBase->markLive();
       ctx.sym.tlsSize->markLive();
       ctx.sym.tlsAlign->markLive();
@@ -986,7 +989,7 @@ static void createOptionalSymbols() {
   auto addDataLayoutSymbol = [&](StringRef s) -> DefinedData * {
     // Data layout symbols are either defined by lld, or (in the case
     // of PIC code) defined by the dynamic linker / embedder.
-    if (ctx.isPic) {
+    if (ctx.getIsPic()) {
       ctx.arg.allowUndefinedSymbols.insert(s);
       return nullptr;
     } else {
@@ -1005,7 +1008,7 @@ static void createOptionalSymbols() {
 
   // for pic, __memory_base and __table_base are handled in
   // createSyntheticSymbols.
-  if (!ctx.isPic) {
+  if (!ctx.getIsPic()) {
     ctx.sym.memoryBase = createOptionalGlobal("__memory_base", false);
     ctx.sym.tableBase = createOptionalGlobal("__table_base", false);
   }
@@ -1481,7 +1484,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
       sym->forceExport = true;
   }
 
-  if (!ctx.arg.relocatable && !ctx.isPic) {
+  if (!ctx.arg.relocatable && !ctx.getIsPic()) {
     // Add synthetic dummies for weak undefined functions.  Must happen
     // after LTO otherwise functions may not yet have signatures.
     symtab->handleWeakUndefines();
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 605d49f08fde7..ccebb059cf9a4 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -421,7 +421,7 @@ uint64_t InputChunk::getVA(uint64_t offset) const {
   // their VA is that relative offset. In single-threaded builds TLS is instead
   // lowered to normal data with a fixed base and so is assigned addresses as
   // usual.
-  if (ctx.isPic && ctx.arg.isMultithreaded() && isTLS())
+  if (ctx.getIsPic() && ctx.arg.isMultithreaded() && isTLS())
     return getChunkOffset(offset);
   return (outputSeg ? outputSeg->startVA : 0) + getChunkOffset(offset);
 }
@@ -452,7 +452,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
     Symbol *sym = file->getSymbol(rel);
     // Runtime relocations are needed when we don't know the address of
     // a symbol statically.
-    bool requiresRuntimeReloc = ctx.isPic || sym->hasGOTIndex();
+    bool requiresRuntimeReloc = ctx.getIsPic() || sym->hasGOTIndex();
     if (!requiresRuntimeReloc)
       continue;
 
@@ -471,7 +471,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
     writePtrConst(os, offset, is64, "offset");
 
     // In PIC mode we need to add the __memory_base
-    if (ctx.isPic) {
+    if (ctx.getIsPic()) {
       writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
       if (isTLS())
         writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "tls_base");
@@ -495,7 +495,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const {
         writeU8(os, opcode_reloc_add, "ADD");
       }
     } else {
-      assert(ctx.isPic);
+      assert(ctx.getIsPic());
       const GlobalSymbol *baseSymbol = ctx.sym.memoryBase;
       if (rel.Type == R_WASM_TABLE_INDEX_I32 ||
           rel.Type == R_WASM_TABLE_INDEX_I64)
diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h
index 9c519a9c3dbe9..e02781225e27d 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -118,7 +118,7 @@ class InputChunk {
   InputChunk(ObjFile *f, Kind k, StringRef name, uint32_t alignment = 0,
              uint32_t flags = 0)
       : name(name), file(f), alignment(alignment), flags(flags), sectionKind(k),
-        live(!ctx.arg.gcSections), discarded(false) {}
+        live(!ctx.arg.getGcSections()), discarded(false) {}
   ArrayRef<uint8_t> data() const { return rawData; }
   uint64_t getTombstone() const;
 
@@ -162,7 +162,8 @@ class SyntheticMergedChunk;
 // be found by looking at the next one).
 struct SectionPiece {
   SectionPiece(size_t off, uint32_t hash, bool live)
-      : inputOff(off), live(live || !ctx.arg.gcSections), hash(hash >> 1) {}
+      : inputOff(off), live(live || !ctx.arg.getGcSections()), hash(hash >> 1) {
+  }
 
   uint32_t inputOff;
   uint32_t live : 1;
diff --git a/lld/wasm/InputElement.h b/lld/wasm/InputElement.h
index c2a24c8ff5f4e..029932fa61d9b 100644
--- a/lld/wasm/InputElement.h
+++ b/lld/wasm/InputElement.h
@@ -24,7 +24,7 @@ namespace wasm {
 class InputElement {
 protected:
   InputElement(StringRef name, ObjFile *f)
-      : file(f), live(!ctx.arg.gcSections), name(name) {}
+      : file(f), live(!ctx.arg.getGcSections()), name(name) {}
 
 public:
   StringRef getName() const { return name; }
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index c72f3102aaec3..0d641b93bc486 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -360,7 +360,7 @@ void ObjFile::addLegacyIndirectFunctionTableIfNeeded(
 
   // We assume that this compilation unit has unrelocatable references to
   // this table.
-  ctx.legacyFunctionTable = true;
+  ctx.setLegacyFunctionTable(true);
 }
 
 static bool shouldMerge(const WasmSection &sec) {
diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h
index fd7fcb13f4426..a27462ad8dc44 100644
--- a/lld/wasm/InputFiles.h
+++ b/lld/wasm/InputFiles.h
@@ -73,7 +73,7 @@ class InputFile {
 
 protected:
   InputFile(Kind k, MemoryBufferRef m)
-      : mb(m), fileKind(k), live(!ctx.arg.gcSections) {}
+      : mb(m), fileKind(k), live(!ctx.arg.getGcSections()) {}
 
   void checkArch(llvm::Triple::ArchType arch) const;
 
diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp
index 1f82780e65a56..33ecafb44228f 100644
--- a/lld/wasm/LTO.cpp
+++ b/lld/wasm/LTO.cpp
@@ -67,14 +67,14 @@ static lto::Config createConfig() {
   }
 
   c.CGOptLevel = ctx.arg.ltoCgo;
-  c.DebugPassManager = ctx.arg.ltoDebugPassManager;
+  c.DebugPassManager = ctx.arg.getLtoDebugPassManager();
   c.AlwaysEmitRegularLTOObj = !ctx.arg.ltoObjPath.empty();
 
   if (auto relocModel = getRelocModelFromCMModel())
     c.RelocModel = *relocModel;
   else if (ctx.arg.relocatable)
     c.RelocModel = std::nullopt;
-  else if (ctx.isPic)
+  else if (ctx.getIsPic())
     c.RelocModel = Reloc::PIC_;
   else if (ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic)
     // With ImportDynamic we also need to use the PIC relocation model so that
diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp
index 3364be006ca24..0321d88969c56 100644
--- a/lld/wasm/MarkLive.cpp
+++ b/lld/wasm/MarkLive.cpp
@@ -180,7 +180,7 @@ void MarkLive::mark() {
 }
 
 void markLive() {
-  if (!ctx.arg.gcSections)
+  if (!ctx.arg.getGcSections())
     return;
 
   LLVM_DEBUG(dbgs() << "markLive\n");
@@ -226,7 +226,7 @@ bool MarkLive::isCallCtorsLive() {
 
   // In Emscripten-style PIC, we call `__wasm_call_ctors` which calls
   // `__wasm_apply_data_relocs`.
-  if (ctx.isPic)
+  if (ctx.getIsPic())
     return true;
 
   // If there are any init functions, mark `__wasm_call_ctors` live so that
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index d9017fefffdd1..d28bc89e8e40f 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -108,7 +108,7 @@ void DataSection::finalizeContents() {
   });
 #endif
 
-  assert((!ctx.isPic || ctx.arg.extendedConst || activeCount <= 1) &&
+  assert((!ctx.getIsPic() || ctx.arg.getExtendedConst() || activeCount <= 1) &&
          "output segments should have been combined by now");
 
   writeUleb128(os, segmentCount, "data segment count");
@@ -123,7 +123,7 @@ void DataSection::finalizeContents() {
     if (segment->initFlags & WASM_DATA_SEGMENT_HAS_MEMINDEX)
       writeUleb128(os, 0, "memory index");
     if (segment->isActive()) {
-      if (ctx.isPic && ctx.arg.extendedConst) {
+      if (ctx.getIsPic() && ctx.arg.getExtendedConst()) {
         writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
         writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
                      "literal (global index)");
@@ -135,7 +135,7 @@ void DataSection::finalizeContents() {
       } else {
         WasmInitExpr initExpr;
         initExpr.Extended = false;
-        if (ctx.isPic) {
+        if (ctx.getIsPic()) {
           assert(segment->startVA == 0);
           initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
           initExpr.Inst.Value.Global = ctx.sym.memoryBase->getGlobalIndex();
diff --git a/lld/wasm/OutputSegment.h b/lld/wasm/OutputSegment.h
index 05fcbacdf317b..c4f8915e14e07 100644
--- a/lld/wasm/OutputSegment.h
+++ b/lld/wasm/OutputSegment.h
@@ -28,7 +28,7 @@ class OutputSegment {
   // to the output binary.  However if the memory is imported, and
   // we can't use memory.fill during startup (due to lack of bulk
   // memory feature) then we include BSS segments verbatim.
-  bool requiredInBinary() const { return !isBss || ctx.emitBssSegments; }
+  bool requiredInBinary() const { return !isBss || ctx.getEmitBssSegments(); }
 
   bool isTLS() const { return name == ".tdata"; }
 
diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index cb597fdeffcf3..b6f2660d9ac5a 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -21,7 +21,7 @@ namespace lld::wasm {
 static bool requiresGOTAccess(const Symbol *sym) {
   if (sym->isShared())
     return true;
-  if (!ctx.isPic &&
+  if (!ctx.getIsPic() &&
       ctx.arg.unresolvedSymbols != UnresolvedPolicy::ImportDynamic)
     return false;
   if (sym->isHidden() || sym->isLocal())
@@ -144,7 +144,7 @@ void scanRelocations(InputChunk *chunk) {
       break;
     }
 
-    if (ctx.isPic || sym->isShared() ||
+    if (ctx.getIsPic() || sym->isShared() ||
         (sym->isUndefined() &&
          ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic)) {
       switch (reloc.Type) {
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index ec6a0d957ce62..a0db9c613dbfc 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -148,7 +148,7 @@ std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) {
   sym->canInline = true;
   sym->traced = trace;
   sym->forceExport = false;
-  sym->referenced = !ctx.arg.gcSections;
+  sym->referenced = !ctx.arg.getGcSections();
   symVector.emplace_back(sym);
   return {sym, true};
 }
@@ -934,12 +934,12 @@ TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) {
   WasmTableType *type = make<WasmTableType>();
   type->ElemType = ValType::FUNCREF;
   type->Limits = limits;
-  uint32_t flags = ctx.arg.exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
+  uint32_t flags = ctx.arg.getExportTable() ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
   flags |= WASM_SYMBOL_UNDEFINED;
   Symbol *sym =
       addUndefinedTable(name, name, defaultModule, flags, nullptr, type);
   sym->markLive();
-  sym->forceExport = ctx.arg.exportTable;
+  sym->forceExport = ctx.arg.getExportTable();
   return cast<TableSymbol>(sym);
 }
 
@@ -950,10 +950,10 @@ TableSymbol *SymbolTable::createDefinedIndirectFunctionTable(StringRef name) {
   WasmTableType type{ValType::FUNCREF, limits};
   WasmTable desc{invalidIndex, type, name};
   InputTable *table = make<InputTable>(desc, nullptr);
-  uint32_t flags = ctx.arg.exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
+  uint32_t flags = ctx.arg.getExportTable() ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
   TableSymbol *sym = addSyntheticTable(name, flags, table);
   sym->markLive();
-  sym->forceExport = ctx.arg.exportTable;
+  sym->forceExport = ctx.arg.getExportTable();
   return sym;
 }
 
@@ -985,7 +985,7 @@ TableSymbol *SymbolTable::resolveIndirectFunctionTable(bool required) {
     }
     if (required)
       return createUndefinedIndirectFunctionTable(functionTableName);
-  } else if ((existing && existing->isLive()) || ctx.arg.exportTable ||
+  } else if ((existing && existing->isLive()) || ctx.arg.getExportTable() ||
              required) {
     // A defined table is required.  Either because the user request an exported
     // table or because the table symbol is already live.  The existing table is
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index 26fff7c802eba..536f8e9c5ad6d 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -217,7 +217,7 @@ bool Symbol::isExported() const {
   if (ctx.arg.shared && isLive() && isWeak() && !isHidden())
     return true;
 
-  if (ctx.arg.exportAll || (ctx.arg.exportDynamic && !isHidden()))
+  if (ctx.arg.exportAll || (ctx.arg.getExportDynamic() && !isHidden()))
     return true;
 
   return isExportedExplicit();
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 1e5c85bd94954..723b411299e14 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -143,10 +143,10 @@ class Symbol {
 
 protected:
   Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
-      : name(name), file(f), symbolKind(k), referenced(!ctx.arg.gcSections),
-        requiresGOT(false), isUsedInRegularObj(false), forceExport(false),
-        forceImport(false), canInline(false), traced(false), isStub(false),
-        flags(flags) {}
+      : name(name), file(f), symbolKind(k),
+        referenced(!ctx.arg.getGcSections()), requiresGOT(false),
+        isUsedInRegularObj(false), forceExport(false), forceImport(false),
+        canInline(false), traced(false), isStub(false), flags(flags) {}
 
   StringRef name;
   InputFile *file;
diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index c629ed3cf2bb4..619b31990499d 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -53,7 +53,7 @@ class SubSection {
 };
 
 void writeGetTLSBase(const Ctx &ctx, raw_ostream &os) {
-  if (ctx.arg.libcallThreadContext) {
+  if (ctx.arg.getLibcallThreadContext()) {
     writeU8(os, WASM_OPCODE_CALL, "call");
     writeUleb128(os, ctx.sym.getTLSBase->getFunctionIndex(), "function index");
   } else {
@@ -65,7 +65,7 @@ void writeGetTLSBase(const Ctx &ctx, raw_ostream &os) {
 } // namespace
 
 bool DylinkSection::isNeeded() const {
-  return ctx.isPic ||
+  return ctx.getIsPic() ||
          ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic ||
          !ctx.sharedFiles.empty();
 }
@@ -199,7 +199,7 @@ void ImportSection::addGOTEntry(Symbol *sym) {
     return;
   LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
   sym->setGOTIndex(numImportedGlobals++);
-  if (ctx.isPic) {
+  if (ctx.getIsPic()) {
     // Any symbol that is assigned an normal GOT entry must be exported
     // otherwise the dynamic linker won't be able create the entry that contains
     // it.
@@ -380,7 +380,7 @@ void TableSection::addTable(InputTable *table) {
     return;
   // Some inputs require that the indirect function table be assigned to table
   // number 0.
-  if (ctx.legacyFunctionTable &&
+  if (ctx.getLegacyFunctionTable() &&
       isa<DefinedTable>(ctx.sym.indirectFunctionTable) &&
       cast<DefinedTable>(ctx.sym.indirectFunctionTable)->table == table) {
     if (out.importSec->getNumImportedTables()) {
@@ -481,7 +481,7 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) {
 }
 
 void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
-  assert(!ctx.arg.extendedConst || TLS);
+  assert(!ctx.arg.getExtendedConst() || TLS);
   bool is64 = ctx.arg.is64.value_or(false);
   unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
 
@@ -535,7 +535,7 @@ void GlobalSection::writeBody() {
       // In the case of dynamic linking, unless we have 'extended-const'
       // available, these global must to be mutable since they get updated to
       // the correct runtime value during `__wasm_apply_global_relocs`.
-      if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())
+      if (!ctx.arg.getExtendedConst() && ctx.getIsPic() && !sym->isTLS())
         mutable_ = true;
       // With multi-threading any TLS globals must be mutable since they get
       // set during `__wasm_apply_global_tls_relocs`
@@ -548,7 +548,7 @@ void GlobalSection::writeBody() {
     bool useExtendedConst = false;
     uint32_t globalIdx;
     int64_t offset;
-    if (ctx.arg.extendedConst && ctx.isPic) {
+    if (ctx.arg.getExtendedConst() && ctx.getIsPic()) {
       if (auto *d = dyn_cast<DefinedData>(sym)) {
         if (!sym->isTLS()) {
           globalIdx = ctx.sym.memoryBase->getGlobalIndex();
@@ -644,7 +644,7 @@ void ElemSection::writeBody() {
 
   WasmInitExpr initExpr;
   initExpr.Extended = false;
-  if (ctx.isPic) {
+  if (ctx.getIsPic()) {
     initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
     initExpr.Inst.Value.Global = ctx.sym.tableBase->getGlobalIndex();
   } else {
diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h
index e0bd91a739026..838817dd99e49 100644
--- a/lld/wasm/SyntheticSections.h
+++ b/lld/wasm/SyntheticSections.h
@@ -269,7 +269,7 @@ class GlobalSection : public SyntheticSection {
   // transform a `global.get` to an `i32.const`.
   void addInternalGOTEntry(Symbol *sym);
   bool needsRelocations() {
-    if (ctx.arg.extendedConst)
+    if (ctx.arg.getExtendedConst())
       return false;
     return llvm::any_of(internalGotSymbols,
                         [=](Symbol *sym) { return !sym->isTLS(); });
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 7ed266a06ca8c..7b79a5ac8b9a4 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -127,7 +127,7 @@ class Writer {
 };
 
 void writeSetTLSBase(const Ctx &ctx, raw_ostream &os) {
-  if (ctx.arg.libcallThreadContext) {
+  if (ctx.arg.getLibcallThreadContext()) {
     writeU8(os, WASM_OPCODE_CALL, "call");
     writeUleb128(os, ctx.sym.setTLSBase->getFunctionIndex(), "function index");
   } else {
@@ -351,7 +351,7 @@ void Writer::layoutMemory() {
   uint64_t memoryPtr = 0;
 
   auto placeStack = [&]() {
-    if (ctx.arg.relocatable || ctx.isPic)
+    if (ctx.arg.relocatable || ctx.getIsPic())
       return;
     memoryPtr = alignTo(memoryPtr, stackAlignment);
     if (ctx.sym.stackLow)
@@ -447,7 +447,7 @@ void Writer::layoutMemory() {
 
   uint64_t staticDataSize = memoryPtr - dataStart;
   log("mem: static data = " + Twine(staticDataSize));
-  if (ctx.isPic)
+  if (ctx.getIsPic())
     out.dylinkSec->memSize = staticDataSize;
 
   if (!ctx.arg.stackFirst)
@@ -513,14 +513,14 @@ void Writer::layoutMemory() {
             Twine(maxMemorySetting));
 
     maxMemory = ctx.arg.maxMemory;
-  } else if (ctx.arg.noGrowableMemory) {
+  } else if (ctx.arg.getNoGrowableMemory()) {
     maxMemory = memoryPtr;
   }
 
   // If no maxMemory config was supplied but we are building with
   // shared memory, we need to pick a sensible upper limit.
   if (ctx.arg.sharedMemory && maxMemory == 0) {
-    if (ctx.isPic)
+    if (ctx.getIsPic())
       maxMemory = maxMemorySetting;
     else
       maxMemory = memoryPtr;
@@ -600,7 +600,7 @@ void Writer::populateTargetFeatures() {
   SmallSet<std::string, 8> &allowed = out.targetFeaturesSec->features;
   bool tlsUsed = false;
 
-  if (ctx.isPic) {
+  if (ctx.getIsPic()) {
     // This should not be necessary because all PIC objects should
     // contain the `mutable-globals` feature.
     // TODO (https://github.com/llvm/llvm-project/issues/51681)
@@ -646,7 +646,7 @@ void Writer::populateTargetFeatures() {
     tlsUsed = tlsUsed || llvm::any_of(file->segments, isTLS);
 
     // Ensure that we're not mixing incompatible thread context models
-    if (ctx.arg.libcallThreadContext &&
+    if (ctx.arg.getLibcallThreadContext() &&
         llvm::any_of(file->getSymbols(), [](const auto &sym) {
           return sym && sym->getName() == "__stack_pointer" &&
                  sym->kind() == Symbol::UndefinedGlobalKind &&
@@ -679,7 +679,7 @@ void Writer::populateTargetFeatures() {
     if (!allowed.contains("bulk-memory"))
       error("'bulk-memory' feature must be used in order to use thread-local "
             "storage");
-    if (!allowed.contains("atomics") && !ctx.arg.cooperativeThreading)
+    if (!allowed.contains("atomics") && !ctx.arg.getCooperativeThreading())
       error("'atomics' feature must be used in order to use thread-local "
             "storage");
   }
@@ -717,10 +717,10 @@ void Writer::populateTargetFeatures() {
   // the bss segments, so these segments need to exist in the binary.
   if (ctx.arg.emitRelocs ||
       (ctx.arg.memoryImport.has_value() && !allowed.contains("bulk-memory")))
-    ctx.emitBssSegments = true;
+    ctx.setEmitBssSegments(true);
 
   if (allowed.contains("extended-const"))
-    ctx.arg.extendedConst = true;
+    ctx.arg.setExtendedConst(true);
 
   for (auto &feature : allowed)
     log("Allowed feature: " + feature);
@@ -772,18 +772,18 @@ static bool shouldImport(Symbol *sym) {
     return true;
   if (!sym->isUndefined())
     return false;
-  if (sym->isWeak() && !ctx.arg.relocatable && !ctx.isPic)
+  if (sym->isWeak() && !ctx.arg.relocatable && !ctx.getIsPic())
     return false;
 
   // In PIC mode we only need to import functions when they are called directly.
   // Indirect usage all goes via GOT imports.
-  if (ctx.isPic) {
+  if (ctx.getIsPic()) {
     if (auto *f = dyn_cast<UndefinedFunction>(sym))
       if (!f->isCalledDirectly)
         return false;
   }
 
-  if (ctx.isPic || ctx.arg.relocatable || ctx.arg.importUndefined ||
+  if (ctx.getIsPic() || ctx.arg.relocatable || ctx.arg.importUndefined ||
       ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic)
     return true;
   if (ctx.arg.allowUndefinedSymbols.contains(sym->getName()))
@@ -917,7 +917,7 @@ void Writer::calculateTypes() {
 // which calls the constructors and destructors.
 void Writer::createCommandExportWrappers() {
   // This logic doesn't currently support Emscripten-style PIC mode.
-  assert(!ctx.isPic);
+  assert(!ctx.getIsPic());
 
   // If there are no ctors and there's no libc `__wasm_call_dtors` to
   // call, don't wrap the exports.
@@ -975,7 +975,8 @@ static void finalizeIndirectFunctionTable() {
 
   uint32_t tableSize = ctx.arg.tableBase + out.elemSec->numEntries();
   WasmLimits limits = {0, tableSize, 0, 0};
-  if (ctx.sym.indirectFunctionTable->isDefined() && !ctx.arg.growableTable) {
+  if (ctx.sym.indirectFunctionTable->isDefined() &&
+      !ctx.arg.getGrowableTable()) {
     limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
     limits.Maximum = limits.Minimum;
   }
@@ -1065,7 +1066,7 @@ OutputSegment *Writer::createOutputSegment(StringRef name) {
   // be able to run TLS initialization on spawned threads, so that's managed
   // here by flagging TLS as passive as well.
   bool needsPassiveInit =
-      ctx.arg.sharedMemory || (ctx.arg.cooperativeThreading && s->isTLS());
+      ctx.arg.sharedMemory || (ctx.arg.getCooperativeThreading() && s->isTLS());
   if (needsPassiveInit)
     s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
   if (!ctx.arg.relocatable && name.starts_with(".bss"))
@@ -1198,8 +1199,8 @@ void Writer::combineActiveOutputSegments() {
   // combines all active data segments into a single .data segment.
   // This restriction does not apply when the extended const extension is
   // available: https://github.com/WebAssembly/extended-const
-  assert(!ctx.arg.extendedConst);
-  assert(ctx.isPic);
+  assert(!ctx.arg.getExtendedConst());
+  assert(ctx.getIsPic());
   auto isActive = [](const OutputSegment *s) {
     return s->requiredInBinary() && s->isActive();
   };
@@ -1318,7 +1319,7 @@ void Writer::createSyntheticInitFunctions() {
     }
   }
 
-  if (ctx.isPic && out.globalSec->needsRelocations()) {
+  if (ctx.getIsPic() && out.globalSec->needsRelocations()) {
     ctx.sym.applyGlobalRelocs = symtab->addSyntheticFunction(
         "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
         make<SyntheticFunction>(nullSignature, "__wasm_apply_global_relocs"));
@@ -1409,10 +1410,10 @@ void Writer::createInitMemoryFunction() {
     unsigned numAddressLocals = 0;
     unsigned tlsAddressLocal = -1;
     unsigned flagAddressLocal = -1;
-    if (ctx.isPic && ctx.arg.sharedMemory)
+    if (ctx.getIsPic() && ctx.arg.sharedMemory)
       flagAddressLocal = numAddressLocals++;
     bool needsTLSAddressLocal =
-        ctx.isPic && ctx.arg.isMultithreaded() &&
+        ctx.getIsPic() && ctx.arg.isMultithreaded() &&
         llvm::any_of(segments, [this](const OutputSegment *s) {
           return s->isTLS() && needsPassiveInitialization(s);
         });
@@ -1425,7 +1426,7 @@ void Writer::createInitMemoryFunction() {
     }
 
     auto writeGetFlagAddress = [&]() {
-      if (ctx.isPic) {
+      if (ctx.getIsPic()) {
         writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
         writeUleb128(os, flagAddressLocal, "flag address local index");
       } else {
@@ -1435,7 +1436,7 @@ void Writer::createInitMemoryFunction() {
 
     if (ctx.arg.sharedMemory) {
       // With PIC code we cache the flag address in a local.
-      if (ctx.isPic) {
+      if (ctx.getIsPic()) {
         writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
         writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "memory_base");
         writePtrConst(os, flagAddress, is64, "flag address");
@@ -1478,7 +1479,7 @@ void Writer::createInitMemoryFunction() {
         // instructions take as their first argument the destination
         // address.
         writePtrConst(os, s->startVA, is64, "destination address");
-        if (ctx.isPic) {
+        if (ctx.getIsPic()) {
           writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
           writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(),
                        "__memory_base");
@@ -1497,11 +1498,11 @@ void Writer::createInitMemoryFunction() {
         // here. For PIC builds the result of the address computation above is
         // what's stored into the global.
         if (ctx.arg.isMultithreaded() && s->isTLS()) {
-          if (ctx.isPic) {
+          if (ctx.getIsPic()) {
             // Cache the result of the addition in the TLS address local
             writeU8(os, WASM_OPCODE_LOCAL_TEE, "local.tee");
             writeUleb128(os, tlsAddressLocal, "tls address local");
-            if (ctx.arg.libcallThreadContext) {
+            if (ctx.arg.getLibcallThreadContext()) {
               writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
               writeUleb128(os, tlsAddressLocal, "tls address local");
               writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set");
@@ -1510,11 +1511,11 @@ void Writer::createInitMemoryFunction() {
             }
           } else {
             writePtrConst(os, s->startVA, is64, "destination address");
-            if (ctx.arg.libcallThreadContext)
+            if (ctx.arg.getLibcallThreadContext())
               ctx.sym.tlsBase->global->setPointerValue(s->startVA);
           }
           writeSetTLSBase(ctx, os);
-          if (ctx.isPic) {
+          if (ctx.getIsPic()) {
             writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
             writeUleb128(os, tlsAddressLocal, "tls address local");
           }
@@ -1874,7 +1875,7 @@ void Writer::createSyntheticSectionsPostLayout() {
 void Writer::run() {
   // For PIC code the table base is assigned dynamically by the loader.
   // For non-PIC, we start at 1 so that accessing table index 0 always traps.
-  if (!ctx.isPic && ctx.sym.tableBase)
+  if (!ctx.getIsPic() && ctx.sym.tableBase)
     setGlobalPtr(cast<DefinedGlobal>(ctx.sym.tableBase), ctx.arg.tableBase);
 
   log("-- allocateCommonSymbols");
@@ -1919,7 +1920,7 @@ void Writer::run() {
   // `__memory_base` import.  Unless we support the extended const expression we
   // can't do addition inside the constant expression, so we much combine the
   // segments into a single one that can live at `__memory_base`.
-  if (ctx.isPic && !ctx.arg.extendedConst) {
+  if (ctx.getIsPic() && !ctx.arg.getExtendedConst()) {
     log("-- combineActiveOutputSegments");
     combineActiveOutputSegments();
   }
@@ -1964,7 +1965,7 @@ void Writer::run() {
     // If the input contains a call to `__wasm_call_ctors`, either in one of
     // the input objects or an explicit export from the command-line, we
     // assume ctors and dtors are taken care of already.
-    if (!ctx.arg.relocatable && !ctx.isPic &&
+    if (!ctx.arg.relocatable && !ctx.getIsPic() &&
         !ctx.sym.callCtors->isUsedInRegularObj &&
         !ctx.sym.callCtors->isExported()) {
       log("-- createCommandExportWrappers");
diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index f0e781c718765..9f7c417727366 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -13,6 +13,7 @@
 #include "lldb/lldb-types.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -187,7 +188,7 @@ struct Entry {
     fmt = lldb::eFormatDefault;
     number = 0;
     level = 0;
-    deref = false;
+    setDeref(false);
   }
 
   static const char *TypeToCString(Type t);
@@ -199,13 +200,16 @@ struct Entry {
       return false;
     if (printf_format != rhs.printf_format)
       return false;
-    if (children_stack != rhs.children_stack)
+    if ((llvm::ArrayRef<std::vector<lldb_private::FormatEntity::Entry>>(
+             children_stack) !=
+         llvm::ArrayRef<std::vector<lldb_private::FormatEntity::Entry>>(
+             rhs.children_stack)))
       return false;
     if (type != rhs.type)
       return false;
     if (fmt != rhs.fmt)
       return false;
-    if (deref != rhs.deref)
+    if (getDeref() != rhs.getDeref())
       return false;
     return true;
   }
@@ -220,14 +224,15 @@ struct Entry {
   /// A stack of children entries, used by Scope entries to provide alterantive
   /// children. All other entries have a stack of size 1.
   /// @{
-  llvm::SmallVector<std::vector<Entry>, 1> children_stack;
+  llvm::SmallVectorWithFlags<std::vector<Entry>, 1> children_stack;
   size_t level = 0;
   /// @}
 
   Type type = Type::Invalid;
   lldb::Format fmt = lldb::eFormatDefault;
   lldb::addr_t number = 0;
-  bool deref = false;
+  bool getDeref() const { return children_stack.getFlag(0); }
+  void setDeref(bool Value) { children_stack.setFlag(0, Value); }
 };
 
 class Formatter {
@@ -235,8 +240,8 @@ class Formatter {
   Formatter(const SymbolContext *sc, const ExecutionContext *exe_ctx,
             const Address *addr, bool function_changed, bool initial_function)
       : m_sc(sc), m_exe_ctx(exe_ctx), m_addr(addr),
-        m_function_changed(function_changed),
-        m_initial_function(initial_function) {}
+        m_entry_type_stack(decltype(this->m_entry_type_stack)::withFlags(
+            unsigned(function_changed) | (unsigned(initial_function) << 1))) {}
 
   bool Format(const Entry &entry, Stream &s, ValueObject *valobj = nullptr);
 
@@ -269,10 +274,10 @@ class Formatter {
   const SymbolContext *const m_sc = nullptr;
   const ExecutionContext *const m_exe_ctx = nullptr;
   const Address *const m_addr = nullptr;
-  const bool m_function_changed = false;
-  const bool m_initial_function = false;
+  bool getM_function_changed() const { return m_entry_type_stack.getFlag(0); }
+  bool getM_initial_function() const { return m_entry_type_stack.getFlag(1); }
 
-  llvm::SmallVector<Entry::Type, 1> m_entry_type_stack;
+  llvm::SmallVectorWithFlags<Entry::Type, 1, 2> m_entry_type_stack;
 };
 
 Status Parse(const llvm::StringRef &format, Entry &entry);
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 52b3683b2570f..354934abb517f 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -379,7 +379,7 @@ VariableAnnotator::AnnotateStructured(Instruction &inst) {
   llvm::DIDumpOptions opts;
   opts.ShowAddresses = false;
   // Prefer "register-only" output when we have an ABI.
-  opts.PrintRegisterOnly = static_cast<bool>(abi_sp);
+  opts.setPrintRegisterOnly(static_cast<bool>(abi_sp));
 
   llvm::DenseMap<lldb::user_id_t, VariableAnnotation> current_vars;
 
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index b911c4c55379a..8c8cea11e4072 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -435,7 +435,7 @@ void FormatEntity::Entry::Dump(Stream &s, int depth) const {
     s.Printf("printf_format = \"%s\"", printf_format.c_str());
   if (number != 0)
     s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
-  if (deref)
+  if (getDeref())
     s.PutCString("deref = true, ");
   s.EOL();
   for (const auto &children : children_stack) {
@@ -766,7 +766,7 @@ bool FormatEntity::Formatter::DumpValue(Stream &s,
           ? ValueObject::eValueObjectRepresentationStyleValue
           : ValueObject::eValueObjectRepresentationStyleSummary;
 
-  bool do_deref_pointer = entry.deref;
+  bool do_deref_pointer = entry.getDeref();
   bool is_script = false;
   switch (entry.type) {
   case FormatEntity::Entry::Type::ScriptVariable:
@@ -1798,10 +1798,10 @@ bool FormatEntity::Formatter::Format(const Entry &entry, Stream &s,
     return false;
 
   case Entry::Type::FunctionDidChange:
-    return m_function_changed;
+    return getM_function_changed();
 
   case Entry::Type::FunctionInitialFunction:
-    return m_initial_function;
+    return getM_initial_function();
 
   case Entry::Type::FunctionName: {
     if (m_sc) {
@@ -1985,7 +1985,7 @@ bool FormatEntity::Formatter::Format(const Entry &entry, Stream &s,
     return false;
 
   case Entry::Type::FunctionChanged:
-    return m_function_changed;
+    return getM_function_changed();
 
   case Entry::Type::FunctionIsOptimized: {
     bool is_optimized = false;
@@ -2000,7 +2000,7 @@ bool FormatEntity::Formatter::Format(const Entry &entry, Stream &s,
   }
 
   case Entry::Type::FunctionInitial:
-    return m_initial_function;
+    return getM_initial_function();
 
   case Entry::Type::LineEntryFile:
     if (m_sc && m_sc->line_entry.IsValid()) {
@@ -2466,7 +2466,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
 
         // Check for dereferences
         if (variable[0] == '*') {
-          entry.deref = true;
+          entry.setDeref(true);
           variable = variable.drop_front();
         }
 
@@ -2507,7 +2507,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
         default:
           // Make sure someone didn't try to dereference anything but ${var}
           // or ${svar}
-          if (entry.deref) {
+          if (entry.getDeref()) {
             error = Status::FromErrorStringWithFormat(
                 "${%s} can't be dereferenced, only ${var} and ${svar} can.",
                 variable.str().c_str());
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
index 9d6dd2617a945..ac05b8fa94a4d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
@@ -1273,8 +1273,8 @@ RemapModule(OptionalClangModuleID from_id,
   OptionalClangModuleID parent = RemapModule(
       from_source.GetIDForModule(module->Parent), from_source, to_source);
   TypeSystemClang &to_ts = to_source.GetTypeSystem();
-  return to_ts.GetOrCreateClangModule(module->Name, parent, module->IsFramework,
-                                      module->IsExplicit);
+  return to_ts.GetOrCreateClangModule(
+      module->Name, parent, module->getIsFramework(), module->getIsExplicit());
 }
 
 void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
index fb8784ed8919c..8d1903afe728f 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -300,9 +300,9 @@ static std::string GetXcodeSDKDir(std::string preferred,
 }
 
 llvm::StringRef PlatformAppleSimulator::GetSDKFilepath() {
-  if (!m_have_searched_for_sdk) {
+  if (!getM_have_searched_for_sdk()) {
     m_sdk = GetXcodeSDKDir(m_sdk_name_primary, m_sdk_name_secondary);
-    m_have_searched_for_sdk = true;
+    setM_have_searched_for_sdk(true);
   }
   return m_sdk;
 }
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
index 9d0c1764e84a6..7a39df1b367c9 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
@@ -18,6 +18,7 @@
 #include "lldb/Utility/XcodeSDK.h"
 #include "lldb/lldb-forward.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/TargetParser/Triple.h"
 
@@ -116,10 +117,15 @@ class PlatformAppleSimulator : public PlatformDarwin {
   llvm::StringRef GetSDKFilepath();
 
   llvm::Triple::OSType m_os_type = llvm::Triple::UnknownOS;
-  llvm::SmallVector<llvm::StringRef, 4> m_supported_triples = {};
+  llvm::SmallVectorWithFlags<llvm::StringRef, 4> m_supported_triples = {};
   std::string m_sdk_name_primary;
   std::string m_sdk_name_secondary;
-  bool m_have_searched_for_sdk = false;
+  bool getM_have_searched_for_sdk() const {
+    return m_supported_triples.getFlag(0);
+  }
+  void setM_have_searched_for_sdk(bool Value) {
+    m_supported_triples.setFlag(0, Value);
+  }
   std::string m_sdk;
   XcodeSDK::Type m_sdk_type;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 21c37af2400f9..d7ab4bd9cd250 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -58,10 +58,10 @@ char SymbolFileDWARFDebugMap::ID;
 const SymbolFileDWARFDebugMap::FileRangeMap &
 SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
     SymbolFileDWARFDebugMap *exe_symfile) {
-  if (file_range_map_valid)
+  if (getFile_range_map_valid())
     return file_range_map;
 
-  file_range_map_valid = true;
+  setFile_range_map_valid(true);
 
   Module *oso_module = exe_symfile->GetModuleByCompUnitInfo(this);
   if (!oso_module)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 0946e7521874f..a21beb9ff151d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -12,6 +12,7 @@
 #include "DIERef.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Utility/RangeMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Chrono.h"
 #include <bitset>
 #include <map>
@@ -178,7 +179,7 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
     Status oso_load_error;
     OSOInfoSP oso_sp;
     /// The compile units that an object file contains.
-    llvm::SmallVector<lldb::CompUnitSP, 2> compile_units_sps;
+    llvm::SmallVectorWithFlags<lldb::CompUnitSP, 2> compile_units_sps;
     /// A map from the compile unit ID to its index in the vector.
     llvm::SmallDenseMap<uint64_t, uint64_t, 2> id_to_index_map;
     uint32_t first_symbol_index = UINT32_MAX;
@@ -186,7 +187,12 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
     uint32_t first_symbol_id = UINT32_MAX;
     uint32_t last_symbol_id = UINT32_MAX;
     FileRangeMap file_range_map;
-    bool file_range_map_valid = false;
+    bool getFile_range_map_valid() const {
+      return compile_units_sps.getFlag(0);
+    }
+    void setFile_range_map_valid(bool Value) {
+      compile_units_sps.setFlag(0, Value);
+    }
 
     CompileUnitInfo() = default;
 
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index c6f0bba051b60..c8cefc76401ca 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -46,6 +46,7 @@
 #define LLVM_ADT_GENERICUNIFORMITYIMPL_H
 
 #include "llvm/ADT/GenericUniformityInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
@@ -388,7 +389,7 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   /// and everything is uniform. Otherwise, values not in UniformValues
   /// (e.g. newly created) are conservatively treated as divergent.
   bool isDivergent(ConstValueRefT V) const {
-    if (!HasBranchDivergence)
+    if (!TemporalDivergenceList.getFlag(0))
       return false;
     // Only values that were present during analysis are tracked in
     // UniformValues (Instructions/Arguments for IR, Registers for MIR).
@@ -415,7 +416,9 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   /// IR specialization iterates F.args(); default is a no-op.
   bool printDivergentArgs(raw_ostream &Out) const;
 
-  SmallVector<TemporalDivergenceTuple, 8> TemporalDivergenceList;
+  // Flag 0 records whether the target has branch divergence. It is set at
+  // the start of compute(); until then, isDivergent() returns false.
+  SmallVectorWithFlags<TemporalDivergenceTuple, 8> TemporalDivergenceList;
 
   void recordTemporalDivergence(ConstValueRefT, const InstructionT *, CycleRef);
 
@@ -432,11 +435,6 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
   const CycleInfoT &CI;
   const TargetTransformInfo *TTI = nullptr;
 
-  // Whether the target has branch divergence. Set at the start of compute(),
-  // which is only called when the target has branch divergence. When false,
-  // isDivergent() returns false for all values.
-  bool HasBranchDivergence = false;
-
   SmallPtrSet<const BlockT *, 32> DivergentTermBlocks;
 
   // Values known to be uniform. Populated in initialize() with all values,
@@ -1155,7 +1153,7 @@ void GenericUniformityAnalysisImpl<ContextT>::analyzeControlDivergence(
 
 template <typename ContextT>
 void GenericUniformityAnalysisImpl<ContextT>::compute() {
-  HasBranchDivergence = true;
+  TemporalDivergenceList.setFlag(0, true);
 
   // All values on the Worklist are divergent.
   // Their users may not have been updated yet.
diff --git a/llvm/include/llvm/ADT/SmallVectorWithFlags.h b/llvm/include/llvm/ADT/SmallVectorWithFlags.h
index 5d10aa144c7d7..ad8aa62ecdb73 100644
--- a/llvm/include/llvm/ADT/SmallVectorWithFlags.h
+++ b/llvm/include/llvm/ADT/SmallVectorWithFlags.h
@@ -56,6 +56,20 @@ class SmallVectorWithFlagsImpl
     setFlags(Value ? getFlags() | Mask : getFlags() & ~Mask);
   }
 
+  using Base::assign;
+
+  /// Replace the elements with an ordinary vector, preserving this vector's
+  /// flags. Take over its heap buffer when the capacity fits in this header.
+  void assign(SmallVectorImpl<T> &&RHS) {
+    if (RHS.capacity() <= this->max_size()) {
+      this->moveAssignFrom(std::move(RHS));
+    } else {
+      Base::assign(std::make_move_iterator(RHS.begin()),
+                   std::make_move_iterator(RHS.end()));
+      RHS.clear();
+    }
+  }
+
   SmallVectorWithFlagsImpl(const SmallVectorWithFlagsImpl &) = delete;
 
   SmallVectorWithFlagsImpl &operator=(const SmallVectorWithFlagsImpl &RHS) {
@@ -145,6 +159,14 @@ class LLVM_GSL_OWNER SmallVectorWithFlags
 public:
   SmallVectorWithFlags() : Base(N) {}
 
+  /// Construct a vector and set its complete flag mask.
+  template <typename... Args>
+  static SmallVectorWithFlags withFlags(unsigned Flags, Args &&...Arguments) {
+    SmallVectorWithFlags Result(std::forward<Args>(Arguments)...);
+    Result.setFlags(Flags);
+    return Result;
+  }
+
   ~SmallVectorWithFlags() { this->destroy_range(this->begin(), this->end()); }
 
   explicit SmallVectorWithFlags(size_t Size) : Base(N) { this->resize(Size); }
@@ -185,6 +207,30 @@ class LLVM_GSL_OWNER SmallVectorWithFlags
     this->setFlags(Flags);
   }
 
+  /// Copy elements from an ordinary vector, starting with clear flags.
+  explicit SmallVectorWithFlags(const SmallVectorImpl<T> &RHS) : Base(N) {
+    this->append(RHS.begin(), RHS.end());
+  }
+
+  /// Move elements from an ordinary vector, starting with clear flags.
+  explicit SmallVectorWithFlags(SmallVectorImpl<T> &&RHS)
+      : SmallVectorWithFlags(0, std::move(RHS)) {}
+
+  /// Move elements from an ordinary vector and supply their flag mask.
+  SmallVectorWithFlags(unsigned Flags, SmallVectorImpl<T> &&RHS) : Base(N) {
+    if (!RHS.empty()) {
+      if (RHS.capacity() <= this->max_size()) {
+        this->moveConstructFrom(std::move(RHS));
+      } else {
+        // A plain vector can reserve more capacity than this header can hold.
+        this->append(std::make_move_iterator(RHS.begin()),
+                     std::make_move_iterator(RHS.end()));
+        RHS.clear();
+      }
+    }
+    this->setFlags(Flags);
+  }
+
   SmallVectorWithFlags(Base &&RHS) : Base(N) {
     if (!RHS.empty()) {
       // See SmallVector(SmallVectorImpl &&) for the rationale of this branch.
@@ -235,6 +281,21 @@ class LLVM_GSL_OWNER SmallVectorWithFlags
   }
 };
 
+namespace detail {
+template <typename Vector, unsigned FlagBits> struct SmallVectorWithFlagsType;
+
+template <typename T, unsigned N, unsigned FlagBits>
+struct SmallVectorWithFlagsType<SmallVector<T, N>, FlagBits> {
+  using type = SmallVectorWithFlags<T, N, FlagBits>;
+};
+} // namespace detail
+
+/// Preserve a SmallVector alias's element type and inline capacity while adding
+/// flags, including when the capacity is selected by the target's data layout.
+template <typename Vector, unsigned FlagBits = 1>
+using SmallVectorWithFlagsFor =
+    typename detail::SmallVectorWithFlagsType<Vector, FlagBits>::type;
+
 /// Also covers complete containers, including across inline capacities.
 template <typename T, unsigned FlagBits>
 void swap(SmallVectorWithFlagsImpl<T, FlagBits> &LHS,
diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index b6cae7c1cba85..82176cb154add 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -39,6 +39,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/MemoryLocation.h"
 #include "llvm/IR/Function.h"
@@ -284,7 +285,8 @@ class AAQueryInfo {
   /// Location pairs for which an assumption based result is currently stored.
   /// Used to remove all potentially incorrect results from the cache if an
   /// assumption is disproven.
-  SmallVector<AAQueryInfo::LocPair, 4> AssumptionBasedResults;
+  // Flag bits 0 and 1 record cross-iteration queries and disabled DT queries.
+  SmallVectorWithFlags<AAQueryInfo::LocPair, 4, 2> AssumptionBasedResults;
 
   /// Tracks whether the accesses may be on different cycle iterations.
   ///
@@ -300,11 +302,17 @@ class AAQueryInfo {
   ///   %addr2 = gep  %alloca2, 0, (%l + 1)
   ///      alias(%p, %addr1) -> MayAlias !
   ///   store %l, ...
-  bool MayBeCrossIteration = false;
+  bool mayBeCrossIteration() const { return AssumptionBasedResults.getFlag(0); }
+  void setMayBeCrossIteration(bool Value) {
+    AssumptionBasedResults.setFlag(0, Value);
+  }
 
   /// Whether alias analysis is allowed to use the dominator tree, for use by
   /// passes that lazily update the DT while performing AA queries.
-  bool UseDominatorTree = true;
+  bool usesDominatorTree() const { return !AssumptionBasedResults.getFlag(1); }
+  void setUseDominatorTree(bool Value) {
+    AssumptionBasedResults.setFlag(1, !Value);
+  }
 
   AAQueryInfo(AAResults &AAR, CaptureAnalysis *CA) : AAR(AAR), CA(CA) {}
 };
@@ -661,12 +669,10 @@ class BatchAAResults {
   }
 
   /// Assume that values may come from different cycle iterations.
-  void enableCrossIterationMode() {
-    AAQI.MayBeCrossIteration = true;
-  }
+  void enableCrossIterationMode() { AAQI.setMayBeCrossIteration(true); }
 
   /// Disable the use of the dominator tree during alias analysis queries.
-  void disableDominatorTree() { AAQI.UseDominatorTree = false; }
+  void disableDominatorTree() { AAQI.setUseDominatorTree(false); }
 };
 
 /// Temporarily set the cross iteration mode on a BatchAA instance.
@@ -676,11 +682,11 @@ class BatchAACrossIterationScope {
 
 public:
   BatchAACrossIterationScope(BatchAAResults &BAA, bool CrossIteration)
-      : BAA(BAA), OrigCrossIteration(BAA.AAQI.MayBeCrossIteration) {
-    BAA.AAQI.MayBeCrossIteration = CrossIteration;
+      : BAA(BAA), OrigCrossIteration(BAA.AAQI.mayBeCrossIteration()) {
+    BAA.AAQI.setMayBeCrossIteration(CrossIteration);
   }
   ~BatchAACrossIterationScope() {
-    BAA.AAQI.MayBeCrossIteration = OrigCrossIteration;
+    BAA.AAQI.setMayBeCrossIteration(OrigCrossIteration);
   }
 };
 
diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h
index df955432e9360..1672368dec025 100644
--- a/llvm/include/llvm/Analysis/AssumptionCache.h
+++ b/llvm/include/llvm/Analysis/AssumptionCache.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Pass.h"
@@ -66,7 +67,8 @@ class AssumptionCache {
 
   /// Vector of weak value handles to calls of the \@llvm.assume
   /// intrinsic.
-  SmallVector<WeakVH, 4> AssumeHandles;
+  // Flag bit 0 records whether the function has been scanned.
+  SmallVectorWithFlags<WeakVH, 4> AssumeHandles;
 
   class LLVM_ABI AffectedValueCallbackVH final : public CallbackVH {
     AssumptionCache *AC;
@@ -103,7 +105,7 @@ class AssumptionCache {
   ///
   /// We want to be as lazy about this as possible, and so we scan the function
   /// at the last moment.
-  bool Scanned = false;
+  bool isScanned() const { return AssumeHandles.getFlag(0); }
 
   /// Scan the function for assumptions and add them to the cache.
   LLVM_ABI void scanFunction();
@@ -145,7 +147,7 @@ class AssumptionCache {
   void clear() {
     AssumeHandles.clear();
     AffectedValues.clear();
-    Scanned = false;
+    AssumeHandles.setFlag(0, false);
   }
 
   /// Access the list of assumption handles currently tracked for this
@@ -157,7 +159,7 @@ class AssumptionCache {
   /// when we can write that to filter out the null values. Then caller code
   /// will become simpler.
   MutableArrayRef<WeakVH> assumptions() {
-    if (!Scanned)
+    if (!isScanned())
       scanFunction();
     return AssumeHandles;
   }
@@ -166,7 +168,7 @@ class AssumptionCache {
   ///
   /// No more than -max-assumes-per-value of them are cached.
   MutableArrayRef<ResultElem> assumptionsFor(const Value *V) {
-    if (!Scanned)
+    if (!isScanned())
       scanFunction();
 
     auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
diff --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index 5d9288ff2c2f3..283e97ec5e2f8 100644
--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -50,7 +50,7 @@ class BasicAAResult : public AAResultBase {
   DominatorTree *DT_;
 
   DominatorTree *getDT(const AAQueryInfo &AAQI) const {
-    return AAQI.UseDominatorTree ? DT_ : nullptr;
+    return AAQI.usesDominatorTree() ? DT_ : nullptr;
   }
 
 public:
diff --git a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 29be24ce0c32a..4b585a8970b29 100644
--- a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseBitVector.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/ADT/iterator_range.h"
@@ -223,13 +224,22 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
     using NodeList = SmallVector<BlockNode, 4>;
 
     LoopData *Parent;        ///< The parent loop.
-    bool IsPackaged = false; ///< Whether this has been packaged.
+    bool getIsPackaged() const { return Nodes.getFlag(0); }
+    void setIsPackaged(bool Value) {
+      Nodes.setFlag(0, Value);
+    } ///< Whether this has been packaged.
     // Has an irreducible SCC in its own nodes; sub-loops package theirs first.
-    bool ContainsIrreducible = false;
+    bool getContainsIrreducible() const { return Nodes.getFlag(1); }
+    bool setContainsIrreducible(bool Value) {
+      Nodes.setFlag(1, Value);
+      return Value;
+    }
     // A multi-entry SCC rather than a natural loop.
-    bool IsIrreducible = false;
+    bool getIsIrreducible() const { return Nodes.getFlag(2); }
+    void setIsIrreducible(bool Value) { Nodes.setFlag(2, Value); }
     ExitMap Exits;          ///< Successor edges (and weights).
-    NodeList Nodes;         ///< Header and the members of the loop.
+    llvm::SmallVectorWithFlagsFor<NodeList, 3>
+        Nodes;              ///< Header and the members of the loop.
     BlockMass BackedgeMass; ///< Mass that circulates, not exits.
     BlockMass Mass;
     Scaled64 Scale;
@@ -241,12 +251,12 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
     /// region is concerned, so the lowest-RPO member stands for the package
     /// and solveIrreducibleMass distributes mass among them all.
     LoopData(LoopData *Parent, NodeList &&Members)
-        : Parent(Parent), IsIrreducible(true), Nodes(std::move(Members)) {}
+        : Parent(Parent), Nodes(4, std::move(Members)) {}
 
     bool isHeader(const BlockNode &Node) const { return Node == Nodes[0]; }
 
     BlockNode getHeader() const { return Nodes[0]; }
-    bool isIrreducible() const { return IsIrreducible; }
+    bool isIrreducible() const { return getIsIrreducible(); }
 
     NodeList::const_iterator members_begin() const { return Nodes.begin() + 1; }
 
@@ -300,10 +310,10 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
     /// Packaging is transient state: this answers what represents Node at the
     /// level being processed, not where Node sits in the loop nest.
     LoopData *getPackagedLoop() const {
-      if (!Loop || !Loop->IsPackaged)
+      if (!Loop || !Loop->getIsPackaged())
         return nullptr;
       auto *L = Loop;
-      while (L->Parent && L->Parent->IsPackaged)
+      while (L->Parent && L->Parent->getIsPackaged())
         L = L->Parent;
       return L;
     }
@@ -312,7 +322,7 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
     /// loop it heads.
     BlockMass &getMass() {
       BlockMass *M = &Mass;
-      for (LoopData *L = Loop; L && L->IsPackaged && L->isHeader(Node);
+      for (LoopData *L = Loop; L && L->getIsPackaged() && L->isHeader(Node);
            L = L->Parent)
         M = &L->Mass;
       return *M;
@@ -322,7 +332,7 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
     bool isPackaged() const { return getResolvedNode() != Node; }
 
     /// Has Loop been packaged up?
-    bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; }
+    bool isAPackage() const { return isLoopHeader() && Loop->getIsPackaged(); }
   };
 
   /// Unscaled probability weight.
@@ -358,11 +368,11 @@ class LLVM_ABI BlockFrequencyInfoImplBase {
   /// \a DidOverflow indicates whether \a Total did overflow while adding to
   /// the distribution.  It should never overflow twice.
   struct Distribution {
-    using WeightList = SmallVector<Weight, 4>;
+    // Flag bit 0 records overflow of the total weight.
+    using WeightList = SmallVectorWithFlags<Weight, 4>;
 
     WeightList Weights;       ///< Individual successor weights.
     uint64_t Total = 0;       ///< Sum of all weights.
-    bool DidOverflow = false; ///< Whether \a Total did overflow.
 
     Distribution() = default;
 
@@ -1074,7 +1084,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() {
       // No LoopData yet; ask computeIrreducibleMass to package the SCC
       // that contains this cycle.
       if (Parent)
-        Parent->ContainsIrreducible = true;
+        Parent->setContainsIrreducible(true);
       else
         TopContainsIrreducible = true;
     }
@@ -1118,7 +1128,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() {
   // computeIrreducibleMass inserts each new loop immediately after *L.
   for (auto L = Loops.end(), B = Loops.begin(); L != B;) {
     --L;
-    if (L->ContainsIrreducible)
+    if (L->getContainsIrreducible())
       computeIrreducibleMass(&*L, std::next(L));
     computeMassInLoop(*L);
   }
diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
index 4a03f548823ee..192fadc33d99e 100644
--- a/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdater.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
@@ -229,15 +230,15 @@ class GenericDomTreeUpdater {
     DomTreeUpdate(CriticalEdge E) : IsCriticalEdgeSplit(true), EdgeSplit(E) {}
   };
 
-  SmallVector<DomTreeUpdate, 16> PendUpdates;
+  SmallVectorWithFlags<DomTreeUpdate, 16, 2> PendUpdates;
   size_t PendDTUpdateIndex = 0;
   size_t PendPDTUpdateIndex = 0;
   DomTreeT *DT = nullptr;
   PostDomTreeT *PDT = nullptr;
   const UpdateStrategy Strategy;
   SmallPtrSet<BasicBlockT *, 8> DeletedBBs;
-  bool IsRecalculatingDomTree = false;
-  bool IsRecalculatingPostDomTree = false;
+  bool isRecalculatingDomTree() const { return PendUpdates.getFlag(0); }
+  bool isRecalculatingPostDomTree() const { return PendUpdates.getFlag(1); }
 
   /// Returns true if the update is self dominance.
   bool isSelfDominance(UpdateT Update) const {
diff --git a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
index 6bfad783b529b..bcf7af736aea2 100644
--- a/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
+++ b/llvm/include/llvm/Analysis/GenericDomTreeUpdaterImpl.h
@@ -39,7 +39,7 @@ void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::recalculate(
   // Lazy UpdateStrategy so we recalculate available trees immediately.
 
   // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
-  IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
+  PendUpdates.setFlags(3);
 
   // Because all trees are going to be up-to-date after recalculation,
   // flush awaiting deleted BasicBlocks.
@@ -50,7 +50,7 @@ void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::recalculate(
     PDT->recalculate(F);
 
   // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
-  IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
+  PendUpdates.setFlags(0);
   PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
   dropOutOfDateUpdates();
 }
@@ -330,11 +330,11 @@ bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isUpdateValid(
 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::eraseDelBBNode(
     BasicBlockT *DelBB) {
-  if (DT && !IsRecalculatingDomTree)
+  if (DT && !isRecalculatingDomTree())
     if (DT->getNode(DelBB))
       DT->eraseNode(DelBB);
 
-  if (PDT && !IsRecalculatingPostDomTree)
+  if (PDT && !isRecalculatingPostDomTree())
     if (PDT->getNode(DelBB))
       PDT->eraseNode(DelBB);
 }
diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index 5d18486fe8113..59176afe9097e 100644
--- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -15,6 +15,7 @@
 #define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H
 
 #include "llvm/ADT/EquivalenceClasses.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/ScalarEvolution.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/Support/Compiler.h"
@@ -191,7 +192,7 @@ class MemoryDepChecker {
     /// Print the dependence.  \p Instr is used to map the instruction
     /// indices to instructions.
     LLVM_ABI void print(raw_ostream &OS, unsigned Depth,
-                        const SmallVectorImpl<Instruction *> &Instrs) const;
+                        ArrayRef<Instruction *> Instrs) const;
   };
 
   MemoryDepChecker(PredicatedScalarEvolution &PSE, AssumptionCache *AC,
@@ -286,7 +287,7 @@ class MemoryDepChecker {
   /// In same cases when the dependency check fails we can still
   /// vectorize the loop with a dynamic array access check.
   bool shouldRetryWithRuntimeChecks() const {
-    return ShouldRetryWithRuntimeChecks &&
+    return InstMap.getFlag(0) &&
            Status == VectorizationSafetyStatus::PossiblySafeWithRtChecks;
   }
 
@@ -294,16 +295,14 @@ class MemoryDepChecker {
   /// the MaxDependences threshold and this information is not
   /// available.
   const SmallVectorImpl<Dependence> *getDependences() const {
-    return RecordDependences ? &Dependences : nullptr;
+    return recordDependences() ? &Dependences : nullptr;
   }
 
   void clearDependences() { Dependences.clear(); }
 
   /// The vector of memory access instructions.  The indices are used as
   /// instruction identifiers in the Dependence class.
-  const SmallVectorImpl<Instruction *> &getMemoryInstructions() const {
-    return InstMap;
-  }
+  ArrayRef<Instruction *> getMemoryInstructions() const { return InstMap; }
 
   /// Generate a mapping between the memory instructions and their
   /// indices according to program order.
@@ -370,7 +369,9 @@ class MemoryDepChecker {
   DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses;
 
   /// Memory access instructions in program order.
-  SmallVector<Instruction *, 16> InstMap;
+  // Flag bits 0 and 1 record retrying with runtime checks and invalid
+  // dependences.
+  SmallVectorWithFlags<Instruction *, 16, 2> InstMap;
 
   /// The program order index to be used for the next instruction.
   unsigned AccessIdx = 0;
@@ -393,7 +394,6 @@ class MemoryDepChecker {
 
   /// Whether we should try to vectorize the loop with runtime checks, if the
   /// dependencies are not safe.
-  bool ShouldRetryWithRuntimeChecks = false;
 
   /// Result of the dependence checks, indicating whether the checked
   /// dependences are safe for vectorization, require RT checks or are known to
@@ -403,7 +403,7 @@ class MemoryDepChecker {
   //// True if Dependences reflects the dependences in the
   //// loop.  If false we exceeded MaxDependences and
   //// Dependences is invalid.
-  bool RecordDependences = true;
+  bool recordDependences() const { return !InstMap.getFlag(1); }
 
   /// Memory dependences collected during the analysis.  Only valid if
   /// RecordDependences is true.
@@ -588,8 +588,7 @@ class RuntimePointerChecking {
 
   /// Reset the state of the pointer runtime information.
   void reset() {
-    Need = false;
-    CanUseDiffCheck = true;
+    DiffChecks.setFlags(0);
     Pointers.clear();
     Checks.clear();
     DiffChecks.clear();
@@ -623,7 +622,7 @@ class RuntimePointerChecking {
   // if any pointer-difference is <u VF * InterleaveCount * access size. Returns
   // std::nullopt if pointer-difference checks cannot be used.
   std::optional<ArrayRef<PointerDiffInfo>> getDiffChecks() const {
-    if (!CanUseDiffCheck)
+    if (DiffChecks.getFlag(1))
       return std::nullopt;
     return {DiffChecks};
   }
@@ -646,7 +645,8 @@ class RuntimePointerChecking {
                             unsigned Depth = 0) const;
 
   /// This flag indicates if we need to add the runtime check.
-  bool Need = false;
+  bool needsChecking() const { return DiffChecks.getFlag(0); }
+  void setNeedsChecking(bool Need) { DiffChecks.setFlag(0, Need); }
 
   /// Information about the pointers that may require checking.
   SmallVector<PointerInfo, 2> Pointers;
@@ -706,11 +706,14 @@ class RuntimePointerChecking {
   SmallVector<RuntimePointerCheck, 4> Checks;
 
   /// Flag indicating if pointer-difference checks can be used
-  bool CanUseDiffCheck = true;
 
   /// A list of (pointer-difference, access size) pairs that can be used to
   /// prove that there are no vectorization-preventing dependencies.
-  SmallVector<PointerDiffInfo> DiffChecks;
+  // Flag bits 0 and 1 record required checks and unavailable diff checks.
+  SmallVectorWithFlags<
+      PointerDiffInfo,
+      CalculateSmallVectorDefaultInlinedElements<PointerDiffInfo>::value, 2>
+      DiffChecks;
 };
 
 /// Drive the analysis of memory accesses in the loop
diff --git a/llvm/include/llvm/Analysis/LoopCacheAnalysis.h b/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
index 00ca85e97a636..7ba1f0c9c7b92 100644
--- a/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopCacheAnalysis.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_ANALYSIS_LOOPCACHEANALYSIS_H
 #define LLVM_ANALYSIS_LOOPCACHEANALYSIS_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/LoopAnalysisManager.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/InstructionCost.h"
@@ -55,7 +56,7 @@ class IndexedReference {
   LLVM_ABI IndexedReference(Instruction &StoreOrLoadInst, const LoopInfo &LI,
                             ScalarEvolution &SE);
 
-  bool isValid() const { return IsValid; }
+  bool isValid() const { return getIsValid(); }
   const SCEV *getBasePointer() const { return BasePointer; }
   size_t getNumSubscripts() const { return Subscripts.size(); }
   const SCEV *getSubscript(unsigned SubNum) const {
@@ -137,7 +138,8 @@ class IndexedReference {
 
 private:
   /// True if the reference can be delinearized, false otherwise.
-  bool IsValid = false;
+  bool getIsValid() const { return Sizes.getFlag(0); }
+  void setIsValid(bool Value) { Sizes.setFlag(0, Value); }
 
   /// Represent the memory reference instruction.
   Instruction &StoreOrLoadInst;
@@ -149,7 +151,7 @@ class IndexedReference {
   SmallVector<const SCEV *, 3> Subscripts;
 
   /// The dimensions of the memory reference.
-  SmallVector<const SCEV *, 3> Sizes;
+  llvm::SmallVectorWithFlags<const SCEV *, 3> Sizes;
 
   ScalarEvolution &SE;
 };
diff --git a/llvm/include/llvm/Analysis/PtrUseVisitor.h b/llvm/include/llvm/Analysis/PtrUseVisitor.h
index 304c147190728..a11c9e906297e 100644
--- a/llvm/include/llvm/Analysis/PtrUseVisitor.h
+++ b/llvm/include/llvm/Analysis/PtrUseVisitor.h
@@ -26,6 +26,7 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/InstVisitor.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -137,7 +138,8 @@ class PtrUseVisitorBase {
   };
 
   /// The worklist of to-visit uses.
-  SmallVector<UseToVisit, 8> Worklist;
+  // Flag bit 0 records whether the current offset is known.
+  SmallVectorWithFlags<UseToVisit, 8> Worklist;
 
   /// A set of visited uses to break cycles in unreachable code.
   SmallPtrSet<Use *, 8> VisitedUses;
@@ -153,7 +155,8 @@ class PtrUseVisitorBase {
 
   /// True if we have a known constant offset for the use currently
   /// being visited.
-  bool IsOffsetKnown;
+  bool isOffsetKnown() const { return Worklist.getFlag(0); }
+  void setIsOffsetKnown(bool Known) { Worklist.setFlag(0, Known); }
 
   /// The constant offset of the use if that is known.
   APInt Offset;
@@ -228,7 +231,7 @@ class PtrUseVisitor : protected InstVisitor<DerivedT>,
     assert(I.getType()->isPointerTy());
     assert(isa<Instruction>(I) || isa<Argument>(I));
     IntegerType *IntIdxTy = cast<IntegerType>(DL.getIndexType(I.getType()));
-    IsOffsetKnown = true;
+    setIsOffsetKnown(true);
     Offset = APInt(IntIdxTy->getBitWidth(), 0);
     PI.reset();
 
@@ -239,8 +242,8 @@ class PtrUseVisitor : protected InstVisitor<DerivedT>,
     while (!Worklist.empty()) {
       UseToVisit ToVisit = Worklist.pop_back_val();
       U = ToVisit.UseAndIsOffsetKnown.getPointer();
-      IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt();
-      if (IsOffsetKnown)
+      setIsOffsetKnown(ToVisit.UseAndIsOffsetKnown.getInt());
+      if (isOffsetKnown())
         Offset = std::move(ToVisit.Offset);
 
       Instruction *I = cast<Instruction>(U->getUser());
@@ -275,7 +278,7 @@ class PtrUseVisitor : protected InstVisitor<DerivedT>,
 
     // If we can't walk the GEP, clear the offset.
     if (!adjustOffsetForGEP(GEPI)) {
-      IsOffsetKnown = false;
+      setIsOffsetKnown(false);
       Offset = APInt();
     }
 
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 298582cc1cf6b..acf22c68ad7ef 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -30,6 +30,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/PassManager.h"
@@ -1368,12 +1369,13 @@ class ScalarEvolution {
     const SCEV *SymbolicMaxNotTaken;
 
     // Not taken either exactly ConstantMaxNotTaken or zero times
-    bool MaxOrZero = false;
+    bool isMaxOrZero() const { return Predicates.getFlag(0); }
 
     /// A vector of predicate guards for this ExitLimit. The result is only
     /// valid if all of the predicates in \c Predicates evaluate to 'true' at
     /// run-time.
-    SmallVector<const SCEVPredicate *, 4> Predicates;
+    // Flag bit 0 records whether the exit count is the maximum or zero.
+    SmallVectorWithFlags<const SCEVPredicate *, 4> Predicates;
 
     /// Construct either an exact exit limit from a constant, or an unknown
     /// one from a SCEVCouldNotCompute.  No other types of SCEVs are allowed
@@ -1808,7 +1810,8 @@ class ScalarEvolution {
 
     /// A list of computable exits and their not-taken counts.  Loops almost
     /// never have more than one computable exit.
-    SmallVector<ExitNotTakenInfo, 1> ExitNotTaken;
+    // Flag bits 0 and 1 record completeness and a maximum-or-zero count.
+    SmallVectorWithFlags<ExitNotTakenInfo, 1, 2> ExitNotTaken;
 
     /// Expression indicating the least constant maximum backedge-taken count of
     /// the loop that is known, or a SCEVCouldNotCompute. This expression is
@@ -1817,16 +1820,14 @@ class ScalarEvolution {
 
     /// Indicating if \c ExitNotTaken has an element for every exiting block in
     /// the loop.
-    bool IsComplete = false;
 
     /// Expression indicating the least maximum backedge-taken count of the loop
     /// that is known, or a SCEVCouldNotCompute. Lazily computed on first query.
     const SCEV *SymbolicMax = nullptr;
 
     /// True iff the backedge is taken either exactly Max or zero times.
-    bool MaxOrZero = false;
 
-    bool isComplete() const { return IsComplete; }
+    bool isComplete() const { return ExitNotTaken.getFlag(0); }
     const SCEV *getConstantMax() const { return ConstantMax; }
 
     LLVM_ABI const ExitNotTakenInfo *getExitNotTaken(
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 42c11d72aa669..704a14328d07d 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -25,6 +25,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Uniformity.h"
 #include "llvm/Analysis/IVDescriptors.h"
 #include "llvm/Analysis/InterestingMemoryOperand.h"
@@ -87,16 +88,23 @@ struct MemIntrinsicInfo {
   // Same Id is set by the target for corresponding load/store intrinsics.
   unsigned short MatchingId = 0;
 
-  bool ReadMem = false;
-  bool WriteMem = false;
-  bool IsVolatile = false;
+  bool getReadMem() const { return InterestingOperands.getFlag(0); }
+  bool setReadMem(bool Value) {
+    InterestingOperands.setFlag(0, Value);
+    return Value;
+  }
+  bool getWriteMem() const { return InterestingOperands.getFlag(1); }
+  void setWriteMem(bool Value) { InterestingOperands.setFlag(1, Value); }
+  bool getIsVolatile() const { return InterestingOperands.getFlag(2); }
+  void setIsVolatile(bool Value) { InterestingOperands.setFlag(2, Value); }
 
-  SmallVector<InterestingMemoryOperand, 1> InterestingOperands;
+  llvm::SmallVectorWithFlags<InterestingMemoryOperand, 1, 3>
+      InterestingOperands;
 
   bool isUnordered() const {
     return (Ordering == AtomicOrdering::NotAtomic ||
             Ordering == AtomicOrdering::Unordered) &&
-           !IsVolatile;
+           !getIsVolatile();
   }
 };
 
diff --git a/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h b/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h
index 1cb29470e2ff7..833aac44b2e7f 100644
--- a/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h
+++ b/llvm/include/llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h
@@ -13,6 +13,7 @@
 #define LLVM_ANALYSIS_UTILS_IMPORTEDFUNCTIONSINLININGSTATISTICS_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -51,14 +52,16 @@ class ImportedFunctionsInliningStatistics {
     InlineGraphNode(InlineGraphNode &&) = default;
     InlineGraphNode &operator=(InlineGraphNode &&) = default;
 
-    llvm::SmallVector<InlineGraphNode *, 8> InlinedCallees;
+    llvm::SmallVectorWithFlags<InlineGraphNode *, 8, 2> InlinedCallees;
     /// Incremented every direct inline.
     int32_t NumberOfInlines = 0;
     /// Number of inlines into non imported function (possibly indirect via
     /// intermediate inlines). Computed based on graph search.
     int32_t NumberOfRealInlines = 0;
-    bool Imported = false;
-    bool Visited = false;
+    bool getImported() const { return InlinedCallees.getFlag(0); }
+    void setImported(bool Value) { InlinedCallees.setFlag(0, Value); }
+    bool getVisited() const { return InlinedCallees.getFlag(1); }
+    void setVisited(bool Value) { InlinedCallees.setFlag(1, Value); }
   };
 
 public:
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 70b98dae850fd..4173c06f3e109 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_ASMPARSER_LLPARSER_H
 #define LLVM_ASMPARSER_LLPARSER_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/AsmParser/AsmParserContext.h"
 #include "llvm/AsmParser/LLLexer.h"
@@ -185,15 +186,18 @@ namespace llvm {
 
     SmallVector<std::tuple<LocTy, DbgRecord *, TrackingMDNodeRef>>
         PendingDbgRecords;
-    SmallVector<std::tuple<LocTy, Instruction *, TrackingMDNodeRef>>
+    SmallVectorWithFlagsFor<
+        SmallVector<std::tuple<LocTy, Instruction *, TrackingMDNodeRef>>, 2>
         PendingDbgInsts;
 
-    /// Only the llvm-as tool may set this to false to bypass
-    /// UpgradeDebuginfo so it can generate broken bitcode.
-    bool UpgradeDebugInfo;
-
-    bool SeenNewDbgInfoFormat = false;
-    bool SeenOldDbgInfoFormat = false;
+    bool getSeenNewDbgInfoFormat() const { return PendingDbgInsts.getFlag(0); }
+    void setSeenNewDbgInfoFormat(bool Value) {
+      PendingDbgInsts.setFlag(0, Value);
+    }
+    bool getSeenOldDbgInfoFormat() const { return PendingDbgInsts.getFlag(1); }
+    void setSeenOldDbgInfoFormat(bool Value) {
+      PendingDbgInsts.setFlag(1, Value);
+    }
 
     std::string SourceFileName;
 
diff --git a/llvm/include/llvm/Bitstream/BitstreamWriter.h b/llvm/include/llvm/Bitstream/BitstreamWriter.h
index a2938642f824a..fda56318b8904 100644
--- a/llvm/include/llvm/Bitstream/BitstreamWriter.h
+++ b/llvm/include/llvm/Bitstream/BitstreamWriter.h
@@ -143,6 +143,14 @@ class BitstreamWriter {
   }
 
 public:
+  /// Create a bitstream in writer-owned storage.
+  BitstreamWriter() : Buffer(OwnBuffer), FS(nullptr), FlushThreshold(0) {}
+
+  /// Access the current storage. FlushToWord() completes any pending word.
+  /// Moving the buffer out finishes the stream; do not emit more data
+  /// afterward.
+  SmallVectorImpl<char> &getBuffer() { return Buffer; }
+
   /// Create a BitstreamWriter over a raw_ostream \p OutStream.
   /// If \p OutStream is a raw_svector_ostream, the BitstreamWriter will write
   /// directly to the latter's buffer. In all other cases, the BitstreamWriter
diff --git a/llvm/include/llvm/CGData/StableFunctionMap.h b/llvm/include/llvm/CGData/StableFunctionMap.h
index 909d0e1debe7e..1733df1189c59 100644
--- a/llvm/include/llvm/CGData/StableFunctionMap.h
+++ b/llvm/include/llvm/CGData/StableFunctionMap.h
@@ -17,6 +17,7 @@
 #define LLVM_CGDATA_STABLEFUNCTIONMAP_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/StructuralHash.h"
 #include "llvm/Support/Compiler.h"
@@ -160,7 +161,7 @@ struct StableFunctionMap {
   /// method assumes that string names have already been uniqued and the
   /// `StableFunctionEntry` is ready for insertion.
   void insert(std::unique_ptr<StableFunctionEntry> FuncEntry) {
-    assert(!Finalized && "Cannot insert after finalization");
+    assert(!isFinalized() && "Cannot insert after finalization");
     HashToFuncs[FuncEntry->Hash].Entries.emplace_back(std::move(FuncEntry));
   }
 
@@ -174,18 +175,23 @@ struct StableFunctionMap {
   /// A map from a stable_hash to a vector of functions with that hash.
   mutable HashFuncsMapType HashToFuncs;
   /// A vector of strings to hold names.
-  SmallVector<std::string> IdToName;
+  // Flag bits 0 and 1 record finalization and disabled name loading.
+  SmallVectorWithFlags<
+      std::string,
+      CalculateSmallVectorDefaultInlinedElements<std::string>::value, 2>
+      IdToName;
   /// A map from StringRef (name) to an ID.
   StringMap<unsigned> NameToId;
   /// True if the function map is finalized with minimal content.
-  bool Finalized = false;
+  bool isFinalized() const { return IdToName.getFlag(0); }
   /// The memory buffer that contains the serialized stable function map for
   /// lazy loading.
   /// Non-empty only if this StableFunctionMap is created from a MemoryBuffer
   /// (i.e. by IndexedCodeGenDataReader::read()) and lazily deserialized.
   std::shared_ptr<MemoryBuffer> Buffer;
   /// Whether to read stable function names from the buffer.
-  bool ReadStableFunctionMapNames = true;
+  bool readStableFunctionMapNames() const { return !IdToName.getFlag(1); }
+  void setReadStableFunctionMapNames(bool Read) { IdToName.setFlag(1, !Read); }
 
   friend struct StableFunctionMapRecord;
 };
diff --git a/llvm/include/llvm/CGData/StableFunctionMapRecord.h b/llvm/include/llvm/CGData/StableFunctionMapRecord.h
index 2d8b573a3cb46..0538c14ac4cba 100644
--- a/llvm/include/llvm/CGData/StableFunctionMapRecord.h
+++ b/llvm/include/llvm/CGData/StableFunctionMapRecord.h
@@ -109,7 +109,7 @@ struct StableFunctionMapRecord {
     assert(
         FunctionMap->empty() &&
         "Cannot change ReadStableFunctionMapNames after the map is populated");
-    FunctionMap->ReadStableFunctionMapNames = Read;
+    FunctionMap->setReadStableFunctionMapNames(Read);
   }
 
 private:
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 7278756a67267..8c26dfe734660 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Analysis/StaticDataProfileInfo.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -215,7 +216,8 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   DenseMap<GCStrategy *, std::unique_ptr<GCMetadataPrinter>> GCMetadataPrinters;
 
   /// Emit comments in assembly output if this is true.
-  bool VerboseAsm;
+  bool getVerboseAsm() const { return Sleds.getFlag(0); }
+  void setVerboseAsm(bool Value) { Sleds.setFlag(0, Value); }
 
   /// Store symbols and type identifiers used to create callgraph section
   /// entries related to a function.
@@ -254,7 +256,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   // A vector of all Debuginfo emitters we should use. Protected so that
   // targets can add their own. This vector maintains ownership of the
   // emitters.
-  SmallVector<std::unique_ptr<AsmPrinterHandler>, 2> Handlers;
+  llvm::SmallVectorWithFlags<std::unique_ptr<AsmPrinterHandler>, 2> Handlers;
   size_t NumUserHandlers = 0;
 
   StackMaps SM;
@@ -279,15 +281,24 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   /// True if the module contains split-stack functions. This is used to
   /// emit .note.GNU-split-stack section as required by the linker for
   /// special handling split-stack function calling no-split-stack function.
-  bool HasSplitStack = false;
+  bool getHasSplitStack() const { return Sleds.getFlag(1); }
+  void setHasSplitStack(bool Value) { Sleds.setFlag(1, Value); }
 
   /// True if the module contains no-split-stack functions. This is used to emit
   /// .note.GNU-no-split-stack section when it also contains functions without a
   /// split stack prologue.
-  bool HasNoSplitStack = false;
+  bool getHasNoSplitStack() const { return Sleds.getFlag(2); }
+  bool setHasNoSplitStack(bool Value) {
+    Sleds.setFlag(2, Value);
+    return Value;
+  }
 
   /// True if debugging information is available in this module.
-  bool DbgInfoAvailable = false;
+  bool getDbgInfoAvailable() const { return Sleds.getFlag(3); }
+  bool setDbgInfoAvailable(bool Value) {
+    Sleds.setFlag(3, Value);
+    return Value;
+  }
 
 protected:
   /// The attribute used for a pointer type's DWARF address space. Targets that
@@ -329,7 +340,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   bool isPositionIndependent() const;
 
   /// Return true if assembly output should contain comments.
-  bool isVerbose() const { return VerboseAsm; }
+  bool isVerbose() const { return getVerboseAsm(); }
 
   /// Return a unique ID for the current function.
   unsigned getFunctionNumber() const;
@@ -396,11 +407,11 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   MCSymbol *getSymbolPreferLocal(const GlobalValue &GV) const;
 
   bool doesDwarfUseRelocationsAcrossSections() const {
-    return DwarfUsesRelocationsAcrossSections;
+    return getDwarfUsesRelocationsAcrossSectionsFlag();
   }
 
   void setDwarfUsesRelocationsAcrossSections(bool Enable) {
-    DwarfUsesRelocationsAcrossSections = Enable;
+    setDwarfUsesRelocationsAcrossSectionsFlag(Enable);
   }
 
   /// Returns a section suffix (hot or unlikely) for the constant if profiles
@@ -445,7 +456,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   };
 
   // All the sleds to be emitted.
-  SmallVector<XRayFunctionEntry, 4> Sleds;
+  llvm::SmallVectorWithFlags<XRayFunctionEntry, 4, 4> Sleds;
 
   // Helper function to record a given XRay sled.
   void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind,
@@ -534,7 +545,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   CFISection getModuleCFISectionType() const { return ModuleCFISection; }
 
   /// Returns true if valid debug info is present.
-  bool hasDebugInfo() const { return DbgInfoAvailable; }
+  bool hasDebugInfo() const { return getDbgInfoAvailable(); }
 
   /// Since emitting CFI unwind information is entangled with supporting the
   /// exceptions, this returns true for platforms which use CFI unwind
@@ -988,7 +999,12 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   mutable unsigned LastFn = 0;
   mutable unsigned Counter = ~0U;
 
-  bool DwarfUsesRelocationsAcrossSections = false;
+  bool getDwarfUsesRelocationsAcrossSectionsFlag() const {
+    return Handlers.getFlag(0);
+  }
+  void setDwarfUsesRelocationsAcrossSectionsFlag(bool Value) {
+    Handlers.setFlag(0, Value);
+  }
 
   /// This method emits the header for the current function.
   virtual void emitFunctionHeader();
diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h
index 45703744efe3a..447bc539b8617 100644
--- a/llvm/include/llvm/CodeGen/CallingConvLower.h
+++ b/llvm/include/llvm/CodeGen/CallingConvLower.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/Register.h"
 #include "llvm/CodeGen/TargetCallingConv.h"
 #include "llvm/IR/CallingConv.h"
@@ -171,14 +172,21 @@ typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
 class CCState {
 private:
   CallingConv::ID CallingConv;
-  bool IsVarArg;
-  bool AnalyzingMustTailForwardedRegs = false;
+  bool getIsVarArg() const { return ByValRegs.getFlag(0); }
+  void setIsVarArg(bool Value) { ByValRegs.setFlag(0, Value); }
+  bool getAnalyzingMustTailForwardedRegs() const {
+    return ByValRegs.getFlag(1);
+  }
+  void setAnalyzingMustTailForwardedRegs(bool Value) {
+    ByValRegs.setFlag(1, Value);
+  }
   MachineFunction &MF;
   const TargetRegisterInfo &TRI;
   SmallVectorImpl<CCValAssign> &Locs;
   LLVMContext &Context;
   // True if arguments should be allocated at negative offsets.
-  bool NegativeOffsets;
+  bool getNegativeOffsets() const { return ByValRegs.getFlag(2); }
+  void setNegativeOffsets(bool Value) { ByValRegs.setFlag(2, Value); }
 
   uint64_t StackSize;
   Align MaxStackArgAlign;
@@ -222,7 +230,7 @@ class CCState {
     // First after last register allocated for current parameter.
     unsigned End;
   };
-  SmallVector<ByValInfo, 4 > ByValRegs;
+  llvm::SmallVectorWithFlags<ByValInfo, 4, 3> ByValRegs;
 
   // InRegsParamsProcessed - shows how many instances of ByValRegs was proceed
   // during argument analysis.
@@ -240,7 +248,7 @@ class CCState {
   LLVMContext &getContext() const { return Context; }
   MachineFunction &getMachineFunction() const { return MF; }
   CallingConv::ID getCallingConv() const { return CallingConv; }
-  bool isVarArg() const { return IsVarArg; }
+  bool isVarArg() const { return getIsVarArg(); }
 
   /// Returns the size of the currently allocated portion of the stack.
   uint64_t getStackSize() const { return StackSize; }
@@ -260,30 +268,27 @@ class CCState {
 
   /// AnalyzeFormalArguments - Analyze an array of argument values,
   /// incorporating info about the formals into this state.
-  LLVM_ABI void
-  AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
-                         CCAssignFn Fn);
+  LLVM_ABI void AnalyzeFormalArguments(llvm::ArrayRef<ISD::InputArg> Ins,
+                                       CCAssignFn Fn);
 
   /// The function will invoke AnalyzeFormalArguments.
-  void AnalyzeArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
-                        CCAssignFn Fn) {
+  void AnalyzeArguments(llvm::ArrayRef<ISD::InputArg> Ins, CCAssignFn Fn) {
     AnalyzeFormalArguments(Ins, Fn);
   }
 
   /// AnalyzeReturn - Analyze the returned values of a return,
   /// incorporating info about the result values into this state.
-  LLVM_ABI void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
+  LLVM_ABI void AnalyzeReturn(llvm::ArrayRef<ISD::OutputArg> Outs,
                               CCAssignFn Fn);
 
   /// CheckReturn - Analyze the return values of a function, returning
   /// true if the return can be performed without sret-demotion, and
   /// false otherwise.
-  LLVM_ABI bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                            CCAssignFn Fn);
+  LLVM_ABI bool CheckReturn(llvm::ArrayRef<ISD::OutputArg> Outs, CCAssignFn Fn);
 
   /// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
   /// incorporating info about the passed values into this state.
-  LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
+  LLVM_ABI void AnalyzeCallOperands(llvm::ArrayRef<ISD::OutputArg> Outs,
                                     CCAssignFn Fn);
 
   /// AnalyzeCallOperands - Same as above except it takes vectors of types
@@ -294,14 +299,13 @@ class CCState {
                                     CCAssignFn Fn);
 
   /// The function will invoke AnalyzeCallOperands.
-  void AnalyzeArguments(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                        CCAssignFn Fn) {
+  void AnalyzeArguments(llvm::ArrayRef<ISD::OutputArg> Outs, CCAssignFn Fn) {
     AnalyzeCallOperands(Outs, Fn);
   }
 
   /// AnalyzeCallResult - Analyze the return values of a call,
   /// incorporating info about the passed values into this state.
-  LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
+  LLVM_ABI void AnalyzeCallResult(llvm::ArrayRef<ISD::InputArg> Ins,
                                   CCAssignFn Fn);
 
   /// A shadow allocated register is a register that was allocated
@@ -407,7 +411,7 @@ class CCState {
   /// and alignment.
   int64_t AllocateStack(unsigned Size, Align Alignment) {
     int64_t Offset;
-    if (NegativeOffsets) {
+    if (getNegativeOffsets()) {
       StackSize = alignTo(StackSize + Size, Alignment);
       Offset = -StackSize;
     } else {
@@ -507,18 +511,19 @@ class CCState {
 
   /// Returns true if the results of the two calling conventions are compatible.
   /// This is usually part of the check for tailcall eligibility.
-  LLVM_ABI static bool
-  resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC,
-                    MachineFunction &MF, LLVMContext &C,
-                    const SmallVectorImpl<ISD::InputArg> &Ins,
-                    CCAssignFn CalleeFn, CCAssignFn CallerFn);
+  LLVM_ABI static bool resultsCompatible(CallingConv::ID CalleeCC,
+                                         CallingConv::ID CallerCC,
+                                         MachineFunction &MF, LLVMContext &C,
+                                         llvm::ArrayRef<ISD::InputArg> Ins,
+                                         CCAssignFn CalleeFn,
+                                         CCAssignFn CallerFn);
 
   /// The function runs an additional analysis pass over function arguments.
   /// It will mark each argument with the attribute flag SecArgPass.
   /// After running, it will sort the locs list.
-  template <class T>
-  void AnalyzeArgumentsSecondPass(const SmallVectorImpl<T> &Args,
-                                  CCAssignFn Fn) {
+  template <class ArgRangeT>
+  void AnalyzeArgumentsSecondPass(const ArgRangeT &Args, CCAssignFn Fn) {
+    using T = typename ArgRangeT::value_type;
     unsigned NumFirstPassLocs = Locs.size();
 
     /// Creates similar argument list to \p Args in which each argument is
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
index 1627d57a5b1f3..22014b11e076e 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/TargetCallingConv.h"
@@ -115,7 +116,7 @@ class LLVM_ABI CallLowering {
     ArgInfo OrigRet;
 
     /// List of descriptors of the arguments passed to the function.
-    SmallVector<ArgInfo, 32> OrigArgs;
+    llvm::SmallVectorWithFlags<ArgInfo, 32, 2> OrigArgs;
 
     /// Valid if the call has a swifterror inout parameter, and contains the
     /// vreg that the swifterror should be copied into after the call.
@@ -159,10 +160,12 @@ class LLVM_ABI CallLowering {
     const ConstantInt *CFIType = nullptr;
 
     /// True if this call results in convergent operations.
-    bool IsConvergent = true;
+    bool getIsConvergent() const { return !OrigArgs.getFlag(0); }
+    void setIsConvergent(bool Value) { OrigArgs.setFlag(0, !Value); }
 
     /// True if this call must not be merged with other calls.
-    bool NoMerge = false;
+    bool getNoMerge() const { return OrigArgs.getFlag(1); }
+    void setNoMerge(bool Value) { OrigArgs.setFlag(1, Value); }
 
     GlobalValue *DeactivationSymbol = nullptr;
   };
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
index 709490fcfc0f8..0d3af2aa8e090 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GISelWorkList.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace llvm {
 
@@ -25,11 +26,16 @@ class MachineInstr;
 // instcombinerWorkList?
 template<unsigned N>
 class GISelWorkList {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+  SmallVectorWithFlags<MachineInstr *, N> Worklist;
+#else
   SmallVector<MachineInstr *, N> Worklist;
+#endif
   DenseMap<MachineInstr *, unsigned> WorklistMap;
 
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-  bool Finalized = true;
+  bool isFinalized() const { return !Worklist.getFlag(0); }
+  void setFinalized(bool Value) { Worklist.setFlag(0, !Value); }
 #endif
 
 public:
@@ -48,7 +54,7 @@ class GISelWorkList {
   void deferred_insert(MachineInstr *I) {
     Worklist.push_back(I);
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-    Finalized = false;
+    setFinalized(false);
 #endif
   }
 
@@ -64,14 +70,14 @@ class GISelWorkList {
       if (!WorklistMap.try_emplace(Worklist[i], i).second)
         llvm_unreachable("Duplicate elements in the list");
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-    Finalized = true;
+    setFinalized(true);
 #endif
   }
 
   /// Add the specified instruction to the worklist if it isn't already in it.
   void insert(MachineInstr *I) {
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-    assert(Finalized && "GISelWorkList used without finalizing");
+    assert(isFinalized() && "GISelWorkList used without finalizing");
 #endif
     if (WorklistMap.try_emplace(I, Worklist.size()).second)
       Worklist.push_back(I);
@@ -80,7 +86,7 @@ class GISelWorkList {
   /// Remove I from the worklist if it exists.
   void remove(const MachineInstr *I) {
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-    assert(Finalized && "GISelWorkList used without finalizing");
+    assert(isFinalized() && "GISelWorkList used without finalizing");
 #endif
     auto It = WorklistMap.find(I);
     if (It == WorklistMap.end())
@@ -99,7 +105,7 @@ class GISelWorkList {
 
   MachineInstr *pop_back_val() {
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-    assert(Finalized && "GISelWorkList used without finalizing");
+    assert(isFinalized() && "GISelWorkList used without finalizing");
 #endif
     MachineInstr *I;
     do {
diff --git a/llvm/include/llvm/CodeGen/LexicalScopes.h b/llvm/include/llvm/CodeGen/LexicalScopes.h
index 6a52bdfb2f48c..ebaf026a7fcc4 100644
--- a/llvm/include/llvm/CodeGen/LexicalScopes.h
+++ b/llvm/include/llvm/CodeGen/LexicalScopes.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/Support/Compiler.h"
 #include <cassert>
@@ -45,7 +46,8 @@ class LexicalScope {
 public:
   LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I,
                bool A)
-      : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) {
+      : Parent(P), Desc(D), InlinedAtLocation(I) {
+    Children.setFlag(0, A);
     assert(D);
     assert(D->getSubprogram()->getUnit()->getEmissionKind() !=
            DICompileUnit::NoDebug &&
@@ -64,8 +66,8 @@ class LexicalScope {
   const MDNode *getDesc() const { return Desc; }
   const DILocation *getInlinedAt() const { return InlinedAtLocation; }
   const DILocalScope *getScopeNode() const { return Desc; }
-  bool isAbstractScope() const { return AbstractScope; }
-  SmallVectorImpl<LexicalScope *> &getChildren() { return Children; }
+  bool isAbstractScope() const { return Children.getFlag(0); }
+  SmallVectorWithFlagsImpl<LexicalScope *> &getChildren() { return Children; }
   SmallVectorImpl<InsnRange> &getRanges() { return Ranges; }
 
   /// Add a child scope.
@@ -125,9 +127,9 @@ class LexicalScope {
   const DILocalScope *Desc;                    // Debug info descriptor.
   const DILocation *InlinedAtLocation;         // Location at which this
                                                // scope is inlined.
-  bool AbstractScope;                          // Abstract Scope
-  SmallVector<LexicalScope *, 4> Children;     // Scopes defined in scope.
-                                               // Contents not owned.
+  // Flag bit 0 marks an abstract scope.
+  SmallVectorWithFlags<LexicalScope *, 4> Children; // Scopes defined in scope.
+                                                    // Contents not owned.
   SmallVector<InsnRange, 4> Ranges;
 
   const MachineInstr *LastInsn = nullptr;  // Last instruction of this scope.
diff --git a/llvm/include/llvm/CodeGen/LiveIntervalUnion.h b/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
index 9b0423486db88..a9917dbfb52bf 100644
--- a/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/llvm/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -18,6 +18,7 @@
 
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/LiveInterval.h"
 #include "llvm/CodeGen/SlotIndexes.h"
 #include <cassert>
@@ -119,9 +120,17 @@ class LiveIntervalUnion {
     const LiveRange *LR = nullptr;
     LiveRange::const_iterator LRI;  ///< current position in LR
     ConstSegmentIter LiveUnionI;    ///< current position in LiveUnion
-    SmallVector<const LiveInterval *, 4> InterferingVRegs;
-    bool CheckedFirstInterference = false;
-    bool SeenAllInterferences = false;
+    llvm::SmallVectorWithFlags<const LiveInterval *, 4, 2> InterferingVRegs;
+    bool getCheckedFirstInterference() const {
+      return InterferingVRegs.getFlag(0);
+    }
+    void setCheckedFirstInterference(bool Value) {
+      InterferingVRegs.setFlag(0, Value);
+    }
+    bool getSeenAllInterferences() const { return InterferingVRegs.getFlag(1); }
+    void setSeenAllInterferences(bool Value) {
+      InterferingVRegs.setFlag(1, Value);
+    }
     unsigned Tag = 0;
     unsigned UserTag = 0;
 
@@ -144,8 +153,8 @@ class LiveIntervalUnion {
       LiveUnion = &NewLiveUnion;
       LR = &NewLR;
       InterferingVRegs.clear();
-      CheckedFirstInterference = false;
-      SeenAllInterferences = false;
+      setCheckedFirstInterference(false);
+      setSeenAllInterferences(false);
       Tag = NewLiveUnion.getTag();
       UserTag = NewUserTag;
     }
@@ -164,9 +173,10 @@ class LiveIntervalUnion {
     bool checkInterference() { return collectInterferingVRegs(1); }
 
     // Vector generated by collectInterferingVRegs.
-    const SmallVectorImpl<const LiveInterval *> &interferingVRegs(
+    ArrayRef<const LiveInterval *> interferingVRegs(
         unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max()) {
-      if (!SeenAllInterferences || MaxInterferingRegs < InterferingVRegs.size())
+      if (!getSeenAllInterferences() ||
+          MaxInterferingRegs < InterferingVRegs.size())
         collectInterferingVRegs(MaxInterferingRegs);
       return InterferingVRegs;
     }
diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 8a928e1e75682..bee66823e1bc7 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseBitVector.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/iterator_range.h"
@@ -151,7 +152,9 @@ class MachineBasicBlock
   Instructions Insts;
 
   /// Keep track of the predecessor / successor basic blocks.
-  SmallVector<MachineBasicBlock *, 4> Predecessors;
+  // Flag bits 0-3 mark cleanup funclets, section boundaries, and asm-br
+  // targets.
+  SmallVectorWithFlags<MachineBasicBlock *, 4, 4> Predecessors;
   SmallVector<MachineBasicBlock *, 2> Successors;
 
   /// Keep track of the probabilities to the successors. This vector has the
@@ -206,7 +209,6 @@ class MachineBasicBlock
   bool IsEHFuncletEntry = false;
 
   /// Indicate that this basic block is the entry block of a cleanup funclet.
-  bool IsCleanupFuncletEntry = false;
 
   /// Fixed unique ID assigned to this basic block upon creation. Used with
   /// basic block sections and basic block labels.
@@ -216,13 +218,10 @@ class MachineBasicBlock
   MBBSectionID SectionID{0};
 
   // Indicate that this basic block begins a section.
-  bool IsBeginSection = false;
 
   // Indicate that this basic block ends a section.
-  bool IsEndSection = false;
 
   /// Indicate that this basic block is the indirect dest of an INLINEASM_BR.
-  bool IsInlineAsmBrIndirectTarget = false;
 
   /// since getSymbol is a relatively heavy-weight operation, the symbol
   /// is only computed once and is cached.
@@ -280,7 +279,7 @@ class MachineBasicBlock
   /// more detailed checks that this function aggregates together.
   bool hasAddressTaken() const {
     return MachineBlockAddressTaken || AddressTakenIRBlock ||
-           IsInlineAsmBrIndirectTarget;
+           isInlineAsmBrIndirectTarget();
   }
 
   /// Test whether this block is used as something other than the target of a
@@ -692,20 +691,20 @@ class MachineBasicBlock
   void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; }
 
   /// Returns true if this is the entry block of a cleanup funclet.
-  bool isCleanupFuncletEntry() const { return IsCleanupFuncletEntry; }
+  bool isCleanupFuncletEntry() const { return Predecessors.getFlag(0); }
 
   /// Indicates if this is the entry block of a cleanup funclet.
-  void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; }
+  void setIsCleanupFuncletEntry(bool V = true) { Predecessors.setFlag(0, V); }
 
   /// Returns true if this block begins any section.
-  bool isBeginSection() const { return IsBeginSection; }
+  bool isBeginSection() const { return Predecessors.getFlag(1); }
 
   /// Returns true if this block ends any section.
-  bool isEndSection() const { return IsEndSection; }
+  bool isEndSection() const { return Predecessors.getFlag(2); }
 
-  void setIsBeginSection(bool V = true) { IsBeginSection = V; }
+  void setIsBeginSection(bool V = true) { Predecessors.setFlag(1, V); }
 
-  void setIsEndSection(bool V = true) { IsEndSection = V; }
+  void setIsEndSection(bool V = true) { Predecessors.setFlag(2, V); }
 
   std::optional<UniqueBBID> getBBID() const { return BBID; }
 
@@ -730,13 +729,11 @@ class MachineBasicBlock
   LLVM_ABI bool mayHaveInlineAsmBr() const;
 
   /// Returns true if this is the indirect dest of an INLINEASM_BR.
-  bool isInlineAsmBrIndirectTarget() const {
-    return IsInlineAsmBrIndirectTarget;
-  }
+  bool isInlineAsmBrIndirectTarget() const { return Predecessors.getFlag(3); }
 
   /// Indicates if this is the indirect dest of an INLINEASM_BR.
   void setIsInlineAsmBrIndirectTarget(bool V = true) {
-    IsInlineAsmBrIndirectTarget = V;
+    Predecessors.setFlag(3, V);
   }
 
   /// Returns true if it is legal to hoist instructions into this block.
diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index 30699c3c18f1c..f0a9d27f59389 100644
--- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -14,6 +14,7 @@
 #define LLVM_CODEGEN_MACHINEFRAMEINFO_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/Register.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
 #include "llvm/Support/Alignment.h"
@@ -248,7 +249,8 @@ class MachineFrameInfo {
 
   /// This boolean keeps track of whether there is a call
   /// to builtin \@llvm.experimental.patchpoint.
-  bool HasPatchPoint = false;
+  bool getHasPatchPointFlag() const { return LocalFrameObjects.getFlag(0); }
+  void setHasPatchPointFlag(bool Value) { LocalFrameObjects.setFlag(0, Value); }
 
   /// The prolog/epilog code inserter calculates the final stack
   /// offsets for all of the fixed size objects, updating the Objects list
@@ -311,11 +313,12 @@ class MachineFrameInfo {
   std::vector<CalleeSavedInfo> CSInfo;
 
   /// Has CSInfo been set yet?
-  bool CSIValid = false;
+  bool getCSIValid() const { return LocalFrameObjects.getFlag(1); }
+  void setCSIValid(bool Value) { LocalFrameObjects.setFlag(1, Value); }
 
   /// References to frame indices which are mapped
   /// into the local frame allocation block. <FrameIdx, LocalOffset>
-  SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects;
+  llvm::SmallVectorWithFlags<std::pair<int, int64_t>, 32, 2> LocalFrameObjects;
 
   /// Size of the pre-allocated local frame block.
   int64_t LocalFrameSize = 0;
@@ -406,8 +409,8 @@ class MachineFrameInfo {
   /// This method may be called any time after instruction
   /// selection is complete to determine if there is a call to builtin
   /// \@llvm.experimental.patchpoint.
-  bool hasPatchPoint() const { return HasPatchPoint; }
-  void setHasPatchPoint(bool s = true) { HasPatchPoint = s; }
+  bool hasPatchPoint() const { return getHasPatchPointFlag(); }
+  void setHasPatchPoint(bool s = true) { setHasPatchPointFlag(s); }
 
   /// Return true if this function requires a split stack prolog, even if it
   /// uses no stack space. This is only meaningful for functions where
@@ -869,9 +872,9 @@ class MachineFrameInfo {
   }
 
   /// Has the callee saved info been calculated yet?
-  bool isCalleeSavedInfoValid() const { return CSIValid; }
+  bool isCalleeSavedInfoValid() const { return getCSIValid(); }
 
-  void setCalleeSavedInfoValid(bool v) { CSIValid = v; }
+  void setCalleeSavedInfoValid(bool v) { setCSIValid(v); }
 
   const SaveRestorePoints &getRestorePoints() const { return RestorePoints; }
 
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h
index 7a6f71b5648a6..0715881858a42 100644
--- a/llvm/include/llvm/CodeGen/MachineFunction.h
+++ b/llvm/include/llvm/CodeGen/MachineFunction.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -402,9 +403,20 @@ class LLVM_ABI MachineFunction {
   bool CallsUnwindInit = false;
   bool HasEHContTarget = false;
   bool HasEHScopes = false;
-  bool HasEHFunclets = false;
-  bool HasFakeUses = false;
-  bool IsOutlined = false;
+  bool getHasEHFuncletsFlag() const {
+    return DebugValueSubstitutions.getFlag(0);
+  }
+  void setHasEHFuncletsFlag(bool Value) {
+    DebugValueSubstitutions.setFlag(0, Value);
+  }
+  bool getHasFakeUsesFlag() const { return DebugValueSubstitutions.getFlag(1); }
+  void setHasFakeUsesFlag(bool Value) {
+    DebugValueSubstitutions.setFlag(1, Value);
+  }
+  bool getIsOutlinedFlag() const { return DebugValueSubstitutions.getFlag(2); }
+  void setIsOutlinedFlag(bool Value) {
+    DebugValueSubstitutions.setFlag(2, Value);
+  }
 
   /// BBID to assign to the next basic block of this function.
   unsigned NextBBID = 0;
@@ -609,7 +621,7 @@ class LLVM_ABI MachineFunction {
   /// recording changes in where a value is defined. For example, when one
   /// instruction is substituted for another. Keeping a record allows recovery
   /// of variable locations after compilation finishes.
-  SmallVector<DebugSubstitution, 8> DebugValueSubstitutions;
+  llvm::SmallVectorWithFlags<DebugSubstitution, 8, 4> DebugValueSubstitutions;
 
   /// Location of a PHI instruction that is also a debug-info variable value,
   /// for the duration of register allocation. Loaded by the PHI-elimination
@@ -631,7 +643,12 @@ class LLVM_ABI MachineFunction {
 
   /// Flag for whether this function contains DBG_VALUEs (false) or
   /// DBG_INSTR_REF (true).
-  bool UseDebugInstrRef = false;
+  bool getUseDebugInstrRefFlag() const {
+    return DebugValueSubstitutions.getFlag(3);
+  }
+  void setUseDebugInstrRefFlag(bool Value) {
+    DebugValueSubstitutions.setFlag(3, Value);
+  }
 
   /// Create a substitution between one <instr,operand> value to a different,
   /// new value.
@@ -1323,14 +1340,14 @@ class LLVM_ABI MachineFunction {
   bool hasEHScopes() const { return HasEHScopes; }
   void setHasEHScopes(bool V) { HasEHScopes = V; }
 
-  bool hasEHFunclets() const { return HasEHFunclets; }
-  void setHasEHFunclets(bool V) { HasEHFunclets = V; }
+  bool hasEHFunclets() const { return getHasEHFuncletsFlag(); }
+  void setHasEHFunclets(bool V) { setHasEHFuncletsFlag(V); }
 
-  bool hasFakeUses() const { return HasFakeUses; }
-  void setHasFakeUses(bool V) { HasFakeUses = V; }
+  bool hasFakeUses() const { return getHasFakeUsesFlag(); }
+  void setHasFakeUses(bool V) { setHasFakeUsesFlag(V); }
 
-  bool isOutlined() const { return IsOutlined; }
-  void setIsOutlined(bool V) { IsOutlined = V; }
+  bool isOutlined() const { return getIsOutlinedFlag(); }
+  void setIsOutlined(bool V) { setIsOutlinedFlag(V); }
 
   /// Find or create an LandingPadInfo for the specified MachineBasicBlock.
   LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad);
diff --git a/llvm/include/llvm/CodeGen/MachinePipeliner.h b/llvm/include/llvm/CodeGen/MachinePipeliner.h
index 9b8beef1a1677..01989fd23a23e 100644
--- a/llvm/include/llvm/CodeGen/MachinePipeliner.h
+++ b/llvm/include/llvm/CodeGen/MachinePipeliner.h
@@ -42,6 +42,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/CodeGen/DFAPacketizer.h"
 #include "llvm/CodeGen/MachineDominators.h"
@@ -625,7 +626,7 @@ class ResourceManager {
   const TargetSubtargetInfo *ST;
   const TargetInstrInfo *TII;
   ScheduleDAGInstrs *DAG;
-  const bool UseDFA;
+  bool getUseDFA() const { return NumScheduledMops.getFlag(0); }
   /// DFA resources for each slot
   llvm::SmallVector<std::unique_ptr<DFAPacketizer>> DFAResources;
   /// Modulo Reservation Table. When a resource with ID R is consumed in cycle
@@ -634,7 +635,7 @@ class ResourceManager {
   /// The number of scheduled micro operations for each slot. Micro operations
   /// are assumed to be scheduled one per cycle, starting with the cycle in
   /// which the instruction is scheduled.
-  llvm::SmallVector<int> NumScheduledMops;
+  llvm::SmallVectorWithFlags<int> NumScheduledMops;
   /// Each processor resource is associated with a so-called processor resource
   /// mask. This vector allows to correlate processor resource IDs with
   /// processor resource masks. There is exactly one element per each processor
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index a5cd22f2c5d9a..e33611dad50f3 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -80,7 +81,6 @@ class MachineRegisterInfo {
   SmallPtrSet<Delegate *, 1> TheDelegates;
 
   /// True if subregister liveness is tracked.
-  const bool TracksSubRegLiveness;
 
   /// VRegInfo - Information we keep for each virtual register.
   ///
@@ -99,12 +99,12 @@ class MachineRegisterInfo {
 
   /// The flag is true upon \p UpdatedCSRs initialization
   /// and false otherwise.
-  bool IsUpdatedCSRsInitialized = false;
 
   /// Contains the updated callee saved register list.
   /// As opposed to the static list defined in register info,
   /// all registers that were disabled are removed from the list.
-  SmallVector<MCPhysReg, 16> UpdatedCSRs;
+  // Flag bits 0 and 1 track subregister liveness and CSR initialization.
+  SmallVectorWithFlags<MCPhysReg, 16, 2> UpdatedCSRs;
 
   /// RegAllocHints - This vector records register allocation hints for
   /// virtual registers. For each virtual register, it keeps a pair of hint
@@ -247,16 +247,14 @@ class MachineRegisterInfo {
     const TargetRegisterClass *RC = getRegClassOrNull(VReg);
     return LLVM_LIKELY(RC) ? shouldTrackSubRegLiveness(*RC) : false;
   }
-  bool subRegLivenessEnabled() const {
-    return TracksSubRegLiveness;
-  }
+  bool subRegLivenessEnabled() const { return UpdatedCSRs.getFlag(0); }
 
   //===--------------------------------------------------------------------===//
   // Register Info
   //===--------------------------------------------------------------------===//
 
   /// Returns true if the updated CSR list was initialized and false otherwise.
-  bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; }
+  bool isUpdatedCSRsInitialized() const { return UpdatedCSRs.getFlag(1); }
 
   /// Disables the register from the list of CSRs.
   /// I.e. the register will not appear as part of the CSR mask.
diff --git a/llvm/include/llvm/CodeGen/MachineScheduler.h b/llvm/include/llvm/CodeGen/MachineScheduler.h
index 7ecc34fed40f8..9e4d13f9401f1 100644
--- a/llvm/include/llvm/CodeGen/MachineScheduler.h
+++ b/llvm/include/llvm/CodeGen/MachineScheduler.h
@@ -79,6 +79,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -95,8 +96,8 @@
 #include "llvm/Support/ErrorHandling.h"
 #include <algorithm>
 #include <cassert>
-#include <llvm/Support/raw_ostream.h>
 #include <list>
+#include <llvm/Support/raw_ostream.h>
 #include <memory>
 #include <string>
 #include <vector>
@@ -883,7 +884,10 @@ class SchedBoundary {
 private:
   /// True if the pending Q should be checked/updated before scheduling another
   /// instruction.
-  bool CheckPending;
+  bool getCheckPending() const { return ResourceGroupSubUnitMasks.getFlag(0); }
+  void setCheckPending(bool Value) {
+    ResourceGroupSubUnitMasks.setFlag(0, Value);
+  }
 
   /// Number of cycles it takes to issue the instructions scheduled in this
   /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls.
@@ -922,7 +926,13 @@ class SchedBoundary {
   unsigned ZoneCritResIdx;
 
   // Is the scheduled region resource limited vs. latency limited.
-  bool IsResourceLimited;
+  bool getIsResourceLimited() const {
+    return ResourceGroupSubUnitMasks.getFlag(1);
+  }
+  bool setIsResourceLimited(bool Value) {
+    ResourceGroupSubUnitMasks.setFlag(1, Value);
+    return Value;
+  }
 
 public:
 private:
@@ -962,7 +972,7 @@ class SchedBoundary {
   SmallVector<unsigned, 16> ReservedCyclesIndex;
 
   // For each PIdx, stores the resource group IDs of its subunits
-  SmallVector<APInt, 16> ResourceGroupSubUnitMasks;
+  llvm::SmallVectorWithFlags<APInt, 16, 2> ResourceGroupSubUnitMasks;
 
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
   // Remember the greatest possible stall as an upper bound on the number of
@@ -1033,7 +1043,7 @@ class SchedBoundary {
   unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
 
   // Is the scheduled region resource limited vs. latency limited.
-  bool isResourceLimited() const { return IsResourceLimited; }
+  bool isResourceLimited() const { return getIsResourceLimited(); }
 
   /// Get the difference between the given SUnit's ready time and the current
   /// cycle.
diff --git a/llvm/include/llvm/CodeGen/Rematerializer.h b/llvm/include/llvm/CodeGen/Rematerializer.h
index 9dda2a47b4387..918a9dd7f814c 100644
--- a/llvm/include/llvm/CodeGen/Rematerializer.h
+++ b/llvm/include/llvm/CodeGen/Rematerializer.h
@@ -15,6 +15,7 @@
 #define LLVM_CODEGEN_REMATERIALIZER_H
 
 #include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/LiveIntervals.h"
 #include "llvm/CodeGen/LiveRangeEdit.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -620,7 +621,7 @@ class LLVM_ABI Rollbacker : public Rematerializer::Listener {
   /// in register deletion order overall. A position is either a MachineInstr*
   /// that existed in the MIR at the time the rollbacker was attached to the
   /// rematerializer, or a MachineBasicBlock*.
-  SmallVector<InsertBeforePos> Positions;
+  llvm::SmallVectorWithFlags<InsertBeforePos> Positions;
   /// Maps all re-creation positions that exist in \ref Positions to the indices
   /// of elements holding that position in the vector.
   DenseMap<InsertBeforePos, SmallDenseSet<unsigned, 1>> PosToIdx;
@@ -629,7 +630,8 @@ class LLVM_ABI Rollbacker : public Rematerializer::Listener {
   DenseMap<RegisterIdx, Rematerializer::RematsOf> Rematerializations;
   /// Used to block further recording of events whenver we are actively rolling
   /// back.
-  bool RollingBack = false;
+  bool getRollingBack() const { return Positions.getFlag(0); }
+  void setRollingBack(bool Value) { Positions.setFlag(0, Value); }
 
   InsertBeforePos makePos(MachineBasicBlock::iterator It,
                           MachineBasicBlock *MBB) const {
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h
index fe1bbde0d58e9..7711dc479607d 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAG.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAG.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/TargetLowering.h"
@@ -743,10 +744,11 @@ class TargetRegisterInfo;
     SUnit *ExitSU;
 
     // Have any new nodes been added?
-    bool Dirty = false;
+    bool getDirty() const { return Updates.getFlag(0); }
+    void setDirty(bool Value) { Updates.setFlag(0, Value); }
 
     // Outstanding added edges, that have not been applied to the ordering.
-    SmallVector<std::pair<SUnit *, SUnit *>, 16> Updates;
+    llvm::SmallVectorWithFlags<std::pair<SUnit *, SUnit *>, 16> Updates;
 
     /// Maps topological index to the node number.
     std::vector<int> Index2Node;
@@ -818,7 +820,7 @@ class TargetRegisterInfo;
 
     /// Mark the ordering as temporarily broken, after a new node has been
     /// added.
-    void MarkDirty() { Dirty = true; }
+    void MarkDirty() { setDirty(true); }
 
     typedef std::vector<int>::iterator iterator;
     typedef std::vector<int>::const_iterator const_iterator;
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 7a080dccfb061..60f1b00fb4a71 100644
--- a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseMultiSet.h"
 #include "llvm/CodeGen/LiveRegUnits.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -116,20 +117,24 @@ namespace llvm {
 
     /// True if the DAG builder should remove kill flags (in preparation for
     /// rescheduling).
-    bool RemoveKillFlags;
+    bool getRemoveKillFlags() const { return Clusters.getFlag(0); }
+    void setRemoveKillFlags(bool Value) { Clusters.setFlag(0, Value); }
 
     /// True if regions with a single MI should be scheduled.
-    bool ScheduleSingleMIRegions = false;
+    bool getScheduleSingleMIRegions() const { return Clusters.getFlag(1); }
+    void setScheduleSingleMIRegions(bool Value) { Clusters.setFlag(1, Value); }
 
     /// The standard DAG builder does not normally include terminators as DAG
     /// nodes because it does not create the necessary dependencies to prevent
     /// reordering. A specialized scheduler can override
     /// TargetInstrInfo::isSchedulingBoundary then enable this flag to indicate
     /// it has taken responsibility for scheduling the terminator correctly.
-    bool CanHandleTerminators = false;
+    bool getCanHandleTerminators() const { return Clusters.getFlag(2); }
+    void setCanHandleTerminators(bool Value) { Clusters.setFlag(2, Value); }
 
     /// Whether lane masks should get tracked.
-    bool TrackLaneMasks = false;
+    bool getTrackLaneMasks() const { return Clusters.getFlag(3); }
+    void setTrackLaneMasks(bool Value) { Clusters.setFlag(3, Value); }
 
     // State specific to the current scheduling region.
     // ------------------------------------------------
@@ -167,7 +172,10 @@ namespace llvm {
     /// Tracks the last instructions in this region using each virtual register.
     VReg2SUnitOperIdxMultiMap CurrentVRegUses;
 
-    SmallVector<ClusterInfo> Clusters;
+    llvm::SmallVectorWithFlags<
+        ClusterInfo,
+        llvm::CalculateSmallVectorDefaultInlinedElements<ClusterInfo>::value, 4>
+        Clusters;
 
     friend class ScheduleDAGDependencyBuilder;
 
@@ -224,7 +232,7 @@ namespace llvm {
 
     /// Whether regions with a single MI should be scheduled.
     bool shouldScheduleSingleMIRegions() const {
-      return ScheduleSingleMIRegions;
+      return getScheduleSingleMIRegions();
     }
 
     /// Returns an iterator to the top of the current scheduling region.
@@ -317,7 +325,7 @@ namespace llvm {
     bool addEdge(SUnit *SuccSU, const SDep &PredDep);
 
     /// Returns the array of the clusters.
-    SmallVector<ClusterInfo> &getClusters() { return Clusters; }
+    auto &getClusters() { return Clusters; }
 
     /// Get the specific cluster, return nullptr for InvalidClusterId.
     ClusterInfo *getCluster(unsigned Idx) {
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index cd4c11dfcacec..bd2d399555a78 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/iterator.h"
@@ -1777,6 +1778,11 @@ class SelectionDAG {
   /// the final TokenFactor has less than 64k operands.
   LLVM_ABI SDValue getTokenFactor(const SDLoc &DL,
                                   SmallVectorImpl<SDValue> &Vals);
+  template <unsigned FlagBits>
+  SDValue getTokenFactor(const SDLoc &DL,
+                         SmallVectorWithFlagsImpl<SDValue, FlagBits> &Vals) {
+    return getTokenFactorImpl(DL, Vals);
+  }
 
   /// *Mutate* the specified machine node's memory references to the provided
   /// list.
@@ -2779,6 +2785,19 @@ class SelectionDAG {
                                                 ArrayRef<SDValue> Scalars);
 
 private:
+  template <typename ValueListT>
+  SDValue getTokenFactorImpl(const SDLoc &DL, ValueListT &Vals) {
+    size_t Limit = SDNode::getMaxNumOperands();
+    while (Vals.size() > Limit) {
+      unsigned SliceIdx = Vals.size() - Limit;
+      auto ExtractedTFs = ArrayRef<SDValue>(Vals).slice(SliceIdx, Limit);
+      SDValue NewTF = getNode(ISD::TokenFactor, DL, MVT::Other, ExtractedTFs);
+      Vals.erase(Vals.begin() + SliceIdx, Vals.end());
+      Vals.emplace_back(NewTF);
+    }
+    return getNode(ISD::TokenFactor, DL, MVT::Other, Vals);
+  }
+
 #ifndef NDEBUG
   void verifyNode(SDNode *N) const;
 #endif
diff --git a/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h b/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h
index 33fa71ae109ea..40b0cda564539 100644
--- a/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h
+++ b/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h
@@ -10,6 +10,7 @@
 #define LLVM_CODEGEN_SWITCHLOWERINGUTILS_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/IR/InstrTypes.h"
@@ -220,21 +221,27 @@ struct BitTestBlock {
   const Value *SValue;
   Register Reg;
   MVT RegVT;
-  bool Emitted;
-  bool ContiguousRange;
+  bool getEmitted() const { return Cases.getFlag(0); }
+  void setEmitted(bool Value) { Cases.setFlag(0, Value); }
+  bool getContiguousRange() const { return Cases.getFlag(1); }
+  void setContiguousRange(bool Value) { Cases.setFlag(1, Value); }
   MachineBasicBlock *Parent;
   MachineBasicBlock *Default;
-  BitTestInfo Cases;
+  llvm::SmallVectorWithFlagsFor<BitTestInfo, 3> Cases;
   BranchProbability Prob;
   BranchProbability DefaultProb;
-  bool FallthroughUnreachable = false;
+  bool getFallthroughUnreachable() const { return Cases.getFlag(2); }
+  bool setFallthroughUnreachable(bool Value) {
+    Cases.setFlag(2, Value);
+    return Value;
+  }
 
   BitTestBlock(APInt F, APInt R, const Value *SV, Register Rg, MVT RgVT, bool E,
                bool CR, MachineBasicBlock *P, MachineBasicBlock *D,
                BitTestInfo C, BranchProbability Pr)
       : First(std::move(F)), Range(std::move(R)), SValue(SV), Reg(Rg),
-        RegVT(RgVT), Emitted(E), ContiguousRange(CR), Parent(P), Default(D),
-        Cases(std::move(C)), Prob(Pr) {}
+        RegVT(RgVT), Parent(P), Default(D),
+        Cases(unsigned(E) | (unsigned(CR) << 1), std::move(C)), Prob(Pr) {}
 };
 
 /// Return the range of values within a range.
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 616ae3e0b7747..877a8a52fba42 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -26,6 +26,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/DAGCombine.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
@@ -4978,10 +4979,11 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
   /// described by the Ins array, into the specified DAG. The implementation
   /// should fill in the InVals array with legal-type argument values, and
   /// return the resulting token chain value.
-  virtual SDValue LowerFormalArguments(
-      SDValue /*Chain*/, CallingConv::ID /*CallConv*/, bool /*isVarArg*/,
-      const SmallVectorImpl<ISD::InputArg> & /*Ins*/, const SDLoc & /*dl*/,
-      SelectionDAG & /*DAG*/, SmallVectorImpl<SDValue> & /*InVals*/) const {
+  virtual SDValue
+  LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
+                       bool /*isVarArg*/, llvm::ArrayRef<ISD::InputArg> /*Ins*/,
+                       const SDLoc & /*dl*/, SelectionDAG & /*DAG*/,
+                       SmallVectorImpl<SDValue> & /*InVals*/) const {
     llvm_unreachable("Not Implemented");
   }
 
@@ -5013,23 +5015,44 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
     Type *OrigRetTy = nullptr;
     /// Same as OrigRetTy, or partially legalized for soft float libcalls.
     Type *RetTy = nullptr;
-    bool RetSExt           : 1;
-    bool RetZExt           : 1;
-    bool IsVarArg          : 1;
-    bool IsInReg           : 1;
-    bool DoesNotReturn     : 1;
-    bool IsReturnValueUsed : 1;
-    bool IsConvergent      : 1;
-    bool IsPatchPoint      : 1;
-    bool IsPreallocated : 1;
-    bool NoMerge           : 1;
+    bool getRetSExt() const { return InVals.getFlag(0); }
+    void setRetSExt(bool Value) { InVals.setFlag(0, Value); }
+    bool getRetZExt() const { return InVals.getFlag(1); }
+    void setRetZExt(bool Value) { InVals.setFlag(1, Value); }
+    bool getIsVarArg() const { return InVals.getFlag(2); }
+    bool setIsVarArg(bool Value) {
+      InVals.setFlag(2, Value);
+      return Value;
+    }
+    bool getIsInReg() const { return InVals.getFlag(3); }
+    void setIsInReg(bool Value) { InVals.setFlag(3, Value); }
+    bool getDoesNotReturn() const { return Ins.getFlag(0); }
+    bool setDoesNotReturn(bool Value) {
+      Ins.setFlag(0, Value);
+      return Value;
+    }
+    bool getIsReturnValueUsed() const { return Ins.getFlag(1); }
+    void setIsReturnValueUsed(bool Value) { Ins.setFlag(1, Value); }
+    bool getIsConvergent() const { return Ins.getFlag(2); }
+    void setIsConvergent(bool Value) { Ins.setFlag(2, Value); }
+    bool getIsPatchPointFlag() const { return Ins.getFlag(3); }
+    void setIsPatchPointFlag(bool Value) { Ins.setFlag(3, Value); }
+    bool getIsPreallocatedFlag() const { return Outs.getFlag(0); }
+    void setIsPreallocatedFlag(bool Value) { Outs.setFlag(0, Value); }
+    bool getNoMerge() const { return Outs.getFlag(1); }
+    void setNoMerge(bool Value) { Outs.setFlag(1, Value); }
 
     // IsTailCall should be modified by implementations of
     // TargetLowering::LowerCall that perform tail call conversions.
-    bool IsTailCall = false;
+    bool getIsTailCall() const { return Outs.getFlag(2); }
+    bool setIsTailCall(bool Value) {
+      Outs.setFlag(2, Value);
+      return Value;
+    }
 
     // Is Call lowering done post SelectionDAG type legalization.
-    bool IsPostTypeLegalization = false;
+    bool getIsPostTypeLegalizationFlag() const { return Outs.getFlag(3); }
+    void setIsPostTypeLegalizationFlag(bool Value) { Outs.setFlag(3, Value); }
 
     unsigned NumFixedArgs = -1;
     CallingConv::ID CallConv = CallingConv::C;
@@ -5038,10 +5061,10 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
     SelectionDAG &DAG;
     SDLoc DL;
     const CallBase *CB = nullptr;
-    SmallVector<ISD::OutputArg, 32> Outs;
+    llvm::SmallVectorWithFlags<ISD::OutputArg, 32, 4> Outs;
     SmallVector<SDValue, 32> OutVals;
-    SmallVector<ISD::InputArg, 32> Ins;
-    SmallVector<SDValue, 4> InVals;
+    llvm::SmallVectorWithFlags<ISD::InputArg, 32, 4> Ins;
+    llvm::SmallVectorWithFlags<SDValue, 4, 4> InVals;
     const ConstantInt *CFIType = nullptr;
     SDValue ConvergenceControlToken;
     GlobalValue *DeactivationSymbol = nullptr;
@@ -5049,10 +5072,7 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
     std::optional<PtrAuthInfo> PAI;
 
     CallLoweringInfo(SelectionDAG &DAG)
-        : RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false),
-          DoesNotReturn(false), IsReturnValueUsed(true), IsConvergent(false),
-          IsPatchPoint(false), IsPreallocated(false), NoMerge(false),
-          DAG(DAG) {}
+        : DAG(DAG), Ins(decltype(this->Ins)::withFlags(2)) {}
 
     CallLoweringInfo &setDebugLoc(const SDLoc &dl) {
       DL = dl;
@@ -5090,10 +5110,10 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
                                 SDValue Target, ArgListTy &&ArgsList,
                                 AttributeSet ResultAttrs = {}) {
       RetTy = OrigRetTy = ResultType;
-      IsInReg = ResultAttrs.hasAttribute(Attribute::InReg);
-      RetSExt = ResultAttrs.hasAttribute(Attribute::SExt);
-      RetZExt = ResultAttrs.hasAttribute(Attribute::ZExt);
-      NoMerge = ResultAttrs.hasAttribute(Attribute::NoMerge);
+      setIsInReg(ResultAttrs.hasAttribute(Attribute::InReg));
+      setRetSExt(ResultAttrs.hasAttribute(Attribute::SExt));
+      setRetZExt(ResultAttrs.hasAttribute(Attribute::ZExt));
+      setNoMerge(ResultAttrs.hasAttribute(Attribute::NoMerge));
 
       Callee = Target;
       CallConv = CC;
@@ -5107,15 +5127,15 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
                                 const CallBase &Call) {
       RetTy = OrigRetTy = ResultType;
 
-      IsInReg = Call.hasRetAttr(Attribute::InReg);
-      DoesNotReturn =
+      setIsInReg(Call.hasRetAttr(Attribute::InReg));
+      setDoesNotReturn(
           Call.doesNotReturn() ||
-          (!isa<InvokeInst>(Call) && isa<UnreachableInst>(Call.getNextNode()));
-      IsVarArg = FTy->isVarArg();
-      IsReturnValueUsed = !Call.use_empty();
-      RetSExt = Call.hasRetAttr(Attribute::SExt);
-      RetZExt = Call.hasRetAttr(Attribute::ZExt);
-      NoMerge = Call.hasFnAttr(Attribute::NoMerge);
+          (!isa<InvokeInst>(Call) && isa<UnreachableInst>(Call.getNextNode())));
+      setIsVarArg(FTy->isVarArg());
+      setIsReturnValueUsed(!Call.use_empty());
+      setRetSExt(Call.hasRetAttr(Attribute::SExt));
+      setRetZExt(Call.hasRetAttr(Attribute::ZExt));
+      setNoMerge(Call.hasFnAttr(Attribute::NoMerge));
 
       Callee = Target;
 
@@ -5129,52 +5149,52 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
     }
 
     CallLoweringInfo &setInRegister(bool Value = true) {
-      IsInReg = Value;
+      setIsInReg(Value);
       return *this;
     }
 
     CallLoweringInfo &setNoReturn(bool Value = true) {
-      DoesNotReturn = Value;
+      setDoesNotReturn(Value);
       return *this;
     }
 
     CallLoweringInfo &setVarArg(bool Value = true) {
-      IsVarArg = Value;
+      setIsVarArg(Value);
       return *this;
     }
 
     CallLoweringInfo &setTailCall(bool Value = true) {
-      IsTailCall = Value;
+      setIsTailCall(Value);
       return *this;
     }
 
     CallLoweringInfo &setDiscardResult(bool Value = true) {
-      IsReturnValueUsed = !Value;
+      setIsReturnValueUsed(!Value);
       return *this;
     }
 
     CallLoweringInfo &setConvergent(bool Value = true) {
-      IsConvergent = Value;
+      setIsConvergent(Value);
       return *this;
     }
 
     CallLoweringInfo &setSExtResult(bool Value = true) {
-      RetSExt = Value;
+      setRetSExt(Value);
       return *this;
     }
 
     CallLoweringInfo &setZExtResult(bool Value = true) {
-      RetZExt = Value;
+      setRetZExt(Value);
       return *this;
     }
 
     CallLoweringInfo &setIsPatchPoint(bool Value = true) {
-      IsPatchPoint = Value;
+      setIsPatchPointFlag(Value);
       return *this;
     }
 
     CallLoweringInfo &setIsPreallocated(bool Value = true) {
-      IsPreallocated = Value;
+      setIsPreallocatedFlag(Value);
       return *this;
     }
 
@@ -5184,7 +5204,7 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
     }
 
     CallLoweringInfo &setIsPostTypeLegalization(bool Value=true) {
-      IsPostTypeLegalization = Value;
+      setIsPostTypeLegalizationFlag(Value);
       return *this;
     }
 
@@ -5285,10 +5305,10 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
   /// described by the Outs array can fit into the return registers.  If false
   /// is returned, an sret-demotion is performed.
   virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/,
-                              MachineFunction &/*MF*/, bool /*isVarArg*/,
-               const SmallVectorImpl<ISD::OutputArg> &/*Outs*/,
-               LLVMContext &/*Context*/, const Type *RetTy) const
-  {
+                              MachineFunction & /*MF*/, bool /*isVarArg*/,
+                              llvm::ArrayRef<ISD::OutputArg> /*Outs*/,
+                              LLVMContext & /*Context*/,
+                              const Type *RetTy) const {
     // Return true by default to get preexisting behavior.
     return true;
   }
@@ -5302,7 +5322,7 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
   /// return the resulting token chain value.
   virtual SDValue LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/,
                               bool /*isVarArg*/,
-                              const SmallVectorImpl<ISD::OutputArg> & /*Outs*/,
+                              llvm::ArrayRef<ISD::OutputArg> /*Outs*/,
                               const SmallVectorImpl<SDValue> & /*OutVals*/,
                               const SDLoc & /*dl*/,
                               SelectionDAG & /*DAG*/) const {
diff --git a/llvm/include/llvm/CodeGen/TargetSchedule.h b/llvm/include/llvm/CodeGen/TargetSchedule.h
index eee87c0398abd..d7342993b057c 100644
--- a/llvm/include/llvm/CodeGen/TargetSchedule.h
+++ b/llvm/include/llvm/CodeGen/TargetSchedule.h
@@ -16,6 +16,7 @@
 #define LLVM_CODEGEN_TARGETSCHEDULE_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/MC/MCInstrItineraries.h"
@@ -36,7 +37,7 @@ class TargetSchedModel {
   const TargetSubtargetInfo *STI = nullptr;
   const TargetInstrInfo *TII = nullptr;
 
-  SmallVector<unsigned, 16> ResourceFactors;
+  llvm::SmallVectorWithFlags<unsigned, 16, 2> ResourceFactors;
 
   // Multiply to normalize microops to resource units.
   unsigned MicroOpFactor = 0;
@@ -53,8 +54,10 @@ class TargetSchedModel {
   // can force preference of the other. By disabling both, we will throw away
   // any target specific hardware details for scheduling decisions, and fall
   // into things that provide generic info such as defaultDefLatency.
-  bool EnableSchedModel = true;
-  bool EnableSchedItins = true;
+  bool getEnableSchedModel() const { return !ResourceFactors.getFlag(0); }
+  void setEnableSchedModel(bool Value) { ResourceFactors.setFlag(0, !Value); }
+  bool getEnableSchedItins() const { return !ResourceFactors.getFlag(1); }
+  void setEnableSchedItins(bool Value) { ResourceFactors.setFlag(1, !Value); }
 
 public:
   TargetSchedModel() : SchedModel(MCSchedModel::Default) {}
diff --git a/llvm/include/llvm/DTLTO/DTLTO.h b/llvm/include/llvm/DTLTO/DTLTO.h
index 9213a84ff57e5..999e18394e955 100644
--- a/llvm/include/llvm/DTLTO/DTLTO.h
+++ b/llvm/include/llvm/DTLTO/DTLTO.h
@@ -18,6 +18,7 @@
 
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/ThreadPool.h"
@@ -56,9 +57,11 @@ class LLVM_ABI DTLTO : public LTO {
         bool SaveTempsArg)
       : Base(std::move(Conf), writeIndexesBackendInstance(),
              ParallelCodeGenParallelismLevel, LTOMode),
-        AddBuffer(AddBufferArg), SaveTemps(SaveTempsArg),
-        ShouldEmitIndexFiles(EmitIndexFiles),
-        ShouldEmitImportFiles(EmitImportsFiles), OnIndexWriteCb(OnWrite),
+        AddBuffer(AddBufferArg),
+        Jobs(decltype(this->Jobs)::withFlags(
+            unsigned(SaveTempsArg) | (unsigned(EmitIndexFiles) << 1) |
+            (unsigned(EmitImportsFiles) << 2))),
+        OnIndexWriteCb(OnWrite),
         DistributorParams{Distributor,        DistributorArgs,
                           RemoteCompiler,     RemoteCompilerPrependArgs,
                           RemoteCompilerArgs, LinkerOutputFile} {
@@ -138,7 +141,8 @@ class LLVM_ABI DTLTO : public LTO {
   // Normalized output directory from LinkerOutputFile.
   SString LinkerOutputDir;
   // Keep temporary files when true.
-  bool SaveTemps = false;
+  bool getSaveTemps() const { return Jobs.getFlag(0); }
+  void setSaveTemps(bool Value) { Jobs.setFlag(0, Value); }
 
   // Saves the content of Buffer to Path overwriting any existing file.
   static Error save(StringRef Buffer, StringRef Path);
@@ -168,7 +172,9 @@ class LLVM_ABI DTLTO : public LTO {
 
 private:
   // Backend compilation jobs, one per module.
-  SmallVector<Job> Jobs;
+  llvm::SmallVectorWithFlags<
+      Job, llvm::CalculateSmallVectorDefaultInlinedElements<Job>::value, 3>
+      Jobs;
   // Input module IDs that must be extracted to individual files.
   DenseSet<StringRef> InputModuleIDsToExtract;
   // Task index offset for first ThinLTO job.
@@ -176,9 +182,11 @@ class LLVM_ABI DTLTO : public LTO {
   // Optional cache for native objects.
   FileCache Cache;
   // Keep summary index files when true.
-  bool ShouldEmitIndexFiles = false;
+  bool getShouldEmitIndexFiles() const { return Jobs.getFlag(1); }
+  void setShouldEmitIndexFiles(bool Value) { Jobs.setFlag(1, Value); }
   // Keep summary import files when true.
-  bool ShouldEmitImportFiles = false;
+  bool getShouldEmitImportFiles() const { return Jobs.getFlag(2); }
+  void setShouldEmitImportFiles(bool Value) { Jobs.setFlag(2, Value); }
   // On index file write callback.
   IndexWriteCallback OnIndexWriteCb;
 
diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
index 4ba1f007b0d00..1e4719061289c 100644
--- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AccelTable.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
@@ -256,20 +257,20 @@ class LLVM_ABI DWARFLinker : public DWARFLinkerBase {
 
   /// Verify the input DWARF.
   void setVerifyInputDWARF(bool Verify) override {
-    Options.VerifyInputDWARF = Verify;
+    Options.setVerifyInputDWARF(Verify);
   }
 
   /// Do not unique types according to ODR.
-  void setNoODR(bool NoODR) override { Options.NoODR = NoODR; }
+  void setNoODR(bool NoODR) override { Options.setNoODR(NoODR); }
 
   /// Update index tables only(do not modify rest of DWARF).
   void setUpdateIndexTablesOnly(bool Update) override {
-    Options.Update = Update;
+    Options.setUpdate(Update);
   }
 
   /// Set whether to keep the enclosing function for a static variable.
   void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {
-    Options.KeepFunctionForStatic = KeepFunctionForStatic;
+    Options.setKeepFunctionForStatic(KeepFunctionForStatic);
   }
 
   /// Use specified number of threads for parallel files linking.
@@ -807,23 +808,27 @@ class LLVM_ABI DWARFLinker : public DWARFLinkerBase {
     bool Statistics = false;
 
     /// Verify the input DWARF.
-    bool VerifyInputDWARF = false;
+    bool getVerifyInputDWARF() const { return AccelTables.getFlag(0); }
+    void setVerifyInputDWARF(bool Value) { AccelTables.setFlag(0, Value); }
 
     /// Do not unique types according to ODR
-    bool NoODR = false;
+    bool getNoODR() const { return AccelTables.getFlag(1); }
+    void setNoODR(bool Value) { AccelTables.setFlag(1, Value); }
 
     /// Update
-    bool Update = false;
+    bool getUpdate() const { return AccelTables.getFlag(2); }
+    void setUpdate(bool Value) { AccelTables.setFlag(2, Value); }
 
     /// Whether we want a static variable to force us to keep its enclosing
     /// function.
-    bool KeepFunctionForStatic = false;
+    bool getKeepFunctionForStatic() const { return AccelTables.getFlag(3); }
+    void setKeepFunctionForStatic(bool Value) { AccelTables.setFlag(3, Value); }
 
     /// Number of threads.
     unsigned Threads = 1;
 
     /// The accelerator table kinds
-    SmallVector<AccelTableKind, 1> AccelTables;
+    llvm::SmallVectorWithFlags<AccelTableKind, 1, 4> AccelTables;
 
     /// Prepend path for the clang modules.
     std::string PrependPath;
diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h
index f4662aa347088..3a18e447f1100 100644
--- a/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/llvm/include/llvm/DebugInfo/DIContext.h
@@ -15,6 +15,7 @@
 #define LLVM_DEBUGINFO_DICONTEXT_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/WithColor.h"
@@ -209,11 +210,14 @@ struct DIDumpOptions {
   bool DisplayRawContents = false;
   bool IsEH = false;
   bool DumpNonSkeleton = false;
-  bool ShowAggregateErrors = false;
-  bool PrintRegisterOnly = false;
+  bool showAggregateErrors() const { return FilterChildTag.getFlag(0); }
+  void setShowAggregateErrors(bool Show) { FilterChildTag.setFlag(0, Show); }
+  bool printRegisterOnly() const { return FilterChildTag.getFlag(1); }
+  void setPrintRegisterOnly(bool Print) { FilterChildTag.setFlag(1, Print); }
   std::string JsonErrSummaryFile;
   /// List of DWARF tags to filter children by.
-  llvm::SmallVector<unsigned, 0> FilterChildTag;
+  // Flag bits 0 and 1 enable aggregate errors and register-only printing.
+  llvm::SmallVectorWithFlags<unsigned, 0, 2> FilterChildTag;
   std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
       GetNameForDWARFReg;
   /// The target of the object being dumped.
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index c510103a448d4..6f41f673f6dd8 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -10,6 +10,7 @@
 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Support/Error.h"
@@ -102,11 +103,12 @@ class DWARFDebugMacro {
     // a macinfo[.dwo] section which doesn't have header itself, hence
     // for that case other fields in the `Header` are uninitialized.
     MacroHeader Header;
-    SmallVector<Entry, 4> Macros;
+    llvm::SmallVectorWithFlags<Entry, 4> Macros;
     uint64_t Offset;
 
     /// Whether or not this is a .debug_macro section.
-    bool IsDebugMacro;
+    bool getIsDebugMacro() const { return Macros.getFlag(0); }
+    void setIsDebugMacro(bool Value) { Macros.setFlag(0, Value); }
   };
 
   /// A list of all the macro entries in the debug_macinfo section.
diff --git a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
index 2b6a3a6620be8..49e2cf191edef 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFEXPRESSION_H
 #define LLVM_DEBUGINFO_DWARF_LOWLEVEL_DWARFEXPRESSION_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -89,10 +90,14 @@ class DWARFExpression {
 
     uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
     Description Desc;
-    bool Error = false;
+    bool getError() const { return OperandEndOffsets.getFlag(0); }
+    bool setError(bool Value) {
+      OperandEndOffsets.setFlag(0, Value);
+      return Value;
+    }
     uint64_t EndOffset;
     SmallVector<uint64_t> Operands;
-    SmallVector<uint64_t> OperandEndOffsets;
+    llvm::SmallVectorWithFlags<uint64_t> OperandEndOffsets;
 
   public:
     const Description &getDescription() const { return Desc; }
@@ -108,7 +113,7 @@ class DWARFExpression {
       return OperandEndOffsets[Idx];
     }
     uint64_t getEndOffset() const { return EndOffset; }
-    bool isError() const { return Error; }
+    bool isError() const { return getError(); }
 
   private:
     LLVM_ABI bool extract(DataExtractor Data, uint8_t AddressSize,
@@ -126,9 +131,9 @@ class DWARFExpression {
     Operation Op;
     iterator(const DWARFExpression *Expr, uint64_t Offset)
         : Expr(Expr), Offset(Offset) {
-      Op.Error =
+      Op.setError(
           Offset >= Expr->Data.getData().size() ||
-          !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
+          !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format));
     }
 
   public:
@@ -137,9 +142,9 @@ class DWARFExpression {
 
     iterator &operator++() {
       Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
-      Op.Error =
+      Op.setError(
           Offset >= Expr->Data.getData().size() ||
-          !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
+          !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format));
       return *this;
     }
 
diff --git a/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
index 27399d93fe587..4077a5d3f3ea9 100644
--- a/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -17,6 +17,7 @@
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
@@ -114,24 +115,28 @@ class LLVM_ABI ExecutionEngine {
   const DataLayout DL;
 
   /// Whether lazy JIT compilation is enabled.
-  bool CompilingLazily;
+  bool getCompilingLazily() const { return Modules.getFlag(0); }
+  void setCompilingLazily(bool Value) { Modules.setFlag(0, Value); }
 
   /// Whether JIT compilation of external global variables is allowed.
-  bool GVCompilationDisabled;
+  bool getGVCompilationDisabled() const { return Modules.getFlag(1); }
+  void setGVCompilationDisabled(bool Value) { Modules.setFlag(1, Value); }
 
   /// Whether the JIT should perform lookups of external symbols (e.g.,
   /// using dlsym).
-  bool SymbolSearchingDisabled;
+  bool getSymbolSearchingDisabled() const { return Modules.getFlag(2); }
+  void setSymbolSearchingDisabled(bool Value) { Modules.setFlag(2, Value); }
 
   /// Whether the JIT should verify IR modules during compilation.
-  bool VerifyModules;
+  bool getVerifyModulesFlag() const { return Modules.getFlag(3); }
+  void setVerifyModulesFlag(bool Value) { Modules.setFlag(3, Value); }
 
   friend class EngineBuilder;  // To allow access to JITCtor and InterpCtor.
 
 protected:
   /// The list of Modules that we are JIT'ing from.  We use a SmallVector to
   /// optimize for the case where there is only one module.
-  SmallVector<std::unique_ptr<Module>, 1> Modules;
+  llvm::SmallVectorWithFlags<std::unique_ptr<Module>, 1, 4> Modules;
 
   /// getMemoryforGV - Allocate memory for a global variable.
   virtual char *getMemoryForGV(const GlobalVariable *GV);
@@ -457,42 +462,34 @@ class LLVM_ABI ExecutionEngine {
   /// (ExecutionEngine::lock) or otherwise ensure that no other thread calls a
   /// lazy stub.  See http://llvm.org/PR5184 for details.
   void DisableLazyCompilation(bool Disabled = true) {
-    CompilingLazily = !Disabled;
-  }
-  bool isCompilingLazily() const {
-    return CompilingLazily;
+    setCompilingLazily(!Disabled);
   }
+  bool isCompilingLazily() const { return getCompilingLazily(); }
 
   /// DisableGVCompilation - If called, the JIT will abort if it's asked to
   /// allocate space and populate a GlobalVariable that is not internal to
   /// the module.
   void DisableGVCompilation(bool Disabled = true) {
-    GVCompilationDisabled = Disabled;
-  }
-  bool isGVCompilationDisabled() const {
-    return GVCompilationDisabled;
+    setGVCompilationDisabled(Disabled);
   }
+  bool isGVCompilationDisabled() const { return getGVCompilationDisabled(); }
 
   /// DisableSymbolSearching - If called, the JIT will not try to lookup unknown
   /// symbols with dlsym.  A client can still use InstallLazyFunctionCreator to
   /// resolve symbols in a custom way.
   void DisableSymbolSearching(bool Disabled = true) {
-    SymbolSearchingDisabled = Disabled;
+    setSymbolSearchingDisabled(Disabled);
   }
   bool isSymbolSearchingDisabled() const {
-    return SymbolSearchingDisabled;
+    return getSymbolSearchingDisabled();
   }
 
   /// Enable/Disable IR module verification.
   ///
   /// Note: Module verification is enabled by default in Debug builds, and
   /// disabled by default in Release. Use this method to override the default.
-  void setVerifyModules(bool Verify) {
-    VerifyModules = Verify;
-  }
-  bool getVerifyModules() const {
-    return VerifyModules;
-  }
+  void setVerifyModules(bool Verify) { setVerifyModulesFlag(Verify); }
+  bool getVerifyModules() const { return getVerifyModulesFlag(); }
 
   /// InstallLazyFunctionCreator - If an unknown function is needed, the
   /// specified function pointer is invoked to create it.  If it returns null,
@@ -545,9 +542,11 @@ class EngineBuilder {
   std::optional<CodeModel::Model> CMModel;
   std::string MArch;
   std::string MCPU;
-  SmallVector<std::string, 4> MAttrs;
-  bool VerifyModules;
-  bool EmulatedTLS = true;
+  llvm::SmallVectorWithFlags<std::string, 4, 2> MAttrs;
+  bool getVerifyModulesFlag() const { return MAttrs.getFlag(0); }
+  void setVerifyModulesFlag(bool Value) { MAttrs.setFlag(0, Value); }
+  bool getEmulatedTLSFlag() const { return !MAttrs.getFlag(1); }
+  void setEmulatedTLSFlag(bool Value) { MAttrs.setFlag(1, !Value); }
 
 public:
   /// Default constructor for EngineBuilder.
@@ -632,7 +631,7 @@ class EngineBuilder {
   /// setVerifyModules - Set whether the JIT implementation should verify
   /// IR modules during compilation.
   EngineBuilder &setVerifyModules(bool Verify) {
-    VerifyModules = Verify;
+    setVerifyModulesFlag(Verify);
     return *this;
   }
 
@@ -645,16 +644,16 @@ class EngineBuilder {
   }
 
   void setEmulatedTLS(bool EmulatedTLS) {
-    this->EmulatedTLS = EmulatedTLS;
+    this->setEmulatedTLSFlag(EmulatedTLS);
   }
 
   LLVM_ABI TargetMachine *selectTarget();
 
   /// selectTarget - Pick a target either via -march or by guessing the native
   /// arch.  Add any CPU features specified via -mcpu or -mattr.
-  LLVM_ABI TargetMachine *
-  selectTarget(const Triple &TargetTriple, StringRef MArch, StringRef MCPU,
-               const SmallVectorImpl<std::string> &MAttrs);
+  LLVM_ABI TargetMachine *selectTarget(const Triple &TargetTriple,
+                                       StringRef MArch, StringRef MCPU,
+                                       ArrayRef<std::string> MAttrs);
 
   ExecutionEngine *create() {
     return create(selectTarget());
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/LibraryScanner.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/LibraryScanner.h
index 5bc8ed7a14dbc..b5f3097b3c032 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/LibraryScanner.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/LibraryScanner.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/FunctionExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Object/ObjectFile.h"
@@ -488,8 +489,12 @@ class LibraryScanner {
 
     SmallVector<StringRef, 2> rpath;
     SmallVector<StringRef, 2> runPath;
-    SmallVector<StringRef, 4> deps;
-    bool isPIE = false;
+    llvm::SmallVectorWithFlags<StringRef, 4> deps;
+    bool getIsPIE() const { return deps.getFlag(0); }
+    bool setIsPIE(bool Value) {
+      deps.setFlag(0, Value);
+      return Value;
+    }
 
     void addRPath(StringRef s) { rpath.push_back(Saver.save(s)); }
 
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 047be5cee229a..dc9e92c1ab097 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Frontend/Atomic/Atomic.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
 #include "llvm/Frontend/OpenMP/OMPGridValues.h"
@@ -513,8 +514,7 @@ class OpenMPIRBuilder {
   /// Create a new OpenMPIRBuilder operating on the given module \p M. This will
   /// not have an effect on \p M (see initialize)
   OpenMPIRBuilder(Module &M)
-      : M(M), Builder(M), OffloadInfoManager(this), T(M.getTargetTriple()),
-        IsFinalized(false) {}
+      : M(M), Builder(M), OffloadInfoManager(this), T(M.getTargetTriple()) {}
   LLVM_ABI ~OpenMPIRBuilder();
 
   class AtomicInfo : public llvm::AtomicInfo {
@@ -2678,10 +2678,15 @@ class OpenMPIRBuilder {
     PostOutlineCBTy PostOutlineCB;
     BasicBlock *EntryBB, *ExitBB, *OuterAllocBB;
     SmallVector<BasicBlock *> OuterDeallocBBs;
-    SmallVector<Value *, 2> ExcludeArgsFromAggregate;
+    llvm::SmallVectorWithFlags<Value *, 2> ExcludeArgsFromAggregate;
     SetVector<Value *> Inputs, Outputs;
     // TODO: this should be safe to enable by default
-    bool FixUpNonEntryAllocas = false;
+    bool getFixUpNonEntryAllocas() const {
+      return ExcludeArgsFromAggregate.getFlag(0);
+    }
+    void setFixUpNonEntryAllocas(bool Value) {
+      ExcludeArgsFromAggregate.setFlag(0, Value);
+    }
 
     virtual ~OutlineInfo() = default;
 
@@ -2719,7 +2724,7 @@ class OpenMPIRBuilder {
 
   /// Collection of declare target globals to rewrite uses of during
   /// device module finalizaiton.
-  SmallVector<DeclareTargetGlobalReplacement, 8>
+  llvm::SmallVectorWithFlags<DeclareTargetGlobalReplacement, 8, 2>
       DeclareTargetGlobalReplacements;
 
   /// Collection of owned canonical loop objects that eventually need to be
@@ -2985,11 +2990,12 @@ class OpenMPIRBuilder {
   /// mappers, and non-contiguous information.
   struct MapInfosTy {
     struct StructNonContiguousInfo {
-      bool IsNonContiguous = false;
+      bool getIsNonContiguous() const { return Strides.getFlag(0); }
+      void setIsNonContiguous(bool Value) { Strides.setFlag(0, Value); }
       MapDimArrayTy Dims;
       MapNonContiguousArrayTy Offsets;
       MapNonContiguousArrayTy Counts;
-      MapNonContiguousArrayTy Strides;
+      llvm::SmallVectorWithFlagsFor<MapNonContiguousArrayTy, 1> Strides;
     };
     MapValuesArrayTy BasePointers;
     MapValuesArrayTy Pointers;
@@ -4050,7 +4056,12 @@ class OpenMPIRBuilder {
   Value *emitRMWOpAsInstruction(Value *Src1, Value *Src2,
                                 AtomicRMWInst::BinOp RMWOp);
 
-  bool IsFinalized;
+  bool getIsFinalized() const {
+    return DeclareTargetGlobalReplacements.getFlag(0);
+  }
+  void setIsFinalized(bool Value) {
+    DeclareTargetGlobalReplacements.setFlag(0, Value);
+  }
 
 public:
   /// a struct to pack relevant information while generating atomic Ops
@@ -4203,13 +4214,18 @@ class OpenMPIRBuilder {
   /// \return Insertion point after generated atomic capture IR.
   /// Whether to emit special handling for IEEE 754 -0.0 == +0.0 in
   /// atomic compare operations on floating-point types.
-  bool HandleFPNegZero = false;
+  bool getHandleFPNegZeroFlag() const {
+    return DeclareTargetGlobalReplacements.getFlag(1);
+  }
+  void setHandleFPNegZeroFlag(bool Value) {
+    DeclareTargetGlobalReplacements.setFlag(1, Value);
+  }
 
   /// Set whether atomic compare should handle -0.0/+0.0 equivalence.
   /// Returns the previous value so callers can save and restore it.
   bool setHandleFPNegZero(bool FPNegZero) {
-    bool Old = HandleFPNegZero;
-    HandleFPNegZero = FPNegZero;
+    bool Old = getHandleFPNegZeroFlag();
+    setHandleFPNegZeroFlag(FPNegZero);
     return Old;
   }
 
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 64541779e726c..b1b52463c7f1e 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/DebugInfoMetadata.h"
@@ -58,8 +59,8 @@ namespace llvm {
     MapVector<MDNode *, SetVector<Metadata *>> AllMacrosPerParent;
 
     /// Track nodes that may be unresolved.
-    SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
-    bool AllowUnresolvedNodes;
+    // Flag bit 0 permits unresolved nodes.
+    SmallVectorWithFlags<TrackingMDNodeRef, 4> UnresolvedNodes;
 
     /// Each subprogram's preserved local and static local variables, labels,
     /// imported entities, and types.
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 934c838782417..55aecfcd50b9b 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
@@ -109,9 +110,6 @@ class DataLayout {
   };
 
 private:
-  bool BigEndian = false;
-  bool VectorsAreElementAligned = false;
-
   unsigned AllocaAddrSpace = 0;
   unsigned ProgramAddrSpace = 0;
   unsigned DefaultGlobalsAddrSpace = 0;
@@ -134,7 +132,8 @@ class DataLayout {
   ManglingModeT ManglingMode = MM_None;
 
   // FIXME: `unsigned char` truncates the value parsed by `parseSpecifier`.
-  SmallVector<unsigned char, 8> LegalIntWidths;
+  // Flag bits 0 and 1 record big endianness and element-aligned vectors.
+  SmallVectorWithFlags<unsigned char, 8, 2> LegalIntWidths;
 
   /// Primitive type specifications. Sorted and uniqued by type bit width.
   SmallVector<PrimitiveSpec, 6> IntSpecs;
@@ -214,11 +213,11 @@ class DataLayout {
   LLVM_ABI static Expected<DataLayout> parse(StringRef LayoutString);
 
   /// Layout endianness...
-  bool isLittleEndian() const { return !BigEndian; }
-  bool isBigEndian() const { return BigEndian; }
+  bool isLittleEndian() const { return !isBigEndian(); }
+  bool isBigEndian() const { return LegalIntWidths.getFlag(0); }
 
   /// Whether vectors are element aligned, rather than naturally aligned.
-  bool vectorsAreElementAligned() const { return VectorsAreElementAligned; }
+  bool vectorsAreElementAligned() const { return LegalIntWidths.getFlag(1); }
 
   /// Returns the string representation of the DataLayout.
   ///
diff --git a/llvm/include/llvm/IR/DroppedVariableStats.h b/llvm/include/llvm/IR/DroppedVariableStats.h
index 8a1dbd6aeb60a..6db9a74b98894 100644
--- a/llvm/include/llvm/IR/DroppedVariableStats.h
+++ b/llvm/include/llvm/IR/DroppedVariableStats.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include <tuple>
 
@@ -48,14 +49,17 @@ class DroppedVariableStats {
   DroppedVariableStats(const DroppedVariableStats &) = delete;
   void operator=(const DroppedVariableStats &) = delete;
 
-  bool getPassDroppedVariables() { return PassDroppedVariables; }
+  bool getPassDroppedVariables() { return getPassDroppedVariablesFlag(); }
 
 protected:
   LLVM_ABI void setup();
 
   LLVM_ABI void cleanup();
 
-  bool DroppedVariableStatsEnabled = false;
+  bool getDroppedVariableStatsEnabled() const { return InlinedAts.getFlag(0); }
+  void setDroppedVariableStatsEnabled(bool Value) {
+    InlinedAts.setFlag(0, Value);
+  }
   struct DebugVariables {
     /// DenseSet of VarIDs before an optimization pass has run.
     DenseSet<VarID> DebugVariablesBefore;
@@ -73,7 +77,9 @@ class DroppedVariableStats {
   /// A stack of DenseMaps, which map the name of an llvm::Function to a
   /// DenseMap of VarIDs and their inlinedAt locations before an optimization
   /// pass has run.
-  SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>> InlinedAts;
+  SmallVectorWithFlagsFor<
+      SmallVector<DenseMap<StringRef, DenseMap<VarID, DILocation *>>>, 2>
+      InlinedAts;
   /// Calculate the number of dropped variables in an llvm::Function or
   /// llvm::MachineFunction and print the relevant information to stdout.
   LLVM_ABI void calculateDroppedStatsAndPrint(
@@ -129,7 +135,8 @@ class DroppedVariableStats {
   bool isInlinedAtChildOfOrEqualTo(const DILocation *InlinedAt,
                                    const DILocation *DbgValInlinedAt);
 
-  bool PassDroppedVariables = false;
+  bool getPassDroppedVariablesFlag() const { return InlinedAts.getFlag(1); }
+  void setPassDroppedVariablesFlag(bool Value) { InlinedAts.setFlag(1, Value); }
 };
 
 } // namespace llvm
diff --git a/llvm/include/llvm/IR/LegacyPassManagers.h b/llvm/include/llvm/IR/LegacyPassManagers.h
index d25bcafc9cc05..30cea275545a7 100644
--- a/llvm/include/llvm/IR/LegacyPassManagers.h
+++ b/llvm/include/llvm/IR/LegacyPassManagers.h
@@ -256,7 +256,7 @@ class LLVM_ABI PMTopLevelManager {
       // TODO: We could consider sorting the dependency arrays within the
       // AnalysisUsage (since they are conceptually unordered).
       ID.AddBoolean(AU.getPreservesAll());
-      auto ProfileVec = [&](const SmallVectorImpl<AnalysisID>& Vec) {
+      auto ProfileVec = [&](ArrayRef<AnalysisID> Vec) {
         ID.AddInteger(Vec.size());
         for(AnalysisID AID : Vec)
           ID.AddPointer(AID);
@@ -432,7 +432,7 @@ class LLVM_ABI PMDataManager {
 
 private:
   void dumpAnalysisUsage(StringRef Msg, const Pass *P,
-                         const AnalysisUsage::VectorType &Set) const;
+                         ArrayRef<AnalysisID> Set) const;
 
   // Set of available Analysis. This information is used while scheduling
   // pass. If a pass requires an analysis which is not available then
diff --git a/llvm/include/llvm/IR/PassTimingInfo.h b/llvm/include/llvm/IR/PassTimingInfo.h
index cf2dcd33fdb96..0673ac07b50fb 100644
--- a/llvm/include/llvm/IR/PassTimingInfo.h
+++ b/llvm/include/llvm/IR/PassTimingInfo.h
@@ -16,6 +16,7 @@
 #define LLVM_IR_PASSTIMINGINFO_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -73,15 +74,17 @@ class TimePassesHandler {
   SmallVector<Timer *, 8> PassActiveTimerStack;
   /// Stack of currently active analysis timers. Analyses can request other
   /// analyses.
-  SmallVector<Timer *, 8> AnalysisActiveTimerStack;
+  llvm::SmallVectorWithFlags<Timer *, 8, 2> AnalysisActiveTimerStack;
 
   /// Custom output stream to print timing information into.
   /// By default (== nullptr) we emit time report into the stream created by
   /// CreateInfoOutputFile().
   raw_ostream *OutStream = nullptr;
 
-  bool Enabled;
-  bool PerRun;
+  bool getEnabled() const { return AnalysisActiveTimerStack.getFlag(0); }
+  void setEnabled(bool Value) { AnalysisActiveTimerStack.setFlag(0, Value); }
+  bool getPerRun() const { return AnalysisActiveTimerStack.getFlag(1); }
+  void setPerRun(bool Value) { AnalysisActiveTimerStack.setFlag(1, Value); }
 
 public:
   static constexpr StringRef PassGroupName = "pass";
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index cea66f99b99bb..ed897725614bf 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_LTO_LTO_H
 #define LLVM_LTO_LTO_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/Support/Compiler.h"
@@ -122,7 +123,7 @@ class InputFile {
   InputFile() = default;
 
   std::vector<BitcodeModule> Mods;
-  SmallVector<char, 0> Strtab;
+  llvm::SmallVectorWithFlags<char, 0, 3> Strtab;
   std::vector<Symbol> Symbols;
 
   // [begin, end) for each module
@@ -133,14 +134,17 @@ class InputFile {
   std::vector<std::pair<StringRef, Comdat::SelectionKind>> ComdatTable;
 
   MemoryBufferRef MbRef;
-  bool IsFatLTOObject = false;
+  bool getIsFatLTOObject() const { return Strtab.getFlag(0); }
+  void setIsFatLTOObject(bool Value) { Strtab.setFlag(0, Value); }
   // For distributed compilation, each input must exist as an individual
   // bitcode file on disk identified by its ModuleID. For archive members and
   // FatLTO objects, the input bitcode is a sub-section of a larger file. In
   // these cases we flag that the bitcode must be written to a temporary
   // standalone file. Effectively, extracted from its container.
-  bool ExtractForDistribution = false;
-  bool IsThinLTO = false;
+  bool getExtractForDistributionFlag() const { return Strtab.getFlag(1); }
+  void setExtractForDistributionFlag(bool Value) { Strtab.setFlag(1, Value); }
+  bool getIsThinLTO() const { return Strtab.getFlag(2); }
+  void setIsThinLTO(bool Value) { Strtab.setFlag(2, Value); }
   StringRef ArchivePath;
   StringRef MemberName;
 
@@ -215,17 +219,21 @@ class InputFile {
   MemoryBufferRef getFileBuffer() const { return MbRef; }
   // Returns true if this input should be extracted to disk for distribution.
   // See the comment on ExtractForDistribution for details.
-  bool getExtractForDistribution() const { return ExtractForDistribution; }
+  bool getExtractForDistribution() const {
+    return getExtractForDistributionFlag();
+  }
   // Mark whether this input should be extracted to disk for distribution.
   // See the comment on ExtractForDistribution for details.
-  void setExtractForDistribution(bool EFD) { ExtractForDistribution = EFD; }
+  void setExtractForDistribution(bool EFD) {
+    setExtractForDistributionFlag(EFD);
+  }
   // Returns true if this bitcode came from a FatLTO object.
-  bool isFatLTOObject() const { return IsFatLTOObject; }
+  bool isFatLTOObject() const { return getIsFatLTOObject(); }
   // Mark this bitcode as coming from a FatLTO object.
-  void fatLTOObject(bool FO) { IsFatLTOObject = FO; }
+  void fatLTOObject(bool FO) { setIsFatLTOObject(FO); }
 
   // Returns true if bitcode is ThinLTO.
-  bool isThinLTO() const { return IsThinLTO; }
+  bool isThinLTO() const { return getIsThinLTO(); }
 
   // Store an archive path and a member name.
   void setArchivePathAndName(StringRef Path, StringRef Name) {
@@ -640,7 +648,10 @@ class LLVM_ABI LTO {
 
   Error checkPartiallySplit();
 
-  mutable bool CalledGetMaxTasks = false;
+  bool getCalledGetMaxTasks() const { return BitcodeLibFuncs.getFlag(0); }
+  void setCalledGetMaxTasks(bool Value) const {
+    BitcodeLibFuncs.setFlag(0, Value);
+  }
 
 protected:
   // LTO mode when using Unified LTO.
@@ -672,7 +683,7 @@ class LLVM_ABI LTO {
   // LibFuncs that were implemented in bitcode but were not extracted
   // from their libraries. Such functions cannot safely be called, since
   // they have lost their opportunity to be defined.
-  SmallVector<StringRef> BitcodeLibFuncs;
+  mutable llvm::SmallVectorWithFlags<StringRef> BitcodeLibFuncs;
 
 public:
   /// Helper to emit an optimization remark during the LTO link when outside of
diff --git a/llvm/include/llvm/MC/DXContainerInfo.h b/llvm/include/llvm/MC/DXContainerInfo.h
index 7f1744034866d..bdf3b4990d3c7 100644
--- a/llvm/include/llvm/MC/DXContainerInfo.h
+++ b/llvm/include/llvm/MC/DXContainerInfo.h
@@ -10,6 +10,7 @@
 #define LLVM_MC_DXCONTAINERINFO_H
 
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 
 namespace llvm {
@@ -128,8 +129,10 @@ struct SourceInfo {
 /// modifiable format, and can be used to serialize the data back into valid
 /// SourceInfo.
 struct SourceInfoBuilder {
-  bool IsFilled = false;
-  bool IsFinalized = false;
+  bool getIsFilled() const { return Args.getFlag(0); }
+  void setIsFilled(bool Value) { Args.setFlag(0, Value); }
+  bool getIsFinalized() const { return Args.getFlag(1); }
+  void setIsFinalized(bool Value) { Args.setFlag(1, Value); }
   SourceInfo BaseData;
   SmallString<128> CompressedContents;
 
@@ -151,7 +154,11 @@ struct SourceInfoBuilder {
 private:
   std::optional<dxbc::SourceInfo::Contents::CompressionType> CompressionType;
   SmallVector<std::pair<StringRef, StringRef>> FileNamesAndContents;
-  SmallVector<std::pair<StringRef, StringRef>> Args;
+  llvm::SmallVectorWithFlags<std::pair<StringRef, StringRef>,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 std::pair<StringRef, StringRef>>::value,
+                             2>
+      Args;
 
   void recomputeAfterCompression(uint32_t CompressedSize);
 };
diff --git a/llvm/include/llvm/MC/DXContainerPSVInfo.h b/llvm/include/llvm/MC/DXContainerPSVInfo.h
index 0de0fbb36d957..4ab25021ef059 100644
--- a/llvm/include/llvm/MC/DXContainerPSVInfo.h
+++ b/llvm/include/llvm/MC/DXContainerPSVInfo.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/MC/StringTableBuilder.h"
@@ -27,16 +28,28 @@ namespace mcdxbc {
 
 struct PSVSignatureElement {
   StringRef Name;
-  SmallVector<uint32_t> Indices;
+  llvm::SmallVectorWithFlags<uint32_t> Indices;
   uint8_t StartRow;
   uint8_t Cols;
   uint8_t StartCol;
-  bool Allocated;
+  bool getAllocated() const { return Indices.getFlag(0); }
+  void setAllocated(bool Value) { Indices.setFlag(0, Value); }
   dxbc::PSV::SemanticKind Kind;
   dxbc::PSV::ComponentType Type;
   dxbc::PSV::InterpolationMode Mode;
   uint8_t DynamicMask;
   uint8_t Stream;
+
+  PSVSignatureElement() = default;
+  PSVSignatureElement(StringRef Name, SmallVector<uint32_t> Indices,
+                      uint8_t StartRow, uint8_t Cols, uint8_t StartCol,
+                      bool Allocated, dxbc::PSV::SemanticKind Kind,
+                      dxbc::PSV::ComponentType Type,
+                      dxbc::PSV::InterpolationMode Mode, uint8_t DynamicMask,
+                      uint8_t Stream)
+      : Name(Name), Indices(unsigned(Allocated), std::move(Indices)),
+        StartRow(StartRow), Cols(Cols), StartCol(StartCol), Kind(Kind),
+        Type(Type), Mode(Mode), DynamicMask(DynamicMask), Stream(Stream) {}
 };
 
 // This data structure is a helper for reading and writing PSV RuntimeInfo data.
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 41d082765a468..3d03630ebade6 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -12,6 +12,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
@@ -57,9 +58,12 @@ class MCAssembler {
   std::unique_ptr<MCCodeEmitter> Emitter;
   std::unique_ptr<MCObjectWriter> Writer;
 
-  bool HasLayout = false;
-  bool HasFinalLayout = false;
-  bool RelaxAll = false;
+  bool getHasLayout() const { return PendingErrors.getFlag(0); }
+  void setHasLayout(bool Value) { PendingErrors.setFlag(0, Value); }
+  bool getHasFinalLayout() const { return PendingErrors.getFlag(1); }
+  void setHasFinalLayout(bool Value) { PendingErrors.setFlag(1, Value); }
+  bool getRelaxAllFlag() const { return PendingErrors.getFlag(2); }
+  void setRelaxAllFlag(bool Value) { PendingErrors.setFlag(2, Value); }
 
   // Cumulative upstream size change during `relaxOnce`. Used to compensate
   // forward-reference displacements in `evaluateFixup`.
@@ -79,7 +83,8 @@ class MCAssembler {
   };
   SmallVector<RelocDirective, 0> relocDirectives;
 
-  mutable SmallVector<std::pair<SMLoc, std::string>, 0> PendingErrors;
+  mutable llvm::SmallVectorWithFlags<std::pair<SMLoc, std::string>, 0, 3>
+      PendingErrors;
 
   MCDwarfLineTableParams LTParams;
 
@@ -196,10 +201,10 @@ class MCAssembler {
   // Layout all section and prepare them for emission.
   LLVM_ABI void layout();
 
-  bool hasLayout() const { return HasLayout; }
-  bool hasFinalLayout() const { return HasFinalLayout; }
-  bool getRelaxAll() const { return RelaxAll; }
-  void setRelaxAll(bool Value) { RelaxAll = Value; }
+  bool hasLayout() const { return getHasLayout(); }
+  bool hasFinalLayout() const { return getHasFinalLayout(); }
+  bool getRelaxAll() const { return getRelaxAllFlag(); }
+  void setRelaxAll(bool Value) { setRelaxAllFlag(Value); }
   int64_t getStretch() const { return Stretch; }
 
   bool isBundlingEnabled() const { return bool(BundleAlign); }
diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h
index 7f871f6816dbb..ea409e541bda8 100644
--- a/llvm/include/llvm/MC/MCCodeView.h
+++ b/llvm/include/llvm/MC/MCCodeView.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include <deque>
@@ -254,7 +255,7 @@ class CodeViewContext {
   };
 
   /// Array storing added file information.
-  SmallVector<FileInfo, 4> Files;
+  llvm::SmallVectorWithFlags<FileInfo, 4> Files;
 
   /// The offset of the first and last .cv_loc directive for a given function
   /// id.
@@ -268,7 +269,8 @@ class CodeViewContext {
 
   /// Indicate whether we have already laid out the checksum table addresses or
   /// not.
-  bool ChecksumOffsetsAssigned = false;
+  bool getChecksumOffsetsAssigned() const { return Files.getFlag(0); }
+  void setChecksumOffsetsAssigned(bool Value) { Files.setFlag(0, Value); }
 
   /// Append-only storage of MCCVDefRangeFragment::Ranges.
   std::deque<SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 0>>
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index 7e76abe08f56f..28888636e10ef 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -12,6 +12,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -186,13 +187,14 @@ class MCContext {
   /// Boolean toggled when .secure_log_unique / .secure_log_reset is seen to
   /// catch errors if .secure_log_unique appears twice without
   /// .secure_log_reset appearing between them.
-  bool SecureLogUsed = false;
 
   /// The compilation directory to use for DW_AT_comp_dir.
   SmallString<128> CompilationDir;
 
   /// Prefix replacement map for source file information.
-  SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
+  // Flag bits 0-3 record secure logging, temporary names, reset, and errors.
+  SmallVectorWithFlags<std::pair<std::string, std::string>, 0, 4>
+      DebugPrefixMap;
 
   /// The main file name if passed in explicitly.
   std::string MainFileName;
@@ -239,7 +241,6 @@ class MCContext {
   /// differences between temporary and non-temporary labels (primarily on
   /// Darwin).
   bool SaveTempLabels = false;
-  bool UseNamesOnTempLabels = false;
 
   /// The Compile Unit ID that we are currently processing.
   unsigned DwarfCompileUnitID = 0;
@@ -324,9 +325,6 @@ class MCContext {
   SpecificBumpPtrAllocator<MCSubtargetInfo> MCSubtargetAllocator;
 
   /// Do automatic reset in destructor
-  bool AutoReset;
-
-  bool HadError = false;
 
   void reportCommon(SMLoc Loc,
                     std::function<void(SMDiagnostic &, const SourceMgr *)>);
@@ -418,7 +416,7 @@ class MCContext {
 
   LLVM_ABI CodeViewContext &getCVContext();
 
-  void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
+  void setUseNamesOnTempLabels(bool Value) { DebugPrefixMap.setFlag(1, Value); }
 
   /// \name Module Lifetime Management
   /// @{
@@ -725,7 +723,7 @@ class MCContext {
     return getMCDwarfLineTable(CUID).getMCDwarfFiles();
   }
 
-  const SmallVectorImpl<std::string> &getMCDwarfDirs(unsigned CUID = 0) {
+  ArrayRef<std::string> getMCDwarfDirs(unsigned CUID = 0) {
     return getMCDwarfLineTable(CUID).getMCDwarfDirs();
   }
 
@@ -822,8 +820,8 @@ class MCContext {
     SecureLog = std::move(Value);
   }
 
-  bool getSecureLogUsed() { return SecureLogUsed; }
-  void setSecureLogUsed(bool Value) { SecureLogUsed = Value; }
+  bool getSecureLogUsed() { return DebugPrefixMap.getFlag(0); }
+  void setSecureLogUsed(bool Value) { DebugPrefixMap.setFlag(0, Value); }
 
   void *allocate(unsigned Size, unsigned Align = 8) {
     return Allocator.Allocate(Size, Align);
@@ -837,7 +835,7 @@ class MCContext {
     return StringSaver(Allocator).save(s);
   }
 
-  bool hadError() { return HadError; }
+  bool hadError() { return DebugPrefixMap.getFlag(3); }
   LLVM_ABI void diagnose(const SMDiagnostic &SMD);
   LLVM_ABI void reportError(SMLoc L, const Twine &Msg);
   LLVM_ABI void reportWarning(SMLoc L, const Twine &Msg);
diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h
index 3534a4f349331..7d9b923214570 100644
--- a/llvm/include/llvm/MC/MCDwarf.h
+++ b/llvm/include/llvm/MC/MCDwarf.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/StringTableBuilder.h"
@@ -277,18 +278,16 @@ struct MCDwarfLineTableParams {
 
 struct MCDwarfLineTableHeader {
   MCSymbol *Label = nullptr;
-  SmallVector<std::string, 3> MCDwarfDirs;
+  // Flag bits 0, 1 and 2 record sources, missing MD5s, and present MD5s.
+  SmallVectorWithFlags<std::string, 3, 3> MCDwarfDirs;
   SmallVector<MCDwarfFile, 3> MCDwarfFiles;
   StringMap<unsigned> SourceIdMap;
   std::string CompilationDir;
   MCDwarfFile RootFile;
-  bool HasAnySource = false;
-
-private:
-  bool HasAllMD5 = true;
-  bool HasAnyMD5 = false;
-
-public:
+  bool hasAnySource() const { return MCDwarfDirs.getFlag(0); }
+  void trackSource(bool HasSource) {
+    MCDwarfDirs.setFlag(0, hasAnySource() || HasSource);
+  }
   MCDwarfLineTableHeader() = default;
 
   LLVM_ABI Expected<unsigned> tryGetFile(StringRef &Directory,
@@ -305,15 +304,16 @@ struct MCDwarfLineTableHeader {
        ArrayRef<char> SpecialOpcodeLengths,
        std::optional<MCDwarfLineStr> &LineStr) const;
   void resetMD5Usage() {
-    HasAllMD5 = true;
-    HasAnyMD5 = false;
+    MCDwarfDirs.setFlag(1, false);
+    MCDwarfDirs.setFlag(2, false);
   }
   void trackMD5Usage(bool MD5Used) {
-    HasAllMD5 &= MD5Used;
-    HasAnyMD5 |= MD5Used;
+    MCDwarfDirs.setFlag(1, MCDwarfDirs.getFlag(1) || !MD5Used);
+    MCDwarfDirs.setFlag(2, MCDwarfDirs.getFlag(2) || MD5Used);
   }
   bool isMD5UsageConsistent() const {
-    return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
+    return MCDwarfFiles.empty() ||
+           (!MCDwarfDirs.getFlag(1) == MCDwarfDirs.getFlag(2));
   }
 
   void setRootFile(StringRef Directory, StringRef FileName,
@@ -325,7 +325,7 @@ struct MCDwarfLineTableHeader {
     RootFile.Checksum = Checksum;
     RootFile.Source = Source;
     trackMD5Usage(Checksum.has_value());
-    HasAnySource |= Source.has_value();
+    trackSource(Source.has_value());
   }
 
   void resetFileTable() {
@@ -333,7 +333,7 @@ struct MCDwarfLineTableHeader {
     MCDwarfFiles.clear();
     RootFile.Name.clear();
     resetMD5Usage();
-    HasAnySource = false;
+    MCDwarfDirs.setFlag(0, false);
   }
 
 private:
@@ -411,7 +411,7 @@ class MCDwarfLineTable {
     Header.RootFile.Checksum = Checksum;
     Header.RootFile.Source = Source;
     Header.trackMD5Usage(Checksum.has_value());
-    Header.HasAnySource |= Source.has_value();
+    Header.trackSource(Source.has_value());
   }
 
   void resetFileTable() { Header.resetFileTable(); }
@@ -432,11 +432,9 @@ class MCDwarfLineTable {
     Header.Label = Label;
   }
 
-  const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
-    return Header.MCDwarfDirs;
-  }
+  ArrayRef<std::string> getMCDwarfDirs() const { return Header.MCDwarfDirs; }
 
-  SmallVectorImpl<std::string> &getMCDwarfDirs() {
+  SmallVectorWithFlagsImpl<std::string, 3> &getMCDwarfDirs() {
     return Header.MCDwarfDirs;
   }
 
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index acd3570016265..9daa05adb71ab 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -10,6 +10,7 @@
 #define LLVM_MC_MCELFSTREAMER_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCObjectStreamer.h"
 
@@ -38,7 +39,7 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
 
   /// state management
   void reset() override {
-    SeenIdent = false;
+    setSeenIdent(false);
     MCObjectStreamer::reset();
   }
 
@@ -97,11 +98,12 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
 
   /// ELF object attributes subsection support
   struct AttributeSubSection {
-    bool IsActive;
+    bool getIsActive() const { return Content.getFlag(0); }
+    void setIsActive(bool Value) { Content.setFlag(0, Value); }
     StringRef VendorName;
     unsigned IsOptional;
     unsigned ParameterType;
-    SmallVector<AttributeItem, 64> Content;
+    llvm::SmallVectorWithFlags<AttributeItem, 64> Content;
   };
 
   // Attributes that are added and managed entirely by target.
@@ -115,6 +117,7 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
   void emitAttributesSection(StringRef Vendor, const Twine &Section,
                              unsigned Type, MCSection *&AttributeSection) {
     createAttributesSection(Vendor, Section, Type, AttributeSection, Contents);
+    Contents.clear();
   }
   void
   emitAttributesSection(MCSection *&AttributeSection, const Twine &Section,
@@ -126,16 +129,16 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
 
 private:
   AttributeItem *getAttributeItem(unsigned Attribute);
-  size_t calculateContentSize(SmallVector<AttributeItem, 64> &AttrsVec) const;
+  size_t calculateContentSize(ArrayRef<AttributeItem> AttrsVec) const;
   void createAttributesSection(StringRef Vendor, const Twine &Section,
                                unsigned Type, MCSection *&AttributeSection,
-                               SmallVector<AttributeItem, 64> &AttrsVec);
+                               ArrayRef<AttributeItem> AttrsVec);
   void createAttributesWithSubsection(
       MCSection *&AttributeSection, const Twine &Section, unsigned Type,
       SmallVector<AttributeSubSection, 64> &SubSectionVec);
 
   // GNU attributes that will get emitted at the end of the asm file.
-  SmallVector<AttributeItem, 64> GNUAttributes;
+  llvm::SmallVectorWithFlags<AttributeItem, 64> GNUAttributes;
   MCBoundaryAlignFragment *BundleBA = nullptr;
 
 public:
@@ -150,7 +153,8 @@ class LLVM_ABI MCELFStreamer : public MCObjectStreamer {
                               const MCSymbolRefExpr *&S);
   void finalizeCGProfile();
 
-  bool SeenIdent = false;
+  bool getSeenIdent() const { return GNUAttributes.getFlag(0); }
+  void setSeenIdent(bool Value) { GNUAttributes.setFlag(0, Value); }
 };
 
 LLVM_ABI MCELFStreamer *
diff --git a/llvm/include/llvm/MC/MCInstPrinter.h b/llvm/include/llvm/MC/MCInstPrinter.h
index c615d01493989..ea2f7ee8e5ac2 100644
--- a/llvm/include/llvm/MC/MCInstPrinter.h
+++ b/llvm/include/llvm/MC/MCInstPrinter.h
@@ -9,7 +9,7 @@
 #ifndef LLVM_MC_MCINSTPRINTER_H
 #define LLVM_MC_MCINSTPRINTER_H
 
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
@@ -72,12 +72,13 @@ class LLVM_ABI MCInstPrinter {
   /// If true, a branch immediate (e.g. bl 4) will be printed as a hexadecimal
   /// address (e.g. bl 0x20004). This is useful for a stream disassembler
   /// (llvm-objdump -d).
-  bool PrintBranchImmAsAddress = false;
+  bool getPrintBranchImmAsAddress() const { return ColorStack.getFlag(0); }
 
   /// If true, symbolize branch target and memory reference operands.
-  bool SymbolizeOperands = false;
+  bool getSymbolizeOperands() const { return ColorStack.getFlag(1); }
 
-  SmallVector<raw_ostream::Colors, 4> ColorStack{raw_ostream::Colors::RESET};
+  SmallVectorWithFlags<raw_ostream::Colors, 4, 2> ColorStack{
+      raw_ostream::Colors::RESET};
 
   /// Utility function for printing annotations.
   void printAnnotation(raw_ostream &OS, StringRef Annot);
@@ -165,11 +166,9 @@ class LLVM_ABI MCInstPrinter {
 
   void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; }
 
-  void setPrintBranchImmAsAddress(bool Value) {
-    PrintBranchImmAsAddress = Value;
-  }
+  void setPrintBranchImmAsAddress(bool Value) { ColorStack.setFlag(0, Value); }
 
-  void setSymbolizeOperands(bool Value) { SymbolizeOperands = Value; }
+  void setSymbolizeOperands(bool Value) { ColorStack.setFlag(1, Value); }
   void setMCInstrAnalysis(const MCInstrAnalysis *Value) { MIA = Value; }
 
   /// Utility function to print immediates in decimal or hex.
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index 7f5875c90d215..bfd38cad6b218 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCFixup.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCStreamer.h"
@@ -39,9 +40,12 @@ class raw_pwrite_stream;
 /// implementation.
 class LLVM_ABI MCObjectStreamer : public MCStreamer {
   std::unique_ptr<MCAssembler> Assembler;
-  bool EmitEHFrame;
-  bool EmitDebugFrame;
-  bool EmitSFrame;
+  bool getEmitEHFrame() const { return FragStorage.getFlag(0); }
+  void setEmitEHFrame(bool Value) { FragStorage.setFlag(0, Value); }
+  bool getEmitDebugFrame() const { return FragStorage.getFlag(1); }
+  void setEmitDebugFrame(bool Value) { FragStorage.setFlag(1, Value); }
+  bool getEmitSFrame() const { return FragStorage.getFlag(2); }
+  void setEmitSFrame(bool Value) { FragStorage.setFlag(2, Value); }
 
   struct PendingAssignment {
     MCSymbol *Symbol;
@@ -53,7 +57,7 @@ class LLVM_ABI MCObjectStreamer : public MCStreamer {
   DenseMap<const MCSymbol *, SmallVector<PendingAssignment, 1>>
       pendingAssignments;
 
-  SmallVector<std::unique_ptr<uint8_t[]>, 0> FragStorage;
+  llvm::SmallVectorWithFlags<std::unique_ptr<uint8_t[]>, 0, 4> FragStorage;
   // Available bytes in the current block for trailing data or new fragments.
   size_t FragSpace = 0;
   // Used to allocate special fragments that do not use MCFragment's fixed-size
@@ -68,7 +72,8 @@ class LLVM_ABI MCObjectStreamer : public MCStreamer {
 protected:
   // Within .bundle_lock/.bundle_unlock. A section cannot be switched while a
   // group is open, so no per-section state is needed.
-  bool BundleLocked = false;
+  bool getBundleLocked() const { return FragStorage.getFlag(3); }
+  void setBundleLocked(bool Value) { FragStorage.setFlag(3, Value); }
 
   MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
                    std::unique_ptr<MCObjectWriter> OW,
@@ -93,7 +98,7 @@ class LLVM_ABI MCObjectStreamer : public MCStreamer {
   MCAssembler &getAssembler() { return *Assembler; }
   MCAssembler *getAssemblerPtr() override;
 
-  bool isBundleLocked() const { return BundleLocked; }
+  bool isBundleLocked() const { return getBundleLocked(); }
 
   /// \name MCStreamer Interface
   /// @{
diff --git a/llvm/include/llvm/MC/MCObjectWriter.h b/llvm/include/llvm/MC/MCObjectWriter.h
index 54a8f8236f6e4..77b7a509fca85 100644
--- a/llvm/include/llvm/MC/MCObjectWriter.h
+++ b/llvm/include/llvm/MC/MCObjectWriter.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_MC_MCOBJECTWRITER_H
 #define LLVM_MC_MCOBJECTWRITER_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/TargetParser/Triple.h"
@@ -35,12 +36,11 @@ class LLVM_ABI MCObjectWriter {
 protected:
   MCAssembler *Asm = nullptr;
   /// List of declared file names
-  SmallVector<std::pair<std::string, size_t>, 0> FileNames;
+  // Flag bits 0 and 1 record addrsig and subsections-via-symbols emission.
+  SmallVectorWithFlags<std::pair<std::string, size_t>, 0, 2> FileNames;
   // XCOFF specific: Optional compiler version.
   std::string CompilerVersion;
   std::vector<const MCSymbol *> AddrsigSyms;
-  bool EmitAddrsigSection = false;
-  bool SubsectionsViaSymbols = false;
 
   struct CGProfileEntry {
     const MCSymbolRefExpr *From;
@@ -106,9 +106,9 @@ class LLVM_ABI MCObjectWriter {
   /// Tell the object writer to emit an address-significance table during
   /// writeObject(). If this function is not called, all symbols are treated as
   /// address-significant.
-  void emitAddrsigSection() { EmitAddrsigSection = true; }
+  void emitAddrsigSection() { FileNames.setFlag(0, true); }
 
-  bool getEmitAddrsigSection() { return EmitAddrsigSection; }
+  bool getEmitAddrsigSection() { return FileNames.getFlag(0); }
 
   /// Record the given symbol in the address-significance table to be written
   /// diring writeObject().
@@ -118,8 +118,8 @@ class LLVM_ABI MCObjectWriter {
   SmallVector<CGProfileEntry, 0> &getCGProfile() { return CGProfile; }
 
   // Mach-O specific: Whether .subsections_via_symbols is enabled.
-  bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; }
-  void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; }
+  bool getSubsectionsViaSymbols() const { return FileNames.getFlag(1); }
+  void setSubsectionsViaSymbols(bool Value) { FileNames.setFlag(1, Value); }
 
   /// Write the object file and returns the number of bytes written.
   ///
diff --git a/llvm/include/llvm/MC/MCParser/AsmLexer.h b/llvm/include/llvm/MC/MCParser/AsmLexer.h
index 6ab484565c0d4..5308978643471 100644
--- a/llvm/include/llvm/MC/MCParser/AsmLexer.h
+++ b/llvm/include/llvm/MC/MCParser/AsmLexer.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCAsmMacro.h"
@@ -42,7 +43,8 @@ class AsmCommentConsumer {
 
 class AsmLexer {
   /// The current token, stored in the base class for faster access.
-  SmallVector<AsmToken, 1> CurTok;
+  // Flag bit 0 selects the MASM default radix.
+  SmallVectorWithFlags<AsmToken, 1> CurTok;
 
   const char *CurPtr = nullptr;
   /// NULL-terminated buffer. NULL terminator must reside at `CurBuf.end()`.
@@ -68,7 +70,6 @@ class AsmLexer {
   bool LexMasmIntegers = false;
   bool LexMasmStrings = false;
   bool LexMotorolaIntegers = false;
-  bool UseMasmDefaultRadix = false;
   unsigned DefaultRadix = 10;
   bool LexHLASMIntegers = false;
   bool LexHLASMStrings = false;
@@ -168,7 +169,7 @@ class AsmLexer {
 
   /// Set whether to use masm-style default-radix integer literals. If disabled,
   /// assume decimal unless prefixed (e.g., 0x2c [hex], 077 [octal]).
-  void useMasmDefaultRadix(bool V) { UseMasmDefaultRadix = V; }
+  void useMasmDefaultRadix(bool V) { CurTok.setFlag(0, V); }
 
   unsigned getMasmDefaultRadix() const { return DefaultRadix; }
   void setMasmDefaultRadix(unsigned Radix) { DefaultRadix = Radix; }
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
index da5ef08381aed..0109a3c73cd3c 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -12,6 +12,7 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/MC/MCAsmMacro.h"
@@ -144,17 +145,24 @@ class LLVM_ABI MCAsmParser {
   SourceMgr &SrcMgr;
   const MCAsmInfo &MAI;
   AsmLexer Lexer;
-  SmallVector<MCPendingError, 0> PendingErrors;
+  llvm::SmallVectorWithFlags<MCPendingError, 0, 3> PendingErrors;
 
   /// Flag tracking whether any errors have been encountered.
-  bool HadError = false;
+  bool getHadError() const { return PendingErrors.getFlag(0); }
+  void setHadError(bool Value) { PendingErrors.setFlag(0, Value); }
 
-  bool ShowParsedOperands = false;
+  bool getShowParsedOperandsFlag() const { return PendingErrors.getFlag(1); }
+  void setShowParsedOperandsFlag(bool Value) {
+    PendingErrors.setFlag(1, Value);
+  }
 
   /// Flag tracking whether we're only interested in symbols, which allows us to
   /// avoid some work (e.g. resolving .incbin directives).
   // TODO: Adopt this in more places.
-  bool SymbolScanningMode = false;
+  bool getSymbolScanningModeFlag() const { return PendingErrors.getFlag(2); }
+  void setSymbolScanningModeFlag(bool Value) {
+    PendingErrors.setFlag(2, Value);
+  }
 
 public:
   MCAsmParser(const MCAsmParser &) = delete;
@@ -178,10 +186,10 @@ class LLVM_ABI MCAsmParser {
   virtual unsigned getAssemblerDialect() { return 0;}
   virtual void setAssemblerDialect(unsigned i) { }
 
-  bool getShowParsedOperands() const { return ShowParsedOperands; }
-  void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; }
+  bool getShowParsedOperands() const { return getShowParsedOperandsFlag(); }
+  void setShowParsedOperands(bool Value) { setShowParsedOperandsFlag(Value); }
 
-  void setSymbolScanningMode(bool Value) { SymbolScanningMode = Value; }
+  void setSymbolScanningMode(bool Value) { setSymbolScanningModeFlag(Value); }
 
   /// Run the parser on the input source buffer.
   virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0;
diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h
index e5b2b8ec3d1b6..df5f2569ea577 100644
--- a/llvm/include/llvm/MCA/Instruction.h
+++ b/llvm/include/llvm/MCA/Instruction.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCRegister.h" // definition of MCPhysReg.
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/MathExtras.h"
@@ -502,7 +503,8 @@ class InstructionBase {
   // This field is set for instructions that are candidates for move
   // elimination. For more information about move elimination, see the
   // definition of RegisterMappingTracker in RegisterFile.h
-  bool IsOptimizableMove;
+  bool getIsOptimizableMove() const { return Uses.getFlag(0); }
+  void setIsOptimizableMove(bool Value) { Uses.setFlag(0, Value); }
 
   // Output dependencies.
   // One entry per each implicit and explicit register definition.
@@ -510,7 +512,7 @@ class InstructionBase {
 
   // Input dependencies.
   // One entry per each implicit and explicit register use.
-  SmallVector<ReadState, 4> Uses;
+  llvm::SmallVectorWithFlags<ReadState, 4> Uses;
 
   // List of operands which can be used by mca::CustomBehaviour
   std::vector<MCAOperand> Operands;
@@ -532,12 +534,12 @@ class InstructionBase {
 
 public:
   InstructionBase(const InstrDesc &D, const unsigned Opcode)
-      : Desc(D), IsOptimizableMove(false), Operands(0), Opcode(Opcode),
-        IsALoadBarrier(false), IsAStoreBarrier(false) {}
+      : Desc(D), Operands(0), Opcode(Opcode), IsALoadBarrier(false),
+        IsAStoreBarrier(false) {}
 
   SmallVectorImpl<WriteState> &getDefs() { return Defs; }
   ArrayRef<WriteState> getDefs() const { return Defs; }
-  SmallVectorImpl<ReadState> &getUses() { return Uses; }
+  SmallVectorWithFlagsImpl<ReadState> &getUses() { return Uses; }
   ArrayRef<ReadState> getUses() const { return Uses; }
   const InstrDesc &getDesc() const { return Desc; }
 
@@ -575,9 +577,9 @@ class InstructionBase {
   }
 
   // Returns true if this instruction is a candidate for move elimination.
-  bool isOptimizableMove() const { return IsOptimizableMove; }
-  void setOptimizableMove() { IsOptimizableMove = true; }
-  void clearOptimizableMove() { IsOptimizableMove = false; }
+  bool isOptimizableMove() const { return getIsOptimizableMove(); }
+  void setOptimizableMove() { setIsOptimizableMove(true); }
+  void clearOptimizableMove() { setIsOptimizableMove(false); }
   bool isMemOp() const { return MayLoad || MayStore; }
 
   // Getters and setters for general instruction flags.
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index 1f984f68c6287..f51c513631fb9 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/ELFTypes.h"
@@ -232,8 +233,9 @@ struct CommonConfig {
   SmallVector<NewSectionInfo, 0> AddSection;
   SmallVector<StringRef, 0> DumpSection;
   SmallVector<NewSectionInfo, 0> UpdateSection;
-  SmallVector<SectionPatternAddressUpdate, 0> ChangeSectionAddress;
-  SmallVector<StringRef, 0> ExtractSection;
+  llvm::SmallVectorWithFlags<SectionPatternAddressUpdate, 0, 3>
+      ChangeSectionAddress;
+  llvm::SmallVectorWithFlags<StringRef, 0, 4> ExtractSection;
 
   // Section matchers
   NameMatcher KeepSection;
@@ -258,31 +260,58 @@ struct CommonConfig {
   StringMap<StringRef> SymbolsToRename;
 
   // Symbol info specified by --add-symbol option.
-  SmallVector<NewSymbolInfo, 0> SymbolsToAdd;
+  llvm::SmallVectorWithFlags<NewSymbolInfo, 0, 4> SymbolsToAdd;
 
   // Integer options
   int64_t ChangeSectionLMAValAll = 0;
 
   // Boolean options
-  bool DeterministicArchives = true;
-  bool ExtractDWO = false;
-  bool ExtractMainPartition = false;
-  bool OnlyKeepDebug = false;
-  bool PreserveDates = false;
-  bool StripAll = false;
-  bool StripAllGNU = false;
-  bool StripDWO = false;
-  bool StripDebug = false;
-  bool StripNonAlloc = false;
-  bool StripSections = false;
-  bool StripUnneeded = false;
-  bool Verbose = false;
-  bool Weaken = false;
-  bool DecompressDebugSections = false;
+  bool getDeterministicArchives() const { return !compressSections.getFlag(0); }
+  void setDeterministicArchives(bool Value) {
+    compressSections.setFlag(0, !Value);
+  }
+  bool getExtractDWO() const { return compressSections.getFlag(1); }
+  void setExtractDWO(bool Value) { compressSections.setFlag(1, Value); }
+  bool getExtractMainPartition() const { return compressSections.getFlag(2); }
+  void setExtractMainPartition(bool Value) {
+    compressSections.setFlag(2, Value);
+  }
+  bool getOnlyKeepDebug() const { return compressSections.getFlag(3); }
+  void setOnlyKeepDebug(bool Value) { compressSections.setFlag(3, Value); }
+  bool getPreserveDates() const { return SymbolsToAdd.getFlag(0); }
+  void setPreserveDates(bool Value) { SymbolsToAdd.setFlag(0, Value); }
+  bool getStripAll() const { return SymbolsToAdd.getFlag(1); }
+  bool setStripAll(bool Value) {
+    SymbolsToAdd.setFlag(1, Value);
+    return Value;
+  }
+  bool getStripAllGNU() const { return SymbolsToAdd.getFlag(2); }
+  void setStripAllGNU(bool Value) { SymbolsToAdd.setFlag(2, Value); }
+  bool getStripDWO() const { return SymbolsToAdd.getFlag(3); }
+  void setStripDWO(bool Value) { SymbolsToAdd.setFlag(3, Value); }
+  bool getStripDebug() const { return ExtractSection.getFlag(0); }
+  void setStripDebug(bool Value) { ExtractSection.setFlag(0, Value); }
+  bool getStripNonAlloc() const { return ExtractSection.getFlag(1); }
+  void setStripNonAlloc(bool Value) { ExtractSection.setFlag(1, Value); }
+  bool getStripSections() const { return ExtractSection.getFlag(2); }
+  void setStripSections(bool Value) { ExtractSection.setFlag(2, Value); }
+  bool getStripUnneeded() const { return ExtractSection.getFlag(3); }
+  void setStripUnneeded(bool Value) { ExtractSection.setFlag(3, Value); }
+  bool getVerbose() const { return ChangeSectionAddress.getFlag(0); }
+  void setVerbose(bool Value) { ChangeSectionAddress.setFlag(0, Value); }
+  bool getWeaken() const { return ChangeSectionAddress.getFlag(1); }
+  void setWeaken(bool Value) { ChangeSectionAddress.setFlag(1, Value); }
+  bool getDecompressDebugSections() const {
+    return ChangeSectionAddress.getFlag(2);
+  }
+  void setDecompressDebugSections(bool Value) {
+    ChangeSectionAddress.setFlag(2, Value);
+  }
 
   DebugCompressionType CompressionType = DebugCompressionType::None;
 
-  SmallVector<std::pair<NameMatcher, llvm::DebugCompressionType>, 0>
+  llvm::SmallVectorWithFlags<std::pair<NameMatcher, llvm::DebugCompressionType>,
+                             0, 4>
       compressSections;
 
   // ErrorCallback is used to handle recoverable errors. An Error returned
diff --git a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
index 01a8762cfb9c3..43e470f32e53b 100644
--- a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
+++ b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_OBJCOPY_ELF_ELFCONFIG_H
 #define LLVM_OBJCOPY_ELF_ELFCONFIG_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ObjCopy/CommonConfig.h"
 #include "llvm/Object/ELFTypes.h"
 
@@ -33,13 +34,17 @@ struct ELFConfig {
   // --change-start is used.
   std::function<uint64_t(uint64_t)> EntryExpr;
 
-  bool AllowBrokenLinks = false;
-  bool KeepFileSymbols = false;
-  bool LocalizeHidden = false;
-  bool VerifyNoteSections = true;
+  bool getAllowBrokenLinks() const { return NotesToRemove.getFlag(0); }
+  void setAllowBrokenLinks(bool Value) { NotesToRemove.setFlag(0, Value); }
+  bool getKeepFileSymbols() const { return NotesToRemove.getFlag(1); }
+  void setKeepFileSymbols(bool Value) { NotesToRemove.setFlag(1, Value); }
+  bool getLocalizeHidden() const { return NotesToRemove.getFlag(2); }
+  void setLocalizeHidden(bool Value) { NotesToRemove.setFlag(2, Value); }
+  bool getVerifyNoteSections() const { return !NotesToRemove.getFlag(3); }
+  void setVerifyNoteSections(bool Value) { NotesToRemove.setFlag(3, !Value); }
 
   // Notes specified by --remove-note option.
-  SmallVector<RemoveNoteInfo, 0> NotesToRemove;
+  llvm::SmallVectorWithFlags<RemoveNoteInfo, 0, 4> NotesToRemove;
 };
 
 } // namespace objcopy
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index cafd6ed3fa9f2..528ca3f6654a5 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
@@ -111,7 +112,8 @@ class ExportEntry {
     unsigned ParentStringLength = 0;
     bool IsExportNode = false;
   };
-  using NodeList = SmallVector<NodeState, 16>;
+  // Flag bit 0 marks the end of the export traversal.
+  using NodeList = SmallVectorWithFlags<NodeState, 16>;
   using node_iterator = NodeList::const_iterator;
 
   Error *E;
@@ -119,7 +121,6 @@ class ExportEntry {
   ArrayRef<uint8_t> Trie;
   SmallString<256> CumulativeString;
   NodeList Stack;
-  bool Done = false;
 
   iterator_range<node_iterator> nodes() const { return Stack; }
 };
@@ -767,7 +768,7 @@ class LLVM_ABI MachOObjectFile : public ObjectFile {
   llvm::binaryformat::Swift5ReflectionSectionKind
   mapReflectionSectionNameToEnumValue(StringRef SectionName) const override;
 
-  bool hasPageZeroSegment() const { return HasPageZeroSegment; }
+  bool hasPageZeroSegment() const { return getHasPageZeroSegment(); }
 
   size_t getMachOFilesetEntryOffset() const { return MachOFilesetEntryOffset; }
 
@@ -858,7 +859,7 @@ class LLVM_ABI MachOObjectFile : public ObjectFile {
   SectionList Sections;
   using LibraryList = SmallVector<const char*, 1>;
   LibraryList Libraries;
-  LoadCommandList LoadCommands;
+  llvm::SmallVectorWithFlagsFor<LoadCommandList, 1> LoadCommands;
   using LibraryShortName = SmallVector<StringRef, 1>;
   using BuildToolList = SmallVector<const char*, 1>;
   BuildToolList BuildTools;
@@ -873,7 +874,8 @@ class LLVM_ABI MachOObjectFile : public ObjectFile {
   const char *DyldChainedFixupsLoadCmd = nullptr;
   const char *DyldExportsTrieLoadCmd = nullptr;
   const char *UuidLoadCmd = nullptr;
-  bool HasPageZeroSegment = false;
+  bool getHasPageZeroSegment() const { return LoadCommands.getFlag(0); }
+  void setHasPageZeroSegment(bool Value) { LoadCommands.setFlag(0, Value); }
   size_t MachOFilesetEntryOffset = 0;
 };
 
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 0996d74d71ce4..f1c77a3673c51 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -19,6 +19,7 @@
 
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/ObjectFile.h"
@@ -94,17 +95,20 @@ class OffloadBundleFatBin {
   uint64_t Size = 0u;
   StringRef FileName;
   uint64_t NumberOfEntries;
-  bool Decompressed;
-  SmallVector<OffloadBundleEntry> Entries;
+  bool getDecompressed() const { return Entries.getFlag(0); }
+  void setDecompressed(bool Value) { Entries.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<OffloadBundleEntry> Entries;
 
 public:
   std::unique_ptr<MemoryBuffer> DecompressedBuffer;
 
-  SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
+  SmallVector<OffloadBundleEntry> getEntries() {
+    return {Entries.begin(), Entries.end()};
+  }
   uint64_t getSize() const { return Size; }
   StringRef getFileName() const { return FileName; }
   uint64_t getNumEntries() const { return NumberOfEntries; }
-  bool isDecompressed() const { return Decompressed; }
+  bool isDecompressed() const { return getDecompressed(); }
 
   LLVM_ABI static Expected<std::unique_ptr<OffloadBundleFatBin>>
   create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName,
@@ -126,8 +130,8 @@ class OffloadBundleFatBin {
 
   OffloadBundleFatBin(MemoryBufferRef Source, StringRef File,
                       bool Decompress = false)
-      : FileName(File), NumberOfEntries(0), Decompressed(Decompress),
-        Entries(SmallVector<OffloadBundleEntry>()) {
+      : FileName(File), NumberOfEntries(0),
+        Entries(decltype(this->Entries)::withFlags(unsigned(Decompress))) {
     if (Decompress)
       DecompressedBuffer =
           MemoryBuffer::getMemBufferCopy(Source.getBuffer(), File);
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 1d3e044bbb22f..f6ba733b3a779 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_OBJECTYAML_DXCONTAINERYAML_H
 #define LLVM_OBJECTYAML_DXCONTAINERYAML_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/DXContainer.h"
@@ -221,17 +222,22 @@ struct SignatureElement {
       : Name(StringTable.substr(El.NameOffset,
                                 StringTable.find('\0', El.NameOffset) -
                                     El.NameOffset)),
-        Indices(IdxTable.slice(El.IndicesOffset, El.Rows)),
+        Indices(decltype(this->Indices)::withFlags(
+            unsigned(bool(El.Allocated != 0)),
+            IdxTable.slice(El.IndicesOffset, El.Rows))),
         StartRow(El.StartRow), Cols(El.Cols), StartCol(El.StartCol),
-        Allocated(El.Allocated != 0), Kind(El.Kind), Type(El.Type),
-        Mode(El.Mode), DynamicMask(El.DynamicMask), Stream(El.Stream) {}
+        Kind(El.Kind), Type(El.Type), Mode(El.Mode),
+        DynamicMask(El.DynamicMask), Stream(El.Stream) {}
   StringRef Name;
-  SmallVector<uint32_t> Indices;
+  llvm::SmallVectorWithFlags<uint32_t> Indices;
 
   uint8_t StartRow;
   uint8_t Cols;
   uint8_t StartCol;
-  bool Allocated;
+  bool getAllocatedFlag() const { return Indices.getFlag(0); }
+  void setAllocatedFlag(bool Value) { Indices.setFlag(0, Value); }
+  bool isAllocated() const { return getAllocatedFlag(); }
+  void setAllocated(bool Value) { setAllocatedFlag(Value); }
   dxbc::PSV::SemanticKind Kind;
 
   dxbc::PSV::ComponentType Type;
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index b61ae77f64a34..51fb8249e3991 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringTable.h"
 #include "llvm/Option/OptSpecifier.h"
@@ -188,7 +189,8 @@ class LLVM_ABI OptTable {
 
   ArrayRef<InfoExtra> InfoExtrasTable;
 
-  bool IgnoreCase;
+  bool getIgnoreCase() const { return PrefixesUnion.getFlag(0); }
+  void setIgnoreCase(bool Value) { PrefixesUnion.setFlag(0, Value); }
 
   /// The subcommand information table.
   ArrayRef<SubCommand> SubCommands;
@@ -200,8 +202,8 @@ class LLVM_ABI OptTable {
 
   ValuesCodeFnTy ValuesCodeFn = nullptr;
 
-  bool GroupedShortOptions = false;
-  bool DashDashParsing = false;
+  bool getGroupedShortOptionsFlag() const { return PrefixesUnion.getFlag(1); }
+  bool getDashDashParsingFlag() const { return PrefixesUnion.getFlag(2); }
   const char *EnvVar = nullptr;
 
   unsigned InputOptionID = 0;
@@ -213,7 +215,7 @@ class LLVM_ABI OptTable {
 
   /// The union of all option prefixes. If an argument does not begin with
   /// one of these, it is an input.
-  SmallVector<StringRef> PrefixesUnion;
+  SmallVectorWithFlagsFor<SmallVector<StringRef>, 3> PrefixesUnion;
 
   /// The union of the first element of all option prefixes.
   SmallString<8> PrefixChars;
@@ -346,11 +348,11 @@ class LLVM_ABI OptTable {
   void setInitialOptionsFromEnvironment(const char *E) { EnvVar = E; }
 
   /// Support grouped short options. e.g. -ab represents -a -b.
-  void setGroupedShortOptions(bool Value) { GroupedShortOptions = Value; }
+  void setGroupedShortOptions(bool Value) { PrefixesUnion.setFlag(1, Value); }
 
   /// Set whether "--" stops option parsing and treats all subsequent arguments
   /// as positional. E.g. -- -a -b gives two positional inputs.
-  void setDashDashParsing(bool Value) { DashDashParsing = Value; }
+  void setDashDashParsing(bool Value) { PrefixesUnion.setFlag(2, Value); }
 
   /// Find possible value for given flags. This is used for shell
   /// autocompletion.
diff --git a/llvm/include/llvm/PassAnalysisSupport.h b/llvm/include/llvm/PassAnalysisSupport.h
index e81c0c4642d20..f3f4bea7c5075 100644
--- a/llvm/include/llvm/PassAnalysisSupport.h
+++ b/llvm/include/llvm/PassAnalysisSupport.h
@@ -24,6 +24,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Compiler.h"
 #include <cassert>
 #include <tuple>
@@ -57,10 +58,9 @@ class AnalysisUsage {
   SmallVector<AnalysisID, 8> Required;
   SmallVector<AnalysisID, 2> RequiredTransitive;
   SmallVector<AnalysisID, 2> Preserved;
-  SmallVector<AnalysisID, 0> Used;
-  bool PreservesAll = false;
-
-  void pushUnique(VectorType &Set, AnalysisID ID) {
+  /// Flag bit 0 records whether all analyses are preserved.
+  SmallVectorWithFlags<AnalysisID, 0> Used;
+  template <typename VectorT> void pushUnique(VectorT &Set, AnalysisID ID) {
     if (!llvm::is_contained(Set, ID))
       Set.push_back(ID);
   }
@@ -128,10 +128,10 @@ class AnalysisUsage {
   LLVM_ABI AnalysisUsage &addPreserved(StringRef Arg);
 
   /// Set by analyses that do not transform their input at all
-  void setPreservesAll() { PreservesAll = true; }
+  void setPreservesAll() { Used.setFlag(0, true); }
 
   /// Determine whether a pass said it does not transform its input at all
-  bool getPreservesAll() const { return PreservesAll; }
+  bool getPreservesAll() const { return Used.getFlag(0); }
 
   /// This function should be called by the pass, iff they do not:
   ///
@@ -147,7 +147,7 @@ class AnalysisUsage {
     return RequiredTransitive;
   }
   const VectorType &getPreservedSet() const { return Preserved; }
-  const VectorType &getUsedSet() const { return Used; }
+  ArrayRef<AnalysisID> getUsedSet() const { return Used; }
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/ProfileData/DataAccessProf.h b/llvm/include/llvm/ProfileData/DataAccessProf.h
index ea256ef7b170b..47bf621808f77 100644
--- a/llvm/include/llvm/ProfileData/DataAccessProf.h
+++ b/llvm/include/llvm/ProfileData/DataAccessProf.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Allocator.h"
@@ -68,8 +69,9 @@ struct SourceLocationRef {
 struct DataAccessProfRecordRef {
   DataAccessProfRecordRef(uint64_t SymbolID, uint64_t AccessCount,
                           bool IsStringLiteral)
-      : SymbolID(SymbolID), AccessCount(AccessCount),
-        IsStringLiteral(IsStringLiteral) {}
+      : SymbolID(SymbolID), AccessCount(AccessCount) {
+    Locations.setFlag(0, IsStringLiteral);
+  }
 
   // Represents a data symbol. The semantic comes in two forms: a symbol index
   // for symbol name if `IsStringLiteral` is false, or the hash of a string
@@ -85,10 +87,10 @@ struct DataAccessProfRecordRef {
 
   // True iff this is a record for string literal (symbols with name pattern
   // `.str.*` in the symbol table). Required.
-  bool IsStringLiteral;
+  bool isStringLiteral() const { return Locations.getFlag(0); }
 
   // The locations of data in the source code. Optional.
-  llvm::SmallVector<SourceLocationRef, 0> Locations;
+  llvm::SmallVectorWithFlags<SourceLocationRef, 0> Locations;
 };
 } // namespace internal
 
diff --git a/llvm/include/llvm/ProfileData/GCOV.h b/llvm/include/llvm/ProfileData/GCOV.h
index 62ca92b2887b5..0c28e9ffed862 100644
--- a/llvm/include/llvm/ProfileData/GCOV.h
+++ b/llvm/include/llvm/ProfileData/GCOV.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
@@ -203,11 +204,12 @@ class GCOVFile {
   StringMap<unsigned> filenameToIdx;
 
 public:
-  bool GCNOInitialized = false;
+  bool getGCNOInitialized() const { return functions.getFlag(0); }
+  void setGCNOInitialized(bool Value) { functions.setFlag(0, Value); }
   GCOV::GCOVVersion version{};
   uint32_t checksum = 0;
   StringRef cwd;
-  SmallVector<std::unique_ptr<GCOVFunction>, 16> functions;
+  llvm::SmallVectorWithFlags<std::unique_ptr<GCOVFunction>, 16> functions;
   std::map<uint32_t, GCOVFunction *> identToFunction;
   uint32_t runCount = 0;
   uint32_t programCount = 0;
@@ -316,7 +318,7 @@ class GCOVBlock {
   LLVM_ABI static uint64_t
   augmentOneCycle(GCOVBlock *src,
                   std::vector<std::pair<GCOVBlock *, size_t>> &stack);
-  LLVM_ABI static uint64_t getCyclesCount(const BlockVector &blocks);
+  LLVM_ABI static uint64_t getCyclesCount(ArrayRef<const GCOVBlock *> blocks);
 
 public:
   uint32_t number;
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index 73fb9432597cf..5278274cc380e 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/Object/BuildID.h"
@@ -42,7 +43,8 @@ class InstrProfWriter {
   using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord>;
 
 private:
-  bool Sparse;
+  bool getSparse() const { return TemporalProfTraces.getFlag(0); }
+  void setSparse(bool Value) { TemporalProfTraces.setFlag(0, Value); }
   StringMap<ProfilingData> FunctionData;
   /// The maximum length of a single temporal profile trace.
   uint64_t MaxTemporalProfTraceLength;
@@ -51,7 +53,11 @@ class InstrProfWriter {
   /// The total number of temporal profile traces seen.
   uint64_t TemporalProfTraceStreamSize = 0;
   /// The list of temporal profile traces.
-  SmallVector<TemporalProfTraceTy> TemporalProfTraces;
+  llvm::SmallVectorWithFlags<TemporalProfTraceTy,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 TemporalProfTraceTy>::value,
+                             4>
+      TemporalProfTraces;
   std::mt19937 RNG;
 
   // The MemProf data.
@@ -73,16 +79,27 @@ class InstrProfWriter {
   // new vtable names section and header fields.
   // TODO: Consider enabling this with future version changes as well, to ease
   // deployment of newer versions of llvm-profdata.
-  bool WritePrevVersion = false;
+  bool getWritePrevVersion() const { return TemporalProfTraces.getFlag(1); }
+  void setWritePrevVersion(bool Value) { TemporalProfTraces.setFlag(1, Value); }
 
   // The MemProf version we should write.
   memprof::IndexedVersion MemProfVersionRequested;
 
   // Whether to serialize the full schema.
-  bool MemProfFullSchema;
+  bool getMemProfFullSchemaFlag() const {
+    return TemporalProfTraces.getFlag(2);
+  }
+  void setMemProfFullSchemaFlag(bool Value) {
+    TemporalProfTraces.setFlag(2, Value);
+  }
 
   // Whether to generated random memprof hotness for testing.
-  bool MemprofGenerateRandomHotness;
+  bool getMemprofGenerateRandomHotness() const {
+    return TemporalProfTraces.getFlag(3);
+  }
+  void setMemprofGenerateRandomHotness(bool Value) {
+    TemporalProfTraces.setFlag(3, Value);
+  }
 
   std::unique_ptr<memprof::DataAccessProfData> DataAccessProfileData;
 
@@ -90,6 +107,10 @@ class InstrProfWriter {
   // to the writer.
   memprof::MemProfSummaryBuilder MemProfSumBuilder;
 
+  template <typename TraceVectorT>
+  void addTemporalProfileTracesImpl(TraceVectorT &SrcTraces,
+                                    uint64_t SrcStreamSize);
+
 public:
   // For memprof testing, random hotness can be assigned to the contexts if
   // MemprofGenerateRandomHotness is enabled.
@@ -219,7 +240,7 @@ class InstrProfWriter {
   void setMemProfVersionRequested(memprof::IndexedVersion Version) {
     MemProfVersionRequested = Version;
   }
-  void setMemProfFullSchema(bool Full) { MemProfFullSchema = Full; }
+  void setMemProfFullSchema(bool Full) { setMemProfFullSchemaFlag(Full); }
 
   // Compute the overlap b/w this object and Other. Program level result is
   // stored in Overlap and function level result is stored in FuncLevelOverlap.
diff --git a/llvm/include/llvm/ProfileData/MemProfReader.h b/llvm/include/llvm/ProfileData/MemProfReader.h
index 8fdae7a472d5f..70a1e5bfc05b7 100644
--- a/llvm/include/llvm/ProfileData/MemProfReader.h
+++ b/llvm/include/llvm/ProfileData/MemProfReader.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
@@ -143,8 +144,8 @@ class LLVM_ABI RawMemProfReader final : public MemProfReader {
                    llvm::SmallVectorImpl<SegmentEntry> &Seg,
                    llvm::MapVector<uint64_t, MemInfoBlock> &Prof,
                    CallStackMap &SM, bool KeepName = false)
-      : SegmentInfo(Seg.begin(), Seg.end()), CallstackProfileData(Prof),
-        StackMap(SM), KeepSymbolName(KeepName) {
+      : SegmentInfo(unsigned(KeepName), Seg.begin(), Seg.end()),
+        CallstackProfileData(Prof), StackMap(SM) {
     // We don't call initialize here since there is no raw profile to read. The
     // test should pass in the raw profile as structured data.
 
@@ -158,7 +159,9 @@ class LLVM_ABI RawMemProfReader final : public MemProfReader {
 
 private:
   RawMemProfReader(object::OwningBinary<object::Binary> &&Bin, bool KeepName)
-      : Binary(std::move(Bin)), KeepSymbolName(KeepName) {}
+      : Binary(std::move(Bin)),
+        SegmentInfo(
+            decltype(this->SegmentInfo)::withFlags(unsigned(KeepName))) {}
   // Initializes the RawMemProfReader with the contents in `DataBuffer`.
   Error initialize(std::unique_ptr<MemoryBuffer> DataBuffer);
   // Read and parse the contents of the `DataBuffer` as a binary format profile.
@@ -195,7 +198,7 @@ class LLVM_ABI RawMemProfReader final : public MemProfReader {
 
   // The memory mapped segment information for all executable segments in the
   // profiled binary (filtered from the raw profile using the build id).
-  llvm::SmallVector<SegmentEntry, 2> SegmentInfo;
+  llvm::SmallVectorWithFlags<SegmentEntry, 2> SegmentInfo;
 
   // A map from callstack id (same as key in CallStackMap below) to the heap
   // information recorded for that allocation context.
@@ -206,7 +209,8 @@ class LLVM_ABI RawMemProfReader final : public MemProfReader {
   llvm::DenseMap<uint64_t, llvm::SmallVector<FrameId>> SymbolizedFrame;
 
   // Whether to keep the symbol name for each frame after hashing.
-  bool KeepSymbolName = false;
+  bool getKeepSymbolName() const { return SegmentInfo.getFlag(0); }
+  void setKeepSymbolName(bool Value) { SegmentInfo.setFlag(0, Value); }
   // A mapping of the hash to symbol name, only used if KeepSymbolName is true.
   llvm::DenseMap<uint64_t, std::string> GuidToSymbolName;
 };
diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index b785d73020de0..e3f2defb15e59 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/Eytzinger.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/ProfileSummary.h"
 #include "llvm/ProfileData/SampleProf.h"
@@ -315,7 +316,7 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
 
   // Set to use MD5 to represent string in NameTable.
   void setUseMD5() override {
-    UseMD5 = true;
+    setUseMD5Flag(true);
     addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name);
     // MD5 will be stored as plain uint64_t instead of variable-length
     // quantity format in NameTable section.
@@ -339,9 +340,9 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
     resetSecLayout(SectionLayout::CtxSplitLayout);
   }
 
-  void setUseMD5ProfileSymbolList() override { UseMD5ProfSymList = true; }
+  void setUseMD5ProfileSymbolList() override { setUseMD5ProfSymList(true); }
 
-  void setUseMD5IndexedTables() override { UseMD5IndexedTables = true; }
+  void setUseMD5IndexedTables() override { setUseMD5IndexedTablesFlag(true); }
 
   /// Select composite encoding for subsequent writes. Composite output
   /// requires CompositeProfileVersion or newer when write() is called.
@@ -359,7 +360,8 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
     }
 #endif
     SecLayout = SL;
-    SectionHdrLayout = ExtBinaryHdrLayoutTable[SL];
+    SectionHdrLayout.assign(ExtBinaryHdrLayoutTable[SL].begin(),
+                            ExtBinaryHdrLayoutTable[SL].end());
   }
 
 protected:
@@ -417,8 +419,9 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
   // the order of sections in SecHdrTable may be different that the
   // order in SectionHdrLayout. sample Reader will follow the order
   // in SectionHdrLayout to read each section.
-  SmallVector<SecHdrTableEntry, 8> SectionHdrLayout =
-      ExtBinaryHdrLayoutTable[DefaultLayout];
+  llvm::SmallVectorWithFlags<SecHdrTableEntry, 8, 3> SectionHdrLayout{
+      ExtBinaryHdrLayoutTable[DefaultLayout].begin(),
+      ExtBinaryHdrLayoutTable[DefaultLayout].end()};
 
   // Save the start of SecLBRProfile so we can compute the offset to the
   // start of SecLBRProfile for each Function's Profile and will keep it
@@ -455,13 +458,20 @@ class LLVM_ABI SampleProfileWriterExtBinaryBase
   // SecLBRProfile section. It is used to load function profile on demand.
   MapVector<SampleContext, uint64_t> FuncOffsetTable;
   // Whether to use MD5 to represent string.
-  bool UseMD5 = false;
+  bool getUseMD5Flag() const { return SectionHdrLayout.getFlag(0); }
+  void setUseMD5Flag(bool Value) { SectionHdrLayout.setFlag(0, Value); }
   // Whether to write the profile symbol list as 64-bit MD5 hashes in Eytzinger
   // layout.
-  bool UseMD5ProfSymList = false;
+  bool getUseMD5ProfSymList() const { return SectionHdrLayout.getFlag(1); }
+  void setUseMD5ProfSymList(bool Value) { SectionHdrLayout.setFlag(1, Value); }
   // Whether to write MD5-based indexed NameTable and parallel FuncOffsetTable
   // in Eytzinger layout.
-  bool UseMD5IndexedTables = false;
+  bool getUseMD5IndexedTablesFlag() const {
+    return SectionHdrLayout.getFlag(2);
+  }
+  void setUseMD5IndexedTablesFlag(bool Value) {
+    SectionHdrLayout.setFlag(2, Value);
+  }
   size_t NumNested = 0;
   size_t NumFlat = 0;
 
diff --git a/llvm/include/llvm/SandboxIR/Tracker.h b/llvm/include/llvm/SandboxIR/Tracker.h
index 881d4cb9d8d64..fe6ccb15845f8 100644
--- a/llvm/include/llvm/SandboxIR/Tracker.h
+++ b/llvm/include/llvm/SandboxIR/Tracker.h
@@ -50,6 +50,7 @@
 
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StableHashing.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instruction.h"
@@ -467,14 +468,20 @@ class Tracker {
 
 #ifndef NDEBUG
   /// One checker per nested snapshot.
-  SmallVector<IRSnapshotChecker> SnapshotChecker;
+  llvm::SmallVectorWithFlags<IRSnapshotChecker> SnapshotChecker;
 #endif
 
 public:
 #ifndef NDEBUG
   /// Helps catch bugs where we are creating new change objects while in the
   /// middle of creating other change objects.
-  bool InMiddleOfCreatingChange = false;
+  bool getInMiddleOfCreatingChange() const {
+    return SnapshotChecker.getFlag(0);
+  }
+  bool setInMiddleOfCreatingChange(bool Value) {
+    SnapshotChecker.setFlag(0, Value);
+    return Value;
+  }
 #endif // NDEBUG
 
   explicit Tracker(Context &Ctx) : Ctx(Ctx) {}
@@ -488,15 +495,15 @@ class Tracker {
   void track(std::unique_ptr<IRChangeBase> &&Change) {
     assert(State == TrackerState::Record && "The tracker should be tracking!");
 #ifndef NDEBUG
-    assert(!InMiddleOfCreatingChange &&
+    assert(!getInMiddleOfCreatingChange() &&
            "We are in the middle of creating another change!");
     if (isTracking())
-      InMiddleOfCreatingChange = true;
+      setInMiddleOfCreatingChange(true);
 #endif // NDEBUG
     Changes.push_back(std::move(Change));
 
 #ifndef NDEBUG
-    InMiddleOfCreatingChange = false;
+    setInMiddleOfCreatingChange(false);
 #endif
   }
   /// A convenience wrapper for `track()` that constructs and tracks the Change
diff --git a/llvm/include/llvm/Support/CFGDiff.h b/llvm/include/llvm/Support/CFGDiff.h
index f81215ed71bd4..33e59c37ce2a5 100644
--- a/llvm/include/llvm/Support/CFGDiff.h
+++ b/llvm/include/llvm/Support/CFGDiff.h
@@ -15,6 +15,7 @@
 #define LLVM_SUPPORT_CFGDIFF_H
 
 #include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/CFGUpdate.h"
@@ -64,12 +65,12 @@ template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
   // to apply these updates as given. If UpdatedAreReverseApplied is set, the
   // updates will be applied in reverse: deleted edges are considered re-added
   // and inserted edges are considered deleted when returning children.
-  bool UpdatedAreReverseApplied;
+  bool updatesAreReverseApplied() const { return LegalizedUpdates.getFlag(0); }
 
   // Keep the list of legalized updates for a deterministic order of updates
   // when using a GraphDiff for incremental updates in the DominatorTree.
   // The list is kept in reverse to allow popping from end.
-  SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
+  SmallVectorWithFlags<cfg::Update<NodePtr>, 4> LegalizedUpdates;
 
   void printMap(raw_ostream &OS, const UpdateMapType &M) const {
     StringRef DIText[2] = {"Delete", "Insert"};
@@ -89,7 +90,7 @@ template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
   }
 
 public:
-  GraphDiff() : UpdatedAreReverseApplied(false) {}
+  GraphDiff() = default;
   GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates,
             bool ReverseApplyUpdates = false) {
     cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
@@ -99,7 +100,7 @@ template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
       Succ[U.getFrom()].DI[IsInsert].push_back(U.getTo());
       Pred[U.getTo()].DI[IsInsert].push_back(U.getFrom());
     }
-    UpdatedAreReverseApplied = ReverseApplyUpdates;
+    LegalizedUpdates.setFlag(0, ReverseApplyUpdates);
   }
 
   auto getLegalizedUpdates() const {
@@ -112,7 +113,7 @@ template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
     assert(!LegalizedUpdates.empty() && "No updates to apply!");
     auto U = LegalizedUpdates.pop_back_val();
     unsigned IsInsert =
-        (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
+        (U.getKind() == cfg::UpdateKind::Insert) == !updatesAreReverseApplied();
     auto &SuccDIList = Succ[U.getFrom()];
     auto &SuccList = SuccDIList.DI[IsInsert];
     assert(SuccList.back() == U.getTo());
diff --git a/llvm/include/llvm/Support/CFGUpdate.h b/llvm/include/llvm/Support/CFGUpdate.h
index 18c34bb73695a..9da55330072a9 100644
--- a/llvm/include/llvm/Support/CFGUpdate.h
+++ b/llvm/include/llvm/Support/CFGUpdate.h
@@ -59,9 +59,8 @@ template <typename NodePtr> class Update {
 //    them when traversing CFG.
 // b) It optimizes away updates that cancel each other out, as the end result
 //    is the same.
-template <typename NodePtr>
-void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
-                     SmallVectorImpl<Update<NodePtr>> &Result,
+template <typename NodePtr, typename VectorT>
+void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates, VectorT &Result,
                      bool InverseGraph, bool ReverseResultOrder = false) {
   // Count the total number of inserions of each edge.
   // Each insertion adds 1 and deletion subtracts 1. The end number should be
diff --git a/llvm/include/llvm/Support/DebugCounter.h b/llvm/include/llvm/Support/DebugCounter.h
index ce690a86e1081..cbef09d9704aa 100644
--- a/llvm/include/llvm/Support/DebugCounter.h
+++ b/llvm/include/llvm/Support/DebugCounter.h
@@ -45,6 +45,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
@@ -63,16 +64,26 @@ class DebugCounter {
 
     /// Whether counting should be enabled, either due to -debug-counter or
     /// -print-debug-counter.
-    bool Active = false;
+    bool getActive() const { return Chunks.getFlag(0); }
+    bool setActive(bool Value) {
+      Chunks.setFlag(0, Value);
+      return Value;
+    }
     /// Whether chunks for the counter are set (differs from Active in that
     /// -print-debug-counter uses Active=true, IsSet=false).
-    bool IsSet = false;
+    bool getIsSet() const { return Chunks.getFlag(1); }
+    bool setIsSet(bool Value) {
+      Chunks.setFlag(1, Value);
+      return Value;
+    }
 
     int64_t Count = 0;
     uint64_t CurrChunkIdx = 0;
     StringRef Name;
     StringRef Desc;
-    IntegerInclusiveIntervalUtils::IntervalList Chunks;
+    llvm::SmallVectorWithFlagsFor<IntegerInclusiveIntervalUtils::IntervalList,
+                                  2>
+        Chunks;
 
   public:
     CounterInfo(StringRef Name, StringRef Desc) : Name(Name), Desc(Desc) {
@@ -80,8 +91,8 @@ class DebugCounter {
     }
 
     void reset() {
-      Active = false;
-      IsSet = false;
+      setActive(false);
+      setIsSet(false);
       Count = 0;
       CurrChunkIdx = 0;
       Chunks.clear();
@@ -108,7 +119,7 @@ class DebugCounter {
   LLVM_ABI static bool shouldExecuteImpl(CounterInfo &Counter);
 
   inline static bool shouldExecute(CounterInfo &Counter) {
-    if (!Counter.Active)
+    if (!Counter.getActive())
       return true;
     return shouldExecuteImpl(Counter);
   }
@@ -116,7 +127,7 @@ class DebugCounter {
   // Return true if a given counter had values set (either programatically or on
   // the command line).  This will return true even if those values are
   // currently in a state where the counter will always execute.
-  static bool isCounterSet(CounterInfo &Info) { return Info.IsSet; }
+  static bool isCounterSet(CounterInfo &Info) { return Info.getIsSet(); }
 
   struct CounterState {
     int64_t Count;
@@ -165,7 +176,7 @@ class DebugCounter {
 
   void activateAllCounters() {
     for (auto &[_, Counter] : Counters)
-      Counter->Active = true;
+      Counter->setActive(true);
   }
 
   void resetAllCounters() {
diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h
index 964e8412ce910..f9fb8263d368c 100644
--- a/llvm/include/llvm/Support/GenericDomTree.h
+++ b/llvm/include/llvm/Support/GenericDomTree.h
@@ -29,6 +29,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/CFGDiff.h"
 #include "llvm/Support/CFGUpdate.h"
@@ -284,7 +285,8 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
 
 protected:
   // Dominators always have a single root, postdominators can have more.
-  SmallVector<NodeT *, IsPostDom ? 4 : 1> Roots;
+  // Mutable only so const queries can update the DFS-valid flag.
+  mutable SmallVectorWithFlags<NodeT *, IsPostDom ? 4 : 1> Roots;
 
   using DomTreeNodeStorageTy = SmallVector<DomTreeNodeBase<NodeT> *>;
   DomTreeNodeStorageTy DomTreeNodes;
@@ -300,7 +302,8 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
                        /*GrowthDelay=*/2>
       NodeAllocator;
 
-  mutable bool DFSInfoValid = false;
+  bool isDFSInfoValid() const { return Roots.getFlag(0); }
+  void setDFSInfoValid(bool Value) const { Roots.setFlag(0, Value); }
   mutable unsigned int SlowQueries = 0;
   unsigned BlockNumberEpoch = 0;
 
@@ -483,12 +486,12 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     // Compare the result of the tree walk and the dfs numbers, if expensive
     // checks are enabled.
 #ifdef EXPENSIVE_CHECKS
-    assert((!DFSInfoValid ||
+    assert((!isDFSInfoValid() ||
             (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
            "Tree walk disagrees with dfs numbers!");
 #endif
 
-    if (DFSInfoValid)
+    if (isDFSInfoValid())
       return B->DominatedBy(A);
 
     // If we end up with too many slow queries, just update the
@@ -650,7 +653,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     assert(getNode(BB) == nullptr && "Block already in dominator tree!");
     DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
     assert(IDomNode && "Not immediate dominator specified for block!");
-    DFSInfoValid = false;
+    setDFSInfoValid(false);
     return createNode(BB, IDomNode);
   }
 
@@ -663,7 +666,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     assert(getNode(BB) == nullptr && "Block already in dominator tree!");
     assert(!this->isPostDominator() &&
            "Cannot change root of post-dominator tree");
-    DFSInfoValid = false;
+    setDFSInfoValid(false);
     DomTreeNodeBase<NodeT> *NewNode = createNode(BB);
     if (Roots.empty()) {
       addRoot(BB);
@@ -685,7 +688,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
   void changeImmediateDominator(DomTreeNodeBase<NodeT> *N,
                                 DomTreeNodeBase<NodeT> *NewIDom) {
     assert(N && NewIDom && "Cannot change null node pointers!");
-    DFSInfoValid = false;
+    setDFSInfoValid(false);
     N->setIDom(NewIDom);
   }
 
@@ -702,7 +705,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     assert(Node && "Removing node that isn't in dominator tree.");
     assert(Node->isLeaf() && "Node is not a leaf node.");
 
-    DFSInfoValid = false;
+    setDFSInfoValid(false);
 
     // Remove node from immediate dominator's children list.
     if (DomTreeNodeBase<NodeT> *IDom = Node->getIDom())
@@ -737,7 +740,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
       O << "Inorder PostDominator Tree: ";
     else
       O << "Inorder Dominator Tree: ";
-    if (!DFSInfoValid)
+    if (!isDFSInfoValid())
       O << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
     O << "\n";
 
@@ -755,7 +758,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
   /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
   /// dominator tree in dfs order.
   void updateDFSNumbers() const {
-    if (DFSInfoValid) {
+    if (isDFSInfoValid()) {
       SlowQueries = 0;
       return;
     }
@@ -796,7 +799,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     }
 
     SlowQueries = 0;
-    DFSInfoValid = true;
+    setDFSInfoValid(true);
   }
 
 private:
@@ -845,7 +848,7 @@ template <typename NodeT, bool IsPostDom> class DominatorTreeBase {
     Roots.clear();
     RootNode = nullptr;
     Parent = nullptr;
-    DFSInfoValid = false;
+    setDFSInfoValid(false);
     NodeAllocator.Reset();
     SlowQueries = 0;
   }
diff --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
index 96fb16e5d4bb3..218d88c35a11f 100644
--- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h
@@ -569,7 +569,9 @@ template <typename DomTreeT> struct SemiNCAInfo {
 
     // Step #0: Number blocks in depth-first order and initialize variables used
     // in later stages of the algorithm.
-    DT.Roots = FindRoots(DT, PostViewBUI);
+    RootsT NewRoots = FindRoots(DT, PostViewBUI);
+    NewRoots.setFlags(DT.Roots.getFlags());
+    DT.Roots = std::move(NewRoots);
     SNCA.doFullDFSWalk(DT, AlwaysDescend);
 
     SNCA.runSemiNCA();
@@ -655,7 +657,7 @@ template <typename DomTreeT> struct SemiNCAInfo {
       DT.Roots.push_back(From);
     }
 
-    DT.DFSInfoValid = false;
+    DT.setDFSInfoValid(false);
 
     const TreeNodePtr ToTN = DT.getNode(To);
     if (!ToTN)
@@ -685,8 +687,7 @@ template <typename DomTreeT> struct SemiNCAInfo {
     return true;
   }
 
-  static bool isPermutation(const SmallVectorImpl<NodePtr> &A,
-                            const SmallVectorImpl<NodePtr> &B) {
+  static bool isPermutation(ArrayRef<NodePtr> A, ArrayRef<NodePtr> B) {
     if (A.size() != B.size())
       return false;
     SmallPtrSet<NodePtr, 4> Set(llvm::from_range, A);
@@ -942,7 +943,7 @@ template <typename DomTreeT> struct SemiNCAInfo {
 
     // If To dominates From -- nothing to do.
     if (ToTN != NCD) {
-      DT.DFSInfoValid = false;
+      DT.setDFSInfoValid(false);
 
       const TreeNodePtr ToIDom = ToTN->getIDom();
       LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
@@ -1322,7 +1323,7 @@ template <typename DomTreeT> struct SemiNCAInfo {
   // be valid, and when that is the case, we don't verify the numbers.
   // Running time: O(N log(N)).
   static bool VerifyDFSNumbers(const DomTreeT &DT) {
-    if (!DT.DFSInfoValid || !DT.Parent)
+    if (!DT.isDFSInfoValid() || !DT.Parent)
       return true;
 
     const NodePtr RootBB = IsPostDom ? nullptr : *DT.root_begin();
diff --git a/llvm/include/llvm/Support/GlobPattern.h b/llvm/include/llvm/Support/GlobPattern.h
index 00a931db9f278..e887a5be4c0e9 100644
--- a/llvm/include/llvm/Support/GlobPattern.h
+++ b/llvm/include/llvm/Support/GlobPattern.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -95,7 +96,6 @@ class GlobPattern {
   StringRef Pattern;
   size_t PrefixSize = 0;
   size_t SuffixSize = 0;
-  bool SlashAgnostic = false;
 
   struct SubGlobPattern {
     /// \param Pat the pattern to match against
@@ -105,7 +105,7 @@ class GlobPattern {
     LLVM_ABI bool match(StringRef S, bool SlashAgnostic) const;
     StringRef getPat() const { return StringRef(Pat.data(), Pat.size()); }
     /// \returns \p true if this sub-pattern matches exactly one string.
-    bool isLiteral() const { return Brackets.empty() && !HasWildcard; }
+    bool isLiteral() const { return Brackets.empty() && !Pat.getFlag(0); }
 
     // Brackets with their end position and matched bytes.
     struct Bracket {
@@ -113,11 +113,11 @@ class GlobPattern {
       BitVector Bytes;
     };
     SmallVector<Bracket, 0> Brackets;
-    // Set while parsing if an unescaped '*' or '?' is present.
-    bool HasWildcard = false;
-    SmallVector<char, 0> Pat;
+    // Flag bit 0 is set if an unescaped '*' or '?' is present.
+    SmallVectorWithFlags<char, 0> Pat;
   };
-  SmallVector<SubGlobPattern, 1> SubGlobs;
+  // Flag bit 0 records slash-agnostic matching.
+  SmallVectorWithFlags<SubGlobPattern, 1> SubGlobs;
 };
 }
 
diff --git a/llvm/include/llvm/Support/LSP/Transport.h b/llvm/include/llvm/Support/LSP/Transport.h
index 4a831b8805acf..da43cd943582e 100644
--- a/llvm/include/llvm/Support/LSP/Transport.h
+++ b/llvm/include/llvm/Support/LSP/Transport.h
@@ -16,6 +16,7 @@
 #define LLVM_SUPPORT_LSP_TRANSPORT_H
 
 #include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -88,13 +89,17 @@ class JSONTransport {
 public:
   JSONTransport(std::unique_ptr<JSONTransportInput> In, raw_ostream &Out,
                 bool PrettyOutput = false)
-      : In(std::move(In)), Out(Out), PrettyOutput(PrettyOutput) {}
+      : In(std::move(In)), OutputBuffer(decltype(this->OutputBuffer)::withFlags(
+                               unsigned(PrettyOutput))),
+        Out(Out) {}
 
   JSONTransport(std::FILE *In, raw_ostream &Out,
                 JSONStreamStyle Style = JSONStreamStyle::Standard,
                 bool PrettyOutput = false)
-      : In(std::make_unique<JSONTransportInputOverFile>(In, Style)), Out(Out),
-        PrettyOutput(PrettyOutput) {}
+      : In(std::make_unique<JSONTransportInputOverFile>(In, Style)),
+        OutputBuffer(
+            decltype(this->OutputBuffer)::withFlags(unsigned(PrettyOutput))),
+        Out(Out) {}
 
   /// The following methods are used to send a message to the LSP client.
   LLVM_ABI void notify(StringRef Method, llvm::json::Value Params);
@@ -115,11 +120,12 @@ class JSONTransport {
 private:
   /// The input to read a message from.
   std::unique_ptr<JSONTransportInput> In;
-  SmallVector<char, 0> OutputBuffer;
+  llvm::SmallVectorWithFlags<char, 0> OutputBuffer;
   /// The output file stream.
   raw_ostream &Out;
   /// If the output JSON should be formatted for easier readability.
-  bool PrettyOutput;
+  bool getPrettyOutput() const { return OutputBuffer.getFlag(0); }
+  void setPrettyOutput(bool Value) { OutputBuffer.setFlag(0, Value); }
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/Support/SuffixTree.h b/llvm/include/llvm/Support/SuffixTree.h
index eac66d84d6f63..aafed0b51cb6d 100644
--- a/llvm/include/llvm/Support/SuffixTree.h
+++ b/llvm/include/llvm/Support/SuffixTree.h
@@ -33,6 +33,7 @@
 #define LLVM_SUPPORT_SUFFIXTREE_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/SuffixTreeNode.h"
@@ -166,7 +167,7 @@ class SuffixTree {
     RepeatedSubstring RS;
 
     /// The nodes left to visit.
-    SmallVector<SuffixTreeInternalNode *> InternalNodesToVisit;
+    llvm::SmallVectorWithFlags<SuffixTreeInternalNode *> InternalNodesToVisit;
 
     /// The minimum length of a repeated substring to find.
     /// Since we're outlining, we want at least two instructions in the range.
@@ -178,7 +179,12 @@ class SuffixTree {
     const std::vector<SuffixTreeLeafNode *> &LeafNodes;
 
     /// Whether to consider leaf descendants or only leaf children.
-    bool OutlinerLeafDescendants = !LeafNodes.empty();
+    bool getOutlinerLeafDescendants() const {
+      return InternalNodesToVisit.getFlag(0);
+    }
+    void setOutlinerLeafDescendants(bool Value) {
+      InternalNodesToVisit.setFlag(0, Value);
+    }
 
     /// Move the iterator to the next repeated substring.
     LLVM_ABI void advance();
@@ -208,7 +214,10 @@ class SuffixTree {
     RepeatedSubstringIterator(
         SuffixTreeInternalNode *N,
         const std::vector<SuffixTreeLeafNode *> &LeafNodes = {})
-        : N(N), LeafNodes(LeafNodes) {
+        : N(N),
+          InternalNodesToVisit(decltype(this->InternalNodesToVisit)::withFlags(
+              unsigned(bool(!LeafNodes.empty())))),
+          LeafNodes(LeafNodes) {
       // Do we have a non-null node?
       if (!N)
         return;
diff --git a/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h
index 7ba43176c6e79..7f08ddc84fe4a 100644
--- a/llvm/include/llvm/Support/YAMLTraits.h
+++ b/llvm/include/llvm/Support/YAMLTraits.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -1896,6 +1897,18 @@ struct SequenceTraits<
     SmallVectorImpl<T>,
     std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
     : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
+template <typename T, unsigned N, unsigned FlagBits>
+struct SequenceTraits<
+    SmallVectorWithFlags<T, N, FlagBits>,
+    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
+    : SequenceTraitsImpl<SmallVectorWithFlags<T, N, FlagBits>,
+                         SequenceElementTraits<T>::flow> {};
+template <typename T, unsigned FlagBits>
+struct SequenceTraits<
+    SmallVectorWithFlagsImpl<T, FlagBits>,
+    std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
+    : SequenceTraitsImpl<SmallVectorWithFlagsImpl<T, FlagBits>,
+                         SequenceElementTraits<T>::flow> {};
 template <typename T>
 struct SequenceTraits<
     MutableArrayRef<T>,
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 67bc27f6a2d1f..94e84a7d592bf 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -105,6 +105,7 @@
 #include "llvm/ADT/SetOperations.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/CFG.h"
@@ -1223,7 +1224,7 @@ struct InformationCache {
   }
 
   /// Return the instructions in \p F that may read or write memory.
-  InstructionVectorTy &getReadOrWriteInstsForFunction(const Function &F) {
+  auto &getReadOrWriteInstsForFunction(const Function &F) {
     return getFunctionInfo(F).RWInsts;
   }
 
@@ -1240,14 +1241,14 @@ struct InformationCache {
   /// Return true if \p F has the "kernel" function attribute
   bool isKernel(const Function &F) {
     FunctionInfo &FI = getFunctionInfo(F);
-    return FI.IsKernel;
+    return FI.getIsKernel();
   }
 
   /// Return true if \p Arg is involved in a must-tail call, thus the argument
   /// of the caller or callee.
   bool isInvolvedInMustTailCall(const Argument &Arg) {
     FunctionInfo &FI = getFunctionInfo(*Arg.getParent());
-    return FI.CalledViaMustTail || FI.ContainsMustTailCall;
+    return FI.getCalledViaMustTail() || FI.getContainsMustTailCall();
   }
 
   bool isOnlyUsedByAssume(const Instruction &I) const {
@@ -1312,16 +1313,22 @@ struct InformationCache {
 
     /// A map from functions to their instructions that may read or write
     /// memory.
-    InstructionVectorTy RWInsts;
+    llvm::SmallVectorWithFlagsFor<InstructionVectorTy, 3> RWInsts;
 
     /// Function is called by a `musttail` call.
-    bool CalledViaMustTail;
+    bool getCalledViaMustTail() const { return RWInsts.getFlag(0); }
+    bool setCalledViaMustTail(bool Value) {
+      RWInsts.setFlag(0, Value);
+      return Value;
+    }
 
     /// Function contains a `musttail` call.
-    bool ContainsMustTailCall;
+    bool getContainsMustTailCall() const { return RWInsts.getFlag(1); }
+    void setContainsMustTailCall(bool Value) { RWInsts.setFlag(1, Value); }
 
     /// Function has the `"kernel"` attribute
-    bool IsKernel;
+    bool getIsKernel() const { return RWInsts.getFlag(2); }
+    void setIsKernel(bool Value) { RWInsts.setFlag(2, Value); }
   };
 
   /// A map type from functions to informatio about it.
diff --git a/llvm/include/llvm/Transforms/IPO/Instrumentor.h b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
index e7e6c52d8c816..d78b4dba9a9b0 100644
--- a/llvm/include/llvm/Transforms/IPO/Instrumentor.h
+++ b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -501,13 +502,17 @@ struct InstrumentationOpportunity {
   /// The list of possible arguments for the instrumentation runtime function.
   /// The order within the array determines the order of arguments. Arguments
   /// may be disabled and will not be passed to the function call.
-  SmallVector<IRTArg> IRTArgs;
+  llvm::SmallVectorWithFlags<IRTArg> IRTArgs;
 
   /// Flag names and their integer bitmask values.
   StringMap<int32_t> FlagNames;
 
   /// Whether the opportunity is enabled.
-  bool Enabled = true;
+  bool getEnabled() const { return !IRTArgs.getFlag(0); }
+  bool setEnabled(bool Value) {
+    IRTArgs.setFlag(0, !Value);
+    return Value;
+  }
 
   /// A filter expression to be matched against runtime property values. If the
   /// filter is non-empty, only instrumentations matching the filter will be
diff --git a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
index 7a872ef1021b2..2ce9745c28b92 100644
--- a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
+++ b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h
@@ -42,6 +42,7 @@
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/PassManager.h"
 #include <algorithm>
@@ -152,7 +153,8 @@ class ConstantHoistingPass
   const DataLayout *DL;
   BasicBlock *Entry;
   ProfileSummaryInfo *PSI;
-  bool OptForSize;
+  bool getOptForSize() const { return ConstIntInfoVec.getFlag(0); }
+  void setOptForSize(bool Value) { ConstIntInfoVec.setFlag(0, Value); }
 
   /// Keeps track of constant candidates found in the function.
   using ConstCandVecType = std::vector<consthoist::ConstantCandidate>;
@@ -163,7 +165,7 @@ class ConstantHoistingPass
   /// These are the final constants we decided to hoist.
   using ConstInfoVecType = SmallVector<consthoist::ConstantInfo, 8>;
   using GVInfoVecMapType = MapVector<GlobalVariable *, ConstInfoVecType>;
-  ConstInfoVecType ConstIntInfoVec;
+  llvm::SmallVectorWithFlagsFor<ConstInfoVecType, 1> ConstIntInfoVec;
   GVInfoVecMapType ConstGEPInfoMap;
 
   /// Keep track of cast instructions we already cloned.
diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h
index 119084eea7238..268dca0fdcbbc 100644
--- a/llvm/include/llvm/Transforms/Utils/Cloning.h
+++ b/llvm/include/llvm/Transforms/Utils/Cloning.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/InlineCost.h"
@@ -264,7 +265,10 @@ class InlineFunctionInfo {
       BlockFrequencyInfo *CallerBFI = nullptr,
       BlockFrequencyInfo *CalleeBFI = nullptr, bool UpdateProfile = true)
       : GetAssumptionCache(GetAssumptionCache), PSI(PSI), CallerBFI(CallerBFI),
-        CalleeBFI(CalleeBFI), UpdateProfile(UpdateProfile) {}
+        CalleeBFI(CalleeBFI),
+        StaticAllocas(
+            decltype(this->StaticAllocas)::withFlags(unsigned(UpdateProfile))) {
+  }
 
   /// If non-null, InlineFunction will update the callgraph to reflect the
   /// changes it makes.
@@ -274,7 +278,7 @@ class InlineFunctionInfo {
 
   /// InlineFunction fills this in with all static allocas that get copied into
   /// the caller.
-  SmallVector<AllocaInst *, 4> StaticAllocas;
+  llvm::SmallVectorWithFlags<AllocaInst *, 4> StaticAllocas;
 
   /// All of the new call sites inlined into the caller.
   ///
@@ -286,7 +290,8 @@ class InlineFunctionInfo {
 
   /// Update profile for callee as well as cloned version. We need to do this
   /// for regular inlining, but not for inlining from sample profile loader.
-  bool UpdateProfile;
+  bool getUpdateProfile() const { return StaticAllocas.getFlag(0); }
+  void setUpdateProfile(bool Value) { StaticAllocas.setFlag(0, Value); }
 
   void reset() {
     StaticAllocas.clear();
diff --git a/llvm/include/llvm/Transforms/Utils/CodeExtractor.h b/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
index 6285bbf29612d..6e4b390fdcba8 100644
--- a/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/llvm/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/IRBuilder.h"
@@ -92,7 +93,7 @@ class LLVM_ABI CodeExtractor {
 
   // Various bits of state computed on construction.
   DominatorTree *const DT;
-  const bool AggregateArgs;
+  bool getAggregateArgs() const { return ExtractedFuncRetVals.getFlag(0); }
   BlockFrequencyInfo *BFI;
   BranchProbabilityInfo *BPI;
   AssumptionCache *AC;
@@ -111,7 +112,8 @@ class LLVM_ABI CodeExtractor {
   SmallVector<BasicBlock *> DeallocationBlocks;
 
   /// If true, varargs functions can be extracted.
-  bool AllowVarArgs;
+  bool getAllowVarArgs() const { return ExtractedFuncRetVals.getFlag(1); }
+  void setAllowVarArgs(bool Value) { ExtractedFuncRetVals.setFlag(1, Value); }
 
   /// Bits of intermediate state computed at various phases of extraction.
   SetVector<BasicBlock *> Blocks;
@@ -132,7 +134,10 @@ class LLVM_ABI CodeExtractor {
   /// When there are 3 or more exit blocks, leaving the extracted function via
   /// the first block it returns 0. When leaving via the second entry it returns
   /// 1, etc.
-  SmallVector<BasicBlock *> ExtractedFuncRetVals;
+  llvm::SmallVectorWithFlags<
+      BasicBlock *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<BasicBlock *>::value, 4>
+      ExtractedFuncRetVals;
 
   /// Suffix to use when creating extracted function (appended to the original
   /// function name + "."). If empty, the default is to use the entry block
@@ -141,11 +146,21 @@ class LLVM_ABI CodeExtractor {
 
   /// If true, the outlined function has aggregate argument in zero address
   /// space.
-  bool ArgsInZeroAddressSpace;
+  bool getArgsInZeroAddressSpace() const {
+    return ExtractedFuncRetVals.getFlag(2);
+  }
+  void setArgsInZeroAddressSpace(bool Value) {
+    ExtractedFuncRetVals.setFlag(2, Value);
+  }
 
   // If true, the outlined function always return void even when there is only
   // one output.
-  bool VoidReturnWithSingleOutput;
+  bool getVoidReturnWithSingleOutput() const {
+    return ExtractedFuncRetVals.getFlag(3);
+  }
+  void setVoidReturnWithSingleOutput(bool Value) {
+    ExtractedFuncRetVals.setFlag(3, Value);
+  }
 
   // If set, the return value of the outline function.
   Value *FuncRetVal = nullptr;
diff --git a/llvm/include/llvm/Transforms/Utils/LockstepReverseIterator.h b/llvm/include/llvm/Transforms/Utils/LockstepReverseIterator.h
index 5b92b33a10ea0..e642a075a8d2e 100644
--- a/llvm/include/llvm/Transforms/Utils/LockstepReverseIterator.h
+++ b/llvm/include/llvm/Transforms/Utils/LockstepReverseIterator.h
@@ -12,6 +12,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Instruction.h"
 
@@ -45,8 +46,8 @@ class LockstepReverseIterator
   using Base = std::conditional_t<EarlyFailure, NoActiveBlocksOption,
                                   ActiveBlocksOption>;
   ArrayRef<BasicBlock *> Blocks;
-  SmallVector<Instruction *, 4> Insts;
-  bool Fail;
+  SmallVectorWithFlags<Instruction *, 4> Insts;
+  bool failed() const { return Insts.getFlag(0); }
 
 public:
   LockstepReverseIterator(ArrayRef<BasicBlock *> Blocks) : Blocks(Blocks) {
@@ -54,7 +55,7 @@ class LockstepReverseIterator
   }
 
   void reset() {
-    Fail = false;
+    Insts.setFlag(0, false);
     if constexpr (!EarlyFailure) {
       this->ActiveBlocks.clear();
       this->ActiveBlocks.insert_range(Blocks);
@@ -65,7 +66,7 @@ class LockstepReverseIterator
       if (!Prev) {
         // Block wasn't big enough - only contained a terminator.
         if constexpr (EarlyFailure) {
-          Fail = true;
+          Insts.setFlag(0, true);
           return;
         } else {
           this->ActiveBlocks.remove(BB);
@@ -75,10 +76,10 @@ class LockstepReverseIterator
       Insts.push_back(Prev);
     }
     if (Insts.empty())
-      Fail = true;
+      Insts.setFlag(0, true);
   }
 
-  bool isValid() const { return !Fail; }
+  bool isValid() const { return !failed(); }
   ArrayRef<Instruction *> operator*() const { return Insts; }
 
   // Note: This needs to return a SmallSetVector as the elements of
@@ -104,7 +105,7 @@ class LockstepReverseIterator
   }
 
   LockstepReverseIterator &operator--() {
-    if (Fail)
+    if (failed())
       return *this;
     SmallVector<Instruction *, 4> NewInsts;
     for (Instruction *Inst : Insts) {
@@ -113,7 +114,7 @@ class LockstepReverseIterator
         if constexpr (!EarlyFailure) {
           this->ActiveBlocks.remove(Inst->getParent());
         } else {
-          Fail = true;
+          Insts.setFlag(0, true);
           return *this;
         }
       } else {
@@ -121,30 +122,30 @@ class LockstepReverseIterator
       }
     }
     if (NewInsts.empty())
-      Fail = true;
+      Insts.setFlag(0, true);
     else
-      Insts = NewInsts;
+      Insts.assign(NewInsts.begin(), NewInsts.end());
     return *this;
   }
 
   LockstepReverseIterator &operator++() {
     static_assert(EarlyFailure, "Unknown method");
-    if (Fail)
+    if (failed())
       return *this;
     SmallVector<Instruction *, 4> NewInsts;
     for (Instruction *Inst : Insts) {
       Instruction *Next = Inst->getNextNode();
       // Already at end of block.
       if (!Next) {
-        Fail = true;
+        Insts.setFlag(0, true);
         return *this;
       }
       NewInsts.push_back(Next);
     }
     if (NewInsts.empty())
-      Fail = true;
+      Insts.setFlag(0, true);
     else
-      Insts = NewInsts;
+      Insts.assign(NewInsts.begin(), NewInsts.end());
     return *this;
   }
 };
diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index a68b928985316..740200874b56d 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
 #define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
@@ -673,14 +674,18 @@ LLVM_ABI Value *addDiffRuntimeChecks(Instruction *Loc,
 struct IVConditionInfo {
   /// Instructions that need to be duplicated and checked for the unswitching
   /// condition.
-  SmallVector<Instruction *> InstToDuplicate;
+  llvm::SmallVectorWithFlags<Instruction *> InstToDuplicate;
 
   /// Constant to indicate for which value the condition is invariant.
   Constant *KnownValue = nullptr;
 
   /// True if the partially invariant path is no-op (=does not have any
   /// side-effects and no loop value is used outside the loop).
-  bool PathIsNoop = true;
+  bool getPathIsNoop() const { return !InstToDuplicate.getFlag(0); }
+  bool setPathIsNoop(bool Value) {
+    InstToDuplicate.setFlag(0, !Value);
+    return Value;
+  }
 
   /// If the partially invariant path reaches a single exit block, ExitForPath
   /// is set to that block. Otherwise it is nullptr.
diff --git a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
index 5590109adcbc5..e0085dc86db20 100644
--- a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
+++ b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/Analysis/StackSafetyAnalysis.h"
@@ -51,7 +52,7 @@ struct AllocaInfo {
 LLVM_ABI void
 forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT,
                      const LoopInfo &LI, const AllocaInfo &AInfo,
-                     const SmallVectorImpl<Instruction *> &RetVec,
+                     ArrayRef<Instruction *> RetVec,
                      llvm::function_ref<void(Instruction *)> Callback);
 
 LLVM_ABI bool isSupportedLifetime(const AllocaInfo &AInfo,
@@ -61,8 +62,9 @@ LLVM_ABI Instruction *getUntagLocationIfFunctionExit(Instruction &Inst);
 
 struct StackInfo {
   MapVector<AllocaInst *, AllocaInfo> AllocasToInstrument;
-  SmallVector<Instruction *, 8> RetVec;
-  bool CallsReturnTwice = false;
+  llvm::SmallVectorWithFlags<Instruction *, 8> RetVec;
+  bool getCallsReturnTwice() const { return RetVec.getFlag(0); }
+  void setCallsReturnTwice(bool Value) { RetVec.setFlag(0, Value); }
 };
 
 enum class AllocaInterestingness {
diff --git a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
index 8a4ca594b77bb..7865a3e0b6438 100644
--- a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
+++ b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/InstSimplifyFolder.h"
 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
 #include "llvm/Analysis/ScalarEvolutionNormalization.h"
@@ -72,7 +73,8 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
   const char *IVName;
 
   /// Indicates whether LCSSA phis should be created for inserted values.
-  bool PreserveLCSSA;
+  bool getPreserveLCSSA() const { return InsertPointGuards.getFlag(0); }
+  void setPreserveLCSSA(bool Value) { InsertPointGuards.setFlag(0, Value); }
 
   // InsertedExpressions caches Values for reuse, so must track RAUW.
   DenseMap<std::pair<SCEVUse, Instruction *>, TrackingVH<Value>>
@@ -129,17 +131,20 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
   /// canonical induction variable. Note that CanonicalMode doesn't guarantee
   /// that all expressions are expanded in "canonical" form. For some
   /// expressions literal mode can be preferred.
-  bool CanonicalMode;
+  bool getCanonicalMode() const { return InsertPointGuards.getFlag(1); }
+  void setCanonicalMode(bool Value) { InsertPointGuards.setFlag(1, Value); }
 
   /// When invoked from LSR, the expander is in "strength reduction" mode. The
   /// only difference is that phi's are only reused if they are already in
   /// "expanded" form.
-  bool LSRMode;
+  bool getLSRMode() const { return InsertPointGuards.getFlag(2); }
+  void setLSRMode(bool Value) { InsertPointGuards.setFlag(2, Value); }
 
   /// When true, rewrite any divisors of UDiv expressions that may be 0 to
   /// umax(Divisor, 1) to avoid introducing UB. If the divisor may be poison,
   /// freeze it first.
-  bool SafeUDivMode = false;
+  bool getSafeUDivMode() const { return InsertPointGuards.getFlag(3); }
+  void setSafeUDivMode(bool Value) { InsertPointGuards.setFlag(3, Value); }
 
   typedef IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> BuilderType;
   BuilderType Builder;
@@ -181,7 +186,7 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
 
   /// Stack of pointers to saved insert points, used to keep insert points
   /// consistent when instructions are moved.
-  SmallVector<SCEVInsertPointGuard *, 8> InsertPointGuards;
+  llvm::SmallVectorWithFlags<SCEVInsertPointGuard *, 8, 4> InsertPointGuards;
 
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
   const char *DebugType;
@@ -193,12 +198,13 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
   /// Construct a SCEVExpander in "canonical" mode.
   explicit SCEVExpander(ScalarEvolution &SE, const char *Name,
                         bool PreserveLCSSA = true)
-      : SE(SE), DL(SE.getDataLayout()), IVName(Name),
-        PreserveLCSSA(PreserveLCSSA), IVIncInsertLoop(nullptr),
-        IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false),
+      : SE(SE), DL(SE.getDataLayout()), IVName(Name), IVIncInsertLoop(nullptr),
+        IVIncInsertPos(nullptr),
         Builder(SE.getModule(), InstSimplifyFolder(DL),
                 IRBuilderCallbackInserter(
-                    [this](Instruction *I) { rememberInstruction(I); })) {
+                    [this](Instruction *I) { rememberInstruction(I); })),
+        InsertPointGuards(decltype(this->InsertPointGuards)::withFlags(
+            unsigned(PreserveLCSSA) | 2)) {
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     DebugType = "";
 #endif
@@ -380,7 +386,7 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
 
   /// Set the current IV increment loop and position.
   void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
-    assert(!CanonicalMode &&
+    assert(!getCanonicalMode() &&
            "IV increment positions are not supported in CanonicalMode");
     IVIncInsertLoop = L;
     IVIncInsertPos = Pos;
@@ -389,7 +395,7 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
   /// Enable post-inc expansion for addrecs referring to the given
   /// loops. Post-inc expansion is only supported in non-canonical mode.
   void setPostInc(const PostIncLoopSet &L) {
-    assert(!CanonicalMode &&
+    assert(!getCanonicalMode() &&
            "Post-inc expansion is not supported in CanonicalMode");
     PostIncLoops = L;
   }
@@ -406,9 +412,9 @@ class SCEVExpander : public SCEVUseVisitor<SCEVExpander, Value *> {
   /// Disable the behavior of expanding expressions in canonical form rather
   /// than in a more literal form. Non-canonical mode is useful for late
   /// optimization passes.
-  void disableCanonicalMode() { CanonicalMode = false; }
+  void disableCanonicalMode() { setCanonicalMode(false); }
 
-  void enableLSRMode() { LSRMode = true; }
+  void enableLSRMode() { setLSRMode(true); }
 
   /// Set the current insertion point. This is useful if multiple calls to
   /// expandCodeFor() are going to be made with the same insert point and the
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index c6f8c61fcb3cb..83230519bd525 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -27,6 +27,7 @@
 #define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H
 
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/LoopAccessAnalysis.h"
 #include "llvm/Analysis/VectorUtils.h"
 #include "llvm/Support/TypeSize.h"
@@ -287,8 +288,10 @@ class LoopVectorizationLegality {
                             AssumptionCache *AC, bool AllowRuntimeSCEVChecks,
                             AAResults *AA)
       : Opts(Opts), TheLoop(L), LI(LI), PSE(PSE), TTI(TTI), TLI(TLI), DT(DT),
-        LAIs(LAIs), ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC),
-        AllowRuntimeSCEVChecks(AllowRuntimeSCEVChecks), AA(AA) {}
+        LAIs(LAIs), ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC), AA(AA),
+        CountableExitingBlocks(
+            decltype(this->CountableExitingBlocks)::withFlags(
+                unsigned(AllowRuntimeSCEVChecks))) {}
 
   /// ReductionList contains the reduction descriptors for all
   /// of the reductions that were found in the loop.
@@ -462,7 +465,7 @@ class LoopVectorizationLegality {
 
   /// Returns true if there is at least one function call in the loop which
   /// has a vectorized variant available.
-  bool hasVectorCallVariants() const { return VecCallVariantsFound; }
+  bool hasVectorCallVariants() const { return getVecCallVariantsFound(); }
 
   /// Returns a HistogramInfo* for the given instruction if it was determined
   /// to be part of a load -> update -> store sequence where multiple lanes
@@ -494,7 +497,7 @@ class LoopVectorizationLegality {
 
   /// Returns all exiting blocks with a countable exit, i.e. the
   /// exit-not-taken count is known exactly at compile time.
-  const SmallVector<BasicBlock *, 4> &getCountableExitingBlocks() const {
+  ArrayRef<BasicBlock *> getCountableExitingBlocks() const {
     return CountableExitingBlocks;
   }
 
@@ -726,7 +729,12 @@ class LoopVectorizationLegality {
   SmallVector<HistogramInfo, 1> Histograms;
 
   /// Whether or not creating SCEV predicates is allowed.
-  bool AllowRuntimeSCEVChecks;
+  bool getAllowRuntimeSCEVChecks() const {
+    return CountableExitingBlocks.getFlag(0);
+  }
+  void setAllowRuntimeSCEVChecks(bool Value) {
+    CountableExitingBlocks.setFlag(0, Value);
+  }
 
   // Alias Analysis results used to check for possible aliasing with loads
   // used in uncountable exit conditions.
@@ -736,11 +744,17 @@ class LoopVectorizationLegality {
   /// vectorized variant, record that fact so that LoopVectorize can
   /// (potentially) make a better decision on the maximum VF and enable
   /// the use of those function variants.
-  bool VecCallVariantsFound = false;
+  bool getVecCallVariantsFound() const {
+    return CountableExitingBlocks.getFlag(1);
+  }
+  bool setVecCallVariantsFound(bool Value) {
+    CountableExitingBlocks.setFlag(1, Value);
+    return Value;
+  }
 
   /// Keep track of all the countable and uncountable exiting blocks if
   /// the exact backedge taken count is not computable.
-  SmallVector<BasicBlock *, 4> CountableExitingBlocks;
+  llvm::SmallVectorWithFlags<BasicBlock *, 4, 2> CountableExitingBlocks;
 
   /// Records whether we have an uncountable early exit in a loop that's
   /// either read-only or read-write.
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
index 762109f1a7b38..d3b1ca214779c 100644
--- a/llvm/lib/Analysis/AssumptionCache.cpp
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
@@ -204,7 +204,7 @@ void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(Value *NV) {
 }
 
 void AssumptionCache::scanFunction() {
-  assert(!Scanned && "Tried to scan the function twice!");
+  assert(!isScanned() && "Tried to scan the function twice!");
   assert(AssumeHandles.empty() && "Already have assumes when scanning!");
 
   // Go through all instructions in all blocks, add all calls to @llvm.assume
@@ -215,7 +215,7 @@ void AssumptionCache::scanFunction() {
         AssumeHandles.push_back(&I);
 
   // Mark the scan as complete.
-  Scanned = true;
+  AssumeHandles.setFlag(0, true);
 
   // Update affected values.
   for (auto &A : AssumeHandles)
@@ -246,7 +246,7 @@ findCacheViolation(const Function &F, ArrayRef<WeakVH> Assumptions,
 void AssumptionCache::registerAssumption(AssumeInst *CI) {
   // If we haven't scanned the function yet, just drop this assumption. It will
   // be found when we scan later.
-  if (!Scanned)
+  if (!isScanned())
     return;
 
   AssumeHandles.push_back(CI);
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 7a79b0d6e24f1..967eedb346bd0 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1437,7 +1437,7 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
   // on corresponding edges. Don't do this if we are analyzing across
   // iterations, as we may pick a different phi entry in different iterations.
   if (const PHINode *PN2 = dyn_cast<PHINode>(V2))
-    if (PN2->getParent() == PN->getParent() && !AAQI.MayBeCrossIteration) {
+    if (PN2->getParent() == PN->getParent() && !AAQI.mayBeCrossIteration()) {
       std::optional<AliasResult> Alias;
       for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
         AliasResult ThisAlias = AAQI.AAR.alias(
@@ -1515,7 +1515,10 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize,
 
   // In the recursive alias queries below, we may compare values from two
   // different loop iterations.
-  SaveAndRestore SavedMayBeCrossIteration(AAQI.MayBeCrossIteration, true);
+  bool WasCrossIteration = AAQI.mayBeCrossIteration();
+  auto RestoreCrossIteration =
+      scope_exit([&] { AAQI.setMayBeCrossIteration(WasCrossIteration); });
+  AAQI.setMayBeCrossIteration(true);
 
   AliasResult Alias = AAQI.AAR.alias(MemoryLocation(V1Srcs[0], PNSize),
                                      MemoryLocation(V2, V2Size), AAQI);
@@ -1701,8 +1704,8 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
   // otherwise infinitely recursive queries. Include MayBeCrossIteration in the
   // cache key, because some cases where MayBeCrossIteration==false returns
   // MustAlias or NoAlias may become MayAlias under MayBeCrossIteration==true.
-  AAQueryInfo::LocPair Locs({V1, V1Size, AAQI.MayBeCrossIteration},
-                            {V2, V2Size, AAQI.MayBeCrossIteration});
+  AAQueryInfo::LocPair Locs({V1, V1Size, AAQI.mayBeCrossIteration()},
+                            {V2, V2Size, AAQI.mayBeCrossIteration()});
   const bool Swapped = V1 > V2;
   if (Swapped)
     std::swap(Locs.first, Locs.second);
@@ -1874,7 +1877,7 @@ bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V,
   if (V != V2)
     return false;
 
-  if (!AAQI.MayBeCrossIteration)
+  if (!AAQI.mayBeCrossIteration())
     return true;
 
   // Non-instructions and instructions in the entry block cannot be part of
@@ -2048,7 +2051,7 @@ std::optional<APInt> BasicAAResult::computeMinAbsVarOffset(
     const VariableGEPIndex &Var1 = VarIndices[1];
     bool Preconditions =
         Var0.Val.TruncBits == 0 && Var0.Val.hasSameCastsAs(Var1.Val) &&
-        !AAQI.MayBeCrossIteration && MultiplyByScaleNoWrap(Var0) &&
+        !AAQI.mayBeCrossIteration() && MultiplyByScaleNoWrap(Var0) &&
         MultiplyByScaleNoWrap(Var1);
 
     if (!Preconditions)
diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
index 66c36f36d7d92..062ae493b7ca8 100644
--- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
+++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
@@ -149,8 +149,8 @@ void Distribution::add(const BlockNode &Node, uint64_t Amount,
 
   // Check for overflow.  It should be impossible to overflow twice.
   bool IsOverflow = NewTotal < Total;
-  assert(!(DidOverflow && IsOverflow) && "unexpected repeated overflow");
-  DidOverflow |= IsOverflow;
+  assert(!(Weights.getFlag(0) && IsOverflow) && "unexpected repeated overflow");
+  Weights.setFlag(0, Weights.getFlag(0) || IsOverflow);
 
   // Update the total.
   Total = NewTotal;
@@ -251,7 +251,7 @@ void Distribution::normalize() {
   // If we shift at all, shift by 1 extra.  Otherwise, the lower limit of 1
   // for each weight can cause a 32-bit overflow.
   int Shift = 0;
-  if (DidOverflow)
+  if (Weights.getFlag(0))
     Shift = 33;
   else if (Total > UINT32_MAX)
     Shift = 33 - llvm::countl_zero(Total);
@@ -405,7 +405,7 @@ void BlockFrequencyInfoImplBase::packageLoop(LoopData &Loop) {
       Loop->Exits.clear();
     LLVM_DEBUG(dbgs() << " - node: " << getBlockName(M.Index) << "\n");
   }
-  Loop.IsPackaged = true;
+  Loop.setIsPackaged(true);
 }
 
 #ifndef NDEBUG
@@ -501,7 +501,7 @@ static void unwrapLoop(BlockFrequencyInfoImplBase &BFI, LoopData &Loop) {
                     << ": mass = " << Loop.Mass << ", scale = " << Loop.Scale
                     << "\n");
   Loop.Scale *= Loop.Mass.toScaled();
-  Loop.IsPackaged = false;
+  Loop.setIsPackaged(false);
   LLVM_DEBUG(dbgs() << "  => combined-scale = " << Loop.Scale << "\n");
 
   // Propagate the head scale through the loop.  Since members are visited in
diff --git a/llvm/lib/Analysis/ImportedFunctionsInliningStatistics.cpp b/llvm/lib/Analysis/ImportedFunctionsInliningStatistics.cpp
index f550cd6e1c68e..21f6331879a9f 100644
--- a/llvm/lib/Analysis/ImportedFunctionsInliningStatistics.cpp
+++ b/llvm/lib/Analysis/ImportedFunctionsInliningStatistics.cpp
@@ -39,7 +39,10 @@ ImportedFunctionsInliningStatistics::createInlineGraphNode(const Function &F) {
   auto &ValueLookup = NodesMap[F.getName()];
   if (!ValueLookup) {
     ValueLookup = std::make_unique<InlineGraphNode>();
-    ValueLookup->Imported = F.hasMetadata("thinlto_src_module");
+    [&] {
+      auto PackedFlagValue = F.hasMetadata("thinlto_src_module");
+      return ValueLookup->setImported(PackedFlagValue);
+    }();
   }
   return *ValueLookup;
 }
@@ -51,7 +54,7 @@ void ImportedFunctionsInliningStatistics::recordInline(const Function &Caller,
   InlineGraphNode &CalleeNode = createInlineGraphNode(Callee);
   CalleeNode.NumberOfInlines++;
 
-  if (!CallerNode.Imported && !CalleeNode.Imported) {
+  if (!CallerNode.getImported() && !CalleeNode.getImported()) {
     // Direct inline from not imported callee to not imported caller, so we
     // don't have to add this to graph. It might be very helpful if you wanna
     // get the inliner statistics in compile step where there are no imported
@@ -61,7 +64,7 @@ void ImportedFunctionsInliningStatistics::recordInline(const Function &Caller,
   }
 
   CallerNode.InlinedCallees.push_back(&CalleeNode);
-  if (!CallerNode.Imported) {
+  if (!CallerNode.getImported()) {
     // We could avoid second lookup, but it would make the code ultra ugly.
     auto It = NodesMap.find(Caller.getName());
     assert(It != NodesMap.end() && "The node should be already there.");
@@ -121,7 +124,7 @@ void ImportedFunctionsInliningStatistics::dump(const bool Verbose) {
     if (Node->second->NumberOfInlines == 0)
       continue;
 
-    if (Node->second->Imported) {
+    if (Node->second->getImported()) {
       InlinedImportedFunctionsCount++;
       InlinedImportedFunctionsToImportingModuleCount +=
           int(Node->second->NumberOfRealInlines > 0);
@@ -133,7 +136,7 @@ void ImportedFunctionsInliningStatistics::dump(const bool Verbose) {
 
     if (Verbose)
       Ostream << "Inlined "
-              << (Node->second->Imported ? "imported " : "not imported ")
+              << (Node->second->getImported() ? "imported " : "not imported ")
               << "function [" << Node->first() << "]"
               << ": #inlines = " << Node->second->NumberOfInlines
               << ", #inlines_to_importing_module = "
@@ -178,17 +181,17 @@ void ImportedFunctionsInliningStatistics::calculateRealInlines() {
 
   for (const auto &Name : NonImportedCallers) {
     auto &Node = *NodesMap[Name];
-    if (!Node.Visited)
+    if (!Node.getVisited())
       dfs(Node);
   }
 }
 
 void ImportedFunctionsInliningStatistics::dfs(InlineGraphNode &GraphNode) {
-  assert(!GraphNode.Visited);
-  GraphNode.Visited = true;
+  assert(!GraphNode.getVisited());
+  GraphNode.setVisited(true);
   for (auto *const InlinedFunctionNode : GraphNode.InlinedCallees) {
     InlinedFunctionNode->NumberOfRealInlines++;
-    if (!InlinedFunctionNode->Visited)
+    if (!InlinedFunctionNode->getVisited())
       dfs(*InlinedFunctionNode);
   }
 }
diff --git a/llvm/lib/Analysis/KernelInfo.cpp b/llvm/lib/Analysis/KernelInfo.cpp
index 4594c06859100..21c195ce9463b 100644
--- a/llvm/lib/Analysis/KernelInfo.cpp
+++ b/llvm/lib/Analysis/KernelInfo.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/Analysis/KernelInfo.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
@@ -38,10 +39,11 @@ class KernelInfo {
                              TargetMachine *TM);
 
   /// Whether the function has external linkage and is not a kernel function.
-  bool ExternalNotKernel = false;
+  bool getExternalNotKernel() const { return LaunchBounds.getFlag(0); }
+  void setExternalNotKernel(bool Value) { LaunchBounds.setFlag(0, Value); }
 
   /// Launch bounds.
-  SmallVector<std::pair<StringRef, int64_t>> LaunchBounds;
+  llvm::SmallVectorWithFlags<std::pair<StringRef, int64_t>> LaunchBounds;
 
   /// The number of alloca instructions inside the function, the number of those
   /// with allocation sizes that cannot be determined at compile time, and the
@@ -289,12 +291,15 @@ void KernelInfo::emitKernelInfo(Function &F, FunctionAnalysisManager &FAM,
   KI.FlatAddrspace = TheTTI.getFlatAddressSpace();
 
   // Record function properties.
-  KI.ExternalNotKernel = F.hasExternalLinkage() && !F.hasKernelCallingConv();
+  KI.setExternalNotKernel(F.hasExternalLinkage() && !F.hasKernelCallingConv());
   for (StringRef Name : {"omp_target_num_teams", "omp_target_thread_limit"}) {
     if (auto Val = parseFnAttrAsInteger(F, Name))
       KI.LaunchBounds.push_back({Name, *Val});
   }
-  TheTTI.collectKernelLaunchBounds(F, KI.LaunchBounds);
+  SmallVector<std::pair<StringRef, int64_t>> LaunchBounds;
+  LaunchBounds = std::move(KI.LaunchBounds);
+  TheTTI.collectKernelLaunchBounds(F, LaunchBounds);
+  KI.LaunchBounds.assign(std::move(LaunchBounds));
 
   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
   for (const auto &BB : F)
@@ -302,7 +307,7 @@ void KernelInfo::emitKernelInfo(Function &F, FunctionAnalysisManager &FAM,
 
 #define REMARK_PROPERTY(PROP_NAME)                                             \
   remarkProperty(ORE, F, #PROP_NAME, KI.PROP_NAME)
-  REMARK_PROPERTY(ExternalNotKernel);
+  REMARK_PROPERTY(getExternalNotKernel());
   for (auto LB : KI.LaunchBounds)
     remarkProperty(ORE, F, LB.first, LB.second);
   REMARK_PROPERTY(Allocas);
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index e0543aa71a77e..c28c2495b7889 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AliasSetTracker.h"
 #include "llvm/Analysis/AssumeBundleQueries.h"
@@ -667,7 +668,8 @@ SmallVector<RuntimePointerCheck, 4> RuntimePointerChecking::generateChecks() {
       const RuntimeCheckingPtrGroup &CGJ = CheckingGroups[J];
 
       if (needsChecking(CGI, CGJ)) {
-        CanUseDiffCheck = CanUseDiffCheck && tryToCreateDiffCheck(CGI, CGJ);
+        DiffChecks.setFlag(1, DiffChecks.getFlag(1) ||
+                                  !tryToCreateDiffCheck(CGI, CGJ));
         Checks.emplace_back(&CGI, &CGJ);
       }
     }
@@ -1801,7 +1803,7 @@ class AccessAnalysis {
   const Loop *TheLoop;
 
   /// List of accesses that need a further dependence check.
-  SmallVector<MemAccessInfo, 8> CheckDeps;
+  llvm::SmallVectorWithFlags<MemAccessInfo, 8> CheckDeps;
 
   /// Set of pointers that are read only.
   SmallPtrSet<Value*, 16> ReadOnlyPtr;
@@ -1834,7 +1836,8 @@ class AccessAnalysis {
   /// memcheck analysis without dependency checking
   /// (i.e. ShouldRetryWithRuntimeChecks), isDependencyCheckNeeded is
   /// cleared while this remains set if we have potentially dependent accesses.
-  bool IsRTCheckAnalysisNeeded = false;
+  bool getIsRTCheckAnalysisNeeded() const { return CheckDeps.getFlag(0); }
+  void setIsRTCheckAnalysisNeeded(bool Value) { CheckDeps.setFlag(0, Value); }
 
   /// The SCEV predicate containing all the SCEV-related assumptions.
   PredicatedScalarEvolution &PSE;
@@ -2262,7 +2265,8 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
   bool CanDoRT = true;
 
   bool MayNeedRTCheck = false;
-  if (!IsRTCheckAnalysisNeeded) return true;
+  if (!getIsRTCheckAnalysisNeeded())
+    return true;
 
   if (auto *Deps = DepChecker.getDependences()) {
     // If there are unknown dependences, this means runtime checks are needed to
@@ -2444,11 +2448,12 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
   // If we can do run-time checks, but there are no checks, no runtime checks
   // are needed. This can happen when all pointers point to the same underlying
   // object for example.
-  RtCheck.Need = CanDoRT ? RtCheck.getNumberOfChecks() != 0 : MayNeedRTCheck;
+  RtCheck.setNeedsChecking(CanDoRT ? RtCheck.getNumberOfChecks() != 0
+                                   : MayNeedRTCheck);
 
-  bool CanDoRTIfNeeded = !RtCheck.Need || CanDoRT;
+  bool CanDoRTIfNeeded = !RtCheck.needsChecking() || CanDoRT;
   assert(CanDoRTIfNeeded == (CanDoRT || !MayNeedRTCheck) &&
-         "CanDoRTIfNeeded depends on RtCheck.Need");
+         "CanDoRTIfNeeded depends on RtCheck.needsChecking()");
   if (!CanDoRTIfNeeded && !AllowPartial)
     RtCheck.reset();
   return CanDoRTIfNeeded;
@@ -2538,7 +2543,7 @@ void AccessAnalysis::buildDependenceSets() {
           // catch "a[i] = a[i] + " without having to do a dependence check).
           if ((IsWrite || IsReadOnlyPtr) && AliasSetHasWrite) {
             CheckDeps.push_back(Access);
-            IsRTCheckAnalysisNeeded = true;
+            setIsRTCheckAnalysisNeeded(true);
           }
 
           if (IsWrite)
@@ -3110,7 +3115,7 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
   // TODO: Historically, we didn't retry with runtime checks when (unscaled)
   // strides were different but there is no inherent reason to.
   if (!isa<SCEVConstant>(Dist))
-    ShouldRetryWithRuntimeChecks |= StrideAPtrInt == StrideBPtrInt;
+    InstMap.setFlag(0, InstMap.getFlag(0) || StrideAPtrInt == StrideBPtrInt);
 
   // If distance is a SCEVCouldNotCompute, return Unknown immediately.
   if (isa<SCEVCouldNotCompute>(Dist)) {
@@ -3405,18 +3410,18 @@ bool MemoryDepChecker::areDepsSafe(const DepCandidates &DepCands,
             // dependences.  In that case return as soon as we find the first
             // unsafe dependence.  This puts a limit on this quadratic
             // algorithm.
-            if (RecordDependences) {
+            if (recordDependences()) {
               if (Type != Dependence::NoDep)
                 Dependences.emplace_back(A.second, B.second, Type);
 
               if (Dependences.size() >= MaxDependences) {
-                RecordDependences = false;
+                InstMap.setFlag(1, true);
                 Dependences.clear();
                 LLVM_DEBUG(dbgs()
                            << "Too many dependences, stopped recording\n");
               }
             }
-            if (!RecordDependences && !isSafeForVectorization())
+            if (!recordDependences() && !isSafeForVectorization())
               return false;
           }
         ++OI;
@@ -3453,9 +3458,8 @@ const char *MemoryDepChecker::Dependence::DepName[] = {
     "BackwardVectorizable",
     "BackwardVectorizableButPreventsForwarding"};
 
-void MemoryDepChecker::Dependence::print(
-    raw_ostream &OS, unsigned Depth,
-    const SmallVectorImpl<Instruction *> &Instrs) const {
+void MemoryDepChecker::Dependence::print(raw_ostream &OS, unsigned Depth,
+                                         ArrayRef<Instruction *> Instrs) const {
   OS.indent(Depth) << DepName[Type] << ":\n";
   OS.indent(Depth + 2) << *Instrs[Source] << " -> \n";
   OS.indent(Depth + 2) << *Instrs[Destination] << "\n";
@@ -3517,7 +3521,7 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
   HasConvergentOp = false;
 
   PtrRtChecking->Pointers.clear();
-  PtrRtChecking->Need = false;
+  PtrRtChecking->setNeedsChecking(false);
 
   const bool IsAnnotatedParallel = TheLoop->isAnnotatedParallel();
 
@@ -3776,7 +3780,7 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
       LLVM_DEBUG(dbgs() << "LAA: Retrying with memory checks\n");
 
       PtrRtChecking->reset();
-      PtrRtChecking->Need = true;
+      PtrRtChecking->setNeedsChecking(true);
 
       UncomputablePtr = nullptr;
       HasCompletePtrRtChecking = Accesses.canCheckPtrAtRT(
@@ -3829,7 +3833,7 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
   if (DepsAreSafe) {
     LLVM_DEBUG(
         dbgs() << "LAA: No unsafe dependent memory operations in loop.  We"
-               << (PtrRtChecking->Need ? "" : " don't")
+               << (PtrRtChecking->needsChecking() ? "" : " don't")
                << " need runtime memory checks.\n");
     return true;
   }
@@ -4121,7 +4125,7 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
       OS << ", with a maximum safe store-load forward width of " << SLDist
          << " bits";
     }
-    if (PtrRtChecking->Need)
+    if (PtrRtChecking->needsChecking())
       OS << " with run-time checks";
     OS << "\n";
   }
@@ -4143,7 +4147,7 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
 
   // List the pair of accesses need run-time checks to prove independence.
   PtrRtChecking->print(OS, Depth);
-  if (PtrRtChecking->Need && !HasCompletePtrRtChecking)
+  if (PtrRtChecking->needsChecking() && !HasCompletePtrRtChecking)
     OS.indent(Depth) << "Generated run-time checks are incomplete\n";
   OS << "\n";
 
diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
index 4954121aeabe1..6abba0342ffe0 100644
--- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
@@ -27,6 +27,7 @@
 
 #include "llvm/Analysis/LoopCacheAnalysis.h"
 #include "llvm/ADT/BreadthFirstIterator.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -127,7 +128,7 @@ static const SCEV *computeTripCount(const Loop &L, const SCEV &ElemSize,
 // IndexedReference implementation
 //
 raw_ostream &llvm::operator<<(raw_ostream &OS, const IndexedReference &R) {
-  if (!R.IsValid) {
+  if (!R.getIsValid()) {
     OS << R.StoreOrLoadInst;
     OS << ", IsValid=false.";
     return OS;
@@ -150,8 +151,8 @@ IndexedReference::IndexedReference(Instruction &StoreOrLoadInst,
   assert((isa<StoreInst>(StoreOrLoadInst) || isa<LoadInst>(StoreOrLoadInst)) &&
          "Expecting a load or store instruction");
 
-  IsValid = delinearize(LI);
-  if (IsValid)
+  setIsValid(delinearize(LI));
+  if (getIsValid())
     LLVM_DEBUG(dbgs().indent(2) << "Succesfully delinearized: " << *this
                                 << "\n");
 }
@@ -159,7 +160,7 @@ IndexedReference::IndexedReference(Instruction &StoreOrLoadInst,
 std::optional<bool>
 IndexedReference::hasSpacialReuse(const IndexedReference &Other, unsigned CLS,
                                   AAResults &AA) const {
-  assert(IsValid && "Expecting a valid reference");
+  assert(getIsValid() && "Expecting a valid reference");
 
   if (BasePointer != Other.getBasePointer() && !isAliased(Other, AA)) {
     LLVM_DEBUG(dbgs().indent(2)
@@ -215,7 +216,7 @@ std::optional<bool>
 IndexedReference::hasTemporalReuse(const IndexedReference &Other,
                                    unsigned MaxDistance, const Loop &L,
                                    DependenceInfo &DI, AAResults &AA) const {
-  assert(IsValid && "Expecting a valid reference");
+  assert(getIsValid() && "Expecting a valid reference");
 
   if (BasePointer != Other.getBasePointer() && !isAliased(Other, AA)) {
     LLVM_DEBUG(dbgs().indent(2)
@@ -271,7 +272,7 @@ IndexedReference::hasTemporalReuse(const IndexedReference &Other,
 
 CacheCostTy IndexedReference::computeRefCost(const Loop &L,
                                              unsigned CLS) const {
-  assert(IsValid && "Expecting a valid reference");
+  assert(getIsValid() && "Expecting a valid reference");
   LLVM_DEBUG({
     dbgs().indent(2) << "Computing cache cost for:\n";
     dbgs().indent(4) << *this << "\n";
@@ -361,12 +362,16 @@ CacheCostTy IndexedReference::computeRefCost(const Loop &L,
 bool IndexedReference::delinearize(const LoopInfo &LI) {
   assert(Subscripts.empty() && "Subscripts should be empty");
   assert(Sizes.empty() && "Sizes should be empty");
-  assert(!IsValid && "Should be called once from the constructor");
+  assert(!getIsValid() && "Should be called once from the constructor");
   LLVM_DEBUG(dbgs() << "Delinearizing: " << StoreOrLoadInst << "\n");
 
   const SCEV *ElemSize = SE.getElementSize(&StoreOrLoadInst);
   const BasicBlock *BB = StoreOrLoadInst.getParent();
 
+  SmallVector<const SCEV *, 3> DimensionSizes;
+  DimensionSizes = std::move(Sizes);
+  auto RestoreSizes =
+      scope_exit([&] { Sizes.assign(std::move(DimensionSizes)); });
   if (Loop *L = LI.getLoopFor(BB)) {
     const SCEV *AccessFn =
         SE.getSCEVAtScope(getPointerOperand(&StoreOrLoadInst), L);
@@ -383,7 +388,8 @@ bool IndexedReference::delinearize(const LoopInfo &LI) {
     AccessFn = SE.getMinusSCEV(AccessFn, BasePointer);
 
     // Try to delinearize fixed-size arrays.
-    if (delinearizeFixedSizeArray(SE, AccessFn, Subscripts, Sizes, ElemSize)) {
+    if (delinearizeFixedSizeArray(SE, AccessFn, Subscripts, DimensionSizes,
+                                  ElemSize)) {
       IsFixedSize = true;
       LLVM_DEBUG(dbgs().indent(2) << "In Loop '" << L->getName()
                                   << "', AccessFn: " << *AccessFn << "\n");
@@ -393,20 +399,20 @@ bool IndexedReference::delinearize(const LoopInfo &LI) {
     if (!IsFixedSize) {
       LLVM_DEBUG(dbgs().indent(2) << "In Loop '" << L->getName()
                                   << "', AccessFn: " << *AccessFn << "\n");
-      Sizes.clear();
-      llvm::delinearize(SE, AccessFn, Subscripts, Sizes,
+      DimensionSizes.clear();
+      llvm::delinearize(SE, AccessFn, Subscripts, DimensionSizes,
                         SE.getElementSize(&StoreOrLoadInst));
     }
 
-    if (Subscripts.empty() || Sizes.empty() ||
-        Subscripts.size() != Sizes.size()) {
+    if (Subscripts.empty() || DimensionSizes.empty() ||
+        Subscripts.size() != DimensionSizes.size()) {
       // Attempt to determine whether we have a single dimensional array access.
       // before giving up.
       if (!isOneDimensionalArray(*AccessFn, *ElemSize, *L, SE)) {
         LLVM_DEBUG(dbgs().indent(2)
                    << "ERROR: failed to delinearize reference\n");
         Subscripts.clear();
-        Sizes.clear();
+        DimensionSizes.clear();
         return false;
       }
 
@@ -424,7 +430,7 @@ bool IndexedReference::delinearize(const LoopInfo &LI) {
                                     AccessFnAR->getLoop(), SCEVFlags::FlagNone);
       const SCEV *Div = SE.getUDivExactExpr(AccessFn, ElemSize);
       Subscripts.push_back(Div);
-      Sizes.push_back(ElemSize);
+      DimensionSizes.push_back(ElemSize);
     }
 
     return all_of(Subscripts, [&](const SCEV *Subscript) {
diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp
index 37cea287284cd..fdcae635efe56 100644
--- a/llvm/lib/Analysis/MemorySSAUpdater.cpp
+++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp
@@ -13,6 +13,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/IteratedDominanceFrontier.h"
 #include "llvm/Analysis/LoopIterator.h"
 #include "llvm/Analysis/MemorySSA.h"
@@ -56,15 +57,20 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
     explicit StackFrame(BasicBlock *BB) : BB(BB), PredIt(pred_begin(BB)) {}
     ResumePoint Resume = ResumePoint::EnterBlock;
     // Multi-predecessor loop state.
-    SmallVector<TrackingVH<MemoryAccess>, 4> PhiOps;
+    llvm::SmallVectorWithFlags<TrackingVH<MemoryAccess>, 4, 2> PhiOps;
     // Cursor over BB's predecessors for the resumable RunPredLoop walk. This
     // stays valid across suspend/resume because the walk only modifies
     // MemorySSA, never terminators or CFG edges, so BB's predecessor list does
     // not change.
     pred_iterator PredIt;
     // When set, `Returned` holds the result for the predecessor at PredIt.
-    bool PendingIncoming = false;
-    bool UniqueIncomingAccess = true;
+    bool getPendingIncoming() const { return PhiOps.getFlag(0); }
+    void setPendingIncoming(bool Value) { PhiOps.setFlag(0, Value); }
+    bool getUniqueIncomingAccess() const { return !PhiOps.getFlag(1); }
+    bool setUniqueIncomingAccess(bool Value) {
+      PhiOps.setFlag(1, !Value);
+      return Value;
+    }
     MemoryAccess *SingleAccess = nullptr;
 
     // Fold an incoming predecessor access into this frame's phi operands,
@@ -74,7 +80,7 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
       if (!SingleAccess)
         SingleAccess = Incoming;
       else if (Incoming != SingleAccess)
-        UniqueIncomingAccess = false;
+        setUniqueIncomingAccess(false);
       PhiOps.push_back(Incoming);
     }
   };
@@ -166,10 +172,10 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
       // Get the values in our predecessors for placement of a potential phi
       // node. This will insert phi nodes if we cycle in order to break the
       // cycle and have an operand.
-      if (F.PendingIncoming) {
+      if (F.getPendingIncoming()) {
         // Returned holds the result for the predecessor at PredIt.
         F.incorporate(Returned);
-        F.PendingIncoming = false;
+        F.setPendingIncoming(false);
         ++F.PredIt;
       }
 
@@ -181,7 +187,7 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
           if (MemoryAccess *IncomingAccess = GetLocalDefFromEnd(Pred)) {
             F.incorporate(IncomingAccess);
           } else {
-            F.PendingIncoming = true;
+            F.setPendingIncoming(true);
             WorkStack.emplace_back(Pred);
             Suspended = true;
             break;
@@ -200,7 +206,7 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
       // See if we can avoid the phi by simplifying it.
       auto *Result = tryRemoveTrivialPhi(Phi, F.PhiOps);
       // If we couldn't simplify, we may have to create a phi
-      if (Result == Phi && F.UniqueIncomingAccess && F.SingleAccess) {
+      if (Result == Phi && F.getUniqueIncomingAccess() && F.SingleAccess) {
         // A concrete Phi only exists if we created an empty one to break a
         // cycle.
         if (Phi) {
@@ -209,7 +215,8 @@ MemoryAccess *MemorySSAUpdater::getPreviousDefIterative(
           removeMemoryAccess(Phi);
         }
         Result = F.SingleAccess;
-      } else if (Result == Phi && !(F.UniqueIncomingAccess && F.SingleAccess)) {
+      } else if (Result == Phi &&
+                 !(F.getUniqueIncomingAccess() && F.SingleAccess)) {
         if (!Phi)
           Phi = MSSA->createMemoryPhi(CurBB);
 
diff --git a/llvm/lib/Analysis/PtrUseVisitor.cpp b/llvm/lib/Analysis/PtrUseVisitor.cpp
index 9c79546f491ef..2d4e1eac4513f 100644
--- a/llvm/lib/Analysis/PtrUseVisitor.cpp
+++ b/llvm/lib/Analysis/PtrUseVisitor.cpp
@@ -21,16 +21,14 @@ void detail::PtrUseVisitorBase::enqueueUsers(Value &I) {
   for (Use &U : I.uses()) {
     if (VisitedUses.insert(&U).second) {
       UseToVisit NewU = {
-        UseToVisit::UseAndIsOffsetKnownPair(&U, IsOffsetKnown),
-        Offset
-      };
+          UseToVisit::UseAndIsOffsetKnownPair(&U, isOffsetKnown()), Offset};
       Worklist.push_back(std::move(NewU));
     }
   }
 }
 
 bool detail::PtrUseVisitorBase::adjustOffsetForGEP(GetElementPtrInst &GEPI) {
-  if (!IsOffsetKnown)
+  if (!isOffsetKnown())
     return false;
 
   APInt TmpOffset(DL.getIndexTypeSizeInBits(GEPI.getType()), 0);
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 38b3b20baeb16..a86f9db644275 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8920,7 +8920,8 @@ bool ScalarEvolution::BackedgeTakenInfo::isConstantMaxOrZero(
   auto PredicateNotAlwaysTrue = [](const ExitNotTakenInfo &ENT) {
     return !ENT.hasAlwaysTruePredicate();
   };
-  return MaxOrZero && !any_of(ExitNotTaken, PredicateNotAlwaysTrue);
+  return ExitNotTaken.getFlag(1) &&
+         !any_of(ExitNotTaken, PredicateNotAlwaysTrue);
 }
 
 ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E)
@@ -8931,7 +8932,8 @@ ScalarEvolution::ExitLimit::ExitLimit(
     const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
     ArrayRef<ArrayRef<const SCEVPredicate *>> PredLists)
     : ExactNotTaken(E), ConstantMaxNotTaken(ConstantMaxNotTaken),
-      SymbolicMaxNotTaken(SymbolicMaxNotTaken), MaxOrZero(MaxOrZero) {
+      SymbolicMaxNotTaken(SymbolicMaxNotTaken) {
+  Predicates.setFlag(0, MaxOrZero);
   // If we prove the max count is zero, so is the symbolic bound.  This happens
   // in practice due to differences in a) how context sensitive we've chosen
   // to be and b) how we reason about bounds implied by UB.
@@ -8981,7 +8983,8 @@ ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E,
 ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
     ArrayRef<ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo> ExitCounts,
     bool IsComplete, const SCEV *ConstantMax, bool MaxOrZero)
-    : ConstantMax(ConstantMax), IsComplete(IsComplete), MaxOrZero(MaxOrZero) {
+    : ConstantMax(ConstantMax) {
+  ExitNotTaken.setFlags(unsigned(IsComplete) | (unsigned(MaxOrZero) << 1));
   using EdgeExitInfo = ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo;
 
   ExitNotTaken.reserve(ExitCounts.size());
@@ -9068,7 +9071,7 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
         DT.dominates(ExitBB, Latch)) {
       if (!MustExitMaxBECount) {
         MustExitMaxBECount = EL.ConstantMaxNotTaken;
-        MustExitMaxOrZero = EL.MaxOrZero;
+        MustExitMaxOrZero = EL.isMaxOrZero();
       } else {
         MustExitMaxBECount = getUMinFromMismatchedTypes(MustExitMaxBECount,
                                                         EL.ConstantMaxNotTaken);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 60b7824342aa3..7e74ca9beec54 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -294,7 +294,7 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
 
   // We should have already returned an error if we observed both intrinsics and
   // records in this IR.
-  assert(!(SeenNewDbgInfoFormat && SeenOldDbgInfoFormat) &&
+  assert(!(getSeenNewDbgInfoFormat() && getSeenOldDbgInfoFormat()) &&
          "Mixed debug intrinsics/records seen without a parsing error?");
 
   // Handle any function attribute group forward references.
@@ -7550,10 +7550,10 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) {
     // following the debug records, i.e. they cannot appear after the block
     // terminator.
     while (Lex.getKind() == lltok::hash) {
-      if (SeenOldDbgInfoFormat)
+      if (getSeenOldDbgInfoFormat())
         return error(Lex.getLoc(), "debug record should not appear in a module "
                                    "containing debug info intrinsics");
-      SeenNewDbgInfoFormat = true;
+      setSeenNewDbgInfoFormat(true);
       Lex.Lex();
 
       DbgRecord *DR;
@@ -9054,12 +9054,12 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS,
 
   if (CalleeID.Kind == ValID::t_GlobalName &&
       isOldDbgFormatIntrinsic(CalleeID.StrVal)) {
-    if (SeenNewDbgInfoFormat) {
+    if (getSeenNewDbgInfoFormat()) {
       CI->deleteValue();
       return error(CallLoc, "llvm.dbg intrinsic should not appear in a module "
                             "using non-intrinsic debug info");
     }
-    SeenOldDbgInfoFormat = true;
+    setSeenOldDbgInfoFormat(true);
   }
   CI->setAttributes(PAL);
   ForwardRefAttrGroups[CI] = FwdRefAttrGrps;
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index bad71316e3dce..65459855b1c86 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Bitcode/BitcodeCommon.h"
@@ -590,7 +591,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   uint64_t NextUnreadBit = 0;
   // Last function offset found in the VST.
   uint64_t LastFunctionBlockBit = 0;
-  bool SeenValueSymbolTable = false;
+  bool getSeenValueSymbolTable() const { return SSIDs.getFlag(0); }
+  void setSeenValueSymbolTable(bool Value) { SSIDs.setFlag(0, Value); }
   uint64_t VSTOffset = 0;
 
   std::vector<std::string> SectionTable;
@@ -617,7 +619,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   std::optional<MetadataLoader> MDLoader;
   std::vector<Comdat *> ComdatList;
   DenseSet<GlobalObject *> ImplicitComdatObjects;
-  SmallVector<Instruction *, 64> InstructionList;
+  llvm::SmallVectorWithFlags<Instruction *, 64, 4> InstructionList;
 
   std::vector<std::pair<GlobalVariable *, unsigned>> GlobalInits;
   std::vector<std::pair<GlobalValue *, unsigned>> IndirectSymbolInits;
@@ -652,7 +654,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   // Several operations happen after the module header has been read, but
   // before function bodies are processed. This keeps track of whether
   // we've done this yet.
-  bool SeenFirstFunctionBody = false;
+  bool getSeenFirstFunctionBody() const { return SSIDs.getFlag(1); }
+  void setSeenFirstFunctionBody(bool Value) { SSIDs.setFlag(1, Value); }
 
   /// When function bodies are initially scanned, this map contains info about
   /// where to find deferred function body in the stream.
@@ -682,22 +685,30 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   /// operands are not relative to the instruction ID: basic block numbers, and
   /// types. Once the old style function blocks have been phased out, we would
   /// not need this flag.
-  bool UseRelativeIDs = false;
+  bool getUseRelativeIDs() const { return SSIDs.getFlag(2); }
+  void setUseRelativeIDs(bool Value) { SSIDs.setFlag(2, Value); }
 
   /// True if all functions will be materialized, negating the need to process
   /// (e.g.) blockaddress forward references.
-  bool WillMaterializeAllForwardRefs = false;
+  bool getWillMaterializeAllForwardRefs() const { return SSIDs.getFlag(3); }
+  void setWillMaterializeAllForwardRefs(bool Value) { SSIDs.setFlag(3, Value); }
 
   /// Tracks whether we have seen debug intrinsics or records in this bitcode;
   /// seeing both in a single module is currently a fatal error.
-  bool SeenDebugIntrinsic = false;
-  bool SeenDebugRecord = false;
+  bool getSeenDebugIntrinsic() const { return InstructionList.getFlag(0); }
+  bool setSeenDebugIntrinsic(bool Value) {
+    InstructionList.setFlag(0, Value);
+    return Value;
+  }
+  bool getSeenDebugRecord() const { return InstructionList.getFlag(1); }
+  void setSeenDebugRecord(bool Value) { InstructionList.setFlag(1, Value); }
 
-  bool StripDebugInfo = false;
+  bool getStripDebugInfoFlag() const { return InstructionList.getFlag(2); }
+  void setStripDebugInfoFlag(bool Value) { InstructionList.setFlag(2, Value); }
   TBAAVerifier TBAAVerifyHelper;
 
   std::vector<std::string> BundleTags;
-  SmallVector<SyncScope::ID, 8> SSIDs;
+  llvm::SmallVectorWithFlags<SyncScope::ID, 8, 4> SSIDs;
 
   std::optional<ValueTypeCallbackTy> ValueTypeCallback;
 
@@ -708,7 +719,12 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
   /// intrinsic calls (llvm.dbg.*) are not auto-upgraded to non-instruction
   /// debug records by globalCleanup(); the caller is expected to perform the
   /// upgrade manually after any custom processing.
-  bool SkipDebugIntrinsicUpgrade = false;
+  bool getSkipDebugIntrinsicUpgrade() const {
+    return InstructionList.getFlag(3);
+  }
+  void setSkipDebugIntrinsicUpgrade(bool Value) {
+    InstructionList.setFlag(3, Value);
+  }
 
 public:
   BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
@@ -779,7 +795,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
     if (Slot == Record.size()) return true;
     unsigned ValNo = (unsigned)Record[Slot++];
     // Adjust the ValNo, if it was encoded relative to the InstNum.
-    if (UseRelativeIDs)
+    if (getUseRelativeIDs())
       ValNo = InstNum - ValNo;
     if (ValNo < InstNum) {
       // If this is not a forward reference, just return the value we already
@@ -846,7 +862,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
     if (Slot == Record.size()) return nullptr;
     unsigned ValNo = (unsigned)Record[Slot];
     // Adjust the ValNo, if it was encoded relative to the InstNum.
-    if (UseRelativeIDs)
+    if (getUseRelativeIDs())
       ValNo = InstNum - ValNo;
     return getFnValueByID(ValNo, Ty, TyID, ConstExprInsertBB);
   }
@@ -858,7 +874,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
     if (Slot == Record.size()) return nullptr;
     unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]);
     // Adjust the ValNo, if it was encoded relative to the InstNum.
-    if (UseRelativeIDs)
+    if (getUseRelativeIDs())
       ValNo = InstNum - ValNo;
     return getFnValueByID(ValNo, Ty, TyID, ConstExprInsertBB);
   }
@@ -1101,11 +1117,11 @@ BitcodeReader::BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
 }
 
 Error BitcodeReader::materializeForwardReferencedFunctions() {
-  if (WillMaterializeAllForwardRefs)
+  if (getWillMaterializeAllForwardRefs())
     return Error::success();
 
   // Prevent recursion.
-  WillMaterializeAllForwardRefs = true;
+  setWillMaterializeAllForwardRefs(true);
 
   while (!BasicBlockFwdRefQueue.empty()) {
     Function *F = BasicBlockFwdRefQueue.front();
@@ -1134,7 +1150,7 @@ Error BitcodeReader::materializeForwardReferencedFunctions() {
   BackwardRefFunctions.clear();
 
   // Reset state.
-  WillMaterializeAllForwardRefs = false;
+  setWillMaterializeAllForwardRefs(false);
   return Error::success();
 }
 
@@ -4045,7 +4061,7 @@ Error BitcodeReader::materializeMetadata() {
   return Error::success();
 }
 
-void BitcodeReader::setStripDebugInfo() { StripDebugInfo = true; }
+void BitcodeReader::setStripDebugInfo() { setStripDebugInfoFlag(true); }
 
 /// When we see the block for a function body, remember where it is and then
 /// skip it.  This lets us lazily deserialize the functions.
@@ -4084,7 +4100,7 @@ Error BitcodeReader::globalCleanup() {
     Function *NewFn;
     if (UpgradeIntrinsicFunction(&F,
                                  NewFn, /*CanUpgradeDebugIntrinsicsToRecords=*/
-                                 !SkipDebugIntrinsicUpgrade))
+                                 !getSkipDebugIntrinsicUpgrade()))
       UpgradedIntrinsics[&F] = NewFn;
     // Look for functions that rely on old function attribute behavior.
     UpgradeFunctionAttributes(F);
@@ -4127,12 +4143,12 @@ Error BitcodeReader::rememberAndSkipFunctionBodies() {
   if (Stream.AtEndOfStream())
     return error("Could not find function in stream");
 
-  if (!SeenFirstFunctionBody)
+  if (!getSeenFirstFunctionBody())
     return error("Trying to materialize functions before seeing function blocks");
 
   // An old bitcode file with the symbol table at the end would have
   // finished the parse greedily.
-  assert(SeenValueSymbolTable);
+  assert(getSeenValueSymbolTable());
 
   while (true) {
     Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
@@ -4709,7 +4725,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
           return Err;
         break;
       case bitc::VALUE_SYMTAB_BLOCK_ID:
-        if (!SeenValueSymbolTable) {
+        if (!getSeenValueSymbolTable()) {
           // Either this is an old form VST without function index and an
           // associated VST forward declaration record (which would have caused
           // the VST to be jumped to and parsed before it was encountered
@@ -4718,7 +4734,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
           assert(VSTOffset == 0 || FunctionsWithBodies.empty());
           if (Error Err = parseValueSymbolTable())
             return Err;
-          SeenValueSymbolTable = true;
+          setSeenValueSymbolTable(true);
         } else {
           // We must have had a VST forward declaration record, which caused
           // the parser to jump to and parse the VST earlier.
@@ -4753,21 +4769,21 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
 
         // If this is the first function body we've seen, reverse the
         // FunctionsWithBodies list.
-        if (!SeenFirstFunctionBody) {
+        if (!getSeenFirstFunctionBody()) {
           std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
           if (Error Err = globalCleanup())
             return Err;
-          SeenFirstFunctionBody = true;
+          setSeenFirstFunctionBody(true);
         }
 
         if (VSTOffset > 0) {
           // If we have a VST forward declaration record, make sure we
           // parse the VST now if we haven't already. It is needed to
           // set up the DeferredFunctionInfo vector for lazy reading.
-          if (!SeenValueSymbolTable) {
+          if (!getSeenValueSymbolTable()) {
             if (Error Err = BitcodeReader::parseValueSymbolTable(VSTOffset))
               return Err;
-            SeenValueSymbolTable = true;
+            setSeenValueSymbolTable(true);
             // Fall through so that we record the NextUnreadBit below.
             // This is necessary in case we have an anonymous function that
             // is later materialized. Since it will not have a VST entry we
@@ -4796,7 +4812,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
         // materialization calls will resume it when necessary. If the bitcode
         // file is old, the symbol table will be at the end instead and will not
         // have been seen yet. In this case, just finish the parse now.
-        if (SeenValueSymbolTable) {
+        if (getSeenValueSymbolTable()) {
           NextUnreadBit = Stream.GetCurrentBitNo();
           // After the VST has been parsed, we need to make sure intrinsic name
           // are auto-upgraded.
@@ -4833,7 +4849,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
       Expected<unsigned> VersionOrErr = parseVersionRecord(Record);
       if (!VersionOrErr)
         return VersionOrErr.takeError();
-      UseRelativeIDs = *VersionOrErr >= 1;
+      setUseRelativeIDs(*VersionOrErr >= 1);
       break;
     }
     case bitc::MODULE_CODE_TRIPLE: {  // TRIPLE: [strchr x N]
@@ -4960,7 +4976,7 @@ Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata,
   };
   MDCallbacks.MDType = Callbacks.MDType;
   MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting, MDCallbacks);
-  SkipDebugIntrinsicUpgrade = Callbacks.SkipDebugIntrinsicUpgrade;
+  setSkipDebugIntrinsicUpgrade(Callbacks.SkipDebugIntrinsicUpgrade);
   return parseModule(0, ShouldLazyLoadMetadata, Callbacks);
 }
 
@@ -6335,7 +6351,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
         // negative IDs (for forward references).  Use a signed VBR
         // representation to keep the encoding small.
         Value *V;
-        if (UseRelativeIDs)
+        if (getUseRelativeIDs())
           V = getValueSigned(Record, i * 2 + 1, NextValueNo, Ty, TyID, EdgeBB);
         else
           V = getValue(Record, i * 2 + 1, NextValueNo, Ty, TyID, EdgeBB);
@@ -6859,7 +6875,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
     case bitc::FUNC_CODE_DEBUG_RECORD_LABEL: {
       // DbgLabelRecords are placed after the Instructions that they are
       // attached to.
-      SeenDebugRecord = true;
+      setSeenDebugRecord(true);
       Instruction *Inst = getLastInstruction();
       if (!Inst)
         return error("Invalid dbg record: missing instruction");
@@ -6876,7 +6892,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
     case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
       // DbgVariableRecords are placed after the Instructions that they are
       // attached to.
-      SeenDebugRecord = true;
+      setSeenDebugRecord(true);
       Instruction *Inst = getLastInstruction();
       if (!Inst)
         return error("Invalid dbg record: missing instruction");
@@ -7045,7 +7061,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
       cast<CallInst>(I)->setTailCallKind(TCK);
       cast<CallInst>(I)->setAttributes(PAL);
       if (isa<DbgInfoIntrinsic>(I))
-        SeenDebugIntrinsic = true;
+        setSeenDebugIntrinsic(true);
       if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(I)) {
         unsigned ArgNo = Intrinsic::NoAliasScopeDeclScopeArg;
         if (auto *ListAsValue =
@@ -7248,10 +7264,10 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
 
   // All parsed Functions should load into the debug info format dictated by the
   // Module.
-  if (SeenDebugIntrinsic && SeenDebugRecord)
+  if (getSeenDebugIntrinsic() && getSeenDebugRecord())
     return error("Mixed debug intrinsics and debug records in bitcode module!");
 
-  if (StripDebugInfo)
+  if (getStripDebugInfoFlag())
     stripDebugInfo(*F);
 
   // Finish fn->subprogram upgrade for materialized functions.
@@ -7343,7 +7359,7 @@ Error BitcodeReader::materializeModule() {
     return Err;
 
   // Promise to materialize all forward references.
-  WillMaterializeAllForwardRefs = true;
+  setWillMaterializeAllForwardRefs(true);
 
   // Iterate over the module, deserializing any functions that are still on
   // disk.
diff --git a/llvm/lib/CAS/OnDiskGraphDB.cpp b/llvm/lib/CAS/OnDiskGraphDB.cpp
index ffec3c3dbe8ae..a204242f45d94 100644
--- a/llvm/lib/CAS/OnDiskGraphDB.cpp
+++ b/llvm/lib/CAS/OnDiskGraphDB.cpp
@@ -48,6 +48,7 @@
 #include "OnDiskCommon.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/CAS/OnDiskCASLogger.h"
 #include "llvm/CAS/OnDiskDataAllocator.h"
@@ -437,11 +438,11 @@ using StandaloneDataMapTy = StandaloneDataMap<16>;
 class InternalRefVector {
 public:
   void push_back(InternalRef Ref) {
-    if (NeedsFull)
+    if (getNeedsFull())
       return FullRefs.push_back(Ref);
     if (std::optional<InternalRef4B> Small = InternalRef4B::tryToShrink(Ref))
       return SmallRefs.push_back(*Small);
-    NeedsFull = true;
+    setNeedsFull(true);
     assert(FullRefs.empty());
     FullRefs.reserve(SmallRefs.size() + 1);
     for (InternalRef4B Small : SmallRefs)
@@ -452,14 +453,15 @@ class InternalRefVector {
 
   operator InternalRefArrayRef() const {
     assert(SmallRefs.empty() || FullRefs.empty());
-    return NeedsFull ? InternalRefArrayRef(FullRefs)
-                     : InternalRefArrayRef(SmallRefs);
+    return getNeedsFull() ? InternalRefArrayRef(FullRefs)
+                          : InternalRefArrayRef(SmallRefs);
   }
 
 private:
-  bool NeedsFull = false;
+  bool getNeedsFull() const { return FullRefs.getFlag(0); }
+  void setNeedsFull(bool Value) { FullRefs.setFlag(0, Value); }
   SmallVector<InternalRef4B> SmallRefs;
-  SmallVector<InternalRef> FullRefs;
+  llvm::SmallVectorWithFlags<InternalRef> FullRefs;
 };
 
 } // namespace
diff --git a/llvm/lib/CGData/StableFunctionMap.cpp b/llvm/lib/CGData/StableFunctionMap.cpp
index b8b8cfd1286ae..5e2bd4b6bb7d5 100644
--- a/llvm/lib/CGData/StableFunctionMap.cpp
+++ b/llvm/lib/CGData/StableFunctionMap.cpp
@@ -41,7 +41,7 @@ std::optional<std::string> StableFunctionMap::getNameForId(unsigned Id) const {
 }
 
 void StableFunctionMap::insert(const StableFunction &Func) {
-  assert(!Finalized && "Cannot insert after finalization");
+  assert(!isFinalized() && "Cannot insert after finalization");
   auto FuncNameId = getIdOrCreateForName(Func.FunctionName);
   auto ModuleNameId = getIdOrCreateForName(Func.ModuleName);
   auto IndexOperandHashMap = std::make_unique<IndexOperandHashMapType>();
@@ -54,7 +54,7 @@ void StableFunctionMap::insert(const StableFunction &Func) {
 }
 
 void StableFunctionMap::merge(const StableFunctionMap &OtherMap) {
-  assert(!Finalized && "Cannot merge after finalization");
+  assert(!isFinalized() && "Cannot merge after finalization");
   deserializeLazyLoadingEntries();
   for (auto &[Hash, Funcs] : OtherMap.HashToFuncs) {
     auto &ThisFuncs = HashToFuncs[Hash].Entries;
@@ -258,5 +258,5 @@ void StableFunctionMap::finalize(bool SkipTrim) {
   for (auto It : ToDelete)
     HashToFuncs.erase(It);
 
-  Finalized = true;
+  IdToName.setFlag(0, true);
 }
diff --git a/llvm/lib/CGData/StableFunctionMapRecord.cpp b/llvm/lib/CGData/StableFunctionMapRecord.cpp
index 4840a9b906f26..5473a1d8708c6 100644
--- a/llvm/lib/CGData/StableFunctionMapRecord.cpp
+++ b/llvm/lib/CGData/StableFunctionMapRecord.cpp
@@ -147,12 +147,12 @@ void StableFunctionMapRecord::deserializeEntry(const unsigned char *Ptr,
                                                StableFunctionMap *FunctionMap) {
   auto FunctionNameId =
       endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
-  if (FunctionMap->ReadStableFunctionMapNames)
+  if (FunctionMap->readStableFunctionMapNames())
     assert(FunctionMap->getNameForId(FunctionNameId) &&
            "FunctionNameId out of range");
   auto ModuleNameId =
       endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
-  if (FunctionMap->ReadStableFunctionMapNames)
+  if (FunctionMap->readStableFunctionMapNames())
     assert(FunctionMap->getNameForId(ModuleNameId) &&
            "ModuleNameId out of range");
   auto InstCount =
@@ -200,7 +200,7 @@ void StableFunctionMapRecord::deserialize(const unsigned char *&Ptr,
   const auto NamesByteSize =
       endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);
   const auto NamesOffset = reinterpret_cast<uintptr_t>(Ptr);
-  if (FunctionMap->ReadStableFunctionMapNames) {
+  if (FunctionMap->readStableFunctionMapNames()) {
     for (unsigned I = 0; I < NumNames; ++I) {
       StringRef Name(reinterpret_cast<const char *>(Ptr));
       Ptr += Name.size() + 1;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index ec28ba8c8efd7..0842b794b2898 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -15,6 +15,7 @@
 #include "DwarfUnit.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -204,7 +205,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   /// FoldingSet that uniques the abbreviations.
   FoldingSet<DebugNamesAbbrev> AbbreviationsSet;
   /// Vector containing DebugNames abbreviations for iteration in order.
-  SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector;
+  llvm::SmallVectorWithFlags<DebugNamesAbbrev *, 5> AbbreviationsVector;
   /// The bump allocator to use when creating DIEAbbrev objects in the uniqued
   /// storage container.
   BumpPtrAllocator Alloc;
@@ -218,7 +219,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
   MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
   // Indicates if this module is built with Split Dwarf enabled.
-  bool IsSplitDwarf = false;
+  bool getIsSplitDwarf() const { return AbbreviationsVector.getFlag(0); }
+  void setIsSplitDwarf(bool Value) { AbbreviationsVector.setFlag(0, Value); }
   /// Stores the DIE offsets which are indexed by this table.
   DenseSet<OffsetAndUnitID> IndexedOffsets;
 
@@ -479,7 +481,7 @@ void Dwarf5AccelTableWriter::emitTUList() const {
     Asm->OutStreamer->AddComment("Type unit " + Twine(TU.index()));
     if (std::holds_alternative<MCSymbol *>(TU.value()))
       Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(TU.value()));
-    else if (IsSplitDwarf)
+    else if (getIsSplitDwarf())
       Asm->emitInt64(std::get<uint64_t>(TU.value()));
     else
       Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(TU.value()));
@@ -637,9 +639,10 @@ Dwarf5AccelTableWriter::Dwarf5AccelTableWriter(
       Header(CompUnits.size(), IsSplitDwarf ? 0 : TypeUnits.size(),
              IsSplitDwarf ? TypeUnits.size() : 0, Contents.getBucketCount(),
              Contents.getUniqueNameCount()),
+      AbbreviationsVector(decltype(this->AbbreviationsVector)::withFlags(
+          unsigned(IsSplitDwarf))),
       CompUnits(CompUnits), TypeUnits(TypeUnits),
-      getIndexForEntry(std::move(getIndexForEntry)),
-      IsSplitDwarf(IsSplitDwarf) {
+      getIndexForEntry(std::move(getIndexForEntry)) {
 
   for (auto &Bucket : Contents.getBuckets())
     for (auto *Hash : Bucket)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 2f699d2972504..77ab58b006e5f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -407,9 +407,9 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer,
       OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)),
       PointerSize(tm.getTargetTriple().getArchPointerBitWidth() / 8),
       SM(*this) {
-  VerboseAsm = OutStreamer->isVerboseAsm();
-  DwarfUsesRelocationsAcrossSections =
-      MAI.doesDwarfUseRelocationsAcrossSections();
+  setVerboseAsm(OutStreamer->isVerboseAsm());
+  setDwarfUsesRelocationsAcrossSectionsFlag(
+      MAI.doesDwarfUseRelocationsAcrossSections());
   GetMMI = [this]() {
     auto *MMIWP = getAnalysisIfAvailable<MachineModuleInfoWrapperPass>();
     return MMIWP ? &MMIWP->getMMI() : nullptr;
@@ -532,9 +532,9 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
 bool AsmPrinter::doInitialization(Module &M) {
   MMI = GetMMI();
   PointerSize = M.getDataLayout().getPointerSize(0);
-  HasSplitStack = false;
-  HasNoSplitStack = false;
-  DbgInfoAvailable = !M.debug_compile_units().empty();
+  setHasSplitStack(false);
+  setHasNoSplitStack(false);
+  setDbgInfoAvailable(!M.debug_compile_units().empty());
   const Triple &Target = M.getTargetTriple();
 
   AddrLabelSymbols = nullptr;
@@ -3157,10 +3157,10 @@ bool AsmPrinter::doFinalization(Module &M) {
 
   // Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if
   // split-stack is used.
-  if (M.getTargetTriple().isOSBinFormatELF() && HasSplitStack) {
+  if (M.getTargetTriple().isOSBinFormatELF() && getHasSplitStack()) {
     OutStreamer->switchSection(OutContext.getELFSection(".note.GNU-split-stack",
                                                         ELF::SHT_PROGBITS, 0));
-    if (HasNoSplitStack)
+    if (getHasNoSplitStack())
       OutStreamer->switchSection(OutContext.getELFSection(
           ".note.GNU-no-split-stack", ELF::SHT_PROGBITS, 0));
   }
@@ -3242,12 +3242,12 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
   // Record that there are split-stack functions, so we will emit a special
   // section to tell the linker.
   if (MF.shouldSplitStack()) {
-    HasSplitStack = true;
+    setHasSplitStack(true);
 
     if (!MF.getFrameInfo().needsSplitStackProlog())
-      HasNoSplitStack = true;
+      setHasNoSplitStack(true);
   } else
-    HasNoSplitStack = true;
+    setHasNoSplitStack(true);
 
   // Get the function symbol.
   if (!MAI.isAIX()) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 9cf268ce8ce4f..180e2d75a585d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -2997,10 +2997,9 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
 /// Convenience routine for collecting lexical block information for a list
 /// of lexical scopes.
 void CodeViewDebug::collectLexicalBlockInfo(
-        SmallVectorImpl<LexicalScope *> &Scopes,
-        SmallVectorImpl<LexicalBlock *> &Blocks,
-        SmallVectorImpl<LocalVariable> &Locals,
-        SmallVectorImpl<CVGlobalVariable> &Globals) {
+    ArrayRef<LexicalScope *> Scopes, SmallVectorImpl<LexicalBlock *> &Blocks,
+    SmallVectorImpl<LocalVariable> &Locals,
+    SmallVectorImpl<CVGlobalVariable> &Globals) {
   for (LexicalScope *Scope : Scopes)
     collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
 }
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 9118394f2fe3b..ae6fc95cc5fc0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -411,7 +411,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
 
   // Construct the lexical block tree for a routine, pruning emptpy lexical
   // scopes, and populate it with local variables.
-  void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
+  void collectLexicalBlockInfo(ArrayRef<LexicalScope *> Scopes,
                                SmallVectorImpl<LexicalBlock *> &Blocks,
                                SmallVectorImpl<LocalVariable> &Locals,
                                SmallVectorImpl<CVGlobalVariable> &Globals);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 5e659c7b7c621..dba67a520c749 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -122,7 +122,7 @@ void DebugHandlerBase::identifyScopeMarkers() {
   while (!WorkList.empty()) {
     LexicalScope *S = WorkList.pop_back_val();
 
-    const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
+    ArrayRef<LexicalScope *> Children = S->getChildren();
     if (!Children.empty())
       WorkList.append(Children.begin(), Children.end());
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
index ada7e9a7a9023..3836107fdf09f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -10,6 +10,7 @@
 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
 
 #include "DebugLocStream.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
@@ -135,17 +136,21 @@ class DbgValueLoc {
   /// Any complex address location expression for this DbgValueLoc.
   const DIExpression *Expression;
 
-  SmallVector<DbgValueLocEntry, 2> ValueLocEntries;
+  llvm::SmallVectorWithFlags<DbgValueLocEntry, 2> ValueLocEntries;
 
-  bool IsVariadic;
+  bool getIsVariadic() const { return ValueLocEntries.getFlag(0); }
+  void setIsVariadic(bool Value) { ValueLocEntries.setFlag(0, Value); }
 
 public:
   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)
-      : Expression(Expr), ValueLocEntries(Locs), IsVariadic(true) {}
+      : Expression(Expr),
+        ValueLocEntries(decltype(this->ValueLocEntries)::withFlags(1, Locs)) {}
 
   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,
               bool IsVariadic)
-      : Expression(Expr), ValueLocEntries(Locs), IsVariadic(IsVariadic) {
+      : Expression(Expr),
+        ValueLocEntries(decltype(this->ValueLocEntries)::withFlags(
+            unsigned(IsVariadic), Locs)) {
 #ifndef NDEBUG
     assert(Expr->isValid() ||
            !any_of(Locs, [](auto LE) { return LE.isLocation(); }));
@@ -156,22 +161,22 @@ class DbgValueLoc {
   }
 
   DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc)
-      : Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) {
+      : Expression(Expr), ValueLocEntries(1, Loc) {
     assert(((Expr && Expr->isValid()) || !Loc.isLocation()) &&
            "DBG_VALUE with a machine location must have a valid expression.");
   }
 
   bool isFragment() const { return getExpression()->isFragment(); }
   bool isEntryVal() const { return getExpression()->isEntryValue(); }
-  bool isVariadic() const { return IsVariadic; }
+  bool isVariadic() const { return getIsVariadic(); }
   bool isEquivalent(const DbgValueLoc &Other) const {
     // Cannot be equivalent with different numbers of entries.
     if (ValueLocEntries.size() != Other.ValueLocEntries.size())
       return false;
     bool ThisIsIndirect =
-        !IsVariadic && ValueLocEntries[0].isIndirectLocation();
+        !getIsVariadic() && ValueLocEntries[0].isIndirectLocation();
     bool OtherIsIndirect =
-        !Other.IsVariadic && Other.ValueLocEntries[0].isIndirectLocation();
+        !Other.getIsVariadic() && Other.ValueLocEntries[0].isIndirectLocation();
     // Check equivalence of DIExpressions + Directness together.
     if (!DIExpression::isEqualExpression(Expression, ThisIsIndirect,
                                          Other.Expression, OtherIsIndirect))
@@ -185,7 +190,8 @@ class DbgValueLoc {
              ThisOp.getLoc().getReg() == OtherOp.getLoc().getReg();
     }
     // If neither are indirect, then just compare the loc entries directly.
-    return ValueLocEntries == Other.ValueLocEntries;
+    return (llvm::ArrayRef<llvm::DbgValueLocEntry>(ValueLocEntries) ==
+            llvm::ArrayRef<llvm::DbgValueLocEntry>(Other.ValueLocEntries));
   }
   const DIExpression *getExpression() const { return Expression; }
   ArrayRef<DbgValueLocEntry> getLocEntries() const { return ValueLocEntries; }
@@ -297,8 +303,9 @@ inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {
 
 /// Compare two DbgValueLocs for equality.
 inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) {
-  return A.ValueLocEntries == B.ValueLocEntries &&
-         A.Expression == B.Expression && A.IsVariadic == B.IsVariadic;
+  return (llvm::ArrayRef<llvm::DbgValueLocEntry>(A.ValueLocEntries) ==
+          llvm::ArrayRef<llvm::DbgValueLocEntry>(B.ValueLocEntries)) &&
+         A.Expression == B.Expression && A.getIsVariadic() == B.getIsVariadic();
 }
 
 /// Compare two fragments based on their offset.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
index 6f553dc85c646..7a508c5fc6d12 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
@@ -12,6 +12,7 @@
 #include "ByteStreamer.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace llvm {
 
@@ -45,17 +46,20 @@ class DebugLocStream {
 
 private:
   SmallVector<List, 4> Lists;
-  SmallVector<Entry, 32> Entries;
+  llvm::SmallVectorWithFlags<Entry, 32> Entries;
   SmallString<256> DWARFBytes;
   std::vector<std::string> Comments;
   MCSymbol *Sym = nullptr;
 
   /// Only verbose textual output needs comments.  This will be set to
   /// true for that case, and false otherwise.
-  bool GenerateComments;
+  bool getGenerateComments() const { return Entries.getFlag(0); }
+  void setGenerateComments(bool Value) { Entries.setFlag(0, Value); }
 
 public:
-  DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }
+  DebugLocStream(bool GenerateComments)
+      : Entries(
+            decltype(this->Entries)::withFlags(unsigned(GenerateComments))) {}
   size_t getNumLists() const { return Lists.size(); }
   const List &getList(size_t LI) const { return Lists[LI]; }
   ArrayRef<List> getLists() const { return Lists; }
@@ -103,7 +107,7 @@ class DebugLocStream {
 
 public:
   BufferByteStreamer getStreamer() {
-    return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
+    return BufferByteStreamer(DWARFBytes, Comments, getGenerateComments());
   }
 
   ArrayRef<Entry> getEntries(const List &L) const {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index ee52dca4803ae..596c3653966d0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -620,7 +620,7 @@ void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope,
 void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
                                          SmallVector<RangeSpan, 2> Range) {
 
-  HasRangeLists = true;
+  setHasRangeLists(true);
 
   // Add the range list to the set of ranges to be emitted.
   auto IndexAndList =
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index fefd8adb3c932..3ca81cad6d76b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -43,7 +44,8 @@ class MDNode;
 enum class UnitKind { Skeleton, Full };
 
 class DwarfCompileUnit final : public DwarfUnit {
-  bool HasRangeLists = false;
+  bool getHasRangeLists() const { return CURanges.getFlag(0); }
+  void setHasRangeLists(bool Value) { CURanges.setFlag(0, Value); }
 
   /// The start of the unit line section, this is also
   /// reused in appyStmtList.
@@ -62,7 +64,7 @@ class DwarfCompileUnit final : public DwarfUnit {
   StringMap<const DIE *> GlobalTypes;
 
   // List of ranges for a given compile unit.
-  SmallVector<RangeSpan, 2> CURanges;
+  llvm::SmallVectorWithFlags<RangeSpan, 2> CURanges;
 
   // The base address of this unit, if any. Used for relative references in
   // ranges/locs.
@@ -190,7 +192,7 @@ class DwarfCompileUnit final : public DwarfUnit {
                    DwarfDebug *DW, DwarfFile *DWU,
                    UnitKind Kind = UnitKind::Full);
 
-  bool hasRangeLists() const { return HasRangeLists; }
+  bool hasRangeLists() const { return getHasRangeLists(); }
 
   DwarfCompileUnit *getSkeleton() const {
     return Skeleton;
@@ -441,8 +443,12 @@ class DwarfCompileUnit final : public DwarfUnit {
   void applyLabelAttributes(const DbgLabel &Label, DIE &LabelDie);
 
   /// getRanges - Get the list of ranges for this unit.
-  const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
-  SmallVector<RangeSpan, 2> takeRanges() { return std::move(CURanges); }
+  const SmallVectorWithFlagsImpl<RangeSpan> &getRanges() const {
+    return CURanges;
+  }
+  SmallVector<RangeSpan, 2> takeRanges() {
+    return SmallVector<RangeSpan, 2>(std::move(CURanges));
+  }
 
   void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; }
   const MCSymbol *getBaseAddress() const { return BaseAddress; }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 12fb2829e1ed6..707e2edb4d5f3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -336,9 +336,11 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
 }
 
 DwarfDebug::DwarfDebug(AsmPrinter *A)
-    : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),
+    : DebugHandlerBase(A),
+      ConcreteEntities(decltype(this->ConcreteEntities)::withFlags(
+          (unsigned(bool(A->TM.getTargetTriple().isOSDarwin())) << 1))),
+      DebugLocs(A->OutStreamer->isVerboseAsm()),
       SkeletonHolder(A, "skel_string", DIEValueAllocator),
-      IsDarwin(A->TM.getTargetTriple().isOSDarwin()),
       InfoHolder(A, "info_string", DIEValueAllocator) {
   const Triple &TT = Asm->TM.getTargetTriple();
 
@@ -346,7 +348,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
   // precedence; fall back to triple-based defaults.
   if (Asm->TM.Options.DebuggerTuning != DebuggerKind::Default)
     DebuggerTuning = Asm->TM.Options.DebuggerTuning;
-  else if (IsDarwin)
+  else if (getIsDarwin())
     DebuggerTuning = DebuggerKind::LLDB;
   else if (TT.isPS())
     DebuggerTuning = DebuggerKind::SCE;
@@ -363,10 +365,10 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
   // Always emit .debug_aranges for SCE tuning.
   UseARangesSection = GenerateARangeSection || tuneForSCE();
 
-  HasAppleExtensionAttributes = tuneForLLDB();
+  setHasAppleExtensionAttributes(tuneForLLDB());
 
   // Handle split DWARF.
-  HasSplitDwarf = !Asm->TM.Options.MCOptions.SplitDwarfFile.empty();
+  setHasSplitDwarf(!Asm->TM.Options.MCOptions.SplitDwarfFile.empty());
 
   // SCE defaults to linkage names only for abstract subprograms.
   if (DwarfLinkageNames == DefaultLinkageNames)
@@ -422,11 +424,11 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
   // from each compile and type unit each preceded by a header. The string
   // offsets table used by the pre-DWARF v5 split-DWARF implementation uses
   // a monolithic string offsets table without any header.
-  UseSegmentedStringOffsetsTable = DwarfVersion >= 5;
+  setUseSegmentedStringOffsetsTable(DwarfVersion >= 5);
 
   // Emit call-site-param debug info for GDB and LLDB, if the target supports
   // the debug entry values feature. It can also be enabled explicitly.
-  EmitDebugEntryValues = Asm->TM.shouldEmitDebugEntryValues();
+  setEmitDebugEntryValues(Asm->TM.shouldEmitDebugEntryValues());
 
   // It is unclear if the GCC .debug_macro extension is well-specified
   // for split DWARF. For now, do not allow LLVM to emit it.
@@ -1234,7 +1236,7 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
   // To avoid the compilation directory being ambiguous, let the line table
   // explicitly describe the directory of all files, never relying on the
   // compilation directory.
-  if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU)
+  if (!Asm->OutStreamer->hasRawTextSupport() || getSingleCU())
     Asm->OutStreamer->emitDwarfFile0Directive(
         CompilationDir, DIUnit->getFilename(), getMD5AsBytes(DIUnit->getFile()),
         DIUnit->getSource(), NewCU.getUniqueID());
@@ -1294,7 +1296,7 @@ void DwarfDebug::beginModule(Module *M) {
     return;
 
   assert(NumDebugCUs > 0 && "Asm unexpectedly initialized");
-  SingleCU = NumDebugCUs == 1;
+  setSingleCU(NumDebugCUs == 1);
 
   // Create the symbol that designates the start of the unit's contribution
   // to the string offsets table. In a split DWARF scenario, only the skeleton
@@ -2924,7 +2926,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
   // is still needed as we need its source location.
   if (!TheCU.getCUNode()->getDebugInfoForProfiling() &&
       TheCU.getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly &&
-      LScopes.getAbstractScopesList().empty() && !IsDarwin) {
+      LScopes.getAbstractScopesList().empty() && !getIsDarwin()) {
     for (const auto &R : Asm->MBBSectionRanges)
       addArangeLabel(SymbolCU(&TheCU, R.second.BeginLabel));
 
@@ -4195,7 +4197,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
   NewTU.setType(NewTU.createTypeDIE(CTy));
 
   if (TopLevelType) {
-    auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
+    auto TypeUnitsToAdd = SmallVector<
+        std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>(
+        std::move(TypeUnitsUnderConstruction));
     TypeUnitsUnderConstruction.clear();
 
     // Types referencing entries in the address table cannot be placed in type
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index eb5ebd85d1b9e..9e90db716bdfd 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -366,7 +367,8 @@ class DwarfDebug : public DebugHandlerBase {
   DenseMap<const MCSymbol *, uint64_t> SymSize;
 
   /// Collection of abstract variables/labels.
-  SmallVector<std::unique_ptr<DbgEntity>, 64> ConcreteEntities;
+  llvm::SmallVectorWithFlags<std::unique_ptr<DbgEntity>, 64, 2>
+      ConcreteEntities;
 
   /// Collection of DebugLocEntry. Stored in a linked list so that DIELocLists
   /// can refer to them in spite of insertions into this list.
@@ -404,8 +406,8 @@ class DwarfDebug : public DebugHandlerBase {
 
   DenseMap<const MCSection *, const MCSymbol *> SectionLabels;
 
-  SmallVector<
-      std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
+  llvm::SmallVectorWithFlags<
+      std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1, 4>
       TypeUnitsUnderConstruction;
 
   /// Symbol pointing to the current function's DWARF line table entries.
@@ -472,19 +474,39 @@ class DwarfDebug : public DebugHandlerBase {
   /// DWARF5 Experimental Options
   /// @{
   AccelTableKind TheAccelTableKind;
-  bool HasAppleExtensionAttributes;
-  bool HasSplitDwarf;
+  bool getHasAppleExtensionAttributes() const {
+    return TypeUnitsUnderConstruction.getFlag(0);
+  }
+  void setHasAppleExtensionAttributes(bool Value) {
+    TypeUnitsUnderConstruction.setFlag(0, Value);
+  }
+  bool getHasSplitDwarf() const {
+    return TypeUnitsUnderConstruction.getFlag(1);
+  }
+  void setHasSplitDwarf(bool Value) {
+    TypeUnitsUnderConstruction.setFlag(1, Value);
+  }
 
   /// Whether to generate the DWARF v5 string offsets table.
   /// It consists of a series of contributions, each preceded by a header.
   /// The pre-DWARF v5 string offsets table for split dwarf is, in contrast,
   /// a monolithic sequence of string offsets.
-  bool UseSegmentedStringOffsetsTable;
+  bool getUseSegmentedStringOffsetsTable() const {
+    return TypeUnitsUnderConstruction.getFlag(2);
+  }
+  void setUseSegmentedStringOffsetsTable(bool Value) {
+    TypeUnitsUnderConstruction.setFlag(2, Value);
+  }
 
   /// Enable production of call site parameters needed to print the debug entry
   /// values. Useful for testing purposes when a debugger does not support the
   /// feature yet.
-  bool EmitDebugEntryValues;
+  bool getEmitDebugEntryValues() const {
+    return TypeUnitsUnderConstruction.getFlag(3);
+  }
+  void setEmitDebugEntryValues(bool Value) {
+    TypeUnitsUnderConstruction.setFlag(3, Value);
+  }
 
   /// Separated Dwarf Variables
   /// In general these will all be for bits that are left in the
@@ -503,8 +525,10 @@ class DwarfDebug : public DebugHandlerBase {
   /// @}
 
   /// True iff there are multiple CUs in this module.
-  bool SingleCU;
-  bool IsDarwin;
+  bool getSingleCU() const { return ConcreteEntities.getFlag(0); }
+  void setSingleCU(bool Value) { ConcreteEntities.setFlag(0, Value); }
+  bool getIsDarwin() const { return ConcreteEntities.getFlag(1); }
+  void setIsDarwin(bool Value) { ConcreteEntities.setFlag(1, Value); }
 
   AddressPool AddrPool;
 
@@ -865,11 +889,11 @@ class DwarfDebug : public DebugHandlerBase {
   void setTheAccelTableKind(AccelTableKind K) { TheAccelTableKind = K; };
 
   bool useAppleExtensionAttributes() const {
-    return HasAppleExtensionAttributes;
+    return getHasAppleExtensionAttributes();
   }
 
   /// Returns whether or not to change the current debug info for split DWARF.
-  bool useSplitDwarf() const { return HasSplitDwarf; }
+  bool useSplitDwarf() const { return getHasSplitDwarf(); }
 
   /// Returns whether to generate a string offsets table with (possibly shared)
   /// contributions from each CU and type unit. This implies the use of
@@ -878,12 +902,10 @@ class DwarfDebug : public DebugHandlerBase {
   /// a pre-DWARF v5 implementation of split DWARF sections, which uses a
   /// monolithic string offsets table.
   bool useSegmentedStringOffsetsTable() const {
-    return UseSegmentedStringOffsetsTable;
+    return getUseSegmentedStringOffsetsTable();
   }
 
-  bool emitDebugEntryValues() const {
-    return EmitDebugEntryValues;
-  }
+  bool emitDebugEntryValues() const { return getEmitDebugEntryValues(); }
 
   bool useOpConvert() const {
     return EnableOpConvert;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index bfcc1bd5f37dd..5d776d11dee44 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -328,8 +328,9 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
   // covering a composite location description. In the future we may want to
   // emit entry value operations for each register location in the composite
   // location, but until that is supported do not emit anything.
-  if ((HasComplexExpression || IsEmittingEntryValue) && DwarfRegs.size() > 1) {
-    if (IsEmittingEntryValue)
+  if ((HasComplexExpression || getIsEmittingEntryValue()) &&
+      DwarfRegs.size() > 1) {
+    if (getIsEmittingEntryValue())
       cancelEntryValue();
     DwarfRegs.clear();
     LocationKind = Unknown;
@@ -468,19 +469,19 @@ void DwarfExpression::beginEntryValueExpression(
   auto Op = ExprCursor.take();
   (void)Op;
   assert(Op && isa<DIExpression::EntryValueOp>(*Op));
-  assert(!IsEmittingEntryValue && "Already emitting entry value?");
+  assert(!getIsEmittingEntryValue() && "Already emitting entry value?");
   assert(cast<DIExpression::EntryValueOp>(*Op).getNumOperations() == 1 &&
          "Can currently only emit entry values covering a single operation");
 
   SavedLocationKind = LocationKind;
   LocationKind = Register;
   LocationFlags |= EntryValue;
-  IsEmittingEntryValue = true;
+  setIsEmittingEntryValue(true);
   enableTemporaryBuffer();
 }
 
 void DwarfExpression::finalizeEntryValue() {
-  assert(IsEmittingEntryValue && "Entry value not open?");
+  assert(getIsEmittingEntryValue() && "Entry value not open?");
   disableTemporaryBuffer();
 
   emitOp(CU.getDwarf5OrGNULocationAtom(dwarf::DW_OP_entry_value));
@@ -494,11 +495,11 @@ void DwarfExpression::finalizeEntryValue() {
 
   LocationFlags &= ~EntryValue;
   LocationKind = SavedLocationKind;
-  IsEmittingEntryValue = false;
+  setIsEmittingEntryValue(false);
 }
 
 void DwarfExpression::cancelEntryValue() {
-  assert(IsEmittingEntryValue && "Entry value not open?");
+  assert(getIsEmittingEntryValue() && "Entry value not open?");
   disableTemporaryBuffer();
 
   // The temporary buffer can't be emptied, so for now just assert that nothing
@@ -507,7 +508,7 @@ void DwarfExpression::cancelEntryValue() {
          "Began emitting entry value block before cancelling entry value");
 
   LocationKind = SavedLocationKind;
-  IsEmittingEntryValue = false;
+  setIsEmittingEntryValue(false);
 }
 
 unsigned DwarfExpression::getOrCreateBaseType(unsigned BitSize,
@@ -554,7 +555,8 @@ bool DwarfExpression::addExpression(
     llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg) {
   // Entry values can currently only cover the initial register location,
   // and not any other parts of the following DWARF expression.
-  assert(!IsEmittingEntryValue && "Can't emit entry value around expression");
+  assert(!getIsEmittingEntryValue() &&
+         "Can't emit entry value around expression");
 
   std::optional<DIExpression::ConvertOp> PrevConvertOp;
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 58784df57fd8c..965fce7b210eb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -16,6 +16,7 @@
 #include "ByteStreamer.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include <cassert>
 #include <cstdint>
@@ -64,12 +65,13 @@ class DwarfExpression {
   };
 
   /// Whether we are currently emitting an entry value operation.
-  bool IsEmittingEntryValue = false;
+  bool getIsEmittingEntryValue() const { return DwarfRegs.getFlag(0); }
+  void setIsEmittingEntryValue(bool Value) { DwarfRegs.setFlag(0, Value); }
 
   DwarfCompileUnit &CU;
 
   /// The register location, if any.
-  SmallVector<Register, 2> DwarfRegs;
+  llvm::SmallVectorWithFlags<Register, 2> DwarfRegs;
 
   /// Current Fragment Offset in Bits.
   uint64_t OffsetInBits = 0;
diff --git a/llvm/lib/CodeGen/CallingConvLower.cpp b/llvm/lib/CodeGen/CallingConvLower.cpp
index 644e9bff8929a..7c87e88652eae 100644
--- a/llvm/lib/CodeGen/CallingConvLower.cpp
+++ b/llvm/lib/CodeGen/CallingConvLower.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/TargetLowering.h"
@@ -22,15 +23,17 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/raw_ostream.h"
+#include <memory>
 
 using namespace llvm;
 
 CCState::CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
                  SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
                  bool NegativeOffsets)
-    : CallingConv(CC), IsVarArg(IsVarArg), MF(MF),
-      TRI(*MF.getSubtarget().getRegisterInfo()), Locs(Locs), Context(Context),
-      NegativeOffsets(NegativeOffsets) {
+    : CallingConv(CC), MF(MF), TRI(*MF.getSubtarget().getRegisterInfo()),
+      Locs(Locs), Context(Context),
+      ByValRegs(decltype(this->ByValRegs)::withFlags(
+          unsigned(IsVarArg) | (unsigned(NegativeOffsets) << 2))) {
 
   // No stack is used.
   StackSize = 0;
@@ -81,9 +84,8 @@ bool CCState::IsShadowAllocatedReg(MCRegister Reg) const {
 
 /// Analyze an array of argument values,
 /// incorporating info about the formals into this state.
-void
-CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
-                                CCAssignFn Fn) {
+void CCState::AnalyzeFormalArguments(llvm::ArrayRef<ISD::InputArg> Ins,
+                                     CCAssignFn Fn) {
   unsigned NumArgs = Ins.size();
 
   for (unsigned i = 0; i != NumArgs; ++i) {
@@ -96,8 +98,7 @@ CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
 
 /// Analyze the return values of a function, returning true if the return can
 /// be performed without sret-demotion and false otherwise.
-bool CCState::CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                          CCAssignFn Fn) {
+bool CCState::CheckReturn(llvm::ArrayRef<ISD::OutputArg> Outs, CCAssignFn Fn) {
   // Determine which register each value should be copied into.
   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
     MVT VT = Outs[i].VT;
@@ -110,7 +111,7 @@ bool CCState::CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
 
 /// Analyze the returned values of a return,
 /// incorporating info about the result values into this state.
-void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
+void CCState::AnalyzeReturn(llvm::ArrayRef<ISD::OutputArg> Outs,
                             CCAssignFn Fn) {
   // Determine which register each value should be copied into.
   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
@@ -123,7 +124,7 @@ void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
 
 /// Analyze the outgoing arguments to a call,
 /// incorporating info about the passed values into this state.
-void CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
+void CCState::AnalyzeCallOperands(llvm::ArrayRef<ISD::OutputArg> Outs,
                                   CCAssignFn Fn) {
   unsigned NumOps = Outs.size();
   for (unsigned i = 0; i != NumOps; ++i) {
@@ -161,7 +162,7 @@ void CCState::AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
 
 /// Analyze the return values of a call, incorporating info about the passed
 /// values into this state.
-void CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
+void CCState::AnalyzeCallResult(llvm::ArrayRef<ISD::InputArg> Ins,
                                 CCAssignFn Fn) {
   for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
     MVT VT = Ins[i].VT;
@@ -188,7 +189,7 @@ void CCState::AnalyzeCallResult(MVT VT, Type *OrigTy, CCAssignFn Fn) {
 }
 
 void CCState::ensureMaxAlignment(Align Alignment) {
-  if (!AnalyzingMustTailForwardedRegs)
+  if (!getAnalyzingMustTailForwardedRegs())
     MF.getFrameInfo().ensureMaxAlignment(Alignment);
 }
 
@@ -246,8 +247,21 @@ void CCState::analyzeMustTailForwardedRegisters(
   // Oftentimes calling conventions will not user register parameters for
   // variadic functions, so we need to assume we're not variadic so that we get
   // all the registers that might be used in a non-variadic call.
-  SaveAndRestore SavedVarArg(IsVarArg, false);
-  SaveAndRestore SavedMustTail(AnalyzingMustTailForwardedRegs, true);
+  auto SavedVarArg = [PackedFlagOwner = this] {
+    const bool PackedFlagOld = PackedFlagOwner->getIsVarArg();
+    PackedFlagOwner->setIsVarArg(false);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setIsVarArg(PackedFlagOld);
+    });
+  }();
+  auto SavedMustTail = [PackedFlagOwner = this] {
+    const bool PackedFlagOld =
+        PackedFlagOwner->getAnalyzingMustTailForwardedRegs();
+    PackedFlagOwner->setAnalyzingMustTailForwardedRegs(true);
+    return llvm::scope_exit([PackedFlagOwner, PackedFlagOld] {
+      PackedFlagOwner->setAnalyzingMustTailForwardedRegs(PackedFlagOld);
+    });
+  }();
 
   for (MVT RegVT : RegParmTypes) {
     SmallVector<MCRegister, 8> RemainingRegs;
@@ -264,7 +278,7 @@ void CCState::analyzeMustTailForwardedRegisters(
 bool CCState::resultsCompatible(CallingConv::ID CalleeCC,
                                 CallingConv::ID CallerCC, MachineFunction &MF,
                                 LLVMContext &C,
-                                const SmallVectorImpl<ISD::InputArg> &Ins,
+                                llvm::ArrayRef<ISD::InputArg> Ins,
                                 CCAssignFn CalleeFn, CCAssignFn CallerFn) {
   if (CalleeCC == CallerCC)
     return true;
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index da02814f642e0..d086e588e36cb 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -62,6 +62,7 @@
 #include "llvm/CodeGen/ComplexDeinterleavingPass.h"
 #include "llvm/ADT/AllocatorList.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
@@ -283,7 +284,7 @@ class ComplexDeinterleavingGraph {
   DenseMap<Instruction *, CompositeNode *> RootToNode;
 
   /// Topologically sorted root instructions
-  SmallVector<Instruction *, 1> OrderedRoots;
+  llvm::SmallVectorWithFlags<Instruction *, 1> OrderedRoots;
 
   /// When examining a basic block for complex deinterleaving, if it is a simple
   /// one-block loop, then the only incoming block is 'Incoming' and the
@@ -320,7 +321,8 @@ class ComplexDeinterleavingGraph {
 
   /// Set this flag to true if RealPHI and ImagPHI were reached during reduction
   /// detection.
-  bool PHIsFound = false;
+  bool getPHIsFound() const { return OrderedRoots.getFlag(0); }
+  void setPHIsFound(bool Value) { OrderedRoots.setFlag(0, Value); }
 
   /// OldToNewPHI maps the original real PHINode to a new, double-sized PHINode.
   /// The new PHINode corresponds to a vector of deinterleaved complex numbers.
@@ -1825,7 +1827,7 @@ void ComplexDeinterleavingGraph::identifyReductionNodes() {
 
       RealPHI = ReductionInfo[Real].first;
       ImagPHI = ReductionInfo[Imag].first;
-      PHIsFound = false;
+      setPHIsFound(false);
       auto Node = identifyNode(Real, Imag);
       if (!Node) {
         std::swap(Real, Imag);
@@ -1836,7 +1838,7 @@ void ComplexDeinterleavingGraph::identifyReductionNodes() {
       // If a node is identified and reduction PHINode is used in the chain of
       // operations, mark its operation instructions as used to prevent
       // re-identification and attach the node to the real part
-      if (Node && PHIsFound) {
+      if (Node && getPHIsFound()) {
         LLVM_DEBUG(dbgs() << "Identified reduction starting from instructions: "
                           << *Real << " / " << *Imag << "\n");
         Processed[i] = true;
@@ -1863,9 +1865,9 @@ void ComplexDeinterleavingGraph::identifyReductionNodes() {
 
     RealPHI = ReductionInfo[Real].first;
     ImagPHI = nullptr;
-    PHIsFound = false;
+    setPHIsFound(false);
     auto Node = identifyNode(Real->getOperand(0), Real->getOperand(1));
-    if (Node && PHIsFound) {
+    if (Node && getPHIsFound()) {
       LLVM_DEBUG(
           dbgs() << "Identified single reduction starting from instruction: "
                  << *Real << "/" << *ReductionInfo[Real].second << "\n");
@@ -2244,7 +2246,7 @@ ComplexDeinterleavingGraph::identifyPHINode(Instruction *Real,
   if (Real != RealPHI || (ImagPHI && Imag != ImagPHI))
     return nullptr;
 
-  PHIsFound = true;
+  setPHIsFound(true);
   CompositeNode *PlaceholderNode = prepareCompositeNode(
       ComplexDeinterleavingOperation::ReductionPHI, Real, Imag);
   return submitCompositeNode(PlaceholderNode);
diff --git a/llvm/lib/CodeGen/DFAPacketizer.cpp b/llvm/lib/CodeGen/DFAPacketizer.cpp
index edbd380eb827b..28b842150d301 100644
--- a/llvm/lib/CodeGen/DFAPacketizer.cpp
+++ b/llvm/lib/CodeGen/DFAPacketizer.cpp
@@ -99,7 +99,7 @@ DefaultVLIWScheduler::DefaultVLIWScheduler(MachineFunction &MF,
                                            MachineLoopInfo &MLI,
                                            AAResults *AA)
     : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
-  CanHandleTerminators = true;
+  setCanHandleTerminators(true);
 }
 
 /// Apply each ScheduleDAGMutation step in order.
diff --git a/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp b/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp
index 8d2f9bfb6c5cb..cf64d5dc82a5b 100644
--- a/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp
+++ b/llvm/lib/CodeGen/FixupStatepointCallerSaved.cpp
@@ -22,6 +22,7 @@
 
 #include "llvm/CodeGen/FixupStatepointCallerSaved.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -318,13 +319,14 @@ class StatepointState {
   const uint32_t *Mask;
   // Cache of frame indexes used on previous instruction processing.
   FrameIndexesCache &CacheFI;
-  bool AllowGCPtrInCSR;
+  bool getAllowGCPtrInCSR() const { return RegsToReload.getFlag(0); }
+  void setAllowGCPtrInCSR(bool Value) { RegsToReload.setFlag(0, Value); }
   // Operands with physical registers requiring spilling.
   SmallVector<unsigned, 8> OpsToSpill;
   // Set of register to spill.
   SmallVector<Register, 8> RegsToSpill;
   // Set of registers to reload after statepoint.
-  SmallVector<Register, 8> RegsToReload;
+  llvm::SmallVectorWithFlags<Register, 8> RegsToReload;
   // Map Register to Frame Slot index.
   DenseMap<Register, int> RegToSlotIdx;
 
@@ -333,7 +335,9 @@ class StatepointState {
                   FrameIndexesCache &CacheFI, bool AllowGCPtrInCSR)
       : MI(MI), MF(*MI.getMF()), TRI(*MF.getSubtarget().getRegisterInfo()),
         TII(*MF.getSubtarget().getInstrInfo()), MFI(MF.getFrameInfo()),
-        Mask(Mask), CacheFI(CacheFI), AllowGCPtrInCSR(AllowGCPtrInCSR) {
+        Mask(Mask), CacheFI(CacheFI),
+        RegsToReload(decltype(this->RegsToReload)::withFlags(
+            unsigned(AllowGCPtrInCSR))) {
 
     // Find statepoint's landing pad, if any.
     EHPad = nullptr;
@@ -383,7 +387,7 @@ class StatepointState {
       Register Reg = MO.getReg();
       assert(Reg.isPhysical() && "Only physical regs are expected");
 
-      if (isCalleeSaved(Reg) && (AllowGCPtrInCSR || !GCRegs.contains(Reg)))
+      if (isCalleeSaved(Reg) && (getAllowGCPtrInCSR() || !GCRegs.contains(Reg)))
         continue;
 
       LLVM_DEBUG(dbgs() << "Will spill " << printReg(Reg, &TRI) << " at index "
@@ -484,13 +488,13 @@ class StatepointState {
       // We skipped undef uses and did not spill them, so we should not
       // proceed with defs here.
       if (MI.getOperand(MI.findTiedOperandIdx(I)).isUndef()) {
-        if (AllowGCPtrInCSR) {
+        if (getAllowGCPtrInCSR()) {
           NewIndices.push_back(NewMI->getNumOperands());
           MIB.addReg(Reg, RegState::Define);
         }
         continue;
       }
-      if (!AllowGCPtrInCSR) {
+      if (!getAllowGCPtrInCSR()) {
         assert(is_contained(RegsToSpill, Reg));
         RegsToReload.push_back(Reg);
       } else {
@@ -522,7 +526,7 @@ class StatepointState {
       } else {
         MIB.add(MO);
         unsigned OldDef;
-        if (AllowGCPtrInCSR && MI.isRegTiedToDefOperand(I, &OldDef)) {
+        if (getAllowGCPtrInCSR() && MI.isRegTiedToDefOperand(I, &OldDef)) {
           assert(OldDef < NumDefs);
           assert(NewIndices[OldDef] < NumOps);
           MIB->tieOperands(NewIndices[OldDef], MIB->getNumOperands() - 1);
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index 02181d9e7d8cd..1d278668f6e16 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -149,8 +149,8 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
   getReturnInfo(CallConv, RetTy, CB.getAttributes(), SplitArgs, DL);
   Info.CanLowerReturn = canLowerReturn(MF, CallConv, SplitArgs, IsVarArg);
 
-  Info.IsConvergent = CB.isConvergent();
-  Info.NoMerge = CB.hasFnAttr(Attribute::NoMerge);
+  Info.setIsConvergent(CB.isConvergent());
+  Info.setNoMerge(CB.hasFnAttr(Attribute::NoMerge));
 
   if (!Info.CanLowerReturn) {
     // Callee requires sret demotion.
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index ebf2eb79a6452..abcea561aee50 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
@@ -190,7 +191,8 @@ class IRTranslatorImpl {
 
   // List of stubbed PHI instructions, for values and basic blocks to be filled
   // in once all MachineBasicBlocks have been created.
-  SmallVector<std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4>
+  llvm::SmallVectorWithFlags<
+      std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4, 2>
       PendingPHIs;
 
   /// Record of what frame index has been allocated to specified allocas for
@@ -681,11 +683,16 @@ class IRTranslatorImpl {
 
   // True when either the Target Machine specifies no optimizations or the
   // function has the optnone attribute.
-  bool EnableOpts = false;
+  bool getEnableOpts() const { return PendingPHIs.getFlag(0); }
+  void setEnableOpts(bool Value) { PendingPHIs.setFlag(0, Value); }
 
   /// True when the block contains a tail call. This allows the IRTranslator to
   /// stop translating such blocks early.
-  bool HasTailCall = false;
+  bool getHasTailCall() const { return PendingPHIs.getFlag(1); }
+  bool setHasTailCall(bool Value) {
+    PendingPHIs.setFlag(1, Value);
+    return Value;
+  }
 
   StackProtectorDescriptor SPDescriptor;
 
@@ -1895,13 +1902,13 @@ void IRTranslatorImpl::emitBitTestHeader(SwitchCG::BitTestBlock &B,
 
   MachineBasicBlock *MBB = B.Cases[0].ThisBB;
 
-  if (!B.FallthroughUnreachable)
+  if (!B.getFallthroughUnreachable())
     addSuccessorWithProb(SwitchBB, B.Default, B.DefaultProb);
   addSuccessorWithProb(SwitchBB, MBB, B.Prob);
 
   SwitchBB->normalizeSuccProbs();
 
-  if (!B.FallthroughUnreachable) {
+  if (!B.getFallthroughUnreachable()) {
     // Conditional branch to the default block.
     auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
     auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::integer(1),
@@ -1997,18 +2004,18 @@ bool IRTranslatorImpl::lowerBitTestWorkItem(
   // If the cases in bit test don't form a contiguous range, we evenly
   // distribute the probability on the edge to Fallthrough to two
   // successors of CurMBB.
-  if (!BTB->ContiguousRange) {
+  if (!BTB->getContiguousRange()) {
     BTB->Prob += DefaultProb / 2;
     BTB->DefaultProb -= DefaultProb / 2;
   }
 
   if (FallthroughUnreachable)
-    BTB->FallthroughUnreachable = true;
+    BTB->setFallthroughUnreachable(true);
 
   // If we're in the right place, emit the bit test header right now.
   if (CurMBB == SwitchMBB) {
     emitBitTestHeader(*BTB, SwitchMBB);
-    BTB->Emitted = true;
+    BTB->setEmitted(true);
   }
   return true;
 }
@@ -2025,7 +2032,7 @@ bool IRTranslatorImpl::lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W,
   if (++BBI != FuncInfo.MF->end())
     NextMBB = &*BBI;
 
-  if (EnableOpts) {
+  if (getEnableOpts()) {
     // Here, we order cases by probability so the most likely case will be
     // checked first. However, two clusters can have the same probability in
     // which case their relative ordering is non-deterministic. So we use Low
@@ -2635,7 +2642,7 @@ bool IRTranslatorImpl::translateTrap(const CallInst &CI,
   Info.Callee = MachineOperand::CreateES(TrapFuncName.data());
   Info.CB = &CI;
   Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0};
-  Info.NoMerge = CI.cannotMerge();
+  Info.setNoMerge(CI.cannotMerge());
   return CLI->lowerCall(MIRBuilder, Info);
 }
 
@@ -3602,9 +3609,9 @@ bool IRTranslatorImpl::translateCallBase(const CallBase &CB,
 
   // Check if we just inserted a tail call.
   if (Success) {
-    assert(!HasTailCall && "Can't tail call return twice from block?");
+    assert(!getHasTailCall() && "Can't tail call return twice from block?");
     const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
-    HasTailCall = TII->isTailCall(*std::prev(MIRBuilder.getInsertPt()));
+    setHasTailCall(TII->isTailCall(*std::prev(MIRBuilder.getInsertPt())));
   }
 
   return Success;
@@ -4845,7 +4852,7 @@ bool IRTranslatorImpl::finalizeBasicBlock(const BasicBlock &BB,
                                           MachineBasicBlock &MBB) {
   for (auto &BTB : SL->BitTestCases) {
     // Emit header first, if it wasn't already emitted.
-    if (!BTB.Emitted)
+    if (!BTB.getEmitted())
       emitBitTestHeader(BTB, BTB.Parent);
 
     BranchProbability UnhandledProb = BTB.Prob;
@@ -4862,7 +4869,8 @@ bool IRTranslatorImpl::finalizeBasicBlock(const BasicBlock &BB,
       // test, and delete the last bit test.
 
       MachineBasicBlock *NextMBB;
-      if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
+      if ((BTB.getContiguousRange() || BTB.getFallthroughUnreachable()) &&
+          j + 2 == ej) {
         // Second-to-last bit-test with contiguous range: fall through to the
         // target of the final bit test.
         NextMBB = BTB.Cases[j + 1].TargetBB;
@@ -4876,7 +4884,8 @@ bool IRTranslatorImpl::finalizeBasicBlock(const BasicBlock &BB,
 
       emitBitTestCase(BTB, NextMBB, UnhandledProb, BTB.Reg, BTB.Cases[j], MBB);
 
-      if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
+      if ((BTB.getContiguousRange() || BTB.getFallthroughUnreachable()) &&
+          j + 2 == ej) {
         // We need to record the replacement phi edge here that normally
         // happens in emitBitTestCase before we delete the case, otherwise the
         // phi edge will be lost.
@@ -4893,7 +4902,7 @@ bool IRTranslatorImpl::finalizeBasicBlock(const BasicBlock &BB,
     CFGEdge HeaderToDefaultEdge = {BTB.Parent->getBasicBlock(),
                                    BTB.Default->getBasicBlock()};
     addMachineCFGPred(HeaderToDefaultEdge, BTB.Parent);
-    if (!BTB.ContiguousRange) {
+    if (!BTB.getContiguousRange()) {
       addMachineCFGPred(HeaderToDefaultEdge, BTB.Cases.back().ThisBB);
     }
   }
@@ -5150,13 +5159,13 @@ bool IRTranslatorImpl::runOnMachineFunction(
   MRI = &MF->getRegInfo();
   DL = &F.getDataLayout();
   const TargetMachine &TM = MF->getTarget();
-  EnableOpts = OptLevel != CodeGenOptLevel::None && !ShouldSkipOpts;
+  setEnableOpts(OptLevel != CodeGenOptLevel::None && !ShouldSkipOpts);
   FuncInfo.MF = MF;
   // Prefer the "exception-model" module flag, else the TargetOptions default.
   FuncInfo.ExceptionModel = F.getParent()->getExceptionModel();
   if (FuncInfo.ExceptionModel == ExceptionHandling::Default)
     FuncInfo.ExceptionModel = TM.getExceptionModel();
-  if (EnableOpts) {
+  if (getEnableOpts()) {
     AA = GetAAResults();
     FuncInfo.BPI = GetBPI();
     AC = GetAC();
@@ -5273,14 +5282,14 @@ bool IRTranslatorImpl::runOnMachineFunction(
       // Set the insertion point of all the following translations to
       // the end of this basic block.
       CurBuilder->setMBB(MBB);
-      HasTailCall = false;
+      setHasTailCall(false);
       for (const Instruction &Inst : *BB) {
         // If we translated a tail call in the last step, then we know
         // everything after the call is either a return, or something that is
         // handled by the call itself. (E.g. a lifetime marker or assume
         // intrinsic.) In this case, we should stop translating the block and
         // move on.
-        if (HasTailCall)
+        if (getHasTailCall())
           break;
 #ifndef NDEBUG
         Verifier.setCurrentInst(&Inst);
diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
index bac2f52c9ede0..9f8c0272d6da9 100644
--- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
@@ -13,6 +13,7 @@
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
@@ -344,12 +345,14 @@ class RegBankSelectImpl {
     /// Index of the operand that will be repaired.
     unsigned OpIdx;
     /// Are all the insert points materializeable?
-    bool CanMaterialize;
+    bool getCanMaterialize() const { return InsertPoints.getFlag(0); }
+    void setCanMaterialize(bool Value) { InsertPoints.setFlag(0, Value); }
     /// Is there any of the insert points needing splitting?
-    bool HasSplit = false;
+    bool getHasSplit() const { return InsertPoints.getFlag(1); }
+    void setHasSplit(bool Value) { InsertPoints.setFlag(1, Value); }
     /// Insertion point for the repair code.
     /// The repairing code needs to happen just before these points.
-    InsertionPoints InsertPoints;
+    llvm::SmallVectorWithFlagsFor<InsertionPoints, 2> InsertPoints;
     /// Some insertion points may need to update the liveness and such.
     Pass *P;
     MachineFunctionAnalysisManager *MFAM;
@@ -369,8 +372,8 @@ class RegBankSelectImpl {
     /// @{
     RepairingKind getKind() const { return Kind; }
     unsigned getOpIdx() const { return OpIdx; }
-    bool canMaterialize() const { return CanMaterialize; }
-    bool hasSplit() { return HasSplit; }
+    bool canMaterialize() const { return getCanMaterialize(); }
+    bool hasSplit() { return getHasSplit(); }
     /// @}
 
     /// \name Overloaded methods to add an insertion point.
@@ -408,8 +411,8 @@ class RegBankSelectImpl {
       assert(NewKind != Kind && "Already of the right Kind");
       Kind = NewKind;
       InsertPoints.clear();
-      CanMaterialize = NewKind != RepairingKind::Impossible;
-      HasSplit = false;
+      setCanMaterialize(NewKind != RepairingKind::Impossible);
+      setHasSplit(false);
       assert(NewKind != RepairingKind::Insert &&
              "We would need more MI to switch to Insert");
     }
@@ -1400,7 +1403,9 @@ RegBankSelectImpl::RepairingPlacement::RepairingPlacement(
     RepairingPlacement::RepairingKind Kind)
     // Default is, we are going to insert code to repair OpIdx.
     : Kind(Kind), OpIdx(OpIdx),
-      CanMaterialize(Kind != RepairingKind::Impossible), P(P) {
+      InsertPoints(decltype(this->InsertPoints)::withFlags(
+          unsigned(bool(Kind != RepairingKind::Impossible)))),
+      P(P) {
   const MachineOperand &MO = MI.getOperand(OpIdx);
   assert(MO.isReg() && "Trying to repair a non-reg operand");
 
@@ -1506,8 +1511,14 @@ void RegBankSelectImpl::RepairingPlacement::addInsertPoint(
 
 void RegBankSelectImpl::RepairingPlacement::addInsertPoint(
     RegBankSelectImpl::InsertPoint &Point) {
-  CanMaterialize &= Point.canMaterialize();
-  HasSplit |= Point.isSplit();
+  [&] {
+    auto PackedFlagValue = Point.canMaterialize();
+    return setCanMaterialize(getCanMaterialize() & PackedFlagValue);
+  }();
+  [&] {
+    auto PackedFlagValue = Point.isSplit();
+    return setHasSplit(getHasSplit() | PackedFlagValue);
+  }();
   InsertPoints.emplace_back(&Point);
 }
 
diff --git a/llvm/lib/CodeGen/LexicalScopes.cpp b/llvm/lib/CodeGen/LexicalScopes.cpp
index 9fc9ac9a66d41..e7ecf8759043a 100644
--- a/llvm/lib/CodeGen/LexicalScopes.cpp
+++ b/llvm/lib/CodeGen/LexicalScopes.cpp
@@ -257,7 +257,7 @@ void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
     auto &ScopePosition = WorkStack.back();
     LexicalScope *WS = ScopePosition.first;
     size_t ChildNum = ScopePosition.second++;
-    const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
+    ArrayRef<LexicalScope *> Children = WS->getChildren();
     if (ChildNum < Children.size()) {
       auto &ChildScope = Children[ChildNum];
       WorkStack.push_back(std::make_pair(ChildScope, 0));
@@ -349,7 +349,7 @@ LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
   const MDNode *N = Desc;
   err.indent(Indent);
   N->dump();
-  if (AbstractScope)
+  if (isAbstractScope())
     err << std::string(Indent, ' ') << "Abstract Scope\n";
 
   if (!Children.empty())
diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
index e34b5e4edaea9..077d1e07e3101 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp
@@ -84,6 +84,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/LexicalScopes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -192,7 +193,8 @@ class TransferTracker {
   MLocTracker *MTracker;
   MachineFunction &MF;
   const DebugVariableMap &DVMap;
-  bool ShouldEmitDebugEntryValues;
+  bool getShouldEmitDebugEntryValues() const { return VarLocs.getFlag(0); }
+  void setShouldEmitDebugEntryValues(bool Value) { VarLocs.setFlag(0, Value); }
 
   /// Record of all changes in variable locations at a block position. Awkwardly
   /// we allow inserting either before or after the point: MBB != nullptr
@@ -233,7 +235,7 @@ class TransferTracker {
   /// between TransferTrackers view of variable locations and MLocTrackers. For
   /// example, MLocTracker observes all clobbers, but TransferTracker lazily
   /// does not.
-  SmallVector<ValueIDNum, 32> VarLocs;
+  llvm::SmallVectorWithFlags<ValueIDNum, 32> VarLocs;
 
   /// Map from LocIdxes to which DebugVariables are based that location.
   /// Mantained while stepping through the block. Not accurate if
@@ -283,7 +285,7 @@ class TransferTracker {
       : TII(TII), MTracker(MTracker), MF(MF), DVMap(DVMap), TRI(TRI),
         CalleeSavedRegs(CalleeSavedRegs) {
     TLI = MF.getSubtarget().getTargetLowering();
-    this->ShouldEmitDebugEntryValues = ShouldEmitDebugEntryValues;
+    this->setShouldEmitDebugEntryValues(ShouldEmitDebugEntryValues);
   }
 
   bool isCalleeSaved(LocIdx L) const {
@@ -666,7 +668,7 @@ class TransferTracker {
                            const ValueIDNum &Num) {
     // Is this variable location a candidate to be an entry value. First,
     // should we be trying this at all?
-    if (!ShouldEmitDebugEntryValues)
+    if (!getShouldEmitDebugEntryValues())
       return false;
 
     const DIExpression *DIExpr = Prop.DIExpr;
@@ -1902,7 +1904,7 @@ void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
   // call, etc). If it is a call that modifies SP, recognise the SP register
   // defs.
   bool CallChangesSP = false;
-  if (AdjustsStackInCalls && MI.isCall() && MI.getOperand(0).isSymbol() &&
+  if (getAdjustsStackInCalls() && MI.isCall() && MI.getOperand(0).isSymbol() &&
       !strcmp(MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
     CallChangesSP = true;
 
@@ -3541,7 +3543,7 @@ void InstrRefBasedLDV::makeDepthFirstEjectionMap(
     LexicalScope *WS = ScopePosition.first;
     ssize_t ChildNum = ScopePosition.second--;
 
-    const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
+    ArrayRef<LexicalScope *> Children = WS->getChildren();
     if (ChildNum >= 0) {
       // If ChildNum is positive, there are remaining children to explore.
       // Push the child and its children-count onto the stack.
@@ -3649,7 +3651,7 @@ bool InstrRefBasedLDV::depthFirstVLocAndEmit(
     HighestDFSIn = std::max(HighestDFSIn, WS->getDFSIn());
 
     // Descend into any scope nests.
-    const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
+    ArrayRef<LexicalScope *> Children = WS->getChildren();
     if (ChildNum < (ssize_t)Children.size()) {
       // There are children to explore -- push onto stack and continue.
       auto &ChildScope = Children[ChildNum];
@@ -3739,9 +3741,10 @@ bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
   LS.scanFunction(MF);
 
   const auto &STI = MF.getSubtarget();
-  AdjustsStackInCalls = MFI->adjustsStack() &&
-                        STI.getFrameLowering()->stackProbeFunctionModifiesSP();
-  if (AdjustsStackInCalls)
+  setAdjustsStackInCalls(
+      MFI->adjustsStack() &&
+      STI.getFrameLowering()->stackProbeFunctionModifiesSP());
+  if (getAdjustsStackInCalls())
     StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
 
   MTracker =
diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
index d73697fe5b4fc..5f327b9634e7e 100644
--- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
+++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/IndexedMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/UniqueVector.h"
 #include "llvm/CodeGen/LexicalScopes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -1222,7 +1223,7 @@ class InstrRefBasedLDV : public LDVImpl {
   /// DBG_PHI read and where. Populated and edited during the machine value
   /// location problem -- we use LLVMs SSA Updater to fix changes by
   /// optimizations that destroy PHI instructions.
-  SmallVector<DebugPHIRecord, 32> DebugPHINumToValue;
+  llvm::SmallVectorWithFlags<DebugPHIRecord, 32> DebugPHINumToValue;
 
   // Map of overlapping variable fragments.
   OverlapMap OverlapFragments;
@@ -1245,7 +1246,10 @@ class InstrRefBasedLDV : public LDVImpl {
   /// True if we need to examine call instructions for stack clobbers. We
   /// normally assume that they don't clobber SP, but stack probes on Windows
   /// do.
-  bool AdjustsStackInCalls = false;
+  bool getAdjustsStackInCalls() const { return DebugPHINumToValue.getFlag(0); }
+  void setAdjustsStackInCalls(bool Value) {
+    DebugPHINumToValue.setFlag(0, Value);
+  }
 
   /// If AdjustsStackInCalls is true, this holds the name of the target's stack
   /// probe function, which is the function we expect will alter the stack
diff --git a/llvm/lib/CodeGen/LiveIntervalUnion.cpp b/llvm/lib/CodeGen/LiveIntervalUnion.cpp
index 4f7b7ba5974cc..3c8d0d50c2448 100644
--- a/llvm/lib/CodeGen/LiveIntervalUnion.cpp
+++ b/llvm/lib/CodeGen/LiveIntervalUnion.cpp
@@ -143,16 +143,17 @@ bool LiveIntervalUnion::Query::isSeenInterference(
 unsigned
 LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
   // Fast path return if we already have the desired information.
-  if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
+  if (getSeenAllInterferences() ||
+      InterferingVRegs.size() >= MaxInterferingRegs)
     return InterferingVRegs.size();
 
   // Set up iterators on the first call.
-  if (!CheckedFirstInterference) {
-    CheckedFirstInterference = true;
+  if (!getCheckedFirstInterference()) {
+    setCheckedFirstInterference(true);
 
     // Quickly skip interference check for empty sets.
     if (LR->empty() || LiveUnion->empty()) {
-      SeenAllInterferences = true;
+      setSeenAllInterferences(true);
       return 0;
     }
 
@@ -179,7 +180,7 @@ LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
       }
       // This LiveUnion segment is no longer interesting.
       if (!(++LiveUnionI).valid()) {
-        SeenAllInterferences = true;
+        setSeenAllInterferences(true);
         return InterferingVRegs.size();
       }
     }
@@ -200,7 +201,7 @@ LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
     // Still not overlapping. Catch up LiveUnionI.
     LiveUnionI.advanceTo(LRI->start);
   }
-  SeenAllInterferences = true;
+  setSeenAllInterferences(true);
   return InterferingVRegs.size();
 }
 
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 0568890583c1d..34c086184f346 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -54,6 +54,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -125,11 +126,19 @@ std::optional<DestSourcePair> isCopyInstr(const MachineInstr &MI,
 
 class CopyTracker {
   struct CopyInfo {
+    CopyInfo() = default;
+    CopyInfo(MachineInstr *MI, bool Avail)
+        : MI(MI), DefRegs(decltype(this->DefRegs)::withFlags(unsigned(Avail))) {
+    }
     MachineInstr *MI = nullptr;
     MachineInstr *LastSeenUseInCopy = nullptr;
     SmallPtrSet<MachineInstr *, 4> SrcUsers;
-    SmallVector<MCRegister, 4> DefRegs;
-    bool Avail = false;
+    llvm::SmallVectorWithFlags<MCRegister, 4> DefRegs;
+    bool getAvail() const { return DefRegs.getFlag(0); }
+    bool setAvail(bool Value) {
+      DefRegs.setFlag(0, Value);
+      return Value;
+    }
   };
 
   DenseMap<MCRegUnit, CopyInfo> Copies;
@@ -167,7 +176,7 @@ class CopyTracker {
       for (MCRegUnit Unit : TRI.regunits(Reg)) {
         auto CI = Copies.find(Unit);
         if (CI != Copies.end())
-          CI->second.Avail = false;
+          CI->second.setAvail(false);
       }
     }
   }
@@ -321,7 +330,7 @@ class CopyTracker {
 
     // Remember Dst is defined by the copy.
     for (MCRegUnit Unit : TRI.regunits(Dst))
-      Copies[Unit] = {MI, nullptr, {}, {}, true};
+      Copies[Unit] = CopyInfo(MI, true);
 
     // Remember source that's copied to Dst. Once it's clobbered, then
     // it's no longer available for copy propagation.
@@ -343,7 +352,7 @@ class CopyTracker {
     auto CI = Copies.find(RegUnit);
     if (CI == Copies.end())
       return nullptr;
-    if (MustBeAvailable && !CI->second.Avail)
+    if (MustBeAvailable && !CI->second.getAvail())
       return nullptr;
     return CI->second.MI;
   }
@@ -422,7 +431,7 @@ class CopyTracker {
                                       bool UseCopyInstr) {
     MCRegUnit RU = *TRI.regunits(Reg).begin();
     auto CI = Copies.find(RU);
-    if (CI == Copies.end() || !CI->second.Avail)
+    if (CI == Copies.end() || !CI->second.getAvail())
       return nullptr;
 
     MachineInstr *DefCopy = CI->second.MI;
@@ -455,7 +464,7 @@ class CopyTracker {
         for (MCRegUnit DstUnit : TRI.regunits(DstReg)) {
           if (!PreservedRegUnits.test(static_cast<unsigned>(DstUnit))) {
             if (auto CI = Copies.find(DstUnit); CI != Copies.end()) {
-              CI->second.Avail = false;
+              CI->second.setAvail(false);
             }
           }
         }
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index b0f06907ef9da..8e10ad87d89ac 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -1404,11 +1404,11 @@ bool MachineFunction::shouldUseDebugInstrRef() const {
 }
 
 bool MachineFunction::useDebugInstrRef() const {
-  return UseDebugInstrRef;
+  return getUseDebugInstrRefFlag();
 }
 
 void MachineFunction::setUseDebugInstrRef(bool Use) {
-  UseDebugInstrRef = Use;
+  setUseDebugInstrRefFlag(Use);
 }
 
 // Use one million as a high / reserved number.
diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index b7b29ba9fb0ad..ae70aab0f830b 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -127,8 +128,10 @@ namespace {
     MachineRegisterInfo *MRI = nullptr;
     const RegisterClassInfo *RegClassInfo = nullptr;
     TargetSchedModel SchedModel;
-    bool PreRegAlloc = false;
-    bool HasProfileData = false;
+    bool getPreRegAlloc() const { return BackTrace.getFlag(0); }
+    void setPreRegAlloc(bool Value) { BackTrace.setFlag(0, Value); }
+    bool getHasProfileData() const { return BackTrace.getFlag(1); }
+    void setHasProfileData(bool Value) { BackTrace.setFlag(1, Value); }
     Pass *LegacyPass;
     MachineFunctionAnalysisManager *MFAM;
 
@@ -139,8 +142,16 @@ namespace {
     MachineDomTreeUpdater *MDTU = nullptr;     // Wraps current dominator tree
 
     // State that is updated as we process loops
-    bool Changed = false;           // True if a loop is changed.
-    bool FirstInLoop = false;       // True if it's the first LICM in the loop.
+    bool getChanged() const { return BackTrace.getFlag(2); }
+    bool setChanged(bool Value) {
+      BackTrace.setFlag(2, Value);
+      return Value;
+    } // True if a loop is changed.
+    bool getFirstInLoop() const { return BackTrace.getFlag(3); }
+    bool setFirstInLoop(bool Value) {
+      BackTrace.setFlag(3, Value);
+      return Value;
+    } // True if it's the first LICM in the loop.
 
     // Holds information about whether it is allowed to move load instructions
     // out of the loop
@@ -168,7 +179,7 @@ namespace {
     SmallVector<unsigned, 8> RegLimit;
 
     // Register pressure on path leading from loop preheader to current BB.
-    SmallVector<SmallVector<unsigned, 8>, 16> BackTrace;
+    llvm::SmallVectorWithFlags<SmallVector<unsigned, 8>, 16, 4> BackTrace;
 
     // For each opcode per preheader, keep a list of potential CSE instructions.
     DenseMap<MachineBasicBlock *,
@@ -189,7 +200,9 @@ namespace {
   public:
     MachineLICMImpl(bool PreRegAlloc, Pass *LegacyPass,
                     MachineFunctionAnalysisManager *MFAM)
-        : PreRegAlloc(PreRegAlloc), LegacyPass(LegacyPass), MFAM(MFAM) {
+        : LegacyPass(LegacyPass), MFAM(MFAM),
+          BackTrace(
+              decltype(this->BackTrace)::withFlags(unsigned(PreRegAlloc))) {
       assert((LegacyPass || MFAM) && "LegacyPass or MFAM must be provided");
       assert(!(LegacyPass && MFAM) &&
              "LegacyPass and MFAM cannot be provided at the same time");
@@ -387,7 +400,7 @@ bool MachineLICMImpl::run(MachineFunction &MF) {
              ? GET_RESULT(MachineBlockFrequency, getMBFI, Info)
              : nullptr;
 
-  Changed = FirstInLoop = false;
+  setChanged(setFirstInLoop(false));
   const TargetSubtargetInfo &ST = MF.getSubtarget();
   TII = ST.getInstrInfo();
   TLI = ST.getTargetLowering();
@@ -396,15 +409,15 @@ bool MachineLICMImpl::run(MachineFunction &MF) {
   MRI = &MF.getRegInfo();
   SchedModel.init(&ST);
 
-  HasProfileData = MF.getFunction().hasProfileData();
+  setHasProfileData(MF.getFunction().hasProfileData());
 
-  if (PreRegAlloc)
+  if (getPreRegAlloc())
     LLVM_DEBUG(dbgs() << "******** Pre-regalloc Machine LICM: ");
   else
     LLVM_DEBUG(dbgs() << "******** Post-regalloc Machine LICM: ");
   LLVM_DEBUG(dbgs() << MF.getName() << " ********\n");
 
-  if (PreRegAlloc) {
+  if (getPreRegAlloc()) {
     // Estimate register pressure during pre-regalloc pass.
     unsigned NumRPS = TRI->getNumRegPressureSets();
     RegPressure.resize(NumRPS);
@@ -421,19 +434,19 @@ bool MachineLICMImpl::run(MachineFunction &MF) {
   while (!Worklist.empty()) {
     MachineLoop *CurLoop = Worklist.pop_back_val();
 
-    if (!PreRegAlloc) {
+    if (!getPreRegAlloc()) {
       HoistRegionPostRA(CurLoop);
     } else {
       // CSEMap is initialized for loop header when the first instruction is
       // being hoisted.
       MachineDomTreeNode *N = MDTU->getDomTree().getNode(CurLoop->getHeader());
-      FirstInLoop = true;
+      setFirstInLoop(true);
       HoistOutOfLoop(N, CurLoop);
       CSEMap.clear();
     }
   }
   releaseMemory();
-  return Changed;
+  return getChanged();
 }
 
 /// Return true if instruction stores to the specified frame.
@@ -763,7 +776,7 @@ void MachineLICMImpl::HoistPostRA(MachineInstr *MI, Register Def,
   AddToLiveIns(Def, CurLoop);
 
   ++NumPostRAHoisted;
-  Changed = true;
+  setChanged(true);
 }
 
 /// Check if this mbb is guaranteed to execute. If not then a load from this mbb
@@ -1508,7 +1521,7 @@ MachineInstr *
 MachineLICMImpl::LookForDuplicate(const MachineInstr *MI,
                                   std::vector<MachineInstr *> &PrevMIs) {
   for (MachineInstr *PrevMI : PrevMIs)
-    if (TII->produceSameValue(*MI, *PrevMI, (PreRegAlloc ? MRI : nullptr)))
+    if (TII->produceSameValue(*MI, *PrevMI, (getPreRegAlloc() ? MRI : nullptr)))
       return PrevMI;
 
   return nullptr;
@@ -1614,7 +1627,7 @@ unsigned MachineLICMImpl::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
 
   // Disable the instruction hoisting due to block hotness
   if ((DisableHoistingToHotterBlocks == UseBFI::All ||
-      (DisableHoistingToHotterBlocks == UseBFI::PGO && HasProfileData)) &&
+       (DisableHoistingToHotterBlocks == UseBFI::PGO && getHasProfileData())) &&
       isTgtHotterThanSrc(SrcBlock, Preheader)) {
     ++NumNotHoistedDueToHotness;
     return HoistResult::NotHoisted;
@@ -1648,9 +1661,9 @@ unsigned MachineLICMImpl::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
 
   // If this is the first instruction being hoisted to the preheader,
   // initialize the CSE map with potential common expressions.
-  if (FirstInLoop) {
+  if (getFirstInLoop()) {
     InitCSEMap(Preheader);
-    FirstInLoop = false;
+    setFirstInLoop(false);
   }
 
   // Look for opportunity to CSE the hoisted instruction.
@@ -1694,7 +1707,7 @@ unsigned MachineLICMImpl::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
   }
 
   ++NumHoisted;
-  Changed = true;
+  setChanged(true);
 
   if (HasCSEDone || HasExtractHoistableLoad)
     return HoistResult::Hoisted | HoistResult::ErasedMI;
@@ -1714,7 +1727,7 @@ MachineBasicBlock *MachineLICMImpl::getOrCreatePreheader(MachineLoop *CurLoop) {
     MachineBasicBlock *NewPreheader =
         Pred->SplitCriticalEdge(CurLoop->getHeader(), LegacyPass, MFAM, MDTU);
     if (NewPreheader)
-      Changed = true;
+      setChanged(true);
     return NewPreheader;
   }
 
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index 540c9c8b018da..f0d8509d8a6d8 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -57,6 +57,7 @@
 #include "llvm/CodeGen/MachineOutliner.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
@@ -191,13 +192,14 @@ struct InstructionMapper {
 
   /// Stores the location of the instruction associated with the integer
   /// at index i in \p UnsignedVec for each index i.
-  SmallVector<MachineBasicBlock::iterator> InstrList;
+  llvm::SmallVectorWithFlags<MachineBasicBlock::iterator> InstrList;
 
   // Set if we added an illegal number in the previous step.
   // Since each illegal number is unique, we only need one of them between
   // each range of legal numbers. This lets us make sure we don't add more
   // than one illegal number per range.
-  bool AddedIllegalLastTime = false;
+  bool getAddedIllegalLastTime() const { return InstrList.getFlag(0); }
+  void setAddedIllegalLastTime(bool Value) { InstrList.setFlag(0, Value); }
 
   /// Maps \p *It to a legal integer.
   ///
@@ -212,7 +214,7 @@ struct InstructionMapper {
       SmallVector<MachineBasicBlock::iterator> &InstrListForMBB) {
     // We added something legal, so we should unset the AddedLegalLastTime
     // flag.
-    AddedIllegalLastTime = false;
+    setAddedIllegalLastTime(false);
 
     // If we have at least two adjacent legal instructions (which may have
     // invisible instructions in between), remember that.
@@ -263,11 +265,11 @@ struct InstructionMapper {
     CanOutlineWithPrevInstr = false;
 
     // Only add one illegal number per range of legal numbers.
-    if (AddedIllegalLastTime)
+    if (getAddedIllegalLastTime())
       return IllegalInstrNumber;
 
     // Remember that we added an illegal number last time.
-    AddedIllegalLastTime = true;
+    setAddedIllegalLastTime(true);
     unsigned MINumber = IllegalInstrNumber;
 
     InstrListForMBB.push_back(It);
@@ -388,7 +390,7 @@ struct InstructionMapper {
           // Normally this is set by mapTo(Blah)Unsigned, but we just want to
           // skip this instruction. So, unset the flag here.
           ++NumInvisible;
-          AddedIllegalLastTime = false;
+          setAddedIllegalLastTime(false);
           break;
         }
       }
diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp
index be68d42b187a7..9c673a375498c 100644
--- a/llvm/lib/CodeGen/MachinePipeliner.cpp
+++ b/llvm/lib/CodeGen/MachinePipeliner.cpp
@@ -40,6 +40,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -245,7 +246,7 @@ namespace {
 /// information related to the instruction.
 struct SUnitWithMemInfo {
   SUnit *SU;
-  SmallVector<const Value *, 2> UnderlyingObjs;
+  llvm::SmallVectorWithFlags<const Value *, 2> UnderlyingObjs;
 
   /// The value of a memory operand.
   const Value *MemOpValue = nullptr;
@@ -256,7 +257,8 @@ struct SUnitWithMemInfo {
   AAMDNodes AATags;
 
   /// True if all the underlying objects are identified.
-  bool IsAllIdentified = false;
+  bool getIsAllIdentified() const { return UnderlyingObjs.getFlag(0); }
+  void setIsAllIdentified(bool Value) { UnderlyingObjs.setFlag(0, Value); }
 
   SUnitWithMemInfo(SUnit *SU);
 
@@ -1138,7 +1140,7 @@ SUnitWithMemInfo::SUnitWithMemInfo(SUnit *SU) : SU(SU) {
     return;
   for (const Value *Obj : UnderlyingObjs)
     if (!isIdentifiedObject(Obj)) {
-      IsAllIdentified = false;
+      setIsAllIdentified(false);
       break;
     }
 }
@@ -1147,7 +1149,7 @@ bool SUnitWithMemInfo::isTriviallyDisjoint(
     const SUnitWithMemInfo &Other) const {
   // If all underlying objects are identified objects and there is no overlap
   // between them, then these two instructions are disjoint.
-  if (!IsAllIdentified || !Other.IsAllIdentified)
+  if (!getIsAllIdentified() || !Other.getIsAllIdentified())
     return false;
   for (const Value *Obj : UnderlyingObjs)
     if (llvm::is_contained(Other.UnderlyingObjs, Obj))
@@ -1168,7 +1170,9 @@ bool SUnitWithMemInfo::getUnderlyingObjects() {
     return false;
   MemOpValue = MM->getValue();
   MemOpOffset = MM->getOffset();
-  llvm::getUnderlyingObjects(MemOpValue, UnderlyingObjs);
+  SmallVector<const Value *, 2> Objects;
+  llvm::getUnderlyingObjects(MemOpValue, Objects);
+  UnderlyingObjs.assign(std::move(Objects));
 
   // TODO: A no alias scope may be valid only in a single iteration. In this
   // case we need to peel off it like LoopAccessAnalysis does.
@@ -3988,7 +3992,7 @@ LLVM_DUMP_METHOD void NodeSet::dump() const { print(dbgs()); }
 
 void ResourceManager::dumpMRT() const {
   LLVM_DEBUG({
-    if (UseDFA)
+    if (getUseDFA())
       return;
     std::stringstream SS;
     SS << "MRT:\n";
@@ -4011,7 +4015,8 @@ void ResourceManager::dumpMRT() const {
 ResourceManager::ResourceManager(const TargetSubtargetInfo *ST,
                                  ScheduleDAGInstrs *DAG)
     : STI(ST), SM(ST->getSchedModel()), ST(ST), TII(ST->getInstrInfo()),
-      DAG(DAG), UseDFA(ST->useDFAforSMS()),
+      DAG(DAG), NumScheduledMops(decltype(this->NumScheduledMops)::withFlags(
+                    unsigned(bool(ST->useDFAforSMS())))),
       ProcResourceMasks(SM.getNumProcResourceKinds(), 0),
       IssueWidth(SM.IssueWidth) {
   initProcResourceVectors(SM, ProcResourceMasks);
@@ -4069,7 +4074,7 @@ bool ResourceManager::canReserveResources(SUnit &SU, int Cycle) {
     if (SwpDebugResource)
       dbgs() << "canReserveResources:\n";
   });
-  if (UseDFA)
+  if (getUseDFA())
     return DFAResources[positiveModulo(Cycle, InitiationInterval)]
         ->canReserveResources(&SU.getInstr()->getDesc());
 
@@ -4095,7 +4100,7 @@ void ResourceManager::reserveResources(SUnit &SU, int Cycle) {
     if (SwpDebugResource)
       dbgs() << "reserveResources:\n";
   });
-  if (UseDFA)
+  if (getUseDFA())
     return DFAResources[positiveModulo(Cycle, InitiationInterval)]
         ->reserveResources(&SU.getInstr()->getDesc());
 
@@ -4120,7 +4125,7 @@ void ResourceManager::reserveResources(SUnit &SU, int Cycle) {
 
 void ResourceManager::reserveResources(const MCSchedClassDesc *SCDesc,
                                        int Cycle) {
-  assert(!UseDFA);
+  assert(!getUseDFA());
   for (const MCWriteProcResEntry &PRE : make_range(
            STI->getWriteProcResBegin(SCDesc), STI->getWriteProcResEnd(SCDesc)))
     for (int C = Cycle; C < Cycle + PRE.ReleaseAtCycle; ++C)
@@ -4132,7 +4137,7 @@ void ResourceManager::reserveResources(const MCSchedClassDesc *SCDesc,
 
 void ResourceManager::unreserveResources(const MCSchedClassDesc *SCDesc,
                                          int Cycle) {
-  assert(!UseDFA);
+  assert(!getUseDFA());
   for (const MCWriteProcResEntry &PRE : make_range(
            STI->getWriteProcResBegin(SCDesc), STI->getWriteProcResEnd(SCDesc)))
     for (int C = Cycle; C < Cycle + PRE.ReleaseAtCycle; ++C)
@@ -4143,7 +4148,7 @@ void ResourceManager::unreserveResources(const MCSchedClassDesc *SCDesc,
 }
 
 bool ResourceManager::isOverbooked() const {
-  assert(!UseDFA);
+  assert(!getUseDFA());
   for (int Slot = 0; Slot < InitiationInterval; ++Slot) {
     for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
       const MCProcResourceDesc *Desc = SM.getProcResource(I);
@@ -4157,7 +4162,7 @@ bool ResourceManager::isOverbooked() const {
 }
 
 int ResourceManager::calculateResMIIDFA() const {
-  assert(UseDFA);
+  assert(getUseDFA());
 
   // Sort the instructions by the number of available choices for scheduling,
   // least to most. Use the number of critical resources as the tie breaker.
@@ -4220,7 +4225,7 @@ int ResourceManager::calculateResMIIDFA() const {
 }
 
 int ResourceManager::calculateResMII() const {
-  if (UseDFA)
+  if (getUseDFA())
     return calculateResMIIDFA();
 
   // Count each resource consumption and divide it by the number of units.
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index 035ccaac06a5a..6d912b5bb087a 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -42,11 +42,10 @@ static cl::opt<bool> EnableSubRegLiveness("enable-subreg-liveness", cl::Hidden,
 // Pin the vtable to this file.
 void MachineRegisterInfo::Delegate::anchor() {}
 
-MachineRegisterInfo::MachineRegisterInfo(MachineFunction *MF)
-    : MF(MF),
-      TracksSubRegLiveness(EnableSubRegLiveness.getNumOccurrences()
-                               ? EnableSubRegLiveness
-                               : MF->getSubtarget().enableSubRegLiveness()) {
+MachineRegisterInfo::MachineRegisterInfo(MachineFunction *MF) : MF(MF) {
+  UpdatedCSRs.setFlag(0, EnableSubRegLiveness.getNumOccurrences()
+                             ? EnableSubRegLiveness
+                             : MF->getSubtarget().enableSubRegLiveness());
   unsigned NumRegs = getTargetRegisterInfo()->getNumRegs();
   VRegInfo.reserve(256);
   UsedPhysRegMask.resize(NumRegs);
@@ -625,7 +624,7 @@ void MachineRegisterInfo::disableCalleeSavedRegister(MCRegister Reg) {
   assert(Reg && (Reg < TRI->getNumRegs()) &&
          "Trying to disable an invalid register");
 
-  if (!IsUpdatedCSRsInitialized) {
+  if (!isUpdatedCSRsInitialized()) {
     const MCPhysReg *CSR = TRI->getCalleeSavedRegs(MF);
     for (const MCPhysReg *I = CSR; *I; ++I)
       UpdatedCSRs.push_back(*I);
@@ -634,7 +633,7 @@ void MachineRegisterInfo::disableCalleeSavedRegister(MCRegister Reg) {
     // (no more registers should be pushed).
     UpdatedCSRs.push_back(0);
 
-    IsUpdatedCSRsInitialized = true;
+    UpdatedCSRs.setFlag(1, true);
   }
 
   // Remove the register (and its aliases from the list).
@@ -643,7 +642,7 @@ void MachineRegisterInfo::disableCalleeSavedRegister(MCRegister Reg) {
 }
 
 const MCPhysReg *MachineRegisterInfo::getCalleeSavedRegs() const {
-  if (IsUpdatedCSRsInitialized)
+  if (isUpdatedCSRsInitialized())
     return UpdatedCSRs.data();
 
   const MCPhysReg *Regs = getTargetRegisterInfo()->getCalleeSavedRegs(MF);
@@ -656,7 +655,7 @@ const MCPhysReg *MachineRegisterInfo::getCalleeSavedRegs() const {
 }
 
 void MachineRegisterInfo::setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs) {
-  if (IsUpdatedCSRsInitialized)
+  if (isUpdatedCSRsInitialized())
     UpdatedCSRs.clear();
 
   append_range(UpdatedCSRs, CSRs);
@@ -664,7 +663,7 @@ void MachineRegisterInfo::setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs) {
   // Zero value represents the end of the register list
   // (no more registers should be pushed).
   UpdatedCSRs.push_back(0);
-  IsUpdatedCSRsInitialized = true;
+  UpdatedCSRs.setFlag(1, true);
 }
 
 bool MachineRegisterInfo::isReservedRegUnit(MCRegUnit Unit) const {
diff --git a/llvm/lib/CodeGen/MachineScheduler.cpp b/llvm/lib/CodeGen/MachineScheduler.cpp
index a7f488e6e6d21..09403bd1e82d5 100644
--- a/llvm/lib/CodeGen/MachineScheduler.cpp
+++ b/llvm/lib/CodeGen/MachineScheduler.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/PriorityQueue.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -1603,7 +1604,7 @@ void ScheduleDAGMILive::collectVRegUses(SUnit &SU) {
       continue;
     if (!MO.readsReg())
       continue;
-    if (TrackLaneMasks && !MO.isUse())
+    if (getTrackLaneMasks() && !MO.isUse())
       continue;
 
     Register Reg = MO.getReg();
@@ -1611,7 +1612,7 @@ void ScheduleDAGMILive::collectVRegUses(SUnit &SU) {
       continue;
 
     // Ignore re-defs.
-    if (TrackLaneMasks) {
+    if (getTrackLaneMasks()) {
       bool FoundDef = false;
       for (const MachineOperand &MO2 : MI.all_defs()) {
         if (MO2.getReg() == Reg && !MO2.isDead()) {
@@ -2150,15 +2151,17 @@ namespace {
 class BaseMemOpClusterMutation : public ScheduleDAGMutation {
   struct MemOpInfo {
     SUnit *SU;
-    SmallVector<const MachineOperand *, 4> BaseOps;
+    llvm::SmallVectorWithFlags<const MachineOperand *, 4> BaseOps;
     int64_t Offset;
     LocationSize Width;
-    bool OffsetIsScalable;
+    bool getOffsetIsScalable() const { return BaseOps.getFlag(0); }
+    void setOffsetIsScalable(bool Value) { BaseOps.setFlag(0, Value); }
 
     MemOpInfo(SUnit *SU, ArrayRef<const MachineOperand *> BaseOps,
               int64_t Offset, bool OffsetIsScalable, LocationSize Width)
-        : SU(SU), BaseOps(BaseOps), Offset(Offset), Width(Width),
-          OffsetIsScalable(OffsetIsScalable) {}
+        : SU(SU), BaseOps(decltype(this->BaseOps)::withFlags(
+                      unsigned(OffsetIsScalable), BaseOps)),
+          Offset(Offset), Width(Width) {}
 
     static bool Compare(const MachineOperand *const &A,
                         const MachineOperand *const &B) {
@@ -2307,8 +2310,8 @@ void BaseMemOpClusterMutation::clusterNeighboringMemOps(
     }
 
     if (!TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpa.Offset,
-                                  MemOpa.OffsetIsScalable, MemOpb.BaseOps,
-                                  MemOpb.Offset, MemOpb.OffsetIsScalable,
+                                  MemOpa.getOffsetIsScalable(), MemOpb.BaseOps,
+                                  MemOpb.Offset, MemOpb.getOffsetIsScalable(),
                                   ClusterLength, CurrentClusterBytes))
       continue;
 
@@ -2688,7 +2691,7 @@ void SchedBoundary::reset() {
     HazardRec.reset();
   Available.clear();
   Pending.clear();
-  CheckPending = false;
+  setCheckPending(false);
   CurrCycle = 0;
   CurrMOps = 0;
   MinReadyCycle = std::numeric_limits<unsigned>::max();
@@ -2697,7 +2700,7 @@ void SchedBoundary::reset() {
   RetiredMOps = 0;
   MaxExecutedResCount = 0;
   ZoneCritResIdx = 0;
-  IsResourceLimited = false;
+  setIsResourceLimited(false);
   ReservedCycles.clear();
   ReservedResourceSegments.clear();
   ReservedCyclesIndex.clear();
@@ -3067,10 +3070,10 @@ void SchedBoundary::bumpCycle(unsigned NextCycle) {
         HazardRec->RecedeCycle();
     }
   }
-  CheckPending = true;
-  IsResourceLimited =
-      checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
-                         getScheduledLatency(), true);
+  setCheckPending(true);
+  setIsResourceLimited(checkResourceLimit(SchedModel->getLatencyFactor(),
+                                          getCriticalCount(),
+                                          getScheduledLatency(), true));
 
   LLVM_DEBUG(dbgs() << "Cycle: " << CurrCycle << ' ' << Available.getName()
                     << '\n');
@@ -3252,9 +3255,9 @@ void SchedBoundary::bumpNode(SUnit *SU) {
   else
     // After updating ZoneCritResIdx and ExpectedLatency, check if we're
     // resource limited. If a stall occurred, bumpCycle does this.
-    IsResourceLimited =
-        checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
-                           getScheduledLatency(), true);
+    setIsResourceLimited(checkResourceLimit(SchedModel->getLatencyFactor(),
+                                            getCriticalCount(),
+                                            getScheduledLatency(), true));
 
   // Update the reservation table.
   if (HazardRec->isEnabled()) {
@@ -3265,7 +3268,7 @@ void SchedBoundary::bumpNode(SUnit *SU) {
     }
     HazardRec->EmitInstruction(SU);
     // Scheduling an instruction may have made pending instructions available.
-    CheckPending = true;
+    setCheckPending(true);
   }
 
   // Update CurrMOps after calling bumpCycle to handle stalls, since bumpCycle
@@ -3320,7 +3323,7 @@ void SchedBoundary::releasePending() {
       --E;
     }
   }
-  CheckPending = false;
+  setCheckPending(false);
 }
 
 /// Remove SU from the ready set for this boundary.
@@ -3337,7 +3340,7 @@ void SchedBoundary::removeReady(SUnit *SU) {
 /// defer any nodes that now hit a hazard, and advance the cycle until at least
 /// one node is ready. If multiple instructions are ready, return NULL.
 SUnit *SchedBoundary::pickOnlyChoice() {
-  if (CheckPending)
+  if (getCheckPending())
     releasePending();
 
   // Defer any ready instrs that now have a hazard.
@@ -3415,7 +3418,7 @@ LLVM_DUMP_METHOD void SchedBoundary::dumpScheduledState() const {
          << ResCount / ResFactor << " "
          << SchedModel->getResourceName(ZoneCritResIdx)
          << "\n  ExpectedLatency: " << ExpectedLatency << "c\n"
-         << (IsResourceLimited ? "  - Resource" : "  - Latency")
+         << (getIsResourceLimited() ? "  - Resource" : "  - Latency")
          << " limited.\n";
   if (MISchedDumpReservedCycles)
     dumpReservedCycles();
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index fa7ac4d39c335..c584939c5f0de 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ADT/SetOperations.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/CodeGen/CodeGenCommonISel.h"
@@ -144,9 +145,16 @@ struct MachineVerifier {
   const RegisterBankInfo *RBI = nullptr;
 
   // Avoid querying the MachineFunctionProperties for each operand.
-  bool isFunctionRegBankSelected = false;
-  bool isFunctionSelected = false;
-  bool isFunctionTracksDebugUserValues = false;
+  bool getIsFunctionRegBankSelected() const { return regMasks.getFlag(0); }
+  void setIsFunctionRegBankSelected(bool Value) { regMasks.setFlag(0, Value); }
+  bool getIsFunctionSelected() const { return regMasks.getFlag(1); }
+  void setIsFunctionSelected(bool Value) { regMasks.setFlag(1, Value); }
+  bool getIsFunctionTracksDebugUserValues() const {
+    return regMasks.getFlag(2);
+  }
+  void setIsFunctionTracksDebugUserValues(bool Value) {
+    regMasks.setFlag(2, Value);
+  }
 
   using RegVector = SmallVector<Register, 16>;
   using RegMaskVector = SmallVector<const uint32_t *, 4>;
@@ -161,7 +169,7 @@ struct MachineVerifier {
   BitVector regsReserved;
   RegSet regsLive;
   RegVector regsDefined, regsDead, regsKilled;
-  RegMaskVector regMasks;
+  llvm::SmallVectorWithFlagsFor<RegMaskVector, 3> regMasks;
 
   SlotIndex lastIndex;
 
@@ -486,9 +494,9 @@ bool MachineVerifier::verify(const MachineFunction &MF) {
   if (isFunctionFailedISel)
     return true;
 
-  isFunctionRegBankSelected = Props.hasRegBankSelected();
-  isFunctionSelected = Props.hasSelected();
-  isFunctionTracksDebugUserValues = Props.hasTracksDebugUserValues();
+  setIsFunctionRegBankSelected(Props.hasRegBankSelected());
+  setIsFunctionSelected(Props.hasSelected());
+  setIsFunctionTracksDebugUserValues(Props.hasTracksDebugUserValues());
 
   if (PASS) {
     auto *LISWrapper = PASS->getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
@@ -1107,7 +1115,7 @@ bool MachineVerifier::verifyGIntrinsicConvergence(const MachineInstr *MI) {
 }
 
 void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
-  if (isFunctionSelected)
+  if (getIsFunctionSelected())
     report("Unexpected generic instruction in a Selected function", MI);
 
   const MCInstrDesc &MCID = MI->getDesc();
@@ -2783,10 +2791,10 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
         // pruning unused debug operands. The final undef substitution occurs
         // when debug values are allocated in LDVImpl::handleDebugValue, so
         // these verifications always apply after this pass.
-        if (isFunctionTracksDebugUserValues || !MO->isUse() ||
+        if (getIsFunctionTracksDebugUserValues() || !MO->isUse() ||
             !MI->isDebugValue() || !MRI->def_empty(Reg)) {
           // If we're post-Select, we can't have gvregs anymore.
-          if (isFunctionSelected) {
+          if (getIsFunctionSelected()) {
             report("Generic virtual register invalid in a Selected function",
                    MO, MONum);
             return;
@@ -2804,7 +2812,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
           const RegisterBankInfo *RBI = MF->getSubtarget().getRegBankInfo();
 
           // If we're post-RegBankSelect, the gvreg must have a bank.
-          if (!RegBank && isFunctionRegBankSelected) {
+          if (!RegBank && getIsFunctionRegBankSelected()) {
             report("Generic virtual register must have a bank in a "
                    "RegBankSelected function",
                    MO, MONum);
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 49fa0f89d616c..638c8921fd5e9 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -82,16 +83,26 @@ class PEIImpl {
   // Save and Restore blocks of the current function. Typically there is a
   // single save block, unless Windows EH funclets are involved.
   MBBVector SaveBlocks;
-  MBBVector RestoreBlocks;
+  llvm::SmallVectorWithFlagsFor<MBBVector, 2> RestoreBlocks;
 
   // Flag to control whether to use the register scavenger to resolve
   // frame index materialization registers. Set according to
   // TRI->requiresFrameIndexScavenging() for the current function.
-  bool FrameIndexVirtualScavenging = false;
+  bool getFrameIndexVirtualScavenging() const {
+    return RestoreBlocks.getFlag(0);
+  }
+  void setFrameIndexVirtualScavenging(bool Value) {
+    RestoreBlocks.setFlag(0, Value);
+  }
 
   // Flag to control whether the scavenger should be passed even though
   // FrameIndexVirtualScavenging is used.
-  bool FrameIndexEliminationScavenging = false;
+  bool getFrameIndexEliminationScavenging() const {
+    return RestoreBlocks.getFlag(1);
+  }
+  void setFrameIndexEliminationScavenging(bool Value) {
+    RestoreBlocks.setFlag(1, Value);
+  }
 
   // Emit remarks.
   MachineOptimizationRemarkEmitter *ORE = nullptr;
@@ -215,7 +226,7 @@ bool PEIImpl::run(MachineFunction &MF) {
   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
 
   RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr;
-  FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF);
+  setFrameIndexVirtualScavenging(TRI->requiresFrameIndexScavenging(MF));
 
   // Spill frame pointer and/or base pointer registers if they are clobbered.
   // It is placed before call frame instruction elimination so it will not mess
@@ -266,9 +277,9 @@ bool PEIImpl::run(MachineFunction &MF) {
   // and actual offsets.
   if (TFI->needsFrameIndexResolution(MF)) {
     // Allow the target to determine this after knowing the frame size.
-    FrameIndexEliminationScavenging =
-        (RS && !FrameIndexVirtualScavenging) ||
-        TRI->requiresFrameIndexReplacementScavenging(MF);
+    setFrameIndexEliminationScavenging(
+        (RS && !getFrameIndexVirtualScavenging()) ||
+        TRI->requiresFrameIndexReplacementScavenging(MF));
 
     if (TRI->eliminateFrameIndicesBackwards())
       replaceFrameIndicesBackward(MF);
@@ -279,7 +290,7 @@ bool PEIImpl::run(MachineFunction &MF) {
   // If register scavenging is needed, as we've enabled doing it as a
   // post-pass, scavenge the virtual registers that frame index elimination
   // inserted.
-  if (TRI->requiresRegisterScavenging(MF) && FrameIndexVirtualScavenging)
+  if (TRI->requiresRegisterScavenging(MF) && getFrameIndexVirtualScavenging())
     scavengeFrameVirtualRegs(MF, *RS);
 
   insertZeroCallUsedRegs(MF);
@@ -1490,7 +1501,7 @@ void PEIImpl::replaceFrameIndicesBackward(MachineBasicBlock *BB,
   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
   const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
 
-  RegScavenger *LocalRS = FrameIndexEliminationScavenging ? RS : nullptr;
+  RegScavenger *LocalRS = getFrameIndexEliminationScavenging() ? RS : nullptr;
   if (LocalRS)
     LocalRS->enterBasicBlockEnd(*BB);
 
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 50a4f15612082..c5ca23e8092c5 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseSet.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -187,7 +188,8 @@ class RegAllocFastImpl {
   RegAllocFastImpl(const RegAllocFilterFunc F = nullptr,
                    bool ClearVirtRegs_ = true)
       : ShouldAllocateRegisterImpl(F), StackSlotForVirtReg(-1),
-        ClearVirtRegs(ClearVirtRegs_) {}
+        RegMasks(decltype(this->RegMasks)::withFlags(
+            (unsigned(ClearVirtRegs_) << 1))) {}
 
 private:
   MachineFrameInfo *MFI = nullptr;
@@ -199,7 +201,8 @@ class RegAllocFastImpl {
 
   /// Tied operands reach this pass unrewritten (TwoAddressInstructionPass was
   /// left out of the pipeline): lower them here.
-  bool LowerTiedOps = false;
+  bool getLowerTiedOps() const { return RegMasks.getFlag(0); }
+  void setLowerTiedOps(bool Value) { RegMasks.setFlag(0, Value); }
 
   /// Basic block currently being allocated.
   MachineBasicBlock *MBB = nullptr;
@@ -284,7 +287,11 @@ class RegAllocFastImpl {
 
   SmallVector<unsigned, 8> DefOperandIndexes;
   // Register masks attached to the current instruction.
-  SmallVector<const uint32_t *> RegMasks;
+  llvm::SmallVectorWithFlags<
+      const uint32_t *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<const uint32_t *>::value,
+      2>
+      RegMasks;
 
   // Assign index for each instruction to quickly determine dominance.
   InstrPosIndexes PosIndexes;
@@ -351,7 +358,8 @@ class RegAllocFastImpl {
   };
 
 public:
-  bool ClearVirtRegs;
+  bool getClearVirtRegs() const { return RegMasks.getFlag(1); }
+  void setClearVirtRegs(bool Value) { RegMasks.setFlag(1, Value); }
 
   bool runOnMachineFunction(MachineFunction &MF);
 
@@ -451,7 +459,7 @@ class RegAllocFast : public MachineFunctionPass {
 
   MachineFunctionProperties getSetProperties() const override {
     MachineFunctionProperties P;
-    if (Impl.ClearVirtRegs)
+    if (Impl.getClearVirtRegs())
       P.setNoVRegs().setTiedOpsRewritten();
     return P;
   }
@@ -954,7 +962,7 @@ Register RegAllocFastImpl::traceCopyChain(Register Reg) const {
     }
     // A two-address instruction's def and tied use end up in the same
     // register, so the tie continues the chain.
-    Reg = LowerTiedOps ? getTiedUseReg(*Def, *DefMO) : Register();
+    Reg = getLowerTiedOps() ? getTiedUseReg(*Def, *DefMO) : Register();
     if (!Reg)
       return Register();
   }
@@ -972,7 +980,7 @@ Register RegAllocFastImpl::traceCopies(Register VirtReg) const {
     Register Reg;
     if (isCoalescable(MI))
       Reg = MI.getOperand(1).getReg();
-    else if (LowerTiedOps)
+    else if (getLowerTiedOps())
       Reg = getTiedUseReg(MI, DefMO);
     if (Reg) {
       Reg = traceCopyChain(Reg);
@@ -1327,7 +1335,7 @@ bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO,
     assert((!MO.isKill() || LRI->LastUse == &MI) && "Invalid kill flag");
   }
 
-  if (LowerTiedOps && MO.isTied() && lowerTiedUse(MI, MO, *LRI))
+  if (getLowerTiedOps() && MO.isTied() && lowerTiedUse(MI, MO, *LRI))
     return false;
 
   // If necessary allocate a register.
@@ -1657,7 +1665,7 @@ void RegAllocFastImpl::allocateInstruction(MachineInstr &MI) {
           HasVRegDef = true;
           if (MO.isEarlyClobber())
             HasEarlyClobber = true;
-          if (LowerTiedOps && MO.isTied())
+          if (getLowerTiedOps() && MO.isTied())
             HasTiedDef = true;
           if (isLiveThroughDef(MI, MO))
             NeedToAssignLiveThroughs = true;
@@ -2099,8 +2107,8 @@ bool RegAllocFastImpl::runOnMachineFunction(MachineFunction &MF) {
   // MIR that already went through TwoAddressInstructionPass carries
   // TiedOpsRewritten, so partial pipelines (-run-pass, -start-before) follow
   // the input they are given.
-  LowerTiedOps = !MF.getProperties().hasTiedOpsRewritten();
-  if (LowerTiedOps) {
+  setLowerTiedOps(!MF.getProperties().hasTiedOpsRewritten());
+  if (getLowerTiedOps()) {
     for (MachineBasicBlock &MBB : MF)
       for (MachineInstr &MI : make_early_inc_range(MBB))
         if (MI.isRegSequence() || MI.isInsertSubreg())
@@ -2119,7 +2127,7 @@ bool RegAllocFastImpl::runOnMachineFunction(MachineFunction &MF) {
   for (MachineBasicBlock &MBB : MF)
     allocateBasicBlock(MBB);
 
-  if (ClearVirtRegs) {
+  if (getClearVirtRegs()) {
     // All machine operands and other references to virtual registers have been
     // replaced. Remove the virtual registers.
     MRI->clearVirtRegs();
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index 685ee021dcab4..118c49bf6a1cd 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -3076,14 +3076,14 @@ bool RAGreedy::run(MachineFunction &mf) {
   initializeCSRCost();
 
   RegCosts = TRI->getRegisterCosts(*MF);
-  RegClassPriorityTrumpsGlobalness =
+  setRegClassPriorityTrumpsGlobalnessFlag(
       GreedyRegClassPriorityTrumpsGlobalness.getNumOccurrences()
           ? GreedyRegClassPriorityTrumpsGlobalness
-          : TRI->regClassPriorityTrumpsGlobalness(*MF);
+          : TRI->regClassPriorityTrumpsGlobalness(*MF));
 
-  ReverseLocalAssignment = GreedyReverseLocalAssignment.getNumOccurrences()
-                               ? GreedyReverseLocalAssignment
-                               : TRI->reverseLocalAssignment();
+  setReverseLocalAssignmentFlag(GreedyReverseLocalAssignment.getNumOccurrences()
+                                    ? GreedyReverseLocalAssignment
+                                    : TRI->reverseLocalAssignment());
 
   ExtraInfo.emplace();
 
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.h b/llvm/lib/CodeGen/RegAllocGreedy.h
index 56c9fd7f177a4..967e482477a81 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.h
+++ b/llvm/lib/CodeGen/RegAllocGreedy.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/IndexedMap.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/CalcSpillWeights.h"
 #include "llvm/CodeGen/LiveDebugVariables.h"
@@ -149,9 +150,9 @@ class LLVM_LIBRARY_VISIBILITY RAGreedy : public RegAllocBase,
 
   // Interface to priority advisers
   bool getRegClassPriorityTrumpsGlobalness() const {
-    return RegClassPriorityTrumpsGlobalness;
+    return GlobalCand.getFlag(0);
   }
-  bool getReverseLocalAssignment() const { return ReverseLocalAssignment; }
+  bool getReverseLocalAssignment() const { return GlobalCand.getFlag(1); }
   // end (interface to priority advisers)
 
 private:
@@ -261,7 +262,7 @@ class LLVM_LIBRARY_VISIBILITY RAGreedy : public RegAllocBase,
   /// Candidate info for each PhysReg in AllocationOrder.
   /// This vector never shrinks, but grows to the size of the largest register
   /// class.
-  SmallVector<GlobalSplitCandidate, 32> GlobalCand;
+  llvm::SmallVectorWithFlags<GlobalSplitCandidate, 32, 2> GlobalCand;
 
   enum : unsigned { NoCand = ~0u };
 
@@ -281,9 +282,13 @@ class LLVM_LIBRARY_VISIBILITY RAGreedy : public RegAllocBase,
 
   /// Flags for the live range priority calculation, determined once per
   /// machine function.
-  bool RegClassPriorityTrumpsGlobalness = false;
+  void setRegClassPriorityTrumpsGlobalnessFlag(bool Value) {
+    GlobalCand.setFlag(0, Value);
+  }
 
-  bool ReverseLocalAssignment = false;
+  void setReverseLocalAssignmentFlag(bool Value) {
+    GlobalCand.setFlag(1, Value);
+  }
 
 public:
   RAGreedy(RequiredAnalyses &Analyses, const RegAllocFilterFunc F = nullptr);
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 14d755ebb8ef6..4ada754e419c8 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/CalcSpillWeights.h"
 #include "llvm/CodeGen/LiveInterval.h"
@@ -2537,10 +2538,10 @@ class JoinVals {
 
   /// This is true when joining sub register ranges, false when joining main
   /// ranges.
-  const bool SubRangeJoin;
+  bool getSubRangeJoin() const { return Vals.getFlag(0); }
 
   /// Whether the current LiveInterval tracks subregister liveness.
-  const bool TrackSubRegLiveness;
+  bool getTrackSubRegLiveness() const { return Vals.getFlag(1); }
 
   /// Values that will be present in the final live range.
   SmallVectorImpl<VNInfo *> &NewVNInfo;
@@ -2646,7 +2647,7 @@ class JoinVals {
   };
 
   /// One entry per value number in LI.
-  SmallVector<Val, 8> Vals;
+  llvm::SmallVectorWithFlags<Val, 8, 2> Vals;
 
   /// Compute the bitmask of lanes actually written by DefMI.
   /// Set Redef if there are any partial register definitions that depend on the
@@ -2710,10 +2711,11 @@ class JoinVals {
            LiveIntervals *lis, const TargetRegisterInfo *TRI, bool SubRangeJoin,
            bool TrackSubRegLiveness)
       : LR(LR), Reg(Reg), SubIdx(SubIdx), LaneMask(LaneMask),
-        SubRangeJoin(SubRangeJoin), TrackSubRegLiveness(TrackSubRegLiveness),
         NewVNInfo(newVNInfo), CP(cp), LIS(lis), Indexes(LIS->getSlotIndexes()),
         TRI(TRI), Assignments(LR.getNumValNums(), -1),
-        Vals(LR.getNumValNums()) {}
+        Vals(decltype(this->Vals)::withFlags(
+            unsigned(SubRangeJoin) | (unsigned(TrackSubRegLiveness) << 1),
+            LR.getNumValNums())) {}
 
   /// Analyze defs in LR and compute a value mapping in NewVNInfo.
   /// Returns false if any conflicts were impossible to resolve.
@@ -2798,7 +2800,7 @@ JoinVals::followCopyChain(const VNInfo *VNI) const {
     const LiveInterval &LI = LIS->getInterval(SrcReg);
     const VNInfo *ValueIn;
     // No subrange involved.
-    if (!SubRangeJoin || !LI.hasSubRanges()) {
+    if (!getSubRangeJoin() || !LI.hasSubRanges()) {
       LiveQueryResult LRQ = LI.Query(Def);
       ValueIn = LRQ.valueIn();
     } else {
@@ -2872,13 +2874,13 @@ JoinVals::ConflictResolution JoinVals::analyzeValue(unsigned ValNo,
   const MachineInstr *DefMI = nullptr;
   if (VNI->isPHIDef()) {
     // Conservatively assume that all lanes in a PHI are valid.
-    LaneBitmask Lanes = SubRangeJoin ? LaneBitmask::getLane(0)
-                                     : TRI->getSubRegIndexLaneMask(SubIdx);
+    LaneBitmask Lanes = getSubRangeJoin() ? LaneBitmask::getLane(0)
+                                          : TRI->getSubRegIndexLaneMask(SubIdx);
     V.ValidLanes = V.WriteLanes = Lanes;
   } else {
     DefMI = Indexes->getInstructionFromIndex(VNI->def);
     assert(DefMI != nullptr);
-    if (SubRangeJoin) {
+    if (getSubRangeJoin()) {
       // We don't care about the lanes when joining subregister ranges.
       V.WriteLanes = V.ValidLanes = LaneBitmask::getLane(0);
       if (DefMI->isImplicitDef()) {
@@ -2906,7 +2908,7 @@ JoinVals::ConflictResolution JoinVals::analyzeValue(unsigned ValNo,
       // not important.
       if (Redef) {
         V.RedefVNI = LR.Query(VNI->def).valueIn();
-        assert((TrackSubRegLiveness || V.RedefVNI) &&
+        assert((getTrackSubRegLiveness() || V.RedefVNI) &&
                "Instruction is reading nonexistent value");
         if (V.RedefVNI != nullptr) {
           computeAssignment(V.RedefVNI->id, Other);
@@ -3052,7 +3054,7 @@ JoinVals::ConflictResolution JoinVals::analyzeValue(unsigned ValNo,
   // The remaining checks apply to the lanes, which aren't tracked here.  This
   // was already decided to be OK via the following CR_Replace condition.
   // CR_Replace.
-  if (SubRangeJoin)
+  if (getSubRangeJoin())
     return CR_Replace;
 
   // If the lanes written by this instruction were all undef in OtherVNI, it is
@@ -3091,7 +3093,7 @@ JoinVals::ConflictResolution JoinVals::analyzeValue(unsigned ValNo,
   if ((TRI->getSubRegIndexLaneMask(Other.SubIdx) & ~V.WriteLanes).none())
     return CR_Impossible;
 
-  if (TrackSubRegLiveness) {
+  if (getTrackSubRegLiveness()) {
     auto &OtherLI = LIS->getInterval(Other.Reg);
     // If OtherVNI does not have subranges, it means all the lanes of OtherVNI
     // share the same live range, so we just need to check whether they have
@@ -3252,7 +3254,7 @@ bool JoinVals::resolveConflicts(JoinVals &Other) {
     LLVM_DEBUG(dbgs() << "\t\tconflict at " << printReg(Reg) << ':' << i << '@'
                       << LR.getValNumInfo(i)->def << ' '
                       << PrintLaneMask(LaneMask) << '\n');
-    if (SubRangeJoin)
+    if (getSubRangeJoin())
       return false;
 
     ++NumLaneConflicts;
diff --git a/llvm/lib/CodeGen/Rematerializer.cpp b/llvm/lib/CodeGen/Rematerializer.cpp
index 5d85098400f0d..9ec83b130548d 100644
--- a/llvm/lib/CodeGen/Rematerializer.cpp
+++ b/llvm/lib/CodeGen/Rematerializer.cpp
@@ -1119,7 +1119,7 @@ Printable Rematerializer::printUser(const MachineInstr *MI,
 
 void Rollbacker::rematerializerNoteRegCreated(const Rematerializer &Remater,
                                               RegisterIdx RegIdx) {
-  if (RollingBack)
+  if (getRollingBack())
     return;
   assert(Remater.isRematerializedRegister(RegIdx) && "only remats are created");
   Rematerializations[Remater.getOriginOf(RegIdx)].insert(RegIdx);
@@ -1127,7 +1127,7 @@ void Rollbacker::rematerializerNoteRegCreated(const Rematerializer &Remater,
 
 void Rollbacker::rematerializerNoteRegWillBeDeleted(
     const Rematerializer &Remater, RegisterIdx RegIdx) {
-  if (RollingBack)
+  if (getRollingBack())
     return;
 
   const Rematerializer::Reg &Reg = Remater.getReg(RegIdx);
@@ -1183,7 +1183,7 @@ void Rollbacker::rematerializerNoteRegWillBeDeleted(
 
 void Rollbacker::rematerializerNoteMIWillBeDeleted(
     const Rematerializer &Remater, MachineInstr &MI) {
-  if (RollingBack)
+  if (getRollingBack())
     return;
 
   // Previously deleted registers that reference this MI as their re-creation
@@ -1196,7 +1196,7 @@ void Rollbacker::rematerializerNoteMIWillBeDeleted(
 }
 
 void Rollbacker::rollback(Rematerializer &Remater) {
-  RollingBack = true;
+  setRollingBack(true);
 
   // As we re-create registers, map deleted definitions to re-created ones. This
   // allows to replace invalid re-creation positions that reference deleted
@@ -1256,7 +1256,7 @@ void Rollbacker::rollback(Rematerializer &Remater) {
   Positions.clear();
   PosToIdx.clear();
   Rematerializations.clear();
-  RollingBack = false;
+  setRollingBack(false);
 }
 
 bool Rollbacker::isRollbackableMI(const MachineInstr &MI,
diff --git a/llvm/lib/CodeGen/ScheduleDAG.cpp b/llvm/lib/CodeGen/ScheduleDAG.cpp
index 4348153356d2c..1487c7c24b9b7 100644
--- a/llvm/lib/CodeGen/ScheduleDAG.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAG.cpp
@@ -473,7 +473,7 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
   // immediately after X in Index2Node.
 
   // Cancel pending updates, mark as valid.
-  Dirty = false;
+  setDirty(false);
   Updates.clear();
   Reachable.clear();
 
@@ -533,7 +533,7 @@ void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
 
 void ScheduleDAGTopologicalSort::FixOrder() {
   // Recompute from scratch after new nodes have been added.
-  if (Dirty) {
+  if (getDirty()) {
     InitDAGTopologicalSorting();
     return;
   }
@@ -548,9 +548,9 @@ void ScheduleDAGTopologicalSort::AddPredQueued(SUnit *Y, SUnit *X) {
   // Recomputing the order from scratch is likely more efficient than applying
   // updates one-by-one for too many updates. The current cut-off is arbitrarily
   // chosen.
-  Dirty = Dirty || Updates.size() > 10;
+  setDirty(getDirty() || Updates.size() > 10);
 
-  if (Dirty)
+  if (getDirty())
     return;
 
   Updates.emplace_back(Y, X);
diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
index e5bc867cc75d4..9916bc92ccf7a 100644
--- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -107,7 +107,8 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf,
                                      const MachineLoopInfo *mli,
                                      bool RemoveKillFlags)
     : ScheduleDAG(mf), MLI(mli), MFI(mf.getFrameInfo()),
-      RemoveKillFlags(RemoveKillFlags), Topo(SUnits, &ExitSU) {
+      Clusters(decltype(this->Clusters)::withFlags(unsigned(RemoveKillFlags))),
+      Topo(SUnits, &ExitSU) {
   DbgValues.clear();
 
   const TargetSubtargetInfo &ST = mf.getSubtarget();
@@ -336,7 +337,7 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
     // Push this SUnit on the use list.
     for (MCRegUnit Unit : TRI->regunits(Reg))
       Uses.insert(PhysRegSUOper(SU, OperIdx, Unit));
-    if (RemoveKillFlags)
+    if (getRemoveKillFlags())
       MO.setIsKill(false);
   } else {
     addPhysRegDataDeps(SU, OperIdx);
@@ -407,7 +408,7 @@ void ScheduleDAGInstrs::addVRegDefDeps(SUnit *SU, unsigned OperIdx) {
 
   LaneBitmask DefLaneMask;
   LaneBitmask KillLaneMask;
-  if (TrackLaneMasks) {
+  if (getTrackLaneMasks()) {
     bool IsKill = MO.getSubReg() == 0 || MO.isUndef();
     DefLaneMask = getLaneMaskForMO(MO);
     // If we have a <read-undef> flag, none of the lane values comes from an
@@ -528,8 +529,8 @@ void ScheduleDAGInstrs::addVRegUseDeps(SUnit *SU, unsigned OperIdx) {
   Register Reg = MO.getReg();
 
   // Remember the use. Data dependencies will be added when we find the def.
-  LaneBitmask LaneMask = TrackLaneMasks ? getLaneMaskForMO(MO)
-                                        : LaneBitmask::getAll();
+  LaneBitmask LaneMask =
+      getTrackLaneMasks() ? getLaneMaskForMO(MO) : LaneBitmask::getAll();
   CurrentVRegUses.insert(VReg2SUnitOperIdx(Reg, LaneMask, OperIdx, SU));
 
   // Add antidependences to the following defs of the vreg.
@@ -926,8 +927,8 @@ void ScheduleDAGDependencyBuilder::buildDeps() {
 
     if (RPTracker) {
       RegisterOperands RegOpers;
-      RegOpers.collect(MI, *DAG.TRI, DAG.MRI, DAG.TrackLaneMasks, false);
-      if (DAG.TrackLaneMasks) {
+      RegOpers.collect(MI, *DAG.TRI, DAG.MRI, DAG.getTrackLaneMasks(), false);
+      if (DAG.getTrackLaneMasks()) {
         SlotIndex SlotIdx = LIS->getInstructionIndex(MI);
         RegOpers.adjustLaneLiveness(*LIS, DAG.MRI, SlotIdx);
       } else if (LIS) {
@@ -944,7 +945,7 @@ void ScheduleDAGDependencyBuilder::buildDeps() {
       RPTracker->recede(RegOpers);
     }
 
-    assert((DAG.CanHandleTerminators ||
+    assert((DAG.getCanHandleTerminators() ||
             (!MI.isTerminator() && !MI.isPosition())) &&
            "Cannot schedule terminators or labels!");
 
@@ -1118,7 +1119,7 @@ void ScheduleDAGInstrs::buildSchedGraph(AAResults *AA,
   const TargetSubtargetInfo &ST = MF.getSubtarget();
   bool UseAA =
       EnableAASchedMI.getNumOccurrences() > 0 ? EnableAASchedMI : ST.useAA();
-  this->TrackLaneMasks = TrackLaneMasks;
+  this->setTrackLaneMasks(TrackLaneMasks);
   MISUnitMap.clear();
   ScheduleDAG::clearDAG();
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 5ea69ea78d434..d04667ea39026 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -138,7 +139,8 @@ namespace {
 class ScheduleDAGRRList : public ScheduleDAGSDNodes {
 private:
   /// NeedLatency - True if the scheduler will make use of latency information.
-  bool NeedLatency;
+  bool getNeedLatency() const { return Interferences.getFlag(0); }
+  void setNeedLatency(bool Value) { Interferences.setFlag(0, Value); }
 
   /// AvailableQueue - The priority queue to use for the available SUnits.
   SchedulingPriorityQueue *AvailableQueue;
@@ -171,7 +173,7 @@ class ScheduleDAGRRList : public ScheduleDAGSDNodes {
 
   // Collect interferences between physical register use/defs.
   // Each interference is an SUnit and set of physical registers.
-  SmallVector<SUnit*, 4> Interferences;
+  llvm::SmallVectorWithFlags<SUnit *, 4> Interferences;
 
   using LRegsMapT = DenseMap<SUnit *, SmallVector<unsigned, 4>>;
 
@@ -189,10 +191,12 @@ class ScheduleDAGRRList : public ScheduleDAGSDNodes {
   ScheduleDAGRRList(MachineFunction &mf, bool needlatency,
                     SchedulingPriorityQueue *availqueue,
                     CodeGenOptLevel OptLevel)
-      : ScheduleDAGSDNodes(mf), NeedLatency(needlatency),
-        AvailableQueue(availqueue), Topo(SUnits, nullptr) {
+      : ScheduleDAGSDNodes(mf), AvailableQueue(availqueue),
+        Interferences(
+            decltype(this->Interferences)::withFlags(unsigned(needlatency))),
+        Topo(SUnits, nullptr) {
     const TargetSubtargetInfo &STI = mf.getSubtarget();
-    if (DisableSchedCycles || !NeedLatency)
+    if (DisableSchedCycles || !getNeedLatency())
       HazardRec = new ScheduleHazardRecognizer();
     else
       HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this);
@@ -286,9 +290,7 @@ class ScheduleDAGRRList : public ScheduleDAGSDNodes {
 
   /// forceUnitLatencies - Register-pressure-reducing scheduling doesn't
   /// need actual latency information but the hybrid scheduler does.
-  bool forceUnitLatencies() const override {
-    return !NeedLatency;
-  }
+  bool forceUnitLatencies() const override { return !getNeedLatency(); }
 };
 
 }  // end anonymous namespace
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 2d5a55a799c02..d24ffe821c9c4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -15253,15 +15253,7 @@ void SelectionDAG::createOperands(SDNode *Node, ArrayRef<SDValue> Vals) {
 
 SDValue SelectionDAG::getTokenFactor(const SDLoc &DL,
                                      SmallVectorImpl<SDValue> &Vals) {
-  size_t Limit = SDNode::getMaxNumOperands();
-  while (Vals.size() > Limit) {
-    unsigned SliceIdx = Vals.size() - Limit;
-    auto ExtractedTFs = ArrayRef<SDValue>(Vals).slice(SliceIdx, Limit);
-    SDValue NewTF = getNode(ISD::TokenFactor, DL, MVT::Other, ExtractedTFs);
-    Vals.erase(Vals.begin() + SliceIdx, Vals.end());
-    Vals.emplace_back(NewTF);
-  }
-  return getNode(ISD::TokenFactor, DL, MVT::Other, Vals);
+  return getTokenFactorImpl(DL, Vals);
 }
 
 SDValue SelectionDAG::getIdentityElement(unsigned Opcode, const SDLoc &DL,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index b595de3734bb9..a753a320100cb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -1111,10 +1112,10 @@ void SelectionDAGBuilder::init(GCFunctionInfo *gfi, BatchAAResults *aa,
   LPadToCallSiteMap.clear();
   this->TTI = &TTI;
   SL->init(DAG.getTargetLoweringInfo(), TM, DAG.getDataLayout());
-  AssignmentTrackingEnabled = isAssignmentTrackingEnabled(
-      *DAG.getMachineFunction().getFunction().getParent());
-  CanDescribeGlobalAddressInLocationList =
-      canDescribeGlobalAddressInLocationList(DAG.getMachineFunction());
+  setAssignmentTrackingEnabled(isAssignmentTrackingEnabled(
+      *DAG.getMachineFunction().getFunction().getParent()));
+  setCanDescribeGlobalAddressInLocationList(
+      canDescribeGlobalAddressInLocationList(DAG.getMachineFunction()));
 }
 
 void SelectionDAGBuilder::clear() {
@@ -1125,7 +1126,7 @@ void SelectionDAGBuilder::clear() {
   PendingConstrainedFP.clear();
   PendingConstrainedFPStrict.clear();
   CurInst = nullptr;
-  HasTailCall = false;
+  setHasTailCall(false);
   SDNodeOrder = LowestSDNodeOrder;
   StatepointLowering.clear();
 }
@@ -1135,7 +1136,8 @@ void SelectionDAGBuilder::clearDanglingDebugInfo() {
 }
 
 // Update DAG root to include dependencies on Pending chains.
-SDValue SelectionDAGBuilder::updateRoot(SmallVectorImpl<SDValue> &Pending) {
+template <typename PendingT>
+SDValue SelectionDAGBuilder::updateRoot(PendingT &Pending) {
   SDValue Root = DAG.getRoot();
 
   if (Pending.empty())
@@ -1395,7 +1397,7 @@ void SelectionDAGBuilder::visit(const Instruction &I) {
 
   visit(I.getOpcode(), I);
 
-  if (!I.isTerminator() && !HasTailCall &&
+  if (!I.isTerminator() && !getHasTailCall() &&
       !isa<GCStatepointInst>(I)) // statepoints handle their exports internally
     CopyToExportRegsIfNeeded(&I);
 
@@ -1702,7 +1704,7 @@ bool SelectionDAGBuilder::handleDebugValue(ArrayRef<const Value *> Values,
     // way falls through to be described by whatever materializes it instead.
     // So does one that a location list could not name, should the variable
     // need one; salvageUnresolvedDbgValue names it if nothing materializes it.
-    if (CanDescribeGlobalAddressInLocationList)
+    if (getCanDescribeGlobalAddressInLocationList())
       if (const GlobalValue *GV = getGlobalAddressDbgOperand(
               V, Expr, OpIdx, DAG.getMachineFunction())) {
         LocationOps.emplace_back(SDDbgOperand::fromGlobalAddr(GV));
@@ -3410,13 +3412,13 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B,
 
   MachineBasicBlock* MBB = B.Cases[0].ThisBB;
 
-  if (!B.FallthroughUnreachable)
+  if (!B.getFallthroughUnreachable())
     addSuccessorWithProb(SwitchBB, B.Default, B.DefaultProb);
   addSuccessorWithProb(SwitchBB, MBB, B.Prob);
   SwitchBB->normalizeSuccProbs();
 
   SDValue Root = CopyTo;
-  if (!B.FallthroughUnreachable) {
+  if (!B.getFallthroughUnreachable()) {
     // Conditional branch to the default block.
     SDValue RangeCmp = DAG.getSetCC(dl,
         TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
@@ -8050,7 +8052,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
         DAG.getExternalSymbol(TrapFuncName.data(),
                               TLI.getPointerTy(DAG.getDataLayout())),
         std::move(Args));
-    CLI.NoMerge = I.hasFnAttr(Attribute::NoMerge);
+    CLI.setNoMerge(I.hasFnAttr(Attribute::NoMerge));
     std::pair<SDValue, SDValue> Result = TLI.LowerCallTo(CLI);
     DAG.setRoot(Result.second);
     return;
@@ -8454,7 +8456,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
               0);
     DAG.setRoot(N);
     setValue(&I, N);
-    HasTailCall = true;
+    setHasTailCall(true);
     return;
   }
 
@@ -8524,7 +8526,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
     assert(!Result.first.getNode() && !Result.second.getNode() &&
            "Should've lowered as tail call");
 
-    HasTailCall = true;
+    setHasTailCall(true);
     return;
   }
   case Intrinsic::amdgcn_call_whole_wave: {
@@ -9360,7 +9362,7 @@ SelectionDAGBuilder::lowerInvokable(TargetLowering::CallLoweringInfo &CLI,
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
   std::pair<SDValue, SDValue> Result = TLI.LowerCallTo(CLI);
 
-  assert((CLI.IsTailCall || Result.second.getNode()) &&
+  assert((CLI.getIsTailCall() || Result.second.getNode()) &&
          "Non-null chain expected with non-tail call!");
   assert((Result.second.getNode() || !Result.first.getNode()) &&
          "Null value expected with tail call!");
@@ -9368,7 +9370,7 @@ SelectionDAGBuilder::lowerInvokable(TargetLowering::CallLoweringInfo &CLI,
   if (!Result.second.getNode()) {
     // As a special case, a null chain means that a tail call has been emitted
     // and the DAG root is already updated.
-    HasTailCall = true;
+    setHasTailCall(true);
 
     // Since there's no actual continuation from this block, nothing can be
     // relying on us setting vregs for them.
@@ -10453,10 +10455,14 @@ static bool isFunction(SDValue Op) {
 namespace {
 
 struct ConstraintDecisionInfo {
-  SmallVector<SDISelAsmOperandInfo, 16> ConstraintOperands;
+  llvm::SmallVectorWithFlags<SDISelAsmOperandInfo, 16> ConstraintOperands;
   std::vector<SDValue> AsmNodeOperands;
   SDValue Glue, Chain;
-  bool HasSideEffect = false;
+  bool getHasSideEffect() const { return ConstraintOperands.getFlag(0); }
+  bool setHasSideEffect(bool Value) {
+    ConstraintOperands.setFlag(0, Value);
+    return Value;
+  }
   MCSymbol *BeginLabel = nullptr;
 
   SmallVector<char> Buffer;
@@ -10480,8 +10486,8 @@ constructOperandInfo(ConstraintDecisionInfo &Info,
     if (OpInfo.CallOperandVal)
       OpInfo.CallOperand = Builder.getValue(OpInfo.CallOperandVal);
 
-    if (!Info.HasSideEffect)
-      Info.HasSideEffect = OpInfo.hasMemory(TLI);
+    if (!Info.getHasSideEffect())
+      Info.setHasSideEffect(OpInfo.hasMemory(TLI));
 
     // Determine if this InlineAsm MayLoad or MayStore based on the constraints.
     // FIXME: Could we compute this on OpInfo rather than T?
@@ -10855,13 +10861,13 @@ determineConstraints(ConstraintDecisionInfo &Info,
   ExtraFlags ExtraInfo(Call);
 
   // First pass: Construct operand info objects.
-  Info.HasSideEffect = IA->hasSideEffects();
+  Info.setHasSideEffect(IA->hasSideEffects());
   if (constructOperandInfo(Info, TargetConstraints, Builder, TLI, ExtraInfo))
     return true;
 
   // We won't need to flush pending loads if this asm doesn't touch
   // memory and is nonvolatile.
-  Info.Chain = Info.HasSideEffect ? Builder.getRoot() : DAG.getRoot();
+  Info.Chain = Info.getHasSideEffect() ? Builder.getRoot() : DAG.getRoot();
 
   bool IsCallBr = isa<CallBrInst>(Call);
   bool EmitEHLabels = isa<InvokeInst>(Call);
@@ -11038,7 +11044,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
     Chain = lowerEndEH(Chain, II, EHPadBB, Info.BeginLabel);
 
   // Only Update Root if inline assembly has a memory effect.
-  if (ResultValues.empty() || Info.HasSideEffect || !OutChains.empty() ||
+  if (ResultValues.empty() || Info.getHasSideEffect() || !OutChains.empty() ||
       IsCallBr || isa<InvokeInst>(Call))
     DAG.setRoot(Chain);
 }
@@ -11526,11 +11532,11 @@ void SelectionDAGBuilder::visitVectorReduce(const CallInst &I,
 /// value of the given call.
 static AttributeList getReturnAttrs(TargetLowering::CallLoweringInfo &CLI) {
   SmallVector<Attribute::AttrKind, 2> Attrs;
-  if (CLI.RetSExt)
+  if (CLI.getRetSExt())
     Attrs.push_back(Attribute::SExt);
-  if (CLI.RetZExt)
+  if (CLI.getRetZExt())
     Attrs.push_back(Attribute::ZExt);
-  if (CLI.IsInReg)
+  if (CLI.getIsInReg())
     Attrs.push_back(Attribute::InReg);
 
   return AttributeList::get(CLI.RetTy->getContext(), AttributeList::ReturnIndex,
@@ -11562,7 +11568,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
       RetVTs.push_back(getValueType(DL, Ty));
   }
 
-  if (CLI.IsPostTypeLegalization) {
+  if (CLI.getIsPostTypeLegalizationFlag()) {
     // If we are lowering a libcall after legalization, split the return type.
     SmallVector<Type *, 4> OldRetOrigTys;
     SmallVector<EVT, 4> OldRetVTs;
@@ -11589,7 +11595,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
 
   bool CanLowerReturn =
       this->CanLowerReturn(CLI.CallConv, CLI.DAG.getMachineFunction(),
-                           CLI.IsVarArg, Outs, Context, CLI.RetTy);
+                           CLI.getIsVarArg(), Outs, Context, CLI.RetTy);
 
   SDValue DemoteStackSlot;
   int DemoteStackIdx = -100;
@@ -11615,10 +11621,10 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
 
     // sret demotion isn't compatible with tail-calls, since the sret argument
     // points into the callers stack frame.
-    CLI.IsTailCall = false;
+    CLI.setIsTailCall(false);
   } else {
     bool NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters(
-        CLI.RetTy, CLI.CallConv, CLI.IsVarArg, DL);
+        CLI.RetTy, CLI.CallConv, CLI.getIsVarArg(), DL);
     for (unsigned I = 0, E = RetVTs.size(); I != E; ++I) {
       ISD::ArgFlagsTy Flags;
       if (NeedsRegBlock) {
@@ -11632,17 +11638,18 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
           getNumRegistersForCallingConv(Context, CLI.CallConv, VT);
       for (unsigned i = 0; i != NumRegs; ++i) {
         ISD::InputArg Ret(Flags, RegisterVT, VT, RetOrigTys[I],
-                          CLI.IsReturnValueUsed, ISD::InputArg::NoArgIndex, 0);
+                          CLI.getIsReturnValueUsed(), ISD::InputArg::NoArgIndex,
+                          0);
         if (CLI.RetTy->isPointerTy()) {
           Ret.Flags.setPointer();
           Ret.Flags.setPointerAddrSpace(
               cast<PointerType>(CLI.RetTy)->getAddressSpace());
         }
-        if (CLI.RetSExt)
+        if (CLI.getRetSExt())
           Ret.Flags.setSExt();
-        if (CLI.RetZExt)
+        if (CLI.getRetZExt())
           Ret.Flags.setZExt();
-        if (CLI.IsInReg)
+        if (CLI.getIsInReg())
           Ret.Flags.setInReg();
         CLI.Ins.push_back(Ret);
       }
@@ -11675,7 +11682,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
     if (Args[i].IsByVal)
       FinalType = Args[i].IndirectType;
     bool NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters(
-        FinalType, CLI.CallConv, CLI.IsVarArg, DL);
+        FinalType, CLI.CallConv, CLI.getIsVarArg(), DL);
     for (unsigned Value = 0, NumValues = OrigArgTys.size(); Value != NumValues;
          ++Value) {
       Type *OrigArgTy = OrigArgTys[Value];
@@ -11805,8 +11812,9 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
         // parameter extension method is not compatible with the return
         // extension method
         if ((NumParts * PartVT.getSizeInBits() == VT.getSizeInBits()) ||
-            (ExtendKind != ISD::ANY_EXTEND && CLI.RetSExt == Args[i].IsSExt &&
-             CLI.RetZExt == Args[i].IsZExt))
+            (ExtendKind != ISD::ANY_EXTEND &&
+             CLI.getRetSExt() == Args[i].IsSExt &&
+             CLI.getRetZExt() == Args[i].IsZExt))
           Flags.setReturned();
       }
 
@@ -11841,21 +11849,22 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
   CLI.Chain = LowerCall(CLI, InVals);
 
   // Update CLI.InVals to use outside of this function.
-  CLI.InVals = InVals;
+  if (CLI.InVals.data() != InVals.data())
+    CLI.InVals.assign(InVals.begin(), InVals.end());
 
   // Verify that the target's LowerCall behaved as expected.
   assert(CLI.Chain.getNode() && CLI.Chain.getValueType() == MVT::Other &&
          "LowerCall didn't return a valid chain!");
-  assert((!CLI.IsTailCall || InVals.empty()) &&
+  assert((!CLI.getIsTailCall() || InVals.empty()) &&
          "LowerCall emitted a return value for a tail call!");
-  assert((CLI.IsTailCall || InVals.size() == CLI.Ins.size()) &&
+  assert((CLI.getIsTailCall() || InVals.size() == CLI.Ins.size()) &&
          "LowerCall didn't emit the correct number of values!");
 
   // For a tail call, the return value is merely live-out and there aren't
   // any nodes in the DAG representing it. Return a special value to
   // indicate that a tail call has been emitted and no more Instructions
   // should be processed in the current block.
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     CLI.DAG.setRoot(CLI.Chain);
     return std::make_pair(SDValue(), SDValue());
   }
@@ -11900,9 +11909,9 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
     // Collect the legal value parts into potentially illegal values
     // that correspond to the original function's return values.
     std::optional<ISD::NodeType> AssertOp;
-    if (CLI.RetSExt)
+    if (CLI.getRetSExt())
       AssertOp = ISD::AssertSext;
-    else if (CLI.RetZExt)
+    else if (CLI.getRetZExt())
       AssertOp = ISD::AssertZext;
     unsigned CurReg = 0;
     for (EVT VT : RetVTs) {
@@ -12642,7 +12651,7 @@ void SelectionDAGBuilder::updateDAGForMaybeTailCall(SDValue MaybeTC) {
   if (MaybeTC.getNode() != nullptr)
     DAG.setRoot(MaybeTC);
   else
-    HasTailCall = true;
+    setHasTailCall(true);
 }
 
 void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
@@ -12839,18 +12848,18 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
         // If the cases in bit test don't form a contiguous range, we evenly
         // distribute the probability on the edge to Fallthrough to two
         // successors of CurMBB.
-        if (!BTB->ContiguousRange) {
+        if (!BTB->getContiguousRange()) {
           BTB->Prob += DefaultProb / 2;
           BTB->DefaultProb -= DefaultProb / 2;
         }
 
         if (FallthroughUnreachable)
-          BTB->FallthroughUnreachable = true;
+          BTB->setFallthroughUnreachable(true);
 
         // If we're in the right place, emit the bit test header right now.
         if (CurMBB == SwitchMBB) {
           visitBitTestHeader(*BTB, SwitchMBB);
-          BTB->Emitted = true;
+          BTB->setEmitted(true);
         }
         break;
       }
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index c9bb96b86b7bd..1b7a4bbae9b0a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AssignmentTrackingAnalysis.h"
 #include "llvm/CodeGen/CodeGenCommonISel.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
@@ -162,11 +163,21 @@ class SelectionDAGBuilder {
 
   /// Cache the module flag for whether we should use debug-info assignment
   /// tracking.
-  bool AssignmentTrackingEnabled = false;
+  bool getAssignmentTrackingEnabled() const {
+    return PendingConstrainedFPStrict.getFlag(0);
+  }
+  void setAssignmentTrackingEnabled(bool Value) {
+    PendingConstrainedFPStrict.setFlag(0, Value);
+  }
 
   /// Cache whether a debug value can name the address of a global directly,
   /// rather than holding out for a register with it.
-  bool CanDescribeGlobalAddressInLocationList = false;
+  bool getCanDescribeGlobalAddressInLocationList() const {
+    return PendingConstrainedFPStrict.getFlag(1);
+  }
+  void setCanDescribeGlobalAddressInLocationList(bool Value) {
+    PendingConstrainedFPStrict.setFlag(1, Value);
+  }
 
 public:
   /// Loads are not emitted to the program immediately.  We bunch them up and
@@ -194,10 +205,10 @@ class SelectionDAGBuilder {
   /// terminator instruction (like PendingExports).  We track the latter
   /// set of nodes in a separate list.
   SmallVector<SDValue, 8> PendingConstrainedFP;
-  SmallVector<SDValue, 8> PendingConstrainedFPStrict;
+  llvm::SmallVectorWithFlags<SDValue, 8, 3> PendingConstrainedFPStrict;
 
   /// Update root to include all chains from the Pending list.
-  SDValue updateRoot(SmallVectorImpl<SDValue> &Pending);
+  template <typename PendingT> SDValue updateRoot(PendingT &Pending);
 
   /// Given a node representing a floating-point operation and its specified
   /// exception behavior, this either updates the root or stores the node in
@@ -279,7 +290,11 @@ class SelectionDAGBuilder {
 
   /// This is set to true if a call in the current block has been translated as
   /// a tail call. In this case, no subsequent DAG nodes should be created.
-  bool HasTailCall = false;
+  bool getHasTailCall() const { return PendingConstrainedFPStrict.getFlag(2); }
+  bool setHasTailCall(bool Value) {
+    PendingConstrainedFPStrict.setFlag(2, Value);
+    return Value;
+  }
 
   LLVMContext *Context = nullptr;
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 84958ac50ab4f..e8376a0c33556 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -885,7 +886,8 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,
   // Lower the instructions. If a call is emitted as a tail call, cease emitting
   // nodes for this block. If an instruction is elided, don't emit it, but do
   // handle any debug-info attached to it.
-  for (BasicBlock::const_iterator I = Begin; I != End && !SDB->HasTailCall; ++I) {
+  for (BasicBlock::const_iterator I = Begin; I != End && !SDB->getHasTailCall();
+       ++I) {
     if (!ElidedArgCopyInstrs.count(&*I))
       SDB->visit(*I);
     else
@@ -894,7 +896,7 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,
 
   // Make sure the root of the DAG is up-to-date.
   CurDAG->setRoot(SDB->getControlRoot());
-  HadTailCall = SDB->HasTailCall;
+  HadTailCall = SDB->getHasTailCall();
   SDB->resolveOrClearDbgInfo();
   SDB->clear();
 
@@ -2048,7 +2050,7 @@ SelectionDAGISel::FinishBasicBlock() {
   // Lower each BitTestBlock.
   for (auto &BTB : SDB->SL->BitTestCases) {
     // Lower header first, if it wasn't already lowered
-    if (!BTB.Emitted) {
+    if (!BTB.getEmitted()) {
       // Set the current basic block to the mbb we wish to insert the code into
       FuncInfo->MBB = BTB.Parent;
       FuncInfo->InsertPt = FuncInfo->MBB->end();
@@ -2076,7 +2078,8 @@ SelectionDAGISel::FinishBasicBlock() {
       // test, and delete the last bit test.
 
       MachineBasicBlock *NextMBB;
-      if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
+      if ((BTB.getContiguousRange() || BTB.getFallthroughUnreachable()) &&
+          j + 2 == ej) {
         // Second-to-last bit-test with contiguous range or omitted range
         // check: fall through to the target of the final bit test.
         NextMBB = BTB.Cases[j + 1].TargetBB;
@@ -2095,7 +2098,8 @@ SelectionDAGISel::FinishBasicBlock() {
       SDB->clear();
       CodeGenAndEmitDAG();
 
-      if ((BTB.ContiguousRange || BTB.FallthroughUnreachable) && j + 2 == ej) {
+      if ((BTB.getContiguousRange() || BTB.getFallthroughUnreachable()) &&
+          j + 2 == ej) {
         // Since we're not going to use the final bit test, remove it.
         BTB.Cases.pop_back();
         break;
@@ -2113,9 +2117,9 @@ SelectionDAGISel::FinishBasicBlock() {
       // from last "case" BB, unless the latter was skipped.
       if (PHIBB == BTB.Default) {
         PHI.addReg(P.second).addMBB(BTB.Parent);
-        if (!BTB.ContiguousRange) {
+        if (!BTB.getContiguousRange()) {
           PHI.addReg(P.second).addMBB(BTB.Cases.back().ThisBB);
-         }
+        }
       }
       // One of "cases" BB.
       for (const SwitchCG::BitTestCase &BT : BTB.Cases) {
@@ -3290,7 +3294,7 @@ struct MatchScope {
   unsigned FailIndex;
 
   /// NodeStack - The node stack when the scope was formed.
-  SmallVector<SDValue, 4> NodeStack;
+  llvm::SmallVectorWithFlags<SDValue, 4> NodeStack;
 
   /// NumRecordedNodes - The number of recorded nodes when the scope was formed.
   unsigned NumRecordedNodes;
@@ -3302,7 +3306,8 @@ struct MatchScope {
   SDValue InputChain, InputGlue;
 
   /// HasChainNodesMatched - True if the ChainNodesMatched list is non-empty.
-  bool HasChainNodesMatched;
+  bool getHasChainNodesMatched() const { return NodeStack.getFlag(0); }
+  void setHasChainNodesMatched(bool Value) { NodeStack.setFlag(0, Value); }
 };
 
 /// \A DAG update listener to keep the matching state
@@ -3574,7 +3579,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
       NewEntry.NumMatchedMemRefs = MatchedMemRefs.size();
       NewEntry.InputChain = InputChain;
       NewEntry.InputGlue = InputGlue;
-      NewEntry.HasChainNodesMatched = !ChainNodesMatched.empty();
+      NewEntry.setHasChainNodesMatched(!ChainNodesMatched.empty());
       continue;
     }
     case OPC_RecordNode: {
@@ -4556,7 +4561,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
 
       InputChain = LastScope.InputChain;
       InputGlue = LastScope.InputGlue;
-      if (!LastScope.HasChainNodesMatched)
+      if (!LastScope.getHasChainNodesMatched())
         ChainNodesMatched.clear();
 
       // Check to see what the offset is at the new MatcherIndex.  If it is zero
diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index b7a9464c6661c..fc31073b5de2a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -1183,7 +1183,7 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl(
       ForceVoidReturnTy ? Type::getVoidTy(*DAG.getContext()) : Call->getType(),
       Call->getAttributes().getRetAttrs(), /*IsPatchPoint=*/false);
   if (!VarArgDisallowed)
-    SI.CLI.IsVarArg = Call->getFunctionType()->isVarArg();
+    SI.CLI.setIsVarArg(Call->getFunctionType()->isVarArg());
 
   auto DeoptBundle = *Call->getOperandBundle(LLVMContext::OB_deopt);
 
diff --git a/llvm/lib/CodeGen/TargetSchedule.cpp b/llvm/lib/CodeGen/TargetSchedule.cpp
index 54bbf8ac60561..ba3a17fea12e5 100644
--- a/llvm/lib/CodeGen/TargetSchedule.cpp
+++ b/llvm/lib/CodeGen/TargetSchedule.cpp
@@ -33,11 +33,11 @@ static cl::opt<bool> ForceEnableIntervals(
     cl::desc("Force the use of resource intervals in the schedule model"));
 
 bool TargetSchedModel::hasInstrSchedModel() const {
-  return EnableSchedModel && SchedModel.hasInstrSchedModel();
+  return getEnableSchedModel() && SchedModel.hasInstrSchedModel();
 }
 
 bool TargetSchedModel::hasInstrItineraries() const {
-  return EnableSchedItins && !InstrItins.isEmpty();
+  return getEnableSchedItins() && !InstrItins.isEmpty();
 }
 
 void TargetSchedModel::init(const TargetSubtargetInfo *TSInfo,
@@ -47,8 +47,8 @@ void TargetSchedModel::init(const TargetSubtargetInfo *TSInfo,
   TII = TSInfo->getInstrInfo();
   STI->initInstrItins(InstrItins);
 
-  EnableSchedModel = EnableSModel;
-  EnableSchedItins = EnableSItins;
+  setEnableSchedModel(EnableSModel);
+  setEnableSchedItins(EnableSItins);
 
   unsigned NumRes = SchedModel.getNumProcResourceKinds();
   ResourceFactors.resize(NumRes);
diff --git a/llvm/lib/DTLTO/DTLTO.cpp b/llvm/lib/DTLTO/DTLTO.cpp
index 669ba75c80d4b..7ae124a90b32d 100644
--- a/llvm/lib/DTLTO/DTLTO.cpp
+++ b/llvm/lib/DTLTO/DTLTO.cpp
@@ -75,7 +75,7 @@ void lto::DTLTO::waitForCleanup() { BackgroundDeleter.waitForTasks(); }
 
 // Remove temporary files created to enable distribution.
 void lto::DTLTO::cleanup() {
-  if (SaveTemps)
+  if (getSaveTemps())
     return;
 
   BackgroundDeleter.removeFiles(std::move(CleanupList), Conf);
@@ -197,16 +197,16 @@ Error lto::DTLTO::prepareDtltoJob(StringRef ModulePath, unsigned Task) {
   if (OnIndexWriteCb)
     OnIndexWriteCb(J.SummaryIndexPath.str());
 
-  if (ShouldEmitImportFiles)
+  if (getShouldEmitImportFiles())
     if (Error Err = save(join(J.ImportsFilesList, "\n"), J.ImportsPath))
       return Err;
 
-  if (!SaveTemps) {
+  if (!getSaveTemps()) {
     if (!J.Cached)
       addToCleanup(J.NativeObjectPath.str());
-    if (!ShouldEmitIndexFiles)
+    if (!getShouldEmitIndexFiles())
       addToCleanup(J.SummaryIndexPath.str());
-    if (!ShouldEmitImportFiles)
+    if (!getShouldEmitImportFiles())
       addToCleanup(J.ImportsPath.str());
   }
   return Error::success();
@@ -283,7 +283,7 @@ Error lto::DTLTO::performCodegen() {
   // Build common remote compiler options.
   buildCommonRemoteCompilerOptions();
 
-  DistributionDriver Distributor(DistributorParams, Jobs, SaveTemps,
+  DistributionDriver Distributor(DistributorParams, Jobs, getSaveTemps(),
                                  [&](StringRef S) { addToCleanup(S); });
 
   if (CachedJobs.load() < Jobs.size()) {
diff --git a/llvm/lib/DTLTO/DTLTOInputFiles.cpp b/llvm/lib/DTLTO/DTLTOInputFiles.cpp
index b940bad4b8635..540ddcde69d2f 100644
--- a/llvm/lib/DTLTO/DTLTOInputFiles.cpp
+++ b/llvm/lib/DTLTO/DTLTOInputFiles.cpp
@@ -216,7 +216,7 @@ Error lto::DTLTO::extractLTOInputs() {
     if (Error Err = save(Buf.getBuffer(), ModuleID))
       return Err;
     // Cleanup this file on abnormal process exit.
-    if (!SaveTemps)
+    if (!getSaveTemps())
       addToCleanup(ModuleID);
   }
   return Error::success();
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
index df69afdd88eea..55bff4729ee6d 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
@@ -614,7 +614,7 @@ unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
   MyInfo.InDebugMap = true;
 
   if (((Flags & TF_InFunctionScope) &&
-       !LLVM_UNLIKELY(Options.KeepFunctionForStatic)))
+       !LLVM_UNLIKELY(Options.getKeepFunctionForStatic())))
     return Flags;
 
   if (Options.Verbose) {
@@ -1312,7 +1312,8 @@ void DWARFLinker::DIECloner::cloneExpression(
       assert(RealSize == ULEBsize && "padding failed");
       ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
       OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
-    } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_addrx) {
+    } else if (!Linker.Options.getUpdate() &&
+               Op.getCode() == dwarf::DW_OP_addrx) {
       if (std::optional<object::SectionedAddress> SA =
               Unit.getOrigUnit().getAddrOffsetSectionItem(
                   Op.getRawOperand(0))) {
@@ -1335,7 +1336,8 @@ void DWARFLinker::DIECloner::cloneExpression(
         OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
       } else
         Linker.reportWarning("cannot read DW_OP_addrx operand.", File);
-    } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_constx) {
+    } else if (!Linker.Options.getUpdate() &&
+               Op.getCode() == dwarf::DW_OP_constx) {
       if (std::optional<object::SectionedAddress> SA =
               Unit.getOrigUnit().getAddrOffsetSectionItem(
                   Op.getRawOperand(0))) {
@@ -1475,7 +1477,7 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
   if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
     Info.HasLowPc = true;
 
-  if (LLVM_UNLIKELY(Linker.Options.Update)) {
+  if (LLVM_UNLIKELY(Linker.Options.getUpdate())) {
     Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
                  dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
     return AttrSize;
@@ -1589,7 +1591,7 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
     return Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize();
   }
 
-  if (LLVM_UNLIKELY(Linker.Options.Update)) {
+  if (LLVM_UNLIKELY(Linker.Options.getUpdate())) {
     if (auto OptionalValue = Val.getAsUnsignedConstant())
       Value = *OptionalValue;
     else if (auto OptionalValue = Val.getAsSignedConstant())
@@ -2085,7 +2087,7 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
 /// to point at the new entries.
 Error DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
                                       DebugDieValuePool &AddrPool) const {
-  if (LLVM_UNLIKELY(Options.Update))
+  if (LLVM_UNLIKELY(Options.getUpdate()))
     return Error::success();
 
   const auto &FunctionRanges = Unit.getFunctionRanges();
@@ -2158,7 +2160,7 @@ Error DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
 Error DWARFLinker::DIECloner::generateUnitLocations(
     CompileUnit &Unit, const DWARFFile &File,
     ExpressionHandlerRef ExprHandler) {
-  if (LLVM_UNLIKELY(Linker.Options.Update))
+  if (LLVM_UNLIKELY(Linker.Options.getUpdate()))
     return Error::success();
 
   const LocListAttributesTy &AllLocListAttributes =
@@ -2226,7 +2228,7 @@ static void patchAddrBase(DIE &Die, DIEInteger Offset) {
 Error DWARFLinker::DIECloner::emitDebugAddrSection(
     CompileUnit &Unit, const uint16_t DwarfVersion) const {
 
-  if (LLVM_UNLIKELY(Linker.Options.Update))
+  if (LLVM_UNLIKELY(Linker.Options.getUpdate()))
     return Error::success();
 
   if (DwarfVersion < 5)
@@ -2353,7 +2355,7 @@ Error DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
     LineTable.Prologue = LT->Prologue;
 
     // Set Line Table Rows.
-    if (Linker.Options.Update) {
+    if (Linker.Options.getUpdate()) {
       LineTable.Rows = LT->Rows;
       // If all the line table contains is a DW_LNE_end_sequence, clear the line
       // table rows, it will be inserted again in the DWARFStreamer.
@@ -2899,8 +2901,8 @@ Error DWARFLinker::loadClangModule(
       }
 
       // Add this module.
-      Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR,
-                                           ModuleName);
+      Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++,
+                                           !Options.getNoODR(), ModuleName);
     }
   }
 
@@ -2943,7 +2945,7 @@ Expected<uint64_t> DWARFLinker::DIECloner::cloneAllCompileUnits(
 
       Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
 
-      if (LLVM_UNLIKELY(Linker.Options.Update))
+      if (LLVM_UNLIKELY(Linker.Options.getUpdate()))
         continue;
 
       if (Error E = Linker.generateUnitRanges(*CurrentUnit, File, AddrPool))
@@ -3028,7 +3030,7 @@ void DWARFLinker::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
 
       OnCUDieLoaded(*CU);
 
-      if (!LLVM_UNLIKELY(Options.Update))
+      if (!LLVM_UNLIKELY(Options.getUpdate()))
         registerModuleReference(CUDie, ObjectContexts.back(), Loader,
                                 OnCUDieLoaded);
     }
@@ -3060,14 +3062,14 @@ Error DWARFLinker::link() {
     if (!OptContext.File.Dwarf)
       continue;
 
-    if (Options.VerifyInputDWARF)
+    if (Options.getVerifyInputDWARF())
       verifyInput(OptContext.File);
 
     // Look for relocations that correspond to address map entries.
 
     // there was findvalidrelocations previously ... probably we need to gather
     // info here
-    if (LLVM_LIKELY(!Options.Update) &&
+    if (LLVM_LIKELY(!Options.getUpdate()) &&
         !OptContext.File.Addresses->hasValidRelocs()) {
       if (Options.Verbose)
         outs() << "No valid relocations found. Skipping.\n";
@@ -3142,10 +3144,11 @@ Error DWARFLinker::link() {
       auto CUDie = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false);
       std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
 
-      if (!CUDie || LLVM_UNLIKELY(Options.Update) ||
+      if (!CUDie || LLVM_UNLIKELY(Options.getUpdate()) ||
           !isClangModuleRef(CUDie, PCMFile, Context, 0, true).first) {
         Context.CompileUnits.push_back(std::make_unique<CompileUnit>(
-            *CU, UniqueUnitID++, !Options.NoODR && !Options.Update, ""));
+            *CU, UniqueUnitID++, !Options.getNoODR() && !Options.getUpdate(),
+            ""));
       }
     }
 
@@ -3180,7 +3183,7 @@ Error DWARFLinker::link() {
     // Note that this loop can not be merged with the previous one because
     // cross-cu references require the ParentIdx to be setup for every CU in
     // the object file before calling this.
-    if (LLVM_UNLIKELY(Options.Update)) {
+    if (LLVM_UNLIKELY(Options.getUpdate())) {
       for (auto &CurrentUnit : OptContext.CompileUnits)
         CurrentUnit->markEverythingAsKept();
       copyInvariantDebugSection(*OptContext.File.Dwarf);
@@ -3199,12 +3202,12 @@ Error DWARFLinker::link() {
     // array again (in the same way findValidRelocsInDebugInfo() did). We
     // need to reset the NextValidReloc index to the beginning.
     if (OptContext.File.Addresses->hasValidRelocs() ||
-        LLVM_UNLIKELY(Options.Update)) {
+        LLVM_UNLIKELY(Options.getUpdate())) {
       SizeByObject[OptContext.File.FileName].Input =
           getDebugInfoSize(*OptContext.File.Dwarf);
       Expected<uint64_t> SizeOrErr =
           DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc,
-                    OptContext.CompileUnits, Options.Update, DebugStrPool,
+                    OptContext.CompileUnits, Options.getUpdate(), DebugStrPool,
                     DebugLineStrPool, StringOffsetPool)
               .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
                                     OptContext.File.Dwarf->isLittleEndian());
@@ -3215,7 +3218,7 @@ Error DWARFLinker::link() {
       SizeByObject[OptContext.File.FileName].Output = *SizeOrErr;
     }
     if ((TheDwarfEmitter != nullptr) && !OptContext.CompileUnits.empty() &&
-        LLVM_LIKELY(!Options.Update))
+        LLVM_LIKELY(!Options.getUpdate()))
       patchFrameInfoForObject(OptContext);
 
     // Clean-up before starting working on the next object.
@@ -3383,7 +3386,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
   assert(TheDwarfEmitter);
   Expected<uint64_t> SizeOrErr =
       DIECloner(*this, TheDwarfEmitter, Unit.File, DIEAlloc, CompileUnits,
-                Options.Update, DebugStrPool, DebugLineStrPool,
+                Options.getUpdate(), DebugStrPool, DebugLineStrPool,
                 StringOffsetPool)
           .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
                                 Unit.File.Dwarf->isLittleEndian());
diff --git a/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp b/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
index 67545ee03d15b..504112891eef1 100644
--- a/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DIEAttributeCloner.cpp
@@ -143,7 +143,7 @@ bool DIEAttributeCloner::shouldSkipAttribute(
   case dwarf::DW_AT_low_pc:
   case dwarf::DW_AT_high_pc:
   case dwarf::DW_AT_ranges:
-    if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
+    if (InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly())
       return false;
 
     // Skip address attribute if we are in function scope and function does not
@@ -155,16 +155,16 @@ bool DIEAttributeCloner::shouldSkipAttribute(
     // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
     // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
     // DW_AT_rnglists_base is removed.
-    return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
+    return !InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly();
   case dwarf::DW_AT_loclists_base:
     // In case !Update the .debug_addr table is not generated/preserved.
     // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
     // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
     // DW_AT_loclists_base is removed.
-    return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
+    return !InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly();
   case dwarf::DW_AT_location:
   case dwarf::DW_AT_frame_base:
-    if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
+    if (InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly())
       return false;
 
     // When location expression contains an address: skip this attribute
@@ -418,7 +418,7 @@ size_t DIEAttributeCloner::cloneScalarAttr(
        InputDieEntry->getTag() == dwarf::DW_TAG_constant))
     AttrInfo.HasLiveAddress = true;
 
-  if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
+  if (InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly()) {
     if (auto OptionalValue = Val.getAsUnsignedConstant())
       Value = *OptionalValue;
     else if (auto OptionalValue = Val.getAsSignedConstant())
@@ -655,7 +655,7 @@ size_t DIEAttributeCloner::cloneBlockAttr(
   if (HasLocationExpressionAddress)
     AttrInfo.HasLiveAddress =
         VarAddressAdjustment.has_value() ||
-        InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
+        InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly();
 
   return FinalAttributeSize;
 }
@@ -666,7 +666,7 @@ size_t DIEAttributeCloner::cloneAddressAttr(
   if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
     AttrInfo.HasLiveAddress = true;
 
-  if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
+  if (InUnit.getGlobalData().getOptions().getUpdateIndexTablesOnly())
     return Generator
         .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
         .second;
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
index eb2f04174f1c4..424f8c4724654 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
@@ -53,9 +53,9 @@ CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,
 
   Language = CUDie.getLanguage();
 
-  if (!GlobalData.getOptions().NoODR && Language.has_value() &&
+  if (!GlobalData.getOptions().getNoODR() && Language.has_value() &&
       isODRLanguage(*Language))
-    NoODR = false;
+    setNoODR(false);
 
   if (const char *CUName = CUDie.getName(DINameKind::ShortName))
     UnitName = CUName;
@@ -114,7 +114,7 @@ bool CompileUnit::loadInputDIEs() {
   // load input dies, resize Info structures array.
   DieInfoArray.resize(getOrigUnit().getNumDIEs());
   OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
-  if (!NoODR)
+  if (!getNoODR())
     TypeEntries.resize(getOrigUnit().getNumDIEs());
   return true;
 }
@@ -168,11 +168,12 @@ void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
       break;
     }
 
-    if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)
+    if (!isClangModule() &&
+        !getGlobalData().getOptions().getUpdateIndexTablesOnly())
       ChildInfo.setTrackLiveness();
 
     if ((!ChildInfo.getIsInAnonNamespaceScope() &&
-         !ChildIsODRUnavailableFunctionScope && !NoODR))
+         !ChildIsODRUnavailableFunctionScope && !getNoODR()))
       ChildInfo.setODRAvailable();
 
     if (CurChild->hasChildren())
@@ -250,7 +251,7 @@ void CompileUnit::cleanupDataAfterClonning() {
   FileNames.shrink_and_clear();
   DieInfoArray = SmallVector<DIEInfo>();
   OutDieOffsetArray = SmallVector<uint64_t>();
-  TypeEntries = SmallVector<TypeEntry *>();
+  TypeEntries.assign(SmallVector<TypeEntry *>());
   Dependencies.reset(nullptr);
   StmtSeqListAttributes.clear();
   getOrigUnit().clear();
@@ -556,7 +557,7 @@ void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
 }
 
 Error CompileUnit::cloneAndEmitDebugLocations() {
-  if (getGlobalData().getOptions().UpdateIndexTablesOnly)
+  if (getGlobalData().getOptions().getUpdateIndexTablesOnly())
     return Error::success();
 
   if (getOrigUnit().getVersion() < 5) {
@@ -744,7 +745,7 @@ uint64_t CompileUnit::emitLocListFragment(
 }
 
 Error CompileUnit::emitDebugAddrSection() {
-  if (GlobalData.getOptions().UpdateIndexTablesOnly)
+  if (GlobalData.getOptions().getUpdateIndexTablesOnly())
     return Error::success();
 
   if (getVersion() < 5)
@@ -786,7 +787,7 @@ Error CompileUnit::emitDebugAddrSection() {
 }
 
 Error CompileUnit::cloneAndEmitRanges() {
-  if (getGlobalData().getOptions().UpdateIndexTablesOnly)
+  if (getGlobalData().getOptions().getUpdateIndexTablesOnly())
     return Error::success();
 
   // Build set of linked address ranges for unit function ranges.
@@ -1287,7 +1288,7 @@ void CompileUnit::cloneDieAttrExpression(
       assert(RealSize == ULEBsize && "padding failed");
       ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
       OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
-    } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
+    } else if (!getGlobalData().getOptions().getUpdateIndexTablesOnly() &&
                Op.getCode() == dwarf::DW_OP_addrx) {
       if (std::optional<object::SectionedAddress> SA =
               OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
@@ -1309,7 +1310,7 @@ void CompileUnit::cloneDieAttrExpression(
         OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
       } else
         warn("cann't read DW_OP_addrx operand.");
-    } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
+    } else if (!getGlobalData().getOptions().getUpdateIndexTablesOnly() &&
                Op.getCode() == dwarf::DW_OP_constx) {
       if (std::optional<object::SectionedAddress> SA =
               OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
@@ -1689,7 +1690,7 @@ Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) {
   OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize;
 
   // Set Line Table Rows.
-  if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
+  if (getGlobalData().getOptions().getUpdateIndexTablesOnly()) {
     OutLineTable.Rows = InputLineTable->Rows;
     // If all the line table contains is a DW_LNE_end_sequence, clear the line
     // table rows, it will be inserted again in the DWARFStreamer.
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
index c8c1b8822aa64..bb5791be78d2d 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
@@ -10,6 +10,7 @@
 #define LLVM_LIB_DWARFLINKER_PARALLEL_DWARFLINKERCOMPILEUNIT_H
 
 #include "DWARFLinkerUnit.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/DWARFLinker/DWARFFile.h"
 #include <limits>
 #include <optional>
@@ -821,7 +822,11 @@ class alignas(8) CompileUnit : public DwarfUnit {
   uint64_t HighPc = 0;
 
   /// Flag indicating whether type de-duplication is forbidden.
-  bool NoODR = true;
+  bool getNoODR() const { return !TypeEntries.getFlag(0); }
+  bool setNoODR(bool Value) {
+    TypeEntries.setFlag(0, !Value);
+    return Value;
+  }
 
   /// Deterministic priority for type DIE allocation (lower wins).
   uint64_t Priority = std::numeric_limits<uint64_t>::max();
@@ -855,7 +860,7 @@ class alignas(8) CompileUnit : public DwarfUnit {
   /// DIE info indexed by DIE index.
   SmallVector<DIEInfo> DieInfoArray;
   SmallVector<uint64_t> OutDieOffsetArray;
-  SmallVector<TypeEntry *> TypeEntries;
+  llvm::SmallVectorWithFlags<TypeEntry *> TypeEntries;
 
   /// The list of accelerator records for this unit.
   ArrayList<AccelInfo> AcceleratorRecords;
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h
index b65c5d809b1d1..36a060c56a425 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h
@@ -11,6 +11,7 @@
 
 #include "ModulePool.h"
 #include "TypePool.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
 #include "llvm/DWARFLinker/StringPool.h"
 #include "llvm/Support/PerThreadBumpPtrAllocator.h"
@@ -37,23 +38,30 @@ struct DWARFLinkerOptions {
   bool Statistics = false;
 
   /// Verify the input DWARF.
-  bool VerifyInputDWARF = false;
+  bool getVerifyInputDWARF() const { return AccelTables.getFlag(0); }
+  void setVerifyInputDWARF(bool Value) { AccelTables.setFlag(0, Value); }
 
   /// Do not unique types according to ODR
-  bool NoODR = false;
+  bool getNoODR() const { return AccelTables.getFlag(1); }
+  bool setNoODR(bool Value) {
+    AccelTables.setFlag(1, Value);
+    return Value;
+  }
 
   /// Update index tables.
-  bool UpdateIndexTablesOnly = false;
+  bool getUpdateIndexTablesOnly() const { return AccelTables.getFlag(2); }
+  void setUpdateIndexTablesOnly(bool Value) { AccelTables.setFlag(2, Value); }
 
   /// Whether we want a static variable to force us to keep its enclosing
   /// function.
-  bool KeepFunctionForStatic = false;
+  bool getKeepFunctionForStatic() const { return AccelTables.getFlag(3); }
+  void setKeepFunctionForStatic(bool Value) { AccelTables.setFlag(3, Value); }
 
   /// Number of threads.
   unsigned Threads = 1;
 
   /// The accelerator table kinds
-  SmallVector<DWARFLinkerBase::AccelTableKind, 1> AccelTables;
+  llvm::SmallVectorWithFlags<DWARFLinkerBase::AccelTableKind, 1, 4> AccelTables;
 
   /// Prepend path for the clang modules.
   std::string PrependPath;
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp
index f0fd044b09e76..3dbbc3bccb805 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp
@@ -64,7 +64,7 @@ void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
       OnCUDieLoaded(*CU);
 
       // Register mofule reference.
-      if (!GlobalData.getOptions().UpdateIndexTablesOnly)
+      if (!GlobalData.getOptions().getUpdateIndexTablesOnly())
         ObjectContexts.back()->registerModuleReference(CUDie, Loader,
                                                        OnCUDieLoaded);
     }
@@ -117,7 +117,7 @@ Error DWARFLinkerImpl::link() {
     }
 
     // Verify input DWARF if requested.
-    if (GlobalData.getOptions().VerifyInputDWARF)
+    if (GlobalData.getOptions().getVerifyInputDWARF())
       verifyInput(Context->InputDWARFFile);
 
     if (!GlobalData.getTargetTriple())
@@ -165,7 +165,7 @@ Error DWARFLinkerImpl::link() {
 
   CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
 
-  if (!GlobalData.Options.NoODR && Language.has_value()) {
+  if (!GlobalData.Options.getNoODR() && Language.has_value()) {
     llvm::parallel::TaskGroup TGroup;
     TGroup.spawn([&]() {
       ArtificialTypeUnit = std::make_unique<TypeUnit>(
@@ -222,7 +222,7 @@ Error DWARFLinkerImpl::link() {
 
   // Build the linker-wide CIE registry, then emit each context's
   // .debug_frame in parallel. See CIERegistry for the ownership rules.
-  if (!GlobalData.getOptions().UpdateIndexTablesOnly) {
+  if (!GlobalData.getOptions().getUpdateIndexTablesOnly()) {
     LinkContext::CIERegistry CIEs;
     for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
       if (Context->FrameScan)
@@ -282,9 +282,9 @@ Error DWARFLinkerImpl::validateAndUpdateOptions() {
   }
 
   // Do not do types deduplication in case --update.
-  if (GlobalData.getOptions().UpdateIndexTablesOnly &&
-      !GlobalData.Options.NoODR)
-    GlobalData.Options.NoODR = true;
+  if (GlobalData.getOptions().getUpdateIndexTablesOnly() &&
+      !GlobalData.Options.getNoODR())
+    GlobalData.Options.setNoODR(true);
 
   return Error::success();
 }
@@ -487,7 +487,7 @@ Error DWARFLinkerImpl::LinkContext::loadClangModule(
 }
 
 Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
-  InterCUProcessingStarted = false;
+  setInterCUProcessingStarted(false);
   if (!InputDWARFFile.Dwarf)
     return Error::success();
 
@@ -506,7 +506,7 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
 
   // Check for live relocations. If there is no any live relocation then we
   // can skip entire object file.
-  if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
+  if (!GlobalData.getOptions().getUpdateIndexTablesOnly() &&
       !InputDWARFFile.Addresses->hasValidRelocs()) {
     if (GlobalData.getOptions().Verbose)
       outs() << "No valid relocations found. Skipping.\n";
@@ -526,7 +526,7 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
 
     // The !isClangModuleRef condition effectively skips over fully resolved
     // skeleton units.
-    if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
+    if (!CUDie || GlobalData.getOptions().getUpdateIndexTablesOnly() ||
         !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
       CompileUnits.emplace_back(std::make_unique<CompileUnit>(
           GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
@@ -550,7 +550,7 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
 
   // Link all inter-connected units.
   if (HasNewInterconnectedCUs) {
-    InterCUProcessingStarted = true;
+    setInterCUProcessingStarted(true);
 
     if (Error Err = finiteLoop([&]() -> Expected<bool> {
           HasNewInterconnectedCUs = false;
@@ -616,7 +616,7 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
     });
   }
 
-  if (GlobalData.getOptions().UpdateIndexTablesOnly) {
+  if (GlobalData.getOptions().getUpdateIndexTablesOnly()) {
     // Emit Invariant sections.
 
     if (Error Err = emitInvariantSections())
@@ -629,7 +629,7 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
 void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
     CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
     enum CompileUnit::Stage DoUntilStage) {
-  if (InterCUProcessingStarted != CU.isInterconnectedCU())
+  if (getInterCUProcessingStarted() != CU.isInterconnectedCU())
     return;
 
   if (Error Err = finiteLoop([&]() -> Expected<bool> {
@@ -656,7 +656,7 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
             // Runs concurrently, so it must stay a no-op: it may only be
             // entered when the serial pass in addObjectFile() has already
             // populated the module map.
-            if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
+            if (!GlobalData.getOptions().getUpdateIndexTablesOnly() &&
                 registerModuleReference(
                     CU.getOrigUnit().getUnitDIE(), nullptr,
                     [](const DWARFUnit &) {}, 0))
@@ -669,8 +669,8 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
         case CompileUnit::Stage::Loaded: {
           // Mark all the DIEs that need to be present in the generated output.
           // If ODR requested, build type names.
-          if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
-                                                     HasNewInterconnectedCUs)) {
+          if (!CU.resolveDependenciesAndMarkLiveness(
+                  getInterCUProcessingStarted(), HasNewInterconnectedCUs)) {
             assert(HasNewInterconnectedCUs &&
                    "Flag indicating new inter-connections is not set");
             return false;
@@ -680,7 +680,7 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
         } break;
 
         case CompileUnit::Stage::LivenessAnalysisDone: {
-          if (InterCUProcessingStarted) {
+          if (getInterCUProcessingStarted()) {
             if (CU.updateDependenciesCompleteness())
               HasNewGlobalDependency = true;
             return false;
@@ -710,7 +710,7 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
         case CompileUnit::Stage::TypeNamesAssigned:
           // Clone input compile unit.
           if (CU.isClangModule() ||
-              GlobalData.getOptions().UpdateIndexTablesOnly ||
+              GlobalData.getOptions().getUpdateIndexTablesOnly() ||
               CU.getContainingFile().Addresses->hasValidRelocs()) {
             if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
                                             ArtificialTypeUnit))
@@ -779,7 +779,7 @@ Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
 }
 
 Error DWARFLinkerImpl::LinkContext::scanFrameData() {
-  if (GlobalData.getOptions().UpdateIndexTablesOnly)
+  if (GlobalData.getOptions().getUpdateIndexTablesOnly())
     return Error::success();
   if (!GlobalData.getTargetTriple().has_value())
     return Error::success();
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h
index b7286bbb82a28..2c3337e3d01c6 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h
@@ -15,6 +15,7 @@
 #include "StringEntryToDwarfStringPoolEntryMap.h"
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AccelTable.h"
 #include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
 #include "llvm/DWARFLinker/StringPool.h"
@@ -68,20 +69,20 @@ class DWARFLinkerImpl : public DWARFLinker {
 
   /// Verify the input DWARF.
   void setVerifyInputDWARF(bool Verify) override {
-    GlobalData.Options.VerifyInputDWARF = Verify;
+    GlobalData.Options.setVerifyInputDWARF(Verify);
   }
 
   /// Do not unique types according to ODR.
-  void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }
+  void setNoODR(bool NoODR) override { GlobalData.Options.setNoODR(NoODR); }
 
   /// Update index tables only(do not modify rest of DWARF).
   void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {
-    GlobalData.Options.UpdateIndexTablesOnly = UpdateIndexTablesOnly;
+    GlobalData.Options.setUpdateIndexTablesOnly(UpdateIndexTablesOnly);
   }
 
   /// Set to keep the enclosing function for a static variable.
   void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {
-    GlobalData.Options.KeepFunctionForStatic = KeepFunctionForStatic;
+    GlobalData.Options.setKeepFunctionForStatic(KeepFunctionForStatic);
   }
 
   /// Use specified number of threads for parallel files linking.
@@ -165,7 +166,7 @@ class DWARFLinkerImpl : public DWARFLinker {
     UnitListTy CompileUnits;
 
     /// Set of Compile Units for modules.
-    UnitListTy ModulesCompileUnits;
+    llvm::SmallVectorWithFlagsFor<UnitListTy, 1> ModulesCompileUnits;
 
     /// Index of this object file in the link order (used for deterministic
     /// type DIE allocation).
@@ -176,7 +177,12 @@ class DWARFLinkerImpl : public DWARFLinker {
 
     /// Flag indicating that all inter-connected units are loaded
     /// and the dwarf linking process for these units is started.
-    bool InterCUProcessingStarted = false;
+    bool getInterCUProcessingStarted() const {
+      return ModulesCompileUnits.getFlag(0);
+    }
+    void setInterCUProcessingStarted(bool Value) {
+      ModulesCompileUnits.setFlag(0, Value);
+    }
 
     StringMap<uint64_t> &ClangModules;
 
diff --git a/llvm/lib/DWARFLinker/Parallel/DependencyTracker.cpp b/llvm/lib/DWARFLinker/Parallel/DependencyTracker.cpp
index 669ea2ceb16c9..99e51508c2221 100644
--- a/llvm/lib/DWARFLinker/Parallel/DependencyTracker.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DependencyTracker.cpp
@@ -127,9 +127,9 @@ bool DependencyTracker::resolveDependenciesAndMarkLiveness(
   // be resolved is reset to its loaded stage and marked again from scratch, so
   // no reference recorded under one resolution mode survives into another.
   assert((SubtreeDependencyRefs.empty() ||
-          InterCUProcessingWasStarted == InterCUProcessingStarted) &&
+          getInterCUProcessingWasStarted() == InterCUProcessingStarted) &&
          "recorded subtrees would be walked in a different resolution mode");
-  InterCUProcessingWasStarted = InterCUProcessingStarted;
+  setInterCUProcessingWasStarted(InterCUProcessingStarted);
 
   // Search for live root DIEs.
   CompileUnit::DIEInfo &CUInfo = CU.getDIEInfo(CU.getDebugInfoEntry(0));
@@ -326,7 +326,7 @@ void DependencyTracker::materializeSubtreeSummaries() {
       std::atomic<bool> HasNewInterconnectedCUs = false;
       [[maybe_unused]] bool Res = markDIEEntryAsKeptRec(
           Ref.Action, Ref.ReferencedBy, Ref.Subtree,
-          InterCUProcessingWasStarted, HasNewInterconnectedCUs,
+          getInterCUProcessingWasStarted(), HasNewInterconnectedCUs,
           TreeWalkKindTy::RecordSubtreeDeps);
       assert(Res && !HasNewInterconnectedCUs && "record-deps-only walk failed");
     }
@@ -998,7 +998,7 @@ bool DependencyTracker::isLiveVariableEntry(const UnitEntryPairTy &Entry,
         return false;
 
       if (!IsLiveParent && Info.getIsInFunctionScope() &&
-          !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
+          !Entry.CU->getGlobalData().getOptions().getKeepFunctionForStatic())
         return false;
     }
   }
diff --git a/llvm/lib/DWARFLinker/Parallel/DependencyTracker.h b/llvm/lib/DWARFLinker/Parallel/DependencyTracker.h
index dbf67cce3365c..83619ddcb4f1d 100644
--- a/llvm/lib/DWARFLinker/Parallel/DependencyTracker.h
+++ b/llvm/lib/DWARFLinker/Parallel/DependencyTracker.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace llvm {
 class DWARFDebugInfoEntry;
@@ -391,7 +392,7 @@ class DependencyTracker {
   DenseMap<SubtreeDependenciesKeyTy, SubtreeDependenciesTy> SubtreeSummaries;
 
   /// Roots referencing an already-marked subtree.
-  SmallVector<SubtreeDependencyRefTy> SubtreeDependencyRefs;
+  llvm::SmallVectorWithFlags<SubtreeDependencyRefTy> SubtreeDependencyRefs;
 
   /// Number of leading SubtreeDependencyRefs whose subtree is summarized.
   size_t MaterializedRefs = 0;
@@ -403,7 +404,12 @@ class DependencyTracker {
 
   /// Whether inter-unit references could be resolved during marking. Reused
   /// when the recorded subtrees are walked, which happens outside of marking.
-  bool InterCUProcessingWasStarted = false;
+  bool getInterCUProcessingWasStarted() const {
+    return SubtreeDependencyRefs.getFlag(0);
+  }
+  void setInterCUProcessingWasStarted(bool Value) {
+    SubtreeDependencyRefs.setFlag(0, Value);
+  }
 };
 
 } // end of namespace parallel
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index b9aaa3146c9cc..60a0d3cf9cb91 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
@@ -126,11 +127,12 @@ class TypeStreamMerger {
   }
 
   bool hasTypeStream() const {
-    return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
+    return (getUseGlobalHashes()) ? (!!DestGlobalTypeStream)
+                                  : (!!DestTypeStream);
   }
 
   bool hasIdStream() const {
-    return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
+    return (getUseGlobalHashes()) ? (!!DestGlobalIdStream) : (!!DestIdStream);
   }
 
   ArrayRef<uint8_t> remapIndices(const CVType &OriginalType,
@@ -169,9 +171,11 @@ class TypeStreamMerger {
 
   std::optional<Error> LastError;
 
-  bool UseGlobalHashes = false;
+  bool getUseGlobalHashes() const { return RemapStorage.getFlag(0); }
+  void setUseGlobalHashes(bool Value) { RemapStorage.setFlag(0, Value); }
 
-  bool IsSecondPass = false;
+  bool getIsSecondPass() const { return RemapStorage.getFlag(1); }
+  void setIsSecondPass(bool Value) { RemapStorage.setFlag(1, Value); }
 
   unsigned NumBadIndices = 0;
 
@@ -195,7 +199,7 @@ class TypeStreamMerger {
 
   /// Temporary storage that we use to copy a record's data while re-writing
   /// its type indices.
-  SmallVector<uint8_t, 256> RemapStorage;
+  llvm::SmallVectorWithFlags<uint8_t, 256, 2> RemapStorage;
 
   std::optional<PCHMergerInfo> PCHInfo;
 };
@@ -205,7 +209,7 @@ class TypeStreamMerger {
 const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
 
 void TypeStreamMerger::addMapping(TypeIndex Idx) {
-  if (!IsSecondPass) {
+  if (!getIsSecondPass()) {
     assert(IndexMap.size() == slotForIndex(CurIndex) &&
            "visitKnownRecord should add one index map entry");
     IndexMap.push_back(Idx);
@@ -221,7 +225,7 @@ bool TypeStreamMerger::remapIndexFallback(TypeIndex &Idx,
 
   // If this is the second pass and this index isn't in the map, then it points
   // outside the current type stream, and this is a corrupt record.
-  if (IsSecondPass && MapPos >= Map.size()) {
+  if (getIsSecondPass() && MapPos >= Map.size()) {
     // FIXME: Print a more useful error. We can give the current record and the
     // index that we think its pointing to.
     if (LastError)
@@ -242,7 +246,7 @@ bool TypeStreamMerger::remapIndexFallback(TypeIndex &Idx,
 Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest,
                                          const CVTypeArray &Types) {
   DestTypeStream = &Dest;
-  UseGlobalHashes = false;
+  setUseGlobalHashes(false);
 
   return doit(Types);
 }
@@ -252,7 +256,7 @@ Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest,
                                        const CVTypeArray &Ids) {
   DestIdStream = &Dest;
   TypeLookup = TypeSourceToDest;
-  UseGlobalHashes = false;
+  setUseGlobalHashes(false);
 
   return doit(Ids);
 }
@@ -262,7 +266,7 @@ Error TypeStreamMerger::mergeTypesAndIds(
     const CVTypeArray &IdsAndTypes, std::optional<PCHMergerInfo> &PCHInfo) {
   DestIdStream = &DestIds;
   DestTypeStream = &DestTypes;
-  UseGlobalHashes = false;
+  setUseGlobalHashes(false);
   auto Err = doit(IdsAndTypes);
   PCHInfo = this->PCHInfo;
   return Err;
@@ -274,7 +278,7 @@ Error TypeStreamMerger::mergeTypeRecords(
     ArrayRef<GloballyHashedType> Hashes,
     std::optional<PCHMergerInfo> &PCHInfo) {
   DestGlobalTypeStream = &Dest;
-  UseGlobalHashes = true;
+  setUseGlobalHashes(true);
   GlobalHashes = Hashes;
   auto Err = doit(Types);
   PCHInfo = this->PCHInfo;
@@ -287,7 +291,7 @@ Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
                                        ArrayRef<GloballyHashedType> Hashes) {
   DestGlobalIdStream = &Dest;
   TypeLookup = TypeSourceToDest;
-  UseGlobalHashes = true;
+  setUseGlobalHashes(true);
   GlobalHashes = Hashes;
 
   return doit(Ids);
@@ -299,7 +303,7 @@ Error TypeStreamMerger::mergeTypesAndIds(
     std::optional<PCHMergerInfo> &PCHInfo) {
   DestGlobalIdStream = &DestIds;
   DestGlobalTypeStream = &DestTypes;
-  UseGlobalHashes = true;
+  setUseGlobalHashes(true);
   GlobalHashes = Hashes;
   auto Err = doit(IdsAndTypes);
   PCHInfo = this->PCHInfo;
@@ -319,7 +323,7 @@ Error TypeStreamMerger::doit(const CVTypeArray &Types) {
   // efficient. MASM type streams are usually very small.
   while (!LastError && NumBadIndices > 0) {
     unsigned BadIndicesRemaining = NumBadIndices;
-    IsSecondPass = true;
+    setIsSecondPass(true);
     NumBadIndices = 0;
     CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
 
@@ -361,7 +365,7 @@ Error TypeStreamMerger::remapType(const CVType &Type) {
     };
     unsigned AlignedSize = alignTo(Type.RecordData.size(), 4);
 
-    if (LLVM_LIKELY(UseGlobalHashes)) {
+    if (LLVM_LIKELY(getUseGlobalHashes())) {
       GlobalTypeTableBuilder &Dest =
           isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
       GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
@@ -379,7 +383,7 @@ Error TypeStreamMerger::remapType(const CVType &Type) {
   addMapping(DestIdx);
 
   ++CurIndex;
-  assert((IsSecondPass || IndexMap.size() == slotForIndex(CurIndex)) &&
+  assert((getIsSecondPass() || IndexMap.size() == slotForIndex(CurIndex)) &&
          "visitKnownRecord should add one index map entry");
   return Error::success();
 }
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
index 91c208eea9738..7b67ad54480c5 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
@@ -46,7 +46,7 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const {
   unsigned IndLevel = 0;
   for (const auto &Macros : MacroLists) {
     OS << formatv("{0:x8}:\n", Macros.Offset);
-    if (Macros.IsDebugMacro)
+    if (Macros.getIsDebugMacro())
       Macros.Header.dumpMacroHeader(OS);
     for (const Entry &E : Macros.Macros) {
       // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
@@ -58,7 +58,7 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const {
         OS << "  ";
       IndLevel += (E.Type == DW_MACINFO_start_file);
       // Based on which version we are handling choose appropriate macro forms.
-      if (Macros.IsDebugMacro)
+      if (Macros.getIsDebugMacro())
         WithColor(OS, HighlightColor::Macro).get()
             << (Macros.Header.Version < 5 ? GnuMacroString(E.Type)
                                           : MacroString(E.Type));
@@ -130,7 +130,7 @@ Error DWARFDebugMacro::parseImpl(
       MacroLists.emplace_back();
       M = &MacroLists.back();
       M->Offset = Offset;
-      M->IsDebugMacro = IsMacro;
+      M->setIsDebugMacro(IsMacro);
       if (IsMacro) {
         auto Err = M->Header.parseMacroHeader(Data, &Offset);
         if (Err)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
index bc9e888b0bd7f..72b5c0fd2f0a2 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
@@ -100,7 +100,7 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
                     DIDumpOptions DumpOpts, const DWARFExpression *Expr,
                     DWARFUnit *U) {
   if (Op->isError()) {
-    if (!DumpOpts.PrintRegisterOnly)
+    if (!DumpOpts.printRegisterOnly())
       OS << "<decoding error>";
     return false;
   }
@@ -111,7 +111,7 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
   // This lets clients print annotations like "i = 0" when the location is
   // a constant (e.g. DW_OP_constu/consts ... DW_OP_stack_value).
   // We continue to suppress all other non-register ops in this mode.
-  if (DumpOpts.PrintRegisterOnly) {
+  if (DumpOpts.printRegisterOnly()) {
     // First, try pretty-printing registers (existing behavior below also does
     // this, but we need to short-circuit here to avoid printing opcode names).
     if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) ||
@@ -145,7 +145,7 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
     return true; // suppress other opcodes silently in register-only mode
   }
 
-  if (!DumpOpts.PrintRegisterOnly) {
+  if (!DumpOpts.printRegisterOnly()) {
     StringRef Name = OperationEncodingString(Op->getCode());
     assert(!Name.empty() && "DW_OP has no name!");
     OS << Name;
@@ -167,7 +167,7 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
                               Op->getRawOperands()))
       return true;
 
-  if (!DumpOpts.PrintRegisterOnly) {
+  if (!DumpOpts.printRegisterOnly()) {
     for (unsigned Operand = 0; Operand < Op->getDescription().Op.size();
          ++Operand) {
       unsigned Size = Op->getDescription().Op[Operand];
@@ -224,14 +224,14 @@ void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS,
 
   for (auto &Op : *E) {
     DumpOpts.IsEH = IsEH;
-    if (!printOp(&Op, OS, DumpOpts, E, U) && !DumpOpts.PrintRegisterOnly) {
+    if (!printOp(&Op, OS, DumpOpts, E, U) && !DumpOpts.printRegisterOnly()) {
       uint64_t FailOffset = Op.getEndOffset();
       while (FailOffset < E->getData().size())
         OS << formatv(" {0:x-2}",
                       static_cast<uint8_t>(E->getData()[FailOffset++]));
       return;
     }
-    if (!DumpOpts.PrintRegisterOnly) {
+    if (!DumpOpts.printRegisterOnly()) {
       if (Op.getCode() == DW_OP_entry_value ||
           Op.getCode() == DW_OP_GNU_entry_value) {
         OS << "(";
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 6b8eed4e4266b..9ad5f9e0de374 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -1207,7 +1207,7 @@ DWARFVerifier::DWARFVerifier(raw_ostream &S, DWARFContext &D,
     : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)), IsObjectFile(false),
       IsMachOObject(false) {
   ErrorCategory.ShowDetail(this->DumpOpts.Verbose ||
-                           !this->DumpOpts.ShowAggregateErrors);
+                           !this->DumpOpts.showAggregateErrors());
   if (const auto *F = DCtx.getDWARFObj().getFile()) {
     IsObjectFile = F->isRelocatableObject();
     IsMachOObject = F->isMachO();
@@ -2389,7 +2389,7 @@ void OutputCategoryAggregator::EnumerateDetailedResultsFor(
 }
 
 void DWARFVerifier::summarize() {
-  if (DumpOpts.ShowAggregateErrors && ErrorCategory.GetNumCategories()) {
+  if (DumpOpts.showAggregateErrors() && ErrorCategory.GetNumCategories()) {
     error() << "Aggregated error counts:\n";
     ErrorCategory.EnumerateResults([&](StringRef s, unsigned count) {
       error() << formatv("{0} occurred {1} time(s).\n", s, count);
diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index eb3833dfdc9f2..5bc7b02755be8 100644
--- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -60,14 +60,14 @@ void JITEventListener::anchor() {}
 void ObjectCache::anchor() {}
 
 void ExecutionEngine::Init(std::unique_ptr<Module> M) {
-  CompilingLazily         = false;
-  GVCompilationDisabled   = false;
-  SymbolSearchingDisabled = false;
+  setCompilingLazily(false);
+  setGVCompilationDisabled(false);
+  setSymbolSearchingDisabled(false);
 
   // IR module verification is enabled by default in debug builds, and disabled
   // by default in release builds.
 #ifndef NDEBUG
-  VerifyModules = true;
+  setVerifyModulesFlag(true);
 #else
   VerifyModules = false;
 #endif
@@ -474,7 +474,7 @@ EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
 // IR module verification is enabled by default in debug builds, and disabled
 // by default in release builds.
 #ifndef NDEBUG
-  VerifyModules = true;
+  setVerifyModulesFlag(true);
 #else
   VerifyModules = false;
 #endif
@@ -538,7 +538,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
                                       std::move(Resolver), std::move(TheTM));
 
     if (EE) {
-      EE->setVerifyModules(VerifyModules);
+      EE->setVerifyModules(getVerifyModulesFlag());
       return EE;
     }
   }
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp
index cf662afe24fe6..0fe065f229986 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp
@@ -865,7 +865,7 @@ Expected<LibraryDepsInfo> parseELF(const object::ELFFile<ELFT> &Elf) {
     case ELF::DT_FLAGS_1:
       // Check if this is not a pie executable.
       if (Dyn.d_un.d_val & ELF::DF_1_PIE)
-        Deps.isPIE = true;
+        Deps.setIsPIE(true);
       break;
       // (Dyn.d_tag == ELF::DT_NULL) continue;
       // (Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER)
@@ -1008,7 +1008,7 @@ void LibraryScanner::handleLibrary(StringRef FilePath, PathType K, int level) {
       dbgs() << "     : " << r << "\n";
   });
 
-  if (Deps.isPIE && level == 0) {
+  if (Deps.getIsPIE() && level == 0) {
     LLVM_DEBUG(dbgs() << "  Skipped PIE executable at top level: " << FilePath
                       << "\n";);
 
diff --git a/llvm/lib/ExecutionEngine/TargetSelect.cpp b/llvm/lib/ExecutionEngine/TargetSelect.cpp
index bce90fc33d64f..a6020f7ad7f2c 100644
--- a/llvm/lib/ExecutionEngine/TargetSelect.cpp
+++ b/llvm/lib/ExecutionEngine/TargetSelect.cpp
@@ -37,9 +37,8 @@ TargetMachine *EngineBuilder::selectTarget() {
 /// selectTarget - Pick a target either via -march or by guessing the native
 /// arch.  Add any CPU features specified via -mcpu or -mattr.
 TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
-                              StringRef MArch,
-                              StringRef MCPU,
-                              const SmallVectorImpl<std::string>& MAttrs) {
+                                           StringRef MArch, StringRef MCPU,
+                                           ArrayRef<std::string> MAttrs) {
   Triple TheTriple(TargetTriple);
   if (TheTriple.getTriple().empty())
     TheTriple.setTriple(sys::getProcessTriple());
@@ -87,7 +86,7 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
   TargetMachine *Target = TheTarget->createTargetMachine(
       TheTriple, MCPU, FeaturesStr, Options, RelocModel, CMModel, OptLevel,
       /*JIT=*/true);
-  Target->Options.EmulatedTLS = EmulatedTLS;
+  Target->Options.EmulatedTLS = getEmulatedTLSFlag();
 
   assert(Target && "Could not allocate target machine!");
   return Target;
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 732b608362879..80c146fe96c13 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1025,7 +1025,7 @@ void OpenMPIRBuilder::finalize(Function *Fn) {
     if (OI->PostOutlineCB)
       OI->PostOutlineCB(*OutlinedFn);
 
-    if (OI->FixUpNonEntryAllocas)
+    if (OI->getFixUpNonEntryAllocas())
       hoistNonEntryAllocasToEntryBlock(OutlinedFn);
   }
 
@@ -1076,10 +1076,10 @@ void OpenMPIRBuilder::finalize(Function *Fn) {
     emitUsed("llvm.compiler.used", LLVMCompilerUsed);
   }
 
-  IsFinalized = true;
+  setIsFinalized(true);
 }
 
-bool OpenMPIRBuilder::isFinalized() { return IsFinalized; }
+bool OpenMPIRBuilder::isFinalized() { return getIsFinalized(); }
 
 void OpenMPIRBuilder::registerDeclareTargetGlobalReplacement(
     GlobalValue *Original, GlobalValue *Replacement) {
@@ -2113,7 +2113,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createParallel(
     };
   }
 
-  OI->FixUpNonEntryAllocas = true;
+  OI->setFixUpNonEntryAllocas(true);
   OI->OuterAllocBB = OuterAllocaBlock;
   OI->EntryBB = PRegEntryBB;
   OI->ExitBB = PRegExitBB;
@@ -11772,7 +11772,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
     Value *OldValue = nullptr;
     Value *SuccessOrFail = nullptr;
 
-    if (!IsInteger && HandleFPNegZero) {
+    if (!IsInteger && getHandleFPNegZeroFlag()) {
       // IEEE 754 special cases for cmpxchg (which is bitwise):
       //   1. -0.0 == +0.0 but they have different bit patterns.
       //   2. NaN != NaN but identical NaN bit patterns would match.
@@ -11966,7 +11966,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createAtomicCompare(
 
     // For the HandleFPNegZero path, handle V.Var and R.Var using the
     // pre-computed OldValue and SuccessOrFail.
-    if (HandleFPNegZero && !IsInteger) {
+    if (getHandleFPNegZeroFlag() && !IsInteger) {
       if (V.Var) {
         assert(OldValue->getType() == V.ElemTy &&
                "OldValue and V must be of same type");
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 1cbcfb195764b..9062069c5bf2e 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
@@ -2986,12 +2987,14 @@ class AssemblyWriter {
   SlotTracker &Machine;
   TypePrinting TypePrinter;
   AssemblyAnnotationWriter *AnnotationWriter = nullptr;
-  bool IsForDebug;
-  bool ShouldPreserveUseListOrder;
+  bool getIsForDebug() const { return SSNs.getFlag(0); }
+  void setIsForDebug(bool Value) { SSNs.setFlag(0, Value); }
+  bool getShouldPreserveUseListOrder() const { return SSNs.getFlag(1); }
+  void setShouldPreserveUseListOrder(bool Value) { SSNs.setFlag(1, Value); }
   UseListOrderMap UseListOrders;
   SmallVector<StringRef, 8> MDNames;
   /// Synchronization scope names registered with LLVMContext.
-  SmallVector<StringRef, 8> SSNs;
+  llvm::SmallVectorWithFlags<StringRef, 8, 2> SSNs;
   DenseMap<const GlobalValueSummary *, GlobalValue::GUID> SummaryToGUIDMap;
 
 public:
@@ -3089,17 +3092,19 @@ AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
                                const Module *M, AssemblyAnnotationWriter *AAW,
                                bool IsForDebug, bool ShouldPreserveUseListOrder)
     : Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
-      IsForDebug(IsForDebug),
-      ShouldPreserveUseListOrder(
-          PreserveAssemblyUseListOrder.getNumOccurrences()
-              ? PreserveAssemblyUseListOrder
-              : ShouldPreserveUseListOrder) {}
+      SSNs(decltype(this->SSNs)::withFlags(
+          unsigned(IsForDebug) |
+          (unsigned(bool(PreserveAssemblyUseListOrder.getNumOccurrences()
+                             ? PreserveAssemblyUseListOrder
+                             : ShouldPreserveUseListOrder))
+           << 1))) {}
 
 AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
                                const ModuleSummaryIndex *Index, bool IsForDebug)
     : Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
-      IsForDebug(IsForDebug),
-      ShouldPreserveUseListOrder(PreserveAssemblyUseListOrder) {}
+      SSNs(decltype(this->SSNs)::withFlags(
+          unsigned(IsForDebug) |
+          (unsigned(bool(PreserveAssemblyUseListOrder)) << 1))) {}
 
 void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
   if (!Operand) {
@@ -3117,8 +3122,11 @@ void AssemblyWriter::writeSyncScope(const LLVMContext &Context,
     break;
   }
   default: {
-    if (SSNs.empty())
-      Context.getSyncScopeNames(SSNs);
+    if (SSNs.empty()) {
+      SmallVector<StringRef, 8> Names;
+      Context.getSyncScopeNames(Names);
+      SSNs.assign(std::move(Names));
+    }
 
     Out << " syncscope(\"";
     printEscapedString(SSNs[SSID], Out);
@@ -3205,7 +3213,7 @@ void AssemblyWriter::writeOperandBundles(const CallBase *Call) {
 void AssemblyWriter::printModule(const Module *M) {
   Machine.initializeIfNeeded();
 
-  if (ShouldPreserveUseListOrder)
+  if (getShouldPreserveUseListOrder())
     UseListOrders = predictUseListOrder(M);
 
   if (!M->getModuleIdentifier().empty() &&
@@ -4296,7 +4304,7 @@ void AssemblyWriter::printFunction(const Function *F) {
   Out << '(';
 
   // Loop over the arguments, printing them...
-  if (F->isDeclaration() && !IsForDebug) {
+  if (F->isDeclaration() && !getIsForDebug()) {
     // We're only interested in the type here - don't print argument names.
     ListSeparator LS;
     for (unsigned I = 0, E = FT->getNumParams(); I != E; ++I) {
@@ -5097,8 +5105,11 @@ void AssemblyWriter::printMetadataAttachments(
   if (MDs.empty())
     return;
 
-  if (MDNames.empty())
-    MDs[0].second->getContext().getMDKindNames(MDNames);
+  if (MDNames.empty()) {
+    SmallVector<StringRef, 8> Names;
+    MDs[0].second->getContext().getMDKindNames(Names);
+    MDNames.assign(std::move(Names));
+  }
 
   auto WriterCtx = getContext();
   for (const auto &I : MDs) {
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 37791652a4375..7baeb89de176e 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -24,8 +24,8 @@ using namespace llvm;
 using namespace llvm::dwarf;
 
 DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU)
-    : M(m), VMContext(M.getContext()), CUNode(CU),
-      AllowUnresolvedNodes(AllowUnresolvedNodes) {
+    : M(m), VMContext(M.getContext()), CUNode(CU) {
+  UnresolvedNodes.setFlag(0, AllowUnresolvedNodes);
   if (CUNode) {
     if (const auto &ETs = CUNode->getEnumTypes())
       EnumTypes.assign(ETs.begin(), ETs.end());
@@ -46,7 +46,7 @@ void DIBuilder::trackIfUnresolved(MDNode *N) {
   if (N->isResolved())
     return;
 
-  assert(AllowUnresolvedNodes && "Cannot handle unresolved nodes");
+  assert(UnresolvedNodes.getFlag(0) && "Cannot handle unresolved nodes");
   UnresolvedNodes.emplace_back(N);
 }
 
@@ -72,7 +72,7 @@ void DIBuilder::finalizeSubprogram(DISubprogram *SP) {
 
 void DIBuilder::finalize() {
   if (!CUNode) {
-    assert(!AllowUnresolvedNodes &&
+    assert(!UnresolvedNodes.getFlag(0) &&
            "creating type nodes without a CU is not supported");
     return;
   }
@@ -131,7 +131,7 @@ void DIBuilder::finalize() {
   UnresolvedNodes.clear();
 
   // Can't handle unresolved nodes anymore.
-  AllowUnresolvedNodes = false;
+  UnresolvedNodes.setFlag(0, false);
 }
 
 /// If N is compile unit return NULL otherwise return N.
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 82b33887b81f2..05c4ee5cd1cb2 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -207,8 +207,6 @@ DataLayout &DataLayout::operator=(const DataLayout &Other) {
   delete static_cast<StructLayoutMap *>(LayoutMap);
   LayoutMap = nullptr;
   StringRepresentation = Other.StringRepresentation;
-  BigEndian = Other.BigEndian;
-  VectorsAreElementAligned = Other.VectorsAreElementAligned;
   AllocaAddrSpace = Other.AllocaAddrSpace;
   ProgramAddrSpace = Other.ProgramAddrSpace;
   DefaultGlobalsAddrSpace = Other.DefaultGlobalsAddrSpace;
@@ -228,9 +226,7 @@ DataLayout &DataLayout::operator=(const DataLayout &Other) {
 
 bool DataLayout::operator==(const DataLayout &Other) const {
   // NOTE: StringRepresentation might differ, it is not canonicalized.
-  return BigEndian == Other.BigEndian &&
-         VectorsAreElementAligned == Other.VectorsAreElementAligned &&
-         AllocaAddrSpace == Other.AllocaAddrSpace &&
+  return AllocaAddrSpace == Other.AllocaAddrSpace &&
          ProgramAddrSpace == Other.ProgramAddrSpace &&
          DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace &&
          StackNaturalAlign == Other.StackNaturalAlign &&
@@ -551,7 +547,7 @@ Error DataLayout::parseSpecification(
   }
 
   if (Spec == "ve") {
-    VectorsAreElementAligned = true;
+    LegalIntWidths.setFlag(1, true);
     return Error::success();
   }
 
@@ -579,7 +575,7 @@ Error DataLayout::parseSpecification(
     if (!Rest.empty())
       return createStringError(
           "malformed specification, must be just 'e' or 'E'");
-    BigEndian = Specifier == 'E';
+    LegalIntWidths.setFlag(0, Specifier == 'E');
     break;
   case 'n': // Native integer types.
     // n<size>[:<size>]...
diff --git a/llvm/lib/IR/DroppedVariableStats.cpp b/llvm/lib/IR/DroppedVariableStats.cpp
index b8c0dd6e7b1dc..456367c6aaa07 100644
--- a/llvm/lib/IR/DroppedVariableStats.cpp
+++ b/llvm/lib/IR/DroppedVariableStats.cpp
@@ -19,7 +19,8 @@
 using namespace llvm;
 
 DroppedVariableStats::DroppedVariableStats(bool DroppedVarStatsEnabled)
-    : DroppedVariableStatsEnabled(DroppedVarStatsEnabled) {
+    : InlinedAts(decltype(this->InlinedAts)::withFlags(
+          unsigned(DroppedVarStatsEnabled))) {
   if (DroppedVarStatsEnabled)
     llvm::outs() << "Pass Level, Pass Name, Num of Dropped Variables, Func or "
                     "Module Name\n";
@@ -62,9 +63,9 @@ void DroppedVariableStats::calculateDroppedStatsAndPrint(
   if (DroppedCount > 0) {
     llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", "
                  << FuncOrModName << "\n";
-    PassDroppedVariables = true;
+    setPassDroppedVariablesFlag(true);
   } else
-    PassDroppedVariables = false;
+    setPassDroppedVariablesFlag(false);
 }
 
 bool DroppedVariableStats::updateDroppedCount(
diff --git a/llvm/lib/IR/DroppedVariableStatsIR.cpp b/llvm/lib/IR/DroppedVariableStatsIR.cpp
index d07bfd6f4390e..c86974c781a1a 100644
--- a/llvm/lib/IR/DroppedVariableStatsIR.cpp
+++ b/llvm/lib/IR/DroppedVariableStatsIR.cpp
@@ -82,7 +82,7 @@ void DroppedVariableStatsIR::calculateDroppedVarStatsOnModule(
 
 void DroppedVariableStatsIR::registerCallbacks(
     PassInstrumentationCallbacks &PIC) {
-  if (!DroppedVariableStatsEnabled)
+  if (!getDroppedVariableStatsEnabled())
     return;
 
   PIC.registerBeforeNonSkippedPassCallback(
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index fb3b4bd8b206f..c5df6978d273b 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -126,30 +126,30 @@ void LLVMContext::setDiagnosticHandlerCallBack(
     void *DiagnosticContext, bool RespectFilters) {
   pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler;
   pImpl->DiagHandler->DiagnosticContext = DiagnosticContext;
-  pImpl->RespectDiagnosticFilters = RespectFilters;
+  pImpl->setRespectDiagnosticFilters(RespectFilters);
 }
 
 void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH,
                                       bool RespectFilters) {
   pImpl->DiagHandler = std::move(DH);
-  pImpl->RespectDiagnosticFilters = RespectFilters;
+  pImpl->setRespectDiagnosticFilters(RespectFilters);
 }
 
 void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) {
-  pImpl->DiagnosticsHotnessRequested = Requested;
+  pImpl->setDiagnosticsHotnessRequested(Requested);
 }
 bool LLVMContext::getDiagnosticsHotnessRequested() const {
-  return pImpl->DiagnosticsHotnessRequested;
+  return pImpl->getDiagnosticsHotnessRequested();
 }
 
 void LLVMContext::setDiagnosticsHotnessThreshold(std::optional<uint64_t> Threshold) {
   pImpl->DiagnosticsHotnessThreshold = Threshold;
 }
 void LLVMContext::setMisExpectWarningRequested(bool Requested) {
-  pImpl->MisExpectWarningRequested = Requested;
+  pImpl->setMisExpectWarningRequested(Requested);
 }
 bool LLVMContext::getMisExpectWarningRequested() const {
-  return pImpl->MisExpectWarningRequested;
+  return pImpl->getMisExpectWarningRequested();
 }
 uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
   return pImpl->DiagnosticsHotnessThreshold.value_or(UINT64_MAX);
@@ -256,7 +256,7 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
   if (pImpl->DiagHandler) {
     if (DI.getSeverity() == DS_Error)
       pImpl->DiagHandler->HasErrors = true;
-    if ((!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) &&
+    if ((!pImpl->getRespectDiagnosticFilters() || isDiagnosticEnabled(DI)) &&
         pImpl->DiagHandler->handleDiagnostics(DI))
       return;
   }
@@ -331,7 +331,7 @@ void LLVMContext::deleteGC(const Function &Fn) {
 }
 
 bool LLVMContext::shouldDiscardValueNames() const {
-  return pImpl->DiscardValueNames;
+  return pImpl->getDiscardValueNames();
 }
 
 bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; }
@@ -346,7 +346,7 @@ void LLVMContext::enableDebugTypeODRUniquing() {
 void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }
 
 void LLVMContext::setDiscardValueNames(bool Discard) {
-  pImpl->DiscardValueNames = Discard;
+  pImpl->setDiscardValueNames(Discard);
 }
 
 OptPassGate &LLVMContext::getOptPassGate() const {
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index d02d57e4c0197..394a01fe75b5f 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -27,6 +27,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/Constants.h"
@@ -1661,8 +1662,12 @@ class LLVMContextImpl {
   std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;
 
   std::unique_ptr<DiagnosticHandler> DiagHandler;
-  bool RespectDiagnosticFilters = false;
-  bool DiagnosticsHotnessRequested = false;
+  bool getRespectDiagnosticFilters() const { return Metadatas.getFlag(0); }
+  void setRespectDiagnosticFilters(bool Value) { Metadatas.setFlag(0, Value); }
+  bool getDiagnosticsHotnessRequested() const { return Metadatas.getFlag(1); }
+  void setDiagnosticsHotnessRequested(bool Value) {
+    Metadatas.setFlag(1, Value);
+  }
   /// The minimum hotness value a diagnostic needs in order to be included in
   /// optimization diagnostics.
   ///
@@ -1686,7 +1691,8 @@ class LLVMContextImpl {
   /// The percentage of difference between profiling branch weights and
   /// llvm.expect branch weights to tolerate when emiting MisExpect diagnostics
   std::optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
-  bool MisExpectWarningRequested = false;
+  bool getMisExpectWarningRequested() const { return Metadatas.getFlag(2); }
+  void setMisExpectWarningRequested(bool Value) { Metadatas.setFlag(2, Value); }
 
   /// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
   std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
@@ -1845,7 +1851,7 @@ class LLVMContextImpl {
   StringMap<unsigned> CustomMDKindNames;
 
   /// Collection of metadata attachments in this context.
-  SmallVector<MDAttachment, 0> Metadatas;
+  llvm::SmallVectorWithFlags<MDAttachment, 0, 4> Metadatas;
   /// Index of first free Metadatas entry, linked list via MDAttachment::Next.
   unsigned MetadataRecycleHead = 0;
   /// Number of currently unused metadata entries. Only used/updated in debug
@@ -1903,7 +1909,8 @@ class LLVMContextImpl {
 
   /// Flag to indicate if Value (other than GlobalValue) retains their name or
   /// not.
-  bool DiscardValueNames = false;
+  bool getDiscardValueNames() const { return Metadatas.getFlag(3); }
+  void setDiscardValueNames(bool Value) { Metadatas.setFlag(3, Value); }
 
   LLVMContextImpl(LLVMContext &C);
   ~LLVMContextImpl();
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp
index d33d6bdd32030..aea7c3ef71b73 100644
--- a/llvm/lib/IR/LegacyPassManager.cpp
+++ b/llvm/lib/IR/LegacyPassManager.cpp
@@ -1201,7 +1201,7 @@ void PMDataManager::dumpUsedSet(const Pass *P) const {
 }
 
 void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P,
-                                   const AnalysisUsage::VectorType &Set) const {
+                                      ArrayRef<AnalysisID> Set) const {
   assert(PassDebugging >= Details);
   if (Set.empty())
     return;
diff --git a/llvm/lib/IR/PassTimingInfo.cpp b/llvm/lib/IR/PassTimingInfo.cpp
index 3c5b85d3d691e..8492886198377 100644
--- a/llvm/lib/IR/PassTimingInfo.cpp
+++ b/llvm/lib/IR/PassTimingInfo.cpp
@@ -167,7 +167,7 @@ void llvm::reportAndResetTimings(raw_ostream *OutStream) {
 /// Each time it creates a new timer.
 Timer &TimePassesHandler::getPassTimer(StringRef PassID, bool IsPass) {
   TimerGroup &TG = IsPass ? PassTG : AnalysisTG;
-  if (!PerRun) {
+  if (!getPerRun()) {
     TimerVector &Timers = TimingData[PassID];
     if (Timers.size() == 0)
       Timers.emplace_back(new Timer(PassID, PassID, TG));
@@ -189,7 +189,8 @@ Timer &TimePassesHandler::getPassTimer(StringRef PassID, bool IsPass) {
 }
 
 TimePassesHandler::TimePassesHandler(bool Enabled, bool PerRun)
-    : Enabled(Enabled), PerRun(PerRun) {}
+    : AnalysisActiveTimerStack(decltype(AnalysisActiveTimerStack)::withFlags(
+          unsigned(Enabled) | (unsigned(PerRun) << 1))) {}
 
 TimePassesHandler::TimePassesHandler()
     : TimePassesHandler(TimePassesIsEnabled, TimePassesPerRun) {}
@@ -199,7 +200,7 @@ void TimePassesHandler::setOutStream(raw_ostream &Out) {
 }
 
 void TimePassesHandler::print() {
-  if (!Enabled)
+  if (!getEnabled())
     return;
   std::unique_ptr<raw_ostream> MaybeCreated;
   raw_ostream *OS = OutStream;
@@ -303,7 +304,7 @@ void TimePassesHandler::stopAnalysisTimer(StringRef PassID) {
 }
 
 void TimePassesHandler::registerCallbacks(PassInstrumentationCallbacks &PIC) {
-  if (!Enabled)
+  if (!getEnabled())
     return;
 
   PIC.registerBeforeNonSkippedPassCallback(
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index ee4ef7d1dd53d..f94572b50aed3 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -57,6 +57,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -178,10 +179,12 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
 
   /// Whether we've seen a call to @llvm.localescape in this function
   /// already.
-  bool SawFrameEscape;
+  bool getSawFrameEscape() const { return NoAliasScopeDecls.getFlag(0); }
+  void setSawFrameEscape(bool Value) { NoAliasScopeDecls.setFlag(0, Value); }
 
   /// Whether the current function has a DISubprogram attached to it.
-  bool HasDebugInfo = false;
+  bool getHasDebugInfo() const { return NoAliasScopeDecls.getFlag(1); }
+  void setHasDebugInfo(bool Value) { NoAliasScopeDecls.setFlag(1, Value); }
 
   /// Stores the count of how many objects were passed to llvm.localescape for a
   /// given function and the largest index passed to llvm.localrecover.
@@ -216,7 +219,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   TBAAVerifier TBAAVerifyHelper;
   ConvergenceVerifier ConvergenceVerifyHelper;
 
-  SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls;
+  llvm::SmallVectorWithFlags<IntrinsicInst *, 4, 2> NoAliasScopeDecls;
 
   void checkAtomicMemAccessSize(Type *Ty, const Instruction *I);
 
@@ -224,7 +227,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError,
                     const Module &M)
       : VerifierSupport(OS, M), LandingPadResultTy(nullptr),
-        SawFrameEscape(false), TBAAVerifyHelper(this) {
+        TBAAVerifyHelper(this) {
     TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError;
   }
 
@@ -277,7 +280,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
     DebugFnArgs.clear();
     DIScopeChainReachesCycle.clear();
     LandingPadResultTy = nullptr;
-    SawFrameEscape = false;
+    setSawFrameEscape(false);
     SiblingFuncletInfo.clear();
     verifyNoAliasScopeDecl();
     NoAliasScopeDecls.clear();
@@ -3542,8 +3545,8 @@ void Verifier::visitFunction(const Function &F) {
   }
 
   auto *N = F.getSubprogram();
-  HasDebugInfo = (N != nullptr);
-  if (!HasDebugInfo)
+  setHasDebugInfo((N != nullptr));
+  if (!getHasDebugInfo())
     return;
 
   // Check that all !dbg attachments lead to back to N.
@@ -6675,8 +6678,8 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     BasicBlock *BB = Call.getParent();
     Check(BB->isEntryBlock(), "llvm.localescape used outside of entry block",
           Call);
-    Check(!SawFrameEscape, "multiple calls to llvm.localescape in one function",
-          Call);
+    Check(!getSawFrameEscape(),
+          "multiple calls to llvm.localescape in one function", Call);
     for (Value *Arg : Call.args()) {
       if (isa<ConstantPointerNull>(Arg))
         continue; // Null values are allowed as placeholders.
@@ -6685,7 +6688,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
             "llvm.localescape only accepts static allocas", Call);
     }
     FrameEscapeInfo[BB->getParent()].first = Call.arg_size();
-    SawFrameEscape = true;
+    setSawFrameEscape(true);
     break;
   }
   case Intrinsic::localrecover: {
@@ -7839,7 +7842,7 @@ void Verifier::verifyFnArgs(const DbgVariableRecord &DVR) {
   // This function does not take the scope of noninlined function arguments into
   // account. Don't run it if current function is nodebug, because it may
   // contain inlined debug intrinsics.
-  if (!HasDebugInfo)
+  if (!getHasDebugInfo())
     return;
 
   // For performance reasons only check non-inlined ones.
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 50232bf87d257..a19d0158d42da 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -652,7 +652,7 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
   }
 
   File->Mods = FOrErr->Mods;
-  File->Strtab = std::move(FOrErr->Strtab);
+  File->Strtab.assign(std::move(FOrErr->Strtab));
   return std::move(File);
 }
 
@@ -826,7 +826,7 @@ static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
 Error LTO::add(std::unique_ptr<InputFile> InputPtr,
                ArrayRef<SymbolResolution> Res) {
   llvm::TimeTraceScope timeScope("LTO add input", InputPtr->getName());
-  assert(!CalledGetMaxTasks);
+  assert(!getCalledGetMaxTasks());
 
   Expected<std::shared_ptr<InputFile>> InputOrErr =
       addInput(std::move(InputPtr));
@@ -893,7 +893,7 @@ LTO::addModule(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
   // If any of the modules inside of a input bitcode file was compiled with
   // ThinLTO, we assume that the whole input file also was compiled with
   // ThinLTO.
-  Input.IsThinLTO |= IsThinLTO;
+  Input.setIsThinLTO(Input.getIsThinLTO() | (IsThinLTO));
 
   auto ModSyms = Input.module_symbols(ModI);
   addModuleToGlobalRes(ModSyms, Res,
@@ -1267,7 +1267,7 @@ LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
 }
 
 unsigned LTO::getMaxTasks() const {
-  CalledGetMaxTasks = true;
+  setCalledGetMaxTasks(true);
   auto ModuleCount = ThinLTO.ModulesToCompile ? ThinLTO.ModulesToCompile->size()
                                               : ThinLTO.ModuleMap.size();
   return RegularLTO.ParallelCodeGenParallelismLevel + ModuleCount;
@@ -2322,7 +2322,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
   LLVM_DEBUG(dbgs() << "[TwoRounds] Running the first round of codegen\n");
   auto FirstRoundLTO = std::make_unique<FirstRoundThinBackend>(
       Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
-      CG.AddStream, CG.Cache, BitcodeLibFuncs, IR.AddStream, IR.Cache);
+      CG.AddStream, CG.Cache, ArrayRef<StringRef>(BitcodeLibFuncs),
+      IR.AddStream, IR.Cache);
   if (Error E = RunBackends(FirstRoundLTO.get()))
     return E;
 
@@ -2338,7 +2339,8 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
   LLVM_DEBUG(dbgs() << "[TwoRounds] Running the second round of codegen\n");
   auto SecondRoundLTO = std::make_unique<SecondRoundThinBackend>(
       Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
-      AddStream, Cache, BitcodeLibFuncs, IR.getResult(), CombinedHash);
+      AddStream, Cache, ArrayRef<StringRef>(BitcodeLibFuncs), IR.getResult(),
+      CombinedHash);
   return RunBackends(SecondRoundLTO.get());
 }
 
diff --git a/llvm/lib/MC/DXContainerInfo.cpp b/llvm/lib/MC/DXContainerInfo.cpp
index 909207b39ee17..d747f4db324cd 100644
--- a/llvm/lib/MC/DXContainerInfo.cpp
+++ b/llvm/lib/MC/DXContainerInfo.cpp
@@ -199,7 +199,7 @@ template <typename VecT> static void clearAndReserve(VecT &Vec, size_t N) {
 }
 
 void SourceInfoBuilder::computeEntries() {
-  IsFilled = true;
+  setIsFilled(true);
   clearAndReserve(BaseData.Names.Entries, FileNamesAndContents.size());
   clearAndReserve(BaseData.Contents.Entries, FileNamesAndContents.size());
   for (const auto &NameContent : FileNamesAndContents) {
@@ -226,11 +226,11 @@ void SourceInfoBuilder::recomputeAfterCompression(uint32_t CompressedSize) {
 }
 
 void SourceInfoBuilder::finalize() {
-  assert(IsFilled && "SourceInfo::computeEntries() must be called before "
-                     "SourceInfo::computeUncompressed()");
+  assert(getIsFilled() && "SourceInfo::computeEntries() must be called before "
+                          "SourceInfo::computeUncompressed()");
   assert(CompressionType && "Compression type must be set.");
 
-  IsFinalized = true;
+  setIsFinalized(true);
 
   BaseData.Contents.computeUncompressed(*CompressionType);
   BaseData.Names.compute();
@@ -279,7 +279,7 @@ void SourceInfoBuilder::finalize() {
 }
 
 void SourceInfoBuilder::write(raw_ostream &OS) const {
-  assert(IsFinalized &&
+  assert(getIsFinalized() &&
          "SourceInfo::finalize() must be called before SourceInfo::write()");
 
   writeStruct(OS, BaseData.Parameters);
diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp
index a6aa556535b48..5577801660698 100644
--- a/llvm/lib/MC/DXContainerPSVInfo.cpp
+++ b/llvm/lib/MC/DXContainerPSVInfo.cpp
@@ -48,7 +48,7 @@ ProcessElementList(StringTableBuilder &StrTabBuilder,
     FinalElement.StartRow = El.StartRow;
     FinalElement.Cols = El.Cols;
     FinalElement.StartCol = El.StartCol;
-    FinalElement.Allocated = El.Allocated;
+    FinalElement.Allocated = El.getAllocated();
     FinalElement.Kind = El.Kind;
     FinalElement.Type = El.Type;
     FinalElement.Mode = El.Mode;
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index db4aa48138e04..10e07efbb8de2 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -89,9 +89,9 @@ MCAssembler::MCAssembler(MCContext &Context,
 }
 
 void MCAssembler::reset() {
-  HasLayout = false;
-  HasFinalLayout = false;
-  RelaxAll = false;
+  setHasLayout(false);
+  setHasFinalLayout(false);
+  setRelaxAllFlag(false);
   BundleAlign.reset();
   Sections.clear();
   Symbols.clear();
@@ -338,7 +338,7 @@ uint64_t MCAssembler::getSymbolOffset(const MCSymbol &S) const {
 }
 
 const MCSymbol *MCAssembler::getBaseSymbol(const MCSymbol &Symbol) const {
-  assert(HasLayout);
+  assert(getHasLayout());
   if (!Symbol.isVariable())
     return &Symbol;
 
@@ -373,7 +373,7 @@ const MCSymbol *MCAssembler::getBaseSymbol(const MCSymbol &Symbol) const {
 
 uint64_t MCAssembler::getSectionAddressSize(const MCSection &Sec) const {
   const MCFragment &F = *Sec.curFragList()->Tail;
-  assert(HasLayout && F.getKind() == MCFragment::FT_Data);
+  assert(getHasLayout() && F.getKind() == MCFragment::FT_Data);
   return getFragmentOffset(F) + F.getSize();
 }
 
@@ -697,7 +697,7 @@ void MCAssembler::layout() {
   }
 
   // Layout until everything fits.
-  this->HasLayout = true;
+  this->setHasLayout(true);
   for (MCSection &Sec : *this)
     layoutSection(Sec);
   unsigned FirstStable = Sections.size();
@@ -726,7 +726,7 @@ void MCAssembler::layout() {
 
   // Fragment sizes are finalized. For RISC-V linker relaxation, this flag
   // helps check whether a PC-relative fixup is fully resolved.
-  this->HasFinalLayout = true;
+  this->setHasFinalLayout(true);
 
   // Stores the current .reloc group for each fragment.
   //
@@ -810,7 +810,7 @@ void MCAssembler::Finish() {
   if (!getContext().hadError())
     stats::ObjectBytes += getWriter().writeObject();
 
-  HasLayout = false;
+  setHasLayout(false);
   assert(PendingErrors.empty());
 }
 
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index 335934a7793e4..9254c039e7a92 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -226,7 +226,7 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
 
   OS.emitLabel(FileEnd);
 
-  ChecksumOffsetsAssigned = true;
+  setChecksumOffsetsAssigned(true);
 }
 
 // Output checksum table offset of the given file number.  It is possible that
@@ -240,7 +240,7 @@ void CodeViewContext::emitFileChecksumOffset(MCObjectStreamer &OS,
   if (Idx >= Files.size())
     Files.resize(Idx + 1);
 
-  if (ChecksumOffsetsAssigned) {
+  if (getChecksumOffsetsAssigned()) {
     OS.emitSymbolValue(Files[Idx].ChecksumTableOffset, 4);
     return;
   }
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 935b0888bf693..35c05900fb0d4 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -70,8 +70,8 @@ MCContext::MCContext(const Triple &TheTriple, const MCAsmInfo &mai,
       SrcMgr(mgr), InlineSrcMgr(nullptr), DiagHandler(defaultDiagHandler),
       MAI(mai), MRI(&mri), MSTI(&msti), Symbols(Allocator),
       InlineAsmUsedLabelNames(Allocator),
-      CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
-      AutoReset(DoAutoReset) {
+      CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0) {
+  DebugPrefixMap.setFlag(2, DoAutoReset);
   const MCTargetOptions &TO = getTargetOptions();
   SaveTempLabels = TO.MCSaveTempLabels;
   if (SaveTempLabels)
@@ -123,7 +123,7 @@ const MCTargetOptions &MCContext::getTargetOptions() const {
 }
 
 MCContext::~MCContext() {
-  if (AutoReset)
+  if (DebugPrefixMap.getFlag(2))
     reset();
 
   // NOTE: The symbols are all allocated out of a bump pointer allocator,
@@ -190,7 +190,7 @@ void MCContext::reset() {
   GenDwarfForAssembly = false;
   GenDwarfFileNumber = 0;
 
-  HadError = false;
+  DebugPrefixMap.setFlag(3, false);
 }
 
 //===----------------------------------------------------------------------===//
@@ -363,7 +363,7 @@ MCSymbol *MCContext::createRenamableSymbol(const Twine &Name,
 }
 
 MCSymbol *MCContext::createTempSymbol(const Twine &Name, bool AlwaysAddSuffix) {
-  if (!UseNamesOnTempLabels)
+  if (!DebugPrefixMap.getFlag(1))
     return createSymbolImpl(nullptr, /*IsTemporary=*/true);
   return createRenamableSymbol(MAI.getInternalSymbolPrefix() + Name,
                                AlwaysAddSuffix, /*IsTemporary=*/true);
@@ -379,7 +379,7 @@ MCSymbol *MCContext::createBlockSymbol(const Twine &Name, bool AlwaysEmit) {
     return getOrCreateSymbol(MAI.getInternalSymbolPrefix() + Name);
 
   bool IsTemporary = !SaveTempLabels;
-  if (IsTemporary && !UseNamesOnTempLabels)
+  if (IsTemporary && !DebugPrefixMap.getFlag(1))
     return createSymbolImpl(nullptr, IsTemporary);
   return createRenamableSymbol(MAI.getInternalSymbolPrefix() + Name,
                                /*AlwaysAddSuffix=*/false, IsTemporary);
@@ -1082,7 +1082,7 @@ CodeViewContext &MCContext::getCVContext() {
 void MCContext::diagnose(const SMDiagnostic &SMD) {
   assert(DiagHandler && "MCContext::DiagHandler is not set");
   if (SMD.getKind() == SourceMgr::DK_Error)
-    HadError = true;
+    DebugPrefixMap.setFlag(3, true);
   bool UseInlineSrcMgr = false;
   const SourceMgr *SMP = nullptr;
   if (SrcMgr) {
@@ -1127,7 +1127,7 @@ void MCContext::reportCommon(
 }
 
 void MCContext::reportError(SMLoc Loc, const Twine &Msg) {
-  HadError = true;
+  DebugPrefixMap.setFlag(3, true);
   reportCommon(Loc, [&](SMDiagnostic &D, const SourceMgr *SMP) {
     D = SMP->GetMessage(Loc, SourceMgr::DK_Error, Msg);
   });
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index da8e057f0f9ee..476f5e9b14e8a 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -511,9 +511,9 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
   // directory index.  We don't track file size/timestamp so don't emit them
   // in the v5 table.  Emit MD5 checksums and source if we have them.
   uint64_t Entries = 2;
-  if (HasAllMD5)
+  if (!MCDwarfDirs.getFlag(1))
     Entries += 1;
-  if (HasAnySource)
+  if (hasAnySource())
     Entries += 1;
   MCOS->emitInt8(Entries);
   MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
@@ -521,11 +521,11 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
                                     : dwarf::DW_FORM_string);
   MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
   MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);
-  if (HasAllMD5) {
+  if (!MCDwarfDirs.getFlag(1)) {
     MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
     MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
   }
-  if (HasAnySource) {
+  if (hasAnySource()) {
     MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
     MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
                                       : dwarf::DW_FORM_string);
@@ -540,9 +540,10 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
   assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
          "No root file and no .file directives");
   emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
-                     HasAllMD5, HasAnySource, LineStr);
+                     !MCDwarfDirs.getFlag(1), hasAnySource(), LineStr);
   for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
-    emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasAnySource, LineStr);
+    emitOneV5FileEntry(MCOS, MCDwarfFiles[i], !MCDwarfDirs.getFlag(1),
+                       hasAnySource(), LineStr);
 }
 
 std::pair<MCSymbol *, MCSymbol *>
@@ -659,7 +660,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
   // If any files have embedded source, they all must.
   if (MCDwarfFiles.empty()) {
     trackMD5Usage(Checksum.has_value());
-    HasAnySource |= Source.has_value();
+    trackSource(Source.has_value());
   }
   if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
     return 0;
@@ -719,7 +720,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
   trackMD5Usage(Checksum.has_value());
   File.Source = Source;
   if (Source.has_value())
-    HasAnySource = true;
+    trackSource(true);
 
   // return the allocated FileNumber.
   return FileNumber;
@@ -1059,7 +1060,7 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
 
   // AT_name, the name of the source file.  Reconstruct from the first directory
   // and file table entries.
-  const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
+  ArrayRef<std::string> MCDwarfDirs = context.getMCDwarfDirs();
   if (MCDwarfDirs.size() > 0) {
     MCOS->emitBytes(MCDwarfDirs[0]);
     MCOS->emitBytes(sys::path::get_separator());
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index efe08d7e09a84..5a01079505b87 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -86,7 +86,7 @@ void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
     getContext().reportError(
         getStartTokLoc(), "unterminated .bundle_lock when changing a section");
     // Clean up bundle state to allow continuing.
-    BundleLocked = false;
+    setBundleLocked(false);
     BundleBA = nullptr;
   }
   auto *SectionELF = static_cast<const MCSectionELF *>(Section);
@@ -316,9 +316,9 @@ void MCELFStreamer::emitIdent(StringRef IdentString) {
       ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1);
   pushSection();
   switchSection(Comment);
-  if (!SeenIdent) {
+  if (!getSeenIdent()) {
     emitInt8(0);
-    SeenIdent = true;
+    setSeenIdent(true);
   }
   emitBytes(IdentString);
   emitInt8(0);
@@ -363,7 +363,7 @@ void MCELFStreamer::emitBundleLock(bool AlignToEnd,
     return getContext().reportError(
         Loc, ".bundle_lock is only allowed in an executable section");
 
-  BundleLocked = true;
+  setBundleLocked(true);
   BundleBA =
       newSpecialFragment<MCBoundaryAlignFragment>(Asm.getBundleAlign(), STI);
   BundleBA->setAlignToEnd(AlignToEnd);
@@ -380,7 +380,7 @@ void MCELFStreamer::emitBundleUnlock(const MCSubtargetInfo &STI) {
     return getContext().reportError(Loc,
                                     ".bundle_unlock without matching lock");
 
-  BundleLocked = false;
+  setBundleLocked(false);
   MCFragment *CF = getCurrentFragment();
   BundleBA->setLastFragment(CF);
 
@@ -464,6 +464,7 @@ void MCELFStreamer::finishImpl() {
     MCSection *DummyAttributeSection = nullptr;
     createAttributesSection("gnu", ".gnu.attributes", ELF::SHT_GNU_ATTRIBUTES,
                             DummyAttributeSection, GNUAttributes);
+    GNUAttributes.clear();
   }
 
   if (Ctx.getTargetTriple().isLFI())
@@ -536,8 +537,8 @@ MCELFStreamer::getAttributeItem(unsigned Attribute) {
   return nullptr;
 }
 
-size_t MCELFStreamer::calculateContentSize(
-    SmallVector<AttributeItem, 64> &AttrsVec) const {
+size_t
+MCELFStreamer::calculateContentSize(ArrayRef<AttributeItem> AttrsVec) const {
   size_t Result = 0;
   for (const AttributeItem &Item : AttrsVec) {
     switch (Item.Type) {
@@ -561,9 +562,10 @@ size_t MCELFStreamer::calculateContentSize(
   return Result;
 }
 
-void MCELFStreamer::createAttributesSection(
-    StringRef Vendor, const Twine &Section, unsigned Type,
-    MCSection *&AttributeSection, SmallVector<AttributeItem, 64> &AttrsVec) {
+void MCELFStreamer::createAttributesSection(StringRef Vendor,
+                                            const Twine &Section, unsigned Type,
+                                            MCSection *&AttributeSection,
+                                            ArrayRef<AttributeItem> AttrsVec) {
   // <format-version>
   // [ <section-length> "vendor-name"
   // [ <file-tag> <size> <attribute>*
@@ -619,8 +621,6 @@ void MCELFStreamer::createAttributesSection(
       break;
     }
   }
-
-  AttrsVec.clear();
 }
 
 void MCELFStreamer::createAttributesWithSubsection(
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 8fb2d7bc90c52..6547b4e695d75 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -32,7 +32,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
     : MCStreamer(Context),
       Assembler(std::make_unique<MCAssembler>(
           Context, std::move(TAB), std::move(Emitter), std::move(OW))),
-      EmitEHFrame(true), EmitDebugFrame(false), EmitSFrame(false) {
+      FragStorage(decltype(this->FragStorage)::withFlags(1)) {
   assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());
   IsObj = true;
   setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
@@ -173,9 +173,9 @@ void MCObjectStreamer::reset() {
     Assembler->reset();
     Assembler->setRelaxAll(getContext().getTargetOptions().MCRelaxAll);
   }
-  EmitEHFrame = true;
-  EmitDebugFrame = false;
-  BundleLocked = false;
+  setEmitEHFrame(true);
+  setEmitDebugFrame(false);
+  setBundleLocked(false);
   FragStorage.clear();
   FragSpace = 0;
   SpecialFragAllocator.Reset();
@@ -193,12 +193,12 @@ void MCObjectStreamer::emitFrames() {
   if (!getNumFrameInfos())
     return;
 
-  if (EmitEHFrame)
+  if (getEmitEHFrame())
     MCDwarfFrameEmitter::emit(*this, true);
-  if (EmitDebugFrame)
+  if (getEmitDebugFrame())
     MCDwarfFrameEmitter::emit(*this, false);
 
-  if (EmitSFrame || getContext().getTargetOptions().EmitSFrameUnwind)
+  if (getEmitSFrame() || getContext().getTargetOptions().EmitSFrameUnwind)
     MCSFrameEmitter::emit(*this);
 }
 
@@ -208,9 +208,9 @@ void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
 
 void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
   MCStreamer::emitCFISections(EH, Debug, SFrame);
-  EmitEHFrame = EH;
-  EmitDebugFrame = Debug;
-  EmitSFrame = SFrame;
+  setEmitEHFrame(EH);
+  setEmitDebugFrame(Debug);
+  setEmitSFrame(SFrame);
 }
 
 void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
@@ -426,7 +426,7 @@ void MCObjectStreamer::emitInstruction(const MCInst &Inst,
   // Bundling emits one relaxable fragment per instruction so that finishLayout
   // can fold padding into instruction encodings.
   if (Assembler.isBundlingEnabled()) {
-    if (BundleLocked || Assembler.getRelaxAll())
+    if (getBundleLocked() || Assembler.getRelaxAll())
       emitInstToFragment(relaxToFixpoint(Inst), STI);
     else
       emitInstToFragment(Inst, STI);
diff --git a/llvm/lib/MC/MCObjectWriter.cpp b/llvm/lib/MC/MCObjectWriter.cpp
index 7cbd0b489d9f6..c1dd11f1f51e7 100644
--- a/llvm/lib/MC/MCObjectWriter.cpp
+++ b/llvm/lib/MC/MCObjectWriter.cpp
@@ -25,8 +25,7 @@ MCContext &MCObjectWriter::getContext() const { return Asm->getContext(); }
 void MCObjectWriter::reset() {
   FileNames.clear();
   AddrsigSyms.clear();
-  EmitAddrsigSection = false;
-  SubsectionsViaSymbols = false;
+  FileNames.setFlags(0);
   CGProfile.clear();
 }
 
diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
index cb7bb903276d4..979e6051cae45 100644
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -495,7 +495,7 @@ AsmToken AsmLexer::LexDigit() {
 
   // MASM default-radix integers: [0-9a-fA-F]+
   // (All other integer literals have a radix specifier.)
-  if (LexMasmIntegers && UseMasmDefaultRadix) {
+  if (LexMasmIntegers && CurTok.getFlag(0)) {
     CurPtr = findLastDigit(CurPtr, 16);
     StringRef Result(TokStart, CurPtr - TokStart);
 
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index b50f27cca1be9..64f6054d6c17d 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -159,10 +160,12 @@ class AsmParser : public MCAsmParser {
   CppHashInfoTy CppHashInfo;
 
   /// Have we seen any file line comment.
-  bool HadCppHashFilename = false;
+  bool getHadCppHashFilename() const { return DirLabels.getFlag(0); }
+  void setHadCppHashFilename(bool Value) { DirLabels.setFlag(0, Value); }
 
   /// List of forward directional labels for diagnosis at the end.
-  SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
+  llvm::SmallVectorWithFlags<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4>
+      DirLabels;
 
   SmallSet<StringRef, 2> LTODiscardSymbols;
 
@@ -767,7 +770,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
                      const MCAsmInfo &MAI, unsigned CB = 0)
     : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
       MacrosEnabledFlag(true) {
-  HadError = false;
+  setHadError(false);
   // Save the old handler.
   SavedDiagHandler = SrcMgr.getDiagHandler();
   SavedDiagContext = SrcMgr.getDiagContext();
@@ -817,7 +820,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
 }
 
 AsmParser::~AsmParser() {
-  assert((HadError || ActiveMacros.empty()) &&
+  assert((getHadError() || ActiveMacros.empty()) &&
          "Unexpected active macro instantiation!");
 
   // Remove MCStreamer's reference to the parser SMLoc.
@@ -851,7 +854,7 @@ bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
 }
 
 bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
-  HadError = true;
+  setHadError(true);
   printMessage(L, SourceMgr::DK_Error, Msg, Range);
   printMacroInstantiations();
   return true;
@@ -875,7 +878,7 @@ bool AsmParser::enterIncludeFile(const std::string &Filename) {
 bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
                                   const MCExpr *Count, SMLoc Loc) {
   // The .incbin file cannot introduce new symbols.
-  if (SymbolScanningMode)
+  if (getSymbolScanningModeFlag())
     return false;
 
   // The buffer is consumed only by emitBytes. Skip the NUL termination to
@@ -969,7 +972,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
   // Prime the lexer.
   Lex();
 
-  HadError = false;
+  setHadError(false);
   AsmCond StartingCondState = TheCondState;
   SmallVector<AsmRewrite, 4> AsmStrRewrites;
 
@@ -1066,14 +1069,14 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
   }
   // Finalize the output stream if there are no errors and if the client wants
   // us to.
-  if (!HadError && !NoFinalize) {
+  if (!getHadError() && !NoFinalize) {
     if (auto *TS = Out.getTargetStreamer())
       TS->emitConstantPools();
 
     Out.finish(Lexer.getLoc());
   }
 
-  return HadError || getContext().hadError();
+  return getHadError() || getContext().hadError();
 }
 
 bool AsmParser::checkForValidSection() {
@@ -2393,8 +2396,8 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {
   CppHashInfo.Filename = Filename;
   CppHashInfo.LineNumber = LineNumber;
   CppHashInfo.Buf = CurBuffer;
-  if (!HadCppHashFilename) {
-    HadCppHashFilename = true;
+  if (!getHadCppHashFilename()) {
+    setHadCppHashFilename(true);
     // If we haven't encountered any .file directives, then the first #line
     // directive describes the "root" file and directory of the compilation
     // unit.
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index ac525f175fd54..85068f9ec059e 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -975,7 +975,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
                        const MCAsmInfo &MAI, struct tm TM, unsigned CB)
     : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
       TM(TM) {
-  HadError = false;
+  setHadError(false);
   // Save the old handler.
   SavedDiagHandler = SrcMgr.getDiagHandler();
   SavedDiagContext = SrcMgr.getDiagContext();
@@ -1002,7 +1002,7 @@ MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
 }
 
 MasmParser::~MasmParser() {
-  assert((HadError || ActiveMacros.empty()) &&
+  assert((getHadError() || ActiveMacros.empty()) &&
          "Unexpected active macro instantiation!");
 
   // Restore the saved diagnostics handler and context for use during
@@ -1037,7 +1037,7 @@ bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
 }
 
 bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
-  HadError = true;
+  setHadError(true);
   printMessage(L, SourceMgr::DK_Error, Msg, Range);
   printMacroInstantiations();
   return true;
@@ -1212,7 +1212,7 @@ bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
   // Prime the lexer.
   Lex();
 
-  HadError = false;
+  setHadError(false);
   AsmCond StartingCondState = TheCondState;
   SmallVector<AsmRewrite, 4> AsmStrRewrites;
 
@@ -1268,10 +1268,10 @@ bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
 
   // Finalize the output stream if there are no errors and if the client wants
   // us to.
-  if (!HadError && !NoFinalize)
+  if (!getHadError() && !NoFinalize)
     Out.finish(Lexer.getLoc());
 
-  return HadError || getContext().hadError();
+  return getHadError() || getContext().hadError();
 }
 
 bool MasmParser::checkForValidSection() {
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 790f7595807b9..021d5f41b6135 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -754,7 +754,7 @@ bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
     if (!hasReliableSymbolDifference) {
       if (!SA.isInSection() || &SecA != &SecB ||
           (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
-           SubsectionsViaSymbols))
+           getSubsectionsViaSymbols()))
         return false;
       return true;
     }
@@ -917,7 +917,7 @@ uint64_t MachObjectWriter::writeObject() {
 
   // Write the prolog, starting with the header and load command...
   writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
-              SubsectionsViaSymbols);
+              getSubsectionsViaSymbols());
   uint32_t Prot =
       MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
   writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
diff --git a/llvm/lib/ObjCopy/Archive.cpp b/llvm/lib/ObjCopy/Archive.cpp
index 191174102c66f..6e3723ec79b2d 100644
--- a/llvm/lib/ObjCopy/Archive.cpp
+++ b/llvm/lib/ObjCopy/Archive.cpp
@@ -38,7 +38,7 @@ objcopy::createNewArchiveMembers(const MultiFormatConfig &Config,
                              ChildOrErr.takeError());
 
     const CommonConfig &CC = Config.getCommonConfig();
-    if (CC.Verbose) {
+    if (CC.getVerbose()) {
       StringRef FormatName = getObjectFormatName(*ChildOrErr->get());
       printCopyMessage(MemberName(Ar.getFileName()), FormatName,
                        MemberName(CC.OutputFilename), FormatName);
@@ -51,7 +51,7 @@ objcopy::createNewArchiveMembers(const MultiFormatConfig &Config,
       return std::move(E);
 
     Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
-        Child, Config.getCommonConfig().DeterministicArchives);
+        Child, Config.getCommonConfig().getDeterministicArchives());
     if (!Member)
       return createFileError(Ar.getFileName(), Member.takeError());
 
@@ -115,6 +115,6 @@ Error objcopy::executeObjcopyOnArchive(const MultiFormatConfig &Config,
   return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,
                           Ar.hasSymbolTable() ? SymtabWritingMode::NormalSymtab
                                               : SymtabWritingMode::NoSymtab,
-                          Ar.kind(), CommonConfig.DeterministicArchives,
+                          Ar.kind(), CommonConfig.getDeterministicArchives(),
                           Ar.isThin());
 }
diff --git a/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
index 96de61737d78f..df312b5065cf6 100644
--- a/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
@@ -182,8 +182,9 @@ static Error handleArgs(const CommonConfig &Config,
     if (!Config.OnlySection.empty() && !Config.OnlySection.matches(Sec.Name))
       return true;
 
-    if (Config.StripDebug || Config.StripAll || Config.StripAllGNU ||
-        Config.DiscardMode == DiscardType::All || Config.StripUnneeded) {
+    if (Config.getStripDebug() || Config.getStripAll() ||
+        Config.getStripAllGNU() || Config.DiscardMode == DiscardType::All ||
+        Config.getStripUnneeded()) {
       if (isDebugSection(Sec) &&
           (Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0)
         return true;
@@ -195,7 +196,7 @@ static Error handleArgs(const CommonConfig &Config,
     return false;
   });
 
-  if (Config.OnlyKeepDebug) {
+  if (Config.getOnlyKeepDebug()) {
     const data_directory *DebugDir =
         Obj.DataDirectories.size() > DEBUG_DIRECTORY
             ? &Obj.DataDirectories[DEBUG_DIRECTORY]
@@ -214,12 +215,12 @@ static Error handleArgs(const CommonConfig &Config,
   }
 
   // StripAll removes all symbols and thus also removes all relocations.
-  if (Config.StripAll || Config.StripAllGNU)
+  if (Config.getStripAll() || Config.getStripAllGNU())
     for (Section &Sec : Obj.getMutableSections())
       Sec.Relocs.clear();
 
   // If we need to do per-symbol removals, initialize the Referenced field.
-  if (Config.StripUnneeded || Config.DiscardMode == DiscardType::All ||
+  if (Config.getStripUnneeded() || Config.DiscardMode == DiscardType::All ||
       !Config.SymbolsToRemove.empty())
     if (Error E = Obj.markSymbols())
       return E;
@@ -233,7 +234,7 @@ static Error handleArgs(const CommonConfig &Config,
   auto ToRemove = [&](const Symbol &Sym) -> Expected<bool> {
     // For StripAll, all relocations have been stripped and we remove all
     // symbols.
-    if (Config.StripAll || Config.StripAllGNU)
+    if (Config.getStripAll() || Config.getStripAllGNU())
       return true;
 
     if (Config.SymbolsToRemove.matches(Sym.Name)) {
@@ -256,7 +257,7 @@ static Error handleArgs(const CommonConfig &Config,
       // local symbol instead of removing all of such.
       if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC ||
           Sym.Sym.SectionNumber == 0)
-        if (Config.StripUnneeded ||
+        if (Config.getStripUnneeded() ||
             Config.UnneededSymbolsToRemove.matches(Sym.Name))
           return true;
 
diff --git a/llvm/lib/ObjCopy/ConfigManager.cpp b/llvm/lib/ObjCopy/ConfigManager.cpp
index 403b9d1bb922e..19d367b94c654 100644
--- a/llvm/lib/ObjCopy/ConfigManager.cpp
+++ b/llvm/lib/ObjCopy/ConfigManager.cpp
@@ -28,10 +28,11 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
       !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
       !Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
       !Common.SetSectionAlignment.empty() || !Common.SetSectionType.empty() ||
-      Common.ExtractDWO || Common.StripDWO || Common.StripNonAlloc ||
-      Common.StripSections || Common.Weaken ||
+      Common.getExtractDWO() || Common.getStripDWO() ||
+      Common.getStripNonAlloc() || Common.getStripSections() ||
+      Common.getWeaken() ||
       Common.CompressionType != DebugCompressionType::None ||
-      !Common.compressSections.empty() || Common.DecompressDebugSections ||
+      !Common.compressSections.empty() || Common.getDecompressDebugSections() ||
       Common.DiscardMode == DiscardType::Locals ||
       !Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
       Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
@@ -49,12 +50,13 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
       !Common.SymbolsToKeep.empty() || !Common.SectionsToRename.empty() ||
       !Common.UnneededSymbolsToRemove.empty() ||
       !Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
-      !Common.SetSectionType.empty() || Common.ExtractDWO ||
-      Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
-      Common.StripNonAlloc || Common.StripSections ||
+      !Common.SetSectionType.empty() || Common.getExtractDWO() ||
+      Common.getPreserveDates() || Common.getStripAllGNU() ||
+      Common.getStripDWO() || Common.getStripNonAlloc() ||
+      Common.getStripSections() ||
       Common.CompressionType != DebugCompressionType::None ||
-      !Common.compressSections.empty() || Common.DecompressDebugSections ||
-      Common.StripUnneeded || Common.DiscardMode == DiscardType::Locals ||
+      !Common.compressSections.empty() || Common.getDecompressDebugSections() ||
+      Common.getStripUnneeded() || Common.DiscardMode == DiscardType::Locals ||
       !Common.SymbolsToAdd.empty() || Common.GapFill != 0 ||
       Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
       !Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty())
@@ -78,7 +80,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
       !Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
       !Common.SymbolsToRename.empty() ||
       Common.CompressionType != DebugCompressionType::None ||
-      !Common.compressSections.empty() || Common.DecompressDebugSections ||
+      !Common.compressSections.empty() || Common.getDecompressDebugSections() ||
       Common.GapFill != 0 || Common.PadTo != 0 ||
       Common.ChangeSectionLMAValAll != 0 ||
       !Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty())
@@ -104,13 +106,14 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
       !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
       !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
       !Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
-      !Common.SymbolsToRename.empty() || Common.ExtractDWO ||
-      Common.ExtractMainPartition || Common.OnlyKeepDebug ||
-      Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
-      Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
-      Common.Weaken || Common.StripUnneeded ||
+      !Common.SymbolsToRename.empty() || Common.getExtractDWO() ||
+      Common.getExtractMainPartition() || Common.getOnlyKeepDebug() ||
+      Common.getPreserveDates() || Common.getStripAllGNU() ||
+      Common.getStripDWO() || Common.getStripDebug() ||
+      Common.getStripNonAlloc() || Common.getStripSections() ||
+      Common.getWeaken() || Common.getStripUnneeded() ||
       Common.CompressionType != DebugCompressionType::None ||
-      !Common.compressSections.empty() || Common.DecompressDebugSections ||
+      !Common.compressSections.empty() || Common.getDecompressDebugSections() ||
       Common.GapFill != 0 || Common.PadTo != 0 ||
       Common.ChangeSectionLMAValAll != 0 ||
       !Common.ChangeSectionAddress.empty() || !Common.ExtractSection.empty()) {
@@ -131,12 +134,13 @@ ConfigManager::getDXContainerConfig() const {
       Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
       !Common.KeepSection.empty() || !Common.SectionsToRename.empty() ||
       !Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
-      !Common.SetSectionType.empty() || Common.ExtractDWO ||
-      Common.OnlyKeepDebug || Common.StripAllGNU || Common.StripDWO ||
-      Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
-      Common.StripUnneeded ||
+      !Common.SetSectionType.empty() || Common.getExtractDWO() ||
+      Common.getOnlyKeepDebug() || Common.getStripAllGNU() ||
+      Common.getStripDWO() || Common.getStripDebug() ||
+      Common.getStripNonAlloc() || Common.getStripSections() ||
+      Common.getStripUnneeded() ||
       Common.CompressionType != DebugCompressionType::None ||
-      !Common.compressSections.empty() || Common.DecompressDebugSections ||
+      !Common.compressSections.empty() || Common.getDecompressDebugSections() ||
       Common.GapFill != 0 || Common.PadTo != 0 ||
       Common.ChangeSectionLMAValAll != 0 ||
       !Common.ChangeSectionAddress.empty()) {
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index d448c3adf442f..9e6e504348aca 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -155,17 +155,17 @@ static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
   // Depending on the initial ELFT and OutputFormat we need a different Writer.
   switch (OutputElfType) {
   case ELFT_ELF32LE:
-    return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections,
-                                                Config.OnlyKeepDebug);
+    return std::make_unique<ELFWriter<ELF32LE>>(
+        Obj, Out, !Config.getStripSections(), Config.getOnlyKeepDebug());
   case ELFT_ELF64LE:
-    return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections,
-                                                Config.OnlyKeepDebug);
+    return std::make_unique<ELFWriter<ELF64LE>>(
+        Obj, Out, !Config.getStripSections(), Config.getOnlyKeepDebug());
   case ELFT_ELF32BE:
-    return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections,
-                                                Config.OnlyKeepDebug);
+    return std::make_unique<ELFWriter<ELF32BE>>(
+        Obj, Out, !Config.getStripSections(), Config.getOnlyKeepDebug());
   case ELFT_ELF64BE:
-    return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections,
-                                                Config.OnlyKeepDebug);
+    return std::make_unique<ELFWriter<ELF64BE>>(
+        Obj, Out, !Config.getStripSections(), Config.getOnlyKeepDebug());
   }
   llvm_unreachable("Invalid output format");
 }
@@ -225,7 +225,7 @@ Error Object::compressOrDecompressSections(const CommonConfig &Config) {
     if (!(Sec.Flags & SHF_ALLOC) && StringRef(Sec.Name).starts_with(".debug")) {
       if (Config.CompressionType != DebugCompressionType::None)
         CType = Config.CompressionType;
-      else if (Config.DecompressDebugSections)
+      else if (Config.getDecompressDebugSections())
         CType = DebugCompressionType::None;
     }
     if (!CType)
@@ -310,7 +310,7 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
     // Common and undefined symbols don't make sense as local symbols, and can
     // even cause crashes if we localize those, so skip them.
     if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
-        ((ELFConfig.LocalizeHidden &&
+        ((ELFConfig.getLocalizeHidden() &&
           (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
          Config.SymbolsToLocalize.matches(Sym.Name)))
       Sym.Binding = STB_LOCAL;
@@ -342,7 +342,7 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
     if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL)
       Sym.Binding = STB_WEAK;
 
-    if (Config.Weaken && Sym.Binding != STB_LOCAL &&
+    if (Config.getWeaken() && Sym.Binding != STB_LOCAL &&
         Sym.getShndx() != SHN_UNDEF)
       Sym.Binding = STB_WEAK;
 
@@ -361,7 +361,7 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
   // The purpose of this loop is to mark symbols referenced by sections
   // (like GroupSection or RelocationSection). This way, we know which
   // symbols are still 'needed' and which are not.
-  if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
+  if (Config.getStripUnneeded() || !Config.UnneededSymbolsToRemove.empty() ||
       !Config.OnlySection.empty() || Config.DiscardMode != DiscardType::None) {
     for (SectionBase &Sec : Obj.sections())
       Sec.markSymbols();
@@ -369,22 +369,22 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
 
   auto RemoveSymbolsPred = [&](const Symbol &Sym) {
     if (Config.SymbolsToKeep.matches(Sym.Name) ||
-        (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE))
+        (ELFConfig.getKeepFileSymbols() && Sym.Type == STT_FILE))
       return false;
 
     if (Config.SymbolsToRemove.matches(Sym.Name))
       return true;
 
-    if (Config.StripAll || Config.StripAllGNU)
+    if (Config.getStripAll() || Config.getStripAllGNU())
       return true;
 
     if (isRequiredByABISymbol(Obj, Sym))
       return false;
 
-    if (Config.StripDebug && Sym.Type == STT_FILE)
+    if (Config.getStripDebug() && Sym.Type == STT_FILE)
       return true;
 
-    if ((Config.StripUnneeded ||
+    if ((Config.getStripUnneeded() ||
          Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
         (!Obj.isRelocatable() || isUnneededSymbol(Sym)))
       return true;
@@ -419,17 +419,17 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
     };
   }
 
-  if (Config.StripDWO)
+  if (Config.getStripDWO())
     RemovePred = [RemovePred](const SectionBase &Sec) {
       return isDWOSection(Sec) || RemovePred(Sec);
     };
 
-  if (Config.ExtractDWO)
+  if (Config.getExtractDWO())
     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
       return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
     };
 
-  if (Config.StripAllGNU)
+  if (Config.getStripAllGNU())
     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
       if (RemovePred(Sec))
         return true;
@@ -447,19 +447,19 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
       return isDebugSection(Sec);
     };
 
-  if (Config.StripSections) {
+  if (Config.getStripSections()) {
     RemovePred = [RemovePred](const SectionBase &Sec) {
       return RemovePred(Sec) || Sec.ParentSegment == nullptr;
     };
   }
 
-  if (Config.StripDebug || Config.StripUnneeded) {
+  if (Config.getStripDebug() || Config.getStripUnneeded()) {
     RemovePred = [RemovePred](const SectionBase &Sec) {
       return RemovePred(Sec) || isDebugSection(Sec);
     };
   }
 
-  if (Config.StripNonAlloc)
+  if (Config.getStripNonAlloc())
     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
       if (RemovePred(Sec))
         return true;
@@ -468,7 +468,7 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
       return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
     };
 
-  if (Config.StripAll)
+  if (Config.getStripAll())
     RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
       if (RemovePred(Sec))
         return true;
@@ -489,7 +489,7 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
       return (Sec.Flags & SHF_ALLOC) == 0;
     };
 
-  if (Config.ExtractPartition || Config.ExtractMainPartition) {
+  if (Config.ExtractPartition || Config.getExtractMainPartition()) {
     RemovePred = [RemovePred](const SectionBase &Sec) {
       if (RemovePred(Sec))
         return true;
@@ -537,7 +537,7 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
   // and at least one of those symbols is present
   // (equivalently, the updated symbol table is not empty)
   // the symbol table and the string table should not be removed.
-  if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) &&
+  if ((!Config.SymbolsToKeep.empty() || ELFConfig.getKeepFileSymbols()) &&
       Obj.SymbolTable && !Obj.SymbolTable->empty()) {
     RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
       if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
@@ -546,7 +546,7 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
     };
   }
 
-  if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
+  if (Error E = Obj.removeSections(ELFConfig.getAllowBrokenLinks(), RemovePred))
     return E;
 
   if (Error E = Obj.compressOrDecompressSections(Config))
@@ -794,9 +794,9 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
     Obj.OSABI = Config.OutputArch->OSABI;
   }
 
-  if (!Config.SplitDWO.empty() && Config.ExtractDWO) {
+  if (!Config.SplitDWO.empty() && Config.getExtractDWO()) {
     return Obj.removeSections(
-        ELFConfig.AllowBrokenLinks,
+        ELFConfig.getAllowBrokenLinks(),
         [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
   }
 
@@ -903,7 +903,7 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
     }
   }
 
-  if (Config.OnlyKeepDebug)
+  if (Config.getOnlyKeepDebug())
     for (auto &Sec : Obj.sections())
       if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
         Sec.Type = SHT_NOBITS;
@@ -924,7 +924,7 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
           Obj.addSection<OwnedDataSection>(Name, Data);
       if (Name.starts_with(".note") && Name != ".note.GNU-stack") {
         NewSection.Type = SHT_NOTE;
-        if (ELFConfig.VerifyNoteSections)
+        if (ELFConfig.getVerifyNoteSections())
           return verifyNoteSection(Name, E, Data);
       }
       return Error::success();
diff --git a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
index 1bca325198e0d..deab0b3e971c5 100644
--- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
@@ -63,7 +63,7 @@ static Error removeSections(const CommonConfig &Config, Object &Obj) {
     };
   }
 
-  if (Config.StripAll || Config.StripDebug) {
+  if (Config.getStripAll() || Config.getStripDebug()) {
     // Remove all debug sections.
     RemovePred = [RemovePred](const std::unique_ptr<Section> &Sec) {
       if (Sec->Segname == "__DWARF")
@@ -90,7 +90,7 @@ static void markSymbols(const CommonConfig &Config, Object &Obj) {
       (*ISE.Symbol)->Referenced = true;
 
   // --strip-all removes relocations, so their symbols need not be preserved.
-  if (Config.StripAll)
+  if (Config.getStripAll())
     return;
 
   for (const LoadCommand &LC : Obj.LoadCommands)
@@ -128,7 +128,7 @@ static void updateAndRemoveSymbols(const CommonConfig &Config,
       Sym.n_type |= MachO::N_EXT;
 
     if (Sym.isExternalSymbol() && !Sym.isUndefinedSymbol() &&
-        (Config.Weaken || Config.SymbolsToWeaken.matches(Sym.Name)))
+        (Config.getWeaken() || Config.SymbolsToWeaken.matches(Sym.Name)))
       Sym.n_desc |= MachO::N_WEAK_DEF;
 
     auto I = Config.SymbolsToRename.find(Sym.Name);
@@ -144,12 +144,12 @@ static void updateAndRemoveSymbols(const CommonConfig &Config,
       return false;
     if (N->n_desc & MachO::REFERENCED_DYNAMICALLY)
       return false;
-    if (Config.StripAll)
+    if (Config.getStripAll())
       return true;
     if (Config.DiscardMode == DiscardType::All && !(N->n_type & MachO::N_EXT))
       return true;
     // This behavior is consistent with cctools' strip.
-    if (Config.StripDebug && (N->n_type & MachO::N_STAB))
+    if (Config.getStripDebug() && (N->n_type & MachO::N_STAB))
       return true;
     // This behavior is consistent with cctools' strip.
     if (MachOConfig.StripSwiftSymbols &&
@@ -468,7 +468,7 @@ static Error handleArgs(const CommonConfig &Config,
 
   updateAndRemoveSymbols(Config, MachOConfig, Obj);
 
-  if (Config.StripAll)
+  if (Config.getStripAll())
     for (LoadCommand &LC : Obj.LoadCommands)
       for (std::unique_ptr<Section> &Sec : LC.Sections)
         Sec->Relocations.clear();
@@ -550,7 +550,7 @@ Error objcopy::macho::executeObjcopyOnMachOUniversalBinary(
               *NewArchiveMembersOrErr,
               (*ArOrErr)->hasSymbolTable() ? SymtabWritingMode::NormalSymtab
                                            : SymtabWritingMode::NoSymtab,
-              Kind, Config.getCommonConfig().DeterministicArchives,
+              Kind, Config.getCommonConfig().getDeterministicArchives(),
               (*ArOrErr)->isThin());
       if (!OutputBufferOrErr)
         return OutputBufferOrErr.takeError();
diff --git a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
index bf5805464649d..0619c8844a340 100644
--- a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
+++ b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
@@ -60,19 +60,19 @@ static void removeSections(const CommonConfig &Config, Object &Obj) {
     };
   }
 
-  if (Config.StripDebug) {
+  if (Config.getStripDebug()) {
     RemovePred = [RemovePred](const Section &Sec) {
       return RemovePred(Sec) || isDebugSection(Sec);
     };
   }
 
-  if (Config.StripAll) {
+  if (Config.getStripAll()) {
     RemovePred = [RemovePred](const Section &Sec) {
       return RemovePred(Sec) || !isEngineInterpretedSection(Sec);
     };
   }
 
-  if (Config.OnlyKeepDebug) {
+  if (Config.getOnlyKeepDebug()) {
     RemovePred = [&Config](const Section &Sec) {
       // Keep debug sections, unless explicitly requested to remove.
       // Remove everything else, including known sections.
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 85c4f69d70dde..9ca5126337abf 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -1452,16 +1452,21 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
       }
       UuidLoadCmd = Load.Ptr;
     } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
-      if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
-                                         MachO::section_64>(
-                   *this, Load, Sections, HasPageZeroSegment, I,
-                   "LC_SEGMENT_64", SizeOfHeaders, Elements)))
+      bool HasPageZero = getHasPageZeroSegment();
+      Err =
+          parseSegmentLoadCommand<MachO::segment_command_64, MachO::section_64>(
+              *this, Load, Sections, HasPageZero, I, "LC_SEGMENT_64",
+              SizeOfHeaders, Elements);
+      setHasPageZeroSegment(HasPageZero);
+      if (Err)
         return;
     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
-      if ((Err = parseSegmentLoadCommand<MachO::segment_command,
-                                         MachO::section>(
-                   *this, Load, Sections, HasPageZeroSegment, I,
-                   "LC_SEGMENT", SizeOfHeaders, Elements)))
+      bool HasPageZero = getHasPageZeroSegment();
+      Err = parseSegmentLoadCommand<MachO::segment_command, MachO::section>(
+          *this, Load, Sections, HasPageZero, I, "LC_SEGMENT", SizeOfHeaders,
+          Elements);
+      setHasPageZeroSegment(HasPageZero);
+      if (Err)
         return;
     } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
       if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
@@ -3044,13 +3049,13 @@ void ExportEntry::moveToFirst() {
 
 void ExportEntry::moveToEnd() {
   Stack.clear();
-  Done = true;
+  Stack.setFlag(0, true);
 }
 
 bool ExportEntry::operator==(const ExportEntry &Other) const {
   // Common case, one at end, other iterating from begin.
-  if (Done || Other.Done)
-    return (Done == Other.Done);
+  if (Stack.getFlag(0) || Other.Stack.getFlag(0))
+    return Stack.getFlag(0) == Other.Stack.getFlag(0);
   // Not equal if different stack sizes.
   if (Stack.size() != Other.Stack.size())
     return false;
@@ -3333,7 +3338,7 @@ void ExportEntry::moveNext() {
       Stack.pop_back();
     }
   }
-  Done = true;
+  Stack.setFlag(0, true);
 }
 
 iterator_range<export_iterator>
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index bcb5376eb68b0..db7765efaea78 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -245,21 +245,24 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
 
       for (auto El : P.Info->SigInputElements)
         PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{
-            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
-            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
-            El.Stream});
+            El.Name,
+            SmallVector<uint32_t>(El.Indices.begin(), El.Indices.end()),
+            El.StartRow, El.Cols, El.StartCol, El.getAllocatedFlag(), El.Kind,
+            El.Type, El.Mode, El.DynamicMask, El.Stream});
 
       for (auto El : P.Info->SigOutputElements)
         PSV.OutputElements.push_back(mcdxbc::PSVSignatureElement{
-            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
-            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
-            El.Stream});
+            El.Name,
+            SmallVector<uint32_t>(El.Indices.begin(), El.Indices.end()),
+            El.StartRow, El.Cols, El.StartCol, El.getAllocatedFlag(), El.Kind,
+            El.Type, El.Mode, El.DynamicMask, El.Stream});
 
       for (auto El : P.Info->SigPatchOrPrimElements)
         PSV.PatchOrPrimElements.push_back(mcdxbc::PSVSignatureElement{
-            El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
-            El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
-            El.Stream});
+            El.Name,
+            SmallVector<uint32_t>(El.Indices.begin(), El.Indices.end()),
+            El.StartRow, El.Cols, El.StartCol, El.getAllocatedFlag(), El.Kind,
+            El.Type, El.Mode, El.DynamicMask, El.Stream});
 
       static_assert(PSV.OutputVectorMasks.size() == PSV.InputOutputMap.size());
       for (unsigned I = 0; I < PSV.OutputVectorMasks.size(); ++I) {
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index aaf9820c2d668..291cf431eda1a 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -605,7 +605,9 @@ void MappingTraits<DXContainerYAML::SignatureElement>::mapping(
   IO.mapRequired("StartRow", El.StartRow);
   IO.mapRequired("Cols", El.Cols);
   IO.mapRequired("StartCol", El.StartCol);
-  IO.mapRequired("Allocated", El.Allocated);
+  bool Allocated = El.isAllocated();
+  IO.mapRequired("Allocated", Allocated);
+  El.setAllocated(Allocated);
   IO.mapRequired("Kind", El.Kind);
   IO.mapRequired("ComponentType", El.Type);
   IO.mapRequired("Interpolation", El.Mode);
diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index 7fc9460af418a..160405b935410 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -76,9 +76,9 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
 OptTable::OptTable(const Tables &T, bool IgnoreCase)
     : StrTable(T.StrTable), PrefixesTable(T.PrefixesTable),
       OptionInfos(T.Infos), InfoExtrasTable(T.InfoExtras),
-      IgnoreCase(IgnoreCase), SubCommands(T.SubCommands),
-      SubCommandIDsTable(T.SubCommandIDs),
-      HelpTextVariantsTable(T.HelpTextVariants) {
+      SubCommands(T.SubCommands), SubCommandIDsTable(T.SubCommandIDs),
+      HelpTextVariantsTable(T.HelpTextVariants),
+      PrefixesUnion(decltype(PrefixesUnion)::withFlags(unsigned(IgnoreCase))) {
   // Each prefix set in PrefixesTable starts with its size.
   for (unsigned I = 0, E = PrefixesTable.size(); I != E;) {
     unsigned Size = PrefixesTable[I++].value();
@@ -371,7 +371,7 @@ std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
   // Search for the option which matches Str.
   for (; Start != End; ++Start) {
     unsigned ArgSize =
-        matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase);
+        matchOption(StrTable, PrefixesTable, Start, Str, getIgnoreCase());
     if (!ArgSize)
       continue;
 
@@ -468,8 +468,8 @@ std::unique_ptr<Arg> OptTable::internalParseOneArg(
     unsigned ArgSize = 0;
     // Scan for first option which is a proper prefix.
     for (; Start != End; ++Start)
-      if ((ArgSize =
-               matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase)))
+      if ((ArgSize = matchOption(StrTable, PrefixesTable, Start, Str,
+                                 getIgnoreCase())))
         break;
     if (Start == End)
       break;
@@ -552,7 +552,7 @@ InputArgList OptTable::internalParseArgs(
 
     // In DashDashParsing mode, the first "--" stops option scanning and treats
     // all subsequent arguments as positional.
-    if (DashDashParsing && Str == "--") {
+    if (getDashDashParsingFlag() && Str == "--") {
       while (++Index < End) {
         Args.append(new Arg(getOption(InputOptionID), Str, Index,
                             Args.getArgString(Index)));
@@ -561,10 +561,11 @@ InputArgList OptTable::internalParseArgs(
     }
 
     unsigned Prev = Index;
-    std::unique_ptr<Arg> A = GroupedShortOptions
-                 ? parseOneArgGrouped(Args, Index)
-                 : internalParseOneArg(Args, Index, ExcludeOption);
-    assert((Index > Prev || GroupedShortOptions) &&
+    std::unique_ptr<Arg> A =
+        getGroupedShortOptionsFlag()
+            ? parseOneArgGrouped(Args, Index)
+            : internalParseOneArg(Args, Index, ExcludeOption);
+    assert((Index > Prev || getGroupedShortOptionsFlag()) &&
            "Parser failed to consume argument.");
 
     // Check for missing argument error.
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index cbb048d15bca2..48ec3e86dd392 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/BuildID.h"
@@ -447,13 +448,14 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
   /// ExecutedTestVectorBitmap.
   MCDCRecord::TestVectors ExecVectors;
   /// Never-executed test vectors
-  MCDCRecord::TestVectors NotExecVectors;
+  llvm::SmallVectorWithFlagsFor<MCDCRecord::TestVectors, 1> NotExecVectors;
 
 #ifndef NDEBUG
   DenseSet<unsigned> TVIdxs;
 #endif
 
-  bool IsVersion11;
+  bool getIsVersion11() const { return NotExecVectors.getFlag(0); }
+  void setIsVersion11(bool Value) { NotExecVectors.setFlag(0, Value); }
 
 public:
   MCDCRecordProcessor(const BitVector &Bitmap,
@@ -464,7 +466,9 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
         Region(Region), DecisionParams(Region.getDecisionParams()),
         Branches(Branches), NumConditions(DecisionParams.NumConditions),
         Folded{{BitVector(NumConditions), BitVector(NumConditions)}},
-        IndependencePairs(NumConditions), IsVersion11(IsVersion11) {}
+        IndependencePairs(NumConditions),
+        NotExecVectors(
+            decltype(this->NotExecVectors)::withFlags(unsigned(IsVersion11))) {}
 
 private:
   // Walk the binary decision diagram and try assigning both false and true to
@@ -488,7 +492,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
       assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
 
       bool Executed =
-          Bitmap[IsVersion11
+          Bitmap[getIsVersion11()
                      ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
                      : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx];
       if (Executed) {
@@ -531,7 +535,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
     MCDCRecord::TestVectors NewNotExec;
     for (const auto &IdxTuple : NotExecVectorIdxs)
       NewNotExec.push_back(std::move(NotExecVectors[IdxTuple.Ord]));
-    NotExecVectors = std::move(NewNotExec);
+    NotExecVectors.assign(std::move(NewNotExec));
   }
 
 public:
@@ -570,7 +574,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
     findTestVectors();
 
     // Record executed vectors, not-executed vectors, and independence pairs.
-    return MCDCRecord(Region, std::move(ExecVectors), std::move(NotExecVectors),
+    return MCDCRecord(Region, MCDCRecord::TestVectors(std::move(ExecVectors)),
+                      MCDCRecord::TestVectors(std::move(NotExecVectors)),
                       std::move(Folded), std::move(PosToID),
                       std::move(CondLoc));
   }
@@ -730,13 +735,14 @@ struct CountedRegionEmitter {
   const CoverageMappingRecord &Record;
   CounterMappingContext &Ctx;
   FunctionRecord &Function;
-  bool IsVersion11;
+  bool getIsVersion11() const { return DecisionStack.getFlag(0); }
+  void setIsVersion11(bool Value) { DecisionStack.setFlag(0, Value); }
 
   /// Evaluated Counters.
   std::map<Counter, uint64_t> CounterValues;
 
   /// Decisions are nestable.
-  SmallVector<DecisionRecord, 1> DecisionStack;
+  llvm::SmallVectorWithFlags<DecisionRecord, 1> DecisionStack;
 
   /// A File pointed by Expansion
   struct FileInfo {
@@ -756,7 +762,9 @@ struct CountedRegionEmitter {
   CountedRegionEmitter(const CoverageMappingRecord &Record,
                        CounterMappingContext &Ctx, FunctionRecord &Function,
                        bool IsVersion11)
-      : Record(Record), Ctx(Ctx), Function(Function), IsVersion11(IsVersion11),
+      : Record(Record), Ctx(Ctx), Function(Function),
+        DecisionStack(
+            decltype(this->DecisionStack)::withFlags(unsigned(IsVersion11))),
         Files(Record.Filenames.size()) {
     // Scan MappingRegions and mark each last index by FileID.
     for (auto [I, Region] : enumerate(Record.MappingRegions)) {
@@ -815,7 +823,7 @@ struct CountedRegionEmitter {
         if (D.pushBranch(Region)) {
           // All Branches have been found in the Decision.
           auto RecordOrErr = Ctx.evaluateMCDCRegion(
-              *D.DecisionRegion, D.MCDCBranches, IsVersion11);
+              *D.DecisionRegion, D.MCDCBranches, getIsVersion11());
           if (!RecordOrErr)
             return RecordOrErr.takeError();
 
diff --git a/llvm/lib/ProfileData/DataAccessProf.cpp b/llvm/lib/ProfileData/DataAccessProf.cpp
index a1e686ba0036b..dd3c005824838 100644
--- a/llvm/lib/ProfileData/DataAccessProf.cpp
+++ b/llvm/lib/ProfileData/DataAccessProf.cpp
@@ -183,7 +183,7 @@ Error DataAccessProfData::serialize(ProfOStream &OS) const {
   OS.write((uint64_t)(Records.size()));
   for (const auto &[Key, Rec] : Records) {
     OS.write(getEncodedIndex(Rec.SymbolID));
-    OS.writeByte(Rec.IsStringLiteral);
+    OS.writeByte(Rec.isStringLiteral());
     OS.write(Rec.AccessCount);
     OS.write(Rec.Locations.size());
     for (const auto &Loc : Rec.Locations) {
diff --git a/llvm/lib/ProfileData/GCOV.cpp b/llvm/lib/ProfileData/GCOV.cpp
index 7d0a243d02388..00450b89c8212 100644
--- a/llvm/lib/ProfileData/GCOV.cpp
+++ b/llvm/lib/ProfileData/GCOV.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ProfileData/GCOV.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Demangle/Demangle.h"
 #include "llvm/Support/Debug.h"
@@ -55,9 +56,10 @@ struct Summary {
 };
 
 struct LineInfo {
-  SmallVector<const GCOVBlock *, 1> blocks;
+  llvm::SmallVectorWithFlags<const GCOVBlock *, 1> blocks;
   uint64_t count = 0;
-  bool exists = false;
+  bool getExists() const { return blocks.getFlag(0); }
+  void setExists(bool Value) { blocks.setFlag(0, Value); }
 };
 
 struct SourceInfo {
@@ -201,14 +203,15 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
     buf.de.skip(buf.cursor, pos - buf.cursor.tell());
   }
 
-  GCNOInitialized = true;
+  setGCNOInitialized(true);
   return true;
 }
 
 /// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
 /// called after readGCNO().
 bool GCOVFile::readGCDA(GCOVBuffer &buf) {
-  assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
+  assert(getGCNOInitialized() &&
+         "readGCDA() can only be called after readGCNO()");
   if (!buf.readGCDAFormat())
     return false;
   GCOV::GCOVVersion GCDAVersion;
@@ -523,7 +526,7 @@ GCOVBlock::augmentOneCycle(GCOVBlock *src,
 // Assuming a reducible flow graph, the count is the sum of back edge counts.
 // Identifying loops is complex, so we simply find cycles and perform cycle
 // cancelling iteratively.
-uint64_t GCOVBlock::getCyclesCount(const BlockVector &blocks) {
+uint64_t GCOVBlock::getCyclesCount(ArrayRef<const GCOVBlock *> blocks) {
   std::vector<std::pair<GCOVBlock *, size_t>> stack;
   uint64_t count = 0, d;
   for (;;) {
@@ -712,7 +715,7 @@ void Context::collectFunction(GCOVFunction &f, Summary &summary) {
         locSource.lines.resize(maxLineNum + 1);
       for (uint32_t lineNum : loc.lines) {
         LineInfo &line = locSource.lines[lineNum];
-        line.exists = true;
+        line.setExists(true);
         line.count += b.count;
         line.blocks.push_back(&b);
         if (f.srcIdx == loc.srcIdx) {
@@ -749,7 +752,7 @@ void Context::collectSourceLine(SourceInfo &si, Summary *summary,
 
   count += GCOVBlock::getCyclesCount(line.blocks);
   line.count = count;
-  if (line.exists) {
+  if (line.getExists()) {
     ++summary->lines;
     if (line.count != 0)
       ++summary->linesExec;
@@ -807,7 +810,7 @@ void Context::annotateSource(SourceInfo &si, const GCOVFile &file,
     if (options.BranchInfo && lineNum < si.startLineToFunctions.size())
       for (const auto *f : si.startLineToFunctions[lineNum])
         printFunctionDetails(*f, os);
-    if (!line.exists)
+    if (!line.getExists())
       os << "        -:";
     else if (line.count == 0)
       os << "    #####:";
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index cd78265f5534f..36cfd70285c1c 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -154,13 +154,14 @@ InstrProfWriter::InstrProfWriter(
     uint64_t MaxTemporalProfTraceLength, bool WritePrevVersion,
     memprof::IndexedVersion MemProfVersionRequested, bool MemProfFullSchema,
     bool MemprofGenerateRandomHotness, unsigned RandomSeed)
-    : Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength),
+    : MaxTemporalProfTraceLength(MaxTemporalProfTraceLength),
       TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize),
+      TemporalProfTraces(decltype(this->TemporalProfTraces)::withFlags(
+          unsigned(Sparse) | (unsigned(WritePrevVersion) << 1) |
+          (unsigned(MemProfFullSchema) << 2) |
+          (unsigned(MemprofGenerateRandomHotness) << 3))),
       InfoObj(new InstrProfRecordWriterTrait()),
-      WritePrevVersion(WritePrevVersion),
-      MemProfVersionRequested(MemProfVersionRequested),
-      MemProfFullSchema(MemProfFullSchema),
-      MemprofGenerateRandomHotness(MemprofGenerateRandomHotness) {
+      MemProfVersionRequested(MemProfVersionRequested) {
   if (RandomSeed)
     RNG.seed(RandomSeed);
 }
@@ -172,7 +173,7 @@ void InstrProfWriter::setValueProfDataEndianness(llvm::endianness Endianness) {
   InfoObj->ValueProfDataEndianness = Endianness;
 }
 
-void InstrProfWriter::setOutputSparse(bool Sparse) { this->Sparse = Sparse; }
+void InstrProfWriter::setOutputSparse(bool Sparse) { this->setSparse(Sparse); }
 
 void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
                                 function_ref<void(Error)> Warn) {
@@ -245,7 +246,7 @@ void InstrProfWriter::addMemProfRecord(
   // Provoke random hotness values if requested. We specify the lifetime access
   // density and lifetime length that will result in a cold or not cold hotness.
   // See the logic in getAllocType() in Analysis/MemoryProfileInfo.cpp.
-  if (MemprofGenerateRandomHotness) {
+  if (getMemprofGenerateRandomHotness()) {
     for (auto &Alloc : NewRecord.AllocSites) {
       // To get a not cold context, set the lifetime access density to the
       // maximum value and the lifetime to 0.
@@ -331,7 +332,7 @@ bool InstrProfWriter::addMemProfData(memprof::IndexedMemProfData Incoming,
         return false;
 
   // Add one record at a time if randomization is requested.
-  if (MemProfData.Records.empty() && !MemprofGenerateRandomHotness) {
+  if (MemProfData.Records.empty() && !getMemprofGenerateRandomHotness()) {
     // Need to manually add each record to the builder, which is otherwise done
     // in addMemProfRecord.
     for (const auto &[GUID, Record] : Incoming.Records)
@@ -356,6 +357,12 @@ void InstrProfWriter::addDataAccessProfData(
 
 void InstrProfWriter::addTemporalProfileTraces(
     SmallVectorImpl<TemporalProfTraceTy> &SrcTraces, uint64_t SrcStreamSize) {
+  addTemporalProfileTracesImpl(SrcTraces, SrcStreamSize);
+}
+
+template <typename TraceVectorT>
+void InstrProfWriter::addTemporalProfileTracesImpl(TraceVectorT &SrcTraces,
+                                                   uint64_t SrcStreamSize) {
   if (TemporalProfTraces.size() > TemporalProfTraceReservoirSize)
     TemporalProfTraces.truncate(TemporalProfTraceReservoirSize);
   for (auto &Trace : SrcTraces)
@@ -394,8 +401,8 @@ void InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW,
   for (auto &I : IPW.BinaryIds)
     addBinaryIds(I);
 
-  addTemporalProfileTraces(IPW.TemporalProfTraces,
-                           IPW.TemporalProfTraceStreamSize);
+  addTemporalProfileTracesImpl(IPW.TemporalProfTraces,
+                               IPW.TemporalProfTraceStreamSize);
 
   MemProfData.Frames.reserve(IPW.MemProfData.Frames.size());
   for (auto &[FrameId, Frame] : IPW.MemProfData.Frames) {
@@ -418,7 +425,7 @@ void InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW,
 }
 
 bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
-  if (!Sparse)
+  if (!getSparse())
     return true;
   for (const auto &Func : PD) {
     const InstrProfRecord &IPR = Func.second;
@@ -548,7 +555,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
   InfoObj->SummaryBuilder = &ISB;
   InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs);
   InfoObj->CSSummaryBuilder = &CSISB;
-  InfoObj->WritePrevVersion = WritePrevVersion;
+  InfoObj->WritePrevVersion = getWritePrevVersion();
 
   // Populate the hash table generator.
   SmallVector<std::pair<StringRef, const ProfilingData *>> OrderedData;
@@ -561,7 +568,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
 
   // Write the header.
   IndexedInstrProf::Header Header;
-  Header.Version = WritePrevVersion
+  Header.Version = getWritePrevVersion()
                        ? IndexedInstrProf::ProfVersion::Version11
                        : IndexedInstrProf::ProfVersion::CurrentVersion;
   // The WritePrevVersion handling will either need to be removed or updated
@@ -588,7 +595,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
     Header.Version |= VARIANT_MASK_TEMPORAL_PROF;
 
   const uint64_t BackPatchStartOffset =
-      writeHeader(Header, WritePrevVersion, OS);
+      writeHeader(Header, getWritePrevVersion(), OS);
 
   // Reserve space to write profile summary data.
   uint32_t NumEntries = ProfileSummaryBuilder::DefaultCutoffs.size();
@@ -614,9 +621,10 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
   if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf)) {
     MemProfSectionStart = OS.tell();
 
-    if (auto E = writeMemProf(
-            OS, MemProfData, MemProfVersionRequested, MemProfFullSchema,
-            std::move(DataAccessProfileData), MemProfSumBuilder.getSummary()))
+    if (auto E = writeMemProf(OS, MemProfData, MemProfVersionRequested,
+                              getMemProfFullSchemaFlag(),
+                              std::move(DataAccessProfileData),
+                              MemProfSumBuilder.getSummary()))
       return E;
   }
 
@@ -626,7 +634,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
 
   uint64_t VTableNamesSectionStart = OS.tell();
 
-  if (!WritePrevVersion)
+  if (!getWritePrevVersion())
     if (Error E = writeVTableNames(OS))
       return E;
 
@@ -664,7 +672,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
   SmallVector<uint64_t, 8> HeaderOffsets = {HashTableStart, MemProfSectionStart,
                                             BinaryIdSectionStart,
                                             TemporalProfTracesSectionStart};
-  if (!WritePrevVersion)
+  if (!getWritePrevVersion())
     HeaderOffsets.push_back(VTableNamesSectionStart);
 
   PatchItem PatchItems[] = {
diff --git a/llvm/lib/ProfileData/MemProfReader.cpp b/llvm/lib/ProfileData/MemProfReader.cpp
index c6f7295c3422c..6bffe0ed1096b 100644
--- a/llvm/lib/ProfileData/MemProfReader.cpp
+++ b/llvm/lib/ProfileData/MemProfReader.cpp
@@ -638,7 +638,7 @@ Error RawMemProfReader::symbolizeAndFilterStackFrames(
         // instead of adding it to the frame object directly to reduce memory
         // overhead. This is because there can be many unique frames,
         // particularly for callsite frames.
-        if (KeepSymbolName) {
+        if (getKeepSymbolName()) {
           StringRef CanonicalName =
               sampleprof::FunctionSamples::getCanonicalFnName(
                   DIFrame.FunctionName);
@@ -732,7 +732,9 @@ Error RawMemProfReader::readRawProfile(
     // profiles in this binary file.
     const llvm::SmallVector<SegmentEntry> Entries =
         readSegmentEntries(Next + Header->SegmentOffset);
-    if (!SegmentInfo.empty() && SegmentInfo != Entries) {
+    if (!SegmentInfo.empty() &&
+        (llvm::ArrayRef<llvm::memprof::SegmentEntry>(SegmentInfo) !=
+         llvm::ArrayRef<llvm::memprof::SegmentEntry>(Entries))) {
       // We do not expect segment information to change when deserializing from
       // the same binary profile file. This can happen if dynamic libraries are
       // loaded/unloaded between profile dumping.
@@ -811,7 +813,7 @@ Error RawMemProfReader::readNextRecord(
   // true. This is useful for debugging and testing.
   auto IdToFrameCallback = [this](const FrameId Id) {
     Frame F = this->idToFrame(Id);
-    if (!this->KeepSymbolName)
+    if (!this->getKeepSymbolName())
       return F;
     auto Iter = this->GuidToSymbolName.find(F.Function);
     assert(Iter != this->GuidToSymbolName.end());
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index d6a6aef1c59f9..9e8084e70cbe8 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -278,10 +278,10 @@ SampleProfileWriterExtBinaryBase::writeSample(const FunctionSamples &S) {
 std::error_code
 SampleProfileWriterExtBinaryBase::writeFuncOffsetTable(SecType Type,
                                                        bool IsNested) {
-  if (UseMD5IndexedTables) {
+  if (getUseMD5IndexedTablesFlag()) {
     // Eytzinger layout requires MD5 representation and does not support
     // multi-context Context-Sensitive profiles.
-    if (!UseMD5 || FunctionSamples::ProfileIsCS)
+    if (!getUseMD5Flag() || FunctionSamples::ProfileIsCS)
       return sampleprof_error::unsupported_writing_format;
     return writeEytzingerFuncOffsetTable(Type, IsNested);
   }
@@ -430,7 +430,7 @@ stabilizeTable(MapVector<KeyT, ValT> &Table) {
 }
 
 std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
-  if (!UseMD5)
+  if (!getUseMD5Flag())
     return SampleProfileWriterBinary::writeNameTable();
 
   auto &OS = *OutputStream;
@@ -456,7 +456,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection(
   // so compiler won't strip the suffix during profile matching after
   // seeing the flag in the profile.
   // Original names are unavailable if using MD5, so this option has no use.
-  if (!UseMD5) {
+  if (!getUseMD5Flag()) {
     for (const auto &I : NameTable) {
       if (I.first.stringRef().contains(FunctionSamples::UniqSuffix)) {
         addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
@@ -465,7 +465,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection(
     }
   }
 
-  if (UseMD5 && UseMD5IndexedTables) {
+  if (getUseMD5Flag() && getUseMD5IndexedTablesFlag()) {
     // Eytzinger name tables do not support CSSPGO profiles
     // (FunctionSamples::ProfileIsCS).
     if (FunctionSamples::ProfileIsCS)
@@ -596,7 +596,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeCSNameTableSection() {
 
 std::error_code
 SampleProfileWriterExtBinaryBase::writeProfileSymbolListSection() {
-  if (UseMD5ProfSymList)
+  if (getUseMD5ProfSymList())
     return writeMD5ProfileSymbolListSection();
   return writeStringBasedProfileSymbolListSection();
 }
@@ -658,9 +658,9 @@ std::error_code SampleProfileWriterExtBinaryBase::writeOneSection(
   if (Type == SecProfSummary && ExtBinaryWriteVTableTypeProf)
     addSectionFlag(SecProfSummary,
                    SecProfSummaryFlags::SecFlagHasVTableTypeProf);
-  if (Type == SecProfileSymbolList && UseMD5ProfSymList)
+  if (Type == SecProfileSymbolList && getUseMD5ProfSymList())
     addSectionFlag(SecProfileSymbolList, SecProfileSymbolListFlags::SecFlagMD5);
-  if (Type == SecNameTable && UseMD5IndexedTables && UseMD5)
+  if (Type == SecNameTable && getUseMD5IndexedTablesFlag() && getUseMD5Flag())
     addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagEytzinger);
 
   uint64_t SectionStart = markSectionStart(Type, LayoutIdx);
diff --git a/llvm/lib/Support/DebugCounter.cpp b/llvm/lib/Support/DebugCounter.cpp
index d9786838aba23..f21554a2acfd2 100644
--- a/llvm/lib/Support/DebugCounter.cpp
+++ b/llvm/lib/Support/DebugCounter.cpp
@@ -138,8 +138,8 @@ void DebugCounter::push_back(const std::string &Val) {
     });
     exit(1);
   }
-  Counter->Chunks = std::move(*ExpectedChunks);
-  Counter->Active = Counter->IsSet = true;
+  Counter->Chunks.assign(std::move(*ExpectedChunks));
+  Counter->setActive(Counter->setIsSet(true));
 }
 
 void DebugCounter::print(raw_ostream &OS) const {
@@ -183,7 +183,7 @@ bool DebugCounter::handleCounterIncrement(CounterInfo &Info) {
 bool DebugCounter::shouldExecuteImpl(CounterInfo &Counter) {
   auto &Us = instance();
   bool Res = Us.handleCounterIncrement(Counter);
-  if (Us.ShouldPrintCounterQueries && Counter.IsSet) {
+  if (Us.ShouldPrintCounterQueries && Counter.getIsSet()) {
     dbgs() << "DebugCounter " << Counter.Name << "=" << (Counter.Count - 1)
            << (Res ? " execute" : " skip") << "\n";
   }
diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp
index 9a6ce774e4150..dc6bc4dddbc3f 100644
--- a/llvm/lib/Support/GlobPattern.cpp
+++ b/llvm/lib/Support/GlobPattern.cpp
@@ -186,7 +186,7 @@ Expected<GlobPattern> GlobPattern::create(StringRef S,
                                           std::optional<size_t> MaxSubPatterns,
                                           bool SlashAgnostic) {
   GlobPattern Pat;
-  Pat.SlashAgnostic = SlashAgnostic;
+  Pat.SubGlobs.setFlag(0, SlashAgnostic);
   Pat.Pattern = S;
 
   const char *PrefixMetas =
@@ -244,7 +244,7 @@ std::optional<std::string> GlobPattern::asLiteral() const {
   // In slash-agnostic mode '/' and '\\' match each other, so a pattern holding
   // either matches more than one string. A pattern with no sub-pattern cannot
   // reach here holding one, as both are prefix metacharacters in that mode.
-  if (SlashAgnostic &&
+  if (SubGlobs.getFlag(0) &&
       StringRef(Literal).find_first_of("/\\") != StringRef::npos)
     return std::nullopt;
 
@@ -287,7 +287,7 @@ GlobPattern::SubGlobPattern::create(StringRef S, bool SlashAgnostic) {
         return make_error<StringError>("invalid glob pattern, stray '\\'",
                                        errc::invalid_argument);
     } else if (S[I] == '*' || S[I] == '?') {
-      Pat.HasWildcard = true;
+      Pat.Pat.setFlag(0, true);
     }
   }
   return Pat;
@@ -295,7 +295,7 @@ GlobPattern::SubGlobPattern::create(StringRef S, bool SlashAgnostic) {
 
 StringRef GlobPattern::longest_substr() const {
   return maxPlainSubstring(Pattern.drop_front(PrefixSize).drop_back(SuffixSize),
-                           SlashAgnostic);
+                           SubGlobs.getFlag(0));
 }
 
 bool GlobPattern::match(StringRef S) const {
@@ -306,7 +306,7 @@ bool GlobPattern::match(StringRef S) const {
   if (SubGlobs.empty() && S.empty())
     return true;
   for (auto &Glob : SubGlobs)
-    if (Glob.match(S, SlashAgnostic))
+    if (Glob.match(S, SubGlobs.getFlag(0)))
       return true;
   return false;
 }
diff --git a/llvm/lib/Support/LSP/Transport.cpp b/llvm/lib/Support/LSP/Transport.cpp
index e79ca679878d0..94e4b743f155a 100644
--- a/llvm/lib/Support/LSP/Transport.cpp
+++ b/llvm/lib/Support/LSP/Transport.cpp
@@ -244,13 +244,15 @@ llvm::Error JSONTransport::run(MessageHandler &Handler) {
 }
 
 void JSONTransport::sendMessage(llvm::json::Value Msg) {
-  OutputBuffer.clear();
-  llvm::raw_svector_ostream os(OutputBuffer);
-  os << llvm::formatv(PrettyOutput ? "{0:2}\n" : "{0}", Msg);
-  Out << "Content-Length: " << OutputBuffer.size() << "\r\n\r\n"
-      << OutputBuffer;
+  SmallVector<char, 0> Buffer;
+  Buffer = std::move(OutputBuffer);
+  Buffer.clear();
+  llvm::raw_svector_ostream os(Buffer);
+  os << llvm::formatv(getPrettyOutput() ? "{0:2}\n" : "{0}", Msg);
+  Out << "Content-Length: " << Buffer.size() << "\r\n\r\n" << Buffer;
   Out.flush();
-  Logger::debug(">>> {0}\n", OutputBuffer);
+  Logger::debug(">>> {0}\n", Buffer);
+  OutputBuffer.assign(std::move(Buffer));
 }
 
 bool JSONTransport::handleMessage(llvm::json::Value Msg,
diff --git a/llvm/lib/Support/SuffixTree.cpp b/llvm/lib/Support/SuffixTree.cpp
index a31287836e860..8873b58e646bc 100644
--- a/llvm/lib/Support/SuffixTree.cpp
+++ b/llvm/lib/Support/SuffixTree.cpp
@@ -329,7 +329,7 @@ void SuffixTree::RepeatedSubstringIterator::advance() {
       continue;
 
     // Collect leaf children or leaf descendants by OutlinerLeafDescendants.
-    if (OutlinerLeafDescendants) {
+    if (getOutlinerLeafDescendants()) {
       for (unsigned I = Curr->getLeftLeafIdx(); I <= Curr->getRightLeafIdx();
            ++I)
         RepeatedSubstringStarts.push_back(LeafNodes[I]->getSuffixIdx());
diff --git a/llvm/lib/Support/YAMLParser.cpp b/llvm/lib/Support/YAMLParser.cpp
index 2ee104aa2be60..1da4864f41a58 100644
--- a/llvm/lib/Support/YAMLParser.cpp
+++ b/llvm/lib/Support/YAMLParser.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -259,7 +260,8 @@ class Scanner {
 
   void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message,
                   ArrayRef<SMRange> Ranges = {}) {
-    SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ {}, ShowColors);
+    SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ {},
+                    getShowColors());
   }
 
   void setError(const Twine &Message, StringRef::iterator Position) {
@@ -272,15 +274,13 @@ class Scanner {
 
     // Don't print out more errors after the first one we encounter. The rest
     // are just the result of the first, and have no meaning.
-    if (!Failed)
+    if (!getFailed())
       printError(SMLoc::getFromPointer(Position), SourceMgr::DK_Error, Message);
-    Failed = true;
+    setFailed(true);
   }
 
   /// Returns true if an error occurred while parsing.
-  bool failed() {
-    return Failed;
-  }
+  bool failed() { return getFailed(); }
 
 private:
   void init(MemoryBufferRef Buffer);
@@ -543,20 +543,27 @@ class Scanner {
   unsigned FlowLevel;
 
   /// Are we at the start of the stream?
-  bool IsStartOfStream;
+  bool getIsStartOfStream() const { return SimpleKeys.getFlag(0); }
+  void setIsStartOfStream(bool Value) { SimpleKeys.setFlag(0, Value); }
 
   /// Can the next token be the start of a simple key?
-  bool IsSimpleKeyAllowed;
+  bool getIsSimpleKeyAllowed() const { return SimpleKeys.getFlag(1); }
+  void setIsSimpleKeyAllowed(bool Value) { SimpleKeys.setFlag(1, Value); }
 
   /// Can the next token be a value indicator even if it does not have a
   /// trailing space?
-  bool IsAdjacentValueAllowedInFlow;
+  bool getIsAdjacentValueAllowedInFlow() const { return SimpleKeys.getFlag(2); }
+  void setIsAdjacentValueAllowedInFlow(bool Value) {
+    SimpleKeys.setFlag(2, Value);
+  }
 
   /// True if an error has occurred.
-  bool Failed;
+  bool getFailed() const { return SimpleKeys.getFlag(3); }
+  void setFailed(bool Value) { SimpleKeys.setFlag(3, Value); }
 
   /// Should colors be used when printing out the diagnostic messages?
-  bool ShowColors;
+  bool getShowColors() const { return Indents.getFlag(0); }
+  void setShowColors(bool Value) { Indents.setFlag(0, Value); }
 
   /// Queue of tokens. This is required to queue up tokens while looking
   ///        for the end of a simple key. And for cases where a single character
@@ -564,10 +571,10 @@ class Scanner {
   TokenQueueT TokenQueue;
 
   /// Indentation levels.
-  SmallVector<int, 4> Indents;
+  llvm::SmallVectorWithFlags<int, 4> Indents;
 
   /// Potential simple keys.
-  SmallVector<SimpleKey, 4> SimpleKeys;
+  llvm::SmallVectorWithFlags<SimpleKey, 4, 4> SimpleKeys;
 
   std::error_code *EC;
 };
@@ -856,13 +863,16 @@ std::optional<bool> yaml::parseBool(StringRef S) {
 
 Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors,
                  std::error_code *EC)
-    : SM(sm), ShowColors(ShowColors), EC(EC) {
+    : SM(sm), Indents(decltype(this->Indents)::withFlags(unsigned(ShowColors))),
+      EC(EC) {
   init(MemoryBufferRef(Input, "YAML"));
 }
 
 Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors,
                  std::error_code *EC)
-    : SM(SM_), ShowColors(ShowColors), EC(EC) {
+    : SM(SM_),
+      Indents(decltype(this->Indents)::withFlags(unsigned(ShowColors))),
+      EC(EC) {
   init(Buffer);
 }
 
@@ -874,10 +884,10 @@ void Scanner::init(MemoryBufferRef Buffer) {
   Column = 0;
   Line = 0;
   FlowLevel = 0;
-  IsStartOfStream = true;
-  IsSimpleKeyAllowed = true;
-  IsAdjacentValueAllowedInFlow = false;
-  Failed = false;
+  setIsStartOfStream(true);
+  setIsSimpleKeyAllowed(true);
+  setIsAdjacentValueAllowedInFlow(false);
+  setFailed(false);
   std::unique_ptr<MemoryBuffer> InputBufferOwner =
       MemoryBuffer::getMemBuffer(Buffer, /*RequiresNullTerminator=*/false);
   SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc());
@@ -1086,7 +1096,7 @@ bool Scanner::consumeLineBreakIfPresent() {
 void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok
                                     , unsigned AtColumn
                                     , bool IsRequired) {
-  if (IsSimpleKeyAllowed) {
+  if (getIsSimpleKeyAllowed()) {
     SimpleKey SK;
     SK.Tok = Tok;
     SK.Line = Line;
@@ -1180,12 +1190,12 @@ void Scanner::scanToNextToken() {
     Column = 0;
     // New lines may start a simple key.
     if (!FlowLevel)
-      IsSimpleKeyAllowed = true;
+      setIsSimpleKeyAllowed(true);
   }
 }
 
 bool Scanner::scanStreamStart() {
-  IsStartOfStream = false;
+  setIsStartOfStream(false);
 
   EncodingInfo EI = getUnicodeEncoding(currentInput());
 
@@ -1206,8 +1216,8 @@ bool Scanner::scanStreamEnd() {
 
   unrollIndent(-1);
   SimpleKeys.clear();
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   Token T;
   T.Kind = Token::TK_StreamEnd;
@@ -1220,8 +1230,8 @@ bool Scanner::scanDirective() {
   // Reset the indentation level.
   unrollIndent(-1);
   SimpleKeys.clear();
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   StringRef::iterator Start = Current;
   consume('%');
@@ -1252,8 +1262,8 @@ bool Scanner::scanDirective() {
 bool Scanner::scanDocumentIndicator(bool IsStart) {
   unrollIndent(-1);
   SimpleKeys.clear();
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   Token T;
   T.Kind = IsStart ? Token::TK_DocumentStart : Token::TK_DocumentEnd;
@@ -1275,17 +1285,17 @@ bool Scanner::scanFlowCollectionStart(bool IsSequence) {
   saveSimpleKeyCandidate(--TokenQueue.end(), Column - 1, false);
 
   // And may also be followed by a simple key.
-  IsSimpleKeyAllowed = true;
+  setIsSimpleKeyAllowed(true);
   // Adjacent values are allowed in flows only after JSON-style keys.
-  IsAdjacentValueAllowedInFlow = false;
+  setIsAdjacentValueAllowedInFlow(false);
   ++FlowLevel;
   return true;
 }
 
 bool Scanner::scanFlowCollectionEnd(bool IsSequence) {
   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = true;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(true);
   Token T;
   T.Kind = IsSequence ? Token::TK_FlowSequenceEnd
                       : Token::TK_FlowMappingEnd;
@@ -1299,8 +1309,8 @@ bool Scanner::scanFlowCollectionEnd(bool IsSequence) {
 
 bool Scanner::scanFlowEntry() {
   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
-  IsSimpleKeyAllowed = true;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(true);
+  setIsAdjacentValueAllowedInFlow(false);
   Token T;
   T.Kind = Token::TK_FlowEntry;
   T.Range = StringRef(Current, 1);
@@ -1312,8 +1322,8 @@ bool Scanner::scanFlowEntry() {
 bool Scanner::scanBlockEntry() {
   rollIndent(Column, Token::TK_BlockSequenceStart, TokenQueue.end());
   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
-  IsSimpleKeyAllowed = true;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(true);
+  setIsAdjacentValueAllowedInFlow(false);
   Token T;
   T.Kind = Token::TK_BlockEntry;
   T.Range = StringRef(Current, 1);
@@ -1327,8 +1337,8 @@ bool Scanner::scanKey() {
     rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
 
   removeSimpleKeyCandidatesOnFlowLevel(FlowLevel);
-  IsSimpleKeyAllowed = !FlowLevel;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(!FlowLevel);
+  setIsAdjacentValueAllowedInFlow(false);
 
   Token T;
   T.Kind = Token::TK_Key;
@@ -1352,7 +1362,7 @@ bool Scanner::scanValue() {
         break;
     }
     if (i == e) {
-      Failed = true;
+      setFailed(true);
       return false;
     }
     i = TokenQueue.insert(i, T);
@@ -1360,13 +1370,13 @@ bool Scanner::scanValue() {
     // We may also need to add a Block-Mapping-Start token.
     rollIndent(SK.Column, Token::TK_BlockMappingStart, i);
 
-    IsSimpleKeyAllowed = false;
+    setIsSimpleKeyAllowed(false);
   } else {
     if (!FlowLevel)
       rollIndent(Column, Token::TK_BlockMappingStart, TokenQueue.end());
-    IsSimpleKeyAllowed = !FlowLevel;
+    setIsSimpleKeyAllowed(!FlowLevel);
   }
-  IsAdjacentValueAllowedInFlow = false;
+  setIsAdjacentValueAllowedInFlow(false);
 
   Token T;
   T.Kind = Token::TK_Value;
@@ -1447,8 +1457,8 @@ bool Scanner::scanFlowScalar(bool IsDoubleQuoted) {
 
   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
 
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = true;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(true);
 
   return true;
 }
@@ -1515,8 +1525,8 @@ bool Scanner::scanPlainScalar() {
   // Plain scalars can be simple keys.
   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
 
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   return true;
 }
@@ -1551,8 +1561,8 @@ bool Scanner::scanAliasOrAnchor(bool IsAlias) {
   // Alias and anchors can be simple keys.
   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
 
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   return true;
 }
@@ -1784,8 +1794,8 @@ bool Scanner::scanBlockScalar(bool IsLiteral) {
 
   // New lines may start a simple key.
   if (!FlowLevel)
-    IsSimpleKeyAllowed = true;
-  IsAdjacentValueAllowedInFlow = false;
+    setIsSimpleKeyAllowed(true);
+  setIsAdjacentValueAllowedInFlow(false);
 
   Token T;
   T.Kind = Token::TK_BlockScalar;
@@ -1818,14 +1828,14 @@ bool Scanner::scanTag() {
   // Tags can be simple keys.
   saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false);
 
-  IsSimpleKeyAllowed = false;
-  IsAdjacentValueAllowedInFlow = false;
+  setIsSimpleKeyAllowed(false);
+  setIsAdjacentValueAllowedInFlow(false);
 
   return true;
 }
 
 bool Scanner::fetchMoreTokens() {
-  if (IsStartOfStream)
+  if (getIsStartOfStream())
     return scanStreamStart();
 
   scanToNextToken();
@@ -1876,7 +1886,7 @@ bool Scanner::fetchMoreTokens() {
     return scanKey();
 
   if (*Current == ':' &&
-      (!isPlainSafeNonBlank(Current + 1) || IsAdjacentValueAllowedInFlow))
+      (!isPlainSafeNonBlank(Current + 1) || getIsAdjacentValueAllowedInFlow()))
     return scanValue();
 
   if (*Current == '*')
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index bbddfc8b4e72e..d83ca7be79f3e 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -769,7 +769,7 @@ const Record *TGParser::ParseClassID() {
                Lex.getCurStrVal() + "'");
     else
       TokError(Msg);
-  } else if (TrackReferenceLocs) {
+  } else if (getTrackReferenceLocs()) {
     Result->appendReferenceLoc(Lex.getLocRange());
   }
 
@@ -1197,7 +1197,7 @@ const RecTy *TGParser::ParseType() {
 const Init *TGParser::ParseIDValue(Record *CurRec, const StringInit *Name,
                                    SMRange NameLoc, IDParseMode Mode) {
   if (const Init *I = CurScope->getVar(Records, CurMultiClass, Name, NameLoc,
-                                       TrackReferenceLocs))
+                                       getTrackReferenceLocs()))
     return I;
 
   if (Mode == ParseNameMode)
@@ -1205,7 +1205,7 @@ const Init *TGParser::ParseIDValue(Record *CurRec, const StringInit *Name,
 
   if (const Init *I = Records.getGlobal(Name->getValue())) {
     // Add a reference to the global if it's a record.
-    if (TrackReferenceLocs) {
+    if (getTrackReferenceLocs()) {
       if (const auto *Def = dyn_cast<DefInit>(I))
         Def->getDef()->appendReferenceLoc(NameLoc);
     }
@@ -3045,7 +3045,7 @@ const Init *TGParser::ParseSimpleValue(Record *CurRec, const RecTy *ItemType,
     if (resolveArguments(Class, Args, NameLoc.Start))
       return nullptr;
 
-    if (TrackReferenceLocs)
+    if (getTrackReferenceLocs())
       Class->appendReferenceLoc(NameLoc);
     return VarDefInit::get(NameLoc.Start, Class, Args)->Fold();
   }
@@ -3334,7 +3334,7 @@ const Init *TGParser::ParseValue(Record *CurRec, const RecTy *ItemType,
       }
 
       // Add a reference to this field if we know the record class.
-      if (TrackReferenceLocs) {
+      if (getTrackReferenceLocs()) {
         if (const auto *DI = dyn_cast<DefInit>(Result)) {
           DI->getDef()->appendValueReferenceLoc(FieldName, FieldNameLoc);
         } else if (const auto *TI = dyn_cast<TypedInit>(Result)) {
@@ -4391,7 +4391,7 @@ bool TGParser::ParseClass() {
   if (ParseObjectBody(CurRec))
     return true;
 
-  if (!NoWarnOnUnusedTemplateArgs)
+  if (!getNoWarnOnUnusedTemplateArgs())
     CurRec->checkUnusedTemplateArgs();
 
   PopScope(ClassScope);
@@ -4590,7 +4590,7 @@ bool TGParser::ParseMultiClass() {
     }
   }
 
-  if (!NoWarnOnUnusedTemplateArgs)
+  if (!getNoWarnOnUnusedTemplateArgs())
     CurMultiClass->Rec.checkUnusedTemplateArgs();
 
   PopScope(MulticlassScope);
diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h
index 31b59628a6cac..7f0598f822ae7 100644
--- a/llvm/lib/TableGen/TGParser.h
+++ b/llvm/lib/TableGen/TGParser.h
@@ -14,6 +14,7 @@
 #define LLVM_LIB_TABLEGEN_TGPARSER_H
 
 #include "TGLexer.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
 #include <map>
@@ -164,7 +165,7 @@ class TGParser {
   ///
   std::vector<std::unique_ptr<ForeachLoop>> Loops;
 
-  SmallVector<DefsetRecord *, 2> Defsets;
+  llvm::SmallVectorWithFlags<DefsetRecord *, 2, 2> Defsets;
 
   /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the
   /// current value.
@@ -187,16 +188,19 @@ class TGParser {
                     // exist.
   };
 
-  bool NoWarnOnUnusedTemplateArgs = false;
-  bool TrackReferenceLocs = false;
+  bool getNoWarnOnUnusedTemplateArgs() const { return Defsets.getFlag(0); }
+  void setNoWarnOnUnusedTemplateArgs(bool Value) { Defsets.setFlag(0, Value); }
+  bool getTrackReferenceLocs() const { return Defsets.getFlag(1); }
+  void setTrackReferenceLocs(bool Value) { Defsets.setFlag(1, Value); }
 
 public:
   TGParser(SourceMgr &SM, ArrayRef<std::string> Macros, RecordKeeper &records,
            const bool NoWarnOnUnusedTemplateArgs = false,
            const bool TrackReferenceLocs = false)
-      : Lex(SM, Macros), CurMultiClass(nullptr), Records(records),
-        NoWarnOnUnusedTemplateArgs(NoWarnOnUnusedTemplateArgs),
-        TrackReferenceLocs(TrackReferenceLocs) {}
+      : Lex(SM, Macros), Defsets(decltype(Defsets)::withFlags(
+                             unsigned(NoWarnOnUnusedTemplateArgs) |
+                             (unsigned(TrackReferenceLocs) << 1))),
+        CurMultiClass(nullptr), Records(records) {}
 
   /// ParseFile - Main entrypoint for parsing a tblgen file. These parser
   /// routines return true on error, or false on success.
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e3257af644550..e81876aa2e512 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9320,8 +9320,8 @@ SDValue AArch64TargetLowering::lowerEHPadEntry(SDValue Chain, SDLoc const &DL,
 
 SDValue AArch64TargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   const Function &F = MF.getFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -9987,8 +9987,8 @@ static void analyzeCallOperands(const AArch64TargetLowering &TLI,
                                 CCState &CCInfo) {
   const SelectionDAG &DAG = CLI.DAG;
   CallingConv::ID CalleeCC = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
-  const SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
+  bool IsVarArg = CLI.getIsVarArg();
+  const auto &Outs = CLI.Outs;
   bool IsCalleeWin64 = Subtarget->isCallingConvWin64(CalleeCC, IsVarArg);
 
   // For Arm64EC thunks, allocate 32 extra bytes at the bottom of the stack
@@ -10061,10 +10061,10 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
     return false;
 
   SDValue Callee = CLI.Callee;
-  bool IsVarArg = CLI.IsVarArg;
-  const SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
+  bool IsVarArg = CLI.getIsVarArg();
+  const auto &Outs = CLI.Outs;
   const SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
-  const SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
+  const auto &Ins = CLI.Ins;
   const SelectionDAG &DAG = CLI.DAG;
   MachineFunction &MF = DAG.getMachineFunction();
   const Function &CallerF = MF.getFunction();
@@ -10446,14 +10446,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
                                  SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
-  SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID &CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
@@ -10519,9 +10518,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   std::optional<unsigned> ZAMarkerNode = getZAMarkerForCall(CallAttrs);
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     // Check if it's really possible to do a tail call.
-    IsTailCall = isEligibleForTailCallOptimization(CLI);
+    CLI.setIsTailCall(isEligibleForTailCallOptimization(CLI));
 
     // If we have a tail-call, it's safe to drop ZAMarkerNode since
     // 1. INOUT_ZA_USE is the only marker node that can reach this point
@@ -10530,7 +10529,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
     // 2. INOUT_ZA_USE is redunant on a tail call, since a tail call is a return
     // for which MachineSMEABIPass requires an acitve ZA state anyway, the
     // marker node doesn't add anything.
-    if (IsTailCall && ZAMarkerNode) {
+    if (CLI.getIsTailCall() && ZAMarkerNode) {
       assert(ZAMarkerNode == AArch64ISD::INOUT_ZA_USE &&
              "Unexpected SME ZA marker node");
       ZAMarkerNode = std::nullopt;
@@ -10538,15 +10537,15 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
 
     // A sibling call is one where we're under the usual C ABI and not planning
     // to change that but can still do a tail call:
-    if (!ZAMarkerNode && !TailCallOpt && IsTailCall &&
+    if (!ZAMarkerNode && !TailCallOpt && CLI.getIsTailCall() &&
         CallConv != CallingConv::Tail && CallConv != CallingConv::SwiftTail)
       IsSibCall = true;
 
-    if (IsTailCall)
+    if (CLI.getIsTailCall())
       ++NumTailCalls;
   }
 
-  if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall())
+  if (!CLI.getIsTailCall() && CLI.CB && CLI.CB->isMustTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
                        "site marked musttail");
 
@@ -10567,7 +10566,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   int FPDiff = 0;
   const Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
 
-  if (IsTailCall && !IsSibCall) {
+  if (CLI.getIsTailCall() && !IsSibCall) {
     unsigned NumReusableBytes = FuncInfo->getBytesInStackArgArea();
 
     // In general, neither NumBytes nor NumReusableBytes is guaranteed to be
@@ -10642,7 +10641,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
     if (Outs.size() < 2)
       report_fatal_error("variadic arm64ec_thunk_x64 call is missing the "
                          "x4/x5 (pointer/length) arguments");
-    if (IsTailCall)
+    if (CLI.getIsTailCall())
       report_fatal_error("tail calls are not supported for variadic "
                          "arm64ec_thunk_x64 calls");
 
@@ -10675,7 +10674,8 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   // These operations are automatically eliminated by the prolog/epilog pass
   assert((!IsSibCall || !ZAMarkerNode) && "ZA markers require CALLSEQ_START");
   if (!IsSibCall) {
-    Chain = DAG.getCALLSEQ_START(Chain, IsTailCall ? 0 : NumBytes, 0, DL);
+    Chain =
+        DAG.getCALLSEQ_START(Chain, CLI.getIsTailCall() ? 0 : NumBytes, 0, DL);
     if (ZAMarkerNode) {
       // Note: We need the CALLSEQ_START to glue the ZAMarkerNode to, simply
       // using a chain can result in incorrect scheduling. The markers refer to
@@ -10899,7 +10899,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
       unsigned LocMemOffset = VA.getLocMemOffset();
       int32_t Offset = LocMemOffset + BEAlign;
 
-      if (IsTailCall) {
+      if (CLI.getIsTailCall()) {
         // When the frame pointer is perfectly aligned for the tail call and the
         // same stack argument is passed down intact, we can reuse it.
         if (!FPDiff && !shouldLowerTailCallStackArg(MF, VA, Arg, Flags, Offset))
@@ -10950,7 +10950,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   if (IsVarArg && Subtarget->isWindowsArm64EC() &&
       !(CLI.CB && CLI.CB->isMustTailCall()) && !IsArm64ECVarArgExitThunk) {
     SDValue ParamPtr = StackPtr;
-    if (IsTailCall) {
+    if (CLI.getIsTailCall()) {
       // Create a dummy object at the top of the stack that can be used to get
       // the SP after the epilogue
       int FI = MF.getFrameInfo().CreateFixedObject(1, FPDiff, true);
@@ -10999,7 +10999,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
     if (OpFlags & AArch64II::MO_GOT) {
       Callee = DAG.getTargetGlobalAddress(CalledGlobal, DL, PtrVT, 0, OpFlags);
       Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
-    } else if (!CLI.PAI || !IsTailCall) {
+    } else if (!CLI.PAI || !CLI.getIsTailCall()) {
       const GlobalValue *GV = G->getGlobal();
       Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags);
     }
@@ -11020,12 +11020,12 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   // the frame up *after* the call, however in the ABI-changing tail-call case
   // we've carefully laid out the parameters so that when sp is reset they'll be
   // in the correct location.
-  if (IsTailCall && !IsSibCall) {
+  if (CLI.getIsTailCall() && !IsSibCall) {
     Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InGlue, DL);
     InGlue = Chain.getValue(1);
   }
 
-  unsigned Opc = IsTailCall ? AArch64ISD::TC_RETURN : AArch64ISD::CALL;
+  unsigned Opc = CLI.getIsTailCall() ? AArch64ISD::TC_RETURN : AArch64ISD::CALL;
 
   std::vector<SDValue> Ops;
   Ops.push_back(Chain);
@@ -11035,7 +11035,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   // be expanded to the call, directly followed by a special marker sequence and
   // a call to an ObjC library function.  Use CALL_RVMARKER to do that.
   if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB)) {
-    assert(!IsTailCall &&
+    assert(!CLI.getIsTailCall() &&
            "tail calls cannot be marked with clang.arc.attachedcall");
     Opc = AArch64ISD::CALL_RVMARKER;
 
@@ -11057,7 +11057,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
     Opc = AArch64ISD::CALL_BTI;
   }
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     // Each tail call may have to adjust the stack by a different amount, so
     // this information must travel along with the operation for eventual
     // consumption by emitEpilogue.
@@ -11077,7 +11077,8 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
     if (Opc == AArch64ISD::CALL_RVMARKER)
       Opc = AArch64ISD::AUTH_CALL_RVMARKER;
     else
-      Opc = IsTailCall ? AArch64ISD::AUTH_TC_RETURN : AArch64ISD::AUTH_CALL;
+      Opc = CLI.getIsTailCall() ? AArch64ISD::AUTH_TC_RETURN
+                                : AArch64ISD::AUTH_CALL;
     Ops.push_back(DAG.getTargetConstant(Key, DL, MVT::i32));
     Ops.push_back(IntDisc);
     Ops.push_back(AddrDisc);
@@ -11119,13 +11120,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // If we're doing a tall call, use a TC_RETURN here rather than an
   // actual call instruction.
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     SDValue Ret = DAG.getNode(Opc, DL, MVT::Other, Ops);
     if (IsCFICall)
       Ret->setCFIType(CLI.CFIType->getZExtValue());
 
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
     if (CalledGlobal &&
         MF.getFunction().getParent()->getModuleFlag("import-call-optimization"))
@@ -11138,7 +11139,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   if (IsCFICall)
     Chain->setCFIType(CLI.CFIType->getZExtValue());
 
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   InGlue = Chain.getValue(1);
   DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
   if (CalledGlobal &&
@@ -11199,10 +11200,11 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
   return Result;
 }
 
-bool AArch64TargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool AArch64TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                           MachineFunction &MF, bool isVarArg,
+                                           llvm::ArrayRef<ISD::OutputArg> Outs,
+                                           LLVMContext &Context,
+                                           const Type *RetTy) const {
   CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
@@ -11212,7 +11214,7 @@ bool AArch64TargetLowering::CanLowerReturn(
 SDValue
 AArch64TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                    bool isVarArg,
-                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                   llvm::ArrayRef<ISD::OutputArg> Outs,
                                    const SmallVectorImpl<SDValue> &OutVals,
                                    const SDLoc &DL, SelectionDAG &DAG) const {
   auto &MF = DAG.getMachineFunction();
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index a017e0508b57c..334a3a8c2dbf2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -638,8 +638,7 @@ class AArch64TargetLowering : public TargetLowering {
                           SelectionDAG &DAG) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -691,12 +690,11 @@ class AArch64TargetLowering : public TargetLowering {
                            SDValue &Chain) const;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index f60a4deb98ab0..cbee946dd63ed 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/CFIInstBuilder.h"
 #include "llvm/CodeGen/LivePhysRegs.h"
@@ -11957,10 +11958,11 @@ class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
   /// The initial value of the loop counter
   Register Init;
   /// True iff Update is a predecessor of Comp
-  bool IsUpdatePriorComp;
+  bool getIsUpdatePriorComp() const { return Cond.getFlag(0); }
+  void setIsUpdatePriorComp(bool Value) { Cond.setFlag(0, Value); }
 
   /// The normalized condition used by createTripCountGreaterCondition()
-  SmallVector<MachineOperand, 4> Cond;
+  llvm::SmallVectorWithFlags<MachineOperand, 4> Cond;
 
 public:
   AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
@@ -11974,7 +11976,7 @@ class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
         LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
         CompCounterOprNum(CompCounterOprNum), Update(Update),
         UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
-        IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
+        Cond(unsigned(IsUpdatePriorComp), Cond.begin(), Cond.end()) {}
 
   bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
     // Make the instructions for loop control be placed in stage 0.
@@ -11988,7 +11990,7 @@ class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
     // A branch instruction will be inserted as "if (Cond) goto epilogue".
     // Cond is normalized for such use.
     // The predecessors of the branch are assumed to have already been inserted.
-    CondParam = Cond;
+    CondParam.assign(Cond.begin(), Cond.end());
     return {};
   }
 
@@ -12080,7 +12082,7 @@ void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
 
       if (I != TC) {
         if (I == 0) {
-          if (Update != Comp && IsUpdatePriorComp) {
+          if (Update != Comp && getIsUpdatePriorComp()) {
             Counter =
                 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
             NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
@@ -12102,7 +12104,7 @@ void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
       // use initial counter value (testing if the trip count is sufficient to
       // be executed by pipelined code)
       Counter = Init;
-      if (IsUpdatePriorComp)
+      if (getIsUpdatePriorComp())
         Counter =
             cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
     } else {
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
index 004315b025119..fa11aaa777d6c 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
@@ -122,8 +122,8 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
   if (F.hasFnAttribute(Attribute::NoRedZone))
     HasRedZone = false;
   SignCondition = GetSignReturnAddress(F);
-  SignWithBKey = ShouldSignWithBKey(F, *STI);
-  HasELFSignedGOT = hasELFSignedGOTHelper(F, STI);
+  setSignWithBKey(ShouldSignWithBKey(F, *STI));
+  setHasELFSignedGOT(hasELFSignedGOTHelper(F, STI));
   // TODO: skip functions that have no instrumented allocas for optimization
   IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);
 
@@ -140,8 +140,8 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
   }
 
   // BTI/PAuthLR are set on the function attribute.
-  BranchTargetEnforcement = F.hasFnAttribute("branch-target-enforcement");
-  BranchProtectionPAuthLR = F.hasFnAttribute("branch-protection-pauth-lr");
+  setBranchTargetEnforcement(F.hasFnAttribute("branch-target-enforcement"));
+  setBranchProtectionPAuthLR(F.hasFnAttribute("branch-protection-pauth-lr"));
 
   // Parse the SME function attributes.
   SMEFnAttrs = SMEAttrs(F);
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 5860dff473823..6db0b19197bf8 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -82,8 +83,18 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
   unsigned CalleeSavedStackSize = 0;
   unsigned ZPRCalleeSavedStackSize = 0;
   unsigned PPRCalleeSavedStackSize = 0;
-  bool HasCalleeSavedStackSize = false;
-  bool HasSVECalleeSavedStackSize = false;
+  bool getHasCalleeSavedStackSize() const {
+    return JumpTableEntryInfo.getFlag(0);
+  }
+  void setHasCalleeSavedStackSize(bool Value) {
+    JumpTableEntryInfo.setFlag(0, Value);
+  }
+  bool getHasSVECalleeSavedStackSize() const {
+    return JumpTableEntryInfo.getFlag(1);
+  }
+  void setHasSVECalleeSavedStackSize(bool Value) {
+    JumpTableEntryInfo.setFlag(1, Value);
+  }
 
   /// Number of TLS accesses using the special (combinable)
   /// _TLS_MODULE_BASE_ symbol.
@@ -178,12 +189,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
   SignReturnAddress SignCondition = SignReturnAddress::None;
 
   /// SignWithBKey modifies the default PAC-RET mode to signing with the B key.
-  bool SignWithBKey = false;
+  bool getSignWithBKey() const { return JumpTableEntryInfo.getFlag(2); }
+  void setSignWithBKey(bool Value) { JumpTableEntryInfo.setFlag(2, Value); }
 
   /// HasELFSignedGOT is true if the target binary format is ELF and the IR
   /// module containing the corresponding function has "ptrauth-elf-got" flag
   /// set to 1.
-  bool HasELFSignedGOT = false;
+  bool getHasELFSignedGOT() const { return JumpTableEntryInfo.getFlag(3); }
+  void setHasELFSignedGOT(bool Value) { JumpTableEntryInfo.setFlag(3, Value); }
 
   /// SigningInstrOffset captures the offset of the PAC-RET signing instruction
   /// within the prologue, so it can be re-used for authentication in the
@@ -198,18 +211,29 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
 
   /// BranchTargetEnforcement enables placing BTI instructions at potential
   /// indirect branch destinations.
-  bool BranchTargetEnforcement = false;
+  bool getBranchTargetEnforcement() const { return LOHContainerSet.getFlag(0); }
+  void setBranchTargetEnforcement(bool Value) {
+    LOHContainerSet.setFlag(0, Value);
+  }
 
   /// Indicates that SP signing should be diversified with PC as-per PAuthLR.
   /// This is set by -mbranch-protection and will emit NOP instructions unless
   /// the subtarget feature +pauthlr is also used (in which case non-NOP
   /// instructions are emitted).
-  bool BranchProtectionPAuthLR = false;
+  bool getBranchProtectionPAuthLR() const { return LOHContainerSet.getFlag(1); }
+  void setBranchProtectionPAuthLR(bool Value) {
+    LOHContainerSet.setFlag(1, Value);
+  }
 
   /// Whether this function has an extended frame record [Ctx, FP, LR]. If so,
   /// bit 60 of the in-memory FP will be 1 to enable other tools to detect the
   /// extended record.
-  bool HasSwiftAsyncContext = false;
+  bool getHasSwiftAsyncContextFlag() const {
+    return LOHContainerSet.getFlag(2);
+  }
+  void setHasSwiftAsyncContextFlag(bool Value) {
+    LOHContainerSet.setFlag(2, Value);
+  }
 
   /// The stack slot where the Swift asynchronous context is stored.
   int SwiftAsyncContextFrameIdx = std::numeric_limits<int>::max();
@@ -337,7 +361,7 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
 
   void setCalleeSavedStackSize(unsigned Size) {
     CalleeSavedStackSize = Size;
-    HasCalleeSavedStackSize = true;
+    setHasCalleeSavedStackSize(true);
   }
 
   // When CalleeSavedStackSize has not been set (for example when
@@ -352,10 +376,10 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
     // Make sure the calculated size derived from the CalleeSavedInfo
     // equals the cached size that was calculated elsewhere (e.g. in
     // determineCalleeSaves).
-    ValidateCalleeSavedStackSize = HasCalleeSavedStackSize;
+    ValidateCalleeSavedStackSize = getHasCalleeSavedStackSize();
 #endif
 
-    if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) {
+    if (!getHasCalleeSavedStackSize() || ValidateCalleeSavedStackSize) {
       assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated");
       if (MFI.getCalleeSavedInfo().empty())
         return 0;
@@ -387,7 +411,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
       }
 
       unsigned Size = alignTo(MaxOffset - MinOffset, 16);
-      assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) &&
+      assert((!getHasCalleeSavedStackSize() ||
+              getCalleeSavedStackSize() == Size) &&
              "Invalid size calculated for callee saves");
       return Size;
     }
@@ -396,7 +421,7 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
   }
 
   unsigned getCalleeSavedStackSize() const {
-    assert(HasCalleeSavedStackSize &&
+    assert(getHasCalleeSavedStackSize() &&
            "CalleeSavedStackSize has not been calculated");
     return CalleeSavedStackSize;
   }
@@ -407,15 +432,15 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
            "expected SVE callee-save sizes to be aligned to 16-bytes");
     ZPRCalleeSavedStackSize = ZPR;
     PPRCalleeSavedStackSize = PPR;
-    HasSVECalleeSavedStackSize = true;
+    setHasSVECalleeSavedStackSize(true);
   }
   unsigned getZPRCalleeSavedStackSize() const {
-    assert(HasSVECalleeSavedStackSize &&
+    assert(getHasSVECalleeSavedStackSize() &&
            "ZPRCalleeSavedStackSize has not been calculated");
     return ZPRCalleeSavedStackSize;
   }
   unsigned getPPRCalleeSavedStackSize() const {
-    assert(HasSVECalleeSavedStackSize &&
+    assert(getHasSVECalleeSavedStackSize() &&
            "PPRCalleeSavedStackSize has not been calculated");
     return PPRCalleeSavedStackSize;
   }
@@ -522,7 +547,7 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
   using MILOHArgs = MILOHDirective::LOHArgs;
   using MILOHContainer = SmallVector<MILOHDirective, 32>;
 
-  const MILOHContainer &getLOHContainer() const { return LOHContainerSet; }
+  ArrayRef<MILOHDirective> getLOHContainer() const { return LOHContainerSet; }
 
   /// Add a LOH directive of this @p Kind and this @p Args.
   void addLOHDirective(MCLOHType Kind, MILOHArgs Args) {
@@ -578,9 +603,9 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
 
   bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const;
 
-  bool shouldSignWithBKey() const { return SignWithBKey; }
+  bool shouldSignWithBKey() const { return getSignWithBKey(); }
 
-  bool hasELFSignedGOT() const { return HasELFSignedGOT; }
+  bool hasELFSignedGOT() const { return getHasELFSignedGOT(); }
 
   MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; }
   void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; }
@@ -591,14 +616,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
     return SignReturnAddressHardening != SignReturnAddressHardeningKind::None;
   }
 
-  bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
+  bool branchTargetEnforcement() const { return getBranchTargetEnforcement(); }
 
-  bool branchProtectionPAuthLR() const { return BranchProtectionPAuthLR; }
+  bool branchProtectionPAuthLR() const { return getBranchProtectionPAuthLR(); }
 
   void setHasSwiftAsyncContext(bool HasContext) {
-    HasSwiftAsyncContext = HasContext;
+    setHasSwiftAsyncContextFlag(HasContext);
   }
-  bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; }
+  bool hasSwiftAsyncContext() const { return getHasSwiftAsyncContextFlag(); }
 
   void setSwiftAsyncContextFrameIdx(int FI) {
     SwiftAsyncContextFrameIdx = FI;
@@ -619,10 +644,11 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
 
 private:
   // Hold the lists of LOHs.
-  MILOHContainer LOHContainerSet;
+  llvm::SmallVectorWithFlagsFor<MILOHContainer, 3> LOHContainerSet;
   SetOfInstructions LOHRelated;
 
-  SmallVector<std::pair<unsigned, MCSymbol *>, 2> JumpTableEntryInfo;
+  llvm::SmallVectorWithFlags<std::pair<unsigned, MCSymbol *>, 2, 4>
+      JumpTableEntryInfo;
 };
 
 namespace yaml {
diff --git a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
index dbeb55d65e8d4..27cf07e7833a8 100644
--- a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
+++ b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
@@ -567,8 +567,8 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
     // postdominator analysis, and will leave us to keep memory tagged after
     // function return. Work around this by always untagging at every return
     // statement if return_twice functions are called.
-    bool StandardLifetime =
-        !SInfo.CallsReturnTwice && memtag::isSupportedLifetime(Info, DT, LI);
+    bool StandardLifetime = !SInfo.getCallsReturnTwice() &&
+                            memtag::isSupportedLifetime(Info, DT, LI);
     if (StandardLifetime) {
       uint64_t Size = *Info.AI->getAllocationSize(*DL);
       Size = alignTo(Size, kTagGranuleSize);
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 14e8d3b61c2dc..3fa716da8e92c 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -6606,8 +6606,8 @@ bool AArch64TTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
   case Intrinsic::aarch64_neon_ld2:
   case Intrinsic::aarch64_neon_ld3:
   case Intrinsic::aarch64_neon_ld4:
-    Info.ReadMem = true;
-    Info.WriteMem = false;
+    Info.setReadMem(true);
+    Info.setWriteMem(false);
     Info.PtrVal = Inst->getArgOperand(0);
     break;
   case Intrinsic::aarch64_neon_st1x2:
@@ -6616,8 +6616,8 @@ bool AArch64TTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
   case Intrinsic::aarch64_neon_st2:
   case Intrinsic::aarch64_neon_st3:
   case Intrinsic::aarch64_neon_st4:
-    Info.ReadMem = false;
-    Info.WriteMem = true;
+    Info.setReadMem(false);
+    Info.setWriteMem(true);
     Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1);
     break;
   }
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
index 18a41f98a7634..04c16649820be 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -1222,7 +1222,7 @@ bool AArch64CallLowering::lowerTailCall(
   unsigned Opc = getCallOpcode(MF, Info.Callee.isReg(), true, Info.PAI, MRI);
   auto MIB = MIRBuilder.buildInstrNoInsert(Opc);
   MIB.add(Info.Callee);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   // Tell the call which registers are clobbered.
@@ -1475,7 +1475,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   }
 
   auto MIB = MIRBuilder.buildInstrNoInsert(Opc);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
   unsigned CalleeOpNo = 0;
 
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index d8384e13f345b..ff9d6f7c22046 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1861,7 +1861,7 @@ void AArch64InstPrinter::printAlignedLabel(const MCInst *MI, uint64_t Address,
                                            const MCSubtargetInfo &STI,
                                            raw_ostream &O) {
   // Do not print the numeric target address when symbolizing.
-  if (SymbolizeOperands)
+  if (getSymbolizeOperands())
     return;
 
   const MCOperand &Op = MI->getOperand(OpNum);
@@ -1870,7 +1870,7 @@ void AArch64InstPrinter::printAlignedLabel(const MCInst *MI, uint64_t Address,
   // we're running the disassembler), just print the immediate.
   if (Op.isImm()) {
     int64_t Offset = Op.getImm() * 4;
-    if (PrintBranchImmAsAddress)
+    if (getPrintBranchImmAsAddress())
       markup(O, Markup::Target) << formatHex(Address + Offset);
     else
       markup(O, Markup::Immediate) << "#" << formatImm(Offset);
@@ -1896,7 +1896,7 @@ void AArch64InstPrinter::printAdrAdrpLabel(const MCInst *MI, uint64_t Address,
   // Do not print the numeric target address when symbolizing.
   // However, do print for ADRP, as this is typically used together with an ADD
   // or an immediate-offset ldr/str and the label is likely at the wrong point.
-  if (SymbolizeOperands && MI->getOpcode() != AArch64::ADRP)
+  if (getSymbolizeOperands() && MI->getOpcode() != AArch64::ADRP)
     return;
 
   const MCOperand &Op = MI->getOperand(OpNum);
@@ -1910,7 +1910,7 @@ void AArch64InstPrinter::printAdrAdrpLabel(const MCInst *MI, uint64_t Address,
       Address = Address & -4096;
     }
     WithMarkup M = markup(O, Markup::Immediate);
-    if (PrintBranchImmAsAddress)
+    if (getPrintBranchImmAsAddress())
       markup(O, Markup::Target) << formatHex(Address + Offset);
     else
       markup(O, Markup::Immediate) << "#" << Offset;
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
index ff3b3f12e2dc6..1321e9a97d19d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
@@ -171,7 +171,7 @@ void AArch64TargetStreamer::emitAttributesSubsection(
 std::unique_ptr<MCELFStreamer::AttributeSubSection>
 AArch64TargetStreamer::getActiveAttributesSubsection() {
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
-    if (SubSection.IsActive) {
+    if (SubSection.getIsActive()) {
       return std::make_unique<MCELFStreamer::AttributeSubSection>(SubSection);
     }
   }
@@ -203,7 +203,7 @@ void AArch64TargetStreamer::emitAttribute(StringRef VendorName, unsigned Tag,
 
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
     if (VendorName == SubSection.VendorName) {
-      if (!SubSection.IsActive) {
+      if (!SubSection.getIsActive()) {
         assert(0 &&
                "Can not add AArch64 build attribute: subsection is not active");
         return;
@@ -236,9 +236,9 @@ void AArch64TargetStreamer::emitAttribute(StringRef VendorName, unsigned Tag,
 void AArch64TargetStreamer::activateAttributesSubsection(StringRef VendorName) {
   for (MCELFStreamer::AttributeSubSection &SubSection : AttributeSubSections) {
     if (VendorName == SubSection.VendorName) {
-      SubSection.IsActive = true;
+      SubSection.setIsActive(true);
     } else {
-      SubSection.IsActive = false;
+      SubSection.setIsActive(false);
     }
   }
 }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index 6aa5c0de451ba..be307789abf06 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -145,11 +145,11 @@ AMDGPUTargetStreamer *AMDGPUAsmPrinter::getTargetStreamer() const {
 }
 
 void AMDGPUAsmPrinter::emitStartOfAsmFile(Module &M) {
-  IsTargetStreamerInitialized = false;
+  setIsTargetStreamerInitialized(false);
 }
 
 void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
-  IsTargetStreamerInitialized = true;
+  setIsTargetStreamerInitialized(true);
 
   // TODO: Which one is called first, emitStartOfAsmFile or
   // emitFunctionBodyStart?
@@ -174,7 +174,7 @@ void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
 
 void AMDGPUAsmPrinter::emitEndOfAsmFile(Module &M) {
   // Init target streamer if it has not yet happened
-  if (!IsTargetStreamerInitialized)
+  if (!getIsTargetStreamerInitialized())
     initTargetStreamer(M);
 
   const Triple &TT = M.getTargetTriple();
@@ -683,7 +683,7 @@ void AMDGPUAsmPrinter::emitAMDGPUInfo(Module &M) {
     return;
 
   AMDGPU::InfoSectionData Data;
-  Data.Funcs = std::move(FunctionInfos);
+  Data.Funcs = SmallVector<AMDGPU::FuncInfo, 8>(std::move(FunctionInfos));
 
   for (auto &[F, TypeId] : AddrTakenTypeIds) {
     MCSymbol *Sym = getSymbol(F);
@@ -897,7 +897,7 @@ AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   // Init target streamer lazily on the first function so that previous passes
   // can set metadata.
-  if (!IsTargetStreamerInitialized)
+  if (!getIsTargetStreamerInitialized())
     initTargetStreamer(*MF.getFunction().getParent());
 
   ResourceUsage = GetResourceUsage(MF);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
index 4394cde308665..8031acf49eb8f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
@@ -19,6 +19,7 @@
 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
 #include "SIProgramInfo.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 
 namespace llvm {
@@ -94,7 +95,7 @@ class AMDGPUAsmPrinter final : public AsmPrinter {
 
   SetVector<std::pair<MCSymbol *, MCSymbol *>> DirectCallEdges;
 
-  SmallVector<AMDGPU::FuncInfo, 8> FunctionInfos;
+  llvm::SmallVectorWithFlags<AMDGPU::FuncInfo, 8> FunctionInfos;
 
   SmallString<128> getMCExprStr(const MCExpr *Value);
 
@@ -161,7 +162,12 @@ class AMDGPUAsmPrinter final : public AsmPrinter {
 
   std::vector<std::string> DisasmLines, HexLines;
   size_t DisasmLineMaxLen;
-  bool IsTargetStreamerInitialized;
+  bool getIsTargetStreamerInitialized() const {
+    return FunctionInfos.getFlag(0);
+  }
+  void setIsTargetStreamerInitialized(bool Value) {
+    FunctionInfos.setFlag(0, Value);
+  }
 };
 
 class AMDGPUAsmPrinterBeginPass
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
index b482f69d81529..462b1f2f09b40 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
@@ -1353,7 +1353,7 @@ bool AMDGPUCallLowering::lowerTailCall(
   unsigned Opc = getCallOpcode(MF, Info.Callee.isReg(), /*IsTailCall*/ true,
                                ST.isWave32(), CalleeCC, IsDynamicVGPRChainCall);
   auto MIB = MIRBuilder.buildInstrNoInsert(Opc);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::NoMerge);
 
   if (FuncInfo->isWholeWaveFunction())
@@ -1664,9 +1664,9 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   auto MIB = MIRBuilder.buildInstrNoInsert(Opc);
   MIB.addDef(TRI->getReturnAddressReg(MF), RegState::Dead);
 
-  if (!Info.IsConvergent)
+  if (!Info.getIsConvergent())
     MIB.setMIFlag(MachineInstr::NoConvergent);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::NoMerge);
 
   if (!addCallTargetOperands(MIB, MIRBuilder, Info))
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUIGroupLP.cpp b/llvm/lib/Target/AMDGPU/AMDGPUIGroupLP.cpp
index 8ea07519116b9..84578bd00fb58 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUIGroupLP.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUIGroupLP.cpp
@@ -18,6 +18,7 @@
 #include "AMDGPUIGroupLP.h"
 #include "SIInstrInfo.h"
 #include "SIMachineFunctionInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MachineScheduler.h"
 #include "llvm/CodeGen/TargetOpcodes.h"
 
@@ -230,7 +231,7 @@ class PipelineSolver {
 
   // Instructions that can be assigned to multiple SchedGroups
   DenseMap<int, SUnitsToCandidateSGsMap> SyncedInstrs;
-  SmallVector<SUsToCandSGsVec, 4> PipelineInstrs;
+  llvm::SmallVectorWithFlags<SUsToCandSGsVec, 4, 2> PipelineInstrs;
   DenseMap<int, SmallVector<SchedGroup, 4>> SyncedSchedGroups;
   // The current working pipeline
   SmallVector<SmallVector<SchedGroup, 4>, 4> CurrPipeline;
@@ -238,7 +239,8 @@ class PipelineSolver {
   SmallVector<SmallVector<SchedGroup, 4>, 4> BestPipeline;
 
   // Whether or not we actually have any SyncedInstrs to try to solve.
-  bool NeedsSolver = false;
+  bool getNeedsSolver() const { return PipelineInstrs.getFlag(0); }
+  void setNeedsSolver(bool Value) { PipelineInstrs.setFlag(0, Value); }
 
   // Compute an estimate of the size of search tree -- the true size is
   // the product of each conflictedInst.Matches.size() across all SyncPipelines
@@ -263,7 +265,8 @@ class PipelineSolver {
   uint64_t BranchesExplored = 0;
 
   // The direction in which we process the candidate SchedGroups per SU
-  bool IsBottomUp = true;
+  bool getIsBottomUp() const { return !PipelineInstrs.getFlag(1); }
+  void setIsBottomUp(bool Value) { PipelineInstrs.setFlag(1, !Value); }
 
   // Update indices to fit next conflicting instruction
   void advancePosition();
@@ -361,16 +364,18 @@ class PipelineSolver {
                  DenseMap<int, SUnitsToCandidateSGsMap> &SyncedInstrs,
                  ScheduleDAGMI *DAG, bool IsBottomUp = true)
       : DAG(DAG), SyncedInstrs(SyncedInstrs),
-        SyncedSchedGroups(SyncedSchedGroups), IsBottomUp(IsBottomUp) {
+        PipelineInstrs(decltype(this->PipelineInstrs)::withFlags(
+            (unsigned(!(IsBottomUp)) << 1))),
+        SyncedSchedGroups(SyncedSchedGroups) {
 
     for (auto &PipelineInstrs : SyncedInstrs) {
       if (!PipelineInstrs.second.empty()) {
-        NeedsSolver = true;
+        setNeedsSolver(true);
         break;
       }
     }
 
-    if (!NeedsSolver)
+    if (!getNeedsSolver())
       return;
 
     convertSyncMapsToArrays();
@@ -463,8 +468,9 @@ void PipelineSolver::makePipeline() {
   }
 
   for (auto &SyncPipeline : BestPipeline) {
-    IsBottomUp ? linkSchedGroups(SyncPipeline.rbegin(), SyncPipeline.rend())
-               : linkSchedGroups(SyncPipeline.begin(), SyncPipeline.end());
+    getIsBottomUp()
+        ? linkSchedGroups(SyncPipeline.rbegin(), SyncPipeline.rend())
+        : linkSchedGroups(SyncPipeline.begin(), SyncPipeline.end());
   }
 }
 
@@ -599,10 +605,10 @@ int PipelineSolver::addEdges(
   // opposite is true if !IsBottomUp. IsBottomUp occurs in the case of multiple
   // SCHED_GROUP_BARRIERS, or if a user specifies IGLP_OPT SchedGroups using
   // IsBottomUp (in reverse).
-  return IsBottomUp ? linkSUnit(SU, SGID, AddedEdges, SyncPipeline.rbegin(),
-                                SyncPipeline.rend())
-                    : linkSUnit(SU, SGID, AddedEdges, SyncPipeline.begin(),
-                                SyncPipeline.end());
+  return getIsBottomUp() ? linkSUnit(SU, SGID, AddedEdges,
+                                     SyncPipeline.rbegin(), SyncPipeline.rend())
+                         : linkSUnit(SU, SGID, AddedEdges, SyncPipeline.begin(),
+                                     SyncPipeline.end());
 }
 
 void PipelineSolver::removeEdges(
@@ -727,10 +733,10 @@ bool PipelineSolver::solveExact() {
   // SchedGroup -> Cost pairs
   SmallVector<std::pair<int, int>, 4> ReadyList;
   // Prioritize the candidate sched groups in terms of lowest cost first
-  IsBottomUp ? populateReadyList(ReadyList, CurrSU.second.rbegin(),
-                                 CurrSU.second.rend())
-             : populateReadyList(ReadyList, CurrSU.second.begin(),
-                                 CurrSU.second.end());
+  getIsBottomUp() ? populateReadyList(ReadyList, CurrSU.second.rbegin(),
+                                      CurrSU.second.rend())
+                  : populateReadyList(ReadyList, CurrSU.second.begin(),
+                                      CurrSU.second.end());
 
   auto *I = ReadyList.begin();
   auto *E = ReadyList.end();
@@ -823,7 +829,7 @@ void PipelineSolver::greedyFind(
   LLVM_DEBUG(dbgs() << "Fitting " << *CurrSU.first << " in Pipeline # "
                     << CurrSyncGroupIdx << "\n");
 
-  EdgeSetBuilder Builder(CurrSU.first, SyncPipeline, IsBottomUp);
+  EdgeSetBuilder Builder(CurrSU.first, SyncPipeline, getIsBottomUp());
 
   // Since we have added the potential SchedGroups from bottom up, but
   // traversed the DAG from top down, parse over the groups from last to
@@ -887,7 +893,7 @@ bool PipelineSolver::solveGreedy() {
 
   while (static_cast<size_t>(CurrSyncGroupIdx) < PipelineInstrs.size()) {
     SUToCandSGsPair CurrSU = PipelineInstrs[CurrSyncGroupIdx][CurrConflInstNo];
-    IsBottomUp
+    getIsBottomUp()
         ? greedyFind(AddedEdges, CurrSU.second.rbegin(), CurrSU.second.rend())
         : greedyFind(AddedEdges, CurrSU.second.begin(), CurrSU.second.end());
     advancePosition();
@@ -907,7 +913,7 @@ unsigned PipelineSolver::computeProblemSize() {
 }
 
 void PipelineSolver::solve() {
-  if (!NeedsSolver)
+  if (!getNeedsSolver())
     return;
 
   unsigned ProblemSize = computeProblemSize();
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index c9ef618e1e7b3..984ea366274ea 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -1186,8 +1186,7 @@ CCAssignFn *AMDGPUCallLowering::CCAssignFnForReturn(CallingConv::ID CC,
 /// calling convention analysis function and the register type (Ins[x].VT) as
 /// the ValVT.
 void AMDGPUTargetLowering::analyzeFormalArgumentsCompute(
-  CCState &State,
-  const SmallVectorImpl<ISD::InputArg> &Ins) const {
+    CCState &State, llvm::ArrayRef<ISD::InputArg> Ins) const {
   const MachineFunction &MF = State.getMachineFunction();
   const Function &Fn = MF.getFunction();
   LLVMContext &Ctx = Fn.getContext();
@@ -1299,12 +1298,12 @@ void AMDGPUTargetLowering::analyzeFormalArgumentsCompute(
   }
 }
 
-SDValue AMDGPUTargetLowering::LowerReturn(
-  SDValue Chain, CallingConv::ID CallConv,
-  bool isVarArg,
-  const SmallVectorImpl<ISD::OutputArg> &Outs,
-  const SmallVectorImpl<SDValue> &OutVals,
-  const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue
+AMDGPUTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                  bool isVarArg,
+                                  llvm::ArrayRef<ISD::OutputArg> Outs,
+                                  const SmallVectorImpl<SDValue> &OutVals,
+                                  const SDLoc &DL, SelectionDAG &DAG) const {
   // FIXME: Fails for r600 tests
   //assert(!isVarArg && Outs.empty() && OutVals.empty() &&
   // "wave terminate should not have return values");
@@ -1378,7 +1377,7 @@ SDValue AMDGPUTargetLowering::lowerUnhandledCall(CallLoweringInfo &CLI,
   DAG.getContext()->diagnose(
       DiagnosticInfoUnsupported(Fn, Reason + FuncName, CLI.DL.getDebugLoc()));
 
-  if (!CLI.IsTailCall) {
+  if (!CLI.getIsTailCall()) {
     for (ISD::InputArg &Arg : CLI.Ins)
       InVals.push_back(DAG.getPOISON(Arg.VT));
   }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h
index 0cec051030d0b..b594a843df7b5 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h
@@ -182,9 +182,8 @@ class AMDGPUTargetLowering : public TargetLowering {
   void LowerUDIVREM64(SDValue Op, SelectionDAG &DAG,
                                     SmallVectorImpl<SDValue> &Results) const;
 
-  void analyzeFormalArgumentsCompute(
-    CCState &State,
-    const SmallVectorImpl<ISD::InputArg> &Ins) const;
+  void analyzeFormalArgumentsCompute(CCState &State,
+                                     llvm::ArrayRef<ISD::InputArg> Ins) const;
 
 public:
   AMDGPUTargetLowering(const TargetMachine &TM, const TargetSubtargetInfo &STI,
@@ -260,7 +259,7 @@ class AMDGPUTargetLowering : public TargetLowering {
   static CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg);
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp
index 23653d4229530..e911ab174f5f5 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULibFunc.cpp
@@ -12,6 +12,7 @@
 
 #include "AMDGPULibFunc.h"
 #include "AMDGPU.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -786,8 +787,10 @@ namespace {
 // substitution.
 
 class ItaniumMangler {
-  SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substitutions
-  bool  UseAddrSpace;
+  llvm::SmallVectorWithFlags<AMDGPULibFunc::Param, 10>
+      Str; // list of accumulated substitutions
+  bool getUseAddrSpace() const { return Str.getFlag(0); }
+  void setUseAddrSpace(bool Value) { Str.setFlag(0, Value); }
 
   int findSubst(const AMDGPULibFunc::Param& P) const {
     for(unsigned I = 0; I < Str.size(); ++I) {
@@ -815,7 +818,7 @@ class ItaniumMangler {
 
 public:
   ItaniumMangler(bool useAddrSpace)
-    : UseAddrSpace(useAddrSpace) {}
+      : Str(decltype(Str)::withFlags(unsigned(useAddrSpace))) {}
 
   template <typename Stream>
   void operator()(Stream& os, AMDGPULibFunc::Param p) {
@@ -837,7 +840,7 @@ class ItaniumMangler {
       os << 'P';
       if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';
       if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';
-      unsigned AS = UseAddrSpace
+      unsigned AS = getUseAddrSpace()
                         ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind)
                         : 0;
       if (EnableOCLManglingMismatchWA || AS != 0)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
index 3e190190ee761..7452679995b7a 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
@@ -514,9 +514,9 @@ bool GCNTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
 
     Info.PtrVal = Inst->getArgOperand(0);
     Info.Ordering = static_cast<AtomicOrdering>(OrderingVal);
-    Info.ReadMem = true;
-    Info.WriteMem = true;
-    Info.IsVolatile = !Volatile->isZero();
+    Info.setReadMem(true);
+    Info.setWriteMem(true);
+    Info.setIsVolatile(!Volatile->isZero());
     return true;
   }
   default:
diff --git a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp
index 057c72d962dc1..9361b4edfebc6 100644
--- a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp
@@ -1015,7 +1015,7 @@ GCNScheduleDAGMILive::GCNScheduleDAGMILive(
   // We want regions with a single MI to be scheduled so that we can reason
   // about them correctly during scheduling stages that move MIs between regions
   // (e.g., rematerialization).
-  ScheduleSingleMIRegions = true;
+  setScheduleSingleMIRegions(true);
   LLVM_DEBUG(dbgs() << "Starting occupancy is " << StartingOccupancy << ".\n");
   if (RelaxedOcc) {
     MinOccupancy = std::min(MFI.getMinAllowedOccupancy(), StartingOccupancy);
@@ -1924,7 +1924,7 @@ bool ClusteredLowOccStage::initGCNRegion() {
 }
 
 bool PreRARematStage::initGCNRegion() {
-  return !RevertAllRegions && RescheduleRegions[RegionIdx] &&
+  return !getRevertAllRegions() && RescheduleRegions[RegionIdx] &&
          GCNSchedStage::initGCNRegion();
 }
 
@@ -1969,7 +1969,7 @@ void PreRARematStage::finalizeGCNRegion() {
     REMAT_DEBUG(dbgs() << "Region " << RegionIdx
                        << " cannot meet occupancy target, interrupting "
                           "re-scheduling in all regions\n");
-    RevertAllRegions = true;
+    setRevertAllRegions(true);
   }
 }
 
diff --git a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h
index 021a1e82f1303..a03df909462ed 100644
--- a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h
+++ b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.h
@@ -15,6 +15,7 @@
 
 #include "GCNRegPressure.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
 #include "llvm/CodeGen/MachineInstr.h"
@@ -732,9 +733,10 @@ class PreRARematStage : public GCNSchedStage {
   };
   /// After re-scheduling, contains pre-re-scheduling data for all re-scheduled
   /// regions.
-  SmallVector<RegionSchedRevert> RegionReverts;
+  llvm::SmallVectorWithFlags<RegionSchedRevert> RegionReverts;
   /// Whether we should revert all re-scheduled regions.
-  bool RevertAllRegions = false;
+  bool getRevertAllRegions() const { return RegionReverts.getFlag(0); }
+  void setRevertAllRegions(bool Value) { RegionReverts.setFlag(0, Value); }
 
   /// Returns the occupancy the stage is trying to achieve.
   unsigned getStageTargetOccupancy() const;
diff --git a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp
index 5a9c18c3ae5db..ed37b6732f6da 100644
--- a/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp
@@ -1424,8 +1424,8 @@ CCAssignFn *R600TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
 /// separate calling conventions for kernel and non-kernel functions.
 SDValue R600TargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
                  *DAG.getContext());
diff --git a/llvm/lib/Target/AMDGPU/R600ISelLowering.h b/llvm/lib/Target/AMDGPU/R600ISelLowering.h
index e1b0afb8f3186..39e607c24bd2a 100644
--- a/llvm/lib/Target/AMDGPU/R600ISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/R600ISelLowering.h
@@ -37,8 +37,7 @@ class R600TargetLowering final : public AMDGPUTargetLowering {
                           SelectionDAG &DAG) const override;
   CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &,
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 66f6a9dfeed99..f40c7994a975e 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -3196,7 +3196,7 @@ void SITargetLowering::allocateHSAUserSGPRs(CCState &CCInfo,
 // sequential starting from the first argument.
 void SITargetLowering::allocatePreloadKernArgSGPRs(
     CCState &CCInfo, SmallVectorImpl<CCValAssign> &ArgLocs,
-    const SmallVectorImpl<ISD::InputArg> &Ins, MachineFunction &MF,
+    llvm::ArrayRef<ISD::InputArg> Ins, MachineFunction &MF,
     const SIRegisterInfo &TRI, SIMachineFunctionInfo &Info) const {
   Function &F = MF.getFunction();
   unsigned LastExplicitArgOffset = Subtarget->getExplicitKernelArgOffset();
@@ -3498,8 +3498,8 @@ void SITargetLowering::insertCopiesSplitCSR(
 
 SDValue SITargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
 
   MachineFunction &MF = DAG.getMachineFunction();
@@ -3838,10 +3838,11 @@ SDValue SITargetLowering::LowerFormalArguments(
 
 // TODO: If return values can't fit in registers, we should return as many as
 // possible in registers before passing on stack.
-bool SITargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool SITargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                      MachineFunction &MF, bool IsVarArg,
+                                      llvm::ArrayRef<ISD::OutputArg> Outs,
+                                      LLVMContext &Context,
+                                      const Type *RetTy) const {
   // Replacing returns with sret/stack usage doesn't make sense for shaders.
   // FIXME: Also sort of a workaround for custom vector splitting in LowerReturn
   // for shaders. Vector types should be explicitly handled by CC.
@@ -3863,12 +3864,12 @@ bool SITargetLowering::CanLowerReturn(
   return true;
 }
 
-SDValue
-SITargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                              bool isVarArg,
-                              const SmallVectorImpl<ISD::OutputArg> &Outs,
-                              const SmallVectorImpl<SDValue> &OutVals,
-                              const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue SITargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                      bool isVarArg,
+                                      llvm::ArrayRef<ISD::OutputArg> Outs,
+                                      const SmallVectorImpl<SDValue> &OutVals,
+                                      const SDLoc &DL,
+                                      SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
   SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
   const SIRegisterInfo *TRI = getSubtarget()->getRegisterInfo();
@@ -3966,8 +3967,8 @@ SITargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 
 SDValue SITargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals, bool IsThisReturn,
     SDValue ThisVal) const {
   CCAssignFn *RetCC = CCAssignFnForReturn(CallConv, IsVarArg);
 
@@ -4205,9 +4206,9 @@ void SITargetLowering::passSpecialInputs(
 
 bool SITargetLowering::isEligibleForTailCallOptimization(
     SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    SelectionDAG &DAG) const {
   if (AMDGPU::isChainCC(CalleeCC))
     return true;
 
@@ -4396,16 +4397,15 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
     }
   }
 
-  SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
-  SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
-  bool &IsTailCall = CLI.IsTailCall;
-  bool IsVarArg = CLI.IsVarArg;
+  auto &Ins = CLI.Ins;
+  bool IsVarArg = CLI.getIsVarArg();
   bool IsSibCall = false;
   MachineFunction &MF = DAG.getMachineFunction();
 
   if (Callee.isUndef() || isNullConstant(Callee)) {
-    if (!CLI.IsTailCall) {
+    if (!CLI.getIsTailCall()) {
       for (ISD::InputArg &Arg : CLI.Ins)
         InVals.push_back(DAG.getPOISON(Arg.VT));
     }
@@ -4421,15 +4421,15 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
   if (!CLI.CB)
     return lowerUnhandledCall(CLI, InVals, "unsupported libcall legalization");
 
-  if (IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
+  if (CLI.getIsTailCall() && MF.getTarget().Options.GuaranteedTailCallOpt) {
     return lowerUnhandledCall(CLI, InVals,
                               "unsupported required tail call to function ");
   }
 
-  if (IsTailCall) {
-    IsTailCall = isEligibleForTailCallOptimization(Callee, CallConv, IsVarArg,
-                                                   Outs, OutVals, Ins, DAG);
-    if (!IsTailCall &&
+  if (CLI.getIsTailCall()) {
+    CLI.setIsTailCall(isEligibleForTailCallOptimization(
+        Callee, CallConv, IsVarArg, Outs, OutVals, Ins, DAG));
+    if (!CLI.getIsTailCall() &&
         ((CLI.CB && CLI.CB->isMustTailCall()) || IsChainCallConv)) {
       report_fatal_error("failed to perform tail call elimination on a call "
                          "site marked musttail or on llvm.amdgcn.cs.chain");
@@ -4439,10 +4439,10 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
 
     // A sibling call is one where we're under the usual C ABI and not planning
     // to change that but can still do a tail call:
-    if (!TailCallOpt && IsTailCall)
+    if (!TailCallOpt && CLI.getIsTailCall())
       IsSibCall = true;
 
-    if (IsTailCall)
+    if (CLI.getIsTailCall())
       ++NumTailCalls;
   }
 
@@ -4553,7 +4553,7 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
       SDValue PtrOff = DAG.getConstant(Offset, DL, PtrVT);
       MaybeAlign Alignment;
 
-      if (IsTailCall) {
+      if (CLI.getIsTailCall()) {
         ISD::ArgFlagsTy Flags = Outs[i].Flags;
         unsigned OpSize = Flags.isByVal() ? Flags.getByValSize()
                                           : VA.getValVT().getStoreSize();
@@ -4653,7 +4653,7 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
   // the frame up *after* the call, however in the ABI-changing tail-call case
   // we've carefully laid out the parameters so that when sp is reset they'll be
   // in the correct location.
-  if (IsTailCall && !IsSibCall) {
+  if (CLI.getIsTailCall() && !IsSibCall) {
     Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
     InGlue = Chain.getValue(1);
   }
@@ -4667,7 +4667,7 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
     Ops.push_back(Callee);
     Ops.push_back(DAG.getTargetGlobalAddress(GV, DL, MVT::i64));
   } else {
-    if (IsTailCall) {
+    if (CLI.getIsTailCall()) {
       // isEligibleForTailCallOptimization considered whether the call target is
       // divergent, but we may still end up with a uniform value in a VGPR.
       // Insert a readfirstlane just in case.
@@ -4685,7 +4685,7 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
     Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64));
   }
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     // Each tail call may have to adjust the stack by a different amount, so
     // this information must travel along with the operation for eventual
     // consumption by emitEpilogue.
@@ -4721,7 +4721,7 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // If we're doing a tall call, use a TC_RETURN here rather than an
   // actual call instruction.
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MFI.setHasTailCall();
     unsigned OPC = AMDGPUISD::TC_RETURN;
     switch (CallConv) {
@@ -4741,13 +4741,13 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI,
       OPC = AMDGPUISD::TC_RETURN_GFX_WholeWave;
 
     SDValue Ret = DAG.getNode(OPC, DL, MVT::Other, Ops);
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     return Ret;
   }
 
   // Returns a chain and a flag for retval copy to use.
   SDValue Call = DAG.getNode(AMDGPUISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
-  DAG.addNoMergeSiteInfo(Call.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Call.getNode(), CLI.getNoMerge());
   Chain = Call.getValue(0);
   InGlue = Call.getValue(1);
 
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 4fffb7bd2d120..b092547e0fc93 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -437,18 +437,16 @@ class SITargetLowering final : public AMDGPUTargetLowering {
     const SmallVectorImpl<MachineBasicBlock *> &Exits) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
-  bool CanLowerReturn(CallingConv::ID CallConv,
-                      MachineFunction &MF, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+  bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
@@ -462,18 +460,17 @@ class SITargetLowering final : public AMDGPUTargetLowering {
 
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool isVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &DL, SelectionDAG &DAG,
-                          SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
-                          SDValue ThisVal) const;
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL,
+                          SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+                          bool isThisReturn, SDValue ThisVal) const;
 
   bool mayBeEmittedAsTailCall(const CallInst *) const override;
 
   bool isEligibleForTailCallOptimization(
-    SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const;
+      SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg,
+      llvm::ArrayRef<ISD::OutputArg> Outs,
+      const SmallVectorImpl<SDValue> &OutVals,
+      llvm::ArrayRef<ISD::InputArg> Ins, SelectionDAG &DAG) const;
 
   SDValue LowerCall(CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
@@ -643,7 +640,7 @@ class SITargetLowering final : public AMDGPUTargetLowering {
 
   void allocatePreloadKernArgSGPRs(CCState &CCInfo,
                                    SmallVectorImpl<CCValAssign> &ArgLocs,
-                                   const SmallVectorImpl<ISD::InputArg> &Ins,
+                                   llvm::ArrayRef<ISD::InputArg> Ins,
                                    MachineFunction &MF,
                                    const SIRegisterInfo &TRI,
                                    SIMachineFunctionInfo &Info) const;
diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp
index 1cef1223c246c..edac3325e6b13 100644
--- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp
@@ -48,17 +48,14 @@ bool SIMachineFunctionInfo::MFMAVGPRForm = false;
 SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F,
                                              const GCNSubtarget *STI)
     : AMDGPUMachineFunctionInfo(F, *STI), Mode(F, *STI),
-      GWSResourcePSV(getTM(STI)), UserSGPRInfo(F, *STI), WorkGroupIDX(false),
-      WorkGroupIDY(false), WorkGroupIDZ(false), WorkGroupInfo(false),
-      LDSKernelId(false), PrivateSegmentWaveByteOffset(false),
-      WorkItemIDX(false), WorkItemIDY(false), WorkItemIDZ(false),
-      ImplicitArgPtr(false), GITPtrHigh(0xffffffff), HighBitsOf32BitAddress(0),
-      IsWholeWaveFunction(F.getCallingConv() ==
-                          CallingConv::AMDGPU_Gfx_WholeWave) {
+      GWSResourcePSV(getTM(STI)), UserSGPRInfo(F, *STI), GITPtrHigh(0xffffffff),
+      HighBitsOf32BitAddress(0) {
+  setIsWholeWaveFunction(F.getCallingConv() ==
+                         CallingConv::AMDGPU_Gfx_WholeWave);
   const GCNSubtarget &ST = *STI;
   FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
   WavesPerEU = ST.getWavesPerEU(F);
-  MaxNumWorkGroups = AMDGPU::getMaxNumWorkGroups(F);
+  MaxNumWorkGroups.assign(AMDGPU::getMaxNumWorkGroups(F));
   assert(MaxNumWorkGroups.size() == 3);
 
   DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
@@ -71,8 +68,8 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F,
                         CC == CallingConv::SPIR_KERNEL;
 
   if (IsKernel) {
-    WorkGroupIDX = true;
-    WorkItemIDX = true;
+    setWorkGroupIDX(true);
+    setWorkItemIDXFlag(true);
   } else if (CC == CallingConv::AMDGPU_PS) {
     PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
   }
@@ -107,9 +104,9 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F,
 
     if (!F.hasFnAttribute("amdgpu-no-implicitarg-ptr") &&
         !AMDGPU::isChainCC(CC))
-      ImplicitArgPtr = true;
+      setImplicitArgPtr(true);
   } else {
-    ImplicitArgPtr = false;
+    setImplicitArgPtr(false);
     MaxKernArgAlign =
         std::max(ST.getAlignmentForImplicitArgPtr(), MaxKernArgAlign);
   }
@@ -119,41 +116,41 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F,
        ST.hasArchitectedSGPRs())) {
     if (IsKernel || !F.hasFnAttribute("amdgpu-no-workgroup-id-x") ||
         !F.hasFnAttribute("amdgpu-no-cluster-id-x"))
-      WorkGroupIDX = true;
+      setWorkGroupIDX(true);
 
     if (!F.hasFnAttribute("amdgpu-no-workgroup-id-y") ||
         !F.hasFnAttribute("amdgpu-no-cluster-id-y"))
-      WorkGroupIDY = true;
+      setWorkGroupIDY(true);
 
     if (!F.hasFnAttribute("amdgpu-no-workgroup-id-z") ||
         !F.hasFnAttribute("amdgpu-no-cluster-id-z"))
-      WorkGroupIDZ = true;
+      setWorkGroupIDZ(true);
   }
 
   if (!AMDGPU::isGraphics(CC)) {
     if (IsKernel || !F.hasFnAttribute("amdgpu-no-workitem-id-x"))
-      WorkItemIDX = true;
+      setWorkItemIDXFlag(true);
 
     if (!F.hasFnAttribute("amdgpu-no-workitem-id-y") &&
         ST.getMaxWorkitemID(F, 1) != 0)
-      WorkItemIDY = true;
+      setWorkItemIDYFlag(true);
 
     if (!F.hasFnAttribute("amdgpu-no-workitem-id-z") &&
         ST.getMaxWorkitemID(F, 2) != 0)
-      WorkItemIDZ = true;
+      setWorkItemIDZFlag(true);
 
     if (!IsKernel && !F.hasFnAttribute("amdgpu-no-lds-kernel-id"))
-      LDSKernelId = true;
+      setLDSKernelId(true);
   }
 
   if (isEntryFunction()) {
     // X, XY, and XYZ are the only supported combinations, so make sure Y is
     // enabled if Z is.
-    if (WorkItemIDZ)
-      WorkItemIDY = true;
+    if (getWorkItemIDZFlag())
+      setWorkItemIDYFlag(true);
 
     if (!ST.hasArchitectedFlatScratch()) {
-      PrivateSegmentWaveByteOffset = true;
+      setPrivateSegmentWaveByteOffsetFlag(true);
 
       // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
       if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
@@ -498,7 +495,7 @@ bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
 
   // This has already been allocated.
   if (!Spill.Lanes.empty())
-    return Spill.FullyAllocated;
+    return Spill.isFullyAllocated();
 
   unsigned Size = FrameInfo.getObjectSize(FI);
   unsigned NumLanes = Size / 4;
@@ -510,7 +507,7 @@ bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
 
   auto &SpillRegs = isAGPRtoVGPR ? SpillAGPR : SpillVGPR;
   const SIRegisterInfo *TRI = ST.getRegisterInfo();
-  Spill.FullyAllocated = true;
+  Spill.setFullyAllocated(true);
 
   // FIXME: Move allocation logic out of MachineFunctionInfo and initialize
   // once.
@@ -538,7 +535,7 @@ bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
         });
 
     if (NextSpillReg == Regs.end()) { // Registers exhausted
-      Spill.FullyAllocated = false;
+      Spill.setFullyAllocated(false);
       break;
     }
 
@@ -548,7 +545,7 @@ bool SIMachineFunctionInfo::allocateVGPRSpillToAGPR(MachineFunction &MF,
     Spill.Lanes[I] = *NextSpillReg++;
   }
 
-  return Spill.FullyAllocated;
+  return Spill.isFullyAllocated();
 }
 
 bool SIMachineFunctionInfo::removeDeadFrameIndices(
@@ -587,7 +584,7 @@ bool SIMachineFunctionInfo::removeDeadFrameIndices(
   }
 
   for (auto &R : VGPRToAGPRSpills) {
-    if (R.second.IsDead)
+    if (R.second.isDead())
       MFI.RemoveStackObject(R.first);
   }
 
@@ -790,14 +787,14 @@ bool SIMachineFunctionInfo::initializeBaseYamlFields(
   IsEntryFunction = YamlMFI.IsEntryFunction;
   MemoryBound = YamlMFI.MemoryBound;
   WaveLimiter = YamlMFI.WaveLimiter;
-  HasSpilledSGPRs = YamlMFI.HasSpilledSGPRs;
-  HasSpilledVGPRs = YamlMFI.HasSpilledVGPRs;
-  HasNoWWMPoolSGPRSpillFallback = YamlMFI.HasNoWWMPoolSGPRSpillFallback;
+  setHasSpilledSGPRsFlag(YamlMFI.HasSpilledSGPRs);
+  setHasSpilledVGPRsFlag(YamlMFI.HasSpilledVGPRs);
+  setHasNoWWMPoolSGPRSpillFallback(YamlMFI.HasNoWWMPoolSGPRSpillFallback);
   NumWaveDispatchSGPRs = YamlMFI.NumWaveDispatchSGPRs;
   NumWaveDispatchVGPRs = YamlMFI.NumWaveDispatchVGPRs;
   BytesInStackArgArea = YamlMFI.BytesInStackArgArea;
   ReturnsVoid = YamlMFI.ReturnsVoid;
-  IsWholeWaveFunction = YamlMFI.IsWholeWaveFunction;
+  setIsWholeWaveFunction(YamlMFI.IsWholeWaveFunction);
   MinNumAGPRs = YamlMFI.MinNumAGPRs;
   // This can also be set by the function attribute, MFI has higher precedence
   // though.
diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
index 359fc36dbcc71..2cee8104297a4 100644
--- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
@@ -22,6 +22,7 @@
 #include "SIModeRegisterDefaults.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/Support/raw_ostream.h"
@@ -473,7 +474,10 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   const AMDGPUGWSResourcePseudoSourceValue GWSResourcePSV;
 
   // Default/requested number of work groups for the function.
-  SmallVector<unsigned> MaxNumWorkGroups = {0, 0, 0};
+  llvm::SmallVectorWithFlags<
+      unsigned,
+      llvm::CalculateSmallVectorDefaultInlinedElements<unsigned>::value, 4>
+      MaxNumWorkGroups = {0, 0, 0};
 
   // Requested cluster dimensions.
   AMDGPU::ClusterDimsAttr ClusterDims;
@@ -485,10 +489,24 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   unsigned NumWaveDispatchSGPRs = 0;
   unsigned NumWaveDispatchVGPRs = 0;
 
-  bool HasSpilledSGPRs = false;
-  bool HasSpilledVGPRs = false;
-  bool HasNonSpillStackObjects = false;
-  bool IsStackRealigned = false;
+  bool getHasSpilledSGPRsFlag() const { return MaxNumWorkGroups.getFlag(0); }
+  void setHasSpilledSGPRsFlag(bool Value) {
+    MaxNumWorkGroups.setFlag(0, Value);
+  }
+  bool getHasSpilledVGPRsFlag() const { return MaxNumWorkGroups.getFlag(1); }
+  void setHasSpilledVGPRsFlag(bool Value) {
+    MaxNumWorkGroups.setFlag(1, Value);
+  }
+  bool getHasNonSpillStackObjectsFlag() const {
+    return MaxNumWorkGroups.getFlag(2);
+  }
+  void setHasNonSpillStackObjectsFlag(bool Value) {
+    MaxNumWorkGroups.setFlag(2, Value);
+  }
+  bool getIsStackRealignedFlag() const { return MaxNumWorkGroups.getFlag(3); }
+  void setIsStackRealignedFlag(bool Value) {
+    MaxNumWorkGroups.setFlag(3, Value);
+  }
 
   unsigned NumSpilledSGPRs = 0;
   unsigned NumSpilledVGPRs = 0;
@@ -504,20 +522,60 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   GCNUserSGPRUsageInfo UserSGPRInfo;
 
   // Feature bits required for inputs passed in system SGPRs.
-  bool WorkGroupIDX : 1; // Always initialized.
-  bool WorkGroupIDY : 1;
-  bool WorkGroupIDZ : 1;
-  bool WorkGroupInfo : 1;
-  bool LDSKernelId : 1;
-  bool PrivateSegmentWaveByteOffset : 1;
-
-  bool WorkItemIDX : 1; // Always initialized.
-  bool WorkItemIDY : 1;
-  bool WorkItemIDZ : 1;
+  bool getWorkGroupIDX() const { return PrologEpilogSGPRSpills.getFlag(0); }
+  bool setWorkGroupIDX(bool Value) {
+    PrologEpilogSGPRSpills.setFlag(0, Value);
+    return Value;
+  } // Always initialized.
+  bool getWorkGroupIDY() const { return PrologEpilogSGPRSpills.getFlag(1); }
+  bool setWorkGroupIDY(bool Value) {
+    PrologEpilogSGPRSpills.setFlag(1, Value);
+    return Value;
+  }
+  bool getWorkGroupIDZ() const { return PrologEpilogSGPRSpills.getFlag(2); }
+  bool setWorkGroupIDZ(bool Value) {
+    PrologEpilogSGPRSpills.setFlag(2, Value);
+    return Value;
+  }
+  bool getWorkGroupInfo() const { return PrologEpilogSGPRSpills.getFlag(3); }
+  void setWorkGroupInfo(bool Value) {
+    PrologEpilogSGPRSpills.setFlag(3, Value);
+  }
+  bool getLDSKernelId() const { return SpillPhysVGPRs.getFlag(0); }
+  bool setLDSKernelId(bool Value) {
+    SpillPhysVGPRs.setFlag(0, Value);
+    return Value;
+  }
+  bool getPrivateSegmentWaveByteOffsetFlag() const {
+    return SpillPhysVGPRs.getFlag(1);
+  }
+  void setPrivateSegmentWaveByteOffsetFlag(bool Value) {
+    SpillPhysVGPRs.setFlag(1, Value);
+  }
+
+  bool getWorkItemIDXFlag() const { return SpillPhysVGPRs.getFlag(2); }
+  bool setWorkItemIDXFlag(bool Value) {
+    SpillPhysVGPRs.setFlag(2, Value);
+    return Value;
+  } // Always initialized.
+  bool getWorkItemIDYFlag() const { return SpillPhysVGPRs.getFlag(3); }
+  bool setWorkItemIDYFlag(bool Value) {
+    SpillPhysVGPRs.setFlag(3, Value);
+    return Value;
+  }
+  bool getWorkItemIDZFlag() const { return SpillVGPRs.getFlag(0); }
+  bool setWorkItemIDZFlag(bool Value) {
+    SpillVGPRs.setFlag(0, Value);
+    return Value;
+  }
 
   // Pointer to where the ABI inserts special kernel arguments separate from the
   // user arguments. This is an offset from the KernargSegmentPtr.
-  bool ImplicitArgPtr : 1;
+  bool getImplicitArgPtr() const { return SpillVGPRs.getFlag(1); }
+  bool setImplicitArgPtr(bool Value) {
+    SpillVGPRs.setFlag(1, Value);
+    return Value;
+  }
 
   /// Minimum number of AGPRs required to allocate in the function. Only
   /// relevant for gfx90a-gfx950. For gfx908, this should be infinite.
@@ -552,9 +610,11 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   static bool MFMAVGPRForm;
 
   struct VGPRSpillToAGPR {
-    SmallVector<MCPhysReg, 32> Lanes;
-    bool FullyAllocated = false;
-    bool IsDead = false;
+    SmallVectorWithFlags<MCPhysReg, 32, 2> Lanes;
+    bool isFullyAllocated() const { return Lanes.getFlag(0); }
+    void setFullyAllocated(bool Value) { Lanes.setFlag(0, Value); }
+    bool isDead() const { return Lanes.getFlag(1); }
+    void setIsDead(bool Value) { Lanes.setFlag(1, Value); }
   };
 
 private:
@@ -568,8 +628,8 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
       SGPRSpillsToPhysicalVGPRLanes;
   unsigned NumVirtualVGPRSpillLanes = 0;
   unsigned NumPhysicalVGPRSpillLanes = 0;
-  SmallVector<Register, 2> SpillVGPRs;
-  SmallVector<Register, 2> SpillPhysVGPRs;
+  llvm::SmallVectorWithFlags<Register, 2, 4> SpillVGPRs;
+  llvm::SmallVectorWithFlags<Register, 2, 4> SpillPhysVGPRs;
   using WWMSpillsMap = MapVector<Register, int>;
   // To track the registers used in instructions that can potentially modify the
   // inactive lanes. The WWM instructions and the writelane instructions for
@@ -591,7 +651,8 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   // the serialization easier.
   ReservedRegSet WWMReservedRegs;
 
-  bool IsWholeWaveFunction = false;
+  bool getIsWholeWaveFunction() const { return SpillVGPRs.getFlag(2); }
+  void setIsWholeWaveFunction(bool Value) { SpillVGPRs.setFlag(2, Value); }
 
   using PrologEpilogSGPRSpill =
       std::pair<Register, PrologEpilogSGPRSaveRestoreInfo>;
@@ -599,7 +660,8 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   // frame lowering. Even though the SGPR spills are handled during
   // SILowerSGPRSpills pass, some special handling needed later during the
   // PrologEpilogInserter.
-  SmallVector<PrologEpilogSGPRSpill, 3> PrologEpilogSGPRSpills;
+  llvm::SmallVectorWithFlags<PrologEpilogSGPRSpill, 3, 4>
+      PrologEpilogSGPRSpills;
 
   // To save/restore EXEC MASK around WWM spills and copies.
   Register SGPRForEXECCopy;
@@ -619,7 +681,12 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   // Ordinary SGPR spills fell back to memory because no WWM VGPR pool was
   // available. This path may require additional nested VGPR scavenging slots
   // during frame-index elimination.
-  bool HasNoWWMPoolSGPRSpillFallback = false;
+  bool getHasNoWWMPoolSGPRSpillFallback() const {
+    return SpillVGPRs.getFlag(3);
+  }
+  void setHasNoWWMPoolSGPRSpillFallback(bool Value) {
+    SpillVGPRs.setFlag(3, Value);
+  }
 
   // Map each VGPR CSR to the mask needed to save and restore it using block
   // load/store instructions. Only used if the subtarget feature for VGPR block
@@ -703,7 +770,7 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
     return WWMReservedRegs.contains(Reg);
   }
 
-  bool isWholeWaveFunction() const { return IsWholeWaveFunction; }
+  bool isWholeWaveFunction() const { return getIsWholeWaveFunction(); }
 
   ArrayRef<PrologEpilogSGPRSpill> getPrologEpilogSGPRSpills() const {
     assert(is_sorted(PrologEpilogSGPRSpills, llvm::less_first()));
@@ -839,7 +906,7 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   void setVGPRToAGPRSpillDead(int FrameIndex) {
     auto I = VGPRToAGPRSpills.find(FrameIndex);
     if (I != VGPRToAGPRSpills.end())
-      I->second.IsDead = true;
+      I->second.setIsDead(true);
   }
 
   // To bring the allocated WWM registers in \p WWMVGPRs to the lowest available
@@ -861,9 +928,11 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI);
   std::optional<int> getOptionalScavengeFI() const { return ScavengeFI; }
 
-  void setNoWWMPoolSGPRSpillFallback() { HasNoWWMPoolSGPRSpillFallback = true; }
+  void setNoWWMPoolSGPRSpillFallback() {
+    setHasNoWWMPoolSGPRSpillFallback(true);
+  }
   bool hasNoWWMPoolSGPRSpillFallback() const {
-    return HasNoWWMPoolSGPRSpillFallback;
+    return getHasNoWWMPoolSGPRSpillFallback();
   }
 
   unsigned getBytesInStackArgArea() const {
@@ -933,7 +1002,7 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
     return ArgInfo.WorkGroupInfo.getRegister();
   }
 
-  bool hasLDSKernelId() const { return LDSKernelId; }
+  bool hasLDSKernelId() const { return getLDSKernelId(); }
 
   // Add special VGPR inputs
   void setWorkItemIDX(ArgDescriptor Arg) {
@@ -959,41 +1028,25 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
     ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg);
   }
 
-  bool hasWorkGroupIDX() const {
-    return WorkGroupIDX;
-  }
+  bool hasWorkGroupIDX() const { return getWorkGroupIDX(); }
 
-  bool hasWorkGroupIDY() const {
-    return WorkGroupIDY;
-  }
+  bool hasWorkGroupIDY() const { return getWorkGroupIDY(); }
 
-  bool hasWorkGroupIDZ() const {
-    return WorkGroupIDZ;
-  }
+  bool hasWorkGroupIDZ() const { return getWorkGroupIDZ(); }
 
-  bool hasWorkGroupInfo() const {
-    return WorkGroupInfo;
-  }
+  bool hasWorkGroupInfo() const { return getWorkGroupInfo(); }
 
   bool hasPrivateSegmentWaveByteOffset() const {
-    return PrivateSegmentWaveByteOffset;
+    return getPrivateSegmentWaveByteOffsetFlag();
   }
 
-  bool hasWorkItemIDX() const {
-    return WorkItemIDX;
-  }
+  bool hasWorkItemIDX() const { return getWorkItemIDXFlag(); }
 
-  bool hasWorkItemIDY() const {
-    return WorkItemIDY;
-  }
+  bool hasWorkItemIDY() const { return getWorkItemIDYFlag(); }
 
-  bool hasWorkItemIDZ() const {
-    return WorkItemIDZ;
-  }
+  bool hasWorkItemIDZ() const { return getWorkItemIDZFlag(); }
 
-  bool hasImplicitArgPtr() const {
-    return ImplicitArgPtr;
-  }
+  bool hasImplicitArgPtr() const { return getImplicitArgPtr(); }
 
   AMDGPUFunctionArgInfo &getArgInfo() {
     return ArgInfo;
@@ -1094,36 +1147,26 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
     return ArgInfo.ImplicitBufferPtr.getRegister();
   }
 
-  bool hasSpilledSGPRs() const {
-    return HasSpilledSGPRs;
-  }
+  bool hasSpilledSGPRs() const { return getHasSpilledSGPRsFlag(); }
 
-  void setHasSpilledSGPRs(bool Spill = true) {
-    HasSpilledSGPRs = Spill;
-  }
+  void setHasSpilledSGPRs(bool Spill = true) { setHasSpilledSGPRsFlag(Spill); }
 
-  bool hasSpilledVGPRs() const {
-    return HasSpilledVGPRs;
-  }
+  bool hasSpilledVGPRs() const { return getHasSpilledVGPRsFlag(); }
 
-  void setHasSpilledVGPRs(bool Spill = true) {
-    HasSpilledVGPRs = Spill;
-  }
+  void setHasSpilledVGPRs(bool Spill = true) { setHasSpilledVGPRsFlag(Spill); }
 
   bool hasNonSpillStackObjects() const {
-    return HasNonSpillStackObjects;
+    return getHasNonSpillStackObjectsFlag();
   }
 
   void setHasNonSpillStackObjects(bool StackObject = true) {
-    HasNonSpillStackObjects = StackObject;
+    setHasNonSpillStackObjectsFlag(StackObject);
   }
 
-  bool isStackRealigned() const {
-    return IsStackRealigned;
-  }
+  bool isStackRealigned() const { return getIsStackRealignedFlag(); }
 
   void setIsStackRealigned(bool Realigned = true) {
-    IsStackRealigned = Realigned;
+    setIsStackRealignedFlag(Realigned);
   }
 
   unsigned getNumSpilledSGPRs() const {
@@ -1241,7 +1284,9 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunctionInfo,
   }
 
   /// \returns Default/requested number of work groups for this function.
-  SmallVector<unsigned> getMaxNumWorkGroups() const { return MaxNumWorkGroups; }
+  SmallVector<unsigned> getMaxNumWorkGroups() const {
+    return {MaxNumWorkGroups.begin(), MaxNumWorkGroups.end()};
+  }
 
   unsigned getMaxNumWorkGroupsX() const { return MaxNumWorkGroups[0]; }
   unsigned getMaxNumWorkGroupsY() const { return MaxNumWorkGroups[1]; }
diff --git a/llvm/lib/Target/AMDGPU/SIModeRegister.cpp b/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
index 3599b4e1ad578..ba090b6f385d1 100644
--- a/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
+++ b/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
@@ -15,6 +15,7 @@
 //
 #include "AMDGPU.h"
 #include "GCNSubtarget.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include <optional>
@@ -100,11 +101,13 @@ class BlockData {
 
   // Call and return sites, each paired with the block local mode changes that
   // precede it. Phase 3 merges the pair with Pred to get the mode at the site.
-  SmallVector<std::pair<MachineInstr *, Status>, 2> BoundarySites;
+  llvm::SmallVectorWithFlags<std::pair<MachineInstr *, Status>, 2>
+      BoundarySites;
 
   // A flag to indicate whether an Exit value has been set (we can't tell by
   // examining the Exit value itself as all values may be valid results).
-  bool ExitSet = false;
+  bool getExitSet() const { return BoundarySites.getFlag(0); }
+  void setExitSet(bool Value) { BoundarySites.setFlag(0, Value); }
 
   BlockData() = default;
 };
@@ -446,7 +449,7 @@ void SIModeRegister::processBlockPhase2(MachineBasicBlock &MBB,
     if ((ThisBlock == PredBlock) && (std::next(P) == E)) {
       BlockInfo[ThisBlock]->Pred = DefaultStatus;
       ExitSet = true;
-    } else if (BlockInfo[PredBlock]->ExitSet) {
+    } else if (BlockInfo[PredBlock]->getExitSet()) {
       BlockInfo[ThisBlock]->Pred = BlockInfo[PredBlock]->Exit;
       ExitSet = true;
     } else if (PredBlock != ThisBlock)
@@ -455,8 +458,8 @@ void SIModeRegister::processBlockPhase2(MachineBasicBlock &MBB,
     for (P = std::next(P); P != E; P = std::next(P)) {
       MachineBasicBlock *Pred = *P;
       unsigned PredBlock = Pred->getNumber();
-      if (BlockInfo[PredBlock]->ExitSet) {
-        if (BlockInfo[ThisBlock]->ExitSet) {
+      if (BlockInfo[PredBlock]->getExitSet()) {
+        if (BlockInfo[ThisBlock]->getExitSet()) {
           BlockInfo[ThisBlock]->Pred =
               BlockInfo[ThisBlock]->Pred.intersect(BlockInfo[PredBlock]->Exit);
         } else {
@@ -476,7 +479,10 @@ void SIModeRegister::processBlockPhase2(MachineBasicBlock &MBB,
     for (MachineBasicBlock *Succ : MBB.successors())
       Phase2List.push(Succ);
   }
-  BlockInfo[ThisBlock]->ExitSet = ExitSet;
+  [&] {
+    auto PackedFlagValue = ExitSet;
+    return BlockInfo[ThisBlock]->setExitSet(PackedFlagValue);
+  }();
   if (RevisitRequired)
     Phase2List.push(&MBB);
 }
diff --git a/llvm/lib/Target/ARC/ARCISelLowering.cpp b/llvm/lib/Target/ARC/ARCISelLowering.cpp
index e3704fcf95051..6cbc923792a0e 100644
--- a/llvm/lib/Target/ARC/ARCISelLowering.cpp
+++ b/llvm/lib/Target/ARC/ARCISelLowering.cpp
@@ -248,16 +248,15 @@ SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                      SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &dl = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
-  bool &IsTailCall = CLI.IsTailCall;
+  bool IsVarArg = CLI.getIsVarArg();
 
-  IsTailCall = false; // Do not support tail calls yet.
+  CLI.setIsTailCall(false); // Do not support tail calls yet.
 
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
@@ -320,7 +319,7 @@ SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       SDValue Store =
           DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
       MemOpChains.push_back(Store);
-      IsTailCall = false;
+      CLI.setIsTailCall(false);
     }
   }
 
@@ -382,7 +381,7 @@ SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // Handle result values, copying them out of physregs into vregs that we
   // return.
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     return Chain;
   return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
 }
@@ -452,8 +451,8 @@ struct ArgDataPair {
 /// ARC formal arguments implementation
 SDValue ARCTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   switch (CallConv) {
   default:
     llvm_unreachable("Unsupported calling convention");
@@ -467,7 +466,7 @@ SDValue ARCTargetLowering::LowerFormalArguments(
 /// operations for argument places on the stack.
 SDValue ARCTargetLowering::LowerCallArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,
+    llvm::ArrayRef<ISD::InputArg> Ins, SDLoc dl, SelectionDAG &DAG,
     SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -612,10 +611,11 @@ SDValue ARCTargetLowering::LowerCallArguments(
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool ARCTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool ARCTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool IsVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
@@ -625,12 +625,12 @@ bool ARCTargetLowering::CanLowerReturn(
   return true;
 }
 
-SDValue
-ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &dl, SelectionDAG &DAG) const {
+SDValue ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool IsVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &dl,
+                                       SelectionDAG &DAG) const {
   auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
 
diff --git a/llvm/lib/Target/ARC/ARCISelLowering.h b/llvm/lib/Target/ARC/ARCISelLowering.h
index d0b3eb898eae9..5b402901dc136 100644
--- a/llvm/lib/Target/ARC/ARCISelLowering.h
+++ b/llvm/lib/Target/ARC/ARCISelLowering.h
@@ -49,8 +49,7 @@ class ARCTargetLowering : public TargetLowering {
 
   // Lower Operand helpers
   SDValue LowerCallArguments(SDValue Chain, CallingConv::ID CallConv,
-                             bool isVarArg,
-                             const SmallVectorImpl<ISD::InputArg> &Ins,
+                             bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                              SDLoc dl, SelectionDAG &DAG,
                              SmallVectorImpl<SDValue> &InVals) const;
   // Lower Operand specifics
@@ -63,8 +62,7 @@ class ARCTargetLowering : public TargetLowering {
   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &dl, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -72,13 +70,12 @@ class ARCTargetLowering : public TargetLowering {
                     SmallVectorImpl<SDValue> &InVals) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
                       SelectionDAG &DAG) const override;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> ArgsFlags,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index 9bbd029495a79..18fb41c0ec8cf 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -52,7 +52,7 @@ using namespace llvm;
 ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM,
                              std::unique_ptr<MCStreamer> Streamer)
     : AsmPrinter(TM, std::move(Streamer), ID), AFI(nullptr), MCP(nullptr),
-      InConstantPool(false), OptimizationGoals(-1) {}
+      OptimizationGoals(-1) {}
 
 const ARMBaseTargetMachine &ARMAsmPrinter::getTM() const {
   return static_cast<const ARMBaseTargetMachine &>(TM);
@@ -61,9 +61,9 @@ const ARMBaseTargetMachine &ARMAsmPrinter::getTM() const {
 void ARMAsmPrinter::emitFunctionBodyEnd() {
   // Make sure to terminate any constant pools that were at the end
   // of the function.
-  if (!InConstantPool)
+  if (!getInConstantPool())
     return;
-  InConstantPool = false;
+  setInConstantPool(false);
   OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
 }
 
@@ -1987,9 +1987,9 @@ void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
 
   // If we just ended a constant pool, mark it as such.
-  if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
+  if (getInConstantPool() && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
     OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
-    InConstantPool = false;
+    setInConstantPool(false);
   }
 
   // Emit unwinding stuff for frame-related instructions
@@ -2367,9 +2367,9 @@ void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
     unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
 
     // If this is the first entry of the pool, mark it.
-    if (!InConstantPool) {
+    if (!getInConstantPool()) {
       OutStreamer->emitDataRegion(MCDR_DataRegion);
-      InConstantPool = true;
+      setInConstantPool(true);
     }
 
     OutStreamer->emitLabel(GetCPISymbol(LabelId));
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h
index 1d35b3c445958..fbd0f3dd0ad2b 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.h
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H
 #define LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/Target/TargetMachine.h"
 
@@ -43,11 +44,13 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
 
   /// InConstantPool - Maintain state when emitting a sequence of constant
   /// pool entries so we can properly mark them as data regions.
-  bool InConstantPool;
+  bool getInConstantPool() const { return ThumbIndirectPads.getFlag(0); }
+  void setInConstantPool(bool Value) { ThumbIndirectPads.setFlag(0, Value); }
 
   /// ThumbIndirectPads - These maintain a per-function list of jump pad
   /// labels used for ARMv4t thumb code to make register indirect calls.
-  SmallVector<std::pair<unsigned, MCSymbol*>, 4> ThumbIndirectPads;
+  llvm::SmallVectorWithFlags<std::pair<unsigned, MCSymbol *>, 4>
+      ThumbIndirectPads;
 
   /// OptimizationGoals - Maintain a combined optimization goal for all
   /// functions in a module: one of Tag_ABI_optimization_goals values,
diff --git a/llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp b/llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp
index afbbe4924fb6c..97edc21683065 100644
--- a/llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBasicBlockInfo.cpp
@@ -53,9 +53,9 @@ void ARMBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) {
     // For inline asm, getInstSizeInBytes returns a conservative estimate.
     // The actual size may be smaller, but still a multiple of the instr size.
     if (I.isInlineAsm())
-      BBI.Unalign = isThumb ? 1 : 2;
+      BBI.Unalign = getIsThumb() ? 1 : 2;
     // Also consider instructions that may be shrunk later.
-    else if (isThumb && mayOptimizeThumb2Instruction(&I))
+    else if (getIsThumb() && mayOptimizeThumb2Instruction(&I))
       BBI.Unalign = 1;
   }
 
@@ -90,7 +90,7 @@ unsigned ARMBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {
 bool ARMBasicBlockUtils::isBBInRange(MachineInstr *MI,
                                      MachineBasicBlock *DestBB,
                                      unsigned MaxDisp) const {
-  unsigned PCAdj      = isThumb ? 4 : 8;
+  unsigned PCAdj = getIsThumb() ? 4 : 8;
   unsigned BrOffset   = getOffsetOf(MI) + PCAdj;
   unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
 
diff --git a/llvm/lib/Target/ARM/ARMBasicBlockInfo.h b/llvm/lib/Target/ARM/ARMBasicBlockInfo.h
index daf8f9b4b8361..abaf2cd88eee5 100644
--- a/llvm/lib/Target/ARM/ARMBasicBlockInfo.h
+++ b/llvm/lib/Target/ARM/ARMBasicBlockInfo.h
@@ -15,6 +15,7 @@
 
 #include "ARMBaseInstrInfo.h"
 #include "ARMMachineFunctionInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/MathExtras.h"
 #include <algorithm>
 #include <cstdint>
@@ -22,7 +23,6 @@
 namespace llvm {
 
 struct BasicBlockInfo;
-using BBInfoVector = SmallVectorImpl<BasicBlockInfo>;
 
 /// UnknownPadding - Return the worst case padding that could result from
 /// unknown offset bits.  This does not include alignment padding caused by
@@ -110,15 +110,16 @@ class ARMBasicBlockUtils {
 
 private:
   MachineFunction &MF;
-  bool isThumb = false;
+  bool getIsThumb() const { return BBInfo.getFlag(0); }
+  void setIsThumb(bool Value) { BBInfo.setFlag(0, Value); }
   const ARMBaseInstrInfo *TII = nullptr;
-  SmallVector<BasicBlockInfo, 8> BBInfo;
+  llvm::SmallVectorWithFlags<BasicBlockInfo, 8> BBInfo;
 
 public:
   ARMBasicBlockUtils(MachineFunction &MF) : MF(MF) {
     TII =
       static_cast<const ARMBaseInstrInfo*>(MF.getSubtarget().getInstrInfo());
-    isThumb = MF.getInfo<ARMFunctionInfo>()->isThumbFunction();
+    setIsThumb(MF.getInfo<ARMFunctionInfo>()->isThumbFunction());
   }
 
   void computeAllBlockSizes() {
@@ -150,8 +151,7 @@ class ARMBasicBlockUtils {
 
   void clear() { BBInfo.clear(); }
 
-  BBInfoVector &getBBInfo() { return BBInfo; }
-
+  auto &getBBInfo() { return BBInfo; }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/ARM/ARMCallLowering.cpp b/llvm/lib/Target/ARM/ARMCallLowering.cpp
index 713f4fccb9e92..ce0473e92635e 100644
--- a/llvm/lib/Target/ARM/ARMCallLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMCallLowering.cpp
@@ -483,7 +483,7 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &
   bool IsDirect = !Info.Callee.isReg();
   auto CallOpcode = getCallOpcode(MF, STI, IsDirect);
   auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   bool IsThumb = STI.isThumb();
diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
index cacbc3e2d69c9..e86950259ab3f 100644
--- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -24,6 +24,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/LivePhysRegs.h"
@@ -203,7 +204,7 @@ namespace {
     SmallVector<MachineInstr*, 4> PushPopMIs;
 
     /// T2JumpTables - Keep track of all the Thumb2 jumptable instructions.
-    SmallVector<MachineInstr*, 4> T2JumpTables;
+    llvm::SmallVectorWithFlags<MachineInstr *, 4, 4> T2JumpTables;
 
     MachineFunction *MF;
     MachineConstantPool *MCP;
@@ -211,10 +212,18 @@ namespace {
     const ARMSubtarget *STI;
     ARMFunctionInfo *AFI;
     MachineDominatorTree *DT = nullptr;
-    bool isThumb;
-    bool isThumb1;
-    bool isThumb2;
-    bool isPositionIndependentOrROPI;
+    bool getIsThumb() const { return T2JumpTables.getFlag(0); }
+    void setIsThumb(bool Value) { T2JumpTables.setFlag(0, Value); }
+    bool getIsThumb1() const { return T2JumpTables.getFlag(1); }
+    void setIsThumb1(bool Value) { T2JumpTables.setFlag(1, Value); }
+    bool getIsThumb2() const { return T2JumpTables.getFlag(2); }
+    void setIsThumb2(bool Value) { T2JumpTables.setFlag(2, Value); }
+    bool getIsPositionIndependentOrROPI() const {
+      return T2JumpTables.getFlag(3);
+    }
+    void setIsPositionIndependentOrROPI(bool Value) {
+      T2JumpTables.setFlag(3, Value);
+    }
 
   public:
     static char ID;
@@ -295,7 +304,7 @@ char ARMConstantIslands::ID = 0;
 /// verify - check BBOffsets, BBSizes, alignment of islands
 void ARMConstantIslands::verify() {
 #ifndef NDEBUG
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   assert(is_sorted(*MF, [&BBInfo](const MachineBasicBlock &LHS,
                                   const MachineBasicBlock &RHS) {
     return BBInfo[LHS.getNumber()].postOffset() <
@@ -323,7 +332,7 @@ void ARMConstantIslands::verify() {
 /// print block size and offset information - debugging
 LLVM_DUMP_METHOD void ARMConstantIslands::dumpBBs() {
   LLVM_DEBUG({
-    BBInfoVector &BBInfo = BBUtils->getBBInfo();
+    auto &BBInfo = BBUtils->getBBInfo();
     for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
       const BasicBlockInfo &BBI = BBInfo[J];
       dbgs() << format("%08x %bb.%u\t", BBI.Offset, J)
@@ -390,16 +399,16 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
 
   STI = &MF->getSubtarget<ARMSubtarget>();
   TII = STI->getInstrInfo();
-  isPositionIndependentOrROPI =
-      STI->getTargetLowering()->isPositionIndependent() || STI->isROPI();
+  setIsPositionIndependentOrROPI(
+      STI->getTargetLowering()->isPositionIndependent() || STI->isROPI());
   AFI = MF->getInfo<ARMFunctionInfo>();
   DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
 
-  isThumb = AFI->isThumbFunction();
-  isThumb1 = AFI->isThumb1OnlyFunction();
-  isThumb2 = AFI->isThumb2Function();
+  setIsThumb(AFI->isThumbFunction());
+  setIsThumb1(AFI->isThumb1OnlyFunction());
+  setIsThumb2(AFI->isThumb2Function());
 
-  bool GenerateTBB = isThumb2 || (isThumb1 && SynthesizeThumb1TBB);
+  bool GenerateTBB = getIsThumb2() || (getIsThumb1() && SynthesizeThumb1TBB);
   // TBB generation code in this constant island pass has not been adapted to
   // deal with speculation barriers.
   if (STI->hardenSlsRetBr())
@@ -486,11 +495,11 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
   }
 
   // Shrink 32-bit Thumb2 load and store instructions.
-  if (isThumb2 && !STI->prefers32BitThumb())
+  if (getIsThumb2() && !STI->prefers32BitThumb())
     MadeChange |= optimizeThumb2Instructions();
 
   // Shrink 32-bit branch instructions.
-  if (isThumb && STI->hasV8MBaselineOps())
+  if (getIsThumb() && STI->hasV8MBaselineOps())
     MadeChange |= optimizeThumb2Branches();
 
   // Optimize jump tables using TBB / TBH.
@@ -711,9 +720,9 @@ Align ARMConstantIslands::getCPEAlign(const MachineInstr *CPEMI) {
   case ARM::CONSTPOOL_ENTRY:
     break;
   case ARM::JUMPTABLE_TBB:
-    return isThumb1 ? Align(4) : Align(1);
+    return getIsThumb1() ? Align(4) : Align(1);
   case ARM::JUMPTABLE_TBH:
-    return isThumb1 ? Align(4) : Align(2);
+    return getIsThumb1() ? Align(4) : Align(2);
   case ARM::JUMPTABLE_INSTS:
     return Align(2);
   case ARM::JUMPTABLE_ADDRS:
@@ -746,7 +755,7 @@ void ARMConstantIslands::
 initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
 
   BBUtils->computeAllBlockSizes();
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   // The known bits of the entry block offset are determined by the function
   // alignment.
   BBInfo.front().KnownBits = Log2(MF->getAlignment());
@@ -982,8 +991,8 @@ MachineBasicBlock *ARMConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
   // Note the new unconditional branch is not being recorded.
   // There doesn't seem to be meaningful DebugInfo available; this doesn't
   // correspond to anything in the source.
-  unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
-  if (!isThumb)
+  unsigned Opc = getIsThumb() ? (getIsThumb2() ? ARM::t2B : ARM::tB) : ARM::B;
+  if (!getIsThumb())
     BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB);
   else
     BuildMI(OrigBB, DebugLoc(), TII->get(Opc))
@@ -1047,12 +1056,12 @@ MachineBasicBlock *ARMConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
 unsigned ARMConstantIslands::getUserOffset(CPUser &U) const {
   unsigned UserOffset = BBUtils->getOffsetOf(U.MI);
 
-  SmallVectorImpl<BasicBlockInfo> &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];
   unsigned KnownBits = BBI.internalKnownBits();
 
   // The value read from PC is offset from the actual instruction address.
-  UserOffset += (isThumb ? 4 : 8);
+  UserOffset += (getIsThumb() ? 4 : 8);
 
   // Because of inline assembly, we may not know the alignment (mod 4) of U.MI.
   // Make sure U.getMaxDisp() returns a constrained range.
@@ -1061,7 +1070,7 @@ unsigned ARMConstantIslands::getUserOffset(CPUser &U) const {
   // On Thumb, offsets==2 mod 4 are rounded down by the hardware for
   // purposes of the displacement computation; compensate for that here.
   // For unknown alignments, getMaxDisp() constrains the range instead.
-  if (isThumb && U.KnownAlignment)
+  if (getIsThumb() && U.KnownAlignment)
     UserOffset &= ~3u;
 
   return UserOffset;
@@ -1096,7 +1105,7 @@ bool ARMConstantIslands::isOffsetInRange(unsigned UserOffset,
 bool ARMConstantIslands::isWaterInRange(unsigned UserOffset,
                                         MachineBasicBlock* Water, CPUser &U,
                                         unsigned &Growth) {
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   const Align CPEAlign = getCPEAlign(U.CPEMI);
   const unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPEAlign);
   unsigned NextBlockOffset;
@@ -1141,7 +1150,7 @@ bool ARMConstantIslands::isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
 
   if (DoDump) {
     LLVM_DEBUG({
-        BBInfoVector &BBInfo = BBUtils->getBBInfo();
+      auto &BBInfo = BBUtils->getBBInfo();
       unsigned Block = MI->getParent()->getNumber();
       const BasicBlockInfo &BBI = BBInfo[Block];
       dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()
@@ -1289,7 +1298,7 @@ bool ARMConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
   // When a CP access is out of range, BB0 may be used as water. However,
   // inserting islands between BB0 and BB1 makes other accesses out of range.
   MachineBasicBlock *UserBB = U.MI->getParent();
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   const Align CPEAlign = getCPEAlign(U.CPEMI);
   unsigned MinNoSplitDisp = BBInfo[UserBB->getNumber()].postOffset(CPEAlign);
   if (CloserWater && MinNoSplitDisp > U.getMaxDisp() / 2)
@@ -1346,7 +1355,7 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
   MachineInstr *CPEMI  = U.CPEMI;
   const Align CPEAlign = getCPEAlign(CPEMI);
   MachineBasicBlock *UserMBB = UserMI->getParent();
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
 
   // If the block does not end in an unconditional branch already, and if the
@@ -1355,7 +1364,7 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
   // Thumb2, 2 on Thumb1.
   if (BBHasFallthrough(UserMBB)) {
     // Size of branch to insert.
-    unsigned Delta = isThumb1 ? 2 : 4;
+    unsigned Delta = getIsThumb1() ? 2 : 4;
     // Compute the offset where the CPE will begin.
     unsigned CPEOffset = UserBBI.postOffset(CPEAlign) + Delta;
 
@@ -1368,8 +1377,9 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
       // but if the preceding conditional branch is out of range, the targets
       // will be exchanged, and the altered branch may be out of range, so the
       // machinery has to know about it.
-      int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B;
-      if (!isThumb)
+      int UncondBr =
+          getIsThumb() ? ((getIsThumb2()) ? ARM::t2B : ARM::tB) : ARM::B;
+      if (!getIsThumb())
         BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
       else
         BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr))
@@ -1499,7 +1509,8 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
   // the instruction and fail to update the MOVT instruction.
   // (These instructions are bundled up until right before the ConstantIslands
   // pass.)
-  if (STI->isTargetWindows() && isThumb && MI->getOpcode() == ARM::t2MOVTi16 &&
+  if (STI->isTargetWindows() && getIsThumb() &&
+      MI->getOpcode() == ARM::t2MOVTi16 &&
       (MI->getOperand(2).getTargetFlags() & ARMII::MO_OPTION_MASK) ==
           ARMII::MO_HI16) {
     --MI;
@@ -1511,7 +1522,7 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
   // We really must not split an IT block.
 #ifndef NDEBUG
   Register PredReg;
-  assert(!isThumb || getITInstrPredicate(*MI, PredReg) == ARMCC::AL);
+  assert(!getIsThumb() || getITInstrPredicate(*MI, PredReg) == ARMCC::AL);
 #endif
   NewMBB = splitBlockBeforeInstr(&*MI);
 }
@@ -1577,7 +1588,7 @@ bool ARMConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
   // Always align the new block because CP entries can be smaller than 4
   // bytes. Be careful not to decrease the existing alignment, e.g. NewMBB may
   // be an already aligned constant pool block.
-  const Align Alignment = isThumb ? Align(2) : Align(4);
+  const Align Alignment = getIsThumb() ? Align(2) : Align(4);
   if (NewMBB->getAlignment() < Alignment)
     NewMBB->setAlignment(Alignment);
 
@@ -1635,7 +1646,7 @@ void ARMConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
   MachineBasicBlock *CPEBB = CPEMI->getParent();
   unsigned Size = CPEMI->getOperand(2).getImm();
   CPEMI->eraseFromParent();
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   BBUtils->adjustBBSize(CPEBB, -Size);
   // All succeeding offsets have the current size value added in, fix this.
   if (CPEBB->empty()) {
@@ -1696,7 +1707,7 @@ bool
 ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
   MachineInstr *MI = Br.MI;
   MachineBasicBlock *MBB = MI->getParent();
-  if (!isThumb1)
+  if (!getIsThumb1())
     llvm_unreachable("fixupUnconditionalBr is Thumb1 only!");
 
   if (!AFI->isLRSpilled())
@@ -1705,7 +1716,7 @@ ARMConstantIslands::fixupUnconditionalBr(ImmBranch &Br) {
   // Use BL to implement far jump.
   Br.MaxDisp = (1 << 21) * 2;
   MI->setDesc(TII->get(ARM::tBfar));
-  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  auto &BBInfo = BBUtils->getBBInfo();
   BBInfo[MBB->getNumber()].Size += 2;
   BBUtils->adjustBBOffsetsAfter(MBB);
   ++NumUBrFixed;
@@ -1792,7 +1803,7 @@ ARMConstantIslands::fixupConditionalBr(ImmBranch &Br) {
     .addMBB(NextBB).addImm(CC).addReg(CCReg);
   Br.MI = &MBB->back();
   BBUtils->adjustBBSize(MBB, TII->getInstSizeInBytes(MBB->back()));
-  if (isThumb)
+  if (getIsThumb())
     BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr))
         .addMBB(DestBB)
         .add(predOps(ARMCC::AL));
@@ -1929,7 +1940,7 @@ bool ARMConstantIslands::optimizeThumb2Branches() {
     // Check if the distance is within 126. Subtract starting offset by 2
     // because the cmp will be eliminated.
     unsigned BrOffset = BBUtils->getOffsetOf(Br.MI) + 4 - 2;
-    BBInfoVector &BBInfo = BBUtils->getBBInfo();
+    auto &BBInfo = BBUtils->getBBInfo();
     unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
     if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
       return false;
@@ -2136,7 +2147,7 @@ bool ARMConstantIslands::preserveBaseRegister(MachineInstr *JumpMI,
 
   if (RemovableAdd) {
     RemovableAdd->eraseFromParent();
-    DeadSize += isThumb2 ? 4 : 2;
+    DeadSize += getIsThumb2() ? 4 : 2;
   } else if (BaseReg == EntryReg) {
     // The add wasn't removable, but clobbered the base for the TBB. So we can't
     // preserve it.
@@ -2221,7 +2232,7 @@ bool ARMConstantIslands::optimizeThumb2JumpTables() {
     bool HalfWordOk = true;
     unsigned JTOffset = BBUtils->getOffsetOf(MI) + 4;
     const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
-    BBInfoVector &BBInfo = BBUtils->getBBInfo();
+    auto &BBInfo = BBUtils->getBBInfo();
     for (MachineBasicBlock *MBB : JTBBs) {
       unsigned DstOffset = BBInfo[MBB->getNumber()].Offset;
       // Negative offset is not ok. FIXME: We should change BB layout to make
@@ -2249,7 +2260,7 @@ bool ARMConstantIslands::optimizeThumb2JumpTables() {
 
     unsigned IdxReg = ~0U;
     bool IdxRegKill = true;
-    if (isThumb2) {
+    if (getIsThumb2()) {
       IdxReg = MI->getOperand(1).getReg();
       IdxRegKill = MI->getOperand(1).isKill();
 
@@ -2302,7 +2313,7 @@ bool ARMConstantIslands::optimizeThumb2JumpTables() {
       if (registerDefinedBetween(BaseReg, Load->getNextNode(), MBB->end(), TRI))
         continue;
 
-      if (isPositionIndependentOrROPI) {
+      if (getIsPositionIndependentOrROPI()) {
         MachineInstr *Add = Load->getNextNode();
         if (Add->getOpcode() != ARM::tADDrr ||
             Add->getOperand(2).getReg() != BaseReg ||
@@ -2334,7 +2345,7 @@ bool ARMConstantIslands::optimizeThumb2JumpTables() {
     LLVM_DEBUG(dbgs() << "Shrink JT: " << *MI);
     MachineInstr *CPEMI = User.CPEMI;
     unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT;
-    if (!isThumb2)
+    if (!getIsThumb2())
       Opc = ByteOk ? ARM::tTBB_JT : ARM::tTBH_JT;
 
     MachineBasicBlock::iterator MI_JT = MI;
@@ -2355,11 +2366,11 @@ bool ARMConstantIslands::optimizeThumb2JumpTables() {
       NewJTMI->getOperand(0).setIsKill(false);
 
       if (CanDeleteLEA) {
-        if (isThumb2)
+        if (getIsThumb2())
           RemoveDeadAddBetweenLEAAndJT(User.MI, MI, DeadSize);
 
         User.MI->eraseFromParent();
-        DeadSize += isThumb2 ? 4 : 2;
+        DeadSize += getIsThumb2() ? 4 : 2;
 
         // The LEA was eliminated, the TBB instruction becomes the only new user
         // of the jump table.
@@ -2478,7 +2489,7 @@ MachineBasicBlock *ARMConstantIslands::adjustJTTargetBlockForward(
   // Add an unconditional branch from NewBB to BB.
   // There doesn't seem to be meaningful DebugInfo available; this doesn't
   // correspond directly to anything in the source.
-  if (isThumb2)
+  if (getIsThumb2())
     BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B))
         .addMBB(BB)
         .add(predOps(ARMCC::AL));
diff --git a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
index e78f228a912c0..685375251e98f 100644
--- a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
+++ b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp
@@ -164,12 +164,12 @@ static bool getBaseOffset(const MachineInstr &MI, const MachineOperand *&BaseOp,
 
 ARMBankConflictHazardRecognizer::ARMBankConflictHazardRecognizer(
     const ScheduleDAG *DAG, int64_t CPUBankMask, bool CPUAssumeITCMConflict)
-    : MF(DAG->MF), DL(DAG->MF.getDataLayout()),
+    : Accesses(decltype(this->Accesses)::withFlags(unsigned(bool(
+          AssumeITCMConflict.getNumOccurrences() ? AssumeITCMConflict
+                                                 : CPUAssumeITCMConflict)))),
+      MF(DAG->MF), DL(DAG->MF.getDataLayout()),
       DataMask(DataBankMask.getNumOccurrences() ? int64_t(DataBankMask)
-                                                : CPUBankMask),
-      AssumeITCMBankConflict(AssumeITCMConflict.getNumOccurrences()
-                                 ? AssumeITCMConflict
-                                 : CPUAssumeITCMConflict) {
+                                                : CPUBankMask) {
   MaxLookAhead = 1;
 }
 
@@ -225,7 +225,7 @@ ARMBankConflictHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
     // Constant pools (likely in ITCM)
     if (BasePseudoVal0 && BasePseudoVal1 &&
         BasePseudoVal0->kind() == BasePseudoVal1->kind() &&
-        BasePseudoVal0->isConstantPool() && AssumeITCMBankConflict)
+        BasePseudoVal0->isConstantPool() && getAssumeITCMBankConflict())
       return Hazard;
 
     // Is this a stack pointer-relative access?  We could in general try to
diff --git a/llvm/lib/Target/ARM/ARMHazardRecognizer.h b/llvm/lib/Target/ARM/ARMHazardRecognizer.h
index b9ac3555c2bc3..99769244ae7c3 100644
--- a/llvm/lib/Target/ARM/ARMHazardRecognizer.h
+++ b/llvm/lib/Target/ARM/ARMHazardRecognizer.h
@@ -16,6 +16,7 @@
 #include "ARMBaseInstrInfo.h"
 #include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
 #include "llvm/Support/DataTypes.h"
 #include <initializer_list>
@@ -44,11 +45,12 @@ class ARMHazardRecognizerFPMLx : public ScheduleHazardRecognizer {
 
 // Hazards related to bank conflicts
 class ARMBankConflictHazardRecognizer : public ScheduleHazardRecognizer {
-  SmallVector<MachineInstr *, 8> Accesses;
+  llvm::SmallVectorWithFlags<MachineInstr *, 8> Accesses;
   const MachineFunction &MF;
   const DataLayout &DL;
   int64_t DataMask;
-  bool AssumeITCMBankConflict;
+  bool getAssumeITCMBankConflict() const { return Accesses.getFlag(0); }
+  void setAssumeITCMBankConflict(bool Value) { Accesses.setFlag(0, Value); }
 
 public:
   ARMBankConflictHazardRecognizer(const ScheduleDAG *DAG, int64_t DDM,
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index cd038985c2f71..3c0e1bd255fa1 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1796,9 +1796,9 @@ SDValue ARMTargetLowering::MoveFromHPR(const SDLoc &dl, SelectionDAG &DAG,
 /// appropriate copies out of appropriate physical registers.
 SDValue ARMTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
-    SDValue ThisVal, bool isCmseNSCall) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals, bool isThisReturn, SDValue ThisVal,
+    bool isCmseNSCall) const {
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
@@ -2014,15 +2014,14 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                              SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &isTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool doesNotRet                       = CLI.DoesNotReturn;
-  bool isVarArg                         = CLI.IsVarArg;
+  bool doesNotRet = CLI.getDoesNotReturn();
+  bool isVarArg = CLI.getIsVarArg();
   const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
@@ -2056,13 +2055,13 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // Disable tail calls if they're not supported.
   if (!Subtarget->supportsTailCall())
-    isTailCall = false;
+    CLI.setIsTailCall(false);
 
   // For both the non-secure calls and the returns from a CMSE entry function,
   // the function needs to do some extra work after the call, or before the
   // return, respectively, thus it cannot end with a tail call
   if (isCmseNSCall || AFI->isCmseNSEntryFunction())
-    isTailCall = false;
+    CLI.setIsTailCall(false);
 
   if (isa<GlobalAddressSDNode>(Callee)) {
     // If we're optimizing for minimum size and the function is called three or
@@ -2078,22 +2077,23 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                        }) > 2;
     }
   }
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     // Check if it's really possible to do a tail call.
-    isTailCall =
-        IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
+    CLI.setIsTailCall(IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs,
+                                                        PreferIndirect));
 
-    if (isTailCall && !getTargetMachine().Options.GuaranteedTailCallOpt &&
+    if (CLI.getIsTailCall() &&
+        !getTargetMachine().Options.GuaranteedTailCallOpt &&
         CallConv != CallingConv::Tail && CallConv != CallingConv::SwiftTail)
       isSibCall = true;
 
     // We don't support GuaranteedTailCallOpt for ARM, only automatically
     // detected sibcalls.
-    if (isTailCall)
+    if (CLI.getIsTailCall())
       ++NumTailCalls;
   }
 
-  if (!isTailCall && CLI.CB && CLI.CB->isMustTailCall())
+  if (!CLI.getIsTailCall() && CLI.CB && CLI.CB->isMustTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
                        "site marked musttail");
 
@@ -2107,7 +2107,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // arguments to begin at SP+0. Completely unused for non-tail calls.
   int SPDiff = 0;
 
-  if (isTailCall && !isSibCall) {
+  if (CLI.getIsTailCall() && !isSibCall) {
     auto FuncInfo = MF.getInfo<ARMFunctionInfo>();
     unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
 
@@ -2134,7 +2134,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   } else {
     // Adjust the stack pointer for the new arguments...
     // These operations are automatically eliminated by the prolog/epilog pass
-    Chain = DAG.getCALLSEQ_START(Chain, isTailCall ? 0 : NumBytes, 0, dl);
+    Chain =
+        DAG.getCALLSEQ_START(Chain, CLI.getIsTailCall() ? 0 : NumBytes, 0, dl);
   }
 
   SDValue StackPtr =
@@ -2151,7 +2152,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // to the argument area.
   DenseMap<unsigned, SDValue> ByValTemporaries;
   SDValue ByValTempChain;
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     SmallVector<SDValue, 8> ByValCopyChains;
     for (const CCValAssign &VA : ArgLocs) {
       unsigned ArgIdx = VA.getValNo();
@@ -2238,7 +2239,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       break;
     }
 
-    if (isTailCall && VA.isMemLoc() && !AfterFormalArgLoads) {
+    if (CLI.getIsTailCall() && VA.isMemLoc() && !AfterFormalArgLoads) {
       Chain = DAG.getStackArgumentTokenFactor(Chain);
       if (ByValTempChain) {
         // In case of large byval copies, re-using the stackframe for tail-calls
@@ -2310,23 +2311,23 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                 DAG.getConstant(1, dl, MVT::i32));
 
       PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
-                       StackPtr, MemOpChains, isTailCall, SPDiff);
+                       StackPtr, MemOpChains, CLI.getIsTailCall(), SPDiff);
 
       VA = ArgLocs[++i]; // skip ahead to next loc
       if (VA.isRegLoc()) {
         PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
-                         StackPtr, MemOpChains, isTailCall, SPDiff);
+                         StackPtr, MemOpChains, CLI.getIsTailCall(), SPDiff);
       } else {
         assert(VA.isMemLoc());
         SDValue DstAddr;
         MachinePointerInfo DstInfo;
-        std::tie(DstAddr, DstInfo) =
-            computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
+        std::tie(DstAddr, DstInfo) = computeAddrForCallArg(
+            dl, DAG, VA, StackPtr, CLI.getIsTailCall(), SPDiff);
         MemOpChains.push_back(DAG.getStore(Chain, dl, Op1, DstAddr, DstInfo));
       }
     } else if (VA.needsCustom() && VA.getLocVT() == MVT::f64) {
       PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
-                       StackPtr, MemOpChains, isTailCall, SPDiff);
+                       StackPtr, MemOpChains, CLI.getIsTailCall(), SPDiff);
     } else if (VA.isRegLoc()) {
       if (realArgIdx == 0 && Flags.isReturned() && !Flags.isSwiftSelf() &&
           Outs[0].VT == MVT::i32) {
@@ -2357,7 +2358,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
         NeedsStackCopy = true;
       } else {
         ByValSrc = Arg;
-        NeedsStackCopy = !isTailCall;
+        NeedsStackCopy = !CLI.getIsTailCall();
       }
 
       // If part of the argument is in registers, load them.
@@ -2390,8 +2391,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
         auto PtrVT = getPointerTy(DAG.getDataLayout());
         SDValue Dst;
         MachinePointerInfo DstInfo;
-        std::tie(Dst, DstInfo) =
-            computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
+        std::tie(Dst, DstInfo) = computeAddrForCallArg(
+            dl, DAG, VA, StackPtr, CLI.getIsTailCall(), SPDiff);
         SDValue SrcOffset = DAG.getIntPtrConstant(4*offset, dl);
         SDValue Src = DAG.getNode(ISD::ADD, dl, PtrVT, ByValSrc, SrcOffset);
         SDValue SizeNode = DAG.getConstant(Flags.getByValSize() - 4*offset, dl,
@@ -2408,8 +2409,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       assert(VA.isMemLoc());
       SDValue DstAddr;
       MachinePointerInfo DstInfo;
-      std::tie(DstAddr, DstInfo) =
-          computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
+      std::tie(DstAddr, DstInfo) = computeAddrForCallArg(
+          dl, DAG, VA, StackPtr, CLI.getIsTailCall(), SPDiff);
 
       SDValue Store = DAG.getStore(Chain, dl, Arg, DstAddr, DstInfo);
       MemOpChains.push_back(Store);
@@ -2631,7 +2632,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // the frame up *after* the call, however in the ABI-changing tail-call case
   // we've carefully laid out the parameters so that when sp is reset they'll be
   // in the correct location.
-  if (isTailCall && !isSibCall) {
+  if (CLI.getIsTailCall() && !isSibCall) {
     Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InGlue, dl);
     InGlue = Chain.getValue(1);
   }
@@ -2640,7 +2641,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   Ops.push_back(Chain);
   Ops.push_back(Callee);
 
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     Ops.push_back(DAG.getSignedTargetConstant(SPDiff, dl, MVT::i32));
   }
 
@@ -2671,12 +2672,12 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   if (InGlue.getNode())
     Ops.push_back(InGlue);
 
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     SDValue Ret = DAG.getNode(ARMISD::TC_RETURN, dl, MVT::Other, Ops);
     if (CLI.CFIType)
       Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue());
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
     return Ret;
   }
@@ -2685,7 +2686,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   Chain = DAG.getNode(CallOpc, dl, {MVT::Other, MVT::Glue}, Ops);
   if (CLI.CFIType)
     Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   InGlue = Chain.getValue(1);
   DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
 
@@ -2771,10 +2772,10 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
     SmallVectorImpl<CCValAssign> &ArgLocs, const bool isIndirect) const {
   CallingConv::ID CalleeCC = CLI.CallConv;
   SDValue Callee = CLI.Callee;
-  bool isVarArg = CLI.IsVarArg;
-  const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  bool isVarArg = CLI.getIsVarArg();
+  const auto &Outs = CLI.Outs;
   const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  const SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  const auto &Ins = CLI.Ins;
   const SelectionDAG &DAG = CLI.DAG;
   MachineFunction &MF = DAG.getMachineFunction();
   const Function &CallerF = MF.getFunction();
@@ -2877,7 +2878,7 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
   // not perform tail call, since part of the argument is in caller's local
   // frame.
   const ARMFunctionInfo *AFI_Caller = MF.getInfo<ARMFunctionInfo>();
-  if (CLI.IsVarArg && AFI_Caller->getArgRegsSaveSize()) {
+  if (CLI.getIsVarArg() && AFI_Caller->getArgRegsSaveSize()) {
     LLVM_DEBUG(dbgs() << "false (arg reg save area)\n");
     return false;
   }
@@ -2899,11 +2900,11 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
   return true;
 }
 
-bool
-ARMTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
-                                  MachineFunction &MF, bool isVarArg,
-                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                  LLVMContext &Context, const Type *RetTy) const {
+bool ARMTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, isVarArg));
@@ -2942,12 +2943,12 @@ static SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
   return DAG.getNode(ARMISD::INTRET_GLUE, DL, MVT::Other, RetOps);
 }
 
-SDValue
-ARMTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &dl, SelectionDAG &DAG) const {
+SDValue ARMTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &dl,
+                                       SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to a location.
   SmallVector<CCValAssign, 16> RVLocs;
 
@@ -4251,8 +4252,8 @@ SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
 
 SDValue ARMTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
 
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 4f95a1cdeb2ef..0288508ea8d9c 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -637,10 +637,10 @@ class VectorType;
 
     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                             CallingConv::ID CallConv, bool isVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
-                            const SDLoc &dl, SelectionDAG &DAG,
-                            SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
-                            SDValue ThisVal, bool isCmseNSCall) const;
+                            llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                            SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+                            bool isThisReturn, SDValue ThisVal,
+                            bool isCmseNSCall) const;
 
     void initializeSplitCSR(MachineBasicBlock *Entry) const override;
     void insertCopiesSplitCSR(
@@ -659,8 +659,8 @@ class VectorType;
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
 
     int StoreByValRegs(CCState &CCInfo, SelectionDAG &DAG, const SDLoc &dl,
@@ -686,13 +686,12 @@ class VectorType;
         TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
         SmallVectorImpl<CCValAssign> &ArgLocs, const bool isIndirect) const;
 
-    bool CanLowerReturn(CallingConv::ID CallConv,
-                        MachineFunction &MF, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+    bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                         LLVMContext &Context, const Type *RetTy) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index 1dd0087cf81eb..9f495306572e2 100644
--- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -28,6 +28,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -108,8 +109,15 @@ struct ARMLoadStoreOpt {
   LiveRegUnits LiveRegs;
   const RegisterClassInfo *RCI = nullptr;
   MachineBasicBlock::const_iterator LiveRegPos;
-  bool LiveRegsValid;
-  bool isThumb1, isThumb2;
+  bool getLiveRegsValid() const { return MergeBaseCandidates.getFlag(0); }
+  bool setLiveRegsValid(bool Value) {
+    MergeBaseCandidates.setFlag(0, Value);
+    return Value;
+  }
+  bool getIsThumb1() const { return MergeBaseCandidates.getFlag(1); }
+  void setIsThumb1(bool Value) { MergeBaseCandidates.setFlag(1, Value); }
+  bool getIsThumb2() const { return MergeBaseCandidates.getFlag(2); }
+  void setIsThumb2(bool Value) { MergeBaseCandidates.setFlag(2, Value); }
 
   bool runOnMachineFunction(MachineFunction &Fn,
                             const RegisterClassInfo &RegClassInfo);
@@ -151,7 +159,7 @@ struct ARMLoadStoreOpt {
   };
   SpecificBumpPtrAllocator<MergeCandidate> Allocator;
   SmallVector<const MergeCandidate *, 4> Candidates;
-  SmallVector<MachineInstr *, 4> MergeBaseCandidates;
+  llvm::SmallVectorWithFlags<MachineInstr *, 4, 3> MergeBaseCandidates;
 
   MachineBasicBlock::iterator eraseInstr(MachineBasicBlock::iterator MI);
 
@@ -502,7 +510,7 @@ void ARMLoadStoreOpt::UpdateBaseRegUses(MachineBasicBlock &MBB,
                                         unsigned WordOffset,
                                         ARMCC::CondCodes Pred,
                                         unsigned PredReg) {
-  assert(isThumb1 && "Can only update base register uses for Thumb1!");
+  assert(getIsThumb1() && "Can only update base register uses for Thumb1!");
   // Start updating any instructions with immediate offsets. Insert a SUB before
   // the first non-updateable instruction (if any).
   for (; MBBI != MBB.end(); ++MBBI) {
@@ -598,8 +606,8 @@ void ARMLoadStoreOpt::UpdateBaseRegUses(MachineBasicBlock &MBB,
 
 MachineBasicBlock::iterator
 ARMLoadStoreOpt::eraseInstr(MachineBasicBlock::iterator MI) {
-  if (LiveRegsValid && LiveRegPos == MI)
-    LiveRegsValid = false;
+  if (getLiveRegsValid() && LiveRegPos == MI)
+    setLiveRegsValid(false);
   return MI->eraseFromParent();
 }
 
@@ -617,11 +625,11 @@ unsigned ARMLoadStoreOpt::findFreeReg(const TargetRegisterClass &RegClass) {
 void ARMLoadStoreOpt::moveLiveRegsBefore(const MachineBasicBlock &MBB,
     MachineBasicBlock::const_iterator Before) {
   // Initialize if we never queried in this block.
-  if (!LiveRegsValid) {
+  if (!getLiveRegsValid()) {
     LiveRegs.init(*TRI);
     LiveRegs.addLiveOuts(MBB);
     LiveRegPos = MBB.end();
-    LiveRegsValid = true;
+    setLiveRegsValid(true);
   }
   // Move backward just before the "Before" position.
   while (LiveRegPos != Before) {
@@ -653,16 +661,17 @@ MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
 
   // For Thumb1 targets, it might be necessary to clobber the CPSR to merge.
   // Compute liveness information for that register to make the decision.
-  bool SafeToClobberCPSR = !isThumb1 ||
-    (MBB.computeRegisterLiveness(TRI, ARM::CPSR, InsertBefore, 20) ==
-     MachineBasicBlock::LQR_Dead);
+  bool SafeToClobberCPSR =
+      !getIsThumb1() ||
+      (MBB.computeRegisterLiveness(TRI, ARM::CPSR, InsertBefore, 20) ==
+       MachineBasicBlock::LQR_Dead);
 
-  bool Writeback = isThumb1; // Thumb1 LDM/STM have base reg writeback.
+  bool Writeback = getIsThumb1(); // Thumb1 LDM/STM have base reg writeback.
 
   // Exception: If the base register is in the input reglist, Thumb1 LDM is
   // non-writeback.
   // It's also not possible to merge an STR of the base register in Thumb1.
-  if (isThumb1 && ContainsReg(Regs, Base)) {
+  if (getIsThumb1() && ContainsReg(Regs, Base)) {
     assert(Base != ARM::SP && "Thumb1 does not allow SP in register list");
     if (Opcode == ARM::tLDRi)
       Writeback = false;
@@ -673,13 +682,13 @@ MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
   ARM_AM::AMSubMode Mode = ARM_AM::ia;
   // VFP and Thumb2 do not support IB or DA modes. Thumb1 only supports IA.
   bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
-  bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;
+  bool haveIBAndDA = isNotVFP && !getIsThumb2() && !getIsThumb1();
 
   if (Offset == 4 && haveIBAndDA) {
     Mode = ARM_AM::ib;
   } else if (Offset == -4 * (int)NumRegs + 4 && haveIBAndDA) {
     Mode = ARM_AM::da;
-  } else if (Offset == -4 * (int)NumRegs && isNotVFP && !isThumb1) {
+  } else if (Offset == -4 * (int)NumRegs && isNotVFP && !getIsThumb1()) {
     // VLDM/VSTM do not support DB mode without also updating the base reg.
     Mode = ARM_AM::db;
   } else if (Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
@@ -713,28 +722,28 @@ MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
         for (const std::pair<unsigned, bool> &R : Regs)
           LiveRegs.addReg(R.first);
 
-      NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);
+      NewBase =
+          findFreeReg(getIsThumb1() ? ARM::tGPRRegClass : ARM::GPRRegClass);
       if (NewBase == 0)
         return nullptr;
     }
 
-    int BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2ADDspImm
-                                                          : ARM::t2ADDri)
-                           : (isThumb1 && Base == ARM::SP)
-                                 ? ARM::tADDrSPi
-                                 : (isThumb1 && Offset < 8)
-                                       ? ARM::tADDi3
-                                       : isThumb1 ? ARM::tADDi8 : ARM::ADDri;
+    int BaseOpc = getIsThumb2() ? (BaseKill && Base == ARM::SP ? ARM::t2ADDspImm
+                                                               : ARM::t2ADDri)
+                  : (getIsThumb1() && Base == ARM::SP) ? ARM::tADDrSPi
+                  : (getIsThumb1() && Offset < 8)      ? ARM::tADDi3
+                  : getIsThumb1()                      ? ARM::tADDi8
+                                                       : ARM::ADDri;
 
     if (Offset < 0) {
       // FIXME: There are no Thumb1 load/store instructions with negative
       // offsets. So the Base != ARM::SP might be unnecessary.
       Offset = -Offset;
-      BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2SUBspImm
-                                                        : ARM::t2SUBri)
-                         : (isThumb1 && Offset < 8 && Base != ARM::SP)
-                               ? ARM::tSUBi3
-                               : isThumb1 ? ARM::tSUBi8 : ARM::SUBri;
+      BaseOpc = getIsThumb2() ? (BaseKill && Base == ARM::SP ? ARM::t2SUBspImm
+                                                             : ARM::t2SUBri)
+                : (getIsThumb1() && Offset < 8 && Base != ARM::SP) ? ARM::tSUBi3
+                : getIsThumb1()                                    ? ARM::tSUBi8
+                                                                   : ARM::SUBri;
     }
 
     if (!TL->isLegalAddImmediate(Offset))
@@ -746,7 +755,7 @@ MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
     bool KillOldBase = BaseKill &&
       (!isi32Store(Opcode) || !ContainsReg(Regs, Base));
 
-    if (isThumb1) {
+    if (getIsThumb1()) {
       // Thumb1: depending on immediate size, use either
       //   ADDS NewBase, Base, #imm3
       // or
@@ -810,13 +819,13 @@ MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(
   // Otherwise, don't merge.
   // It's safe to return here since the code to materialize a new base register
   // above is also conditional on SafeToClobberCPSR.
-  if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)
+  if (getIsThumb1() && !SafeToClobberCPSR && Writeback && !BaseKill)
     return nullptr;
 
   MachineInstrBuilder MIB;
 
   if (Writeback) {
-    assert(isThumb1 && "expected Writeback only inThumb1");
+    assert(getIsThumb1() && "expected Writeback only inThumb1");
     if (Opcode == ARM::tLDMIA) {
       assert(!(ContainsReg(Regs, Base)) && "Thumb1 can't LDM ! with Base in Regs");
       // Update tLDMIA with writeback if necessary.
@@ -1305,7 +1314,8 @@ findIncDecAfter(MachineBasicBlock::iterator MBBI, Register Reg,
 /// ldmdb rn!, <ra, rb, rc>
 bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) {
   // Thumb1 is already using updating loads/stores.
-  if (isThumb1) return false;
+  if (getIsThumb1())
+    return false;
   LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);
 
   const MachineOperand &BaseOP = MI->getOperand(0);
@@ -1486,7 +1496,8 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc,
 bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {
   // Thumb1 doesn't have updating LDR/STR.
   // FIXME: Use LDM/STM with single register instead.
-  if (isThumb1) return false;
+  if (getIsThumb1())
+    return false;
   LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);
 
   Register Base = getLoadStoreBaseOp(*MI).getReg();
@@ -1902,7 +1913,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
   unsigned Position = 0;
   assert(Candidates.size() == 0);
   assert(MergeBaseCandidates.size() == 0);
-  LiveRegsValid = false;
+  setLiveRegsValid(false);
 
   for (MachineBasicBlock::iterator I = MBB.end(), MBBI; I != MBB.begin();
        I = MBBI) {
@@ -2055,7 +2066,8 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
 ///   ldmfd sp!, {..., pc}
 bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
   // Thumb1 LDM doesn't allow high registers.
-  if (isThumb1) return false;
+  if (getIsThumb1())
+    return false;
   if (MBB.empty()) return false;
 
   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
@@ -2075,9 +2087,10 @@ bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
       MachineOperand &MO = PrevMI.getOperand(PrevMI.getNumOperands() - 1);
       if (MO.getReg() != ARM::LR)
         return false;
-      unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
-      assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||
-              Opcode == ARM::LDMIA_UPD) && "Unsupported multiple load-return!");
+      unsigned NewOpc = (getIsThumb2() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);
+      assert(((getIsThumb2() && Opcode == ARM::t2LDMIA_UPD) ||
+              Opcode == ARM::LDMIA_UPD) &&
+             "Unsupported multiple load-return!");
       PrevMI.setDesc(TII->get(NewOpc));
       MO.setReg(ARM::PC);
       PrevMI.copyImplicitOps(*MBB.getParent(), *MBBI);
@@ -2125,15 +2138,15 @@ bool ARMLoadStoreOpt::runOnMachineFunction(
   TRI = STI->getRegisterInfo();
   RCI = &RegClassInfo;
 
-  isThumb2 = AFI->isThumb2Function();
-  isThumb1 = AFI->isThumbFunction() && !isThumb2;
+  setIsThumb2(AFI->isThumb2Function());
+  setIsThumb1(AFI->isThumbFunction() && !getIsThumb2());
 
   bool Modified = false, ModifiedLDMReturn = false;
   for (MachineBasicBlock &MBB : Fn) {
     Modified |= LoadStoreMultipleOpti(MBB);
     if (STI->hasV5TOps() && !AFI->shouldSignReturnAddress())
       ModifiedLDMReturn |= MergeReturnIntoLDM(MBB);
-    if (isThumb1)
+    if (getIsThumb1())
       Modified |= CombineMovBx(MBB);
   }
   Modified |= ModifiedLDMReturn;
diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
index 3635fb3da020c..8230c162805e8 100644
--- a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
+++ b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
@@ -58,6 +58,7 @@
 #include "MVETailPredUtils.h"
 #include "Thumb2InstrInfo.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/LivePhysRegs.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -373,13 +374,15 @@ namespace {
     MachineInstr *Dec = nullptr;
     MachineInstr *End = nullptr;
     MachineOperand TPNumElements;
-    SmallVector<MachineInstr *, 4> VCTPs;
+    llvm::SmallVectorWithFlags<MachineInstr *, 4, 2> VCTPs;
     SmallPtrSet<MachineInstr *, 4> ToRemove;
     SmallPtrSet<MachineInstr *, 4> BlockMasksToRecompute;
     SmallPtrSet<MachineInstr *, 4> DoubleWidthResultInstrs;
     SmallPtrSet<MachineInstr *, 4> VMOVCopies;
-    bool Revert = false;
-    bool CannotTailPredicate = false;
+    bool getRevert() const { return VCTPs.getFlag(0); }
+    void setRevert(bool Value) { VCTPs.setFlag(0, Value); }
+    bool getCannotTailPredicate() const { return VCTPs.getFlag(1); }
+    void setCannotTailPredicate(bool Value) { VCTPs.setFlag(1, Value); }
     VPTState VPTstate;
 
     LowOverheadLoop(MachineLoop &ML, MachineLoopInfo &MLI, ReachingDefInfo &RDI,
@@ -399,14 +402,14 @@ namespace {
     bool ValidateMVEInst(MachineInstr *MI);
 
     void AnalyseMVEInst(MachineInstr *MI) {
-      CannotTailPredicate = !ValidateMVEInst(MI);
+      setCannotTailPredicate(!ValidateMVEInst(MI));
     }
 
     bool IsTailPredicationLegal() const {
       // For now, let's keep things really simple and only support a single
       // block for tail predication.
-      return !Revert && FoundAllComponents() && !VCTPs.empty() &&
-             !CannotTailPredicate && ML.getNumBlocks() == 1;
+      return !getRevert() && FoundAllComponents() && !VCTPs.empty() &&
+             !getCannotTailPredicate() && ML.getNumBlocks() == 1;
     }
 
     // Given that MI is a VCTP, check that is equivalent to any other VCTPs
@@ -1067,7 +1070,7 @@ bool LowOverheadLoop::ValidateLiveOuts() {
 }
 
 void LowOverheadLoop::Validate(ARMBasicBlockUtils *BBUtils) {
-  if (Revert)
+  if (getRevert())
     return;
 
   // Check branch target ranges: WLS[TP] can only branch forwards and LE[TP]
@@ -1108,8 +1111,8 @@ void LowOverheadLoop::Validate(ARMBasicBlockUtils *BBUtils) {
   LLVM_DEBUG(dbgs() << "ARM Loops: Will insert LoopStart at "
                     << *StartInsertPt);
 
-  Revert = !ValidateRanges(Start, End, BBUtils, ML);
-  CannotTailPredicate = !ValidateTailPredicate();
+  setRevert(!ValidateRanges(Start, End, BBUtils, ML));
+  setCannotTailPredicate(!ValidateTailPredicate());
 }
 
 bool LowOverheadLoop::AddVCTP(MachineInstr *MI) {
@@ -1211,7 +1214,7 @@ static bool ValidateMVEStore(MachineInstr *MI, MachineLoop *ML) {
 }
 
 bool LowOverheadLoop::ValidateMVEInst(MachineInstr *MI) {
-  if (CannotTailPredicate)
+  if (getCannotTailPredicate())
     return false;
 
   if (!shouldInspect(*MI))
@@ -1380,7 +1383,7 @@ bool ARMLowOverheadLoops::ProcessLoop(MachineLoop *ML) {
         // TODO: Though the call will require LE to execute again, does this
         // mean we should revert? Always executing LE hopefully should be
         // faster than performing a sub,cmp,br or even subs,br.
-        LoLoop.Revert = true;
+        LoLoop.setRevert(true);
         LLVM_DEBUG(dbgs() << "ARM Loops: Found call.\n");
       } else {
         // Record VPR defs and build up their corresponding vpt blocks.
@@ -1407,7 +1410,7 @@ bool ARMLowOverheadLoops::ProcessLoop(MachineLoop *ML) {
     RDI->getReachingLocalUses(LoLoop.Dec, MCRegister::from(ARM::LR), Uses);
     if (Uses.size() > 1 || !Uses.count(LoLoop.End)) {
       LLVM_DEBUG(dbgs() << "ARM Loops: Unable to remove LoopDec.\n");
-      LoLoop.Revert = true;
+      LoLoop.setRevert(true);
     }
   }
   LoLoop.Validate(BBUtils.get());
@@ -1769,7 +1772,7 @@ void ARMLowOverheadLoops::Expand(LowOverheadLoop &LoLoop) {
     }
   };
 
-  if (LoLoop.Revert) {
+  if (LoLoop.getRevert()) {
     if (isWhileLoopStart(*LoLoop.Start))
       RevertWhile(LoLoop.Start);
     else
diff --git a/llvm/lib/Target/ARM/ARMParallelDSP.cpp b/llvm/lib/Target/ARM/ARMParallelDSP.cpp
index 13a52416caab3..4650054faa05f 100644
--- a/llvm/lib/Target/ARM/ARMParallelDSP.cpp
+++ b/llvm/lib/Target/ARM/ARMParallelDSP.cpp
@@ -17,6 +17,7 @@
 #include "ARM.h"
 #include "ARMSubtarget.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
@@ -64,9 +65,15 @@ namespace {
     Instruction   *Root;
     Value*        LHS;
     Value*        RHS;
-    bool          Exchange = false;
-    bool          Paired = false;
-    SmallVector<LoadInst*, 2> VecLd;    // Container for loads to widen.
+    bool getExchange() const { return VecLd.getFlag(0); }
+    bool setExchange(bool Value) {
+      VecLd.setFlag(0, Value);
+      return Value;
+    }
+    bool getPaired() const { return VecLd.getFlag(1); }
+    void setPaired(bool Value) { VecLd.setFlag(1, Value); }
+    llvm::SmallVectorWithFlags<LoadInst *, 2, 2>
+        VecLd; // Container for loads to widen.
 
     MulCandidate(Instruction *I, Value *lhs, Value *rhs) :
       Root(I), LHS(lhs), RHS(rhs) { }
@@ -145,10 +152,10 @@ namespace {
       LLVM_DEBUG(dbgs() << "Pairing:\n"
                  << *Mul0->Root << "\n"
                  << *Mul1->Root << "\n");
-      Mul0->Paired = true;
-      Mul1->Paired = true;
+      Mul0->setPaired(true);
+      Mul1->setPaired(true);
       if (Exchange)
-        Mul1->Exchange = true;
+        Mul1->setExchange(true);
       MulPairs.push_back(std::make_pair(Mul0, Mul1));
     }
 
@@ -196,8 +203,7 @@ namespace {
     SmallVector<LoadInst*, 4> Loads;
 
   public:
-    WidenedLoad(SmallVectorImpl<LoadInst*> &Lds, LoadInst *Wide)
-      : NewLd(Wide) {
+    WidenedLoad(ArrayRef<LoadInst *> Lds, LoadInst *Wide) : NewLd(Wide) {
       append_range(Loads, Lds);
     }
     LoadInst *getLoad() {
@@ -221,8 +227,9 @@ namespace {
     bool Search(Value *V, BasicBlock *BB, Reduction &R);
     bool RecordMemoryOps(BasicBlock *BB);
     void InsertParallelMACs(Reduction &Reduction);
-    bool AreSequentialLoads(LoadInst *Ld0, LoadInst *Ld1, MemInstList &VecMem);
-    LoadInst* CreateWideLoad(MemInstList &Loads, IntegerType *LoadTy);
+    template <typename LoadVectorT>
+    bool AreSequentialLoads(LoadInst *Ld0, LoadInst *Ld1, LoadVectorT &VecMem);
+    LoadInst *CreateWideLoad(ArrayRef<LoadInst *> Loads, IntegerType *LoadTy);
     bool CreateParallelPairs(Reduction &R);
 
     /// Try to match and generate: SMLAD, SMLADX - Signed Multiply Accumulate
@@ -294,8 +301,9 @@ namespace {
   };
 }
 
+template <typename LoadVectorT>
 bool ARMParallelDSP::AreSequentialLoads(LoadInst *Ld0, LoadInst *Ld1,
-                                        MemInstList &VecMem) {
+                                        LoadVectorT &VecMem) {
   if (!Ld0 || !Ld1)
     return false;
 
@@ -594,7 +602,7 @@ bool ARMParallelDSP::CreateParallelPairs(Reduction &R) {
   const unsigned Elems = Muls.size();
   for (unsigned i = 0; i < Elems; ++i) {
     MulCandidate *PMul0 = static_cast<MulCandidate*>(Muls[i].get());
-    if (PMul0->Paired)
+    if (PMul0->getPaired())
       continue;
 
     for (unsigned j = 0; j < Elems; ++j) {
@@ -602,7 +610,7 @@ bool ARMParallelDSP::CreateParallelPairs(Reduction &R) {
         continue;
 
       MulCandidate *PMul1 = static_cast<MulCandidate*>(Muls[j].get());
-      if (PMul1->Paired)
+      if (PMul1->getPaired())
         continue;
 
       const Instruction *Mul0 = PMul0->Root;
@@ -667,7 +675,7 @@ void ARMParallelDSP::InsertParallelMACs(Reduction &R) {
   IRBuilder<NoFolder> Builder(R.getRoot()->getParent());
   MulCandList &MulCands = R.getMuls();
   for (auto &MulCand : MulCands) {
-    if (MulCand->Paired)
+    if (MulCand->getPaired())
       continue;
 
     Instruction *Mul = cast<Instruction>(MulCand->Root);
@@ -724,12 +732,13 @@ void ARMParallelDSP::InsertParallelMACs(Reduction &R) {
 
     Instruction *InsertAfter = GetInsertPoint(WideLHS, WideRHS);
     InsertAfter = GetInsertPoint(InsertAfter, Acc);
-    Acc = CreateSMLAD(WideLHS, WideRHS, Acc, RHSMul->Exchange, InsertAfter);
+    Acc =
+        CreateSMLAD(WideLHS, WideRHS, Acc, RHSMul->getExchange(), InsertAfter);
   }
   R.UpdateRoot(cast<Instruction>(Acc));
 }
 
-LoadInst* ARMParallelDSP::CreateWideLoad(MemInstList &Loads,
+LoadInst *ARMParallelDSP::CreateWideLoad(ArrayRef<LoadInst *> Loads,
                                          IntegerType *LoadTy) {
   assert(Loads.size() == 2 && "currently only support widening two loads");
 
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index ab94d8eb21f44..71ec9b955d806 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -247,7 +248,12 @@ class ARMAsmParser : public MCTargetAsmParser {
   // Map of register aliases registers via the .req directive.
   StringMap<MCRegister> RegisterReqs;
 
-  bool NextSymbolIsThumb;
+  bool getNextSymbolIsThumb() const {
+    return PendingConditionalInsts.getFlag(0);
+  }
+  void setNextSymbolIsThumb(bool Value) {
+    PendingConditionalInsts.setFlag(0, Value);
+  }
 
   bool useImplicitITThumb() const {
     return ImplicitItMode == ImplicitItModeTy::Always ||
@@ -284,7 +290,7 @@ class ARMAsmParser : public MCTargetAsmParser {
                               //         would be legal.
   } ITState;
 
-  SmallVector<MCInst, 4> PendingConditionalInsts;
+  llvm::SmallVectorWithFlags<MCInst, 4> PendingConditionalInsts;
 
   void onEndOfFile() override {
     flushPendingInstructions(getParser().getStreamer());
@@ -707,7 +713,7 @@ class ARMAsmParser : public MCTargetAsmParser {
 
     VPTState.CurPosition = ~0U;
 
-    NextSymbolIsThumb = false;
+    setNextSymbolIsThumb(false);
   }
 
   // Implementation of the MCTargetAsmParser interface:
@@ -11673,9 +11679,9 @@ void ARMAsmParser::doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {
 }
 
 void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
-  if (NextSymbolIsThumb) {
+  if (getNextSymbolIsThumb()) {
     getTargetStreamer().emitThumbFunc(Symbol);
-    NextSymbolIsThumb = false;
+    setNextSymbolIsThumb(false);
   }
 }
 
@@ -11711,7 +11717,7 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
 
   getTargetStreamer().emitCode16();
 
-  NextSymbolIsThumb = true;
+  setNextSymbolIsThumb(true);
   return false;
 }
 
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index f51a8fd890f3e..b3da381258424 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -481,7 +482,8 @@ class ARMELFStreamer : public MCELFStreamer {
                  bool IsAndroid)
       : MCELFStreamer(Context, std::move(TAB), std::move(OW),
                       std::move(Emitter)),
-        IsThumb(IsThumb), IsAndroid(IsAndroid) {
+        Opcodes(decltype(this->Opcodes)::withFlags(
+            unsigned(IsThumb) | (unsigned(IsAndroid) << 1))) {
     EHReset();
   }
 
@@ -521,7 +523,7 @@ class ARMELFStreamer : public MCELFStreamer {
   /// necessary.
   void emitInstruction(const MCInst &Inst,
                        const MCSubtargetInfo &STI) override {
-    if (IsThumb)
+    if (getIsThumbFlag())
       EmitThumbMappingSymbol();
     else
       EmitARMMappingSymbol();
@@ -538,7 +540,7 @@ class ARMELFStreamer : public MCELFStreamer {
     case '\0':
       Size = 4;
 
-      assert(!IsThumb);
+      assert(!getIsThumbFlag());
       EmitARMMappingSymbol();
       for (unsigned II = 0, IE = Size; II != IE; II++) {
         const unsigned I = LittleEndian ? (Size - II - 1) : II;
@@ -550,7 +552,7 @@ class ARMELFStreamer : public MCELFStreamer {
     case 'w':
       Size = (Suffix == 'n' ? 2 : 4);
 
-      assert(IsThumb);
+      assert(getIsThumbFlag());
       EmitThumbMappingSymbol();
       // Thumb wide instructions are emitted as a pair of 16-bit words of the
       // appropriate endianness.
@@ -627,7 +629,7 @@ class ARMELFStreamer : public MCELFStreamer {
     return Val;
   };
 
-  void setIsThumb(bool Val) { IsThumb = Val; }
+  void setIsThumb(bool Val) { setIsThumbFlag(Val); }
 
 private:
   enum ElfMappingSymbol {
@@ -715,8 +717,10 @@ class ARMELFStreamer : public MCELFStreamer {
   void SwitchToExTabSection(const MCSymbol &FnStart);
   void SwitchToExIdxSection(const MCSymbol &FnStart);
 
-  bool IsThumb;
-  bool IsAndroid;
+  bool getIsThumbFlag() const { return Opcodes.getFlag(0); }
+  void setIsThumbFlag(bool Value) { Opcodes.setFlag(0, Value); }
+  bool getIsAndroid() const { return Opcodes.getFlag(1); }
+  void setIsAndroid(bool Value) { Opcodes.setFlag(1, Value); }
   DenseSet<const MCSymbol *> ThumbLabels;
 
   DenseMap<const MCSection *, std::unique_ptr<ElfMappingSymbolInfo>>
@@ -733,9 +737,11 @@ class ARMELFStreamer : public MCELFStreamer {
   int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp)
   int64_t SPOffset; // Offset: (final $sp) - (initial $sp)
   int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp)
-  bool UsedFP;
-  bool CantUnwind;
-  SmallVector<uint8_t, 64> Opcodes;
+  bool getUsedFP() const { return Opcodes.getFlag(2); }
+  void setUsedFP(bool Value) { Opcodes.setFlag(2, Value); }
+  bool getCantUnwind() const { return Opcodes.getFlag(3); }
+  void setCantUnwind(bool Value) { Opcodes.setFlag(3, Value); }
+  llvm::SmallVectorWithFlags<uint8_t, 64, 4> Opcodes;
   UnwindOpcodeAssembler UnwindOpAsm;
 };
 
@@ -1094,7 +1100,7 @@ void ARMTargetELFStreamer::finishAttributeSection() {
 
 void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) {
   ARMELFStreamer &Streamer = getStreamer();
-  if (!Streamer.IsThumb)
+  if (!Streamer.getIsThumbFlag())
     return;
 
   Streamer.ThumbLabels.insert(Symbol);
@@ -1226,8 +1232,8 @@ void ARMELFStreamer::EHReset() {
   FPOffset = 0;
   SPOffset = 0;
   PendingOffset = 0;
-  UsedFP = false;
-  CantUnwind = false;
+  setUsedFP(false);
+  setCantUnwind(false);
 
   Opcodes.clear();
   UnwindOpAsm.Reset();
@@ -1243,7 +1249,7 @@ void ARMELFStreamer::emitFnEnd() {
   assert(FnStart && ".fnstart must precedes .fnend");
 
   // Emit unwind opcodes if there is no .handlerdata directive
-  if (!ExTab && !CantUnwind)
+  if (!ExTab && !getCantUnwind())
     FlushUnwindOpcodes(true);
 
   // Emit the exception index table entry
@@ -1254,7 +1260,7 @@ void ARMELFStreamer::emitFnEnd() {
   // linker garbage collection. We disable this for Android where the unwinder
   // is either dynamically linked or directly references the personality
   // routine.
-  if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX && !IsAndroid)
+  if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX && !getIsAndroid())
     EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
 
   const MCSymbolRefExpr *FnStartRef =
@@ -1262,7 +1268,7 @@ void ARMELFStreamer::emitFnEnd() {
 
   emitValue(FnStartRef, 4);
 
-  if (CantUnwind) {
+  if (getCantUnwind()) {
     emitInt32(ARM::EHABI::EXIDX_CANTUNWIND);
   } else if (ExTab) {
     // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
@@ -1291,7 +1297,7 @@ void ARMELFStreamer::emitFnEnd() {
   EHReset();
 }
 
-void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; }
+void ARMELFStreamer::emitCantUnwind() { setCantUnwind(true); }
 
 // Add the R_ARM_NONE fixup at the same position
 void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
@@ -1312,7 +1318,7 @@ void ARMELFStreamer::FlushPendingOffset() {
 
 void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
   // Emit the unwind opcode to restore $sp.
-  if (UsedFP) {
+  if (getUsedFP()) {
     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
     int64_t LastRegSaveSPOffset = SPOffset - PendingOffset;
     UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset);
@@ -1322,7 +1328,10 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
   }
 
   // Finalize the unwind opcode sequence
-  UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
+  SmallVector<uint8_t, 64> UnwindOpcodes;
+  UnwindOpcodes = std::move(Opcodes);
+  UnwindOpAsm.Finalize(PersonalityIndex, UnwindOpcodes);
+  Opcodes.assign(std::move(UnwindOpcodes));
 
   // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
   // section.  Thus, we don't have to create an entry in the .ARM.extab
@@ -1385,7 +1394,7 @@ void ARMELFStreamer::emitSetFP(MCRegister NewFPReg, MCRegister NewSPReg,
   assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
          "the operand of .setfp directive should be either $sp or $fp");
 
-  UsedFP = true;
+  setUsedFP(true);
   FPReg = NewFPReg;
 
   if (NewSPReg == ARM::SP)
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
index cea173231f3bc..b7a33fa380700 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
@@ -380,7 +380,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, uint64_t Address,
                                   unsigned OpNum, const MCSubtargetInfo &STI,
                                   raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNum);
-  if (!Op.isImm() || !PrintBranchImmAsAddress || getUseMarkup())
+  if (!Op.isImm() || !getPrintBranchImmAsAddress() || getUseMarkup())
     return printOperand(MI, OpNum, STI, O);
   uint64_t Target = ARM_MC::evaluateBranchTarget(MII.get(MI->getOpcode()),
                                                  Address, Op.getImm());
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
index 1a329fd8fde36..118d0886b8a62 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.cpp
@@ -159,7 +159,7 @@ void UnwindOpcodeAssembler::Finalize(unsigned &PersonalityIndex,
                                      SmallVectorImpl<uint8_t> &Result) {
   UnwindOpcodeStreamer OpStreamer(Result);
 
-  if (HasPersonality) {
+  if (getHasPersonality()) {
     // User-specified personality routine: [ SIZE , OP1 , OP2 , ... ]
     PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX;
     size_t TotalSize = Ops.size() + 1;
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
index 9d35626f449de..688895c0a8073 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <cstddef>
 #include <cstdint>
 
@@ -26,8 +27,9 @@ class MCSymbol;
 class UnwindOpcodeAssembler {
 private:
   SmallVector<uint8_t, 32> Ops;
-  SmallVector<unsigned, 8> OpBegins;
-  bool HasPersonality = false;
+  llvm::SmallVectorWithFlags<unsigned, 8> OpBegins;
+  bool getHasPersonality() const { return OpBegins.getFlag(0); }
+  void setHasPersonality(bool Value) { OpBegins.setFlag(0, Value); }
 
 public:
   UnwindOpcodeAssembler() {
@@ -39,13 +41,11 @@ class UnwindOpcodeAssembler {
     Ops.clear();
     OpBegins.clear();
     OpBegins.push_back(0);
-    HasPersonality = false;
+    setHasPersonality(false);
   }
 
   /// Set the personality
-  void setPersonality(const MCSymbol *Per) {
-    HasPersonality = true;
-  }
+  void setPersonality(const MCSymbol *Per) { setHasPersonality(true); }
 
   /// Emit unwind opcodes for .save directives
   void EmitRegSave(uint32_t RegSave);
diff --git a/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp
index aa7e9c40db806..3cb103ba6fae4 100644
--- a/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp
+++ b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -213,14 +214,20 @@ namespace {
     /// ReduceMBB - Reduce width of instructions in the specified basic block.
     bool ReduceMBB(MachineBasicBlock &MBB, bool SkipPrologueEpilogue);
 
-    bool OptimizeSize;
-    bool MinimizeSize;
+    bool getOptimizeSize() const { return BlockInfo.getFlag(0); }
+    void setOptimizeSize(bool Value) { BlockInfo.setFlag(0, Value); }
+    bool getMinimizeSize() const { return BlockInfo.getFlag(1); }
+    bool setMinimizeSize(bool Value) {
+      BlockInfo.setFlag(1, Value);
+      return Value;
+    }
 
     // Last instruction to define CPSR in the current block.
     MachineInstr *CPSRDef;
     // Was CPSR last defined by a high latency instruction?
     // When CPSRDef is null, this refers to CPSR defs in predecessors.
-    bool HighLatencyCPSR;
+    bool getHighLatencyCPSR() const { return BlockInfo.getFlag(2); }
+    void setHighLatencyCPSR(bool Value) { BlockInfo.setFlag(2, Value); }
 
     struct MBBInfo {
       // The flags leaving this block have high latency.
@@ -231,7 +238,7 @@ namespace {
       MBBInfo() = default;
     };
 
-    SmallVector<MBBInfo, 8> BlockInfo;
+    llvm::SmallVectorWithFlags<MBBInfo, 8, 3> BlockInfo;
 
     std::function<bool(const Function &)> PredicateFtor;
   };
@@ -245,7 +252,7 @@ INITIALIZE_PASS(Thumb2SizeReduce, DEBUG_TYPE, THUMB2_SIZE_REDUCE_NAME, false,
 
 Thumb2SizeReduce::Thumb2SizeReduce(std::function<bool(const Function &)> Ftor)
     : MachineFunctionPass(ID), PredicateFtor(std::move(Ftor)) {
-  OptimizeSize = MinimizeSize = false;
+  setOptimizeSize(setMinimizeSize(false));
   for (unsigned i = 0, e = std::size(ReduceTable); i != e; ++i) {
     unsigned FromOpc = ReduceTable[i].WideOpc;
     if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second)
@@ -287,13 +294,13 @@ static bool isHighLatencyCPSR(const MachineInstr *Def) {
 bool Thumb2SizeReduce::canAddPseudoFlagDep(const MachineInstr *Use,
                                            bool FirstInSelfLoop) {
   // Disable the check for -Oz (aka OptimizeForSizeHarder).
-  if (MinimizeSize || !STI->avoidCPSRPartialUpdate())
+  if (getMinimizeSize() || !STI->avoidCPSRPartialUpdate())
     return false;
 
   if (!CPSRDef)
     // If this BB loops back to itself, conservatively avoid narrowing the
     // first instruction that does partial flag update.
-    return HighLatencyCPSR || FirstInSelfLoop;
+    return getHighLatencyCPSR() || FirstInSelfLoop;
 
   SmallSet<unsigned, 2> Defs;
   for (const MachineOperand &MO : CPSRDef->operands()) {
@@ -314,7 +321,7 @@ bool Thumb2SizeReduce::canAddPseudoFlagDep(const MachineInstr *Use,
   }
 
   // If the current CPSR has high latency, try to avoid the false dependency.
-  if (HighLatencyCPSR)
+  if (getHighLatencyCPSR())
     return true;
 
   // tMOVi8 usually doesn't start long dependency chains, and there are a lot
@@ -452,7 +459,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
     break;
   case ARM::t2LDR_POST:
   case ARM::t2STR_POST: {
-    if (!MinimizeSize)
+    if (!getMinimizeSize())
       return false;
 
     if (!MI->hasOneMemOperand() ||
@@ -747,7 +754,7 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
   if (ReduceLimit2Addr != -1 && ((int)Num2Addrs >= ReduceLimit2Addr))
     return false;
 
-  if (!OptimizeSize && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
+  if (!getOptimizeSize() && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
     // Don't issue movs with shifter operand for some CPUs unless we
     // are optimizing for size.
     return false;
@@ -757,7 +764,7 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
   // t2MUL is "special". The tied source operand is second, not first.
   if (MI->getOpcode() == ARM::t2MUL) {
     // MULS can be slower than MUL
-    if (!MinimizeSize && STI->avoidMULS())
+    if (!getMinimizeSize() && STI->avoidMULS())
       return false;
     Register Reg2 = MI->getOperand(2).getReg();
     // Early exit if the regs aren't all low regs.
@@ -865,7 +872,7 @@ Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
   if (ReduceLimit != -1 && ((int)NumNarrows >= ReduceLimit))
     return false;
 
-  if (!OptimizeSize && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
+  if (!getOptimizeSize() && Entry.AvoidMovs && STI->avoidMOVsShifterOperand())
     // Don't issue movs with shifter operand for some CPUs unless we
     // are optimizing for size.
     return false;
@@ -1031,7 +1038,7 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB,
   }
 
   CPSRDef = nullptr;
-  HighLatencyCPSR = false;
+  setHighLatencyCPSR(false);
 
   // Check predecessors for the latest CPSRDef.
   for (auto *Pred : MBB.predecessors()) {
@@ -1042,7 +1049,7 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB,
     }
 
     if (PInfo.HighLatencyCPSR) {
-      HighLatencyCPSR = true;
+      setHighLatencyCPSR(true);
       break;
     }
   }
@@ -1080,18 +1087,18 @@ bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB,
     if (MI->isCall()) {
       // Calls don't really set CPSR.
       CPSRDef = nullptr;
-      HighLatencyCPSR = false;
+      setHighLatencyCPSR(false);
       IsSelfLoop = false;
     } else if (MI->definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {
       // This is the last CPSR defining instruction.
       CPSRDef = MI;
-      HighLatencyCPSR = isHighLatencyCPSR(CPSRDef);
+      setHighLatencyCPSR(isHighLatencyCPSR(CPSRDef));
       IsSelfLoop = false;
     }
   }
 
   MBBInfo &Info = BlockInfo[MBB.getNumber()];
-  Info.HighLatencyCPSR = HighLatencyCPSR;
+  Info.HighLatencyCPSR = getHighLatencyCPSR();
   Info.Visited = true;
   return Modified;
 }
@@ -1107,8 +1114,8 @@ bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
   TII = static_cast<const Thumb2InstrInfo *>(STI->getInstrInfo());
 
   // Optimizing / minimizing size? Minimizing size implies optimizing for size.
-  OptimizeSize = MF.getFunction().hasOptSize();
-  MinimizeSize = STI->hasMinSize();
+  setOptimizeSize(MF.getFunction().hasOptSize());
+  setMinimizeSize(STI->hasMinSize());
 
   BlockInfo.clear();
   BlockInfo.resize(MF.getNumBlockIDs());
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index bb7caa275718a..10f51ab1ba54c 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -1278,10 +1278,10 @@ static_assert(std::size(RegList8Tiny) == std::size(RegList16Tiny),
 /// to handle special constraints in the ABI.
 /// In addition, all pieces of a certain argument have to be passed either
 /// using registers or the stack but never mixing both.
-template <typename ArgT>
+template <typename ArgRangeT>
 static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI,
                              const Function *F, const DataLayout *TD,
-                             const SmallVectorImpl<ArgT> &Args,
+                             const ArgRangeT &Args,
                              SmallVectorImpl<CCValAssign> &ArgLocs,
                              CCState &CCInfo, bool Tiny) {
   // Choose the proper register list for argument passing according to the ABI.
@@ -1357,12 +1357,11 @@ static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI,
 }
 
 /// Count the total number of bytes needed to pass or return these arguments.
-template <typename ArgT>
-static unsigned
-getTotalArgumentsSizeInBytes(const SmallVectorImpl<ArgT> &Args) {
+template <typename ArgRangeT>
+static unsigned getTotalArgumentsSizeInBytes(const ArgRangeT &Args) {
   unsigned TotalBytes = 0;
 
-  for (const ArgT &Arg : Args) {
+  for (const auto &Arg : Args) {
     TotalBytes += Arg.VT.getStoreSize();
   }
   return TotalBytes;
@@ -1371,9 +1370,9 @@ getTotalArgumentsSizeInBytes(const SmallVectorImpl<ArgT> &Args) {
 /// Analyze incoming and outgoing value of returning from a function.
 /// The algorithm is similar to analyzeArguments, but there can only be
 /// one value, possibly an aggregate, and it is limited to 8 bytes.
-template <typename ArgT>
-static void analyzeReturnValues(const SmallVectorImpl<ArgT> &Args,
-                                CCState &CCInfo, bool Tiny) {
+template <typename ArgRangeT>
+static void analyzeReturnValues(const ArgRangeT &Args, CCState &CCInfo,
+                                bool Tiny) {
   unsigned NumArgs = Args.size();
   unsigned TotalBytes = getTotalArgumentsSizeInBytes(Args);
   // CanLowerReturn() guarantees this assertion.
@@ -1424,8 +1423,8 @@ static void analyzeReturnValues(const SmallVectorImpl<ArgT> &Args,
 
 SDValue AVRTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   auto DL = DAG.getDataLayout();
@@ -1526,19 +1525,18 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                      SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &isTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool isVarArg = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
 
   MachineFunction &MF = DAG.getMachineFunction();
 
   // AVR does not yet support tail call optimization.
-  isTailCall = false;
+  CLI.setIsTailCall(false);
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -1702,8 +1700,8 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 ///
 SDValue AVRTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
@@ -1733,10 +1731,11 @@ SDValue AVRTargetLowering::LowerCallResult(
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool AVRTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool AVRTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   if (CallConv == CallingConv::AVR_BUILTIN) {
     SmallVector<CCValAssign, 16> RVLocs;
     CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
@@ -1747,12 +1746,12 @@ bool AVRTargetLowering::CanLowerReturn(
   return TotalBytes <= (unsigned)(Subtarget.hasTinyEncoding() ? 4 : 8);
 }
 
-SDValue
-AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &dl, SelectionDAG &DAG) const {
+SDValue AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &dl,
+                                       SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to locations.
   SmallVector<CCValAssign, 16> RVLocs;
 
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index 4ad386db00183..affd1c1aac187 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -112,25 +112,23 @@ class AVRTargetLowering : public TargetLowering {
   SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
                       SelectionDAG &DAG) const override;
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &dl, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool isVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &dl, SelectionDAG &DAG,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                          SelectionDAG &DAG,
                           SmallVectorImpl<SDValue> &InVals) const;
 
 protected:
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 435f0e15a25c5..c523e7525c61c 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -407,8 +407,8 @@ static SDValue convertLocValType(SelectionDAG &DAG, const SDLoc &DL,
 
 SDValue BPFTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   switch (CallConv) {
   default:
     report_fatal_error("unimplemented calling convention: " + Twine(CallConv));
@@ -502,13 +502,12 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   MachineFunction &MF = DAG.getMachineFunction();
 
   // BPF target does not support tail call optimization.
-  IsTailCall = false;
+  CLI.setIsTailCall(false);
 
   switch (CallConv) {
   default:
@@ -649,7 +648,7 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   Chain = DAG.getNode(BPFISD::CALL, CLI.DL, NodeTys, Ops);
   InGlue = Chain.getValue(1);
 
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
 
   // Create the CALLSEQ_END node.
   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, CLI.DL);
@@ -661,12 +660,12 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                          InVals);
 }
 
-SDValue
-BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool IsVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &DL,
+                                       SelectionDAG &DAG) const {
   unsigned Opc = BPFISD::RET_GLUE;
 
   // CCValAssign - represent the assignment of the return value to a location
@@ -707,8 +706,8 @@ BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 
 SDValue BPFTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   MachineFunction &MF = DAG.getMachineFunction();
   // Assign locations to each value returned by this call.
@@ -860,12 +859,12 @@ SDValue BPFTargetLowering::LowerTRAP(SDValue Op, SelectionDAG &DAG) const {
   auto PtrVT = getPointerTy(MF.getDataLayout());
   CLI.Callee = DAG.getTargetGlobalAddress(Fn, DL, PtrVT);
   CLI.Chain = N->getOperand(0);
-  CLI.IsTailCall = false;
+  CLI.setIsTailCall(false);
   CLI.CallConv = CallingConv::C;
-  CLI.IsVarArg = false;
+  CLI.setIsVarArg(false);
   CLI.DL = std::move(DL);
-  CLI.NoMerge = false;
-  CLI.DoesNotReturn = true;
+  CLI.setNoMerge(false);
+  CLI.setDoesNotReturn(true);
   return LowerCall(CLI, InVals);
 }
 
@@ -1248,10 +1247,11 @@ bool BPFTargetLowering::isLegalAddressingMode(const DataLayout &DL,
   return true;
 }
 
-bool BPFTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool BPFTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool IsVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, getHasAlu32() ? RetCC_BPF32 : RetCC_BPF64);
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8c00c8caa5bcd..fe39d39f36382 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -97,8 +97,8 @@ class BPFTargetLowering : public TargetLowering {
   // Lower the result values of a call, copying them out of physregs into vregs
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool IsVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &DL, SelectionDAG &DAG,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL,
+                          SelectionDAG &DAG,
                           SmallVectorImpl<SDValue> &InVals) const;
 
   // Lower a call into CALLSEQ_START - BPFISD:CALL - CALLSEQ_END chain
@@ -107,13 +107,12 @@ class BPFTargetLowering : public TargetLowering {
 
   // Lower incoming arguments, copy physregs into vregs
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
@@ -169,8 +168,7 @@ class BPFTargetLowering : public TargetLowering {
                                      MachineBasicBlock *BB) const;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 };
 }
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index 7ddeedb838e87..57ccfb11a1f92 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -618,8 +618,9 @@ BTFTypeFuncProto::BTFTypeFuncProto(
     bool UseFilteredParams, ArrayRef<uint32_t> AliveParamIndices,
     bool VoidReturn)
     : STy(STy), FuncArgNames(FuncArgNames),
-      AliveParamIndices(AliveParamIndices),
-      UseFilteredParams(UseFilteredParams), VoidReturn(VoidReturn) {
+      AliveParamIndices(decltype(this->AliveParamIndices)::withFlags(
+          unsigned(UseFilteredParams) | (unsigned(VoidReturn) << 1),
+          AliveParamIndices)) {
   Kind = BTF::BTF_KIND_FUNC_PROTO;
   BTFType.Info = (Kind << 24) | VLen;
 }
@@ -630,7 +631,7 @@ void BTFTypeFuncProto::completeType(BTFDebug &BDebug) {
   IsCompleted = true;
 
   DITypeArray Elements = STy->getTypeArray();
-  if (VoidReturn) {
+  if (getVoidReturn()) {
     BTFType.Type = 0;
   } else {
     auto RetType = tryRemoveAtomicType(Elements[0]);
@@ -653,7 +654,7 @@ void BTFTypeFuncProto::completeType(BTFDebug &BDebug) {
     Parameters.push_back(Param);
   };
 
-  if (UseFilteredParams) {
+  if (getUseFilteredParams()) {
     for (uint32_t I : AliveParamIndices)
       EmitParam(I);
     return;
diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h
index b29a0cb88624d..2d67e92279271 100644
--- a/llvm/lib/Target/BPF/BTFDebug.h
+++ b/llvm/lib/Target/BPF/BTFDebug.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/CodeGen/DebugHandlerBase.h"
 #include "llvm/DebugInfo/BTF/BTF.h"
@@ -145,10 +146,12 @@ class BTFTypeStruct : public BTFTypeBase {
 class BTFTypeFuncProto : public BTFTypeBase {
   const DISubroutineType *STy;
   SmallDenseMap<uint32_t, StringRef> FuncArgNames;
-  SmallVector<uint32_t, 8> AliveParamIndices;
-  bool UseFilteredParams = false;
+  llvm::SmallVectorWithFlags<uint32_t, 8, 2> AliveParamIndices;
+  bool getUseFilteredParams() const { return AliveParamIndices.getFlag(0); }
+  void setUseFilteredParams(bool Value) { AliveParamIndices.setFlag(0, Value); }
   std::vector<struct BTF::BTFParam> Parameters;
-  bool VoidReturn = false;
+  bool getVoidReturn() const { return AliveParamIndices.getFlag(1); }
+  void setVoidReturn(bool Value) { AliveParamIndices.setFlag(1, Value); }
 
 public:
   BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
diff --git a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
index 8b0bb2e28ad19..24bea13088c5e 100644
--- a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
+++ b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
@@ -327,8 +327,8 @@ static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA,
 // Transform physical registers into virtual registers.
 SDValue CSKYTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   switch (CallConv) {
   default:
@@ -425,21 +425,22 @@ SDValue CSKYTargetLowering::LowerFormalArguments(
   return Chain;
 }
 
-bool CSKYTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool CSKYTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                        MachineFunction &MF, bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        LLVMContext &Context,
+                                        const Type *RetTy) const {
   SmallVector<CCValAssign, 16> CSKYLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);
   return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
 }
 
-SDValue
-CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                                bool IsVarArg,
-                                const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                const SmallVectorImpl<SDValue> &OutVals,
-                                const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                        bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        const SmallVectorImpl<SDValue> &OutVals,
+                                        const SDLoc &DL,
+                                        SelectionDAG &DAG) const {
   // Stores the assignment of the return value to a location.
   SmallVector<CCValAssign, 16> CSKYLocs;
 
@@ -508,14 +509,13 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                       SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   MVT XLenVT = MVT::i32;
 
@@ -528,10 +528,10 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
   ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg));
 
   // Check if it's really possible to do a tail call.
-  if (IsTailCall)
-    IsTailCall = false; // TODO: TailCallOptimization;
+  if (CLI.getIsTailCall())
+    CLI.setIsTailCall(false); // TODO: TailCallOptimization;
 
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     ++NumTailCalls;
   else if (CLI.CB && CLI.CB->isMustTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
@@ -558,12 +558,13 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
     Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
                           /*IsVolatile=*/false,
-                          /*AlwaysInline=*/false, /*CI=*/nullptr, IsTailCall,
-                          MachinePointerInfo(), MachinePointerInfo());
+                          /*AlwaysInline=*/false, /*CI=*/nullptr,
+                          CLI.getIsTailCall(), MachinePointerInfo(),
+                          MachinePointerInfo());
     ByValArgs.push_back(FIPtr);
   }
 
-  if (!IsTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
 
   // Copy argument values to their designated locations.
@@ -615,8 +616,8 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
     } else {
       assert(VA.isMemLoc() && "Argument not register or memory");
-      assert(!IsTailCall && "Tail call not allowed if stack is used "
-                            "for passing parameters");
+      assert(!CLI.getIsTailCall() && "Tail call not allowed if stack is used "
+                                     "for passing parameters");
 
       // Work out the address of the stack slot.
       if (!StackPtr.getNode())
@@ -684,7 +685,7 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
   for (auto &Reg : RegsToPass)
     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
 
-  if (!IsTailCall) {
+  if (!CLI.getIsTailCall()) {
     // Add a register mask operand representing the call-preserved registers.
     const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
     const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
@@ -699,7 +700,7 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // Emit the call.
   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL,
                        NodeTys, Ops);
@@ -707,7 +708,7 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys,
                       Ops);
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   Glue = Chain.getValue(1);
 
   // Mark the end of the call, which is glued to the call itself.
diff --git a/llvm/lib/Target/CSKY/CSKYISelLowering.h b/llvm/lib/Target/CSKY/CSKYISelLowering.h
index ecd2ad96ae179..7f6922f5a5a71 100644
--- a/llvm/lib/Target/CSKY/CSKYISelLowering.h
+++ b/llvm/lib/Target/CSKY/CSKYISelLowering.h
@@ -36,18 +36,16 @@ class CSKYTargetLowering : public TargetLowering {
 
 private:
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
index 90428e34cefa3..74627fe902679 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp
@@ -83,7 +83,7 @@ void CSKYInstPrinter::printInst(const MCInst *MI, uint64_t Address,
 }
 
 void CSKYInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) {
-  if (PrintBranchImmAsAddress)
+  if (getPrintBranchImmAsAddress())
     O << getRegisterName(Reg, ABIRegNames ? CSKY::ABIRegAltName
                                           : CSKY::NoRegAltName);
   else
@@ -91,7 +91,7 @@ void CSKYInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) {
 }
 
 void CSKYInstPrinter::printFPRRegName(raw_ostream &O, unsigned RegNo) const {
-  if (PrintBranchImmAsAddress)
+  if (getPrintBranchImmAsAddress())
     O << getRegisterName(RegNo, CSKY::NoRegAltName);
   else
     O << getRegisterName(RegNo);
@@ -104,7 +104,7 @@ void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
   if (MO.isReg()) {
     unsigned Reg = MO.getReg();
     bool useABIName = false;
-    if (PrintBranchImmAsAddress)
+    if (getPrintBranchImmAsAddress())
       useABIName = ABIRegNames;
     else
       useABIName = !ArchRegNames;
@@ -130,7 +130,7 @@ void CSKYInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
     uint64_t TSFlags = MII.get(MI->getOpcode()).TSFlags;
 
     if (((TSFlags & CSKYII::AddrModeMask) != CSKYII::AddrModeNone) &&
-        PrintBranchImmAsAddress)
+        getPrintBranchImmAsAddress())
       O << formatHex(MO.getImm());
     else
       O << MO.getImm();
@@ -160,7 +160,7 @@ void CSKYInstPrinter::printConstpool(const MCInst *MI, uint64_t Address,
   const MCOperand &MO = MI->getOperand(OpNo);
 
   if (MO.isImm()) {
-    if (PrintBranchImmAsAddress) {
+    if (getPrintBranchImmAsAddress()) {
       uint64_t Target = Address + MO.getImm();
       Target &= 0xfffffffc;
       O << formatHex(Target);
@@ -186,7 +186,7 @@ void CSKYInstPrinter::printCSKYSymbolOperand(const MCInst *MI, uint64_t Address,
     return printOperand(MI, OpNo, STI, O);
   }
 
-  if (PrintBranchImmAsAddress) {
+  if (getPrintBranchImmAsAddress()) {
     uint64_t Target = Address + MO.getImm();
     Target &= 0xffffffff;
     O << formatHex(Target);
diff --git a/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp b/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp
index 1dabcf32fa8e8..8193ea2563550 100644
--- a/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp
@@ -15,6 +15,7 @@
 #include "HexagonSubtarget.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -54,10 +55,13 @@ class HexagonCopyToCombine : public MachineFunctionPass  {
   const HexagonInstrInfo *TII;
   const TargetRegisterInfo *TRI;
   const HexagonSubtarget *ST;
-  bool ShouldCombineAggressively;
+  bool getShouldCombineAggressively() const { return DbgMItoMove.getFlag(0); }
+  void setShouldCombineAggressively(bool Value) {
+    DbgMItoMove.setFlag(0, Value);
+  }
 
   DenseSet<MachineInstr *> PotentiallyNewifiableTFR;
-  SmallVector<MachineInstr *, 8> DbgMItoMove;
+  llvm::SmallVectorWithFlags<MachineInstr *, 8> DbgMItoMove;
 
 public:
   static char ID;
@@ -270,7 +274,7 @@ bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
     MachineBasicBlock::reverse_iterator I = ++I2.getIterator().getReverse();
     MachineBasicBlock::reverse_iterator End = I1.getIterator().getReverse();
     // At 03 we got better results (dhrystone!) by being more conservative.
-    if (!ShouldCombineAggressively)
+    if (!getShouldCombineAggressively())
       End = ++I1.getIterator().getReverse();
     // If I2 kills its operand and we move I2 over an instruction that also
     // uses I2's use reg we need to modify that (first) instruction to now kill
@@ -318,7 +322,7 @@ bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
     // Look at instructions I in between I1 and (excluding) I2.
     MachineBasicBlock::iterator I(I1), End(I2);
     // At O3 we got better results (dhrystone) by being more conservative here.
-    if (!ShouldCombineAggressively)
+    if (!getShouldCombineAggressively())
       End = std::next(MachineBasicBlock::iterator(I2));
     Register I1UseReg = UseReg(I1.getOperand(1));
     // Track killed operands. If we move across an instruction that kills our
@@ -400,7 +404,8 @@ HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
         MachineInstr *DefInst = LastDef[Reg];
         if (!DefInst)
           continue;
-        if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
+        if (!isCombinableInstType(*DefInst, TII,
+                                  getShouldCombineAggressively()))
           continue;
 
         // Only close newifiable stores should influence the decision.
@@ -460,8 +465,8 @@ bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
   bool OptForSize = F.hasOptSize();
 
   // Combine aggressively (for code size)
-  ShouldCombineAggressively =
-      MF.getTarget().getOptLevel() <= CodeGenOptLevel::Default;
+  setShouldCombineAggressively(MF.getTarget().getOptLevel() <=
+                               CodeGenOptLevel::Default);
 
   // Disable CONST64 for tiny core since it takes a LD resource.
   if (!OptForSize && ST->isTinyCore())
@@ -483,11 +488,11 @@ bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
       // Don't combine a TFR whose user could be newified (instructions that
       // define double registers can not be newified - Programmer's Ref Manual
       // 5.4.2 New-value stores).
-      if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1))
+      if (getShouldCombineAggressively() && PotentiallyNewifiableTFR.count(&I1))
         continue;
 
       // Ignore instructions that are not combinable.
-      if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
+      if (!isCombinableInstType(I1, TII, getShouldCombineAggressively()))
         continue;
 
       // Find a second instruction that can be merged into a combine
@@ -526,11 +531,11 @@ MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,
       break;
 
     // Ignore non-combinable instructions.
-    if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
+    if (!isCombinableInstType(*I2, TII, getShouldCombineAggressively()))
       continue;
 
     // Don't combine a TFR whose user could be newified.
-    if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2))
+    if (getShouldCombineAggressively() && PotentiallyNewifiableTFR.count(&*I2))
       continue;
 
     Register I2DestReg = I2->getOperand(0).getReg();
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 199edef3d05ce..24cb03fddd973 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -15,6 +15,7 @@
 #include "HexagonISelLowering.h"
 #include "HexagonMachineFunctionInfo.h"
 #include "HexagonTargetMachine.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
@@ -1822,33 +1823,28 @@ struct WeightedLeaf {
 /// constants and allows removal of non-top elements while maintaining the
 /// priority order.
 class LeafPrioQueue {
-  SmallVector<WeightedLeaf, 8> Q;
-  bool HaveConst;
+  llvm::SmallVectorWithFlags<WeightedLeaf, 8> Q;
+  bool getHaveConst() const { return Q.getFlag(0); }
+  void setHaveConst(bool Value) { Q.setFlag(0, Value); }
   WeightedLeaf ConstElt;
   unsigned Opcode;
 
 public:
-  bool empty() {
-    return (!HaveConst && Q.empty());
-  }
+  bool empty() { return (!getHaveConst() && Q.empty()); }
 
-  size_t size() {
-    return Q.size() + HaveConst;
-  }
+  size_t size() { return Q.size() + getHaveConst(); }
 
-  bool hasConst() {
-    return HaveConst;
-  }
+  bool hasConst() { return getHaveConst(); }
 
   const WeightedLeaf &top() {
-    if (HaveConst)
+    if (getHaveConst())
       return ConstElt;
     return Q.front();
   }
 
   WeightedLeaf pop() {
-    if (HaveConst) {
-      HaveConst = false;
+    if (getHaveConst()) {
+      setHaveConst(false);
       return ConstElt;
     }
     std::pop_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
@@ -1856,7 +1852,7 @@ class LeafPrioQueue {
   }
 
   void push(WeightedLeaf L, bool SeparateConst=true) {
-    if (!HaveConst && SeparateConst && isa<ConstantSDNode>(L.Value)) {
+    if (!getHaveConst() && SeparateConst && isa<ConstantSDNode>(L.Value)) {
       if (Opcode == ISD::MUL &&
           cast<ConstantSDNode>(L.Value)->getSExtValue() == 1)
         return;
@@ -1864,7 +1860,7 @@ class LeafPrioQueue {
           cast<ConstantSDNode>(L.Value)->getSExtValue() == 0)
         return;
 
-      HaveConst = true;
+      setHaveConst(true);
       ConstElt = L;
     } else {
       Q.push_back(L);
@@ -1885,8 +1881,7 @@ class LeafPrioQueue {
 
   WeightedLeaf findMULbyConst();
 
-  LeafPrioQueue(unsigned Opcode) :
-    HaveConst(false), Opcode(Opcode) { }
+  LeafPrioQueue(unsigned Opcode) : Opcode(Opcode) {}
 };
 } // end anonymous namespace
 
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index b6e16893bc134..cb5580a016b2e 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -223,11 +223,11 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst,
                        MachinePointerInfo());
 }
 
-bool
-HexagonTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    LLVMContext &Context, const Type *RetTy) const {
+bool HexagonTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                           MachineFunction &MF, bool IsVarArg,
+                                           llvm::ArrayRef<ISD::OutputArg> Outs,
+                                           LLVMContext &Context,
+                                           const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
 
@@ -242,7 +242,7 @@ HexagonTargetLowering::CanLowerReturn(
 SDValue
 HexagonTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                    bool IsVarArg,
-                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                   llvm::ArrayRef<ISD::OutputArg> Outs,
                                    const SmallVectorImpl<SDValue> &OutVals,
                                    const SDLoc &dl, SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to locations.
@@ -387,9 +387,9 @@ Register HexagonTargetLowering::getRegisterByName(
 /// ISD::CALL.
 SDValue HexagonTargetLowering::LowerCallResult(
     SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
-    const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals, const SmallVectorImpl<SDValue> &OutVals,
+    SDValue Callee) const {
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
 
@@ -443,14 +443,14 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                  SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
   SDValue Callee                        = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool IsVarArg                         = CLI.IsVarArg;
-  bool DoesNotReturn                    = CLI.DoesNotReturn;
+  bool IsVarArg = CLI.getIsVarArg();
+  bool DoesNotReturn = CLI.getDoesNotReturn();
 
   bool IsStructRet    = Outs.empty() ? false : Outs[0].Flags.isSRet();
   MachineFunction &MF = DAG.getMachineFunction();
@@ -474,20 +474,21 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   else
     CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
 
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     bool StructAttrFlag = MF.getFunction().hasStructRetAttr();
-    CLI.IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
-                        IsVarArg, IsStructRet, StructAttrFlag, Outs,
-                        OutVals, Ins, DAG);
+    CLI.setIsTailCall(IsEligibleForTailCallOptimization(
+        Callee, CallConv, IsVarArg, IsStructRet, StructAttrFlag, Outs, OutVals,
+        Ins, DAG));
     for (const CCValAssign &VA : ArgLocs) {
       if (VA.isMemLoc()) {
-        CLI.IsTailCall = false;
+        CLI.setIsTailCall(false);
         break;
       }
     }
-    LLVM_DEBUG(dbgs() << (CLI.IsTailCall ? "Eligible for Tail Call\n"
-                                         : "Argument must be passed on stack. "
-                                           "Not eligible for Tail Call\n"));
+    LLVM_DEBUG(dbgs() << (CLI.getIsTailCall()
+                              ? "Eligible for Tail Call\n"
+                              : "Argument must be passed on stack. "
+                                "Not eligible for Tail Call\n"));
   }
   // Get a count of how many bytes are to be pushed on the stack.
   unsigned NumBytes = CCInfo.getStackSize();
@@ -570,7 +571,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
 
   SDValue Glue;
-  if (!CLI.IsTailCall) {
+  if (!CLI.getIsTailCall()) {
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
     Glue = Chain.getValue(1);
   }
@@ -579,7 +580,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // chain and flag operands which copy the outgoing args into registers.
   // The Glue is necessary since all emitted instructions must be
   // stuck together.
-  if (!CLI.IsTailCall) {
+  if (!CLI.getIsTailCall()) {
     for (const auto &R : RegsToPass) {
       Chain = DAG.getCopyToReg(Chain, dl, R.first, R.second, Glue);
       Glue = Chain.getValue(1);
@@ -633,7 +634,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   if (Glue.getNode())
     Ops.push_back(Glue);
 
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MFI.setHasTailCall();
     return DAG.getNode(HexagonISD::TC_RETURN, dl, MVT::Other, Ops);
   }
@@ -844,8 +845,8 @@ SDValue HexagonTargetLowering::LowerFMINFMAX(SDValue Op,
 
 SDValue HexagonTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MachineRegisterInfo &MRI = MF.getRegInfo();
@@ -3786,15 +3787,11 @@ bool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
 /// for tail call optimization. Targets which want to do tail call
 /// optimization should implement this function.
 bool HexagonTargetLowering::IsEligibleForTailCallOptimization(
-                                 SDValue Callee,
-                                 CallingConv::ID CalleeCC,
-                                 bool IsVarArg,
-                                 bool IsCalleeStructRet,
-                                 bool IsCallerStructRet,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                 const SmallVectorImpl<SDValue> &OutVals,
-                                 const SmallVectorImpl<ISD::InputArg> &Ins,
-                                 SelectionDAG& DAG) const {
+    SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
+    bool IsCalleeStructRet, bool IsCallerStructRet,
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    SelectionDAG &DAG) const {
   const Function &CallerF = DAG.getMachineFunction().getFunction();
   CallingConv::ID CallerCC = CallerF.getCallingConv();
   bool CCMatch = CallerCC == CalleeCC;
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 7754027f50258..09a62981ffa43 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -43,11 +43,12 @@ class HexagonTargetLowering : public TargetLowering {
   /// IsEligibleForTailCallOptimization - Check whether the call is eligible
   /// for tail call optimization. Targets which want to do tail call
   /// optimization should implement this function.
-  bool IsEligibleForTailCallOptimization(SDValue Callee,
-      CallingConv::ID CalleeCC, bool isVarArg, bool isCalleeStructRet,
-      bool isCallerStructRet, const SmallVectorImpl<ISD::OutputArg> &Outs,
+  bool IsEligibleForTailCallOptimization(
+      SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg,
+      bool isCalleeStructRet, bool isCallerStructRet,
+      llvm::ArrayRef<ISD::OutputArg> Outs,
       const SmallVectorImpl<SDValue> &OutVals,
-      const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG& DAG) const;
+      llvm::ArrayRef<ISD::InputArg> Ins, SelectionDAG &DAG) const;
 
   void getTgtMemIntrinsic(SmallVectorImpl<IntrinsicInfo> &Infos,
                           const CallBase &I, MachineFunction &MF,
@@ -119,11 +120,10 @@ class HexagonTargetLowering : public TargetLowering {
   SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
-  SDValue
-  LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                       const SmallVectorImpl<ISD::InputArg> &Ins,
-                       const SDLoc &dl, SelectionDAG &DAG,
-                       SmallVectorImpl<SDValue> &InVals) const override;
+  SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
+                               const SDLoc &dl, SelectionDAG &DAG,
+                               SmallVectorImpl<SDValue> &InVals) const override;
   SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
@@ -142,9 +142,8 @@ class HexagonTargetLowering : public TargetLowering {
       SmallVectorImpl<SDValue> &InVals) const override;
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool isVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &dl, SelectionDAG &DAG,
-                          SmallVectorImpl<SDValue> &InVals,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                          SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
                           const SmallVectorImpl<SDValue> &OutVals,
                           SDValue Callee) const;
 
@@ -154,15 +153,14 @@ class HexagonTargetLowering : public TargetLowering {
   SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
   SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
 
-  bool CanLowerReturn(CallingConv::ID CallConv,
-                      MachineFunction &MF, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+  bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
-                      const SmallVectorImpl<SDValue> &OutVals,
-                      const SDLoc &dl, SelectionDAG &DAG) const override;
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
+                      const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
+                      SelectionDAG &DAG) const override;
 
   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
 
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
index 5831bd8685f72..dbf9a749aca3d 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
@@ -383,8 +383,8 @@ static bool CC_Lanai32_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT,
 
 SDValue LanaiTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   switch (CallConv) {
   case CallingConv::C:
   case CallingConv::Fast:
@@ -398,23 +398,23 @@ SDValue LanaiTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                        SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
 
   // Lanai target does not yet support tail call optimization.
-  IsTailCall = false;
+  CLI.setIsTailCall(false);
 
   switch (CallConv) {
   case CallingConv::Fast:
   case CallingConv::C:
-    return LowerCCCCallTo(Chain, Callee, CallConv, IsVarArg, IsTailCall, Outs,
-                          OutVals, Ins, DL, DAG, InVals);
+    return LowerCCCCallTo(Chain, Callee, CallConv, IsVarArg,
+                          CLI.getIsTailCall(), Outs, OutVals, Ins, DL, DAG,
+                          InVals);
   default:
     report_fatal_error("Unsupported calling convention");
   }
@@ -424,8 +424,8 @@ SDValue LanaiTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 // generate load operations for arguments places on the stack.
 SDValue LanaiTargetLowering::LowerCCCArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
@@ -517,10 +517,11 @@ SDValue LanaiTargetLowering::LowerCCCArguments(
   return Chain;
 }
 
-bool LanaiTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool LanaiTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                         MachineFunction &MF, bool IsVarArg,
+                                         llvm::ArrayRef<ISD::OutputArg> Outs,
+                                         LLVMContext &Context,
+                                         const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
 
@@ -530,7 +531,7 @@ bool LanaiTargetLowering::CanLowerReturn(
 SDValue
 LanaiTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                  bool IsVarArg,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                 llvm::ArrayRef<ISD::OutputArg> Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SDLoc &DL, SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to a location
@@ -592,10 +593,10 @@ LanaiTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 // (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
 SDValue LanaiTargetLowering::LowerCCCCallTo(
     SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool IsVarArg,
-    bool /*IsTailCall*/, const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    bool /*IsTailCall*/, llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
@@ -758,8 +759,8 @@ SDValue LanaiTargetLowering::LowerCCCCallTo(
 // appropriate copies out of appropriate physical registers.
 SDValue LanaiTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.h b/llvm/lib/Target/Lanai/LanaiISelLowering.h
index b0d5644c1c4a1..906569cfaed72 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.h
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.h
@@ -46,8 +46,7 @@ class LanaiTargetLowering : public TargetLowering {
   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   Register getRegisterByName(const char *RegName, LLT VT,
@@ -72,36 +71,33 @@ class LanaiTargetLowering : public TargetLowering {
 private:
   SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
                          CallingConv::ID CallConv, bool IsVarArg,
-                         bool IsTailCall,
-                         const SmallVectorImpl<ISD::OutputArg> &Outs,
+                         bool IsTailCall, llvm::ArrayRef<ISD::OutputArg> Outs,
                          const SmallVectorImpl<SDValue> &OutVals,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const;
 
   SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv,
-                            bool IsVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
+                            bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                             const SDLoc &DL, SelectionDAG &DAG,
                             SmallVectorImpl<SDValue> &InVals) const;
 
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool IsVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &DL, SelectionDAG &DAG,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL,
+                          SelectionDAG &DAG,
                           SmallVectorImpl<SDValue> &InVals) const;
 
   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 1d01e76a5ebd2..2f6cb55d2efd8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -9965,9 +9965,8 @@ static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI,
 }
 
 void LoongArchTargetLowering::analyzeInputArgs(
-    MachineFunction &MF, CCState &CCInfo,
-    const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
-    LoongArchCCAssignFn Fn) const {
+    MachineFunction &MF, CCState &CCInfo, llvm::ArrayRef<ISD::InputArg> Ins,
+    bool IsRet, LoongArchCCAssignFn Fn) const {
   FunctionType *FType = MF.getFunction().getFunctionType();
   for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
     MVT ArgVT = Ins[i].VT;
@@ -9988,9 +9987,8 @@ void LoongArchTargetLowering::analyzeInputArgs(
 }
 
 void LoongArchTargetLowering::analyzeOutputArgs(
-    MachineFunction &MF, CCState &CCInfo,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, bool IsRet,
-    CallLoweringInfo *CLI, LoongArchCCAssignFn Fn) const {
+    MachineFunction &MF, CCState &CCInfo, llvm::ArrayRef<ISD::OutputArg> Outs,
+    bool IsRet, CallLoweringInfo *CLI, LoongArchCCAssignFn Fn) const {
   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
     MVT ArgVT = Outs[i].VT;
     Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty : nullptr;
@@ -10180,8 +10178,8 @@ static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
 // Transform physical registers into virtual registers.
 SDValue LoongArchTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   MachineFunction &MF = DAG.getMachineFunction();
 
@@ -10444,16 +10442,15 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                    SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   MVT GRLenVT = Subtarget.getGRLenVT();
-  bool &IsTailCall = CLI.IsTailCall;
 
   MachineFunction &MF = DAG.getMachineFunction();
 
@@ -10467,10 +10464,11 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
     analyzeOutputArgs(MF, ArgCCInfo, Outs, /*IsRet=*/false, &CLI, CC_LoongArch);
 
   // Check if it's really possible to do a tail call.
-  if (IsTailCall)
-    IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
+  if (CLI.getIsTailCall())
+    CLI.setIsTailCall(
+        isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs));
 
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     ++NumTailCalls;
   else if (CLI.CB && CLI.CB->isMustTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
@@ -10502,7 +10500,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
     ByValArgs.push_back(FIPtr);
   }
 
-  if (!IsTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
 
   // Copy argument values to their designated locations.
@@ -10556,7 +10554,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
       // For musttail calls, reuse incoming indirect pointers instead of
       // creating new stack temporaries. The incoming pointers point to the
       // caller's caller's frame, which remains valid after a tail call.
-      if (IsTailCall && CLI.CB && CLI.CB->isMustTailCall()) {
+      if (CLI.getIsTailCall() && CLI.CB && CLI.CB->isMustTailCall()) {
         LoongArchMachineFunctionInfo *LAFI =
             MF.getInfo<LoongArchMachineFunctionInfo>();
         unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
@@ -10709,7 +10707,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
     } else {
       assert(VA.isMemLoc() && "Argument not register or memory");
-      assert((!IsTailCall || (CLI.CB && CLI.CB->isMustTailCall())) &&
+      assert((!CLI.getIsTailCall() || (CLI.CB && CLI.CB->isMustTailCall())) &&
              "Tail call not allowed if stack is used for passing parameters");
 
       // Work out the address of the stack slot.
@@ -10763,7 +10761,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
   for (auto &Reg : RegsToPass)
     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
 
-  if (!IsTailCall) {
+  if (!CLI.getIsTailCall()) {
     // Add a register mask operand representing the call-preserved registers.
     const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
     const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
@@ -10782,26 +10780,28 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
   default:
     report_fatal_error("Unsupported code model");
   case CodeModel::Small:
-    Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
+    Op = CLI.getIsTailCall() ? LoongArchISD::TAIL : LoongArchISD::CALL;
     break;
   case CodeModel::Medium:
-    Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
+    Op = CLI.getIsTailCall() ? LoongArchISD::TAIL_MEDIUM
+                             : LoongArchISD::CALL_MEDIUM;
     break;
   case CodeModel::Large:
     assert(Subtarget.is64Bit() && "Large code model requires LA64");
-    Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
+    Op = CLI.getIsTailCall() ? LoongArchISD::TAIL_LARGE
+                             : LoongArchISD::CALL_LARGE;
     break;
   }
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     SDValue Ret = DAG.getNode(Op, DL, NodeTys, Ops);
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     return Ret;
   }
 
   Chain = DAG.getNode(Op, DL, NodeTys, Ops);
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   Glue = Chain.getValue(1);
 
   // Mark the end of the call, which is glued to the call itself.
@@ -10842,7 +10842,7 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
 bool LoongArchTargetLowering::CanLowerReturn(
     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
+    llvm::ArrayRef<ISD::OutputArg> Outs, LLVMContext &Context,
     const Type *RetTy) const {
   SmallVector<CCValAssign> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
@@ -10857,11 +10857,12 @@ bool LoongArchTargetLowering::CanLowerReturn(
   return true;
 }
 
-SDValue LoongArchTargetLowering::LowerReturn(
-    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
-    SelectionDAG &DAG) const {
+SDValue
+LoongArchTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                     bool IsVarArg,
+                                     llvm::ArrayRef<ISD::OutputArg> Outs,
+                                     const SmallVectorImpl<SDValue> &OutVals,
+                                     const SDLoc &DL, SelectionDAG &DAG) const {
   // Stores the assignment of the return value to a location.
   SmallVector<CCValAssign> RVLocs;
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 7c3ae7d6aac14..3805c18ff29cb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -42,16 +42,14 @@ class LoongArchTargetLowering : public TargetLowering {
 
   // Lower incoming arguments, copy physregs into vregs.
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
@@ -198,12 +196,11 @@ class LoongArchTargetLowering : public TargetLowering {
                                    bool IsRet, Type *OrigTy);
 
   void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo,
-                        const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,
+                        llvm::ArrayRef<ISD::InputArg> Ins, bool IsRet,
                         LoongArchCCAssignFn Fn) const;
   void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo,
-                         const SmallVectorImpl<ISD::OutputArg> &Outs,
-                         bool IsRet, CallLoweringInfo *CLI,
-                         LoongArchCCAssignFn Fn) const;
+                         llvm::ArrayRef<ISD::OutputArg> Outs, bool IsRet,
+                         CallLoweringInfo *CLI, LoongArchCCAssignFn Fn) const;
 
   template <class NodeTy>
   SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
index a3f5759fb87d2..f6b4e2d7f5d2b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
@@ -15,6 +15,7 @@
 
 #include "LoongArchSubtarget.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 
@@ -49,9 +50,10 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
 
   /// Pairs of `jr` instructions and corresponding JTI operands, used for the
   /// `annotate-tablejump` option.
-  SmallVector<std::pair<MachineInstr *, int>, 4> JumpInfos;
+  llvm::SmallVectorWithFlags<std::pair<MachineInstr *, int>, 4> JumpInfos;
 
-  bool HasDynamicAllocation = false;
+  bool getHasDynamicAllocation() const { return JumpInfos.getFlag(0); }
+  void setHasDynamicAllocation(bool Value) { JumpInfos.setFlag(0, Value); }
 
 public:
   LoongArchMachineFunctionInfo(const Function &F,
@@ -102,8 +104,8 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
   MachineInstr *getJumpInfoJrMI(unsigned Idx) { return JumpInfos[Idx].first; }
   int getJumpInfoJTIIndex(unsigned Idx) { return JumpInfos[Idx].second; }
 
-  bool hasDynamicAllocation() const { return HasDynamicAllocation; }
-  void setDynamicAllocation() { HasDynamicAllocation = true; }
+  bool hasDynamicAllocation() const { return getHasDynamicAllocation(); }
+  void setDynamicAllocation() { setHasDynamicAllocation(true); }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp
index 8587e16c1cde7..c6247b1376102 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp
@@ -110,7 +110,7 @@ void LoongArchInstPrinter::printBranchOperand(const MCInst *MI,
                                               const MCSubtargetInfo &STI,
                                               raw_ostream &O) {
   // Do not print the numeric target address when symbolizing.
-  if (SymbolizeOperands)
+  if (getSymbolizeOperands())
     return;
 
   return printOperand(MI, OpNo, STI, O);
diff --git a/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp b/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
index 587906093cebf..6bdb61472ca9b 100644
--- a/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
+++ b/llvm/lib/Target/M68k/GISel/M68kCallLowering.cpp
@@ -219,7 +219,7 @@ bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   auto MIB = MIRBuilder.buildInstrNoInsert(Opc)
                  .add(Info.Callee)
                  .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg);
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp
index 7562a6ec6c790..6b6863878923a 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.cpp
+++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp
@@ -254,7 +254,7 @@ MVT M68kTargetLowering::getScalarShiftAmountTy(const DataLayout &DL,
 enum StructReturnType { NotStructReturn, RegStructReturn, StackStructReturn };
 
 static StructReturnType
-callIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) {
+callIsStructReturn(llvm::ArrayRef<ISD::OutputArg> Outs) {
   if (Outs.empty())
     return NotStructReturn;
 
@@ -267,8 +267,7 @@ callIsStructReturn(const SmallVectorImpl<ISD::OutputArg> &Outs) {
 }
 
 /// Determines whether a function uses struct return semantics.
-static StructReturnType
-argsAreStructReturn(const SmallVectorImpl<ISD::InputArg> &Ins) {
+static StructReturnType argsAreStructReturn(llvm::ArrayRef<ISD::InputArg> Ins) {
   if (Ins.empty())
     return NotStructReturn;
 
@@ -450,13 +449,10 @@ SDValue M68kTargetLowering::EmitTailCallStoreRetAddr(
   return Chain;
 }
 
-SDValue
-M68kTargetLowering::LowerMemArgument(SDValue Chain, CallingConv::ID CallConv,
-                                     const SmallVectorImpl<ISD::InputArg> &Ins,
-                                     const SDLoc &DL, SelectionDAG &DAG,
-                                     const CCValAssign &VA,
-                                     MachineFrameInfo &MFI,
-                                     unsigned ArgIdx) const {
+SDValue M68kTargetLowering::LowerMemArgument(
+    SDValue Chain, CallingConv::ID CallConv, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &DL, SelectionDAG &DAG, const CCValAssign &VA,
+    MachineFrameInfo &MFI, unsigned ArgIdx) const {
   // Create the nodes corresponding to a load from this parameter slot.
   ISD::ArgFlagsTy Flags = Ins[ArgIdx].Flags;
   EVT ValVT;
@@ -545,14 +541,13 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                       SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool &IsTailCall = CLI.IsTailCall;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
 
   MachineFunction &MF = DAG.getMachineFunction();
   StructReturnType SR = callIsStructReturn(Outs);
@@ -565,7 +560,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
   if (Attr.getValueAsBool())
-    IsTailCall = false;
+    CLI.setIsTailCall(false);
 
   // FIXME Add tailcalls support
 
@@ -574,20 +569,20 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     // Force this to be a tail call.  The verifier rules are enough to ensure
     // that we can lower this successfully without moving the return address
     // around.
-    IsTailCall = true;
-  } else if (IsTailCall) {
+    CLI.setIsTailCall(true);
+  } else if (CLI.getIsTailCall()) {
     // Check if it's really possible to do a tail call.
-    IsTailCall = IsEligibleForTailCallOptimization(
+    CLI.setIsTailCall(IsEligibleForTailCallOptimization(
         Callee, CallConv, IsVarArg, SR != NotStructReturn,
         MF.getFunction().hasStructRetAttr(), CLI.RetTy, Outs, OutVals, Ins,
-        DAG);
+        DAG));
 
     // Sibcalls are automatically detected tailcalls which do not require
     // ABI changes.
-    if (!MF.getTarget().Options.GuaranteedTailCallOpt && IsTailCall)
+    if (!MF.getTarget().Options.GuaranteedTailCallOpt && CLI.getIsTailCall())
       IsSibcall = true;
 
-    if (IsTailCall)
+    if (CLI.getIsTailCall())
       ++NumTailCalls;
   }
 
@@ -615,7 +610,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   }
 
   int FPDiff = 0;
-  if (IsTailCall && !IsSibcall && !IsMustTail) {
+  if (CLI.getIsTailCall() && !IsSibcall && !IsMustTail) {
     // Lower arguments at fp - stackoffset + fpdiff.
     unsigned NumBytesCallerPushed = MFI->getBytesToPopOnReturn();
 
@@ -649,8 +644,9 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   SDValue RetFI;
   // Load return address for tail calls.
-  if (IsTailCall && FPDiff)
-    Chain = EmitTailCallLoadRetAddr(DAG, RetFI, Chain, IsTailCall, FPDiff, DL);
+  if (CLI.getIsTailCall() && FPDiff)
+    Chain = EmitTailCallLoadRetAddr(DAG, RetFI, Chain, CLI.getIsTailCall(),
+                                    FPDiff, DL);
 
   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
   SmallVector<SDValue, 8> MemOpChains;
@@ -703,7 +699,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
     if (VA.isRegLoc()) {
       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
-    } else if (!IsSibcall && (!IsTailCall || IsByVal)) {
+    } else if (!IsSibcall && (!CLI.getIsTailCall() || IsByVal)) {
       assert(VA.isMemLoc());
       if (!StackPtr.getNode()) {
         StackPtr = DAG.getCopyFromReg(Chain, DL, RegInfo->getStackRegister(),
@@ -732,7 +728,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // For tail calls lower the arguments to the 'real' stack slots.  Sibcalls
   // don't need this because the eligibility check rejects calls that require
   // shuffling arguments passed in memory.
-  if (!IsSibcall && IsTailCall) {
+  if (!IsSibcall && CLI.getIsTailCall()) {
     // Force all the incoming stack arguments to be loaded from the stack
     // before any new outgoing arguments are stored to the stack, because the
     // outgoing stack slots may alias the incoming argument stack slots, and
@@ -836,7 +832,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   SmallVector<SDValue, 8> Ops;
 
-  if (!IsSibcall && IsTailCall) {
+  if (!IsSibcall && CLI.getIsTailCall()) {
     Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, 0, InGlue, DL);
     InGlue = Chain.getValue(1);
   }
@@ -844,7 +840,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   Ops.push_back(Chain);
   Ops.push_back(Callee);
 
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     Ops.push_back(DAG.getConstant(FPDiff, DL, MVT::i32));
 
   // Add argument registers to the end of the list so that they are known live
@@ -862,7 +858,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   if (InGlue.getNode())
     Ops.push_back(InGlue);
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     return DAG.getNode(M68kISD::TC_RETURN, DL, MVT::Other, Ops);
   }
@@ -884,7 +880,7 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     NumBytesForCalleeToPop = 0; // Callee pops nothing.
   }
 
-  if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) {
+  if (CLI.getDoesNotReturn() && !getTargetMachine().Options.TrapUnreachable) {
     // No need to reset the stack after the call if the call doesn't return. To
     // make the MI verify, we'll pretend the callee does it for us.
     NumBytesForCalleeToPop = NumBytes;
@@ -905,8 +901,8 @@ SDValue M68kTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
 SDValue M68kTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
@@ -940,8 +936,8 @@ SDValue M68kTargetLowering::LowerCallResult(
 
 SDValue M68kTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CCID, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   M68kMachineFunctionInfo *MMFI = MF.getInfo<M68kMachineFunctionInfo>();
   // const TargetFrameLowering &TFL = *Subtarget.getFrameLowering();
@@ -1049,8 +1045,8 @@ SDValue M68kTargetLowering::LowerFormalArguments(
 
     // Compute the set of forwarded registers. The rest are scratch.
     // ??? what is this for?
-    SmallVectorImpl<ForwardedRegister> &Forwards =
-        MMFI->getForwardedMustTailRegParms();
+    SmallVector<ForwardedRegister, 1> Forwards;
+    Forwards = std::move(MMFI->getForwardedMustTailRegParms());
     CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_M68k);
 
     // Copy all forwards from physical to virtual registers.
@@ -1060,6 +1056,7 @@ SDValue M68kTargetLowering::LowerFormalArguments(
       F.VReg = MF.getRegInfo().createVirtualRegister(getRegClassFor(F.VT));
       Chain = DAG.getCopyToReg(Chain, DL, F.VReg, RegVal);
     }
+    MMFI->getForwardedMustTailRegParms().assign(std::move(Forwards));
   }
 
   // Some CCs need callee pop.
@@ -1082,21 +1079,22 @@ SDValue M68kTargetLowering::LowerFormalArguments(
 //              Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool M68kTargetLowering::CanLowerReturn(
-    CallingConv::ID CCID, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool M68kTargetLowering::CanLowerReturn(CallingConv::ID CCID,
+                                        MachineFunction &MF, bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        LLVMContext &Context,
+                                        const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, RetCC_M68k);
 }
 
-SDValue
-M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID,
-                                bool IsVarArg,
-                                const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                const SmallVectorImpl<SDValue> &OutVals,
-                                const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue M68kTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CCID,
+                                        bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        const SmallVectorImpl<SDValue> &OutVals,
+                                        const SDLoc &DL,
+                                        SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
   M68kMachineFunctionInfo *MFI = MF.getInfo<M68kMachineFunctionInfo>();
 
@@ -1247,9 +1245,9 @@ M68kTargetLowering::GetAlignedArgumentStackSize(unsigned StackSize,
 bool M68kTargetLowering::IsEligibleForTailCallOptimization(
     SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
     bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const {
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    SelectionDAG &DAG) const {
   if (!mayTailCallThisCC(CalleeCC))
     return false;
 
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h
index e4a92754606a0..bdf11b30e9371 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.h
+++ b/llvm/lib/Target/M68k/M68kISelLowering.h
@@ -152,7 +152,7 @@ class M68kTargetLowering : public TargetLowering {
                                    const SDLoc &DL) const;
 
   SDValue LowerMemArgument(SDValue Chain, CallingConv::ID CallConv,
-                           const SmallVectorImpl<ISD::InputArg> &ArgInfo,
+                           llvm::ArrayRef<ISD::InputArg> ArgInfo,
                            const SDLoc &DL, SelectionDAG &DAG,
                            const CCValAssign &VA, MachineFrameInfo &MFI,
                            unsigned ArgIdx) const;
@@ -185,16 +185,15 @@ class M68kTargetLowering : public TargetLowering {
 
   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                           CallingConv::ID CallConv, bool IsVarArg,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &DL, SelectionDAG &DAG,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL,
+                          SelectionDAG &DAG,
                           SmallVectorImpl<SDValue> &InVals) const;
   SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
 
   /// LowerFormalArguments - transform physical registers into virtual
   /// registers and generate load operations for arguments places on the stack.
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CCID,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -202,14 +201,13 @@ class M68kTargetLowering : public TargetLowering {
                     SmallVectorImpl<SDValue> &InVals) const override;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   /// Lower the result values of a call into the
   /// appropriate copies out of appropriate physical registers.
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CCID, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
@@ -250,9 +248,9 @@ class M68kTargetLowering : public TargetLowering {
   bool IsEligibleForTailCallOptimization(
       SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg,
       bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy,
-      const SmallVectorImpl<ISD::OutputArg> &Outs,
+      llvm::ArrayRef<ISD::OutputArg> Outs,
       const SmallVectorImpl<SDValue> &OutVals,
-      const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG &DAG) const;
+      llvm::ArrayRef<ISD::InputArg> Ins, SelectionDAG &DAG) const;
 
   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
 };
diff --git a/llvm/lib/Target/M68k/M68kMachineFunction.h b/llvm/lib/Target/M68k/M68kMachineFunction.h
index 2fefbb49ccd4f..3c8e616e25c83 100644
--- a/llvm/lib/Target/M68k/M68kMachineFunction.h
+++ b/llvm/lib/Target/M68k/M68kMachineFunction.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_LIB_TARGET_M68K_M68KMACHINEFUNCTION_H
 #define LLVM_LIB_TARGET_M68K_M68KMACHINEFUNCTION_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGenTypes/MachineValueType.h"
@@ -50,7 +51,12 @@ class M68kMachineFunctionInfo : public MachineFunctionInfo {
 
   /// Keeps track of whether this function uses sequences of pushes to pass
   /// function parameters.
-  bool HasPushSequences = false;
+  bool getHasPushSequencesFlag() const {
+    return ForwardedMustTailRegParms.getFlag(0);
+  }
+  void setHasPushSequencesFlag(bool Value) {
+    ForwardedMustTailRegParms.setFlag(0, Value);
+  }
 
   /// Some subtargets require that sret lowering includes
   /// returning the value of the returned struct in a register. This field
@@ -59,7 +65,7 @@ class M68kMachineFunctionInfo : public MachineFunctionInfo {
 
   /// A list of virtual and physical registers that must be forwarded to every
   /// musttail call.
-  SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms;
+  llvm::SmallVectorWithFlags<ForwardedRegister, 1> ForwardedMustTailRegParms;
 
   /// The number of bytes on stack consumed by the arguments being passed on
   /// the stack.
@@ -96,8 +102,8 @@ class M68kMachineFunctionInfo : public MachineFunctionInfo {
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
 
-  bool getHasPushSequences() const { return HasPushSequences; }
-  void setHasPushSequences(bool HasPush) { HasPushSequences = HasPush; }
+  bool getHasPushSequences() const { return getHasPushSequencesFlag(); }
+  void setHasPushSequences(bool HasPush) { setHasPushSequencesFlag(HasPush); }
 
   unsigned getSRetReturnReg() const { return SRetReturnReg; }
   void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
@@ -105,7 +111,7 @@ class M68kMachineFunctionInfo : public MachineFunctionInfo {
   unsigned getArgumentStackSize() const { return ArgumentStackSize; }
   void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
 
-  SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() {
+  SmallVectorWithFlagsImpl<ForwardedRegister> &getForwardedMustTailRegParms() {
     return ForwardedMustTailRegParms;
   }
 
diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
index 04a8a0721e6f5..5cdbeee178e05 100644
--- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -235,8 +235,8 @@ MSP430TargetLowering::getRegForInlineAsmConstraint(
 
 /// For each argument in a function store the number of pieces it is composed
 /// of.
-template<typename ArgT>
-static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
+template <typename ArgRangeT>
+static void ParseFunctionArgs(const ArgRangeT &Args,
                               SmallVectorImpl<unsigned> &Out) {
   unsigned CurrentArgIndex;
 
@@ -257,12 +257,11 @@ static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
 }
 
 static void AnalyzeVarArgs(CCState &State,
-                           const SmallVectorImpl<ISD::OutputArg> &Outs) {
+                           llvm::ArrayRef<ISD::OutputArg> Outs) {
   State.AnalyzeCallOperands(Outs, CC_MSP430_AssignStack);
 }
 
-static void AnalyzeVarArgs(CCState &State,
-                           const SmallVectorImpl<ISD::InputArg> &Ins) {
+static void AnalyzeVarArgs(CCState &State, llvm::ArrayRef<ISD::InputArg> Ins) {
   State.AnalyzeFormalArguments(Ins, CC_MSP430_AssignStack);
 }
 
@@ -270,10 +269,10 @@ static void AnalyzeVarArgs(CCState &State,
 /// to handle special constraints in the ABI like reversing the order of the
 /// pieces of splitted arguments. In addition, all pieces of a certain argument
 /// have to be passed either using registers or the stack but never mixing both.
-template<typename ArgT>
+template <typename ArgRangeT>
 static void AnalyzeArguments(CCState &State,
                              SmallVectorImpl<CCValAssign> &ArgLocs,
-                             const SmallVectorImpl<ArgT> &Args) {
+                             const ArgRangeT &Args) {
   static const MCPhysReg CRegList[] = {
     MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15
   };
@@ -369,26 +368,26 @@ static void AnalyzeArguments(CCState &State,
 }
 
 static void AnalyzeRetResult(CCState &State,
-                             const SmallVectorImpl<ISD::InputArg> &Ins) {
+                             llvm::ArrayRef<ISD::InputArg> Ins) {
   State.AnalyzeCallResult(Ins, RetCC_MSP430);
 }
 
 static void AnalyzeRetResult(CCState &State,
-                             const SmallVectorImpl<ISD::OutputArg> &Outs) {
+                             llvm::ArrayRef<ISD::OutputArg> Outs) {
   State.AnalyzeReturn(Outs, RetCC_MSP430);
 }
 
-template<typename ArgT>
+template <typename ArgRangeT>
 static void AnalyzeReturnValues(CCState &State,
                                 SmallVectorImpl<CCValAssign> &RVLocs,
-                                const SmallVectorImpl<ArgT> &Args) {
+                                const ArgRangeT &Args) {
   AnalyzeRetResult(State, Args);
 }
 
 SDValue MSP430TargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   switch (CallConv) {
   default:
@@ -408,17 +407,16 @@ MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                 SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &isTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool isVarArg                         = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
 
   // MSP430 target does not yet support tail call optimization.
-  isTailCall = false;
+  CLI.setIsTailCall(false);
 
   switch (CallConv) {
   default:
@@ -426,8 +424,9 @@ MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   case CallingConv::MSP430_BUILTIN:
   case CallingConv::Fast:
   case CallingConv::C:
-    return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
-                          Outs, OutVals, Ins, dl, DAG, InVals);
+    return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg,
+                          CLI.getIsTailCall(), Outs, OutVals, Ins, dl, DAG,
+                          InVals);
   case CallingConv::MSP430_INTR:
     report_fatal_error("ISRs cannot be called directly");
   }
@@ -438,8 +437,8 @@ MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 // FIXME: struct return stuff
 SDValue MSP430TargetLowering::LowerCCCArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
@@ -541,13 +540,11 @@ SDValue MSP430TargetLowering::LowerCCCArguments(
   return Chain;
 }
 
-bool
-MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
-                                     MachineFunction &MF,
-                                     bool IsVarArg,
-                                     const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                     LLVMContext &Context,
-                                     const Type *RetTy) const {
+bool MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                          MachineFunction &MF, bool IsVarArg,
+                                          llvm::ArrayRef<ISD::OutputArg> Outs,
+                                          LLVMContext &Context,
+                                          const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, RetCC_MSP430);
@@ -556,7 +553,7 @@ MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
 SDValue
 MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                   bool isVarArg,
-                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                  llvm::ArrayRef<ISD::OutputArg> Outs,
                                   const SmallVectorImpl<SDValue> &OutVals,
                                   const SDLoc &dl, SelectionDAG &DAG) const {
 
@@ -626,10 +623,10 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
 SDValue MSP430TargetLowering::LowerCCCCallTo(
     SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
-    bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    bool isTailCall, llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
@@ -755,8 +752,8 @@ SDValue MSP430TargetLowering::LowerCCCCallTo(
 ///
 SDValue MSP430TargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/llvm/lib/Target/MSP430/MSP430ISelLowering.h
index 6e90569b0752e..05a3105b1d05d 100644
--- a/llvm/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.h
@@ -85,42 +85,38 @@ namespace llvm {
   private:
     SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
                            CallingConv::ID CallConv, bool isVarArg,
-                           bool isTailCall,
-                           const SmallVectorImpl<ISD::OutputArg> &Outs,
+                           bool isTailCall, llvm::ArrayRef<ISD::OutputArg> Outs,
                            const SmallVectorImpl<SDValue> &OutVals,
-                           const SmallVectorImpl<ISD::InputArg> &Ins,
-                           const SDLoc &dl, SelectionDAG &DAG,
+                           llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                           SelectionDAG &DAG,
                            SmallVectorImpl<SDValue> &InVals) const;
 
     SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv,
-                              bool isVarArg,
-                              const SmallVectorImpl<ISD::InputArg> &Ins,
+                              bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                               const SDLoc &dl, SelectionDAG &DAG,
                               SmallVectorImpl<SDValue> &InVals) const;
 
     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                             CallingConv::ID CallConv, bool isVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
-                            const SDLoc &dl, SelectionDAG &DAG,
+                            llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                            SelectionDAG &DAG,
                             SmallVectorImpl<SDValue> &InVals) const;
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
     SDValue
       LowerCall(TargetLowering::CallLoweringInfo &CLI,
                 SmallVectorImpl<SDValue> &InVals) const override;
 
-    bool CanLowerReturn(CallingConv::ID CallConv,
-                        MachineFunction &MF,
-                        bool IsVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+    bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+                        bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                         LLVMContext &Context, const Type *RetTy) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
index dc33afac69485..abd4dc9d31970 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp
@@ -149,7 +149,7 @@ void MipsInstPrinter::printJumpOperand(const MCInst *MI, unsigned OpNo,
   if (!Op.isImm())
     return printOperand(MI, OpNo, STI, O);
 
-  if (PrintBranchImmAsAddress)
+  if (getPrintBranchImmAsAddress())
     markup(O, Markup::Immediate) << formatHex(Op.getImm());
   else
     markup(O, Markup::Immediate) << formatImm(Op.getImm());
@@ -163,7 +163,7 @@ void MipsInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,
   if (!Op.isImm())
     return printOperand(MI, OpNo, STI, O);
 
-  if (PrintBranchImmAsAddress) {
+  if (getPrintBranchImmAsAddress()) {
     uint64_t Target = Address + Op.getImm();
     if (STI.hasFeature(Mips::FeatureMips32))
       Target &= 0xffffffff;
diff --git a/llvm/lib/Target/Mips/MipsBranchExpansion.cpp b/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
index 2460459a9b3be..27f643edf3102 100644
--- a/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
+++ b/llvm/lib/Target/Mips/MipsBranchExpansion.cpp
@@ -80,6 +80,7 @@
 #include "MipsMachineFunction.h"
 #include "MipsSubtarget.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
@@ -160,10 +161,12 @@ class MipsBranchExpansion : public MachineFunctionPass {
   const MipsInstrInfo *TII;
 
   MachineFunction *MFp;
-  SmallVector<MBBInfo, 16> MBBInfos;
-  bool IsPIC;
+  llvm::SmallVectorWithFlags<MBBInfo, 16, 2> MBBInfos;
+  bool getIsPIC() const { return MBBInfos.getFlag(0); }
+  void setIsPIC(bool Value) { MBBInfos.setFlag(0, Value); }
   MipsABIInfo ABI;
-  bool ForceLongBranchFirstPass = false;
+  bool getForceLongBranchFirstPass() const { return MBBInfos.getFlag(1); }
+  void setForceLongBranchFirstPass(bool Value) { MBBInfos.setFlag(1, Value); }
 };
 
 } // end of anonymous namespace
@@ -408,7 +411,7 @@ void MipsBranchExpansion::expandToLongBranch(MBBInfo &I) {
   MFp->insert(FallThroughMBB, LongBrMBB);
   MBB->replaceSuccessor(TgtMBB, LongBrMBB);
 
-  if (IsPIC) {
+  if (getIsPIC()) {
     MachineBasicBlock *BalTgtMBB = MFp->CreateMachineBasicBlock(BB);
     MFp->insert(FallThroughMBB, BalTgtMBB);
     LongBrMBB->addSuccessor(BalTgtMBB);
@@ -876,10 +879,10 @@ bool MipsBranchExpansion::handlePossibleLongBranch() {
 
       if ((Br != End) && Br->isBranch() && !Br->isIndirectBranch() &&
           (Br->isConditionalBranch() ||
-           (Br->isUnconditionalBranch() && IsPIC))) {
+           (Br->isUnconditionalBranch() && getIsPIC()))) {
         int64_t Offset = computeOffset(&*Br);
 
-        if (ForceLongBranchFirstPass ||
+        if (getForceLongBranchFirstPass() ||
             !TII->isBranchOffsetInRange(Br->getOpcode(), Offset)) {
           MBBInfos[I].Offset = Offset;
           MBBInfos[I].Br = &*Br;
@@ -887,7 +890,7 @@ bool MipsBranchExpansion::handlePossibleLongBranch() {
       }
     } // End for
 
-    ForceLongBranchFirstPass = false;
+    setForceLongBranchFirstPass(false);
 
     SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end();
 
@@ -910,18 +913,18 @@ bool MipsBranchExpansion::handlePossibleLongBranch() {
 
 bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) {
   const TargetMachine &TM = MF.getTarget();
-  IsPIC = TM.isPositionIndependent();
+  setIsPIC(TM.isPositionIndependent());
   STI = &MF.getSubtarget<MipsSubtarget>();
   ABI = STI->getABI();
   TII = STI->getInstrInfo();
 
-  if (IsPIC && ABI.IsO32() &&
+  if (getIsPIC() && ABI.IsO32() &&
       MF.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
     emitGPDisp(MF, TII);
 
   MFp = &MF;
 
-  ForceLongBranchFirstPass = STI->getCLOpts().force_mips_long_branch;
+  setForceLongBranchFirstPass(STI->getCLOpts().force_mips_long_branch);
   // Run these at least once.
   bool longBranchChanged = handlePossibleLongBranch();
   bool forbiddenSlotChanged = handleForbiddenSlot();
diff --git a/llvm/lib/Target/Mips/MipsCallLowering.cpp b/llvm/lib/Target/Mips/MipsCallLowering.cpp
index 98a8c563defbf..37078ecc1cf7e 100644
--- a/llvm/lib/Target/Mips/MipsCallLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsCallLowering.cpp
@@ -420,7 +420,7 @@ bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(
       Info.Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL);
   MIB.setOperandDead(0); // implicit-def $ra
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
   MIB.addDef(Mips::SP, RegState::Implicit);
   if (IsCalleeGlobalPIC) {
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index b9c1c57af6e61..451417a4a0b97 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -3385,14 +3385,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                               SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc DL                              = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &IsTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool IsVarArg                         = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   const CallBase *CB = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
@@ -3471,9 +3470,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       CalleeIsLocal = GV->isDSOLocal();
   }
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     if (!Subtarget.getCLOpts().tail_calls) {
-      IsTailCall = false;
+      CLI.setIsTailCall(false);
       if (IsMustTail)
         report_fatal_error("failed to perform tail call elimination on a call "
                            "site marked musttail");
@@ -3481,7 +3480,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       bool Eligible = isEligibleForTailCallOptimization(
           CCInfo, StackSize, *MF.getInfo<MipsFunctionInfo>());
       if (!Eligible || !CalleeIsLocal) {
-        IsTailCall = false;
+        CLI.setIsTailCall(false);
         if (IsMustTail)
           report_fatal_error(
               "failed to perform tail call elimination on a call "
@@ -3490,7 +3489,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     }
   }
 
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     ++NumTailCalls;
 
   // Chain is the output chain of the last Load/Store or CopyToReg node.
@@ -3499,7 +3498,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   unsigned StackAlignment = TFL->getStackAlignment();
   StackSize = alignTo(StackSize, StackAlignment);
 
-  if (!(IsTailCall || MemcpyInByVal))
+  if (!(CLI.getIsTailCall() || MemcpyInByVal))
     Chain = DAG.getCALLSEQ_START(Chain, StackSize, 0, DL);
 
   SDValue StackPtr =
@@ -3527,7 +3526,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       assert(Flags.getByValSize() &&
              "ByVal args of size 0 should have been ignored by front-end.");
       assert(ByValIdx < CCInfo.getInRegsParamsCount());
-      assert(!IsTailCall &&
+      assert(!CLI.getIsTailCall() &&
              "Do not tail-call optimize if there is a byval argument.");
       passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg,
                    FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(),
@@ -3618,8 +3617,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
     // emit ISD::STORE whichs stores the
     // parameter value to a stack Location
-    MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(),
-                                         Chain, Arg, DL, IsTailCall, DAG));
+    MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), Chain,
+                                         Arg, DL, CLI.getIsTailCall(), DAG));
   }
 
   // Transform all store nodes into one single node because all store
@@ -3720,7 +3719,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, LocalLinkage,
               IsCallReloc, CLI, Callee, Chain);
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     SDValue Ret = DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops);
     DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
@@ -3749,8 +3748,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 /// appropriate copies out of appropriate physical registers.
 SDValue MipsTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals,
     TargetLowering::CallLoweringInfo &CLI) const {
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
@@ -3873,8 +3872,8 @@ static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA,
 /// and generate load operations for arguments places on the stack.
 SDValue MipsTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
@@ -4028,11 +4027,11 @@ SDValue MipsTargetLowering::LowerFormalArguments(
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool
-MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
-                                   MachineFunction &MF, bool IsVarArg,
-                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                   LLVMContext &Context, const Type *RetTy) const {
+bool MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                        MachineFunction &MF, bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        LLVMContext &Context,
+                                        const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, RetCC_Mips);
@@ -4058,12 +4057,12 @@ MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
   return DAG.getNode(MipsISD::ERet, DL, MVT::Other, RetOps);
 }
 
-SDValue
-MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                                bool IsVarArg,
-                                const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                const SmallVectorImpl<SDValue> &OutVals,
-                                const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                        bool IsVarArg,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs,
+                                        const SmallVectorImpl<SDValue> &OutVals,
+                                        const SDLoc &DL,
+                                        SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of
   // the return value to a location
   SmallVector<CCValAssign, 16> RVLocs;
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 84af86e6cc088..42a13cbca2006 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -347,9 +347,8 @@ using TargetRegisterClass = MCRegisterClass;
     // Lower Operand helpers
     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                             CallingConv::ID CallConv, bool isVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
-                            const SDLoc &dl, SelectionDAG &DAG,
-                            SmallVectorImpl<SDValue> &InVals,
+                            llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                            SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
                             TargetLowering::CallLoweringInfo &CLI) const;
 
     // Lower Operand specifics
@@ -420,8 +419,8 @@ using TargetRegisterClass = MCRegisterClass;
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
 
     SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain,
@@ -432,12 +431,11 @@ using TargetRegisterClass = MCRegisterClass;
                       SmallVectorImpl<SDValue> &InVals) const override;
 
     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                        bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                         LLVMContext &Context, const Type *RetTy) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp
index ca39b74b244d3..b618aad74c169 100644
--- a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp
+++ b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.cpp
@@ -36,7 +36,7 @@ void NVPTXTargetStreamer::outputDwarfFileDirectives() {
 }
 
 void NVPTXTargetStreamer::closeLastSection() {
-  if (HasSections)
+  if (getHasSections())
     getStreamer().emitRawText("\t}");
 }
 
@@ -98,7 +98,7 @@ void NVPTXTargetStreamer::changeSection(const MCSection *CurSection,
     OS << "\t.section\t" << Section->getName() << '\n';
     // DWARF sections are enclosed into braces - emit the open one.
     OS << "\t{\n";
-    HasSections = true;
+    setHasSections(true);
   }
 }
 
diff --git a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h
index cad8c7dc19263..acd4f7d89fd07 100644
--- a/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h
+++ b/llvm/lib/Target/NVPTX/MCTargetDesc/NVPTXTargetStreamer.h
@@ -10,6 +10,7 @@
 #define LLVM_LIB_TARGET_NVPTX_MCTARGETDESC_NVPTXTARGETSTREAMER_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCStreamer.h"
 #include <optional>
 
@@ -21,8 +22,9 @@ class formatted_raw_ostream;
 /// Implments NVPTX-specific streamer.
 class NVPTXTargetStreamer : public MCTargetStreamer {
 private:
-  SmallVector<std::string, 4> DwarfFiles;
-  bool HasSections = false;
+  llvm::SmallVectorWithFlags<std::string, 4> DwarfFiles;
+  bool getHasSections() const { return DwarfFiles.getFlag(0); }
+  void setHasSections(bool Value) { DwarfFiles.setFlag(0, Value); }
 
 public:
   NVPTXTargetStreamer(MCStreamer &S);
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index ab90036722ca4..60bf3de0fe0bb 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -37,6 +37,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -162,15 +163,18 @@ class NVPTXAsmPrinter : public AsmPrinter {
     // We need to keep these values because AggBuffer::print decides whether to
     // emit a "generic()" cast for Symbols[i] depending on the address space of
     // SymbolsBeforeStripping[i].
-    SmallVector<const Value *, 4> SymbolsBeforeStripping;
+    llvm::SmallVectorWithFlags<const Value *, 4> SymbolsBeforeStripping;
     unsigned curpos;
     const NVPTXAsmPrinter &AP;
-    const bool EmitGeneric;
+    bool getEmitGeneric() const { return SymbolsBeforeStripping.getFlag(0); }
 
   public:
     AggBuffer(unsigned Size, const NVPTXAsmPrinter &AP)
-        : Size(Size), buffer(Size), curpos(0), AP(AP),
-          EmitGeneric(AP.EmitGeneric) {}
+        : Size(Size), buffer(Size),
+          SymbolsBeforeStripping(
+              decltype(this->SymbolsBeforeStripping)::withFlags(
+                  unsigned(bool(AP.EmitGeneric)))),
+          curpos(0), AP(AP) {}
 
     unsigned getBufferSize() const { return Size; }
 
@@ -1593,7 +1597,7 @@ void NVPTXAsmPrinter::AggBuffer::printSymbol(unsigned nSym, raw_ostream &os) {
     PointerType *PTy = dyn_cast<PointerType>(v0->getType());
     // Is v0 a generic pointer?
     bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
-    if (EmitGeneric && isGenericPointer && !isa<Function>(v)) {
+    if (getEmitGeneric() && isGenericPointer && !isa<Function>(v)) {
       os << "generic(";
       Name->print(os, AP.MAI);
       os << ")";
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
index 7d55ba810e106..037813739c962 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
@@ -1298,7 +1298,7 @@ static SDValue getSymbolNode(SelectionDAG &DAG, const Twine &Name, EVT T) {
 SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                        SmallVectorImpl<SDValue> &InVals) const {
 
-  if (CLI.IsVarArg &&
+  if (CLI.getIsVarArg() &&
       (!STI.hasFeature(NVPTX::PTX60) || !STI.hasFeature(NVPTX::SM30)))
     report_fatal_error(
         "Support for variadic functions (unsized array parameter) introduced "
@@ -1306,7 +1306,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   SelectionDAG &DAG = CLI.DAG;
   SDLoc dl = CLI.DL;
-  const SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  const auto &Ins = CLI.Ins;
   SDValue Callee = CLI.Callee;
   ArgListTy &Args = CLI.getArgs();
   Type *RetTy = CLI.RetTy;
@@ -1363,7 +1363,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   //
   // After all vararg is processed, 'VAOffset' holds the size of the
   // vararg byte array.
-  assert((CLI.IsVarArg || CLI.Args.size() <= CLI.NumFixedArgs) &&
+  assert((CLI.getIsVarArg() || CLI.Args.size() <= CLI.NumFixedArgs) &&
          "Non-VarArg function with extra arguments");
 
   const unsigned FirstVAArg = CLI.NumFixedArgs; // position of first variadic
@@ -1636,7 +1636,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   const SDValue CallToken = DAG.getTokenFactor(dl, CallPrereqs);
   const SDValue Call = DAG.getNode(
       NVPTXISD::CALL, dl, MVT::Other,
-      {CallToken, GetI32(CLI.IsConvergent), GetI32(IsIndirectCall),
+      {CallToken, GetI32(CLI.getIsConvergent()), GetI32(IsIndirectCall),
        GetI32(Ins.empty() ? 0 : 1), GetI32(NumArgs), Callee, Proto});
 
   SmallVector<SDValue, 16> LoadChains{Call};
@@ -1698,7 +1698,7 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // set IsTailCall to false for now, until we figure out how to express
   // tail call optimization in PTX
-  CLI.IsTailCall = false;
+  CLI.setIsTailCall(false);
   return CallEnd;
 }
 
@@ -4276,8 +4276,8 @@ SDValue NVPTXTargetLowering::getCallParamSymbolNode(SelectionDAG &DAG, int I,
 
 SDValue NVPTXTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   const DataLayout &DL = DAG.getDataLayout();
   LLVMContext &Ctx = *DAG.getContext();
 
@@ -4405,7 +4405,7 @@ SDValue NVPTXTargetLowering::LowerFormalArguments(
 SDValue
 NVPTXTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                  bool isVarArg,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                 llvm::ArrayRef<ISD::OutputArg> Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SDLoc &dl, SelectionDAG &DAG) const {
   const Function &F = DAG.getMachineFunction().getFunction();
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
index 4942408f6449b..7b8590e0f80c1 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
@@ -73,8 +73,7 @@ class NVPTXTargetLowering : public TargetLowering {
                                StringRef Constraint, MVT VT) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &dl, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -86,7 +85,7 @@ class NVPTXTargetLowering : public TargetLowering {
   SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp
index 45dbd50945bfe..c49e2e75ced75 100644
--- a/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp
@@ -185,7 +185,7 @@ struct ArgUseChecker : PtrUseVisitor<ArgUseChecker> {
   PtrInfo visitArgPtr(Argument &A) {
     assert(A.getType()->isPointerTy());
     IntegerType *IntIdxTy = cast<IntegerType>(DL.getIndexType(A.getType()));
-    IsOffsetKnown = false;
+    setIsOffsetKnown(false);
     Offset = APInt(IntIdxTy->getBitWidth(), 0);
     PI.reset();
 
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
index 3f455223f401d..badb107f043e7 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
@@ -422,7 +422,7 @@ void PPCInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,
   if (!MI->getOperand(OpNo).isImm())
     return printOperand(MI, OpNo, STI, O);
   int32_t Imm = SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
-  if (PrintBranchImmAsAddress) {
+  if (getPrintBranchImmAsAddress()) {
     uint64_t Target = Address + Imm;
     if (!TT.isPPC64())
       Target &= 0xffffffff;
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index e2e3d0f70d0e1..674e410805a5a 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2462,7 +2462,7 @@ void PPCAIXAsmPrinter::emitTracebackTable() {
   if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
     FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
 
-  const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
+  ArrayRef<Register> MustSaveCRs = FI->getMustSaveCRs();
   if (!MustSaveCRs.empty())
     FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;
 
diff --git a/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp b/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
index 3644e75609fc3..53aec13cec236 100644
--- a/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
+++ b/llvm/lib/Target/PowerPC/PPCBranchCoalescing.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "PPC.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -137,9 +138,11 @@ class PPCBranchCoalescing : public MachineFunctionPass {
     MachineBasicBlock *BranchBlock;       // Block containing the branch
     MachineBasicBlock *BranchTargetBlock; // Block branched to
     MachineBasicBlock *FallThroughBlock;  // Fall-through if branch not taken
-    SmallVector<MachineOperand, 4> Cond;
-    bool MustMoveDown;
-    bool MustMoveUp;
+    llvm::SmallVectorWithFlags<MachineOperand, 4, 2> Cond;
+    bool getMustMoveDown() const { return Cond.getFlag(0); }
+    void setMustMoveDown(bool Value) { Cond.setFlag(0, Value); }
+    bool getMustMoveUp() const { return Cond.getFlag(1); }
+    void setMustMoveUp(bool Value) { Cond.setFlag(1, Value); }
 
     CoalescingCandidateInfo();
     void clear();
@@ -200,15 +203,15 @@ INITIALIZE_PASS_END(PPCBranchCoalescing, DEBUG_TYPE, "Branch Coalescing",
 
 PPCBranchCoalescing::CoalescingCandidateInfo::CoalescingCandidateInfo()
     : BranchBlock(nullptr), BranchTargetBlock(nullptr),
-      FallThroughBlock(nullptr), MustMoveDown(false), MustMoveUp(false) {}
+      FallThroughBlock(nullptr) {}
 
 void PPCBranchCoalescing::CoalescingCandidateInfo::clear() {
   BranchBlock = nullptr;
   BranchTargetBlock = nullptr;
   FallThroughBlock = nullptr;
   Cond.clear();
-  MustMoveDown = false;
-  MustMoveUp = false;
+  setMustMoveDown(false);
+  setMustMoveUp(false);
 }
 
 void PPCBranchCoalescing::initialize(MachineFunction &MF) {
@@ -233,8 +236,12 @@ bool PPCBranchCoalescing::canCoalesceBranch(CoalescingCandidateInfo &Cand) {
                     << Cand.BranchBlock->getNumber() << " can be coalesced:");
   MachineBasicBlock *FalseMBB = nullptr;
 
-  if (TII->analyzeBranch(*Cand.BranchBlock, Cand.BranchTargetBlock, FalseMBB,
-                         Cand.Cond)) {
+  SmallVector<MachineOperand, 4> Condition;
+  Condition = std::move(Cand.Cond);
+  bool CannotAnalyze = TII->analyzeBranch(
+      *Cand.BranchBlock, Cand.BranchTargetBlock, FalseMBB, Condition);
+  Cand.Cond.assign(std::move(Condition));
+  if (CannotAnalyze) {
     LLVM_DEBUG(dbgs() << "TII unable to Analyze Branch - skip\n");
     return false;
   }
@@ -551,7 +558,7 @@ bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion,
           LLVM_DEBUG(dbgs() << "PHI " << *I
                             << " defines register used in this "
                                "block -- all must move down\n");
-          SourceRegion.MustMoveDown = true;
+          SourceRegion.setMustMoveDown(true);
         }
       }
   }
@@ -565,16 +572,18 @@ bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion,
     if (!canMoveToBeginning(*I, *SourceRegion.BranchTargetBlock)) {
       LLVM_DEBUG(dbgs() << "Instruction " << *I
                         << " cannot move down - must move up!\n");
-      SourceRegion.MustMoveUp = true;
+      SourceRegion.setMustMoveUp(true);
     }
     if (!canMoveToEnd(*I, *TargetRegion.BranchBlock)) {
       LLVM_DEBUG(dbgs() << "Instruction " << *I
                         << " cannot move up - must move down!\n");
-      SourceRegion.MustMoveDown = true;
+      SourceRegion.setMustMoveDown(true);
     }
   }
 
-  return (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) ? false : true;
+  return (SourceRegion.getMustMoveUp() && SourceRegion.getMustMoveDown())
+             ? false
+             : true;
 }
 
 /// Merge the instructions from SourceRegion.BranchBlock,
@@ -636,7 +645,7 @@ bool PPCBranchCoalescing::canMerge(CoalescingCandidateInfo &SourceRegion,
 bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion,
                                        CoalescingCandidateInfo &TargetRegion) {
 
-  if (SourceRegion.MustMoveUp && SourceRegion.MustMoveDown) {
+  if (SourceRegion.getMustMoveUp() && SourceRegion.getMustMoveDown()) {
     llvm_unreachable("Cannot have both MustMoveDown and MustMoveUp set!");
     return false;
   }
@@ -655,12 +664,12 @@ bool PPCBranchCoalescing::mergeCandidates(CoalescingCandidateInfo &SourceRegion,
   MachineBasicBlock::iterator lastInstr =
       SourceRegion.BranchBlock->getFirstTerminator();
 
-  MachineBasicBlock *Source = SourceRegion.MustMoveDown
+  MachineBasicBlock *Source = SourceRegion.getMustMoveDown()
                                   ? SourceRegion.BranchTargetBlock
                                   : TargetRegion.BranchBlock;
 
   MachineBasicBlock::iterator Target =
-      SourceRegion.MustMoveDown
+      SourceRegion.getMustMoveDown()
           ? SourceRegion.BranchTargetBlock->getFirstNonPHI()
           : TargetRegion.BranchBlock->getFirstTerminator();
 
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index 6d8300fc8faa2..93e2761477765 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -639,7 +639,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
   PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
   bool MustSaveLR = FI->mustSaveLR();
   bool MustSaveTOC = FI->mustSaveTOC();
-  const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
+  ArrayRef<Register> MustSaveCRs = FI->getMustSaveCRs();
   bool MustSaveCR = !MustSaveCRs.empty();
   // Do we have a frame pointer and/or base pointer for this function?
   bool HasFP = hasFP(MF);
@@ -1561,7 +1561,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
   // Check if the link register (LR) has been saved.
   PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
   bool MustSaveLR = FI->mustSaveLR();
-  const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
+  ArrayRef<Register> MustSaveCRs = FI->getMustSaveCRs();
   bool MustSaveCR = !MustSaveCRs.empty();
   // Do we have a frame pointer and/or base pointer for this function?
   bool HasFP = hasFP(MF);
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 43258d8ff0b87..4cd2f14d87d5e 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -24,6 +24,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
@@ -1856,7 +1857,7 @@ class BitPermutationSelector {
   // For each value (except the constant ones), compute the left-rotate amount
   // to get it from its original to final position.
   void computeRotationAmounts() {
-    NeedMask = false;
+    setNeedMask(false);
     RLAmt.resize(Bits.size());
     for (unsigned i = 0; i < Bits.size(); ++i)
       if (Bits[i].hasValue()) {
@@ -1866,7 +1867,7 @@ class BitPermutationSelector {
         else
           RLAmt[i] = Bits.size() - (VBI - i);
       } else if (Bits[i].isZero()) {
-        NeedMask = true;
+        setNeedMask(true);
         RLAmt[i] = UINT32_MAX;
       } else {
         llvm_unreachable("Unknown value bit type");
@@ -2276,7 +2277,7 @@ class BitPermutationSelector {
     // If we've not yet selected a 'starting' instruction, and we have no zeros
     // to fill in, select the (Value, RLAmt) with the highest priority (largest
     // number of groups), and start with this rotated value.
-    if ((!NeedMask || LateMask) && !Res) {
+    if ((!getNeedMask() || LateMask) && !Res) {
       ValueRotInfo &VRI = ValueRotsVec[0];
       if (VRI.RLAmt) {
         if (InstCnt) *InstCnt += 1;
@@ -2662,7 +2663,7 @@ class BitPermutationSelector {
     // If we've not yet selected a 'starting' instruction, and we have no zeros
     // to fill in, select the (Value, RLAmt) with the highest priority (largest
     // number of groups), and start with this rotated value.
-    if ((!NeedMask || LateMask) && !Res) {
+    if ((!getNeedMask() || LateMask) && !Res) {
       // If we have both Repl32 groups and non-Repl32 groups, the non-Repl32
       // groups will come first, and so the VRI representing the largest number
       // of groups might not be first (it might be the first Repl32 groups).
@@ -2822,13 +2823,14 @@ class BitPermutationSelector {
 
   SmallVector<ValueBit, 64> Bits;
 
-  bool NeedMask = false;
+  bool getNeedMask() const { return ValueRotsVec.getFlag(0); }
+  void setNeedMask(bool Value) { ValueRotsVec.setFlag(0, Value); }
   SmallVector<unsigned, 64> RLAmt;
 
   SmallVector<BitGroup, 16> BitGroups;
 
   DenseMap<std::pair<SDValue, unsigned>, ValueRotInfo> ValueRots;
-  SmallVector<ValueRotInfo, 16> ValueRotsVec;
+  llvm::SmallVectorWithFlags<ValueRotInfo, 16> ValueRotsVec;
 
   SelectionDAG *CurDAG = nullptr;
 
@@ -2854,7 +2856,7 @@ class BitPermutationSelector {
     // Fill it RLAmt and set NeedMask.
     computeRotationAmounts();
 
-    if (!NeedMask)
+    if (!getNeedMask())
       return Select(N, false);
 
     // We currently have two techniques for handling results with zeros: early
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index b2f1fd6176862..af896c7f5e875 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -4191,8 +4191,8 @@ static unsigned EnsureStackAlignment(const PPCFrameLowering *Lowering,
 
 SDValue PPCTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   if (Subtarget.isAIXABI())
     return LowerFormalArguments_AIX(Chain, CallConv, isVarArg, Ins, dl, DAG,
                                     InVals);
@@ -4206,8 +4206,8 @@ SDValue PPCTargetLowering::LowerFormalArguments(
 
 SDValue PPCTargetLowering::LowerFormalArguments_32SVR4(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   // 32-bit SVR4 ABI Stack Frame Layout:
   //              +-----------------------------------+
@@ -4464,8 +4464,8 @@ SDValue PPCTargetLowering::extendArgForPPC64(ISD::ArgFlagsTy Flags,
 
 SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   // TODO: add description of PPC stack frame format, or at least some docs.
   //
   bool isELFv2ABI = Subtarget.isELFv2ABI();
@@ -4934,9 +4934,8 @@ static bool callsShareTOCBase(const Function *Caller,
   return true;
 }
 
-static bool
-needStackSlotPassParameters(const PPCSubtarget &Subtarget,
-                            const SmallVectorImpl<ISD::OutputArg> &Outs) {
+static bool needStackSlotPassParameters(const PPCSubtarget &Subtarget,
+                                        llvm::ArrayRef<ISD::OutputArg> Outs) {
   assert(Subtarget.is64BitELFABI());
 
   const unsigned PtrByteSize = 8;
@@ -5021,9 +5020,8 @@ areCallingConvEligibleForTCO_64SVR4(CallingConv::ID CallerCC,
 bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
     const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
     CallingConv::ID CallerCC, const CallBase *CB, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const Function *CallerFunc,
-    bool isCalleeExternalSymbol) const {
+    llvm::ArrayRef<ISD::OutputArg> Outs, llvm::ArrayRef<ISD::InputArg> Ins,
+    const Function *CallerFunc, bool isCalleeExternalSymbol) const {
   bool TailCallOpt = getTargetMachine().Options.GuaranteedTailCallOpt;
 
   if (!EnableSCO && !TailCallOpt)
@@ -5110,7 +5108,7 @@ bool PPCTargetLowering::IsEligibleForTailCallOptimization_64SVR4(
 bool PPCTargetLowering::IsEligibleForTailCallOptimization(
     const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
     CallingConv::ID CallerCC, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins) const {
+    llvm::ArrayRef<ISD::InputArg> Ins) const {
   if (!getTargetMachine().Options.GuaranteedTailCallOpt)
     return false;
 
@@ -5319,8 +5317,8 @@ static bool isFunctionGlobalAddress(const GlobalValue *GV) {
 
 SDValue PPCTargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCRetInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
                     *DAG.getContext());
@@ -5785,7 +5783,7 @@ SDValue PPCTargetLowering::FinishCall(
     CallFlags CFlags, const SDLoc &dl, SelectionDAG &DAG,
     SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass, SDValue Glue,
     SDValue Chain, SDValue CallSeqStart, SDValue &Callee, int SPDiff,
-    unsigned NumBytes, const SmallVectorImpl<ISD::InputArg> &Ins,
+    unsigned NumBytes, llvm::ArrayRef<ISD::InputArg> Ins,
     SmallVectorImpl<SDValue> &InVals, const CallBase *CB) const {
 
   if ((Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls()) ||
@@ -5884,9 +5882,8 @@ bool PPCTargetLowering::supportsTailCallFor(const CallBase *CB) const {
 bool PPCTargetLowering::isEligibleForTCO(
     const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
     CallingConv::ID CallerCC, const CallBase *CB, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const Function *CallerFunc,
-    bool isCalleeExternalSymbol) const {
+    llvm::ArrayRef<ISD::OutputArg> Outs, llvm::ArrayRef<ISD::InputArg> Ins,
+    const Function *CallerFunc, bool isCalleeExternalSymbol) const {
   if (Subtarget.useLongCalls() && !(CB && CB->isMustTailCall()))
     return false;
 
@@ -5904,28 +5901,27 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                              SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &isTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool isVarArg                         = CLI.IsVarArg;
-  bool isPatchPoint                     = CLI.IsPatchPoint;
+  bool isVarArg = CLI.getIsVarArg();
+  bool isPatchPoint = CLI.getIsPatchPointFlag();
   const CallBase *CB                    = CLI.CB;
 
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     MachineFunction &MF = DAG.getMachineFunction();
     CallingConv::ID CallerCC = MF.getFunction().getCallingConv();
     auto *G = dyn_cast<GlobalAddressSDNode>(Callee);
     const GlobalValue *GV = G ? G->getGlobal() : nullptr;
     bool IsCalleeExternalSymbol = isa<ExternalSymbolSDNode>(Callee);
 
-    isTailCall =
-        isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg, Outs, Ins,
-                         &(MF.getFunction()), IsCalleeExternalSymbol);
-    if (isTailCall) {
+    CLI.setIsTailCall(isEligibleForTCO(GV, CallConv, CallerCC, CB, isVarArg,
+                                       Outs, Ins, &(MF.getFunction()),
+                                       IsCalleeExternalSymbol));
+    if (CLI.getIsTailCall()) {
       ++NumTailCalls;
       if (!getTargetMachine().Options.GuaranteedTailCallOpt)
         ++NumSiblingCalls;
@@ -5946,7 +5942,7 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     }
   }
 
-  if (!isTailCall && CB && CB->isMustTailCall())
+  if (!CLI.getIsTailCall() && CB && CB->isMustTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
                        "site marked musttail");
 
@@ -5954,16 +5950,16 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // made via function pointer. If we have a function name, first translate it
   // into a pointer.
   if (Subtarget.useLongCalls() && isa<GlobalAddressSDNode>(Callee) &&
-      !isTailCall)
+      !CLI.getIsTailCall())
     Callee = LowerGlobalAddress(Callee, DAG);
 
   CallFlags CFlags(
-      CallConv, isTailCall, isVarArg, isPatchPoint,
+      CallConv, CLI.getIsTailCall(), isVarArg, isPatchPoint,
       isIndirectCall(Callee, DAG, Subtarget, isPatchPoint),
       // hasNest
       Subtarget.is64BitELFABI() &&
           any_of(Outs, [](ISD::OutputArg Arg) { return Arg.Flags.isNest(); }),
-      CLI.NoMerge);
+      CLI.getNoMerge());
 
   if (Subtarget.isAIXABI())
     return LowerCall_AIX(Chain, Callee, CFlags, Outs, OutVals, Ins, dl, DAG,
@@ -5979,10 +5975,9 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
 SDValue PPCTargetLowering::LowerCall_32SVR4(
     SDValue Chain, SDValue Callee, CallFlags CFlags,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
     const CallBase *CB) const {
   // See PPCTargetLowering::LowerFormalArguments_32SVR4() for a description
   // of the 32-bit SVR4 ABI stack frame layout.
@@ -6229,10 +6224,9 @@ SDValue PPCTargetLowering::createMemcpyOutsideCallSeq(
 
 SDValue PPCTargetLowering::LowerCall_64SVR4(
     SDValue Chain, SDValue Callee, CallFlags CFlags,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
     const CallBase *CB) const {
   bool isELFv2ABI = Subtarget.isELFv2ABI();
   bool isLittleEndian = Subtarget.isLittleEndian();
@@ -7195,8 +7189,8 @@ static unsigned mapArgRegToOffsetAIX(unsigned Reg, const PPCFrameLowering *FL) {
 
 SDValue PPCTargetLowering::LowerFormalArguments_AIX(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   assert((CallConv == CallingConv::C || CallConv == CallingConv::Cold ||
           CallConv == CallingConv::Fast) &&
@@ -7565,10 +7559,9 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
 
 SDValue PPCTargetLowering::LowerCall_AIX(
     SDValue Chain, SDValue Callee, CallFlags CFlags,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+    llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
     const CallBase *CB) const {
   // See PPCTargetLowering::LowerFormalArguments_AIX() for a description of the
   // AIX ABI stack frame layout.
@@ -7886,12 +7879,11 @@ SDValue PPCTargetLowering::LowerCall_AIX(
                     Callee, SPDiff, NumBytes, Ins, InVals, CB);
 }
 
-bool
-PPCTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
-                                  MachineFunction &MF, bool isVarArg,
-                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
-                                  LLVMContext &Context,
-                                  const Type *RetTy) const {
+bool PPCTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(
@@ -7900,12 +7892,12 @@ PPCTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
                 : RetCC_PPC);
 }
 
-SDValue
-PPCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &dl, SelectionDAG &DAG) const {
+SDValue PPCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &dl,
+                                       SelectionDAG &DAG) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
                  *DAG.getContext());
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index eaa27ee4e4229..1965f36c8c7e3 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -670,23 +670,22 @@ namespace llvm {
     SDValue getFramePointerFrameIndex(SelectionDAG & DAG) const;
     SDValue getReturnAddrFrameIndex(SelectionDAG & DAG) const;
 
-    bool IsEligibleForTailCallOptimization(
-        const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
-        CallingConv::ID CallerCC, bool isVarArg,
-        const SmallVectorImpl<ISD::InputArg> &Ins) const;
+    bool
+    IsEligibleForTailCallOptimization(const GlobalValue *CalleeGV,
+                                      CallingConv::ID CalleeCC,
+                                      CallingConv::ID CallerCC, bool isVarArg,
+                                      llvm::ArrayRef<ISD::InputArg> Ins) const;
 
     bool IsEligibleForTailCallOptimization_64SVR4(
         const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
         CallingConv::ID CallerCC, const CallBase *CB, bool isVarArg,
-        const SmallVectorImpl<ISD::OutputArg> &Outs,
-        const SmallVectorImpl<ISD::InputArg> &Ins, const Function *CallerFunc,
-        bool isCalleeExternalSymbol) const;
+        llvm::ArrayRef<ISD::OutputArg> Outs, llvm::ArrayRef<ISD::InputArg> Ins,
+        const Function *CallerFunc, bool isCalleeExternalSymbol) const;
 
     bool isEligibleForTCO(const GlobalValue *CalleeGV, CallingConv::ID CalleeCC,
                           CallingConv::ID CallerCC, const CallBase *CB,
-                          bool isVarArg,
-                          const SmallVectorImpl<ISD::OutputArg> &Outs,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
+                          bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
+                          llvm::ArrayRef<ISD::InputArg> Ins,
                           const Function *CallerFunc,
                           bool isCalleeExternalSymbol) const;
 
@@ -788,34 +787,33 @@ namespace llvm {
 
     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                             CallingConv::ID CallConv, bool isVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
-                            const SDLoc &dl, SelectionDAG &DAG,
+                            llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                            SelectionDAG &DAG,
                             SmallVectorImpl<SDValue> &InVals) const;
 
     SDValue FinishCall(CallFlags CFlags, const SDLoc &dl, SelectionDAG &DAG,
                        SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass,
                        SDValue InGlue, SDValue Chain, SDValue CallSeqStart,
                        SDValue &Callee, int SPDiff, unsigned NumBytes,
-                       const SmallVectorImpl<ISD::InputArg> &Ins,
+                       llvm::ArrayRef<ISD::InputArg> Ins,
                        SmallVectorImpl<SDValue> &InVals,
                        const CallBase *CB) const;
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
 
     SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
                       SmallVectorImpl<SDValue> &InVals) const override;
 
     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                        bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                         LLVMContext &Context, const Type *RetTy) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
@@ -823,18 +821,21 @@ namespace llvm {
                               SelectionDAG &DAG, SDValue ArgVal,
                               const SDLoc &dl) const;
 
-    SDValue LowerFormalArguments_AIX(
-        SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-        const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-        SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
-    SDValue LowerFormalArguments_64SVR4(
-        SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-        const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-        SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
-    SDValue LowerFormalArguments_32SVR4(
-        SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-        const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-        SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
+    SDValue LowerFormalArguments_AIX(SDValue Chain, CallingConv::ID CallConv,
+                                     bool isVarArg,
+                                     llvm::ArrayRef<ISD::InputArg> Ins,
+                                     const SDLoc &dl, SelectionDAG &DAG,
+                                     SmallVectorImpl<SDValue> &InVals) const;
+    SDValue LowerFormalArguments_64SVR4(SDValue Chain, CallingConv::ID CallConv,
+                                        bool isVarArg,
+                                        llvm::ArrayRef<ISD::InputArg> Ins,
+                                        const SDLoc &dl, SelectionDAG &DAG,
+                                        SmallVectorImpl<SDValue> &InVals) const;
+    SDValue LowerFormalArguments_32SVR4(SDValue Chain, CallingConv::ID CallConv,
+                                        bool isVarArg,
+                                        llvm::ArrayRef<ISD::InputArg> Ins,
+                                        const SDLoc &dl, SelectionDAG &DAG,
+                                        SmallVectorImpl<SDValue> &InVals) const;
 
     SDValue createMemcpyOutsideCallSeq(SDValue Arg, SDValue PtrOff,
                                        SDValue CallSeqStart,
@@ -842,25 +843,24 @@ namespace llvm {
                                        const SDLoc &dl) const;
 
     SDValue LowerCall_64SVR4(SDValue Chain, SDValue Callee, CallFlags CFlags,
-                             const SmallVectorImpl<ISD::OutputArg> &Outs,
+                             llvm::ArrayRef<ISD::OutputArg> Outs,
                              const SmallVectorImpl<SDValue> &OutVals,
-                             const SmallVectorImpl<ISD::InputArg> &Ins,
-                             const SDLoc &dl, SelectionDAG &DAG,
+                             llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                             SelectionDAG &DAG,
                              SmallVectorImpl<SDValue> &InVals,
                              const CallBase *CB) const;
     SDValue LowerCall_32SVR4(SDValue Chain, SDValue Callee, CallFlags CFlags,
-                             const SmallVectorImpl<ISD::OutputArg> &Outs,
+                             llvm::ArrayRef<ISD::OutputArg> Outs,
                              const SmallVectorImpl<SDValue> &OutVals,
-                             const SmallVectorImpl<ISD::InputArg> &Ins,
-                             const SDLoc &dl, SelectionDAG &DAG,
+                             llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                             SelectionDAG &DAG,
                              SmallVectorImpl<SDValue> &InVals,
                              const CallBase *CB) const;
     SDValue LowerCall_AIX(SDValue Chain, SDValue Callee, CallFlags CFlags,
-                          const SmallVectorImpl<ISD::OutputArg> &Outs,
+                          llvm::ArrayRef<ISD::OutputArg> Outs,
                           const SmallVectorImpl<SDValue> &OutVals,
-                          const SmallVectorImpl<ISD::InputArg> &Ins,
-                          const SDLoc &dl, SelectionDAG &DAG,
-                          SmallVectorImpl<SDValue> &InVals,
+                          llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                          SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
                           const CallBase *CB) const;
 
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
index b7d14da05ee24..c5269cb8e5f6e 100644
--- a/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCMachineFunctionInfo.h
@@ -14,6 +14,7 @@
 #define LLVM_LIB_TARGET_POWERPC_PPCMACHINEFUNCTIONINFO_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/TargetCallingConv.h"
 
@@ -91,7 +92,8 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   bool LRStoreRequired = false;
 
   /// This function makes use of the PPC64 ELF TOC base pointer (register r2).
-  bool UsesTOCBasePtr = false;
+  bool getUsesTOCBasePtrFlag() const { return MustSaveCRs.getFlag(0); }
+  void setUsesTOCBasePtrFlag(bool Value) { MustSaveCRs.setFlag(0, Value); }
 
   /// MinReservedArea - This is the frame size that is at least reserved in a
   /// potential caller (parameter+linkage area).
@@ -104,7 +106,8 @@ class PPCFunctionInfo : public MachineFunctionInfo {
 
   /// HasFastCall - Does this function contain a fast call. Used to determine
   /// how the caller's stack pointer should be calculated (epilog/dynamicalloc).
-  bool HasFastCall = false;
+  bool getHasFastCallFlag() const { return MustSaveCRs.getFlag(1); }
+  void setHasFastCallFlag(bool Value) { MustSaveCRs.setFlag(1, Value); }
 
   /// VarArgsFrameIndex - FrameIndex for start of varargs area.
   int VarArgsFrameIndex = 0;
@@ -133,7 +136,7 @@ class PPCFunctionInfo : public MachineFunctionInfo {
 
   /// ParamtersType - Store all the parameter's type that are saved on
   /// registers.
-  SmallVector<ParamType, 32> ParamtersType;
+  llvm::SmallVectorWithFlags<ParamType, 32> ParamtersType;
 
   /// CRSpillFrameIndex - FrameIndex for CR spill slot for 32-bit SVR4.
   int CRSpillFrameIndex = 0;
@@ -141,10 +144,11 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   /// If any of CR[2-4] need to be saved in the prologue and restored in the
   /// epilogue then they are added to this array. This is used for the
   /// 64-bit SVR4 ABI.
-  SmallVector<Register, 3> MustSaveCRs;
+  llvm::SmallVectorWithFlags<Register, 3, 4> MustSaveCRs;
 
   /// Whether this uses the PIC Base register or not.
-  bool UsesPICBase = false;
+  bool getUsesPICBaseFlag() const { return MustSaveCRs.getFlag(2); }
+  void setUsesPICBaseFlag(bool Value) { MustSaveCRs.setFlag(2, Value); }
 
   /// We keep track attributes for each live-in virtual registers
   /// to use SExt/ZExt flags in later optimization.
@@ -152,8 +156,16 @@ class PPCFunctionInfo : public MachineFunctionInfo {
 
   /// Flags for aix-shared-lib-tls-model-opt, will be lazily initialized for
   /// each function.
-  bool AIXFuncUseTLSIEForLD = false;
-  bool AIXFuncTLSModelOptInitDone = false;
+  bool getAIXFuncUseTLSIEForLDFlag() const { return MustSaveCRs.getFlag(3); }
+  void setAIXFuncUseTLSIEForLDFlag(bool Value) {
+    MustSaveCRs.setFlag(3, Value);
+  }
+  bool getAIXFuncTLSModelOptInitDoneFlag() const {
+    return ParamtersType.getFlag(0);
+  }
+  void setAIXFuncTLSModelOptInitDoneFlag(bool Value) {
+    ParamtersType.setFlag(0, Value);
+  }
 
 public:
   explicit PPCFunctionInfo(const Function &F, const TargetSubtargetInfo *STI);
@@ -220,18 +232,20 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   void setLRStoreRequired() { LRStoreRequired = true; }
   bool isLRStoreRequired() const { return LRStoreRequired; }
 
-  void setUsesTOCBasePtr()    { UsesTOCBasePtr = true; }
-  bool usesTOCBasePtr() const { return UsesTOCBasePtr; }
+  void setUsesTOCBasePtr() { setUsesTOCBasePtrFlag(true); }
+  bool usesTOCBasePtr() const { return getUsesTOCBasePtrFlag(); }
 
-  void setHasFastCall() { HasFastCall = true; }
-  bool hasFastCall() const { return HasFastCall;}
+  void setHasFastCall() { setHasFastCallFlag(true); }
+  bool hasFastCall() const { return getHasFastCallFlag(); }
 
-  void setAIXFuncTLSModelOptInitDone() { AIXFuncTLSModelOptInitDone = true; }
+  void setAIXFuncTLSModelOptInitDone() {
+    setAIXFuncTLSModelOptInitDoneFlag(true);
+  }
   bool isAIXFuncTLSModelOptInitDone() const {
-    return AIXFuncTLSModelOptInitDone;
+    return getAIXFuncTLSModelOptInitDoneFlag();
   }
-  void setAIXFuncUseTLSIEForLD() { AIXFuncUseTLSIEForLD = true; }
-  bool isAIXFuncUseTLSIEForLD() const { return AIXFuncUseTLSIEForLD; }
+  void setAIXFuncUseTLSIEForLD() { setAIXFuncUseTLSIEForLDFlag(true); }
+  bool isAIXFuncUseTLSIEForLD() const { return getAIXFuncUseTLSIEForLDFlag(); }
 
   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
@@ -272,12 +286,11 @@ class PPCFunctionInfo : public MachineFunctionInfo {
   int getCRSpillFrameIndex() const { return CRSpillFrameIndex; }
   void setCRSpillFrameIndex(int idx) { CRSpillFrameIndex = idx; }
 
-  const SmallVectorImpl<Register> &
-    getMustSaveCRs() const { return MustSaveCRs; }
+  ArrayRef<Register> getMustSaveCRs() const { return MustSaveCRs; }
   void addMustSaveCR(Register Reg) { MustSaveCRs.push_back(Reg); }
 
-  void setUsesPICBase(bool uses) { UsesPICBase = uses; }
-  bool usesPICBase() const { return UsesPICBase; }
+  void setUsesPICBase(bool uses) { setUsesPICBaseFlag(uses); }
+  bool usesPICBase() const { return getUsesPICBaseFlag(); }
 
   MCSymbol *getPICOffsetSymbol(MachineFunction &MF) const;
 
diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index b7ad26081ea4d..6946d8ad83cc7 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -1005,8 +1005,8 @@ bool PPCTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
   case Intrinsic::ppc_vsx_lxvll:
   case Intrinsic::ppc_vsx_lxvp: {
     Info.PtrVal = Inst->getArgOperand(0);
-    Info.ReadMem = true;
-    Info.WriteMem = false;
+    Info.setReadMem(true);
+    Info.setWriteMem(false);
     return true;
   }
   case Intrinsic::ppc_altivec_stvx:
@@ -1022,8 +1022,8 @@ bool PPCTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
   case Intrinsic::ppc_vsx_stxvll:
   case Intrinsic::ppc_vsx_stxvp: {
     Info.PtrVal = Inst->getArgOperand(1);
-    Info.ReadMem = false;
-    Info.WriteMem = true;
+    Info.setReadMem(false);
+    Info.setWriteMem(true);
     return true;
   }
   case Intrinsic::ppc_stbcx:
@@ -1031,8 +1031,8 @@ bool PPCTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
   case Intrinsic::ppc_stdcx:
   case Intrinsic::ppc_stwcx: {
     Info.PtrVal = Inst->getArgOperand(0);
-    Info.ReadMem = false;
-    Info.WriteMem = true;
+    Info.setReadMem(false);
+    Info.setWriteMem(true);
     return true;
   }
   default:
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
index 07029d09dad7c..5a77ff4a5d8e0 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
@@ -624,7 +624,7 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
           .buildInstrNoInsert(Info.Callee.isReg() ? RISCV::PseudoCALLIndirect
                                                   : RISCV::PseudoCALL)
           .add(Info.Callee);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     Call.setMIFlag(MachineInstr::MIFlag::NoMerge);
   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
   Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv))
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
index 222b7cae942c8..cec3980efb358 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
@@ -108,14 +108,14 @@ void RISCVInstPrinter::printBranchOperand(const MCInst *MI, uint64_t Address,
                                           const MCSubtargetInfo &STI,
                                           raw_ostream &O) {
   // Do not print the numeric target address when symbolizing.
-  if (SymbolizeOperands)
+  if (getSymbolizeOperands())
     return;
 
   const MCOperand &MO = MI->getOperand(OpNo);
   if (!MO.isImm())
     return printOperand(MI, OpNo, STI, O);
 
-  if (PrintBranchImmAsAddress) {
+  if (getPrintBranchImmAsAddress()) {
     uint64_t Target = Address + MO.getImm();
     if (!STI.hasFeature(RISCV::Feature64Bit))
       Target &= 0xffffffff;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 17032ffc99a7b..e71f163a1a0bb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -28062,8 +28062,8 @@ static SDValue unpackGPRVecOnRV32(SelectionDAG &DAG, SDValue Chain,
 // Transform physical registers into virtual registers.
 SDValue RISCVTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   MachineFunction &MF = DAG.getMachineFunction();
 
@@ -28376,14 +28376,13 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                        SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   MVT XLenVT = Subtarget.getXLenVT();
   const CallBase *CB = CLI.CB;
@@ -28408,10 +28407,11 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   ArgCCInfo.AnalyzeCallOperands(Outs, CC_RISCV);
 
   // Check if it's really possible to do a tail call.
-  if (IsTailCall)
-    IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
+  if (CLI.getIsTailCall())
+    CLI.setIsTailCall(
+        isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs));
 
-  if (IsTailCall)
+  if (CLI.getIsTailCall())
     ++NumTailCalls;
   else if (CLI.CB && CLI.CB->isMustTailCall())
     reportFatalInternalError("failed to perform tail call elimination on a "
@@ -28438,12 +28438,13 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
     Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
                           /*IsVolatile=*/false,
-                          /*AlwaysInline=*/false, /*CI*/ nullptr, IsTailCall,
-                          MachinePointerInfo(), MachinePointerInfo());
+                          /*AlwaysInline=*/false, /*CI*/ nullptr,
+                          CLI.getIsTailCall(), MachinePointerInfo(),
+                          MachinePointerInfo());
     ByValArgs.push_back(FIPtr);
   }
 
-  if (!IsTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
 
   // Copy argument values to their designated locations.
@@ -28537,7 +28538,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
       // For musttail calls, reuse incoming indirect pointers instead of
       // creating new stack temporaries. The incoming pointers point to the
       // caller's caller's frame, which remains valid after a tail call.
-      if (IsTailCall && CLI.CB && CLI.CB->isMustTailCall()) {
+      if (CLI.getIsTailCall() && CLI.CB && CLI.CB->isMustTailCall()) {
         RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
         unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
 
@@ -28703,7 +28704,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
         CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i);
     } else {
       assert(VA.isMemLoc() && "Argument not register or memory");
-      assert((!IsTailCall || (CLI.CB && CLI.CB->isMustTailCall())) &&
+      assert((!CLI.getIsTailCall() || (CLI.CB && CLI.CB->isMustTailCall())) &&
              "Tail call not allowed if stack is used for passing parameters");
 
       // Work out the address of the stack slot.
@@ -28736,7 +28737,8 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // reserved, if so report an error. Do the same for the return address if this
   // is not a tailcall.
   validateCCReservedRegs(RegsToPass, MF);
-  if (!IsTailCall && MF.getSubtarget().isRegisterReservedByUser(RISCV::X1))
+  if (!CLI.getIsTailCall() &&
+      MF.getSubtarget().isRegisterReservedByUser(RISCV::X1))
     MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
         MF.getFunction(),
         "Return address register required, but has been reserved."});
@@ -28805,14 +28807,14 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
       CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
       MF.getInfo<RISCVMachineFunctionInfo>()->hasCFProtectionBranch();
 
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     MF.getFrameInfo().setHasTailCall();
     unsigned CallOpc =
         NeedSWGuardedTail ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
     SDValue Ret = DAG.getNode(CallOpc, DL, NodeTys, Ops);
     if (CLI.CFIType)
       Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue());
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
     return Ret;
   }
@@ -28832,7 +28834,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   if (CLI.CFIType)
     Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
 
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
   Glue = Chain.getValue(1);
 
@@ -28888,10 +28890,11 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
   return Chain;
 }
 
-bool RISCVTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool RISCVTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                         MachineFunction &MF, bool IsVarArg,
+                                         llvm::ArrayRef<ISD::OutputArg> Outs,
+                                         LLVMContext &Context,
+                                         const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, RetCC_RISCV);
@@ -28900,7 +28903,7 @@ bool RISCVTargetLowering::CanLowerReturn(
 SDValue
 RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                  bool IsVarArg,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                 llvm::ArrayRef<ISD::OutputArg> Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SDLoc &DL, SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index af5ea77662d1e..ef3d6fdd61f40 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -302,16 +302,14 @@ class RISCVTargetLowering : public TargetLowering {
 
   // Lower incoming arguments, copy physregs into vregs
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
index f96a8dce3d848..0939b09ebab3d 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
@@ -31,7 +31,7 @@ RISCVMachineFunctionInfo::RISCVMachineFunctionInfo(const Function &F,
                                                    const RISCVSubtarget *STI) {
   if (const auto *CFB = mdconst::extract_or_null<ConstantInt>(
           F.getParent()->getModuleFlag("cf-protection-branch")))
-    CFProtectionBranch = CFB->getZExtValue() != 0;
+    setCFProtectionBranch(CFB->getZExtValue() != 0);
 
   // The default stack probe size is 4096 if the function has no
   // stack-probe-size attribute. This is a safe default because it is the
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
index 3aaf7466d7425..3022df243e0a3 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
@@ -15,6 +15,7 @@
 
 #include "RISCVSubtarget.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -75,7 +76,12 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
   DenseMap<unsigned, Register> IncomingIndirectArgs;
 
   /// Is there any vector argument or return?
-  bool IsVectorCall = false;
+  bool getIsVectorCallFlag() const {
+    return InterruptCSRFrameIndexes.getFlag(0);
+  }
+  void setIsVectorCallFlag(bool Value) {
+    InterruptCSRFrameIndexes.setFlag(0, Value);
+  }
 
   /// Registers that have been sign extended from i32.
   SmallVector<Register, 8> SExt32Registers;
@@ -88,15 +94,26 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
   unsigned QCIInterruptStackSize = 0;
 
   /// Store Frame Indexes for Interrupt-Related CSR Spills.
-  SmallVector<int, 2> InterruptCSRFrameIndexes;
+  llvm::SmallVectorWithFlags<int, 2, 3> InterruptCSRFrameIndexes;
 
   int64_t StackProbeSize = 0;
 
   /// Does it probe the stack for a dynamic allocation?
-  bool HasDynamicAllocation = false;
+  bool getHasDynamicAllocation() const {
+    return InterruptCSRFrameIndexes.getFlag(1);
+  }
+  void setHasDynamicAllocation(bool Value) {
+    InterruptCSRFrameIndexes.setFlag(1, Value);
+  }
 
   /// Whether the function has cf-protection-branch module flag set.
-  bool CFProtectionBranch = false;
+  bool getCFProtectionBranch() const {
+    return InterruptCSRFrameIndexes.getFlag(2);
+  }
+  bool setCFProtectionBranch(bool Value) {
+    InterruptCSRFrameIndexes.setFlag(2, Value);
+    return Value;
+  }
 
 public:
   RISCVMachineFunctionInfo(const Function &F, const RISCVSubtarget *STI);
@@ -241,13 +258,13 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
   void addSExt32Register(Register Reg);
   bool isSExt32Register(Register Reg) const;
 
-  bool isVectorCall() const { return IsVectorCall; }
-  void setIsVectorCall() { IsVectorCall = true; }
+  bool isVectorCall() const { return getIsVectorCallFlag(); }
+  void setIsVectorCall() { setIsVectorCallFlag(true); }
 
-  bool hasDynamicAllocation() const { return HasDynamicAllocation; }
-  void setDynamicAllocation() { HasDynamicAllocation = true; }
+  bool hasDynamicAllocation() const { return getHasDynamicAllocation(); }
+  void setDynamicAllocation() { setHasDynamicAllocation(true); }
 
-  bool hasCFProtectionBranch() const { return CFProtectionBranch; }
+  bool hasCFProtectionBranch() const { return getCFProtectionBranch(); }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index a2e9fb2e2cca1..a878f0b21cf7c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -680,7 +680,7 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
                  .addDef(ResVReg)
                  .addUse(GR->getSPIRVTypeID(RetType))
                  .add(Info.Callee);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   for (const auto &Arg : Info.OrigArgs) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizeZeroSizeArrays.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizeZeroSizeArrays.cpp
index abbdfdfecf6c4..3ae36c39ae808 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizeZeroSizeArrays.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizeZeroSizeArrays.cpp
@@ -16,6 +16,7 @@
 #include "SPIRVUtils.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/InstVisitor.h"
@@ -78,8 +79,9 @@ class SPIRVLegalizeZeroSizeArraysImpl
   const SPIRVTargetMachine &TM;
   DenseMap<Type *, Type *> TypeMap;
   DenseMap<GlobalVariable *, GlobalVariable *> GlobalMap;
-  SmallVector<Instruction *, 16> ToErase;
-  bool Modified = false;
+  llvm::SmallVectorWithFlags<Instruction *, 16> ToErase;
+  bool getModified() const { return ToErase.getFlag(0); }
+  void setModified(bool Value) { ToErase.setFlag(0, Value); }
 };
 
 class SPIRVLegalizeZeroSizeArraysLegacy : public ModulePass {
@@ -205,7 +207,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitAllocaInst(AllocaInst &AI) {
   NewAI->setDebugLoc(AI.getDebugLoc());
   AI.replaceAllUsesWith(NewAI);
   ToErase.push_back(&AI);
-  Modified = true;
+  setModified(true);
 }
 
 void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(LoadInst &LI) {
@@ -217,7 +219,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitLoadInst(LoadInst &LI) {
   if (shouldLegalizeInstType(ArrTy)) {
     LI.replaceAllUsesWith(PoisonValue::get(LI.getType()));
     ToErase.push_back(&LI);
-    Modified = true;
+    setModified(true);
   }
 }
 
@@ -228,7 +230,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitStoreInst(StoreInst &SI) {
   ArrayType *ArrTy = dyn_cast<ArrayType>(StoreTy);
   if (shouldLegalizeInstType(ArrTy)) {
     ToErase.push_back(&SI);
-    Modified = true;
+    setModified(true);
   }
 }
 
@@ -241,7 +243,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitSelectInst(SelectInst &Sel) {
   if (shouldLegalizeInstType(ArrTy)) {
     Sel.replaceAllUsesWith(PoisonValue::get(Sel.getType()));
     ToErase.push_back(&Sel);
-    Modified = true;
+    setModified(true);
   }
 }
 
@@ -255,7 +257,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitExtractValueInst(
   if (shouldLegalizeInstType(ArrTy)) {
     EVI.replaceAllUsesWith(PoisonValue::get(EVI.getType()));
     ToErase.push_back(&EVI);
-    Modified = true;
+    setModified(true);
   }
 }
 
@@ -270,7 +272,7 @@ void SPIRVLegalizeZeroSizeArraysImpl::visitInsertValueInst(
   if (shouldLegalizeInstType(ArrTy)) {
     IVI.replaceAllUsesWith(IVI.getAggregateOperand());
     ToErase.push_back(&IVI);
-    Modified = true;
+    setModified(true);
   }
 }
 
@@ -278,7 +280,7 @@ bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(Module &M) {
   TypeMap.clear();
   GlobalMap.clear();
   ToErase.clear();
-  Modified = false;
+  setModified(false);
 
   // Runtime arrays are allowed for shaders, so we don't need to do anything.
   if (TM.getSubtargetImpl()->isShader())
@@ -321,7 +323,7 @@ bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(Module &M) {
     NewGV->setAlignment(GV.getAlign());
     GlobalMap[&GV] = NewGV;
     OldGlobals.push_back(&GV);
-    Modified = true;
+    setModified(true);
   }
 
   // Second pass: replace uses, transfer names, and erase old globals.
@@ -339,7 +341,7 @@ bool SPIRVLegalizeZeroSizeArraysImpl::runOnModule(Module &M) {
   for (Instruction *I : ToErase)
     I->eraseFromParent();
 
-  return Modified;
+  return getModified();
 }
 
 } // namespace
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
index 77d74f06ea5da..efdd0967f1688 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp
@@ -273,7 +273,7 @@ void SparcInstPrinter::printCTILabel(const MCInst *MI, uint64_t Address,
   // we're running the disassembler), just print the immediate.
   if (Op.isImm()) {
     int64_t Offset = Op.getImm();
-    if (PrintBranchImmAsAddress) {
+    if (getPrintBranchImmAsAddress()) {
       uint64_t Target = Address + Offset;
       if (STI.getTargetTriple().isSPARC32())
         Target &= 0xffffffff;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index a61f919582070..b3239b603b714 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -237,10 +237,11 @@ static unsigned toCallerWindow(unsigned Reg) {
   return Reg;
 }
 
-bool SparcTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool SparcTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                         MachineFunction &MF, bool isVarArg,
+                                         llvm::ArrayRef<ISD::OutputArg> Outs,
+                                         LLVMContext &Context,
+                                         const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, Subtarget->is64Bit() ? RetCC_Sparc64
@@ -250,7 +251,7 @@ bool SparcTargetLowering::CanLowerReturn(
 SDValue
 SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                  bool IsVarArg,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                 llvm::ArrayRef<ISD::OutputArg> Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SDLoc &DL, SelectionDAG &DAG) const {
   if (Subtarget->is64Bit())
@@ -261,7 +262,7 @@ SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 SDValue
 SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
                                     bool IsVarArg,
-                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    llvm::ArrayRef<ISD::OutputArg> Outs,
                                     const SmallVectorImpl<SDValue> &OutVals,
                                     const SDLoc &DL, SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
@@ -352,7 +353,7 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
 SDValue
 SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
                                     bool IsVarArg,
-                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    llvm::ArrayRef<ISD::OutputArg> Outs,
                                     const SmallVectorImpl<SDValue> &OutVals,
                                     const SDLoc &DL, SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to locations.
@@ -428,8 +429,8 @@ SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
 
 SDValue SparcTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   if (Subtarget->is64Bit())
     return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins,
                                    DL, DAG, InVals);
@@ -442,8 +443,8 @@ SDValue SparcTargetLowering::LowerFormalArguments(
 /// pass FP values in FP registers for fastcc functions.
 SDValue SparcTargetLowering::LowerFormalArguments_32(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
   SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
@@ -649,8 +650,8 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
 // Lower formal arguments for the 64 bit ABI.
 SDValue SparcTargetLowering::LowerFormalArguments_64(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
 
   // Analyze arguments according to CC_Sparc64.
@@ -846,14 +847,13 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
                                   SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &isTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool isVarArg                         = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
   MachineFunction &MF = DAG.getMachineFunction();
   LLVMContext &Ctx = *DAG.getContext();
   EVT PtrVT = getPointerTy(MF.getDataLayout());
@@ -864,8 +864,9 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
                  *DAG.getContext());
   CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
 
-  isTailCall = isTailCall && IsEligibleForTailCallOptimization(
-                                 CCInfo, CLI, DAG.getMachineFunction());
+  CLI.setIsTailCall(
+      CLI.getIsTailCall() &&
+      IsEligibleForTailCallOptimization(CCInfo, CLI, DAG.getMachineFunction()));
 
   // Get the size of the outgoing arguments stack space requirement.
   unsigned ArgsSize = CCInfo.getStackSize();
@@ -905,9 +906,9 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
     }
   }
 
-  assert(!isTailCall || ArgsSize == 0);
+  assert(!CLI.getIsTailCall() || ArgsSize == 0);
 
-  if (!isTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl);
 
   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
@@ -956,7 +957,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
     if (Flags.isSRet()) {
       assert(VA.needsCustom());
 
-      if (isTailCall)
+      if (CLI.getIsTailCall())
         continue;
 
       // store SRet argument in %sp+64
@@ -1114,7 +1115,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
   // stuck together.
   SDValue InGlue;
   for (const auto &[OrigReg, N] : RegsToPass) {
-    Register Reg = isTailCall ? OrigReg : toCallerWindow(OrigReg);
+    Register Reg = CLI.getIsTailCall() ? OrigReg : toCallerWindow(OrigReg);
     Chain = DAG.getCopyToReg(Chain, dl, Reg, N, InGlue);
     InGlue = Chain.getValue(1);
   }
@@ -1137,7 +1138,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
   if (hasStructRetAttr)
     Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32));
   for (const auto &[OrigReg, N] : RegsToPass) {
-    Register Reg = isTailCall ? OrigReg : toCallerWindow(OrigReg);
+    Register Reg = CLI.getIsTailCall() ? OrigReg : toCallerWindow(OrigReg);
     Ops.push_back(DAG.getRegister(Reg, N.getValueType()));
   }
 
@@ -1157,7 +1158,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
   if (InGlue.getNode())
     Ops.push_back(InGlue);
 
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     DAG.getMachineFunction().getFrameInfo().setHasTailCall();
     return DAG.getNode(SPISD::TAIL_CALL, dl, MVT::Other, Ops);
   }
@@ -1292,12 +1293,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
-  CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
-                 *DAG.getContext());
+  CCState CCInfo(CLI.CallConv, CLI.getIsVarArg(), DAG.getMachineFunction(),
+                 ArgLocs, *DAG.getContext());
   CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64);
 
-  CLI.IsTailCall = CLI.IsTailCall && IsEligibleForTailCallOptimization(
-                                         CCInfo, CLI, DAG.getMachineFunction());
+  CLI.setIsTailCall(
+      CLI.getIsTailCall() &&
+      IsEligibleForTailCallOptimization(CCInfo, CLI, DAG.getMachineFunction()));
 
   // Get the size of the outgoing arguments stack space requirement.
   // The stack offset computed by CC_Sparc64 includes all arguments.
@@ -1310,15 +1312,15 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
   ArgsSize = alignTo(ArgsSize, 16);
 
   // Varargs calls require special treatment.
-  if (CLI.IsVarArg)
+  if (CLI.getIsVarArg())
     fixupVariableFloatArgs(ArgLocs, CLI.Outs);
 
-  assert(!CLI.IsTailCall || ArgsSize == StackReserved);
+  assert(!CLI.getIsTailCall() || ArgsSize == StackReserved);
 
   // Adjust the stack pointer to make room for the arguments.
   // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
   // with more than 6 arguments.
-  if (!CLI.IsTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
 
   // Collect the set of registers to pass to the function and their values.
@@ -1382,7 +1384,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
 
         Register HiReg = VA.getLocReg();
         Register LoReg = VA.getLocReg() + 1;
-        if (!CLI.IsTailCall) {
+        if (!CLI.getIsTailCall()) {
           HiReg = toCallerWindow(HiReg);
           LoReg = toCallerWindow(LoReg);
         }
@@ -1411,7 +1413,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
       }
 
       Register Reg = VA.getLocReg();
-      if (!CLI.IsTailCall)
+      if (!CLI.getIsTailCall())
         Reg = toCallerWindow(Reg);
       RegsToPass.push_back(std::make_pair(Reg, Arg));
       continue;
@@ -1481,7 +1483,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
     Ops.push_back(InGlue);
 
   // Now the call itself.
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     DAG.getMachineFunction().getFrameInfo().setHasTailCall();
     return DAG.getNode(SPISD::TAIL_CALL, DL, MVT::Other, Ops);
   }
@@ -1498,8 +1500,8 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
-  CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
-                 *DAG.getContext());
+  CCState RVInfo(CLI.CallConv, CLI.getIsVarArg(), DAG.getMachineFunction(),
+                 RVLocs, *DAG.getContext());
 
   // Set inreg flag manually for codegen generated library calls that
   // return float.
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index b685b9ea9243e..3700738cd7643 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -86,17 +86,17 @@ namespace llvm {
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
     SDValue LowerFormalArguments_32(SDValue Chain, CallingConv::ID CallConv,
                                     bool isVarArg,
-                                    const SmallVectorImpl<ISD::InputArg> &Ins,
+                                    llvm::ArrayRef<ISD::InputArg> Ins,
                                     const SDLoc &dl, SelectionDAG &DAG,
                                     SmallVectorImpl<SDValue> &InVals) const;
     SDValue LowerFormalArguments_64(SDValue Chain, CallingConv::ID CallConv,
                                     bool isVarArg,
-                                    const SmallVectorImpl<ISD::InputArg> &Ins,
+                                    llvm::ArrayRef<ISD::InputArg> Ins,
                                     const SDLoc &dl, SelectionDAG &DAG,
                                     SmallVectorImpl<SDValue> &InVals) const;
 
@@ -109,22 +109,19 @@ namespace llvm {
                          SmallVectorImpl<SDValue> &InVals) const;
 
     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                        bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                         LLVMContext &Context, const Type *RetTy) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
     SDValue LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
-                           bool IsVarArg,
-                           const SmallVectorImpl<ISD::OutputArg> &Outs,
+                           bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                            const SmallVectorImpl<SDValue> &OutVals,
                            const SDLoc &DL, SelectionDAG &DAG) const;
     SDValue LowerReturn_64(SDValue Chain, CallingConv::ID CallConv,
-                           bool IsVarArg,
-                           const SmallVectorImpl<ISD::OutputArg> &Outs,
+                           bool IsVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                            const SmallVectorImpl<SDValue> &OutVals,
                            const SDLoc &DL, SelectionDAG &DAG) const;
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp
index 1e9936194c94a..dd3cb7f473f1c 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinterCommon.cpp
@@ -184,7 +184,7 @@ void SystemZInstPrinterCommon::printPCRelOperand(const MCInst *MI,
   // we're running the disassembler), just print the immediate.
   if (MO.isImm()) {
     int64_t Offset = MO.getImm();
-    if (PrintBranchImmAsAddress)
+    if (getPrintBranchImmAsAddress())
       markup(O, Markup::Target) << formatHex(Address + Offset);
     else
       markup(O, Markup::Immediate) << formatImm(Offset);
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 1813f9b97ceaa..72919764d33d4 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -933,7 +933,7 @@ bool SystemZVectorConstantInfo::isVectorConstantLegal(
     const SystemZSubtarget &Subtarget) {
   const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
   if (!Subtarget.hasVector() ||
-      (isFP128 && !Subtarget.hasVectorEnhancements1()))
+      (getIsFP128() && !Subtarget.hasVectorEnhancements1()))
     return false;
 
   // Try using VECTOR GENERATE BYTE MASK.  This is the architecturally-
@@ -2037,8 +2037,8 @@ SDValue SystemZTargetLowering::joinRegisterPartsIntoValue(
 
 // The first part of a split stack argument is at index I in Args (and
 // ArgLocs). Return the type of a part and the number of them by reference.
-template <class ArgTy>
-static bool analyzeArgSplit(const SmallVectorImpl<ArgTy> &Args,
+template <class ArgRangeT>
+static bool analyzeArgSplit(const ArgRangeT &Args,
                             SmallVector<CCValAssign, 16> &ArgLocs, unsigned I,
                             MVT &PartVT, unsigned &NumParts) {
   if (!Args[I].Flags.isSplit())
@@ -2059,8 +2059,8 @@ static bool analyzeArgSplit(const SmallVectorImpl<ArgTy> &Args,
 
 SDValue SystemZTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MachineRegisterInfo &MRI = MF.getRegInfo();
@@ -2261,7 +2261,7 @@ SDValue SystemZTargetLowering::LowerFormalArguments(
 
 static bool canUseSiblingCall(const CCState &ArgCCInfo,
                               SmallVectorImpl<CCValAssign> &ArgLocs,
-                              SmallVectorImpl<ISD::OutputArg> &Outs) {
+                              ArrayRef<ISD::OutputArg> Outs) {
   // Punt if there are any indirect or stack arguments, or if the call
   // needs the callee-saved argument register R6, or if the call uses
   // the callee-saved register arguments SwiftSelf and SwiftError.
@@ -2373,14 +2373,13 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                  SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   MachineFunction &MF = DAG.getMachineFunction();
   EVT PtrVT = getPointerTy(MF.getDataLayout());
   LLVMContext &Ctx = *DAG.getContext();
@@ -2388,7 +2387,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // FIXME: z/OS support to be added in later.
   if (Subtarget.isTargetXPLINK64())
-    IsTailCall = false;
+    CLI.setIsTailCall(false);
 
   // Integer args <=32 bits should have an extension attribute.
   verifyNarrowIntegerArgs_Call(Outs, &MF.getFunction(), Callee);
@@ -2400,14 +2399,14 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // We don't support GuaranteedTailCallOpt, only automatically-detected
   // sibling calls.
-  if (IsTailCall && !canUseSiblingCall(ArgCCInfo, ArgLocs, Outs))
-    IsTailCall = false;
+  if (CLI.getIsTailCall() && !canUseSiblingCall(ArgCCInfo, ArgLocs, Outs))
+    CLI.setIsTailCall(false);
 
   // Get a count of how many bytes are to be pushed on the stack.
   unsigned NumBytes = ArgCCInfo.getStackSize();
 
   // Mark the start of the call.
-  if (!IsTailCall)
+  if (!CLI.getIsTailCall())
     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
 
   // Copy argument values to their designated locations.
@@ -2524,7 +2523,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
     } else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
       Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT);
       Callee = DAG.getNode(SystemZISD::PCREL_WRAPPER, DL, PtrVT, Callee);
-    } else if (IsTailCall) {
+    } else if (CLI.getIsTailCall()) {
       Chain = DAG.getCopyToReg(Chain, DL, SystemZ::R1D, Callee, Glue);
       Glue = Chain.getValue(1);
       Callee = DAG.getRegister(SystemZ::R1D, Callee.getValueType());
@@ -2559,13 +2558,13 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
   // Emit the call.
   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
-  if (IsTailCall) {
+  if (CLI.getIsTailCall()) {
     SDValue Ret = DAG.getNode(SystemZISD::SIBCALL, DL, NodeTys, Ops);
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     return Ret;
   }
   Chain = DAG.getNode(SystemZISD::CALL, DL, NodeTys, Ops);
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   Glue = Chain.getValue(1);
 
   // Mark the end of the call, which is glued to the call itself.
@@ -2626,10 +2625,11 @@ std::pair<SDValue, SDValue> SystemZTargetLowering::makeExternalCall(
   return LowerCallTo(CLI);
 }
 
-bool SystemZTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool SystemZTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                           MachineFunction &MF, bool IsVarArg,
+                                           llvm::ArrayRef<ISD::OutputArg> Outs,
+                                           LLVMContext &Context,
+                                           const Type *RetTy) const {
   // Special case that we cannot easily detect in RetCC_SystemZ since
   // i128 may not be a legal type.
   for (auto &Out : Outs)
@@ -2644,7 +2644,7 @@ bool SystemZTargetLowering::CanLowerReturn(
 SDValue
 SystemZTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                    bool IsVarArg,
-                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                   llvm::ArrayRef<ISD::OutputArg> Outs,
                                    const SmallVectorImpl<SDValue> &OutVals,
                                    const SDLoc &DL, SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
@@ -11518,9 +11518,9 @@ bool SystemZTargetLowering::isInternal(const Function *Fn) const {
   return Itr->second;
 }
 
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                             const Function *F, SDValue Callee) const {
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Call(
+    llvm::ArrayRef<ISD::OutputArg> Outs, const Function *F,
+    SDValue Callee) const {
   // Temporarily only do the check when explicitly requested, until it can be
   // enabled by default.
   if (!EnableIntArgExtCheck)
@@ -11544,9 +11544,8 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
   }
 }
 
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                            const Function *F) const {
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Ret(
+    llvm::ArrayRef<ISD::OutputArg> Outs, const Function *F) const {
   // Temporarily only do the check when explicitly requested, until it can be
   // enabled by default.
   if (!EnableIntArgExtCheck)
@@ -11563,7 +11562,7 @@ verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
 // Verify that narrow integer arguments are extended as required by the ABI.
 // Return false if an error is found.
 bool SystemZTargetLowering::verifyNarrowIntegerArgs(
-    const SmallVectorImpl<ISD::OutputArg> &Outs) const {
+    llvm::ArrayRef<ISD::OutputArg> Outs) const {
   if (!Subtarget.isTargetELF())
     return true;
 
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 65463c48f3c4a..de04b23161940 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -16,6 +16,7 @@
 
 #include "SystemZ.h"
 #include "SystemZInstrInfo.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/LibcallLoweringInfo.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/SelectionDAG.h"
@@ -240,8 +241,7 @@ class SystemZTargetLowering : public TargetLowering {
       unsigned NumParts, MVT PartVT, EVT ValueVT,
       std::optional<CallingConv::ID> CC) const override;
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
   SDValue LowerCall(CallLoweringInfo &CLI,
@@ -257,12 +257,10 @@ class SystemZTargetLowering : public TargetLowering {
                      SDLoc DL, SDValue Chain, bool IsStrict) const;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
-                      LLVMContext &Context,
-                      const Type *RetTy) const override;
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
+                      LLVMContext &Context, const Type *RetTy) const override;
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
   SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
@@ -467,12 +465,11 @@ class SystemZTargetLowering : public TargetLowering {
 private:
   bool isInternal(const Function *Fn) const;
   mutable std::map<const Function *, bool> IsInternalCache;
-  void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
+  void verifyNarrowIntegerArgs_Call(llvm::ArrayRef<ISD::OutputArg> Outs,
                                     const Function *F, SDValue Callee) const;
-  void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
+  void verifyNarrowIntegerArgs_Ret(llvm::ArrayRef<ISD::OutputArg> Outs,
                                    const Function *F) const;
-  bool
-  verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs) const;
+  bool verifyNarrowIntegerArgs(llvm::ArrayRef<ISD::OutputArg> Outs) const;
 
 public:
 };
@@ -483,15 +480,17 @@ struct SystemZVectorConstantInfo {
   APInt SplatBits;           // Smallest splat value.
   APInt SplatUndef;          // Bits correspoding to undef operands of the BVN.
   unsigned SplatBitSize = 0;
-  bool isFP128 = false;
+  bool getIsFP128() const { return OpVals.getFlag(0); }
+  void setIsFP128(bool Value) { OpVals.setFlag(0, Value); }
+
 public:
   unsigned Opcode = 0;
-  SmallVector<unsigned, 2> OpVals;
+  llvm::SmallVectorWithFlags<unsigned, 2> OpVals;
   MVT VecVT;
   SystemZVectorConstantInfo(APInt IntImm);
   SystemZVectorConstantInfo(APFloat FPImm)
       : SystemZVectorConstantInfo(FPImm.bitcastToAPInt()) {
-    isFP128 = (&FPImm.getSemantics() == &APFloat::IEEEquad());
+    setIsFP128((&FPImm.getSemantics() == &APFloat::IEEEquad()));
   }
   SystemZVectorConstantInfo(BuildVectorSDNode *BVN);
   bool isVectorConstantLegal(const SystemZSubtarget &Subtarget);
diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp
index 6d9068ef579c6..5fa9025d0b8cd 100644
--- a/llvm/lib/Target/VE/VEISelLowering.cpp
+++ b/llvm/lib/Target/VE/VEISelLowering.cpp
@@ -65,10 +65,11 @@ CCAssignFn *getParamCC(CallingConv::ID CallConv, bool IsVarArg) {
   }
 }
 
-bool VETargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool VETargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                      MachineFunction &MF, bool IsVarArg,
+                                      llvm::ArrayRef<ISD::OutputArg> Outs,
+                                      LLVMContext &Context,
+                                      const Type *RetTy) const {
   CCAssignFn *RetCC = getReturnCC(CallConv);
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
@@ -362,12 +363,12 @@ void VETargetLowering::initVPUActions() {
   }
 }
 
-SDValue
-VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                              bool IsVarArg,
-                              const SmallVectorImpl<ISD::OutputArg> &Outs,
-                              const SmallVectorImpl<SDValue> &OutVals,
-                              const SDLoc &DL, SelectionDAG &DAG) const {
+SDValue VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                      bool IsVarArg,
+                                      llvm::ArrayRef<ISD::OutputArg> Outs,
+                                      const SmallVectorImpl<SDValue> &OutVals,
+                                      const SDLoc &DL,
+                                      SelectionDAG &DAG) const {
   // CCValAssign - represent the assignment of the return value to locations.
   SmallVector<CCValAssign, 16> RVLocs;
 
@@ -439,8 +440,8 @@ VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 
 SDValue VETargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
 
   // Get the base offset of the incoming arguments stack space.
@@ -580,7 +581,7 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   auto PtrVT = getPointerTy(DAG.getDataLayout());
 
   // VE target does not yet support tail call optimization.
-  CLI.IsTailCall = false;
+  CLI.setIsTailCall(false);
 
   // Get the base offset of the outgoing arguments stack space.
   unsigned ArgsBaseOffset = Subtarget->getRsaSize();
@@ -589,8 +590,8 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
-  CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
-                 *DAG.getContext());
+  CCState CCInfo(CLI.CallConv, CLI.getIsVarArg(), DAG.getMachineFunction(),
+                 ArgLocs, *DAG.getContext());
   // Allocate the preserved area first.
   CCInfo.AllocateStack(ArgsPreserved, Align(8));
   // We already allocated the preserved area, so the stack offset computed
@@ -599,11 +600,11 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // VE requires to use both register and stack for varargs or no-prototyped
   // functions.
-  bool UseBoth = CLI.IsVarArg;
+  bool UseBoth = CLI.getIsVarArg();
 
   // Analyze operands again if it is required to store BOTH.
   SmallVector<CCValAssign, 16> ArgLocs2;
-  CCState CCInfo2(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
+  CCState CCInfo2(CLI.CallConv, CLI.getIsVarArg(), DAG.getMachineFunction(),
                   ArgLocs2, *DAG.getContext());
   if (UseBoth)
     CCInfo2.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, true));
@@ -776,8 +777,8 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
-  CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
-                 *DAG.getContext());
+  CCState RVInfo(CLI.CallConv, CLI.getIsVarArg(), DAG.getMachineFunction(),
+                 RVLocs, *DAG.getContext());
 
   // Set inreg flag manually for codegen generated library calls that
   // return float.
diff --git a/llvm/lib/Target/VE/VEISelLowering.h b/llvm/lib/Target/VE/VEISelLowering.h
index 487804194757e..9eb54e89ba4c9 100644
--- a/llvm/lib/Target/VE/VEISelLowering.h
+++ b/llvm/lib/Target/VE/VEISelLowering.h
@@ -134,8 +134,7 @@ class VETargetLowering : public TargetLowering {
                          EVT VT) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &dl, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -143,12 +142,10 @@ class VETargetLowering : public TargetLowering {
                     SmallVectorImpl<SDValue> &InVals) const override;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
-                      LLVMContext &Context,
-                      const Type *RetTy) const override;
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> ArgsFlags,
+                      LLVMContext &Context, const Type *RetTy) const override;
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
index e5420fc1ef9d8..2dfcb74cd764a 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
@@ -46,7 +46,8 @@ namespace llvm {
 WebAssemblyAsmTypeCheck::WebAssemblyAsmTypeCheck(MCAsmParser &Parser,
                                                  const MCInstrInfo &MII,
                                                  bool Is64)
-    : Parser(Parser), MII(MII), Is64(Is64) {}
+    : Parser(Parser), MII(MII),
+      LocalTypes(decltype(this->LocalTypes)::withFlags(unsigned(Is64))) {}
 
 void WebAssemblyAsmTypeCheck::funcDecl(const wasm::WasmSignature &Sig) {
   LocalTypes.assign(Sig.Params.begin(), Sig.Params.end());
@@ -265,7 +266,7 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc,
     switch (SymRef->getSpecifier()) {
     case WebAssembly::S_GOT:
     case WebAssembly::S_GOT_TLS:
-      Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
+      Type = getIs64() ? wasm::ValType::I64 : wasm::ValType::I32;
       return false;
     default:
       break;
@@ -498,7 +499,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
   }
 
   if (Name == "memory.fill") {
-    Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
+    Type = getIs64() ? wasm::ValType::I64 : wasm::ValType::I32;
     bool Error = popType(ErrorLoc, Type);
     Error |= popType(ErrorLoc, wasm::ValType::I32);
     Error |= popType(ErrorLoc, Type);
@@ -506,7 +507,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
   }
 
   if (Name == "memory.copy") {
-    Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
+    Type = getIs64() ? wasm::ValType::I64 : wasm::ValType::I32;
     bool Error = popType(ErrorLoc, Type);
     Error |= popType(ErrorLoc, Type);
     Error |= popType(ErrorLoc, Type);
@@ -514,7 +515,7 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst,
   }
 
   if (Name == "memory.init") {
-    Type = Is64 ? wasm::ValType::I64 : wasm::ValType::I32;
+    Type = getIs64() ? wasm::ValType::I64 : wasm::ValType::I32;
     bool Error = popType(ErrorLoc, wasm::ValType::I32);
     Error |= popType(ErrorLoc, wasm::ValType::I32);
     Error |= popType(ErrorLoc, Type);
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
index e6fddf9806026..c2c04a222ab4b 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
@@ -16,6 +16,7 @@
 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_ASMPARSER_TYPECHECK_H
 #define LLVM_LIB_TARGET_WEBASSEMBLY_ASMPARSER_TYPECHECK_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCParser/MCAsmParser.h"
@@ -40,9 +41,10 @@ class WebAssemblyAsmTypeCheck final {
     bool IsLoop;
   };
   SmallVector<BlockInfo, 8> BlockInfoStack;
-  SmallVector<wasm::ValType, 16> LocalTypes;
+  llvm::SmallVectorWithFlags<wasm::ValType, 16> LocalTypes;
   wasm::WasmSignature LastSig;
-  bool Is64;
+  bool getIs64() const { return LocalTypes.getFlag(0); }
+  void setIs64(bool Value) { LocalTypes.setFlag(0, Value); }
 
   // checkTypes checks 'Types' against the value stack. popTypes checks 'Types'
   // against the value stack and also pops them.
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
index c8faeb7c7a40e..1e0cf2c05ceb0 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
@@ -440,7 +440,7 @@ bool WebAssemblyCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
     return false;
 
   CallInst = MIRBuilder.buildInstrNoInsert(WebAssembly::CALL);
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     CallInst.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   SmallVector<ArgInfo, 8> SplitArgs;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index b898dce8112b9..c6827113470d8 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -1304,21 +1304,21 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
     fail(DL, DAG,
          "WebAssembly doesn't support language-specific or target-specific "
          "calling conventions yet");
-  if (CLI.IsPatchPoint)
+  if (CLI.getIsPatchPointFlag())
     fail(DL, DAG, "WebAssembly doesn't support patch point yet");
 
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     auto NoTail = [&](const char *Msg) {
       if (CLI.CB && CLI.CB->isMustTailCall())
         fail(DL, DAG, Msg);
-      CLI.IsTailCall = false;
+      CLI.setIsTailCall(false);
     };
 
     if (!Subtarget->hasTailCall())
       NoTail("WebAssembly 'tail-call' feature not enabled");
 
     // Varargs calls cannot be tail calls because the buffer is on the stack
-    if (CLI.IsVarArg)
+    if (CLI.getIsVarArg())
       NoTail("WebAssembly does not support varargs tail calls");
 
     // Do not tail call unless caller and callee return types match
@@ -1365,8 +1365,8 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
       NoTail("WebAssembly does not support tail calling with byval arguments");
   }
 
-  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Ins = CLI.Ins;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
 
   // The generic code may have added an sret argument. If we're lowering an
@@ -1416,7 +1416,7 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
     NumFixedArgs += !Out.Flags.isVarArg();
   }
 
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
   auto PtrVT = getPointerTy(Layout);
 
   // For swiftcc and swifttailcc, emit additional swiftself, swifterror, and
@@ -1571,7 +1571,7 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
     Ops[0] = TableSet; // The new chain is the TableSet itself
   }
 
-  if (CLI.IsTailCall) {
+  if (CLI.getIsTailCall()) {
     // ret_calls do not return values to the current frame
     SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
     return DAG.getNode(WebAssemblyISD::RET_CALL, DL, NodeTys, Ops);
@@ -1590,7 +1590,7 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
 
 bool WebAssemblyTargetLowering::CanLowerReturn(
     CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext & /*Context*/,
+    llvm::ArrayRef<ISD::OutputArg> Outs, LLVMContext & /*Context*/,
     const Type *RetTy) const {
   // WebAssembly can only handle returning tuples with multivalue enabled
   return WebAssembly::canLowerReturn(Outs.size(), Subtarget);
@@ -1598,7 +1598,7 @@ bool WebAssemblyTargetLowering::CanLowerReturn(
 
 SDValue WebAssemblyTargetLowering::LowerReturn(
     SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
-    const SmallVectorImpl<ISD::OutputArg> &Outs,
+    llvm::ArrayRef<ISD::OutputArg> Outs,
     const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
     SelectionDAG &DAG) const {
   assert(WebAssembly::canLowerReturn(Outs.size(), Subtarget) &&
@@ -1628,8 +1628,8 @@ SDValue WebAssemblyTargetLowering::LowerReturn(
 
 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   if (!callingConvSupported(CallConv))
     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index 04e6d6f2d9367..ed82444ee2a27 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -81,16 +81,14 @@ class WebAssemblyTargetLowering final : public TargetLowering {
   SDValue LowerCall(CallLoweringInfo &CLI,
                     SmallVectorImpl<SDValue> &InVals) const override;
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
                       SelectionDAG &DAG) const override;
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool IsVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool IsVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
diff --git a/llvm/lib/Target/X86/GISel/X86CallLowering.cpp b/llvm/lib/Target/X86/GISel/X86CallLowering.cpp
index a2629c7281fc6..7ddbbe7724acd 100644
--- a/llvm/lib/Target/X86/GISel/X86CallLowering.cpp
+++ b/llvm/lib/Target/X86/GISel/X86CallLowering.cpp
@@ -347,7 +347,7 @@ bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   auto MIB = MIRBuilder.buildInstrNoInsert(CallOpc)
                  .add(Info.Callee)
                  .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
-  if (Info.NoMerge)
+  if (Info.getNoMerge())
     MIB.setMIFlag(MachineInstr::MIFlag::NoMerge);
 
   SmallVector<ArgInfo, 8> SplitArgs;
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
index 564636959f00f..cc6fd075150d5 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp
@@ -439,7 +439,7 @@ void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
                                           raw_ostream &O) {
   // Do not print the exact form of the memory operand if it references a known
   // binary object.
-  if (SymbolizeOperands && MIA) {
+  if (getSymbolizeOperands() && MIA) {
     uint64_t Target;
     if (MIA->evaluateBranch(*MI, 0, 0, Target))
       return;
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp
index 5f6e007fe6a87..04b640e0352b0 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp
@@ -356,12 +356,12 @@ void X86InstPrinterCommon::printRoundingControl(const MCInst *MI, unsigned Op,
 void X86InstPrinterCommon::printPCRelImm(const MCInst *MI, uint64_t Address,
                                          unsigned OpNo, raw_ostream &O) {
   // Do not print the numberic target address when symbolizing.
-  if (SymbolizeOperands)
+  if (getSymbolizeOperands())
     return;
 
   const MCOperand &Op = MI->getOperand(OpNo);
   if (Op.isImm()) {
-    if (PrintBranchImmAsAddress) {
+    if (getPrintBranchImmAsAddress()) {
       uint64_t Target = Address + Op.getImm();
       if (MAI.getCodePointerSize() == 4)
         Target &= 0xffffffff;
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp
index ff27005f52ea8..9df969b40cb31 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp
@@ -381,7 +381,7 @@ void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
                                             raw_ostream &O) {
   // Do not print the exact form of the memory operand if it references a known
   // binary object.
-  if (SymbolizeOperands && MIA) {
+  if (getSymbolizeOperands() && MIA) {
     uint64_t Target;
     if (MIA->evaluateBranch(*MI, 0, 0, Target))
       return;
diff --git a/llvm/lib/Target/X86/X86CallFrameOptimization.cpp b/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
index 3690a095987a8..4945dd3931d1e 100644
--- a/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
+++ b/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
@@ -25,6 +25,7 @@
 #include "X86Subtarget.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -75,13 +76,15 @@ class X86CallFrameOptimizationImpl {
     int64_t ExpectedDist = 0;
 
     // The sequence of storing instructions used to pass the parameters
-    SmallVector<MachineInstr *, 4> ArgStoreVector;
+    llvm::SmallVectorWithFlags<MachineInstr *, 4, 2> ArgStoreVector;
 
     // True if this call site has no stack parameters
-    bool NoStackParams = false;
+    bool getNoStackParams() const { return ArgStoreVector.getFlag(0); }
+    void setNoStackParams(bool Value) { ArgStoreVector.setFlag(0, Value); }
 
     // True if this call site can use push instructions
-    bool UsePush = false;
+    bool getUsePush() const { return ArgStoreVector.getFlag(1); }
+    void setUsePush(bool Value) { ArgStoreVector.setFlag(1, Value); }
   };
 
   typedef SmallVector<CallContext, 8> ContextVector;
@@ -212,10 +215,10 @@ bool X86CallFrameOptimizationImpl::isProfitable(MachineFunction &MF,
     // Call sites where no parameters are passed on the stack
     // do not affect the cost, since there needs to be no
     // stack adjustment.
-    if (CC.NoStackParams)
+    if (CC.getNoStackParams())
       continue;
 
-    if (!CC.UsePush) {
+    if (!CC.getUsePush()) {
       // If we don't use pushes for a particular call site,
       // we pay for not having a reserved call frame with an
       // additional sub/add esp pair. The cost is ~3 bytes per instruction,
@@ -271,7 +274,7 @@ bool X86CallFrameOptimizationImpl::runOnMachineFunction(MachineFunction &MF) {
     return false;
 
   for (const auto &CC : CallSeqVector) {
-    if (CC.UsePush) {
+    if (CC.getUsePush()) {
       adjustCallSequence(MF, CC);
       Changed = true;
     }
@@ -373,7 +376,7 @@ void X86CallFrameOptimizationImpl::collectCallInfo(
 
   // A zero adjustment means no stack parameters
   if (!MaxAdjust) {
-    Context.NoStackParams = true;
+    Context.setNoStackParams(true);
     return;
   }
 
@@ -490,7 +493,7 @@ void X86CallFrameOptimizationImpl::collectCallInfo(
     if (*MMI != nullptr)
       return;
 
-  Context.UsePush = true;
+  Context.setUsePush(true);
 }
 
 void X86CallFrameOptimizationImpl::adjustCallSequence(
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index b972949b5727e..e4e458f566361 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -768,12 +768,11 @@ namespace llvm {
 
     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
                             CallingConv::ID CallConv, bool isVarArg,
-                            const SmallVectorImpl<ISD::InputArg> &Ins,
-                            const SDLoc &dl, SelectionDAG &DAG,
-                            SmallVectorImpl<SDValue> &InVals,
+                            llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                            SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
                             uint32_t *RegMask) const;
     SDValue LowerMemArgument(SDValue Chain, CallingConv::ID CallConv,
-                             const SmallVectorImpl<ISD::InputArg> &ArgInfo,
+                             llvm::ArrayRef<ISD::InputArg> ArgInfo,
                              const SDLoc &dl, SelectionDAG &DAG,
                              const CCValAssign &VA, MachineFrameInfo &MFI,
                              unsigned i) const;
@@ -866,14 +865,14 @@ namespace llvm {
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
     SDValue LowerCall(CallLoweringInfo &CLI,
                       SmallVectorImpl<SDValue> &InVals) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
@@ -894,10 +893,8 @@ namespace llvm {
                             ISD::NodeType ExtendKind) const override;
 
     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                        bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
-                        LLVMContext &Context,
-                        const Type *RetTy) const override;
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
+                        LLVMContext &Context, const Type *RetTy) const override;
 
     const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override;
     ArrayRef<MCPhysReg> getRoundingControlRegisters() const override;
diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index af4ae285b8c70..7464a1df609d3 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -667,10 +667,11 @@ Value *X86TargetLowering::getSafeStackPointerLocation(
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool X86TargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool X86TargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                       MachineFunction &MF, bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       LLVMContext &Context,
+                                       const Type *RetTy) const {
   // Mingw64 GCC returns f128 via sret, and LLVM matches it for compatibility.
   // This logic exists for libcalls, a frontend should explicitly use sret
   // rather than rely on the sret demotion here.
@@ -778,12 +779,12 @@ static void Passv64i1ArgInRegs(
   RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Hi));
 }
 
-SDValue
-X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               const SmallVectorImpl<SDValue> &OutVals,
-                               const SDLoc &dl, SelectionDAG &DAG) const {
+SDValue X86TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+                                       bool isVarArg,
+                                       llvm::ArrayRef<ISD::OutputArg> Outs,
+                                       const SmallVectorImpl<SDValue> &OutVals,
+                                       const SDLoc &dl,
+                                       SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
   X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
 
@@ -1148,9 +1149,8 @@ static SDValue getPopFromX87Reg(SelectionDAG &DAG, SDValue Chain,
 ///
 SDValue X86TargetLowering::LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
-    uint32_t *RegMask) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals, uint32_t *RegMask) const {
 
   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
   // Assign locations to each value returned by this call.
@@ -1246,11 +1246,12 @@ SDValue X86TargetLowering::LowerCallResult(
 /// set of incoming args of a call, contains an sret pointer that the callee
 /// pops. This happens on most x86-32, System V platforms, unless register
 /// parameters are in use (-mregparm=1+, regcallcc, etc).
-template <typename T>
-static bool hasCalleePopSRet(const SmallVectorImpl<T> &Args,
+template <typename ArgRangeT>
+static bool hasCalleePopSRet(const ArgRangeT &Args,
                              const SmallVectorImpl<CCValAssign> &ArgLocs,
                              const X86Subtarget &Subtarget) {
   // Not C++20 (yet), so no concepts available.
+  using T = typename ArgRangeT::value_type;
   static_assert(std::is_same_v<T, ISD::OutputArg> ||
                     std::is_same_v<T, ISD::InputArg>,
                 "requires ISD::OutputArg or ISD::InputArg");
@@ -1329,12 +1330,10 @@ bool X86TargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
   return true;
 }
 
-SDValue
-X86TargetLowering::LowerMemArgument(SDValue Chain, CallingConv::ID CallConv,
-                                    const SmallVectorImpl<ISD::InputArg> &Ins,
-                                    const SDLoc &dl, SelectionDAG &DAG,
-                                    const CCValAssign &VA,
-                                    MachineFrameInfo &MFI, unsigned i) const {
+SDValue X86TargetLowering::LowerMemArgument(
+    SDValue Chain, CallingConv::ID CallConv, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG, const CCValAssign &VA,
+    MachineFrameInfo &MFI, unsigned i) const {
   // Create the nodes corresponding to a load from this parameter slot.
   ISD::ArgFlagsTy Flags = Ins[i].Flags;
   bool AlwaysUseMutable = shouldGuaranteeTCO(
@@ -1709,8 +1708,8 @@ void VarArgsLoweringHelper::lowerVarArgsParameters(SDValue &Chain,
 
 SDValue X86TargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
 
@@ -2089,14 +2088,13 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                              SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
   SDValue Callee                        = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool &isTailCall                      = CLI.IsTailCall;
-  bool isVarArg                         = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
   const auto *CB                        = CLI.CB;
 
   MachineFunction &MF = DAG.getMachineFunction();
@@ -2118,7 +2116,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   bool IsNoTrackIndirectCall = IsIndirectCall && CB->doesNoCfCheck() &&
                                M->getModuleFlag("cf-protection-branch");
   if (IsNoTrackIndirectCall)
-    isTailCall = false;
+    CLI.setIsTailCall(false);
 
   MachineFunction::CallSiteInfo CSInfo;
   if (CallConv == CallingConv::X86_INTR)
@@ -2150,9 +2148,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   }
 
   // We cannot guarantee TCO for mismatched calling conventions.
-  if (isTailCall && ShouldGuaranteeTCO) {
+  if (CLI.getIsTailCall() && ShouldGuaranteeTCO) {
     CallingConv::ID CallerCC = MF.getFunction().getCallingConv();
-    isTailCall = (CallConv == CallerCC);
+    CLI.setIsTailCall((CallConv == CallerCC));
   }
 
   // Check if this tail call is a "sibling" call, which is loosely defined to
@@ -2161,15 +2159,15 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // sibling calls to avoid unnecessary argument copies.
   bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
   bool IsSibcall = false;
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     IsSibcall = isEligibleForSiblingCallOpt(CLI, CCInfo, ArgLocs);
-    isTailCall = IsSibcall || IsMustTail || ShouldGuaranteeTCO;
+    CLI.setIsTailCall(IsSibcall || IsMustTail || ShouldGuaranteeTCO);
   }
 
-  if (isTailCall)
+  if (CLI.getIsTailCall())
     ++NumTailCalls;
 
-  if (IsMustTail && !isTailCall)
+  if (IsMustTail && !CLI.getIsTailCall())
     report_fatal_error("failed to perform tail call elimination on a call "
                        "site marked musttail");
 
@@ -2187,7 +2185,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   // A sibcall is ABI-compatible and does not need to adjust the stack pointer.
   int FPDiff = 0;
-  if (isTailCall && ShouldGuaranteeTCO && !IsSibcall) {
+  if (CLI.getIsTailCall() && ShouldGuaranteeTCO && !IsSibcall) {
     // Lower arguments at fp - stackoffset + fpdiff.
     unsigned NumBytesCallerPushed = X86Info->getBytesToPopOnReturn();
 
@@ -2215,7 +2213,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // temporary storage, and letting the register allocator spill if needed.
   SmallVector<SDValue, 8> ByValTemporaries;
   SDValue ByValTempChain;
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     // Use null SDValue to mean "no temporary recorded for this arg index".
     ByValTemporaries.assign(OutVals.size(), SDValue());
 
@@ -2288,7 +2286,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     if (ArgLocs.back().getLocMemOffset() != 0)
       report_fatal_error("any parameter with the inalloca attribute must be "
                          "the only memory argument");
-  } else if (CLI.IsPreallocated) {
+  } else if (CLI.getIsPreallocatedFlag()) {
     assert(ArgLocs.back().isMemLoc() &&
            "cannot use preallocated attribute on a register "
            "parameter");
@@ -2311,9 +2309,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   SDValue RetAddrFrIdx;
   // Load return address for tail calls.
-  if (isTailCall && FPDiff)
-    Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain, isTailCall,
-                                    Is64Bit, FPDiff, dl);
+  if (CLI.getIsTailCall() && FPDiff)
+    Chain = EmitTailCallLoadRetAddr(DAG, RetAddrFrIdx, Chain,
+                                    CLI.getIsTailCall(), Is64Bit, FPDiff, dl);
 
   SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
   SmallVector<SDValue, 8> MemOpChains;
@@ -2414,7 +2412,8 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
         if (ShadowReg)
           RegsToPass.push_back(std::make_pair(ShadowReg, Arg));
       }
-    } else if (!IsSibcall && (!isTailCall || (isByVal && !IsMustTail))) {
+    } else if (!IsSibcall &&
+               (!CLI.getIsTailCall() || (isByVal && !IsMustTail))) {
       assert(VA.isMemLoc());
       if (!StackPtr.getNode())
         StackPtr = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(),
@@ -2430,7 +2429,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   if (Subtarget.isPICStyleGOT()) {
     // ELF / PIC requires GOT in the EBX register before function calls via PLT
     // GOT pointer.
-    if (!isTailCall) {
+    if (!CLI.getIsTailCall()) {
       // Only PLT calls (GlobalAddress or ExternalSymbol) require the GOT in
       // EBX. Indirect calls through a register or an absolute address do not
       // go through the PLT and do not need EBX to hold the GOT base.
@@ -2492,7 +2491,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // For tail calls lower the arguments to the 'real' stack slots.  Sibcalls
   // don't need this because the eligibility check rejects calls that require
   // shuffling arguments passed in memory.
-  if (isTailCall && !IsSibcall) {
+  if (CLI.getIsTailCall() && !IsSibcall) {
     // Force all the incoming stack arguments to be loaded from the stack
     // before any new outgoing arguments or the return address are stored to the
     // stack, because the outgoing stack slots may alias the incoming argument
@@ -2608,7 +2607,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 
   SmallVector<SDValue, 8> Ops;
 
-  if (!IsSibcall && isTailCall && !IsMustTail) {
+  if (!IsSibcall && CLI.getIsTailCall() && !IsMustTail) {
     Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, 0, InGlue, dl);
     InGlue = Chain.getValue(1);
   }
@@ -2616,7 +2615,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   Ops.push_back(Chain);
   Ops.push_back(Callee);
 
-  if (isTailCall)
+  if (CLI.getIsTailCall())
     Ops.push_back(DAG.getSignedTargetConstant(FPDiff, dl, MVT::i32));
 
   // Add argument registers to the end of the list so that they are known live
@@ -2700,7 +2699,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   if (InGlue.getNode())
     Ops.push_back(InGlue);
 
-  if (isTailCall) {
+  if (CLI.getIsTailCall()) {
     // We used to do:
     //// If this is the first return lowered for this function, add the regs
     //// to the liveout set for the function.
@@ -2715,7 +2714,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     if (IsCFICall)
       Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue());
 
-    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
+    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.getNoMerge());
     DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
     return Ret;
   }
@@ -2732,7 +2731,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     // Calls with a "clang.arc.attachedcall" bundle are special. They should be
     // expanded to the call, directly followed by a special marker sequence and
     // a call to a ObjC library function. Use the CALL_RVMARKER to do that.
-    assert(!isTailCall &&
+    assert(!CLI.getIsTailCall() &&
            "tail calls cannot be marked with clang.arc.attachedcall");
     assert(Is64Bit && "clang.arc.attachedcall is only supported in 64bit mode");
 
@@ -2751,7 +2750,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
 
   InGlue = Chain.getValue(1);
-  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
+  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.getNoMerge());
   DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
 
   // Save heapallocsite metadata.
@@ -2977,12 +2976,12 @@ bool X86TargetLowering::isEligibleForSiblingCallOpt(
     TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo,
     SmallVectorImpl<CCValAssign> &ArgLocs) const {
   SelectionDAG &DAG = CLI.DAG;
-  const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  const auto &Outs = CLI.Outs;
   const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
-  const SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  const auto &Ins = CLI.Ins;
   SDValue Callee = CLI.Callee;
   CallingConv::ID CalleeCC = CLI.CallConv;
-  bool isVarArg = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
 
   if (!mayTailCallThisCC(CalleeCC))
     return false;
diff --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
index 1cfe86d57071f..87c4da1a67737 100644
--- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h
+++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -118,11 +119,9 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   unsigned NumLocalDynamics = 0;
   /// HasPushSequences - Keeps track of whether this function uses sequences
   /// of pushes to pass function parameters.
-  bool HasPushSequences = false;
 
   /// True if the function recovers from an SEH exception, and therefore needs
   /// to spill and restore the frame pointer.
-  bool HasSEHFramePtrSave = false;
 
   /// The frame index of a stack object containing the original frame pointer
   /// used to address arguments in a function using a base pointer.
@@ -147,7 +146,6 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   /// Whether this function has an extended frame record [Ctx, RBP, Return
   /// addr]. If so, bit 60 of the in-memory frame pointer will be 1 to enable
   /// other tools to detect the extended record.
-  bool HasSwiftAsyncContext = false;
 
   /// Candidate registers for push2/pop2
   std::set<Register> CandidatesForPush2Pop2;
@@ -155,7 +153,6 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   /// True if this function has CFI directives that adjust the CFA.
   /// This is used to determine if we should direct the debugger to use
   /// the CFA instead of the stack pointer.
-  bool HasCFIAdjustCfa = false;
 
   MachineInstr *StackPtrSaveMI = nullptr;
 
@@ -164,14 +161,11 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   // Preallocated fields are only used during isel.
   // FIXME: Can we find somewhere else to store these?
   DenseMap<const Value *, size_t> PreallocatedIds;
-  SmallVector<size_t, 0> PreallocatedStackSizes;
-  SmallVector<SmallVector<size_t, 4>, 0> PreallocatedArgOffsets;
+  llvm::SmallVectorWithFlags<size_t, 0, 4> PreallocatedStackSizes;
+  llvm::SmallVectorWithFlags<SmallVector<size_t, 4>, 0, 4>
+      PreallocatedArgOffsets;
 
   // True if a function clobbers FP/BP according to its calling convention.
-  bool FPClobberedByCall = false;
-  bool BPClobberedByCall = false;
-  bool FPClobberedByInvoke = false;
-  bool BPClobberedByInvoke = false;
 
 private:
   /// ForwardedMustTailRegParms - A list of virtual and physical registers
@@ -194,8 +188,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   bool getForceFramePointer() const { return ForceFramePointer;}
   void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
 
-  bool getHasPushSequences() const { return HasPushSequences; }
-  void setHasPushSequences(bool HasPush) { HasPushSequences = HasPush; }
+  bool getHasPushSequences() const { return PreallocatedArgOffsets.getFlag(0); }
+  void setHasPushSequences(bool HasPush) {
+    PreallocatedArgOffsets.setFlag(0, HasPush);
+  }
 
   bool getRestoreBasePointer() const { return RestoreBasePointerOffset!=0; }
   void setRestoreBasePointer(const MachineFunction *MF);
@@ -247,8 +243,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   unsigned getNumLocalDynamicTLSAccesses() const { return NumLocalDynamics; }
   void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamics; }
 
-  bool getHasSEHFramePtrSave() const { return HasSEHFramePtrSave; }
-  void setHasSEHFramePtrSave(bool V) { HasSEHFramePtrSave = V; }
+  bool getHasSEHFramePtrSave() const {
+    return PreallocatedArgOffsets.getFlag(1);
+  }
+  void setHasSEHFramePtrSave(bool V) { PreallocatedArgOffsets.setFlag(1, V); }
 
   int getSEHFramePtrSaveIndex() const { return SEHFramePtrSaveIndex; }
   void setSEHFramePtrSaveIndex(int Index) { SEHFramePtrSaveIndex = Index; }
@@ -276,8 +274,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
   bool hasPreallocatedCall() const { return HasPreallocatedCall; }
   void setHasPreallocatedCall(bool v) { HasPreallocatedCall = v; }
 
-  bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; }
-  void setHasSwiftAsyncContext(bool v) { HasSwiftAsyncContext = v; }
+  bool hasSwiftAsyncContext() const {
+    return PreallocatedArgOffsets.getFlag(2);
+  }
+  void setHasSwiftAsyncContext(bool v) { PreallocatedArgOffsets.setFlag(2, v); }
 
   bool isCandidateForPush2Pop2(Register Reg) const {
     return CandidatesForPush2Pop2.find(Reg) != CandidatesForPush2Pop2.end();
@@ -289,8 +289,8 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
     return CandidatesForPush2Pop2.size();
   }
 
-  bool hasCFIAdjustCfa() const { return HasCFIAdjustCfa; }
-  void setHasCFIAdjustCfa(bool v) { HasCFIAdjustCfa = v; }
+  bool hasCFIAdjustCfa() const { return PreallocatedArgOffsets.getFlag(3); }
+  void setHasCFIAdjustCfa(bool v) { PreallocatedArgOffsets.setFlag(3, v); }
 
   void setStackPtrSaveMI(MachineInstr *MI) { StackPtrSaveMI = MI; }
   MachineInstr *getStackPtrSaveMI() const { return StackPtrSaveMI; }
@@ -327,17 +327,25 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
     return PreallocatedArgOffsets[Id];
   }
 
-  bool getFPClobberedByCall() const { return FPClobberedByCall; }
-  void setFPClobberedByCall(bool C) { FPClobberedByCall = C; }
+  bool getFPClobberedByCall() const {
+    return PreallocatedStackSizes.getFlag(0);
+  }
+  void setFPClobberedByCall(bool C) { PreallocatedStackSizes.setFlag(0, C); }
 
-  bool getBPClobberedByCall() const { return BPClobberedByCall; }
-  void setBPClobberedByCall(bool C) { BPClobberedByCall = C; }
+  bool getBPClobberedByCall() const {
+    return PreallocatedStackSizes.getFlag(1);
+  }
+  void setBPClobberedByCall(bool C) { PreallocatedStackSizes.setFlag(1, C); }
 
-  bool getFPClobberedByInvoke() const { return FPClobberedByInvoke; }
-  void setFPClobberedByInvoke(bool C) { FPClobberedByInvoke = C; }
+  bool getFPClobberedByInvoke() const {
+    return PreallocatedStackSizes.getFlag(2);
+  }
+  void setFPClobberedByInvoke(bool C) { PreallocatedStackSizes.setFlag(2, C); }
 
-  bool getBPClobberedByInvoke() const { return BPClobberedByInvoke; }
-  void setBPClobberedByInvoke(bool C) { BPClobberedByInvoke = C; }
+  bool getBPClobberedByInvoke() const {
+    return PreallocatedStackSizes.getFlag(3);
+  }
+  void setBPClobberedByInvoke(bool C) { PreallocatedStackSizes.setFlag(3, C); }
 };
 
 } // End llvm namespace
diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp
index 8b193cfab7a74..8be8406eee3d2 100644
--- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp
@@ -904,17 +904,16 @@ XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG                     = CLI.DAG;
   SDLoc &dl                             = CLI.DL;
-  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
-  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain                         = CLI.Chain;
-  SDValue Callee                        = CLI.Callee;
-  bool &isTailCall                      = CLI.IsTailCall;
+  SDValue Callee = CLI.Callee;
   CallingConv::ID CallConv              = CLI.CallConv;
-  bool isVarArg                         = CLI.IsVarArg;
+  bool isVarArg = CLI.getIsVarArg();
 
   // XCore target does not yet support tail call optimization.
-  isTailCall = false;
+  CLI.setIsTailCall(false);
 
   // For now, only CallingConv::C implemented
   switch (CallConv)
@@ -923,8 +922,9 @@ XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
       report_fatal_error("Unsupported calling convention");
     case CallingConv::Fast:
     case CallingConv::C:
-      return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
-                            Outs, OutVals, Ins, dl, DAG, InVals);
+      return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg,
+                            CLI.getIsTailCall(), Outs, OutVals, Ins, dl, DAG,
+                            InVals);
   }
 }
 
@@ -977,10 +977,10 @@ static SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
 /// TODO: isTailCall, sret.
 SDValue XCoreTargetLowering::LowerCCCCallTo(
     SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
-    bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
-    const SmallVectorImpl<SDValue> &OutVals,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    bool isTailCall, llvm::ArrayRef<ISD::OutputArg> Outs,
+    const SmallVectorImpl<SDValue> &OutVals, llvm::ArrayRef<ISD::InputArg> Ins,
+    const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -1107,8 +1107,8 @@ namespace {
 /// XCore formal arguments implementation
 SDValue XCoreTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   switch (CallConv)
   {
     default:
@@ -1126,8 +1126,8 @@ SDValue XCoreTargetLowering::LowerFormalArguments(
 /// TODO: sret
 SDValue XCoreTargetLowering::LowerCCCArguments(
     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
@@ -1282,11 +1282,11 @@ SDValue XCoreTargetLowering::LowerCCCArguments(
 //               Return Value Calling Convention Implementation
 //===----------------------------------------------------------------------===//
 
-bool XCoreTargetLowering::
-CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-               bool isVarArg,
-               const SmallVectorImpl<ISD::OutputArg> &Outs,
-               LLVMContext &Context, const Type *RetTy) const {
+bool XCoreTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                         MachineFunction &MF, bool isVarArg,
+                                         llvm::ArrayRef<ISD::OutputArg> Outs,
+                                         LLVMContext &Context,
+                                         const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
   if (!CCInfo.CheckReturn(Outs, RetCC_XCore))
@@ -1299,7 +1299,7 @@ CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
 SDValue
 XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                  bool isVarArg,
-                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                 llvm::ArrayRef<ISD::OutputArg> Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SDLoc &dl, SelectionDAG &DAG) const {
 
diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.h b/llvm/lib/Target/XCore/XCoreISelLowering.h
index a965fe93f093b..eeeb4e24ec821 100644
--- a/llvm/lib/Target/XCore/XCoreISelLowering.h
+++ b/llvm/lib/Target/XCore/XCoreISelLowering.h
@@ -80,17 +80,15 @@ namespace llvm {
 
     // Lower Operand helpers
     SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv,
-                              bool isVarArg,
-                              const SmallVectorImpl<ISD::InputArg> &Ins,
+                              bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                               const SDLoc &dl, SelectionDAG &DAG,
                               SmallVectorImpl<SDValue> &InVals) const;
     SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
                            CallingConv::ID CallConv, bool isVarArg,
-                           bool isTailCall,
-                           const SmallVectorImpl<ISD::OutputArg> &Outs,
+                           bool isTailCall, llvm::ArrayRef<ISD::OutputArg> Outs,
                            const SmallVectorImpl<SDValue> &OutVals,
-                           const SmallVectorImpl<ISD::InputArg> &Ins,
-                           const SDLoc &dl, SelectionDAG &DAG,
+                           llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                           SelectionDAG &DAG,
                            SmallVectorImpl<SDValue> &InVals) const;
     SDValue getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
                                     SelectionDAG &DAG) const;
@@ -139,8 +137,8 @@ namespace llvm {
 
     SDValue
     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
+                         llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &dl,
+                         SelectionDAG &DAG,
                          SmallVectorImpl<SDValue> &InVals) const override;
 
     SDValue
@@ -148,13 +146,12 @@ namespace llvm {
                 SmallVectorImpl<SDValue> &InVals) const override;
 
     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &Outs,
+                        llvm::ArrayRef<ISD::OutputArg> Outs,
                         const SmallVectorImpl<SDValue> &OutVals,
                         const SDLoc &dl, SelectionDAG &DAG) const override;
 
     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                        bool isVarArg,
-                        const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
+                        bool isVarArg, llvm::ArrayRef<ISD::OutputArg> ArgsFlags,
                         LLVMContext &Context, const Type *RetTy) const override;
   };
 }
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
index 083e4ecaf93a5..615c85de4767b 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp
@@ -123,7 +123,7 @@ void XtensaInstPrinter::printCallOperand(const MCInst *MI, uint64_t Address,
   const MCOperand &MC = MI->getOperand(OpNum);
   if (MC.isImm()) {
     int64_t Val = MC.getImm() + 4;
-    if (PrintBranchImmAsAddress) {
+    if (getPrintBranchImmAsAddress()) {
       uint64_t Target = Address;
       Target &= ~0x3;
       Target += Val & (~0x3);
@@ -145,7 +145,7 @@ void XtensaInstPrinter::printL32RTarget(const MCInst *MI, uint64_t Address,
   const MCOperand &MC = MI->getOperand(OpNum);
   if (MC.isImm()) {
     int64_t Value = MI->getOperand(OpNum).getImm();
-    if (PrintBranchImmAsAddress) {
+    if (getPrintBranchImmAsAddress()) {
       uint64_t Target = (Address + 0x3) & (~0x3);
       Value &= ~0x3;
       Target += Value;
@@ -166,7 +166,7 @@ void XtensaInstPrinter::printL32RTarget(const MCInst *MI, uint64_t Address,
 
 void XtensaInstPrinter::printPCRelImm(uint64_t Address, int64_t Offset,
                                       raw_ostream &O) {
-  if (PrintBranchImmAsAddress) {
+  if (getPrintBranchImmAsAddress()) {
     uint64_t Target = Address + Offset;
     Target &= 0xffffffff;
     O << formatHex(Target);
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 59e356da1fdc8..ece27651ee215 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -469,8 +469,8 @@ CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
 
 SDValue XtensaTargetLowering::LowerFormalArguments(
     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+    llvm::ArrayRef<ISD::InputArg> Ins, const SDLoc &DL, SelectionDAG &DAG,
+    SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   XtensaMachineFunctionInfo *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
@@ -618,21 +618,20 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                 SmallVectorImpl<SDValue> &InVals) const {
   SelectionDAG &DAG = CLI.DAG;
   SDLoc &DL = CLI.DL;
-  SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
+  auto &Outs = CLI.Outs;
   SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
-  SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
+  auto &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool IsVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.getIsVarArg();
 
   MachineFunction &MF = DAG.getMachineFunction();
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   const TargetFrameLowering *TFL = Subtarget.getFrameLowering();
 
   // TODO: Support tail call optimization.
-  IsTailCall = false;
+  CLI.setIsTailCall(false);
 
   // Analyze the operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -666,7 +665,7 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
       assert(VA.isMemLoc());
       assert(Flags.getByValSize() &&
              "ByVal args of size 0 should have been ignored by front-end.");
-      assert(!IsTailCall &&
+      assert(!CLI.getIsTailCall() &&
              "Do not tail-call optimize if there is a byval argument.");
 
       if (!StackPtr.getNode())
@@ -803,10 +802,11 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   return Chain;
 }
 
-bool XtensaTargetLowering::CanLowerReturn(
-    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
-    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
-    const Type *RetTy) const {
+bool XtensaTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
+                                          MachineFunction &MF, bool IsVarArg,
+                                          llvm::ArrayRef<ISD::OutputArg> Outs,
+                                          LLVMContext &Context,
+                                          const Type *RetTy) const {
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
   return CCInfo.CheckReturn(Outs, RetCC_Xtensa);
@@ -815,7 +815,7 @@ bool XtensaTargetLowering::CanLowerReturn(
 SDValue
 XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                   bool IsVarArg,
-                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                  llvm::ArrayRef<ISD::OutputArg> Outs,
                                   const SmallVectorImpl<SDValue> &OutVals,
                                   const SDLoc &DL, SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index f62cf70a6fbb1..03d8c0885236a 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -72,8 +72,7 @@ class XtensaTargetLowering : public TargetLowering {
   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
 
   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
-                               bool isVarArg,
-                               const SmallVectorImpl<ISD::InputArg> &Ins,
+                               bool isVarArg, llvm::ArrayRef<ISD::InputArg> Ins,
                                const SDLoc &DL, SelectionDAG &DAG,
                                SmallVectorImpl<SDValue> &InVals) const override;
 
@@ -81,12 +80,11 @@ class XtensaTargetLowering : public TargetLowering {
                     SmallVectorImpl<SDValue> &InVals) const override;
 
   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
-                      bool isVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      bool isVarArg, llvm::ArrayRef<ISD::OutputArg> Outs,
                       LLVMContext &Context, const Type *RetTy) const override;
 
   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
-                      const SmallVectorImpl<ISD::OutputArg> &Outs,
+                      llvm::ArrayRef<ISD::OutputArg> Outs,
                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
                       SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Transforms/Coroutines/SpillUtils.cpp b/llvm/lib/Transforms/Coroutines/SpillUtils.cpp
index 5078b3a026ae1..67d5a1bba006a 100644
--- a/llvm/lib/Transforms/Coroutines/SpillUtils.cpp
+++ b/llvm/lib/Transforms/Coroutines/SpillUtils.cpp
@@ -409,7 +409,7 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
     if (DT.dominates(CoroShape.CoroBegin, &I) || !usedAfterCoroBegin(I))
       return;
 
-    if (!IsOffsetKnown) {
+    if (!isOffsetKnown()) {
       AliasOffetMap[&I].reset();
     } else {
       auto [Itr, Inserted] = AliasOffetMap.try_emplace(&I, Offset);
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 9e44f0d657794..36502ec642ddb 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -3236,7 +3236,7 @@ void InformationCache::initializeInformationCache(const Function &CF,
   // initialize the cache eagerly which would look the same to the users.
   Function &F = const_cast<Function &>(CF);
 
-  FI.IsKernel = F.hasFnAttribute("kernel");
+  FI.setIsKernel(F.hasFnAttribute("kernel"));
 
   // Walk all instructions to find interesting instructions that might be
   // queried by abstract attributes during their initialization or update.
@@ -3289,10 +3289,10 @@ void InformationCache::initializeInformationCache(const Function &CF,
         fillMapFromAssume(*Assume, KnowledgeMap);
         AddToAssumeUsesMap(*Assume->getArgOperand(0));
       } else if (cast<CallInst>(I).isMustTailCall()) {
-        FI.ContainsMustTailCall = true;
+        FI.setContainsMustTailCall(true);
         if (auto *Callee = dyn_cast_if_present<Function>(
                 cast<CallInst>(I).getCalledOperand()))
-          getFunctionInfo(*Callee).CalledViaMustTail = true;
+          getFunctionInfo(*Callee).setCalledViaMustTail(true);
       }
       [[fallthrough]];
     case Instruction::CallBr:
@@ -3396,11 +3396,11 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
   // determine if it is part of a must-tail call edge. This will influence what
   // attributes we can derive.
   InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F);
-  if (!isModulePass() && !FI.CalledViaMustTail) {
+  if (!isModulePass() && !FI.getCalledViaMustTail()) {
     for (const Use &U : F.uses())
       if (const auto *CB = dyn_cast<CallBase>(U.getUser()))
         if (CB->isCallee(&U) && CB->isMustTailCall())
-          FI.CalledViaMustTail = true;
+          FI.setCalledViaMustTail(true);
   }
 
   IRPosition FPos = IRPosition::function(F);
diff --git a/llvm/lib/Transforms/IPO/BlockExtractor.cpp b/llvm/lib/Transforms/IPO/BlockExtractor.cpp
index 9bede77c8ac89..4d5377a029393 100644
--- a/llvm/lib/Transforms/IPO/BlockExtractor.cpp
+++ b/llvm/lib/Transforms/IPO/BlockExtractor.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/Transforms/IPO/BlockExtractor.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
@@ -41,7 +42,9 @@ static cl::opt<bool>
 namespace {
 class BlockExtractor {
 public:
-  BlockExtractor(bool EraseFunctions) : EraseFunctions(EraseFunctions) {}
+  BlockExtractor(bool EraseFunctions)
+      : BlocksByName(
+            decltype(BlocksByName)::withFlags(unsigned(EraseFunctions))) {}
   bool runOnModule(Module &M);
   void
   init(const std::vector<std::vector<BasicBlock *>> &GroupsOfBlocksToExtract) {
@@ -52,9 +55,11 @@ class BlockExtractor {
 
 private:
   std::vector<std::vector<BasicBlock *>> GroupsOfBlocks;
-  bool EraseFunctions;
+  bool getEraseFunctions() const { return BlocksByName.getFlag(0); }
+  void setEraseFunctions(bool Value) { BlocksByName.setFlag(0, Value); }
   /// Map a function name to groups of blocks.
-  SmallVector<std::pair<std::string, SmallVector<std::string, 4>>, 4>
+  llvm::SmallVectorWithFlags<
+      std::pair<std::string, SmallVector<std::string, 4>>, 4>
       BlocksByName;
 
   void loadFile();
@@ -181,7 +186,7 @@ bool BlockExtractor::runOnModule(Module &M) {
   }
 
   // Erase the functions.
-  if (EraseFunctions || BlockExtractorEraseFuncs) {
+  if (getEraseFunctions() || BlockExtractorEraseFuncs) {
     for (Function *F : Functions) {
       LLVM_DEBUG(dbgs() << "BlockExtractor: Trying to delete " << F->getName()
                         << "\n");
diff --git a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
index 97183c76a079b..36f5a7cd519c6 100644
--- a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
+++ b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Transforms/IPO/HotColdSplitting.h"
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
@@ -464,7 +465,7 @@ class OutliningRegion {
   /// A list of (block, score) pairs. A block's score is non-zero iff it's a
   /// viable sub-region entry point. Blocks with higher scores are better entry
   /// points (i.e. they are more distant ancestors of the sink block).
-  SmallVector<BlockTy, 0> Blocks = {};
+  llvm::SmallVectorWithFlags<BlockTy, 0> Blocks = {};
 
   /// The suggested entry point into the region. If the region has multiple
   /// entry points, all blocks within the region may not be reachable from this
@@ -472,7 +473,8 @@ class OutliningRegion {
   BasicBlock *SuggestedEntryPoint = nullptr;
 
   /// Whether the entire function is cold.
-  bool EntireFunctionCold = false;
+  bool getEntireFunctionCold() const { return Blocks.getFlag(0); }
+  void setEntireFunctionCold(bool Value) { Blocks.setFlag(0, Value); }
 
   /// If \p BB is a viable entry point, return \p Score. Return 0 otherwise.
   static unsigned getEntryPointScore(BasicBlock &BB, unsigned Score) {
@@ -521,7 +523,7 @@ class OutliningRegion {
       // If the predecessor is cold and has no predecessors, the entire
       // function must be cold.
       if (SinkPostDom && pred_empty(&PredBB)) {
-        ColdRegion->EntireFunctionCold = true;
+        ColdRegion->setEntireFunctionCold(true);
         return Regions;
       }
 
@@ -554,7 +556,7 @@ class OutliningRegion {
     if (mayExtractBlock(SinkBB)) {
       addBlockToRegion(&SinkBB, SinkScore);
       if (pred_empty(&SinkBB)) {
-        ColdRegion->EntireFunctionCold = true;
+        ColdRegion->setEntireFunctionCold(true);
         return Regions;
       }
     } else {
@@ -600,7 +602,7 @@ class OutliningRegion {
   ArrayRef<std::pair<BasicBlock *, unsigned>> blocks() const { return Blocks; }
 
   /// Whether the entire function containing this region is cold.
-  bool isEntireFunctionCold() const { return EntireFunctionCold; }
+  bool isEntireFunctionCold() const { return getEntireFunctionCold(); }
 
   /// Remove a sub-region from this region and return it as a block sequence.
   BlockSequence takeSingleEntrySubRegion(DominatorTree &DT) {
diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp
index 18a3c86dcfe71..25b938e0f3382 100644
--- a/llvm/lib/Transforms/IPO/Instrumentor.cpp
+++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp
@@ -391,7 +391,7 @@ bool InstrumentorImpl::instrumentFunction(Function &Fn) {
   Value *FPtr = &Fn;
   for (auto &[Name, IO] :
        IConf.IChoices[InstrumentationLocation::FUNCTION_PRE]) {
-    if (!IO->Enabled)
+    if (!IO->getEnabled())
       continue;
     // Count epochs eagerly.
     ++IIRB.Epoch;
@@ -405,7 +405,7 @@ bool InstrumentorImpl::instrumentFunction(Function &Fn) {
 
   for (auto &[Name, IO] :
        IConf.IChoices[InstrumentationLocation::FUNCTION_POST]) {
-    if (!IO->Enabled)
+    if (!IO->getEnabled())
       continue;
     // Count epochs eagerly.
     ++IIRB.Epoch;
@@ -459,7 +459,7 @@ bool InstrumentorImpl::instrumentModule() {
     Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
     for (auto &ChoiceIt : IConf.IChoices[Loc]) {
       auto *IO = ChoiceIt.second;
-      if (!IO->Enabled)
+      if (!IO->getEnabled())
         continue;
       if (!YtorFn) {
         YtorFn = CreateYtor(IsPRE);
@@ -483,7 +483,7 @@ bool InstrumentorImpl::instrumentModule() {
     Function *&YtorFn = IsPRE ? CtorFn : DtorFn;
     for (auto &ChoiceIt : IConf.IChoices[Loc]) {
       auto *IO = ChoiceIt.second;
-      if (!IO->Enabled)
+      if (!IO->getEnabled())
         continue;
       if (!YtorFn) {
         YtorFn = CreateYtor(IsPRE);
@@ -530,11 +530,11 @@ bool InstrumentorImpl::instrument() {
 
   for (auto &[Name, IO] :
        IConf.IChoices[InstrumentationLocation::INSTRUCTION_PRE])
-    if (IO->Enabled)
+    if (IO->getEnabled())
       RegisterForAllOpcodes(InstChoicesPRE, IO);
   for (auto &[Name, IO] :
        IConf.IChoices[InstrumentationLocation::INSTRUCTION_POST])
-    if (IO->Enabled)
+    if (IO->getEnabled())
       RegisterForAllOpcodes(InstChoicesPOST, IO);
   Changed |= instrumentModule();
 
@@ -692,7 +692,7 @@ InstrumentationConfig::getBasePointerInfo(Value &V,
 
   auto *BPIO =
       IChoices[InstrumentationLocation::SPECIAL_VALUE]["base_pointer_info"];
-  if (!BPIO || !BPIO->Enabled) {
+  if (!BPIO || !BPIO->getEnabled()) {
     IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation(
         "Base pointer info disabled but required, passing nullptr.",
         DS_Warning));
diff --git a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
index 083eca05b00f4..617e1bb6dca4a 100644
--- a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
+++ b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
@@ -96,7 +96,7 @@ void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile,
     for (auto &[Name, Choice] : KindChoices) {
       J.attributeBegin(Name);
       J.objectBegin();
-      J.attribute("enabled", Choice->Enabled);
+      J.attribute("enabled", Choice->getEnabled());
       J.attribute("filter", Choice->Filter);
       J.attribute("filter.description",
                   "Static property filter to exclude instrumentation.");
@@ -292,7 +292,7 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
           Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
         }
       }
-      IO->Enabled = ValueMap["enabled"];
+      IO->setEnabled(ValueMap["enabled"]);
       IO->Filter = FilterStr;
       for (auto &IRArg : IO->IRTArgs) {
         IRArg.Enabled = ValueMap[IRArg.Name];
@@ -307,7 +307,7 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
   for (auto &IChoiceMap : IConf.IChoices)
     for (auto &It : IChoiceMap)
       if (!SeenIOs.count(It.second))
-        It.second->Enabled = false;
+        It.second->setEnabled(false);
 
   return true;
 }
diff --git a/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp b/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp
index a2c5c7660e61f..b2e8a72064e32 100644
--- a/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp
+++ b/llvm/lib/Transforms/IPO/InstrumentorStubPrinter.cpp
@@ -310,7 +310,7 @@ void printRuntimeStub(const InstrumentationConfig &IConf,
 
   for (auto &ChoiceMap : IConf.IChoices) {
     for (auto &[_, IO] : ChoiceMap) {
-      if (!IO->Enabled)
+      if (!IO->getEnabled())
         continue;
       IRTCallDescription IRTCallDesc(*IO, IO->getRetTy(Ctx));
       const auto Signatures = IRTCallDesc.createCSignature(IConf);
diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
index 119b32aee2e8e..180eb66bee992 100644
--- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
+++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
@@ -18,6 +18,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/IPO/OpenMPOpt.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/EnumeratedArray.h"
@@ -353,13 +354,14 @@ struct OMPInformationCache : public InformationCache {
     StringRef Name;
 
     /// Flag to indicate a variadic function.
-    bool IsVarArg;
+    bool getIsVarArg() const { return ArgumentTypes.getFlag(0); }
+    void setIsVarArg(bool Value) { ArgumentTypes.setFlag(0, Value); }
 
     /// The return type of the function.
     Type *ReturnType;
 
     /// The argument types of the function.
-    SmallVector<Type *, 8> ArgumentTypes;
+    llvm::SmallVectorWithFlags<Type *, 8> ArgumentTypes;
 
     /// The declaration if available.
     Function *Declaration = nullptr;
@@ -669,9 +671,9 @@ struct OMPInformationCache : public InformationCache {
       auto &RFI = RFIs[_Enum];                                                 \
       RFI.Kind = _Enum;                                                        \
       RFI.Name = _Name;                                                        \
-      RFI.IsVarArg = _IsVarArg;                                                \
+      RFI.setIsVarArg(_IsVarArg);                                              \
       RFI.ReturnType = OMPBuilder._ReturnType;                                 \
-      RFI.ArgumentTypes = std::move(ArgsTypes);                                \
+      RFI.ArgumentTypes.assign(std::move(ArgsTypes));                          \
       RFI.Declaration = F;                                                     \
       unsigned NumUses = collectUses(RFI);                                     \
       (void)NumUses;                                                           \
diff --git a/llvm/lib/Transforms/IPO/PartialInlining.cpp b/llvm/lib/Transforms/IPO/PartialInlining.cpp
index 2d45578071d89..852f1473c8039 100644
--- a/llvm/lib/Transforms/IPO/PartialInlining.cpp
+++ b/llvm/lib/Transforms/IPO/PartialInlining.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
@@ -244,11 +245,14 @@ struct PartialInlinerImpl {
 
     typedef std::pair<Function *, BasicBlock *> FuncBodyCallerPair;
     // Keep track of Outlined Functions and the basic block they're called from.
-    SmallVector<FuncBodyCallerPair, 4> OutlinedFunctions;
+    llvm::SmallVectorWithFlags<FuncBodyCallerPair, 4> OutlinedFunctions;
 
     // ClonedFunc is inlined in one of its callers after function
     // outlining.
-    bool IsFunctionInlined = false;
+    bool getIsFunctionInlined() const { return OutlinedFunctions.getFlag(0); }
+    void setIsFunctionInlined(bool Value) {
+      OutlinedFunctions.setFlag(0, Value);
+    }
     // The cost of the region to be outlined.
     InstructionCost OutlinedRegionCost = 0;
     // ClonedOI is specific to outlining non-early return blocks.
@@ -1220,7 +1224,7 @@ PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
   // users (function pointers, etc.) back to the original function.
   ClonedFunc->replaceAllUsesWith(OrigFunc);
   ClonedFunc->eraseFromParent();
-  if (!IsFunctionInlined) {
+  if (!getIsFunctionInlined()) {
     // Remove each function that was speculatively created if there is no
     // reference.
     for (auto FuncBBPair : OutlinedFunctions) {
@@ -1410,7 +1414,7 @@ bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {
   }
 
   if (AnyInline) {
-    Cloner.IsFunctionInlined = true;
+    Cloner.setIsFunctionInlined(true);
     if (CalleeEntryCount)
       Cloner.OrigFunc->setEntryCount(CalleeEntryCountV);
     OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index 7bef602c3e2c3..4efac84767738 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -1243,7 +1243,7 @@ bool SampleProfileLoader::tryInlineCandidate(
     return false;
 
   InlineFunctionInfo IFI(GetAC);
-  IFI.UpdateProfile = false;
+  IFI.setUpdateProfile(false);
   InlineResult IR = InlineFunction(CB, IFI,
                                    /*MergeAttributes=*/true);
   if (!IR.isSuccess())
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index 88c57d2195bbd..50926ab59277e 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -67,6 +67,7 @@
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/BasicAliasAnalysis.h"
@@ -587,7 +588,9 @@ struct DevirtModule {
   /// when multiple unique return values occur in the same vtable.
   ArrayType *const Int8Arr0Ty;
 
-  const bool RemarksEnabled;
+  bool getRemarksEnabled() const {
+    return CallsWithPtrAuthBundleRemoved.getFlag(0);
+  }
   std::function<OptimizationRemarkEmitter &(Function &)> OREGetter;
   MapVector<VTableSlot, VTableSlotInfo> CallSlots;
 
@@ -598,7 +601,7 @@ struct DevirtModule {
 
   // Store calls that had their ptrauth bundle removed. They are to be deleted
   // at the end of the optimization.
-  SmallVector<CallBase *, 8> CallsWithPtrAuthBundleRemoved;
+  llvm::SmallVectorWithFlags<CallBase *, 8, 2> CallsWithPtrAuthBundleRemoved;
 
   // This map keeps track of the number of "unsafe" uses of a loaded function
   // pointer. The key is the associated llvm.type.test intrinsic call generated
@@ -611,7 +614,9 @@ struct DevirtModule {
   std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
   PatternList FunctionsToSkip;
 
-  const bool DevirtSpeculatively;
+  bool getDevirtSpeculatively() const {
+    return CallsWithPtrAuthBundleRemoved.getFlag(1);
+  }
   DevirtModule(Module &M, ModuleAnalysisManager &MAM,
                ModuleSummaryIndex *ExportSummary,
                const ModuleSummaryIndex *ImportSummary,
@@ -625,11 +630,13 @@ struct DevirtModule {
         Int64Ty(Type::getInt64Ty(M.getContext())),
         IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
         Int8Arr0Ty(ArrayType::get(Type::getInt8Ty(M.getContext()), 0)),
-        RemarksEnabled(areRemarksEnabled()),
         OREGetter([&](Function &F) -> OptimizationRemarkEmitter & {
           return FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
         }),
-        DevirtSpeculatively(DevirtSpeculatively) {
+        CallsWithPtrAuthBundleRemoved(
+            decltype(this->CallsWithPtrAuthBundleRemoved)::withFlags(
+                unsigned(bool(areRemarksEnabled())) |
+                (unsigned(DevirtSpeculatively) << 1))) {
     assert(!(ExportSummary && ImportSummary));
     FunctionsToSkip.init(SkipFunctionNames);
   }
@@ -1111,8 +1118,8 @@ bool DevirtModule::tryFindVirtualCallTargets(
 
     // Without DevirtSpeculatively, we cannot perform whole program
     // devirtualization analysis on a vtable with public LTO visibility.
-    if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
-                                    GlobalObject::VCallVisibilityPublic)
+    if (!getDevirtSpeculatively() && TM.Bits->GV->getVCallVisibility() ==
+                                         GlobalObject::VCallVisibilityPublic)
       return false;
 
     Function *Fn = nullptr;
@@ -1133,7 +1140,7 @@ bool DevirtModule::tryFindVirtualCallTargets(
 
     // In most cases empty functions will be overridden by the
     // implementation of the derived class, so we can skip them.
-    if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
+    if (getDevirtSpeculatively() && Fn->getReturnType()->isVoidTy() &&
         Fn->getInstructionCount() <= 1)
       continue;
 
@@ -1228,7 +1235,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
       if (!DebugCounter::shouldExecute(CallsToDevirt))
         continue;
 
-      if (RemarksEnabled)
+      if (getRemarksEnabled())
         VCallSite.emitRemark("single-impl",
                              TheFn->stripPointerCasts()->getName(), OREGetter);
       NumSingleImpl++;
@@ -1257,7 +1264,8 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
       // add support to compare the virtual function pointer to the
       // devirtualized target. In case of a mismatch, fall back to indirect
       // call.
-      if (DevirtCheckMode == WPDCheckMode::Fallback || DevirtSpeculatively) {
+      if (DevirtCheckMode == WPDCheckMode::Fallback ||
+          getDevirtSpeculatively()) {
         MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights();
         // Version the indirect call site. If the called value is equal to the
         // given callee, 'NewInst' will be executed, otherwise the original call
@@ -1347,7 +1355,7 @@ bool DevirtModule::trySingleImplDevirt(
       return false;
 
   // If so, update each call site to call that implementation directly.
-  if (RemarksEnabled || AreStatisticsEnabled())
+  if (getRemarksEnabled() || AreStatisticsEnabled())
     TargetsForSlot[0].WasDevirt = true;
 
   bool IsExported = false;
@@ -1559,7 +1567,7 @@ void DevirtModule::applyICallBranchFunnel(VTableSlotInfo &SlotInfo,
         continue;
 
       NumBranchFunnel++;
-      if (RemarksEnabled)
+      if (getRemarksEnabled())
         VCallSite.emitRemark("branch-funnel", JT.getName(), OREGetter);
 
       // Pass the address of the vtable in the nest register, which is r10 on
@@ -1682,7 +1690,7 @@ void DevirtModule::applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
       continue;
     NumUniformRetVal++;
     Call.replaceAndErase(
-        "uniform-ret-val", FnName, RemarksEnabled, OREGetter,
+        "uniform-ret-val", FnName, getRemarksEnabled(), OREGetter,
         ConstantInt::get(cast<IntegerType>(Call.CB.getType()), TheRetVal));
   }
   CSInfo.markDevirt();
@@ -1704,7 +1712,7 @@ bool DevirtModule::tryUniformRetValOpt(
   }
 
   applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), TheRetVal);
-  if (RemarksEnabled || AreStatisticsEnabled())
+  if (getRemarksEnabled() || AreStatisticsEnabled())
     for (auto &&Target : TargetsForSlot)
       Target.WasDevirt = true;
   return true;
@@ -1798,8 +1806,8 @@ void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
                      B.CreateBitCast(UniqueMemberAddr, Call.VTable->getType()));
     Cmp = B.CreateZExt(Cmp, Call.CB.getType());
     NumUniqueRetVal++;
-    Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, OREGetter,
-                         Cmp);
+    Call.replaceAndErase("unique-ret-val", FnName, getRemarksEnabled(),
+                         OREGetter, Cmp);
   }
   CSInfo.markDevirt();
 }
@@ -1841,7 +1849,7 @@ bool DevirtModule::tryUniqueRetValOpt(
                          UniqueMemberAddr);
 
     // Update devirtualization statistics for targets.
-    if (RemarksEnabled || AreStatisticsEnabled())
+    if (getRemarksEnabled() || AreStatisticsEnabled())
       for (auto &&Target : TargetsForSlot)
         Target.WasDevirt = true;
 
@@ -1870,12 +1878,12 @@ void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
       Value *BitsAndBit = B.CreateAnd(Bits, Bit);
       auto IsBitSet = B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
       NumVirtConstProp1Bit++;
-      Call.replaceAndErase("virtual-const-prop-1-bit", FnName, RemarksEnabled,
-                           OREGetter, IsBitSet);
+      Call.replaceAndErase("virtual-const-prop-1-bit", FnName,
+                           getRemarksEnabled(), OREGetter, IsBitSet);
     } else {
       Value *Val = B.CreateLoad(RetType, Addr);
       NumVirtConstProp++;
-      Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled,
+      Call.replaceAndErase("virtual-const-prop", FnName, getRemarksEnabled(),
                            OREGetter, Val);
     }
   }
@@ -2006,7 +2014,7 @@ bool DevirtModule::tryVirtualConstProp(
     // have an aligned load.
     assert(OffsetByte % TypeAlignment.value() == 0);
 
-    if (RemarksEnabled || AreStatisticsEnabled())
+    if (getRemarksEnabled() || AreStatisticsEnabled())
       for (auto &&Target : TargetsForSlot)
         Target.WasDevirt = true;
 
@@ -2445,7 +2453,7 @@ bool DevirtModule::run() {
   Function *PublicTypeTestFunc = nullptr;
   // If we are in speculative devirtualization mode, we can work on the public
   // type test intrinsics.
-  if (DevirtSpeculatively)
+  if (getDevirtSpeculatively())
     PublicTypeTestFunc =
         Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
   Function *TypeTestFunc =
@@ -2581,7 +2589,7 @@ bool DevirtModule::run() {
       // Out of speculative devirtualization mode, Try to apply virtual constant
       // propagation or branch funneling.
       // TODO: This should eventually be enabled for non-public type tests.
-      if (!SingleImplDevirt && !DevirtSpeculatively) {
+      if (!SingleImplDevirt && !getDevirtSpeculatively()) {
         DidVirtualConstProp |=
             tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
 
@@ -2589,7 +2597,7 @@ bool DevirtModule::run() {
       }
 
       // Collect functions devirtualized at least for one call site for stats.
-      if (RemarksEnabled || AreStatisticsEnabled())
+      if (getRemarksEnabled() || AreStatisticsEnabled())
         for (const auto &T : TargetsForSlot)
           if (T.WasDevirt)
             DevirtTargets[std::string(T.Fn->getName())] = T.Fn;
@@ -2613,7 +2621,7 @@ bool DevirtModule::run() {
     }
   }
 
-  if (RemarksEnabled) {
+  if (getRemarksEnabled()) {
     // Generate remarks for each devirtualized function.
     for (const auto &DT : DevirtTargets) {
       GlobalValue *GV = DT.second;
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 8de58841938a8..d81e5dc9deaab 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -462,22 +463,26 @@ namespace {
 /// required funclet OpBundle.
 class RuntimeCallInserter {
   Function *OwnerFn = nullptr;
-  bool TrackInsertedCalls = false;
-  SmallVector<CallInst *> InsertedCalls;
+  bool getTrackInsertedCalls() const { return InsertedCalls.getFlag(0); }
+  bool setTrackInsertedCalls(bool Value) {
+    InsertedCalls.setFlag(0, Value);
+    return Value;
+  }
+  llvm::SmallVectorWithFlags<CallInst *> InsertedCalls;
 
 public:
   RuntimeCallInserter(Function &Fn) : OwnerFn(&Fn) {
     if (Fn.hasPersonalityFn()) {
       auto Personality = classifyEHPersonality(Fn.getPersonalityFn());
       if (isScopedEHPersonality(Personality))
-        TrackInsertedCalls = true;
+        setTrackInsertedCalls(true);
     }
   }
 
   ~RuntimeCallInserter() {
     if (InsertedCalls.empty())
       return;
-    assert(TrackInsertedCalls && "Calls were wrongly tracked");
+    assert(getTrackInsertedCalls() && "Calls were wrongly tracked");
 
     DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*OwnerFn);
     for (CallInst *CI : InsertedCalls) {
@@ -519,7 +524,7 @@ class RuntimeCallInserter {
     assert(IRB.GetInsertBlock()->getParent() == OwnerFn);
 
     CallInst *Inst = IRB.CreateCall(Callee, Args, Name, nullptr);
-    if (TrackInsertedCalls)
+    if (getTrackInsertedCalls())
       InsertedCalls.push_back(Inst);
     return Inst;
   }
@@ -833,13 +838,16 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
   SmallVector<AllocaPoisonCall, 8> StaticAllocaPoisonCallVec;
 
   SmallVector<AllocaInst *, 1> DynamicAllocaVec;
-  SmallVector<IntrinsicInst *, 1> StackRestoreVec;
+  llvm::SmallVectorWithFlags<IntrinsicInst *, 1, 3> StackRestoreVec;
   AllocaInst *DynamicAllocaLayout = nullptr;
   IntrinsicInst *LocalEscapeCall = nullptr;
 
-  bool HasInlineAsm = false;
-  bool HasReturnsTwiceCall = false;
-  bool PoisonStack;
+  bool getHasInlineAsm() const { return StackRestoreVec.getFlag(0); }
+  void setHasInlineAsm(bool Value) { StackRestoreVec.setFlag(0, Value); }
+  bool getHasReturnsTwiceCall() const { return StackRestoreVec.getFlag(1); }
+  void setHasReturnsTwiceCall(bool Value) { StackRestoreVec.setFlag(1, Value); }
+  bool getPoisonStack() const { return StackRestoreVec.getFlag(2); }
+  void setPoisonStack(bool Value) { StackRestoreVec.setFlag(2, Value); }
 
   FunctionStackPoisoner(Function &F, AddressSanitizer &ASan,
                         RuntimeCallInserter &RTCI)
@@ -848,11 +856,13 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
         IntptrTy(ASan.IntptrTy),
         IntptrPtrTy(PointerType::get(IntptrTy->getContext(), 0)),
         Mapping(ASan.Mapping),
-        PoisonStack(Opts.asan_stack &&
-                    !F.getParent()->getTargetTriple().isAMDGPU()) {}
+        StackRestoreVec(decltype(this->StackRestoreVec)::withFlags(
+            (unsigned(bool(Opts.asan_stack &&
+                           !F.getParent()->getTargetTriple().isAMDGPU()))
+             << 2))) {}
 
   bool runOnFunction() {
-    if (!PoisonStack)
+    if (!getPoisonStack())
       return false;
 
     if (Opts.asan_redzone_byval_args)
@@ -1000,8 +1010,16 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
 
   void visitCallBase(CallBase &CB) {
     if (CallInst *CI = dyn_cast<CallInst>(&CB)) {
-      HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
-      HasReturnsTwiceCall |= CI->canReturnTwice();
+      [&] {
+        auto PackedFlagValue =
+            CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
+        return setHasInlineAsm(getHasInlineAsm() | PackedFlagValue);
+      }();
+      [&] {
+        auto PackedFlagValue = CI->canReturnTwice();
+        return setHasReturnsTwiceCall(getHasReturnsTwiceCall() |
+                                      PackedFlagValue);
+      }();
     }
   }
 
@@ -1362,7 +1380,8 @@ void AddressSanitizer::getInterestingMemoryOperands(
       if (auto *II = dyn_cast<IntrinsicInst>(I)) {
         MemIntrinsicInfo IntrInfo;
         if (TTI->getTgtMemIntrinsic(II, IntrInfo))
-          Interesting = IntrInfo.InterestingOperands;
+          Interesting.assign(IntrInfo.InterestingOperands.begin(),
+                             IntrInfo.InterestingOperands.end());
         return;
       }
       for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
@@ -3456,8 +3475,8 @@ void FunctionStackPoisoner::processStaticAllocas() {
   // 2) There is a returns_twice call (typically setjmp), which is
   //    optimization-hostile, and doesn't play well with introduced indirect
   //    register-relative calculation of local variable addresses.
-  DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall;
-  DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall;
+  DoDynamicAlloca &= !getHasInlineAsm() && !getHasReturnsTwiceCall();
+  DoStackMalloc &= !getHasInlineAsm() && !getHasReturnsTwiceCall();
 
   Type *PtrTy = F.getDataLayout().getAllocaPtrType(F.getContext());
   Value *StaticAlloca =
diff --git a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
index d4e6a6936bbcc..bfe8348bc45c2 100644
--- a/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
 #include "llvm/Analysis/GlobalsModRef.h"
@@ -110,8 +111,9 @@ struct RegInfo {
   RegInfo() = default;
   RegInfo(Region *RegionIn) : R(RegionIn) {}
   Region *R = nullptr;
-  bool HasBranch = false;
-  SmallVector<SelectInst *, 8> Selects;
+  bool getHasBranch() const { return Selects.getFlag(0); }
+  void setHasBranch(bool Value) { Selects.setFlag(0, Value); }
+  llvm::SmallVectorWithFlags<SelectInst *, 8> Selects;
 };
 
 typedef DenseMap<Region *, DenseSet<Instruction *>> HoistStopMapTy;
@@ -424,7 +426,7 @@ void CHRScope::print(raw_ostream &OS) const {
   OS << RegInfos.size() << ", Regions[";
   for (const RegInfo &RI : RegInfos) {
     OS << RI.R->getNameStr();
-    if (RI.HasBranch)
+    if (RI.getHasBranch())
       OS << " B";
     if (RI.Selects.size() > 0)
       OS << " S" << RI.Selects.size();
@@ -760,14 +762,14 @@ CHRScope * CHR::findScope(Region *R) {
       CHR_DEBUG(dbgs() << "S1 " << S1->getName() << "\n");
       if (S0 != S1 && (S0 == Exit || S1 == Exit)) {
         RegInfo RI(R);
-        RI.HasBranch =
-            checkBiasedBranch(Opts, BI, R, TrueBiasedRegionsGlobal,
-                              FalseBiasedRegionsGlobal, BranchBiasMap);
+        RI.setHasBranch(checkBiasedBranch(Opts, BI, R, TrueBiasedRegionsGlobal,
+                                          FalseBiasedRegionsGlobal,
+                                          BranchBiasMap));
         Result = new CHRScope(RI);
         Scopes.insert(Result);
         CHR_DEBUG(dbgs() << "Found a region with a branch\n");
         ++Stats.NumBranches;
-        if (!RI.HasBranch) {
+        if (!RI.getHasBranch()) {
           ORE.emit([&]() {
             return OptimizationRemarkMissed(DEBUG_TYPE, "BranchNotBiased", BI)
                 << "Branch not biased";
@@ -863,9 +865,9 @@ void CHR::checkScopeHoistable(CHRScope *Scope) {
   Region *R = RI.R;
   BasicBlock *EntryBB = R->getEntry();
   auto *Branch =
-      RI.HasBranch ? cast<CondBrInst>(EntryBB->getTerminator()) : nullptr;
-  SmallVector<SelectInst *, 8> &Selects = RI.Selects;
-  if (RI.HasBranch || !Selects.empty()) {
+      RI.getHasBranch() ? cast<CondBrInst>(EntryBB->getTerminator()) : nullptr;
+  auto &Selects = RI.Selects;
+  if (RI.getHasBranch() || !Selects.empty()) {
     Instruction *InsertPoint = getBranchInsertPoint(RI);
     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
     // Avoid a data dependence from a select or a branch to a(nother)
@@ -900,7 +902,7 @@ void CHR::checkScopeHoistable(CHRScope *Scope) {
     // Update InsertPoint after potentially removing selects.
     InsertPoint = getBranchInsertPoint(RI);
     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
-    if (RI.HasBranch && InsertPoint != Branch) {
+    if (RI.getHasBranch() && InsertPoint != Branch) {
       DenseMap<Instruction *, bool> Visited;
       bool IsHoistable = checkHoistValue(Branch->getCondition(), InsertPoint,
                                          DT, Unhoistables, nullptr, Visited);
@@ -930,7 +932,7 @@ void CHR::checkScopeHoistable(CHRScope *Scope) {
     }
     CHR_DEBUG(dbgs() << "InsertPoint " << *InsertPoint << "\n");
 #ifndef NDEBUG
-    if (RI.HasBranch) {
+    if (RI.getHasBranch()) {
       assert(!DT.dominates(Branch, InsertPoint) &&
              "Branch can't be already above the hoist point");
       DenseMap<Instruction *, bool> Visited;
@@ -947,7 +949,7 @@ void CHR::checkScopeHoistable(CHRScope *Scope) {
              "checkHoistValue for selects");
     }
     CHR_DEBUG(dbgs() << "Result\n");
-    if (RI.HasBranch) {
+    if (RI.getHasBranch()) {
       CHR_DEBUG(dbgs() << "BI " << *Branch << "\n");
     }
     for (auto *SI : Selects) {
@@ -1009,7 +1011,7 @@ CHRScope * CHR::findScopes(Region *R, Region *NextRegion, Region *ParentRegion,
 
 static DenseSet<Value *> getCHRConditionValuesForRegion(RegInfo &RI) {
   DenseSet<Value *> ConditionValues;
-  if (RI.HasBranch) {
+  if (RI.getHasBranch()) {
     auto *BI = cast<CondBrInst>(RI.R->getEntry()->getTerminator());
     ConditionValues.insert(BI->getCondition());
   }
@@ -1272,7 +1274,7 @@ void CHR::classifyBiasedScopes(SmallVectorImpl<CHRScope *> &Scopes) {
 
 void CHR::classifyBiasedScopes(CHRScope *Scope, CHRScope *OutermostScope) {
   for (RegInfo &RI : Scope->RegInfos) {
-    if (RI.HasBranch) {
+    if (RI.getHasBranch()) {
       Region *R = RI.R;
       if (TrueBiasedRegionsGlobal.contains(R))
         OutermostScope->TrueBiasedRegions.insert(R);
@@ -1363,7 +1365,7 @@ void CHR::setCHRRegions(CHRScope *Scope, CHRScope *OutermostScope) {
     Region *R = RI.R;
     DenseSet<Instruction *> HoistStops;
     bool IsHoisted = false;
-    if (RI.HasBranch) {
+    if (RI.getHasBranch()) {
       assert((OutermostScope->TrueBiasedRegions.contains(R) ||
               OutermostScope->FalseBiasedRegions.contains(R)) &&
              "Must be truthy or falsy");
@@ -1466,7 +1468,7 @@ static void hoistScopeConditions(CHRScope *Scope, Instruction *HoistPoint,
     Region *R = RI.R;
     bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
     bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
-    if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
+    if (RI.getHasBranch() && (IsTrueBiased || IsFalseBiased)) {
       auto *BI = cast<CondBrInst>(R->getEntry()->getTerminator());
       hoistValue(BI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
                  HoistedSet, TrivialPHIs, DT);
@@ -1641,7 +1643,7 @@ assertBranchOrSelectConditionHoisted(CHRScope *Scope,
     Region *R = RI.R;
     bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
     bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
-    if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
+    if (RI.getHasBranch() && (IsTrueBiased || IsFalseBiased)) {
       auto *BI = cast<CondBrInst>(R->getEntry()->getTerminator());
       Value *V = BI->getCondition();
       CHR_DEBUG(dbgs() << *V << "\n");
@@ -1862,7 +1864,7 @@ void CHR::fixupBranchesAndSelects(CHRScope *Scope, BasicBlock *PreEntryBlock,
   IRBuilder<> IRB(PreEntryBlock->getTerminator());
   for (RegInfo &RI : Scope->CHRRegions) {
     Region *R = RI.R;
-    if (RI.HasBranch) {
+    if (RI.getHasBranch()) {
       fixupBranch(R, Scope, IRB, MergedCondition, CHRBranchBias);
       ++NumCHRedBranches;
     }
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index ea31e08a4661a..ead13eba80a57 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -1382,7 +1382,7 @@ void HWAddressSanitizer::instrumentStack(OptimizationRemarkEmitter &ORE,
     // postdominator analysis, and will leave us to keep memory tagged after
     // function return. Work around this by always untagging at every return
     // statement if return_twice functions are called.
-    if (DetectUseAfterScope && !SInfo.CallsReturnTwice &&
+    if (DetectUseAfterScope && !SInfo.getCallsReturnTwice() &&
         memtag::isSupportedLifetime(Info, &DT, &LI)) {
       TagStarts();
       memtag::forAllReachableExits(DT, PDT, LI, Info, SInfo.RetVec, TagEnd);
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 6a7bda565ef21..8ee3e351d51d0 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
@@ -426,8 +427,9 @@ class PGOCounterPromoter {
       const InstrumentationOptions &Opts,
       DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands,
       Loop &CurLoop, LoopInfo &LI, BlockFrequencyInfo *BFI, bool IsAtomic)
-      : Opts(Opts), LoopToCandidates(LoopToCands), L(CurLoop), LI(LI), BFI(BFI),
-        IsAtomic(IsAtomic) {
+      : Opts(Opts), LoopToCandidates(LoopToCands),
+        InsertPts(decltype(this->InsertPts)::withFlags(unsigned(IsAtomic))),
+        L(CurLoop), LI(LI), BFI(BFI) {
 
     // Skip collection of ExitBlocks and InsertPts for loops that will not be
     // able to have counters promoted.
@@ -468,7 +470,7 @@ class PGOCounterPromoter {
     //  3) convert all (promoted and unpromotable) updates to atomicRMW.
     // This requires that promoted candidates are set to nullptr in the
     // Candidates array by the promoteCandidates() function.
-    if (IsAtomic)
+    if (getIsAtomic())
       for (auto &Cand : Candidates)
         if (Cand.first != nullptr && Cand.second != nullptr)
           makeAtomic(Cand.first, Cand.second);
@@ -518,7 +520,7 @@ class PGOCounterPromoter {
 
       PGOCounterPromoterHelper Promoter(
           Opts, Cand.first, Cand.second, SSA, InitVal, L.getLoopPreheader(),
-          ExitBlocks, InsertPts, LoopToCandidates, LI, IsAtomic);
+          ExitBlocks, InsertPts, LoopToCandidates, LI, getIsAtomic());
       Promoter.run(SmallVector<Instruction *, 2>({Cand.first, Cand.second}));
 
       Cand = {nullptr, nullptr};
@@ -614,11 +616,13 @@ class PGOCounterPromoter {
   const InstrumentationOptions &Opts;
   DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCandidates;
   SmallVector<BasicBlock *, 8> ExitBlocks;
-  SmallVector<Instruction *, 8> InsertPts;
+  llvm::SmallVectorWithFlags<Instruction *, 8> InsertPts;
   Loop &L;
   LoopInfo &LI;
   BlockFrequencyInfo *BFI;
-  const bool IsAtomic; // Whether to convert counter updates to atomics.
+  bool getIsAtomic() const {
+    return InsertPts.getFlag(0);
+  } // Whether to convert counter updates to atomics.
 };
 
 enum class ValueProfilingCallType {
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 2e31d692599cf..630b4d7ddb1f2 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -157,6 +157,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/GlobalsModRef.h"
@@ -1046,11 +1047,18 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
   // The following flags disable parts of MSan instrumentation based on
   // exclusion list contents and command-line options.
-  bool InsertChecks;
-  bool PropagateShadow;
-  bool PoisonStack;
-  bool PoisonUndef;
-  bool PoisonUndefVectors;
+  bool getInsertChecks() const { return StoreList.getFlag(0); }
+  void setInsertChecks(bool Value) { StoreList.setFlag(0, Value); }
+  bool getPropagateShadow() const { return StoreList.getFlag(1); }
+  void setPropagateShadow(bool Value) { StoreList.setFlag(1, Value); }
+  bool getPoisonStack() const { return StoreList.getFlag(2); }
+  void setPoisonStack(bool Value) { StoreList.setFlag(2, Value); }
+  bool getPoisonUndef() const { return StoreList.getFlag(3); }
+  void setPoisonUndef(bool Value) { StoreList.setFlag(3, Value); }
+  bool getPoisonUndefVectors() const { return LifetimeStartList.getFlag(0); }
+  void setPoisonUndefVectors(bool Value) {
+    LifetimeStartList.setFlag(0, Value);
+  }
 
   struct ShadowOriginAndInsertPoint {
     Value *Shadow;
@@ -1063,8 +1071,9 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;
   DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
   SmallSetVector<AllocaInst *, 16> AllocaSet;
-  SmallVector<std::pair<IntrinsicInst *, AllocaInst *>, 16> LifetimeStartList;
-  SmallVector<StoreInst *, 16> StoreList;
+  llvm::SmallVectorWithFlags<std::pair<IntrinsicInst *, AllocaInst *>, 16>
+      LifetimeStartList;
+  llvm::SmallVectorWithFlags<StoreInst *, 16, 4> StoreList;
   int64_t SplittableBlocksCount = 0;
 
   MemorySanitizerVisitor(Function &F, MemorySanitizer &MS,
@@ -1073,11 +1082,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
         TLI(&TLI) {
     bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeMemory) &&
                             !Opts.msan_disable_checks;
-    InsertChecks = SanitizeFunction;
-    PropagateShadow = SanitizeFunction;
-    PoisonStack = SanitizeFunction && Opts.msan_poison_stack;
-    PoisonUndef = SanitizeFunction && Opts.msan_poison_undef;
-    PoisonUndefVectors = SanitizeFunction && Opts.msan_poison_undef_vectors;
+    setInsertChecks(SanitizeFunction);
+    setPropagateShadow(SanitizeFunction);
+    setPoisonStack(SanitizeFunction && Opts.msan_poison_stack);
+    setPoisonUndef(SanitizeFunction && Opts.msan_poison_undef);
+    setPoisonUndefVectors(SanitizeFunction && Opts.msan_poison_undef_vectors);
 
     // In the presence of unreachable blocks, we may see Phi nodes with
     // incoming nodes from such blocks. Since InstVisitor skips unreachable
@@ -1095,7 +1104,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       insertKmsanPrologue(IRB);
     }
 
-    LLVM_DEBUG(if (!InsertChecks) dbgs()
+    LLVM_DEBUG(if (!getInsertChecks()) dbgs()
                << "MemorySanitizer is not inserting checks into '"
                << F.getName() << "'\n");
   }
@@ -1834,7 +1843,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
              "setShadow called with mismatching types");
     }
 
-    ShadowMap[V] = PropagateShadow ? SV : getCleanShadow(V);
+    ShadowMap[V] = getPropagateShadow() ? SV : getCleanShadow(V);
   }
 
   /// Set Origin to be the origin value for V.
@@ -1895,7 +1904,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   /// or extracts if from ParamTLS (for function arguments).
   Value *getShadow(Value *V) {
     if (Instruction *I = dyn_cast<Instruction>(V)) {
-      if (!PropagateShadow || I->getMetadata(LLVMContext::MD_nosanitize))
+      if (!getPropagateShadow() || I->getMetadata(LLVMContext::MD_nosanitize))
         return getCleanShadow(V);
       // For instructions the shadow is already stored in the map.
       Value *Shadow = ShadowMap[V];
@@ -1908,8 +1917,9 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
     // Handle fully undefined values
     // (partially undefined constant vectors are handled later)
     if ([[maybe_unused]] UndefValue *U = dyn_cast<UndefValue>(V)) {
-      Value *AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
-                                                        : getCleanShadow(V);
+      Value *AllOnes = (getPropagateShadow() && getPoisonUndef())
+                           ? getPoisonedShadow(V)
+                           : getCleanShadow(V);
       LLVM_DEBUG(dbgs() << "Undef: " << *U << " ==> " << *AllOnes << "\n");
       return AllOnes;
     }
@@ -1951,7 +1961,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
             std::tie(CpShadowPtr, CpOriginPtr) =
                 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
                                    /*isStore*/ true);
-            if (!PropagateShadow || Overflow) {
+            if (!getPropagateShadow() || Overflow) {
               // ParamTLS overflow.
               EntryIRB.CreateMemSet(
                   CpShadowPtr, Constant::getNullValue(EntryIRB.getInt8Ty()),
@@ -1977,7 +1987,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
             }
           }
 
-          if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
+          if (!getPropagateShadow() || Overflow || FArg.hasByValAttr() ||
               (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
             ShadowPtr = getCleanShadow(V);
             setOrigin(A, getCleanOrigin());
@@ -2005,8 +2015,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
     // Check for partially-undefined constant vectors
     // TODO: scalable vectors (this is hard because we do not have IRBuilder)
     if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
-        cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
-        PoisonUndefVectors) {
+        cast<Constant>(V)->containsUndefOrPoisonElement() &&
+        getPropagateShadow() && getPoisonUndefVectors()) {
       unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
       SmallVector<Constant *, 32> ShadowVector(NumElems);
       for (unsigned i = 0; i != NumElems; ++i) {
@@ -2037,7 +2047,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   Value *getOrigin(Value *V) {
     if (!MS.TrackOrigins)
       return nullptr;
-    if (!PropagateShadow || isa<Constant>(V) || isa<InlineAsm>(V))
+    if (!getPropagateShadow() || isa<Constant>(V) || isa<InlineAsm>(V))
       return getCleanOrigin();
     assert((isa<Instruction>(V) || isa<Argument>(V)) &&
            "Unexpected value type in getOrigin()");
@@ -2061,7 +2071,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   /// UMR warning in runtime if the shadow value is not 0.
   void insertCheckShadow(Value *Shadow, Value *Origin, Instruction *OrigIns) {
     assert(Shadow);
-    if (!InsertChecks)
+    if (!getInsertChecks())
       return;
 
     if (!DebugCounter::shouldExecute(DebugInsertCheck)) {
@@ -2207,7 +2217,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
     Value *Addr = I.getPointerOperand();
     Value *ShadowPtr = nullptr, *OriginPtr = nullptr;
     const Align Alignment = I.getAlign();
-    if (PropagateShadow) {
+    if (getPropagateShadow()) {
       std::tie(ShadowPtr, OriginPtr) =
           getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ false);
       setShadow(&I,
@@ -2223,7 +2233,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       I.setOrdering(addAcquireOrdering(I.getOrdering()));
 
     if (MS.TrackOrigins) {
-      if (PropagateShadow) {
+      if (getPropagateShadow()) {
         const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
         setOrigin(
             &I, IRB.CreateAlignedLoad(MS.OriginTy, OriginPtr, OriginAlignment));
@@ -3306,7 +3316,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
     Type *ShadowTy = getShadowTy(&I);
     Value *ShadowPtr = nullptr, *OriginPtr = nullptr;
-    if (PropagateShadow) {
+    if (getPropagateShadow()) {
       // We don't know the pointer alignment (could be unaligned SSE load!).
       // Have to assume to worst case.
       const Align Alignment = Align(1);
@@ -3322,7 +3332,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       insertCheckShadowOf(Addr, &I);
 
     if (MS.TrackOrigins) {
-      if (PropagateShadow)
+      if (getPropagateShadow())
         setOrigin(&I, IRB.CreateLoad(MS.OriginTy, OriginPtr));
       else
         setOrigin(&I, getCleanOrigin());
@@ -3425,7 +3435,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   }
 
   void handleLifetimeStart(IntrinsicInst &I) {
-    if (!PoisonStack)
+    if (!getPoisonStack())
       return;
     AllocaInst *AI = dyn_cast<AllocaInst>(I.getArgOperand(0));
     if (AI)
@@ -4318,7 +4328,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   }
 
   void handleLdmxcsr(IntrinsicInst &I) {
-    if (!InsertChecks)
+    if (!getInsertChecks())
       return;
 
     IRBuilder<> IRB(&I);
@@ -4350,7 +4360,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       insertCheckShadowOf(Mask, &I);
     }
 
-    if (!PropagateShadow) {
+    if (!getPropagateShadow()) {
       setShadow(&I, getCleanShadow(&I));
       setOrigin(&I, getCleanOrigin());
       return;
@@ -4410,7 +4420,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &I);
     }
 
-    if (!PropagateShadow) {
+    if (!getPropagateShadow()) {
       setShadow(&I, getCleanShadow(&I));
       setOrigin(&I, getCleanOrigin());
       return;
@@ -4507,7 +4517,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       insertCheckShadowOf(Mask, &I);
     }
 
-    if (!PropagateShadow) {
+    if (!getPropagateShadow()) {
       setShadow(&I, getCleanShadow(&I));
       setOrigin(&I, getCleanOrigin());
       return;
@@ -4555,7 +4565,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
         Mask, getShadow(Divisor), getCleanShadow(Divisor), "_msmaskeddivisor");
     insertCheckShadow(MaskedDivisorShadow, getOrigin(Divisor), &I);
 
-    if (!PropagateShadow) {
+    if (!getPropagateShadow()) {
       setShadow(&I, getCleanShadow(&I));
       setOrigin(&I, getCleanOrigin());
       return;
@@ -7754,7 +7764,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
           std::tie(AShadowPtr, AOriginPtr) =
               getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), Alignment,
                                  /*isStore*/ false);
-          if (!PropagateShadow) {
+          if (!getPropagateShadow()) {
             Store = IRB.CreateMemSet(ArgShadowBase,
                                      Constant::getNullValue(IRB.getInt8Ty()),
                                      Size, Alignment);
@@ -7891,7 +7901,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
   void visitPHINode(PHINode &I) {
     IRBuilder<> IRB(&I);
-    if (!PropagateShadow) {
+    if (!getPropagateShadow()) {
       setShadow(&I, getCleanShadow(&I));
       setOrigin(&I, getCleanOrigin());
       return;
@@ -7918,7 +7928,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
   }
 
   void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {
-    if (PoisonStack && Opts.msan_poison_stack_with_call) {
+    if (getPoisonStack() && Opts.msan_poison_stack_with_call) {
       IRB.CreateCall(MS.MsanPoisonStackFn, {&I, Len});
     } else {
       Value *ShadowBase, *OriginBase;
@@ -7926,11 +7936,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
           &I, IRB, IRB.getInt8Ty(), Align(1), /*isStore*/ true);
 
       Value *PoisonValue =
-          IRB.getInt8(PoisonStack ? Opts.msan_poison_stack_pattern : 0);
+          IRB.getInt8(getPoisonStack() ? Opts.msan_poison_stack_pattern : 0);
       IRB.CreateMemSet(ShadowBase, PoisonValue, Len, I.getAlign());
     }
 
-    if (PoisonStack && MS.TrackOrigins) {
+    if (getPoisonStack() && MS.TrackOrigins) {
       Value *Idptr = getLocalVarIdptr(I);
       if (Opts.msan_print_stack_names) {
         Value *Descr = getLocalVarDescription(I);
@@ -7944,7 +7954,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
 
   void poisonAllocaKmsan(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {
     Value *Descr = getLocalVarDescription(I);
-    if (PoisonStack) {
+    if (getPoisonStack()) {
       IRB.CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
     } else {
       IRB.CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
index 03a79ac734f71..cf284cd5fd120 100644
--- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
@@ -36,6 +36,7 @@
 #include "ScalarOptions.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
@@ -549,7 +550,7 @@ ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S,
                                            ConstCandVecType::iterator &MaxCostItr) {
   unsigned NumUses = 0;
 
-  if (!OptForSize || std::distance(S,E) > 100) {
+  if (!getOptForSize() || std::distance(S, E) > 100) {
     for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
       NumUses += ConstCand->Uses.size();
       if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost)
@@ -630,12 +631,17 @@ void ConstantHoistingPass::findAndMakeBaseConstant(
 /// Finds and combines constant candidates that can be easily
 /// rematerialized with an add from a common base constant.
 void ConstantHoistingPass::findBaseConstants(GlobalVariable *BaseGV) {
+  ConstInfoVecType IntegerInfo;
+  IntegerInfo = std::move(ConstIntInfoVec);
+  auto RestoreIntegerInfo =
+      scope_exit([&] { ConstIntInfoVec.assign(std::move(IntegerInfo)); });
+
   // If BaseGV is nullptr, find base among candidate constant integers;
   // Otherwise find base among constant GEPs that share the same BaseGV.
   ConstCandVecType &ConstCandVec = BaseGV ?
       ConstGEPCandMap[BaseGV] : ConstIntCandVec;
-  ConstInfoVecType &ConstInfoVec = BaseGV ?
-      ConstGEPInfoMap[BaseGV] : ConstIntInfoVec;
+  ConstInfoVecType &ConstInfoVec =
+      BaseGV ? ConstGEPInfoMap[BaseGV] : IntegerInfo;
 
   // Sort the constants by value and type. This invalidates the mapping!
   llvm::stable_sort(ConstCandVec, [](const ConstantCandidate &LHS,
@@ -811,9 +817,14 @@ void ConstantHoistingPass::emitBaseConstants(Instruction *Base,
 /// Hoist and hide the base constant behind a bitcast and emit
 /// materialization code for derived constants.
 bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) {
+  ConstInfoVecType IntegerInfo;
+  IntegerInfo = std::move(ConstIntInfoVec);
+  auto RestoreIntegerInfo =
+      scope_exit([&] { ConstIntInfoVec.assign(std::move(IntegerInfo)); });
+
   bool MadeChange = false;
   SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec =
-      BaseGV ? ConstGEPInfoMap[BaseGV] : ConstIntInfoVec;
+      BaseGV ? ConstGEPInfoMap[BaseGV] : IntegerInfo;
   for (const consthoist::ConstantInfo &ConstInfo : ConstInfoVec) {
     SmallVector<BasicBlock::iterator, 4> MatInsertPts;
     collectMatInsertPts(ConstInfo.RebasedConstants, MatInsertPts);
@@ -919,8 +930,8 @@ bool ConstantHoistingPass::runImpl(Function &Fn, TargetTransformInfo &TTI,
   this->Ctx = &Fn.getContext();
   this->Entry = &Entry;
   this->PSI = PSI;
-  this->OptForSize = llvm::shouldOptimizeForSize(Entry.getParent(), PSI, BFI,
-                                                 PGSOQueryType::IRPass);
+  this->setOptForSize(llvm::shouldOptimizeForSize(Entry.getParent(), PSI, BFI,
+                                                  PGSOQueryType::IRPass));
 
   // Collect all constant candidates.
   collectConstantCandidates(Fn);
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 51c118e995096..15dd5c49ffa5d 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ConstraintSystem.h"
 #include "llvm/Analysis/GlobalsModRef.h"
@@ -245,15 +246,16 @@ class ConstraintInfo;
 struct StackEntry {
   unsigned NumIn;
   unsigned NumOut;
-  bool IsSigned = false;
+  bool getIsSigned() const { return ValuesToRelease.getFlag(0); }
+  void setIsSigned(bool Value) { ValuesToRelease.setFlag(0, Value); }
   /// Variables that can be removed from the system once the stack entry gets
   /// removed.
-  SmallVector<Value *, 2> ValuesToRelease;
+  llvm::SmallVectorWithFlags<Value *, 2> ValuesToRelease;
 
   StackEntry(unsigned NumIn, unsigned NumOut, bool IsSigned,
              SmallVector<Value *, 2> ValuesToRelease)
-      : NumIn(NumIn), NumOut(NumOut), IsSigned(IsSigned),
-        ValuesToRelease(std::move(ValuesToRelease)) {}
+      : NumIn(NumIn), NumOut(NumOut),
+        ValuesToRelease(unsigned(IsSigned), std::move(ValuesToRelease)) {}
 };
 
 struct ConstraintTy {
@@ -2138,12 +2140,12 @@ removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
                      SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
                      SmallVectorImpl<StackEntry> &DFSInStack) {
   Info.getDecomposeCache().clear();
-  Info.popLastConstraint(E.IsSigned);
+  Info.popLastConstraint(E.getIsSigned());
   // Remove variables in the system that went out of scope.
-  auto &Mapping = Info.getValue2Index(E.IsSigned);
+  auto &Mapping = Info.getValue2Index(E.getIsSigned());
   for (Value *V : E.ValuesToRelease)
     Mapping.erase(V);
-  Info.popLastNVariables(E.IsSigned, E.ValuesToRelease.size());
+  Info.popLastNVariables(E.getIsSigned(), E.ValuesToRelease.size());
   DFSInStack.pop_back();
   if (ReproducerModule)
     ReproducerCondStack.pop_back();
@@ -2463,8 +2465,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
         break;
       LLVM_DEBUG({
         dbgs() << "Removing ";
-        dumpConstraint(Info.getCS(E.IsSigned).getLastConstraint(),
-                       Info.getValue2Index(E.IsSigned));
+        dumpConstraint(Info.getCS(E.getIsSigned()).getLastConstraint(),
+                       Info.getValue2Index(E.getIsSigned()));
         dbgs() << "\n";
       });
       removeEntryFromStack(E, Info, ReproducerModule.get(), ReproducerCondStack,
@@ -2716,7 +2718,7 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
 
 #ifndef NDEBUG
   unsigned SignedEntries =
-      count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; });
+      count_if(DFSInStack, [](const StackEntry &E) { return E.getIsSigned(); });
   assert(Info.getCS(false).size() - FunctionArgs.size() ==
              DFSInStack.size() - SignedEntries &&
          "updates to CS and DFSInStack are out of sync");
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 1266fd0708bfe..069f86a9a15df 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -38,6 +38,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -933,15 +934,26 @@ struct DSEState {
   // Check if there are root nodes that are terminated by UnreachableInst.
   // Those roots pessimize post-dominance queries. If there are such roots,
   // fall back to CFG scan starting from all non-unreachable roots.
-  bool AnyUnreachableExit;
+  bool getAnyUnreachableExit() const { return ToRemove.getFlag(0); }
+  bool setAnyUnreachableExit(bool Value) {
+    ToRemove.setFlag(0, Value);
+    return Value;
+  }
 
   // Whether or not we should iterate on removing dead stores at the end of the
   // function due to removing a store causing a previously captured pointer to
   // no longer be captured.
-  bool ShouldIterateEndOfFunctionDSE;
+  bool getShouldIterateEndOfFunctionDSE() const { return ToRemove.getFlag(1); }
+  bool setShouldIterateEndOfFunctionDSE(bool Value) {
+    ToRemove.setFlag(1, Value);
+    return Value;
+  }
 
   /// Dead instructions to be removed at the end of DSE.
-  SmallVector<Instruction *> ToRemove;
+  llvm::SmallVectorWithFlags<
+      Instruction *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<Instruction *>::value, 2>
+      ToRemove;
 
   // Class contains self-reference, make sure it's not copied/moved.
   DSEState(const ScalarOptions &Opts, Function &F, AliasAnalysis &AA,
@@ -1163,9 +1175,9 @@ DSEState::DSEState(const ScalarOptions &Opts, Function &F, AliasAnalysis &AA,
       InvisibleToCallerAfterRetBounded.insert({&AI, DeadBytes});
   }
 
-  AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) {
+  setAnyUnreachableExit(any_of(PDT.roots(), [](const BasicBlock *E) {
     return isa<UnreachableInst>(E->getTerminator());
-  });
+  }));
 }
 
 LocationSize DSEState::strengthenLocationSize(const Instruction *I,
@@ -1902,7 +1914,7 @@ std::optional<MemoryAccess *> DSEState::getDomMemoryDef(
     // there is a path from MaybeDeadAccess to an exit not going through a
     // killing block.
     if (!PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) {
-      if (!AnyUnreachableExit)
+      if (!getAnyUnreachableExit())
         return std::nullopt;
 
       // Fall back to CFG scan starting at all non-unreachable roots if not
@@ -1982,7 +1994,7 @@ void DSEState::deleteDeadInstruction(Instruction *SI,
           if (SI->getValueOperand()->getType()->isPointerTy()) {
             const Value *UO = getUnderlyingObject(SI->getValueOperand());
             if (CapturedBeforeReturn.erase(UO))
-              ShouldIterateEndOfFunctionDSE = true;
+              setShouldIterateEndOfFunctionDSE(true);
             InvisibleToCallerAfterRet.erase(UO);
             InvisibleToCallerAfterRetBounded.erase(UO);
           }
@@ -2057,7 +2069,7 @@ bool DSEState::eliminateDeadWritesAtEndOfFunction() {
   LLVM_DEBUG(
       dbgs() << "Trying to eliminate MemoryDefs at the end of the function\n");
   do {
-    ShouldIterateEndOfFunctionDSE = false;
+    setShouldIterateEndOfFunctionDSE(false);
     for (MemoryDef *Def : llvm::reverse(MemDefs)) {
       if (SkipStores.contains(Def))
         continue;
@@ -2088,7 +2100,7 @@ bool DSEState::eliminateDeadWritesAtEndOfFunction() {
         MadeChange = true;
       }
     }
-  } while (ShouldIterateEndOfFunctionDSE);
+  } while (getShouldIterateEndOfFunctionDSE());
   return MadeChange;
 }
 
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index ccd923cf7cc79..a015df31630cf 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -681,9 +681,9 @@ class EarlyCSE {
           case Intrinsic::masked_load:
             Info.PtrVal = Inst->getOperand(0);
             Info.MatchingId = Intrinsic::masked_load;
-            Info.ReadMem = true;
-            Info.WriteMem = false;
-            Info.IsVolatile = false;
+            Info.setReadMem(true);
+            Info.setWriteMem(false);
+            Info.setIsVolatile(false);
             break;
           case Intrinsic::masked_store:
             Info.PtrVal = Inst->getOperand(1);
@@ -694,17 +694,17 @@ class EarlyCSE {
             // so keep the MatchingIds specific to masked instructions
             // for now (TODO).
             Info.MatchingId = Intrinsic::masked_load;
-            Info.ReadMem = false;
-            Info.WriteMem = true;
-            Info.IsVolatile = false;
+            Info.setReadMem(false);
+            Info.setWriteMem(true);
+            Info.setIsVolatile(false);
             break;
           }
         } else if (auto *MI = dyn_cast<MemSetInst>(Inst)) {
           Info.PtrVal = MI->getDest();
           Info.MatchingId = 0;
-          Info.ReadMem = false;
-          Info.WriteMem = true;
-          Info.IsVolatile = MI->isVolatile();
+          Info.setReadMem(false);
+          Info.setWriteMem(true);
+          Info.setIsVolatile(MI->isVolatile());
         }
       }
     }
@@ -714,13 +714,13 @@ class EarlyCSE {
 
     bool isLoad() const {
       if (IntrID != 0)
-        return Info.ReadMem;
+        return Info.getReadMem();
       return isa<LoadInst>(Inst);
     }
 
     bool isStore() const {
       if (IntrID != 0)
-        return Info.WriteMem;
+        return Info.getWriteMem();
       return isa<StoreInst>(Inst);
     }
 
@@ -745,7 +745,7 @@ class EarlyCSE {
 
     bool isVolatile() const {
       if (IntrID != 0)
-        return Info.IsVolatile;
+        return Info.getIsVolatile();
 
       if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
         return LI->isVolatile();
@@ -787,13 +787,13 @@ class EarlyCSE {
 
     bool mayReadFromMemory() const {
       if (IntrID != 0)
-        return Info.ReadMem;
+        return Info.getReadMem();
       return Inst->mayReadFromMemory();
     }
 
     bool mayWriteToMemory() const {
       if (IntrID != 0)
-        return Info.WriteMem;
+        return Info.getWriteMem();
       return Inst->mayWriteToMemory();
     }
 
diff --git a/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp b/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
index a22a2e5e62f08..466aec5fdd1c6 100644
--- a/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
+++ b/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/Transforms/Scalar/ExpandMemCmp.h"
 #include "ScalarOptions.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
@@ -81,7 +82,7 @@ class MemCmpExpansion {
   std::vector<BasicBlock *> LoadCmpBlocks;
   BasicBlock *EndBlock = nullptr;
   PHINode *PhiRes = nullptr;
-  const bool IsUsedForZeroCmp;
+  bool getIsUsedForZeroCmp() const { return LoadSequence.getFlag(0); }
   const DataLayout &DL;
   const TargetTransformInfo &TTI;
   // The known common alignment of the two source pointers.
@@ -102,7 +103,7 @@ class MemCmpExpansion {
     uint64_t Offset;
   };
   using LoadEntryVector = SmallVector<LoadEntry, 8>;
-  LoadEntryVector LoadSequence;
+  llvm::SmallVectorWithFlagsFor<LoadEntryVector, 1> LoadSequence;
 
   void createLoadCmpBlocks();
   void createResultBlock();
@@ -137,9 +138,7 @@ class MemCmpExpansion {
                                                  unsigned MaxNumLoads) const;
 
   void optimiseLoadSequence(
-      LoadEntryVector &LoadSequence,
-      const TargetTransformInfo::MemCmpExpansionOptions &Options,
-      bool IsUsedForZeroCmp) const;
+      const TargetTransformInfo::MemCmpExpansionOptions &Options);
 
 public:
   MemCmpExpansion(CallInst *CI, uint64_t Size,
@@ -259,14 +258,12 @@ MemCmpExpansion::computeOverlappingLoadSequence(
 }
 
 void MemCmpExpansion::optimiseLoadSequence(
-    LoadEntryVector &LoadSequence,
-    const TargetTransformInfo::MemCmpExpansionOptions &Options,
-    bool IsUsedForZeroCmp) const {
+    const TargetTransformInfo::MemCmpExpansionOptions &Options) {
   // This part of code attempts to optimize the LoadSequence by merging allowed
   // subsequences into single loads of allowed sizes from
   // `MemCmpExpansionOptions::AllowedTailExpansions`. If it is for zero
   // comparison or if no allowed tail expansions are specified, we exit early.
-  if (IsUsedForZeroCmp || Options.AllowedTailExpansions.empty())
+  if (getIsUsedForZeroCmp() || Options.AllowedTailExpansions.empty())
     return;
 
   while (LoadSequence.size() >= 2) {
@@ -313,9 +310,10 @@ MemCmpExpansion::MemCmpExpansion(
     DomTreeUpdater *DTU, const TargetTransformInfo &TTI, Align CommonAlign,
     unsigned MaxBytesPerBlock)
     : CI(CI), Size(Size), NumLoadsPerBlock(Options.NumLoadsPerBlock),
-      MaxBytesPerBlock(MaxBytesPerBlock), IsUsedForZeroCmp(IsUsedForZeroCmp),
-      DL(TheDataLayout), TTI(TTI), CommonAlign(CommonAlign), DTU(DTU),
-      Builder(CI) {
+      MaxBytesPerBlock(MaxBytesPerBlock), DL(TheDataLayout), TTI(TTI),
+      CommonAlign(CommonAlign), DTU(DTU), Builder(CI),
+      LoadSequence(
+          decltype(this->LoadSequence)::withFlags(unsigned(IsUsedForZeroCmp))) {
   assert(Size > 0 && "zero blocks");
   assert(NumLoadsPerBlock > 0 && "zero loads per block");
   // Scale the max size down if the target can load more bytes than we need.
@@ -326,8 +324,8 @@ MemCmpExpansion::MemCmpExpansion(
   assert(!LoadSizes.empty() && "cannot load Size bytes");
   MaxLoadSize = LoadSizes.front();
   // Compute the decomposition.
-  LoadSequence =
-      computeGreedyLoadSequence(Size, LoadSizes, Options.MaxNumLoads);
+  LoadSequence.assign(
+      computeGreedyLoadSequence(Size, LoadSizes, Options.MaxNumLoads));
   assert(LoadSequence.size() <= Options.MaxNumLoads && "broken invariant");
   // If we allow overlapping loads and the load sequence is not already optimal,
   // use overlapping loads.
@@ -338,11 +336,12 @@ MemCmpExpansion::MemCmpExpansion(
     if (!OverlappingLoads.empty() &&
         (LoadSequence.empty() ||
          OverlappingLoads.size() < LoadSequence.size())) {
-      LoadSequence = OverlappingLoads;
+      if (LoadSequence.data() != OverlappingLoads.data())
+        LoadSequence.assign(OverlappingLoads.begin(), OverlappingLoads.end());
     }
   }
   assert(LoadSequence.size() <= Options.MaxNumLoads && "broken invariant");
-  optimiseLoadSequence(LoadSequence, Options, IsUsedForZeroCmp);
+  optimiseLoadSequence(Options);
 
   unsigned LoadIndex = 0;
   while (LoadIndex < getNumLoads()) {
@@ -356,7 +355,7 @@ MemCmpExpansion::MemCmpExpansion(
 }
 
 unsigned MemCmpExpansion::getNumLoadsInBlock(unsigned LoadIndex) const {
-  if (IsUsedForZeroCmp)
+  if (getIsUsedForZeroCmp())
     return std::min<uint64_t>(getNumLoads() - LoadIndex, NumLoadsPerBlock);
 
   unsigned NumLoads = 0;
@@ -662,7 +661,7 @@ void MemCmpExpansion::emitLoadCompareBlock(unsigned BlockIndex,
 
   // Add the loaded values to the phi nodes for calculating memcmp result only
   // if result is not used in a zero equality.
-  if (!IsUsedForZeroCmp) {
+  if (!getIsUsedForZeroCmp()) {
     ResBlock.PhiSrc1->addIncoming(Loads.Lhs, LoadCmpBlocks[BlockIndex]);
     ResBlock.PhiSrc2->addIncoming(Loads.Rhs, LoadCmpBlocks[BlockIndex]);
   }
@@ -696,7 +695,7 @@ void MemCmpExpansion::emitLoadCompareBlock(unsigned BlockIndex,
 void MemCmpExpansion::emitMemCmpResultBlock() {
   // Special case: if memcmp result is used in a zero equality, result does not
   // need to be calculated and can simply return 1.
-  if (IsUsedForZeroCmp) {
+  if (getIsUsedForZeroCmp()) {
     BasicBlock::iterator InsertPt = ResBlock.BB->getFirstInsertionPt();
     Builder.SetInsertPoint(InsertPt);
     Value *Res = ConstantInt::get(Type::getInt32Ty(CI->getContext()), 1);
@@ -856,7 +855,8 @@ Value *MemCmpExpansion::getMemCmpExpansion() {
     // calculate which source was larger. The calculation requires the
     // two loaded source values of each load compare block.
     // These will be saved in the phi nodes created by setupResultBlockPHINodes.
-    if (!IsUsedForZeroCmp) setupResultBlockPHINodes();
+    if (!getIsUsedForZeroCmp())
+      setupResultBlockPHINodes();
 
     // Create the number of required load compare basic blocks.
     createLoadCmpBlocks();
@@ -871,7 +871,7 @@ Value *MemCmpExpansion::getMemCmpExpansion() {
 
   Builder.SetCurrentDebugLocation(CI->getDebugLoc());
 
-  if (IsUsedForZeroCmp)
+  if (getIsUsedForZeroCmp())
     return getNumBlocks() == 1 ? getMemCmpEqZeroOneBlock()
                                : getMemCmpExpansionZeroCase();
 
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 113b3abf484cd..45d0c20a0a2fd 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumeBundleQueries.h"
@@ -291,7 +292,8 @@ class llvm::GVNPassImpl {
   // This is set 'true' initially and also when new blocks have been added to
   // the function being analyzed. This boolean is used to control the updating
   // of BlockRPONumber prior to accessing the contents of BlockRPONumber.
-  bool InvalidBlockRPONumbers = true;
+  bool getInvalidBlockRPONumbers() const { return !ToSplit.getFlag(0); }
+  void setInvalidBlockRPONumbers(bool Value) { ToSplit.setFlag(0, !Value); }
 
   using LoadDepVect = SmallVector<NonLocalDepResult, 64>;
   using AvailValInBlkVect = SmallVector<AvailableValueInBlock, 64>;
@@ -303,7 +305,7 @@ class llvm::GVNPassImpl {
            OptimizationRemarkEmitter *ORE, MemorySSA *MSSA = nullptr);
 
   // List of critical edges to be split between iterations.
-  SmallVector<std::pair<Instruction *, unsigned>, 4> ToSplit;
+  llvm::SmallVectorWithFlags<std::pair<Instruction *, unsigned>, 4> ToSplit;
 
   enum class DepKind {
     Other = 0, // Unknown value.
@@ -3422,7 +3424,7 @@ void GVNPassImpl::assignBlockRPONumber(Function &F) {
   ReversePostOrderTraversal<Function *> RPOT(&F);
   for (BasicBlock *BB : RPOT)
     BlockRPONumber[BB] = NextBlockNumber++;
-  InvalidBlockRPONumbers = false;
+  setInvalidBlockRPONumbers(false);
 }
 
 /// The given values are known to be equal in every use
@@ -3853,7 +3855,7 @@ bool GVNPassImpl::run(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
   // IsMSSAEnabled is turned on.
   VN.setMemorySSA(MSSA, isMemorySSAEnabled());
   ORE = RunORE;
-  InvalidBlockRPONumbers = true;
+  setInvalidBlockRPONumbers(true);
   MemorySSAUpdater Updater(MSSA);
   MSSAU = MSSA ? &Updater : nullptr;
 
@@ -4022,7 +4024,7 @@ bool GVNPassImpl::performScalarPRE(Instruction *CurInst) {
   BasicBlock *CurrentBlock = CurInst->getParent();
 
   // Update the RPO numbers for this function.
-  if (InvalidBlockRPONumbers)
+  if (getInvalidBlockRPONumbers())
     assignBlockRPONumber(*CurrentBlock->getParent());
 
   SmallVector<std::pair<Value *, BasicBlock *>, 8> PredMap;
@@ -4177,7 +4179,7 @@ BasicBlock *GVNPassImpl::splitCriticalEdges(BasicBlock *Pred,
   if (BB) {
     if (MD)
       MD->invalidateCachedPredecessors();
-    InvalidBlockRPONumbers = true;
+    setInvalidBlockRPONumbers(true);
   }
   return BB;
 }
@@ -4198,7 +4200,7 @@ bool GVNPassImpl::splitCriticalEdges() {
   if (Changed) {
     if (MD)
       MD->invalidateCachedPredecessors();
-    InvalidBlockRPONumbers = true;
+    setInvalidBlockRPONumbers(true);
   }
   return Changed;
 }
@@ -4225,7 +4227,7 @@ void GVNPassImpl::cleanupGlobalSets() {
   LeaderTable.clear();
   BlockRPONumber.clear();
   ICF->clear();
-  InvalidBlockRPONumbers = true;
+  setInvalidBlockRPONumbers(true);
 }
 
 void GVNPassImpl::removeInstruction(Instruction *I) {
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 267eabedce27f..4e912c072e50a 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -28,8 +28,10 @@
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/LoopInfo.h"
@@ -100,10 +102,12 @@ class IndVarSimplify {
   const TargetTransformInfo *TTI;
   std::unique_ptr<MemorySSAUpdater> MSSAU;
 
-  SmallVector<WeakTrackingVH, 16> DeadInsts;
-  bool WidenIndVars;
+  llvm::SmallVectorWithFlags<WeakTrackingVH, 16, 2> DeadInsts;
+  bool getWidenIndVars() const { return DeadInsts.getFlag(0); }
+  void setWidenIndVars(bool Value) { DeadInsts.setFlag(0, Value); }
 
-  bool RunUnswitching = false;
+  bool getRunUnswitching() const { return DeadInsts.getFlag(1); }
+  void setRunUnswitching(bool Value) { DeadInsts.setFlag(1, Value); }
 
   bool handleFloatingPointIV(Loop *L, PHINode *PH);
   bool rewriteNonIntegerIVs(Loop *L);
@@ -127,20 +131,29 @@ class IndVarSimplify {
 
   bool sinkUnusedInvariants(Loop *L);
 
+  template <typename CallbackT>
+  decltype(auto) withDeadInsts(CallbackT &&Callback) {
+    SmallVector<WeakTrackingVH, 16> Pending;
+    Pending = std::move(DeadInsts);
+    auto Restore = scope_exit([&] { DeadInsts.assign(std::move(Pending)); });
+    return Callback(Pending);
+  }
+
 public:
   IndVarSimplify(const ScalarOptions &Opts, LoopInfo *LI, ScalarEvolution *SE,
                  DominatorTree *DT, const DataLayout &DL,
                  TargetLibraryInfo *TLI, TargetTransformInfo *TTI,
                  MemorySSA *MSSA, bool WidenIndVars)
       : Opts(Opts), LI(LI), SE(SE), DT(DT), DL(DL), TLI(TLI), TTI(TTI),
-        WidenIndVars(WidenIndVars) {
+        DeadInsts(
+            decltype(this->DeadInsts)::withFlags(unsigned(WidenIndVars))) {
     if (MSSA)
       MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
   }
 
   bool run(Loop *L);
 
-  bool runUnswitching() const { return RunUnswitching; }
+  bool runUnswitching() const { return getRunUnswitching(); }
 };
 
 } // end anonymous namespace
@@ -695,26 +708,30 @@ bool IndVarSimplify::simplifyAndExtend(Loop *L,
       // Information about sign/zero extensions of CurrIV.
       IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT);
 
-      const auto &[C, U] = simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts,
-                                             Rewriter, &Visitor);
+      const auto &[C, U] = withDeadInsts([&](auto &DeadInsts) {
+        return simplifyUsersOfIV(CurrIV, SE, DT, LI, TTI, DeadInsts, Rewriter,
+                                 &Visitor);
+      });
 
       Changed |= C;
-      RunUnswitching |= U;
+      setRunUnswitching(int(getRunUnswitching()) | (U));
       if (Visitor.WI.WidestNativeType) {
         WideIVs.push_back(Visitor.WI);
       }
     } while(!LoopPhis.empty());
 
     // Continue if we disallowed widening.
-    if (!WidenIndVars)
+    if (!getWidenIndVars())
       continue;
 
     for (; !WideIVs.empty(); WideIVs.pop_back()) {
       unsigned ElimExt;
       unsigned Widened;
-      if (PHINode *WidePhi = createWideIV(
-              WideIVs.back(), LI, SE, Rewriter, DT, DeadInsts, ElimExt, Widened,
-              HasGuards, Opts.indvars_post_increment_ranges)) {
+      if (PHINode *WidePhi = withDeadInsts([&](auto &DeadInsts) {
+            return createWideIV(WideIVs.back(), LI, SE, Rewriter, DT, DeadInsts,
+                                ElimExt, Widened, HasGuards,
+                                Opts.indvars_post_increment_ranges);
+          })) {
         NumElimExt += ElimExt;
         NumWidened += Widened;
         Changed = true;
@@ -1646,7 +1663,9 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
       // unconditional exit, we can still replace header phis with their
       // preheader value.
       if (!L->contains(BI->getSuccessor(CI->isNullValue())))
-        replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts, *SE);
+        withDeadInsts([&](auto &DeadInsts) {
+          return replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts, *SE);
+        });
       return true;
     }
 
@@ -1707,9 +1726,11 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
       // will remain the same within iteration space?
       auto *BI = cast<CondBrInst>(ExitingBB->getTerminator());
       auto OptimizeCond = [&](bool SkipLastIter) {
-        return optimizeLoopExitWithUnknownExitCount(L, BI, ExitingBB,
-                                                    MaxBECount, SkipLastIter,
-                                                    SE, Rewriter, DeadInsts);
+        return withDeadInsts([&](auto &DeadInsts) {
+          return optimizeLoopExitWithUnknownExitCount(L, BI, ExitingBB,
+                                                      MaxBECount, SkipLastIter,
+                                                      SE, Rewriter, DeadInsts);
+        });
       };
 
       // TODO: We might have proved that we can skip the last iteration for
@@ -1744,8 +1765,12 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
     // We know that the backedge can't be taken, so we replace all
     // the header PHIs with values coming from the preheader.
     if (ExactExitCount->isZero()) {
-      foldExit(L, ExitingBB, true, DeadInsts);
-      replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts, *SE);
+      withDeadInsts([&](auto &DeadInsts) {
+        return foldExit(L, ExitingBB, true, DeadInsts);
+      });
+      withDeadInsts([&](auto &DeadInsts) {
+        return replaceLoopPHINodesWithPreheaderValues(LI, L, DeadInsts, *SE);
+      });
       Changed = true;
       continue;
     }
@@ -1764,7 +1789,9 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
     // one?
     if (SE->isLoopEntryGuardedByCond(L, CmpInst::ICMP_ULT, MaxBECount,
                                      ExactExitCount)) {
-      foldExit(L, ExitingBB, false, DeadInsts);
+      withDeadInsts([&](auto &DeadInsts) {
+        return foldExit(L, ExitingBB, false, DeadInsts);
+      });
       Changed = true;
       continue;
     }
@@ -1774,7 +1801,9 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
     // exiting iteration, but (from the visit order) strictly follows another
     // which does the same and is thus dead.
     if (!DominatingExactExitCounts.insert(ExactExitCount).second) {
-      foldExit(L, ExitingBB, false, DeadInsts);
+      withDeadInsts([&](auto &DeadInsts) {
+        return foldExit(L, ExitingBB, false, DeadInsts);
+      });
       Changed = true;
       continue;
     }
@@ -2005,7 +2034,7 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
     if (OldCond->use_empty())
       DeadInsts.emplace_back(OldCond);
     Changed = true;
-    RunUnswitching = true;
+    setRunUnswitching(true);
   }
 
   return Changed;
@@ -2057,15 +2086,19 @@ bool IndVarSimplify::run(Loop *L) {
   // loop into any instructions outside of the loop that use the final values
   // of the current expressions.
   if (Opts.replexitval != NeverRepl) {
-    if (int Rewrites = rewriteLoopExitValues(L, LI, TLI, SE, TTI, Rewriter, DT,
-                                             Opts.replexitval, DeadInsts)) {
+    if (int Rewrites = withDeadInsts([&](auto &DeadInsts) {
+          return rewriteLoopExitValues(L, LI, TLI, SE, TTI, Rewriter, DT,
+                                       Opts.replexitval, DeadInsts);
+        })) {
       NumReplaced += Rewrites;
       Changed = true;
     }
   }
 
   // Eliminate redundant IV cycles.
-  NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI);
+  NumElimIV += withDeadInsts([&](auto &DeadInsts) {
+    return Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI);
+  });
 
   // Try to convert exit conditions to unsigned and rotate computation
   // out of the loop.  Note: Handles invalidation internally if needed.
diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
index 0044174efcb66..dd80039aaa848 100644
--- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
@@ -29,6 +29,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -96,12 +97,14 @@ class InstPartition {
 
 public:
   InstPartition(Instruction *I, Loop *L, bool DepCycle = false)
-      : DepCycle(DepCycle), OrigLoop(L) {
+      : OrigLoop(L),
+        ClonedLoopBlocks(
+            decltype(this->ClonedLoopBlocks)::withFlags(unsigned(DepCycle))) {
     Set.insert(I);
   }
 
   /// Returns whether this partition contains a dependence cycle.
-  bool hasDepCycle() const { return DepCycle; }
+  bool hasDepCycle() const { return getDepCycle(); }
 
   /// Adds an instruction to this partition.
   void add(Instruction *I) { Set.insert(I); }
@@ -118,7 +121,7 @@ class InstPartition {
   void moveTo(InstPartition &Other) {
     Other.Set.insert_range(Set);
     Set.clear();
-    Other.DepCycle |= DepCycle;
+    Other.setDepCycle(int(Other.getDepCycle()) | (getDepCycle()));
   }
 
   /// Populates the partition with a transitive closure of all the
@@ -151,9 +154,12 @@ class InstPartition {
   Loop *cloneLoopWithPreheader(BasicBlock *InsertBefore, BasicBlock *LoopDomBB,
                                unsigned Index, LoopInfo *LI,
                                DominatorTree *DT) {
+    SmallVector<BasicBlock *, 8> Blocks;
+    Blocks = std::move(ClonedLoopBlocks);
     ClonedLoop = ::cloneLoopWithPreheader(InsertBefore, LoopDomBB, OrigLoop,
                                           VMap, Twine(".ldist") + Twine(Index),
-                                          LI, DT, ClonedLoopBlocks);
+                                          LI, DT, Blocks);
+    ClonedLoopBlocks.assign(std::move(Blocks));
     return ClonedLoop;
   }
 
@@ -205,7 +211,7 @@ class InstPartition {
   }
 
   void print(raw_ostream &OS) const {
-    OS << (DepCycle ? " (cycle)\n" : "\n");
+    OS << (getDepCycle() ? " (cycle)\n" : "\n");
     for (auto *I : Set)
       // Prefix with the block name.
       OS << "  " << I->getParent()->getName() << ":" << *I << "\n";
@@ -221,7 +227,8 @@ class InstPartition {
   InstructionSet Set;
 
   /// Whether this partition contains a dependence cycle.
-  bool DepCycle;
+  bool getDepCycle() const { return ClonedLoopBlocks.getFlag(0); }
+  void setDepCycle(bool Value) { ClonedLoopBlocks.setFlag(0, Value); }
 
   /// The original loop.
   Loop *OrigLoop;
@@ -232,7 +239,7 @@ class InstPartition {
 
   /// The blocks of ClonedLoop including the preheader.  If this
   /// partition is mapped to the original loop, this is empty.
-  SmallVector<BasicBlock *, 8> ClonedLoopBlocks;
+  llvm::SmallVectorWithFlags<BasicBlock *, 8> ClonedLoopBlocks;
 
   /// These gets populated once the set of instructions have been
   /// finalized. If this partition is mapped to the original loop, these are not
@@ -596,9 +603,8 @@ class MemoryInstructionDependences {
   AccessesType::const_iterator begin() const { return Accesses.begin(); }
   AccessesType::const_iterator end() const { return Accesses.end(); }
 
-  MemoryInstructionDependences(
-      const SmallVectorImpl<Instruction *> &Instructions,
-      const SmallVectorImpl<Dependence> &Dependences) {
+  MemoryInstructionDependences(ArrayRef<Instruction *> Instructions,
+                               const SmallVectorImpl<Dependence> &Dependences) {
     Accesses.append(Instructions.begin(), Instructions.end());
 
     LLVM_DEBUG(dbgs() << "LDist: Backward dependences:\n");
diff --git a/llvm/lib/Transforms/Scalar/LoopFuse.cpp b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
index b9e65fb0ed520..f091d2fa6e594 100644
--- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
@@ -48,6 +48,7 @@
 #include "ScalarOptions.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
@@ -139,17 +140,20 @@ struct FusionCandidate {
   /// Vector of instructions in this loop that read from memory
   SmallVector<Instruction *, 16> MemReads;
   /// Vector of instructions in this loop that write to memory
-  SmallVector<Instruction *, 16> MemWrites;
+  llvm::SmallVectorWithFlags<Instruction *, 16, 3> MemWrites;
   /// Are all of the members of this fusion candidate still valid
-  bool Valid;
+  bool getValid() const { return MemWrites.getFlag(0); }
+  void setValid(bool Value) { MemWrites.setFlag(0, Value); }
   /// Guard branch of the loop, if it exists
   CondBrInst *GuardBranch;
   /// Peeling Paramaters of the Loop.
   TTI::PeelingPreferences PP;
   /// Can you Peel this Loop?
-  bool AbleToPeel;
+  bool getAbleToPeel() const { return MemWrites.getFlag(1); }
+  void setAbleToPeel(bool Value) { MemWrites.setFlag(1, Value); }
   /// Has this loop been Peeled
-  bool Peeled;
+  bool getPeeled() const { return MemWrites.getFlag(2); }
+  void setPeeled(bool Value) { MemWrites.setFlag(2, Value); }
 
   DominatorTree &DT;
   const PostDominatorTree *PDT;
@@ -160,9 +164,11 @@ struct FusionCandidate {
                   OptimizationRemarkEmitter &ORE, TTI::PeelingPreferences PP)
       : Preheader(L->getLoopPreheader()), Header(L->getHeader()),
         ExitingBlock(L->getExitingBlock()), ExitBlock(L->getExitBlock()),
-        Latch(L->getLoopLatch()), L(L), Valid(true),
-        GuardBranch(L->getLoopGuardBranch()), PP(PP), AbleToPeel(canPeel(L)),
-        Peeled(false), DT(DT), PDT(PDT), ORE(ORE) {
+        Latch(L->getLoopLatch()), L(L),
+        MemWrites(decltype(this->MemWrites)::withFlags(
+            (unsigned(bool(canPeel(L))) << 1) | 1)),
+        GuardBranch(L->getLoopGuardBranch()), PP(PP), DT(DT), PDT(PDT),
+        ORE(ORE) {
 
     // Walk over all blocks in the loop and check for conditions that may
     // prevent fusion. For each block, walk over all instructions and collect
@@ -213,7 +219,7 @@ struct FusionCandidate {
   /// Check if all members of the class are valid.
   bool isValid() const {
     return Preheader && ExitingBlock && ExitBlock && Latch && L &&
-           !L->isInvalid() && Valid;
+           !L->isInvalid() && getValid();
   }
 
   /// Verify that all members are in sync with the Loop object.
@@ -259,7 +265,7 @@ struct FusionCandidate {
   /// This method is only valid for guarded loops.
   BasicBlock *getNonLoopBlock() const {
     assert(GuardBranch && "Only valid on guarded loops.");
-    if (Peeled)
+    if (getPeeled())
       return GuardBranch->getSuccessor(1);
     return (GuardBranch->getSuccessor(0) == Preheader)
                ? GuardBranch->getSuccessor(1)
@@ -336,7 +342,7 @@ struct FusionCandidate {
   void invalidate() {
     MemWrites.clear();
     MemReads.clear();
-    Valid = false;
+    setValid(false);
   }
 
   // Emit an analysis remark explaining why this loop cannot be fused. The
@@ -740,7 +746,7 @@ struct LoopFuser {
 
   void peelFusionCandidate(FusionCandidate &FC0, const FusionCandidate &FC1,
                            unsigned PeelCount) {
-    assert(FC0.AbleToPeel && "Should be able to peel loop");
+    assert(FC0.getAbleToPeel() && "Should be able to peel loop");
 
     LLVM_DEBUG(dbgs() << "Attempting to peel first " << PeelCount
                       << " iterations of the first loop. \n");
@@ -751,7 +757,7 @@ struct LoopFuser {
     // simplifyLoop call.
     peelLoop(FC0.L, PeelCount, /*PeelLast=*/false, &LI, &SE, DT, &AC,
              /*PreserveLCSSA=*/false, VMap);
-    FC0.Peeled = true;
+    FC0.setPeeled(true);
     LLVM_DEBUG(dbgs() << "Done Peeling\n");
 
 #ifndef NDEBUG
@@ -845,9 +851,10 @@ struct LoopFuser {
         // the first loop has a larger trip count. In this case it is possible
         // that the first loop is peeled to expose the fusion opportunity.
         // Peeling the second loop is not currently supported.
-        bool WillPeel = FC0.AbleToPeel && TCDifference && *TCDifference > 0 &&
-                        *TCDifference <= static_cast<int64_t>(
-                                             Opts.loop_fusion_peel_max_count);
+        bool WillPeel =
+            FC0.getAbleToPeel() && TCDifference && *TCDifference > 0 &&
+            *TCDifference <=
+                static_cast<int64_t>(Opts.loop_fusion_peel_max_count);
 
         if (!WillPeel && (!TCDifference || *TCDifference != 0)) {
           LLVM_DEBUG(dbgs() << "Fusion candidates do not have identical trip "
@@ -1718,8 +1725,9 @@ struct LoopFuser {
     if (FC0.GuardBranch)
       return fuseGuardedLoops(FC0, FC1);
 
-    assert(FC1.Preheader ==
-           (FC0.Peeled ? FC0.ExitBlock->getUniqueSuccessor() : FC0.ExitBlock));
+    assert(FC1.Preheader == (FC0.getPeeled()
+                                 ? FC0.ExitBlock->getUniqueSuccessor()
+                                 : FC0.ExitBlock));
     assert(FC1.Preheader->size() == 1 &&
            FC1.Preheader->getSingleSuccessor() == FC1.Header);
 
@@ -1761,7 +1769,7 @@ struct LoopFuser {
     // to FC1.Header? I think this is basically what the three sequences are
     // trying to accomplish; however, doing this directly in the CFG may mean
     // the DT/PDT becomes invalid
-    if (!FC0.Peeled) {
+    if (!FC0.getPeeled()) {
       FC0.ExitingBlock->getTerminator()->replaceUsesOfWith(FC1.Preheader,
                                                            FC1.Header);
       TreeUpdates.emplace_back(DominatorTree::UpdateType(
@@ -1797,7 +1805,7 @@ struct LoopFuser {
 
     LI.removeBlock(FC1.Preheader);
     DTU.deleteBB(FC1.Preheader);
-    if (FC0.Peeled) {
+    if (FC0.getPeeled()) {
       LI.removeBlock(FC0.ExitBlock);
       DTU.deleteBB(FC0.ExitBlock);
     }
@@ -1881,8 +1889,8 @@ struct LoopFuser {
     // case that FC0 loop is peeled, then move the instructions of the successor
     // of the FC0 Exit block to the beginning of the exit block of FC1.
     moveInstructionsToTheBeginning(
-        (FC0.Peeled ? *FC0ExitBlockSuccessor : *FC0.ExitBlock), *FC1.ExitBlock,
-        DT, PDT, DI, SE);
+        (FC0.getPeeled() ? *FC0ExitBlockSuccessor : *FC0.ExitBlock),
+        *FC1.ExitBlock, DT, PDT, DI, SE);
 
     // Move instructions from the guard block of FC1 to the end of the guard
     // block of FC0.
@@ -1903,7 +1911,8 @@ struct LoopFuser {
     FC1NonLoopBlock->replacePhiUsesWith(FC1GuardBlock, FC0GuardBlock);
     FC0.GuardBranch->replaceUsesOfWith(FC0NonLoopBlock, FC1NonLoopBlock);
 
-    BasicBlock *BBToUpdate = FC0.Peeled ? FC0ExitBlockSuccessor : FC0.ExitBlock;
+    BasicBlock *BBToUpdate =
+        FC0.getPeeled() ? FC0ExitBlockSuccessor : FC0.ExitBlock;
     BBToUpdate->getTerminator()->replaceUsesOfWith(FC1GuardBlock, FC1.Header);
 
     // The guard of FC1 is not necessary anymore.
@@ -1919,7 +1928,7 @@ struct LoopFuser {
     TreeUpdates.emplace_back(DominatorTree::UpdateType(
         DominatorTree::Insert, FC0GuardBlock, FC1NonLoopBlock));
 
-    if (FC0.Peeled) {
+    if (FC0.getPeeled()) {
       TreeUpdates.emplace_back(DominatorTree::UpdateType(
           DominatorTree::Delete, FC0.ExitBlock, FC0ExitBlockSuccessor));
       // Remove the Block after the ExitBlock of FC0
@@ -2012,7 +2021,7 @@ struct LoopFuser {
     LI.removeBlock(FC1GuardBlock);
     LI.removeBlock(FC1.Preheader);
     LI.removeBlock(FC0.ExitBlock);
-    if (FC0.Peeled) {
+    if (FC0.getPeeled()) {
       LI.removeBlock(FC0ExitBlockSuccessor);
       DTU.deleteBB(FC0ExitBlockSuccessor);
     }
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index a188c33528e5e..370a9a2f9a6a4 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -37,6 +37,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/AliasAnalysis.h"
@@ -172,7 +173,12 @@ class LoopIdiomRecognize {
   const TargetTransformInfo *TTI;
   const DataLayout *DL;
   OptimizationRemarkEmitter &ORE;
-  bool ApplyCodeSizeHeuristics;
+  bool getApplyCodeSizeHeuristics() const {
+    return StoreRefsForMemcpy.getFlag(0);
+  }
+  void setApplyCodeSizeHeuristics(bool Value) {
+    StoreRefsForMemcpy.setFlag(0, Value);
+  }
   std::unique_ptr<MemorySSAUpdater> MSSAU;
 
 public:
@@ -196,10 +202,13 @@ class LoopIdiomRecognize {
 
   StoreListMap StoreRefsForMemset;
   StoreListMap StoreRefsForMemsetPattern;
-  StoreList StoreRefsForMemcpy;
-  bool HasMemset;
-  bool HasMemsetPattern;
-  bool HasMemcpy;
+  llvm::SmallVectorWithFlagsFor<StoreList, 4> StoreRefsForMemcpy;
+  bool getHasMemset() const { return StoreRefsForMemcpy.getFlag(1); }
+  void setHasMemset(bool Value) { StoreRefsForMemcpy.setFlag(1, Value); }
+  bool getHasMemsetPattern() const { return StoreRefsForMemcpy.getFlag(2); }
+  void setHasMemsetPattern(bool Value) { StoreRefsForMemcpy.setFlag(2, Value); }
+  bool getHasMemcpy() const { return StoreRefsForMemcpy.getFlag(3); }
+  void setHasMemcpy(bool Value) { StoreRefsForMemcpy.setFlag(3, Value); }
 
   /// Return code for isLegalStore()
   enum LegalStoreKind {
@@ -333,20 +342,20 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L) {
     return false;
 
   // Determine if code size heuristics need to be applied.
-  ApplyCodeSizeHeuristics =
-      L->getHeader()->getParent()->hasOptSize() && Opts.use_lir_code_size_heurs;
+  setApplyCodeSizeHeuristics(L->getHeader()->getParent()->hasOptSize() &&
+                             Opts.use_lir_code_size_heurs);
 
-  HasMemset = TLI->has(LibFunc_memset);
+  setHasMemset(TLI->has(LibFunc_memset));
   // TODO: Unconditionally enable use of the memset pattern intrinsic (or at
   // least, opt-in via target hook) once we are confident it will never result
   // in worse codegen than without. For now, use it only when the target
   // supports memset_pattern16 libcall (or unless this is overridden by
   // command line option).
-  HasMemsetPattern = TLI->has(LibFunc_memset_pattern16);
-  HasMemcpy = TLI->has(LibFunc_memcpy);
+  setHasMemsetPattern(TLI->has(LibFunc_memset_pattern16));
+  setHasMemcpy(TLI->has(LibFunc_memcpy));
 
-  if (HasMemset || HasMemsetPattern ||
-      Opts.loop_idiom_force_memset_pattern_intrinsic || HasMemcpy ||
+  if (getHasMemset() || getHasMemsetPattern() ||
+      Opts.loop_idiom_force_memset_pattern_intrinsic || getHasMemcpy() ||
       !DisableLIRP::HashRecognize)
     if (SE->hasLoopInvariantBackedgeTakenCount(L))
       return runOnCountableLoop();
@@ -507,7 +516,7 @@ LoopIdiomRecognize::isLegalStore(StoreInst *SI) {
 
   // If we're allowed to form a memset, and the stored value would be
   // acceptable for memset, use it.
-  if (!MustPreserveExternalState && !UnorderedAtomic && HasMemset &&
+  if (!MustPreserveExternalState && !UnorderedAtomic && getHasMemset() &&
       SplatValue && !DisableLIRP::Memset &&
       // Verify that the stored value is loop invariant.  If not, we can't
       // promote the memset.
@@ -516,7 +525,8 @@ LoopIdiomRecognize::isLegalStore(StoreInst *SI) {
     return LegalStoreKind::Memset;
   }
   if (!MustPreserveExternalState && !UnorderedAtomic &&
-      (HasMemsetPattern || Opts.loop_idiom_force_memset_pattern_intrinsic) &&
+      (getHasMemsetPattern() ||
+       Opts.loop_idiom_force_memset_pattern_intrinsic) &&
       !DisableLIRP::Memset &&
       // Don't create memset_pattern16s with address spaces.
       StorePtr->getType()->getPointerAddressSpace() == 0 &&
@@ -526,7 +536,7 @@ LoopIdiomRecognize::isLegalStore(StoreInst *SI) {
   }
 
   // Otherwise, see if the store can be turned into a memcpy.
-  if (HasMemcpy && !DisableLIRP::Memcpy) {
+  if (getHasMemcpy() && !DisableLIRP::Memcpy) {
     // Check to see if the stride matches the size of the store.  If so, then we
     // know that every byte is touched in the loop.
     unsigned StoreSize = DL->getTypeStoreSize(SI->getValueOperand()->getType());
@@ -815,7 +825,7 @@ bool LoopIdiomRecognize::processLoopMemCpy(MemCpyInst *MCI,
   // If we're not allowed to hack on memcpy, we fail. We don't mess with the
   // inlined version as generating a larger inline mempcy could affect code
   // size.
-  if (!HasMemcpy || MCI->isForceInlined() || DisableLIRP::Memcpy)
+  if (!getHasMemcpy() || MCI->isForceInlined() || DisableLIRP::Memcpy)
     return false;
 
   Value *Dest = MCI->getDest();
@@ -879,7 +889,7 @@ bool LoopIdiomRecognize::processLoopMemSet(MemSetInst *MSI,
 
   // If we're not allowed to hack on memset, we fail. We don't mess with the
   // inlined version as generating a larger memset could affect code size.
-  if (!HasMemset || MSI->isForceInlined() || DisableLIRP::Memset)
+  if (!getHasMemset() || MSI->isForceInlined() || DisableLIRP::Memset)
     return false;
 
   Value *Pointer = MSI->getDest();
@@ -1141,8 +1151,8 @@ bool LoopIdiomRecognize::processLoopStridedStore(
   Value *MemsetArg;
   std::optional<int64_t> BytesWritten;
 
-  if (PatternValue &&
-      (HasMemsetPattern || Opts.loop_idiom_force_memset_pattern_intrinsic)) {
+  if (PatternValue && (getHasMemsetPattern() ||
+                       Opts.loop_idiom_force_memset_pattern_intrinsic)) {
     const SCEV *TripCountS =
         SE->getTripCountFromExitCount(BECount, IntIdxTy, CurLoop);
     if (!Expander.isSafeToExpand(TripCountS))
@@ -1567,7 +1577,7 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(
 //
 bool LoopIdiomRecognize::avoidLIRForMultiBlockLoop(bool IsMemset,
                                                    bool IsLoopMemset) {
-  if (ApplyCodeSizeHeuristics && CurLoop->getNumBlocks() > 1) {
+  if (getApplyCodeSizeHeuristics() && CurLoop->getNumBlocks() > 1) {
     if (CurLoop->isOutermost() && (!IsMemset || !IsLoopMemset)) {
       LLVM_DEBUG(dbgs() << "  " << CurLoop->getHeader()->getParent()->getName()
                         << " : LIR " << (IsMemset ? "Memset" : "Memcpy")
@@ -1683,7 +1693,7 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
     // TODO: The clmul optimization is around the same size in many cases, so it
     // could be worth it to take advantage of that fact, especially if it would
     // be much faster than the original loop.
-    if (ApplyCodeSizeHeuristics) {
+    if (getApplyCodeSizeHeuristics()) {
       ReportMissed("optimizing for size");
       return false;
     }
diff --git a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
index a2ff998864456..8a1f57bf67440 100644
--- a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
 #include "ScalarOptions.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/LoopInfo.h"
@@ -113,7 +114,8 @@ class ConstantTerminatorFoldingImpl {
   SmallVector<DominatorTree::UpdateType, 16> DTUpdates;
 
   // Whether or not the current loop has irreducible CFG.
-  bool HasIrreducibleCFG = false;
+  bool getHasIrreducibleCFG() const { return FoldCandidates.getFlag(0); }
+  void setHasIrreducibleCFG(bool Value) { FoldCandidates.setFlag(0, Value); }
   // Whether or not the current loop will still exist after terminator constant
   // folding will be done. In theory, there are two ways how it can happen:
   // 1. Loop's latch(es) become unreachable from loop header;
@@ -122,9 +124,11 @@ class ConstantTerminatorFoldingImpl {
   // current loop and its preheader and do not affect preheader's reachibility
   // from any other block. So this variable set to true means that loop's latch
   // has become unreachable from loop header.
-  bool DeleteCurrentLoop = false;
+  bool getDeleteCurrentLoop() const { return FoldCandidates.getFlag(1); }
+  void setDeleteCurrentLoop(bool Value) { FoldCandidates.setFlag(1, Value); }
   // Whether or not we enter the loop through an indirectbr.
-  bool HasIndirectEntry = false;
+  bool getHasIndirectEntry() const { return FoldCandidates.getFlag(2); }
+  void setHasIndirectEntry(bool Value) { FoldCandidates.setFlag(2, Value); }
 
   // The blocks of the original loop that will still be reachable from entry
   // after the constant folding.
@@ -143,16 +147,15 @@ class ConstantTerminatorFoldingImpl {
   // The blocks that have terminators with constant condition that can be
   // folded. Note: fold candidates should be in L but not in any of its
   // subloops to avoid complex LI updates.
-  SmallVector<BasicBlock *, 8> FoldCandidates;
+  llvm::SmallVectorWithFlags<BasicBlock *, 8, 3> FoldCandidates;
 
   void dump() const {
     dbgs() << "Constant terminator folding for loop " << L << "\n";
     dbgs() << "After terminator constant-folding, the loop will";
-    if (!DeleteCurrentLoop)
+    if (!getDeleteCurrentLoop())
       dbgs() << " not";
     dbgs() << " be destroyed\n";
-    auto PrintOutVector = [&](const char *Message,
-                           const SmallVectorImpl<BasicBlock *> &S) {
+    auto PrintOutVector = [&](const char *Message, ArrayRef<BasicBlock *> S) {
       dbgs() << Message << "\n";
       for (const BasicBlock *BB : S)
         dbgs() << "\t" << BB->getName() << "\n";
@@ -169,7 +172,7 @@ class ConstantTerminatorFoldingImpl {
     PrintOutVector("Dead blocks from the original loop:", DeadLoopBlocks);
     PrintOutSet("Live exit blocks:", LiveExitBlocks);
     PrintOutVector("Dead exit blocks:", DeadExitBlocks);
-    if (!DeleteCurrentLoop)
+    if (!getDeleteCurrentLoop())
       PrintOutSet("The following blocks will still be part of the loop:",
                   BlocksInLoopAfterFolding);
   }
@@ -209,7 +212,7 @@ class ConstantTerminatorFoldingImpl {
     // on this). We can later decide to support such cases by altering the
     // algorithms, but so far we just give up analyzing them.
     if (hasIrreducibleCFG(DFS)) {
-      HasIrreducibleCFG = true;
+      setHasIrreducibleCFG(true);
       return;
     }
 
@@ -222,7 +225,7 @@ class ConstantTerminatorFoldingImpl {
                       return isa<IndirectBrInst>(Pred->getTerminator());
                     }) &&
              "Loop should have preheader if it is not entered indirectly");
-      HasIndirectEntry = true;
+      setHasIndirectEntry(true);
       return;
     }
 
@@ -285,11 +288,11 @@ class ConstantTerminatorFoldingImpl {
     };
 
     // The loop will not be destroyed if its latch is live.
-    DeleteCurrentLoop = !IsEdgeLive(L.getLoopLatch(), L.getHeader());
+    setDeleteCurrentLoop(!IsEdgeLive(L.getLoopLatch(), L.getHeader()));
 
     // If we are going to delete the current loop completely, no extra analysis
     // is needed.
-    if (DeleteCurrentLoop)
+    if (getDeleteCurrentLoop())
       return;
 
     // Otherwise, we should check which blocks will still be a part of the
@@ -561,12 +564,12 @@ class ConstantTerminatorFoldingImpl {
     LLVM_DEBUG(dbgs() << "In function " << Header->getParent()->getName()
                       << ": ");
 
-    if (HasIrreducibleCFG) {
+    if (getHasIrreducibleCFG()) {
       LLVM_DEBUG(dbgs() << "Loops with irreducible CFG are not supported!\n");
       return false;
     }
 
-    if (HasIndirectEntry) {
+    if (getHasIndirectEntry()) {
       LLVM_DEBUG(dbgs() << "Loops which can be entered indirectly are not"
                            " supported!\n");
       return false;
@@ -581,7 +584,7 @@ class ConstantTerminatorFoldingImpl {
     }
 
     // TODO: Support deletion of the current loop.
-    if (DeleteCurrentLoop) {
+    if (getDeleteCurrentLoop()) {
       LLVM_DEBUG(
           dbgs()
           << "Give up constant terminator folding in loop " << Header->getName()
@@ -656,9 +659,7 @@ class ConstantTerminatorFoldingImpl {
     return true;
   }
 
-  bool foldingBreaksCurrentLoop() const {
-    return DeleteCurrentLoop;
-  }
+  bool foldingBreaksCurrentLoop() const { return getDeleteCurrentLoop(); }
 };
 } // namespace
 
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 6073a177babaf..5b176b0c9d169 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -64,6 +64,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Analysis/AssumptionCache.h"
@@ -424,7 +425,8 @@ struct Formula {
   Immediate BaseOffset = Immediate::getZero();
 
   /// Whether any complex addressing has a base register.
-  bool HasBaseReg = false;
+  bool getHasBaseReg() const { return BaseRegs.getFlag(0); }
+  void setHasBaseReg(bool Value) { BaseRegs.setFlag(0, Value); }
 
   /// The scale of any complex addressing.
   int64_t Scale = 0;
@@ -443,7 +445,7 @@ struct Formula {
   /// This invariant can be temporarily broken while building a formula.
   /// However, every formula inserted into the LSRInstance must be in canonical
   /// form.
-  SmallVector<const SCEV *, 4> BaseRegs;
+  llvm::SmallVectorWithFlags<const SCEV *, 4> BaseRegs;
 
   /// The 'scaled' register for this use. This should be non-null when Scale is
   /// not zero.
@@ -547,13 +549,13 @@ void Formula::initialMatch(const SCEV *S, Loop *L, ScalarEvolution &SE) {
     const SCEV *Sum = SE.getAddExpr(Good);
     if (!Sum->isZero())
       BaseRegs.push_back(Sum);
-    HasBaseReg = true;
+    setHasBaseReg(true);
   }
   if (!Bad.empty()) {
     const SCEV *Sum = SE.getAddExpr(Bad);
     if (!Sum->isZero())
       BaseRegs.push_back(Sum);
-    HasBaseReg = true;
+    setHasBaseReg(true);
   }
   canonicalize(*L);
 }
@@ -714,9 +716,9 @@ void Formula::print(raw_ostream &OS) const {
   for (const SCEV *BaseReg : BaseRegs)
     OS << Plus << "reg(" << *BaseReg << ')';
 
-  if (HasBaseReg && BaseRegs.empty())
+  if (getHasBaseReg() && BaseRegs.empty())
     OS << Plus << "**error: HasBaseReg**";
-  else if (!HasBaseReg && !BaseRegs.empty())
+  else if (!getHasBaseReg() && !BaseRegs.empty())
     OS << Plus << "**error: !HasBaseReg**";
 
   if (Scale != 0) {
@@ -1299,24 +1301,30 @@ class LSRUse {
 
   /// This records whether all of the fixups using this LSRUse are outside of
   /// the loop, in which case some special-case heuristics may be used.
-  bool AllFixupsOutsideLoop = true;
+  bool getAllFixupsOutsideLoop() const { return !Formulae.getFlag(0); }
+  void setAllFixupsOutsideLoop(bool Value) { Formulae.setFlag(0, !Value); }
 
   /// This records whether all of the fixups using this LSRUse are unconditional
   /// within the loop, meaning they will be executed on every path to the loop
   /// latch. This includes fixups before early exits.
-  bool AllFixupsUnconditional = true;
+  bool getAllFixupsUnconditional() const { return !Formulae.getFlag(1); }
+  void setAllFixupsUnconditional(bool Value) { Formulae.setFlag(1, !Value); }
 
   /// RigidFormula is set to true to guarantee that this use will be associated
   /// with a single formula--the one that initially matched. Some SCEV
   /// expressions cannot be expanded. This allows LSR to consider the registers
   /// used by those expressions without the need to expand them later after
   /// changing the formula.
-  bool RigidFormula = false;
+  bool getRigidFormula() const { return Formulae.getFlag(2); }
+  bool setRigidFormula(bool Value) {
+    Formulae.setFlag(2, Value);
+    return Value;
+  }
 
   /// A list of ways to build a value that can satisfy this user.  After the
   /// list is populated, one of these is selected heuristically and used to
   /// formulate a replacement for OperandValToReplace in UserInst.
-  SmallVector<Formula, 12> Formulae;
+  llvm::SmallVectorWithFlags<Formula, 12, 3> Formulae;
 
   /// The set of register candidates used by all formulae in this LSRUse.
   SmallPtrSet<const SCEV *, 4> Regs;
@@ -1422,7 +1430,7 @@ void Cost::RateRegister(const Formula &F, const SCEV *Reg,
                             !isa<SCEVConstant>(Start) &&
                             SE->isLoopInvariant(Start, L);
         // We can only pre or post index when the load/store is unconditional.
-        if ((CanPreIndex || CanPostIndex) && LU.AllFixupsUnconditional)
+        if ((CanPreIndex || CanPostIndex) && LU.getAllFixupsUnconditional())
           LoopCost = 0;
       }
     }
@@ -1543,7 +1551,8 @@ void Cost::RateFormula(const Formula &F, SmallPtrSetImpl<const SCEV *> &Regs,
       // specifically not supported.
       if (LU.Kind == LSRUse::Address && Offset.isNonZero() &&
           !isAMCompletelyFolded(*TTI, LSRUse::Address, LU.AccessTy, F.BaseGV,
-                                Offset, F.HasBaseReg, F.Scale, Fixup.UserInst))
+                                Offset, F.getHasBaseReg(), F.Scale,
+                                Fixup.UserInst))
         C.NumBaseAdds++;
     } else {
       // Incompatible immediate type, increase cost to avoid using
@@ -1684,7 +1693,7 @@ LLVM_DUMP_METHOD void LSRFixup::dump() const {
 /// Test whether this use as a formula which has the same registers as the given
 /// formula.
 bool LSRUse::HasFormulaWithSameRegs(const Formula &F) const {
-  SmallVector<const SCEV *, 4> Key = F.BaseRegs;
+  SmallVector<const SCEV *, 4> Key(F.BaseRegs.begin(), F.BaseRegs.end());
   if (F.ScaledReg) Key.push_back(F.ScaledReg);
   // Unstable sort by host order ok, because this is only used for uniquifying.
   llvm::sort(Key);
@@ -1705,10 +1714,10 @@ float LSRUse::getNotSelectedProbability(const SCEV *Reg) const {
 bool LSRUse::InsertFormula(const Formula &F, const Loop &L) {
   assert(F.isCanonical(L) && "Invalid canonical representation");
 
-  if (!Formulae.empty() && RigidFormula)
+  if (!Formulae.empty() && getRigidFormula())
     return false;
 
-  SmallVector<const SCEV *, 4> Key = F.BaseRegs;
+  SmallVector<const SCEV *, 4> Key(F.BaseRegs.begin(), F.BaseRegs.end());
   if (F.ScaledReg) Key.push_back(F.ScaledReg);
   // Unstable sort by host order ok, because this is only used for uniquifying.
   llvm::sort(Key);
@@ -1785,10 +1794,10 @@ void LSRUse::print(raw_ostream &OS) const {
   }
   OS << '}';
 
-  if (AllFixupsOutsideLoop)
+  if (getAllFixupsOutsideLoop())
     OS << ", all-fixups-outside-loop";
 
-  if (AllFixupsUnconditional)
+  if (getAllFixupsUnconditional())
     OS << ", all-fixups-unconditional";
 }
 
@@ -1900,7 +1909,8 @@ static bool isAMCompletelyFolded(const TargetTransformInfo &TTI,
   // compile time sake.
   assert((F.isCanonical(L) || F.Scale != 0));
   return isAMCompletelyFolded(TTI, MinOffset, MaxOffset, Kind, AccessTy,
-                              F.BaseGV, F.BaseOffset, F.HasBaseReg, F.Scale);
+                              F.BaseGV, F.BaseOffset, F.getHasBaseReg(),
+                              F.Scale);
 }
 
 /// Test whether we know how to expand the current formula.
@@ -1922,7 +1932,7 @@ static bool isLegalUse(const TargetTransformInfo &TTI, Immediate MinOffset,
                        Immediate MaxOffset, LSRUse::KindType Kind,
                        MemAccessTy AccessTy, const Formula &F) {
   return isLegalUse(TTI, MinOffset, MaxOffset, Kind, AccessTy, F.BaseGV,
-                    F.BaseOffset, F.HasBaseReg, F.Scale);
+                    F.BaseOffset, F.getHasBaseReg(), F.Scale);
 }
 
 static bool isLegalAddImmediate(const TargetTransformInfo &TTI,
@@ -1939,15 +1949,15 @@ static bool isAMCompletelyFolded(const TargetTransformInfo &TTI,
   if (LU.Kind == LSRUse::Address && TTI.LSRWithInstrQueries()) {
     for (const LSRFixup &Fixup : LU.Fixups)
       if (!isAMCompletelyFolded(TTI, LSRUse::Address, LU.AccessTy, F.BaseGV,
-                                (F.BaseOffset + Fixup.Offset), F.HasBaseReg,
-                                F.Scale, Fixup.UserInst))
+                                (F.BaseOffset + Fixup.Offset),
+                                F.getHasBaseReg(), F.Scale, Fixup.UserInst))
         return false;
     return true;
   }
 
   return isAMCompletelyFolded(TTI, LU.MinOffset, LU.MaxOffset, LU.Kind,
-                              LU.AccessTy, F.BaseGV, F.BaseOffset, F.HasBaseReg,
-                              F.Scale);
+                              LU.AccessTy, F.BaseGV, F.BaseOffset,
+                              F.getHasBaseReg(), F.Scale);
 }
 
 static InstructionCost getScalingFactorCost(const TargetTransformInfo &TTI,
@@ -1975,10 +1985,10 @@ static InstructionCost getScalingFactorCost(const TargetTransformInfo &TTI,
     }
     InstructionCost ScaleCostMinOffset = TTI.getScalingFactorCost(
         LU.AccessTy.MemTy, F.BaseGV, StackOffset::get(FixedMin, ScalableMin),
-        F.HasBaseReg, F.Scale, LU.AccessTy.AddrSpace);
+        F.getHasBaseReg(), F.Scale, LU.AccessTy.AddrSpace);
     InstructionCost ScaleCostMaxOffset = TTI.getScalingFactorCost(
         LU.AccessTy.MemTy, F.BaseGV, StackOffset::get(FixedMax, ScalableMax),
-        F.HasBaseReg, F.Scale, LU.AccessTy.AddrSpace);
+        F.getHasBaseReg(), F.Scale, LU.AccessTy.AddrSpace);
 
     assert(ScaleCostMinOffset.isValid() && ScaleCostMaxOffset.isValid() &&
            "Legal addressing mode has an illegal cost!");
@@ -2141,9 +2151,15 @@ class LSRInstance {
   MemorySSAUpdater *MSSAU;
   TTI::AddressingModeKind AMK;
   mutable SCEVExpander Rewriter;
-  bool Changed = false;
-  bool HardwareLoopProfitable = false;
-  bool ShouldPreserveLCSSA = false;
+  bool getChangedFlag() const { return IVChainVec.getFlag(0); }
+  bool setChangedFlag(bool Value) {
+    IVChainVec.setFlag(0, Value);
+    return Value;
+  }
+  bool getHardwareLoopProfitable() const { return IVChainVec.getFlag(1); }
+  void setHardwareLoopProfitable(bool Value) { IVChainVec.setFlag(1, Value); }
+  bool getShouldPreserveLCSSA() const { return IVChainVec.getFlag(2); }
+  void setShouldPreserveLCSSA(bool Value) { IVChainVec.setFlag(2, Value); }
 
   /// This is the insert position that the current loop's induction variable
   /// increment should be placed. In simple loops, this is the latch block's
@@ -2178,7 +2194,7 @@ class LSRInstance {
   static const unsigned MaxChains = 8;
 
   /// IV users can form a chain of IV increments.
-  SmallVector<IVChain, MaxChains> IVChainVec;
+  llvm::SmallVectorWithFlags<IVChain, MaxChains, 3> IVChainVec;
 
   /// IV users that belong to profitable IVChains.
   SmallPtrSet<Use*, MaxChains> IVIncSet;
@@ -2300,7 +2316,7 @@ class LSRInstance {
               TargetLibraryInfo &TLI, MemorySSAUpdater *MSSAU,
               bool PreserveLCSSA);
 
-  bool getChanged() const { return Changed; }
+  bool getChanged() const { return getChangedFlag(); }
   const SmallVectorImpl<WeakVH> &getScalarEvolutionIVs() const {
     return ScalarEvolutionIVs;
   }
@@ -2429,7 +2445,7 @@ void LSRInstance::OptimizeShadowIV() {
     /* Remove cast operation */
     ShadowUse->replaceAllUsesWith(NewPH);
     ShadowUse->eraseFromParent();
-    Changed = true;
+    setChangedFlag(true);
     break;
   }
 }
@@ -2752,7 +2768,7 @@ LSRInstance::OptimizeLoopTermCond() {
     // use the post-incremented version of the IV, allowing us to coalesce the
     // live ranges for the IV correctly.
     CondUse->transformToPostInc(L);
-    Changed = true;
+    setChangedFlag(true);
 
     PostIncs.insert(Cond);
   decline_post_inc:;
@@ -2888,9 +2904,9 @@ LSRInstance::FindUseWithSimilarFormula(const Formula &OrigF,
       for (const Formula &F : LU.Formulae) {
         // Check to see if this formula has the same registers and symbols
         // as OrigF.
-        if (F.BaseRegs == OrigF.BaseRegs &&
-            F.ScaledReg == OrigF.ScaledReg &&
-            F.BaseGV == OrigF.BaseGV &&
+        if ((llvm::ArrayRef<const llvm::SCEV *>(F.BaseRegs) ==
+             llvm::ArrayRef<const llvm::SCEV *>(OrigF.BaseRegs)) &&
+            F.ScaledReg == OrigF.ScaledReg && F.BaseGV == OrigF.BaseGV &&
             F.Scale == OrigF.Scale &&
             F.UnfoldedOffset == OrigF.UnfoldedOffset) {
           if (F.BaseOffset.isZero())
@@ -3584,7 +3600,7 @@ void LSRInstance::CollectFixupsAndInitialFormulae() {
           CI->setOperand(1, CI->getOperand(0));
           CI->setOperand(0, NV);
           NV = CI->getOperand(1);
-          Changed = true;
+          setChangedFlag(true);
         }
 
         // x == y  -->  x - y == 0
@@ -3639,15 +3655,23 @@ void LSRInstance::CollectFixupsAndInitialFormulae() {
     LF.OperandValToReplace = U.getOperandValToReplace();
     LF.PostIncLoops = TmpPostIncLoops;
     LF.Offset = Offset;
-    LU.AllFixupsOutsideLoop &= LF.isUseFullyOutsideLoop(L);
-    LU.AllFixupsUnconditional &= IsFixupExecutedEachIncrement(LF);
+    [&] {
+      auto PackedFlagValue = LF.isUseFullyOutsideLoop(L);
+      return LU.setAllFixupsOutsideLoop(LU.getAllFixupsOutsideLoop() &
+                                        PackedFlagValue);
+    }();
+    [&] {
+      auto PackedFlagValue = IsFixupExecutedEachIncrement(LF);
+      return LU.setAllFixupsUnconditional(LU.getAllFixupsUnconditional() &
+                                          PackedFlagValue);
+    }();
 
     // Create SCEV as Formula for calculating baseline cost
     if (!VisitedLSRUse.count(LUIdx) && !LF.isUseFullyOutsideLoop(L)) {
       Formula F;
       F.initialMatch(S, L, SE);
       BaselineCost.RateFormula(F, Regs, VisitedRegs, LU,
-                               HardwareLoopProfitable);
+                               getHardwareLoopProfitable());
       VisitedLSRUse.insert(LUIdx);
     }
 
@@ -3667,7 +3691,7 @@ void LSRInstance::InsertInitialFormula(const SCEV *S, LSRUse &LU,
                                        size_t LUIdx) {
   // Mark uses whose expressions cannot be expanded.
   if (!Rewriter.isSafeToExpand(S))
-    LU.RigidFormula = true;
+    LU.setRigidFormula(true);
 
   Formula F;
   F.initialMatch(S, L, SE);
@@ -3682,7 +3706,7 @@ LSRInstance::InsertSupplementalFormula(const SCEV *S,
                                        LSRUse &LU, size_t LUIdx) {
   Formula F;
   F.BaseRegs.push_back(S);
-  F.HasBaseReg = true;
+  F.setHasBaseReg(true);
   bool Inserted = InsertFormula(LU, LUIdx, F);
   assert(Inserted && "Supplemental formula already exists!"); (void)Inserted;
 }
@@ -3839,8 +3863,16 @@ LSRInstance::CollectLoopInvariantFixupsAndFormulae() {
         LF.UserInst = const_cast<Instruction *>(UserInst);
         LF.OperandValToReplace = U;
         LF.Offset = Offset;
-        LU.AllFixupsOutsideLoop &= LF.isUseFullyOutsideLoop(L);
-        LU.AllFixupsUnconditional &= IsFixupExecutedEachIncrement(LF);
+        [&] {
+          auto PackedFlagValue = LF.isUseFullyOutsideLoop(L);
+          return LU.setAllFixupsOutsideLoop(LU.getAllFixupsOutsideLoop() &
+                                            PackedFlagValue);
+        }();
+        [&] {
+          auto PackedFlagValue = IsFixupExecutedEachIncrement(LF);
+          return LU.setAllFixupsUnconditional(LU.getAllFixupsUnconditional() &
+                                              PackedFlagValue);
+        }();
         InsertSupplementalFormula(US, LU, LUIdx);
         CountRegisters(LU.Formulae.back(), Uses.size() - 1);
         break;
@@ -4353,7 +4385,7 @@ void LSRInstance::GenerateScales(LSRUse &LU, unsigned LUIdx, Formula Base) {
   // Check each interesting stride.
   for (int64_t Factor : Factors) {
     Base.Scale = Factor;
-    Base.HasBaseReg = Base.BaseRegs.size() > 1;
+    Base.setHasBaseReg(Base.BaseRegs.size() > 1);
     // Check whether this scale is going to be legal.
     if (!isLegalUse(TTI, LU.MinOffset, LU.MaxOffset, LU.Kind, LU.AccessTy,
                     Base)) {
@@ -4362,20 +4394,20 @@ void LSRInstance::GenerateScales(LSRUse &LU, unsigned LUIdx, Formula Base) {
       if (LU.Kind == LSRUse::Basic &&
           isLegalUse(TTI, LU.MinOffset, LU.MaxOffset, LSRUse::Special,
                      LU.AccessTy, Base) &&
-          LU.AllFixupsOutsideLoop)
+          LU.getAllFixupsOutsideLoop())
         LU.Kind = LSRUse::Special;
       else
         continue;
     }
     // For an ICmpZero, negating a solitary base register won't lead to
     // new solutions.
-    if (LU.Kind == LSRUse::ICmpZero && !Base.HasBaseReg &&
+    if (LU.Kind == LSRUse::ICmpZero && !Base.getHasBaseReg() &&
         Base.BaseOffset.isZero() && !Base.BaseGV)
       continue;
     // For each addrec base reg, if its loop is current loop, apply the scale.
     for (size_t i = 0, e = Base.BaseRegs.size(); i != e; ++i) {
       const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Base.BaseRegs[i]);
-      if (AR && (AR->getLoop() == L || LU.AllFixupsOutsideLoop)) {
+      if (AR && (AR->getLoop() == L || LU.getAllFixupsOutsideLoop())) {
         const SCEV *FactorS = SE.getConstant(IntTy, Factor);
         if (FactorS->isZero())
           continue;
@@ -4390,12 +4422,13 @@ void LSRInstance::GenerateScales(LSRUse &LU, unsigned LUIdx, Formula Base) {
             // The canonical representation of 1*reg is reg, which is already in
             // Base. In that case, do not try to insert the formula, it will be
             // rejected anyway.
-            if (F.Scale == 1 && (F.BaseRegs.empty() ||
-                                 (AR->getLoop() != L && LU.AllFixupsOutsideLoop)))
+            if (F.Scale == 1 &&
+                (F.BaseRegs.empty() ||
+                 (AR->getLoop() != L && LU.getAllFixupsOutsideLoop())))
               continue;
             // If AllFixupsOutsideLoop is true and F.Scale is 1, we may generate
             // non canonical Formula with ScaledReg's loop not being L.
-            if (F.Scale == 1 && LU.AllFixupsOutsideLoop)
+            if (F.Scale == 1 && LU.getAllFixupsOutsideLoop())
               F.canonicalize(*L);
             (void)InsertFormula(LU, LUIdx, F);
           }
@@ -4794,7 +4827,7 @@ void LSRInstance::FilterOutUndesirableDedicatedRegisters() {
       // the corresponding bad register from the Regs set.
       Cost CostF(Opts, L, SE, TTI, AMK);
       Regs.clear();
-      CostF.RateFormula(F, Regs, VisitedRegs, LU, HardwareLoopProfitable,
+      CostF.RateFormula(F, Regs, VisitedRegs, LU, getHardwareLoopProfitable(),
                         &LoserRegs);
       if (CostF.isLoser()) {
         // During initial formula generation, undesirable formulae are generated
@@ -4829,7 +4862,7 @@ void LSRInstance::FilterOutUndesirableDedicatedRegisters() {
         Cost CostBest(Opts, L, SE, TTI, AMK);
         Regs.clear();
         CostBest.RateFormula(Best, Regs, VisitedRegs, LU,
-                             HardwareLoopProfitable);
+                             getHardwareLoopProfitable());
         if (CostF.isLess(CostBest))
           std::swap(F, Best);
         LLVM_DEBUG(dbgs() << "  Filtering out formula "; F.print(dbgs());
@@ -4979,8 +5012,12 @@ void LSRInstance::NarrowSearchSpaceByCollapsingUnrolledCode() {
 
       LLVM_DEBUG(dbgs() << "  Deleting use "; LU.print(dbgs()); dbgs() << '\n');
 
-      LUThatHas->AllFixupsOutsideLoop &= LU.AllFixupsOutsideLoop;
-      LUThatHas->AllFixupsUnconditional &= LU.AllFixupsUnconditional;
+      LUThatHas->setAllFixupsOutsideLoop(
+          int(LUThatHas->getAllFixupsOutsideLoop()) &
+          (LU.getAllFixupsOutsideLoop()));
+      LUThatHas->setAllFixupsUnconditional(
+          int(LUThatHas->getAllFixupsUnconditional()) &
+          (LU.getAllFixupsUnconditional()));
 
       // Transfer the fixups of LU to LUThatHas.
       for (LSRFixup &Fixup : LU.Fixups) {
@@ -5097,9 +5134,11 @@ void LSRInstance::NarrowSearchSpaceByFilterFormulaWithSameScaledReg() {
       Cost CostFA(Opts, L, SE, TTI, AMK);
       Cost CostFB(Opts, L, SE, TTI, AMK);
       Regs.clear();
-      CostFA.RateFormula(FA, Regs, VisitedRegs, LU, HardwareLoopProfitable);
+      CostFA.RateFormula(FA, Regs, VisitedRegs, LU,
+                         getHardwareLoopProfitable());
       Regs.clear();
-      CostFB.RateFormula(FB, Regs, VisitedRegs, LU, HardwareLoopProfitable);
+      CostFB.RateFormula(FB, Regs, VisitedRegs, LU,
+                         getHardwareLoopProfitable());
       return CostFA.isLess(CostFB);
     };
 
@@ -5203,7 +5242,7 @@ void LSRInstance::NarrowSearchSpaceByMergingUsesOutsideLoop() {
     LSRUse &LU = Uses[LUIdx];
     // Don't merge ICmpZero uses outside the loop, as ICmpZero needs to be
     // handled specially when expanding.
-    if (!LU.AllFixupsOutsideLoop || LU.Formulae.empty() ||
+    if (!LU.getAllFixupsOutsideLoop() || LU.Formulae.empty() ||
         LU.Kind == LSRUse::ICmpZero)
       continue;
 
@@ -5215,7 +5254,7 @@ void LSRInstance::NarrowSearchSpaceByMergingUsesOutsideLoop() {
     const Formula &ThisF = LU.Formulae[0];
     for (LSRUse &OtherLU : Uses) {
       // Only merge with uses inside the loop
-      if (OtherLU.AllFixupsOutsideLoop)
+      if (OtherLU.getAllFixupsOutsideLoop())
         continue;
       // Can't merge with ICmpZero uses as they're handled specially when
       // expanding
@@ -5235,7 +5274,7 @@ void LSRInstance::NarrowSearchSpaceByMergingUsesOutsideLoop() {
       // cost may end up being inaccurate, but it's also what we would have
       // gotten if we'd ignored uses outside the loop entirely.
       const Formula &OtherF = OtherLU.Formulae[0];
-      if (ThisF.BaseRegs == OtherF.BaseRegs &&
+      if (ArrayRef(ThisF.BaseRegs) == ArrayRef(OtherF.BaseRegs) &&
           ThisF.ScaledReg == OtherF.ScaledReg &&
           ThisF.BaseGV == OtherF.BaseGV && ThisF.Scale == OtherF.Scale &&
           ThisF.UnfoldedOffset == OtherF.UnfoldedOffset &&
@@ -5579,7 +5618,8 @@ void LSRInstance::SolveRecurse(SmallVectorImpl<const Formula *> &Solution,
     // the current best, prune the search at that point.
     NewCost = CurCost;
     NewRegs = CurRegs;
-    NewCost.RateFormula(F, NewRegs, VisitedRegs, LU, HardwareLoopProfitable);
+    NewCost.RateFormula(F, NewRegs, VisitedRegs, LU,
+                        getHardwareLoopProfitable());
     if (NewCost.isLess(SolutionCost)) {
       Workspace.push_back(&F);
       if (Workspace.size() != Uses.size()) {
@@ -5773,7 +5813,7 @@ BasicBlock::iterator LSRInstance::AdjustInsertPositionForExpand(
 Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
                            const Formula &F, BasicBlock::iterator IP,
                            SmallVectorImpl<WeakTrackingVH> &DeadInsts) const {
-  if (LU.RigidFormula)
+  if (LU.getRigidFormula())
     return LF.OperandValToReplace;
 
   // Determine an input position which will be dominated by the operands and
@@ -5993,7 +6033,7 @@ void LSRInstance::RewriteForPHI(PHINode *PN, const LSRUse &LU,
             CriticalEdgeSplittingOptions SplitOptions(&DT, &LI, MSSAU);
             SplitOptions =
                 SplitOptions.setMergeIdenticalEdges().setKeepOneInputPHIs();
-            if (ShouldPreserveLCSSA)
+            if (getShouldPreserveLCSSA())
               SplitOptions = SplitOptions.setPreserveLCSSA();
             NewBB = SplitCriticalEdge(BB, Parent, SplitOptions);
           } else {
@@ -6180,7 +6220,7 @@ void LSRInstance::ImplementSolution(
           getFixupInsertPos(TTI, Fixup, Uses[LUIdx], IVIncInsertPos, DT);
       Rewriter.setIVIncInsertPos(L, InsertPos);
       Rewrite(Uses[LUIdx], Fixup, *Solution[LUIdx], DeadInsts);
-      Changed = true;
+      setChangedFlag(true);
     }
 
   auto InsertedInsts = InsertedNonLCSSAInsts.takeVector();
@@ -6188,7 +6228,7 @@ void LSRInstance::ImplementSolution(
 
   for (const IVChain &Chain : IVChainVec) {
     GenerateIVChain(Chain, DeadInsts);
-    Changed = true;
+    setChangedFlag(true);
   }
 
   for (const WeakVH &IV : Rewriter.getInsertedIVs())
@@ -6199,8 +6239,12 @@ void LSRInstance::ImplementSolution(
   // instructions.
   Rewriter.clear();
 
-  Changed |= RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts,
-                                                                  &TLI, MSSAU);
+  [&] {
+    auto PackedFlagValue_ =
+        RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI,
+                                                             MSSAU);
+    return setChangedFlag(getChangedFlag() | PackedFlagValue_);
+  }();
 
   // In our cost analysis above, we assume that each addrec consumes exactly
   // one register, and arrange to have increments inserted just before the
@@ -6241,7 +6285,7 @@ void LSRInstance::ImplementSolution(
                       [&](Use &U) {return DT.dominates(IVIncInsertPos, U);}))
       continue;
     BO->moveBefore(IVIncInsertPos->getIterator());
-    Changed = true;
+    setChangedFlag(true);
   }
 
 
@@ -6255,8 +6299,9 @@ LSRInstance::LSRInstance(const ScalarOptions &Opts, Loop *L, IVUsers &IU,
     : Opts(Opts), IU(IU), SE(SE), DT(DT), LI(LI), AC(AC), TLI(TLI), TTI(TTI),
       L(L), MSSAU(MSSAU), AMK(Opts.lsr_preferred_addressing_mode.value_or(
                               TTI.getPreferredAddressingMode(L, &SE))),
-      Rewriter(SE, "lsr", PreserveLCSSA), ShouldPreserveLCSSA(PreserveLCSSA),
-      BaselineCost(Opts, L, SE, TTI, AMK) {
+      Rewriter(SE, "lsr", PreserveLCSSA), BaselineCost(Opts, L, SE, TTI, AMK),
+      IVChainVec(decltype(this->IVChainVec)::withFlags(
+          (unsigned(PreserveLCSSA) << 2))) {
   // If LoopSimplify form is not available, stay out of trouble.
   if (!L->isLoopSimplifyForm())
     return;
@@ -6294,8 +6339,8 @@ LSRInstance::LSRInstance(const ScalarOptions &Opts, Loop *L, IVUsers &IU,
   // Check if we expect this loop to use a hardware loop instruction, which will
   // be used when calculating the costs of formulas.
   HardwareLoopInfo HWLoopInfo(L);
-  HardwareLoopProfitable =
-      TTI.isHardwareLoopProfitable(L, SE, AC, &TLI, HWLoopInfo);
+  setHardwareLoopProfitable(
+      TTI.isHardwareLoopProfitable(L, SE, AC, &TLI, HWLoopInfo));
 
   // Configure SCEVExpander already now, so the correct mode is used for
   // isSafeToExpand() checks.
@@ -6759,14 +6804,16 @@ struct SCEVDbgValueBuilder {
 /// and DIExpression.
 struct DVIRecoveryRec {
   DVIRecoveryRec(DbgVariableRecord *DVR)
-      : DbgRef(DVR), Expr(DVR->getExpression()), HadLocationArgList(false) {}
+      : DbgRef(DVR), Expr(DVR->getExpression()) {}
 
   DbgVariableRecord *DbgRef;
   DIExpression *Expr;
-  bool HadLocationArgList;
+  bool getHadLocationArgList() const { return RecoveryExprs.getFlag(0); }
+  void setHadLocationArgList(bool Value) { RecoveryExprs.setFlag(0, Value); }
   SmallVector<WeakVH, 2> LocationOps;
   SmallVector<const llvm::SCEV *, 2> SCEVs;
-  SmallVector<std::unique_ptr<SCEVDbgValueBuilder>, 2> RecoveryExprs;
+  llvm::SmallVectorWithFlags<std::unique_ptr<SCEVDbgValueBuilder>, 2>
+      RecoveryExprs;
 
   void clear() {
     for (auto &RE : RecoveryExprs)
@@ -6872,7 +6919,7 @@ static void restorePreTransformState(DVIRecoveryRec &DVIRec) {
 
   // Even a single location-op may be inside a DIArgList and referenced with
   // DW_OP_LLVM_arg, which is valid only with a DIArgList.
-  if (!DVIRec.HadLocationArgList) {
+  if (!DVIRec.getHadLocationArgList()) {
     assert(DVIRec.LocationOps.size() == 1 &&
            "Unexpected number of location ops.");
     // LSR's unsuccessful salvage attempt may have added DIArgList, which in
@@ -7083,7 +7130,10 @@ static void DbgGatherSalvagableDVI(
         for (const auto LocOp : DbgVal.location_ops()) {
           NewRec->SCEVs.push_back(SE.getSCEV(LocOp));
           NewRec->LocationOps.push_back(LocOp);
-          NewRec->HadLocationArgList = DbgVal.hasArgList();
+          [&] {
+            auto PackedFlagValue_ = DbgVal.hasArgList();
+            return NewRec->setHadLocationArgList(PackedFlagValue_);
+          }();
         }
         SalvageableDVISCEVs.push_back(std::move(NewRec));
       }
diff --git a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
index 44af9c7dbc976..efd523db4fe36 100644
--- a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
+++ b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
@@ -380,17 +381,27 @@ class LowerMatrixIntrinsics {
   /// Wrapper class representing a matrix as a set of vectors, either in row or
   /// column major layout. All vectors must have the same vector type.
   class MatrixTy {
-    SmallVector<Value *, 16> Vectors;
+    llvm::SmallVectorWithFlags<Value *, 16> Vectors;
 
     OpInfoTy OpInfo;
 
-    bool IsColumnMajor = ScalarOptions::Global.matrix_default_layout ==
-                         MatrixLayoutTy::ColumnMajor;
+    bool getIsColumnMajor() const { return Vectors.getFlag(0); }
+    void setIsColumnMajor(bool Value) { Vectors.setFlag(0, Value); }
 
   public:
-    MatrixTy() = default;
-    MatrixTy(ArrayRef<Value *> Vectors) : Vectors(Vectors) {}
-    MatrixTy(unsigned NumRows, unsigned NumColumns, Type *EltTy) {
+    MatrixTy()
+        : Vectors(decltype(this->Vectors)::withFlags(
+              unsigned(bool(ScalarOptions::Global.matrix_default_layout ==
+                            MatrixLayoutTy::ColumnMajor)))) {}
+    MatrixTy(ArrayRef<Value *> Vectors)
+        : Vectors(decltype(this->Vectors)::withFlags(
+              unsigned(bool(ScalarOptions::Global.matrix_default_layout ==
+                            MatrixLayoutTy::ColumnMajor)),
+              Vectors)) {}
+    MatrixTy(unsigned NumRows, unsigned NumColumns, Type *EltTy)
+        : Vectors(decltype(this->Vectors)::withFlags(
+              unsigned(bool(ScalarOptions::Global.matrix_default_layout ==
+                            MatrixLayoutTy::ColumnMajor)))) {
 
       unsigned D = isColumnMajor() ? NumColumns : NumRows;
       for (unsigned J = 0; J < D; ++J)
@@ -489,7 +500,7 @@ class LowerMatrixIntrinsics {
 
     const OpInfoTy &getOpInfo() const { return OpInfo; }
 
-    bool isColumnMajor() const { return IsColumnMajor; }
+    bool isColumnMajor() const { return getIsColumnMajor(); }
 
     unsigned getStride() const {
       if (isColumnMajor())
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index e6407049899ec..f59abaf7b6886 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -33,6 +33,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseBitVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringRef.h"
@@ -172,8 +173,8 @@ class SROA {
   LLVMContext *const C;
   DomTreeUpdater *const DTU;
   AssumptionCache *const AC;
-  const bool PreserveCFG;
-  const bool AggregateToVector;
+  bool getPreserveCFG() const { return DeadInsts.getFlag(0); }
+  bool getAggregateToVector() const { return DeadInsts.getFlag(1); }
 
   /// Worklist of alloca instructions to simplify.
   ///
@@ -187,7 +188,7 @@ class SROA {
   /// A collection of instructions to delete.
   /// We try to batch deletions to simplify code and make things a bit more
   /// efficient. We also make sure there is no dangling pointers.
-  SmallVector<WeakVH, 8> DeadInsts;
+  llvm::SmallVectorWithFlags<WeakVH, 8, 2> DeadInsts;
 
   /// Post-promotion worklist.
   ///
@@ -243,8 +244,9 @@ class SROA {
   SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
        SROAOptions Options)
       : C(C), DTU(DTU), AC(AC),
-        PreserveCFG(Options.CFG == SROAOptions::PreserveCFG),
-        AggregateToVector(Options.AggregateToVector) {}
+        DeadInsts(decltype(this->DeadInsts)::withFlags(
+            unsigned(bool(Options.CFG == SROAOptions::PreserveCFG)) |
+            (unsigned(bool(Options.AggregateToVector)) << 1))) {}
 
   /// Main run method used by both the SROAPass and by the legacy pass.
   std::pair<bool /*Changed*/, bool /*CFGChanged*/> runSROA(Function &F);
@@ -1116,7 +1118,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
 
     // If there is a load with an unknown offset, we can still perform store
     // to load forwarding for other known-offset loads.
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setEscapedReadOnly(&LI);
 
     TypeSize Size = DL.getTypeStoreSize(LI.getType());
@@ -1136,7 +1138,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
     Value *ValOp = SI.getValueOperand();
     if (ValOp == *U)
       return PI.setEscapedAndAborted(&SI);
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setAborted(&SI);
 
     TypeSize StoreSize = DL.getTypeStoreSize(ValOp->getType());
@@ -1175,11 +1177,11 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
     assert(II.getRawDest() == *U && "Pointer use is not the destination?");
     ConstantInt *Length = dyn_cast<ConstantInt>(II.getLength());
     if ((Length && Length->getValue() == 0) ||
-        (IsOffsetKnown && Offset.uge(AllocSize)))
+        (isOffsetKnown() && Offset.uge(AllocSize)))
       // Zero-length mem transfer intrinsics can be ignored entirely.
       return markAsDead(II);
 
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setAborted(&II);
 
     insertUse(II, Offset,
@@ -1199,7 +1201,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
     if (VisitedDeadInsts.count(&II))
       return;
 
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setAborted(&II);
 
     // This side of the transfer is completely out-of-bounds, and so we can
@@ -1266,7 +1268,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
       return;
     }
 
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setAborted(&II);
 
     if (II.isLifetimeStartOrEnd()) {
@@ -1364,7 +1366,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
       return;
     }
 
-    if (!IsOffsetKnown)
+    if (!isOffsetKnown())
       return PI.setAborted(&I);
 
     // See if we already have computed info on this node.
@@ -5721,7 +5723,7 @@ SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &P) {
   const DataLayout &DL = AI.getDataLayout();
   // Select the type for the new alloca that spans the partition.
   auto [PartitionTy, IsIntegerWideningViable, VecTy] =
-      selectPartitionType(P, DL, AI, *C, AggregateToVector);
+      selectPartitionType(P, DL, AI, *C, getAggregateToVector());
 
   // Check for the case where we're going to rewrite to a new alloca of the
   // exact same type as the original, and with the same access offsets. In that
@@ -5791,7 +5793,7 @@ SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &P) {
       NewSpeculatablePHIs.push_back(PHI);
       continue;
     }
-    if (getPHIStoreToRewrite(*PHI, PreserveCFG, DTU->getDomTree())) {
+    if (getPHIStoreToRewrite(*PHI, getPreserveCFG(), DTU->getDomTree())) {
       NewPHIsWithStoreToRewrite.push_back(PHI);
       continue;
     }
@@ -5806,7 +5808,7 @@ SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &P) {
   NewSelectsToRewrite.reserve(SelectUsers.size());
   for (SelectInst *Sel : SelectUsers) {
     std::optional<RewriteableMemOps> Ops =
-        isSafeSelectToSpeculate(*Sel, PreserveCFG);
+        isSafeSelectToSpeculate(*Sel, getPreserveCFG());
     if (!Ops) {
       Promotable = false;
       break;
@@ -6410,7 +6412,7 @@ SROA::runOnAlloca(AllocaInst &AI) {
   while (!RemainingSelectsToRewrite.empty()) {
     const auto [K, V] = RemainingSelectsToRewrite.pop_back_val();
     CFGChanged |=
-        rewriteSelectInstMemOps(*K, V, IRB, PreserveCFG ? nullptr : DTU);
+        rewriteSelectInstMemOps(*K, V, IRB, getPreserveCFG() ? nullptr : DTU);
   }
 
   return {Changed, CFGChanged};
@@ -6529,7 +6531,7 @@ std::pair<bool /*Changed*/, bool /*CFGChanged*/> SROA::runSROA(Function &F) {
   } while (!Worklist.empty());
 
   assert((!CFGChanged || Changed) && "Can not only modify the CFG.");
-  assert((!CFGChanged || !PreserveCFG) &&
+  assert((!CFGChanged || !getPreserveCFG()) &&
          "Should not have modified the CFG when told to preserve it.");
 
   if (Changed && isAssignmentTrackingEnabled(*F.getParent())) {
diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
index 080c88d1cd951..9d08745a867cc 100644
--- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp
+++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Transforms/Scalar/Scalarizer.h"
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/VectorUtils.h"
@@ -119,9 +120,10 @@ class Scatterer {
   BasicBlock::iterator BBI;
   Value *V;
   VectorSplit VS;
-  bool IsPointer;
+  bool getIsPointer() const { return Tmp.getFlag(0); }
+  void setIsPointer(bool Value) { Tmp.setFlag(0, Value); }
   ValueVector *CachePtr;
-  ValueVector Tmp;
+  llvm::SmallVectorWithFlagsFor<ValueVector, 1> Tmp;
 };
 
 // FCmpSplitter(FCI)(Builder, X, Y, Name) uses Builder to create an FCmp
@@ -278,10 +280,10 @@ class ScalarizerVisitor : public InstVisitor<ScalarizerVisitor, bool> {
 public:
   ScalarizerVisitor(DominatorTree *DT, const TargetTransformInfo *TTI,
                     ScalarizerPassOptions Options)
-      : DT(DT), TTI(TTI),
-        ScalarizeVariableInsertExtract(Options.ScalarizeVariableInsertExtract),
-        ScalarizeLoadStore(Options.ScalarizeLoadStore),
-        ScalarizeMinBits(Options.ScalarizeMinBits) {}
+      : Gathered(decltype(this->Gathered)::withFlags(
+            (unsigned(bool(Options.ScalarizeVariableInsertExtract)) << 1) |
+            (unsigned(bool(Options.ScalarizeLoadStore)) << 2))),
+        DT(DT), TTI(TTI), ScalarizeMinBits(Options.ScalarizeMinBits) {}
 
   bool visit(Function &F);
 
@@ -323,16 +325,17 @@ class ScalarizerVisitor : public InstVisitor<ScalarizerVisitor, bool> {
   bool splitCall(CallInst &CI);
 
   ScatterMap Scattered;
-  GatherList Gathered;
-  bool Scalarized;
+  llvm::SmallVectorWithFlagsFor<GatherList, 3> Gathered;
+  bool getScalarized() const { return Gathered.getFlag(0); }
+  void setScalarized(bool Value) { Gathered.setFlag(0, Value); }
 
   SmallVector<WeakTrackingVH, 32> PotentiallyDeadInstrs;
 
   DominatorTree *DT;
   const TargetTransformInfo *TTI;
 
-  const bool ScalarizeVariableInsertExtract;
-  const bool ScalarizeLoadStore;
+  bool getScalarizeVariableInsertExtract() const { return Gathered.getFlag(1); }
+  bool getScalarizeLoadStore() const { return Gathered.getFlag(2); }
   const unsigned ScalarizeMinBits;
 };
 
@@ -368,12 +371,12 @@ INITIALIZE_PASS_END(ScalarizerLegacyPass, "scalarizer",
 Scatterer::Scatterer(BasicBlock::iterator bbi, Value *v, const VectorSplit &VS,
                      ValueVector *cachePtr)
     : BBI(bbi), V(v), VS(VS), CachePtr(cachePtr) {
-  IsPointer = V->getType()->isPointerTy();
+  setIsPointer(V->getType()->isPointerTy());
   if (!CachePtr) {
     Tmp.resize(VS.NumFragments, nullptr);
   } else {
     assert((CachePtr->empty() || VS.NumFragments == CachePtr->size() ||
-            IsPointer) &&
+            getIsPointer()) &&
            "Inconsistent vector sizes");
     if (VS.NumFragments > CachePtr->size())
       CachePtr->resize(VS.NumFragments, nullptr);
@@ -382,12 +385,13 @@ Scatterer::Scatterer(BasicBlock::iterator bbi, Value *v, const VectorSplit &VS,
 
 // Return fragment Frag, creating a new Value for it if necessary.
 Value *Scatterer::operator[](unsigned Frag) {
-  ValueVector &CV = CachePtr ? *CachePtr : Tmp;
+  MutableArrayRef<Value *> CV = CachePtr ? MutableArrayRef<Value *>(*CachePtr)
+                                         : MutableArrayRef<Value *>(Tmp);
   // Try to reuse a previous value.
   if (CV[Frag])
     return CV[Frag];
   IRBuilder<> Builder(BBI);
-  if (IsPointer) {
+  if (getIsPointer()) {
     if (Frag == 0)
       CV[Frag] = V;
     else
@@ -455,7 +459,7 @@ FunctionPass *llvm::createScalarizerPass(const ScalarizerPassOptions &Options) {
 bool ScalarizerVisitor::visit(Function &F) {
   assert(Gathered.empty() && Scattered.empty());
 
-  Scalarized = false;
+  setScalarized(false);
 
   // To ensure we replace gathered components correctly we need to do an ordered
   // traversal of the basic blocks in the function.
@@ -467,7 +471,7 @@ bool ScalarizerVisitor::visit(Function &F) {
       ++II;
       if (Done && I->getType()->isVoidTy()) {
         I->eraseFromParent();
-        Scalarized = true;
+        setScalarized(true);
       }
     }
   }
@@ -538,7 +542,7 @@ void ScalarizerVisitor::replaceUses(Instruction *Op, Value *CV) {
   if (CV != Op) {
     Op->replaceAllUsesWith(CV);
     PotentiallyDeadInstrs.emplace_back(Op);
-    Scalarized = true;
+    setScalarized(true);
   }
 }
 
@@ -1091,7 +1095,7 @@ bool ScalarizerVisitor::visitInsertElementInst(InsertElementInst &IEI) {
     }
   } else {
     // Never split a variable insertelement that isn't fully scalarized.
-    if (!ScalarizeVariableInsertExtract || VS->NumPacked > 1)
+    if (!getScalarizeVariableInsertExtract() || VS->NumPacked > 1)
       return false;
 
     for (unsigned I = 0; I < VS->NumFragments; ++I) {
@@ -1184,7 +1188,7 @@ bool ScalarizerVisitor::visitExtractElementInst(ExtractElementInst &EEI) {
   }
 
   // Never split a variable extractelement that isn't fully scalarized.
-  if (!ScalarizeVariableInsertExtract || VS->NumPacked > 1)
+  if (!getScalarizeVariableInsertExtract() || VS->NumPacked > 1)
     return false;
 
   Value *Res = PoisonValue::get(VS->VecTy->getElementType());
@@ -1251,7 +1255,7 @@ bool ScalarizerVisitor::visitPHINode(PHINode &PHI) {
 }
 
 bool ScalarizerVisitor::visitLoadInst(LoadInst &LI) {
-  if (!ScalarizeLoadStore)
+  if (!getScalarizeLoadStore())
     return false;
   if (!LI.isSimple())
     return false;
@@ -1276,7 +1280,7 @@ bool ScalarizerVisitor::visitLoadInst(LoadInst &LI) {
 }
 
 bool ScalarizerVisitor::visitStoreInst(StoreInst &SI) {
-  if (!ScalarizeLoadStore)
+  if (!getScalarizeLoadStore())
     return false;
   if (!SI.isSimple())
     return false;
@@ -1318,7 +1322,7 @@ bool ScalarizerVisitor::visitFreezeInst(FreezeInst &FI) {
 bool ScalarizerVisitor::finish() {
   // The presence of data in Gathered or Scattered indicates changes
   // made to the Function.
-  if (Gathered.empty() && Scattered.empty() && !Scalarized)
+  if (Gathered.empty() && Scattered.empty() && !getScalarized())
     return false;
   for (const auto &GMI : Gathered) {
     Instruction *Op = GMI.first;
@@ -1380,7 +1384,7 @@ bool ScalarizerVisitor::finish() {
   }
   Gathered.clear();
   Scattered.clear();
-  Scalarized = false;
+  setScalarized(false);
 
   RecursivelyDeleteTriviallyDeadInstructionsPermissive(PotentiallyDeadInstrs);
 
diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
index f891bf693b560..57b02532c5457 100644
--- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp
@@ -53,6 +53,7 @@
 #include "ScalarOptions.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/BlockFrequencyInfo.h"
 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
@@ -482,7 +483,7 @@ class TailRecursionEliminator {
   DomTreeUpdater &DTU;
   BlockFrequencyInfo *const BFI;
   ProfileSummaryInfo *const PSI;
-  const bool UpdateFunctionEntryCount;
+  bool getUpdateFunctionEntryCount() const { return RetSelects.getFlag(0); }
   const uint64_t OrigEntryBBFreq;
   const uint64_t OrigEntryCount;
 
@@ -500,7 +501,7 @@ class TailRecursionEliminator {
 
   // Vector of select instructions we insereted. These selects use RetKnownPN
   // to either propagate RetPN or select a new return value.
-  SmallVector<SelectInst *, 8> RetSelects;
+  llvm::SmallVectorWithFlags<SelectInst *, 8> RetSelects;
 
   // Keep track of the sum of frequencies of blocks that have calls eliminated
   // so we can synthesize branch weights later that require information on
@@ -525,10 +526,12 @@ class TailRecursionEliminator {
                           BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI,
                           bool UpdateFunctionEntryCount)
       : Opts(Opts), F(F), TTI(TTI), AA(AA), ORE(ORE), DTU(DTU), BFI(BFI),
-        PSI(PSI), UpdateFunctionEntryCount(UpdateFunctionEntryCount),
+        PSI(PSI),
         OrigEntryBBFreq(
             BFI ? BFI->getBlockFreq(&F.getEntryBlock()).getFrequency() : 0U),
-        OrigEntryCount(F.getEntryCount() ? *F.getEntryCount() : 0) {
+        OrigEntryCount(F.getEntryCount() ? *F.getEntryCount() : 0),
+        RetSelects(decltype(this->RetSelects)::withFlags(
+            unsigned(UpdateFunctionEntryCount))) {
     if (BFI) {
       // The assert is meant as API documentation for the caller.
       assert(OrigEntryBBFreq != 0 &&
@@ -966,7 +969,7 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) {
   CI->eraseFromParent();   // Remove call.
   DTU.applyUpdates({{DominatorTree::Insert, BB, HeaderBB}});
   ++NumEliminated;
-  if (!Opts.tre_disable_entrycount_recompute && UpdateFunctionEntryCount &&
+  if (!Opts.tre_disable_entrycount_recompute && getUpdateFunctionEntryCount() &&
       OrigEntryBBFreq) {
     assert(F.getEntryCount().has_value());
     // This pass is not expected to remove BBs, only add an entry BB. For that
diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
index aad520d25212a..08207de4887f9 100644
--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -271,12 +271,15 @@ CodeExtractor::CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT,
                              ArrayRef<BasicBlock *> DeallocationBlocks,
                              std::string Suffix, bool ArgsInZeroAddressSpace,
                              bool VoidReturnWithSingleOutput)
-    : DT(DT), AggregateArgs(AggregateArgs || AggregateArgsOpt), BFI(BFI),
-      BPI(BPI), AC(AC), AllocationBlock(AllocationBlock),
-      DeallocationBlocks(DeallocationBlocks), AllowVarArgs(AllowVarArgs),
+    : DT(DT), BFI(BFI), BPI(BPI), AC(AC), AllocationBlock(AllocationBlock),
+      DeallocationBlocks(DeallocationBlocks),
       Blocks(buildExtractionBlockSet(BBs, DT, AllowVarArgs, AllowAlloca)),
-      Suffix(Suffix), ArgsInZeroAddressSpace(ArgsInZeroAddressSpace),
-      VoidReturnWithSingleOutput(VoidReturnWithSingleOutput) {}
+      ExtractedFuncRetVals(decltype(this->ExtractedFuncRetVals)::withFlags(
+          unsigned(bool(AggregateArgs || AggregateArgsOpt)) |
+          (unsigned(AllowVarArgs) << 1) |
+          (unsigned(ArgsInZeroAddressSpace) << 2) |
+          (unsigned(VoidReturnWithSingleOutput) << 3))),
+      Suffix(Suffix) {}
 
 /// definedInRegion - Return true if the specified value is defined in the
 /// extracted region.
@@ -460,7 +463,8 @@ Instruction *CodeExtractor::allocateVar(IRBuilder<>::InsertPoint AllocaIP,
   Instruction *Alloca =
       new AllocaInst(VarType, DL.getAllocaAddrSpace(), nullptr, Name, AllocaIP);
 
-  if (CastedAlloc && ArgsInZeroAddressSpace && DL.getAllocaAddrSpace() != 0) {
+  if (CastedAlloc && getArgsInZeroAddressSpace() &&
+      DL.getAllocaAddrSpace() != 0) {
     *CastedAlloc = new AddrSpaceCastInst(
         Alloca, PointerType::get(BB->getContext(), 0), Name + ".ascast");
     (*CastedAlloc)->insertAfter(Alloca->getIterator());
@@ -654,7 +658,7 @@ bool CodeExtractor::isEligible() const {
 
   // For functions with varargs, check that varargs handling is only done in the
   // outlined function, i.e vastart and vaend are only used in outlined blocks.
-  if (AllowVarArgs && F->getFunctionType()->isVarArg()) {
+  if (getAllowVarArgs() && F->getFunctionType()->isVarArg()) {
     auto containsVarArgIntrinsic = [](const Instruction &I) {
       if (const CallInst *CI = dyn_cast<CallInst>(&I))
         if (const Function *Callee = CI->getCalledFunction())
@@ -717,8 +721,8 @@ void CodeExtractor::findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs,
   // Reset stale state from any prior call in HotColdSplitting; the CFG may
   // have changed since.
   FuncRetVal = nullptr;
-  if (!VoidReturnWithSingleOutput && !AggregateArgs && Outputs.size() == 1 &&
-      getCommonExitBlock(Blocks)) {
+  if (!getVoidReturnWithSingleOutput() && !getAggregateArgs() &&
+      Outputs.size() == 1 && getCommonExitBlock(Blocks)) {
     FuncRetVal = Outputs[0];
     Outputs.clear();
   }
@@ -885,7 +889,7 @@ Function *CodeExtractor::constructFunctionDeclaration(
   // Add the types of the input values to the function's argument list
   for (Value *value : inputs) {
     LLVM_DEBUG(dbgs() << "value used in func: " << *value << "\n");
-    if (AggregateArgs && !ExcludeArgsFromAggregate.contains(value)) {
+    if (getAggregateArgs() && !ExcludeArgsFromAggregate.contains(value)) {
       AggParamTy.push_back(value->getType());
       StructValues.insert(value);
     } else
@@ -895,7 +899,7 @@ Function *CodeExtractor::constructFunctionDeclaration(
   // Add the types of the output values to the function's argument list.
   for (Value *output : outputs) {
     LLVM_DEBUG(dbgs() << "instr used in func: " << *output << "\n");
-    if (AggregateArgs && !ExcludeArgsFromAggregate.contains(output)) {
+    if (getAggregateArgs() && !ExcludeArgsFromAggregate.contains(output)) {
       AggParamTy.push_back(output->getType());
       StructValues.insert(output);
     } else
@@ -907,14 +911,15 @@ Function *CodeExtractor::constructFunctionDeclaration(
       (ParamTy.size() + AggParamTy.size()) ==
           (inputs.size() + outputs.size()) &&
       "Number of scalar and aggregate params does not match inputs, outputs");
-  assert((StructValues.empty() || AggregateArgs) &&
+  assert((StructValues.empty() || getAggregateArgs()) &&
          "Expeced StructValues only with AggregateArgs set");
 
   // Concatenate scalar and aggregate params in ParamTy.
   if (!AggParamTy.empty()) {
     StructTy = StructType::get(M->getContext(), AggParamTy);
     ParamTy.push_back(PointerType::get(
-        M->getContext(), ArgsInZeroAddressSpace ? 0 : DL.getAllocaAddrSpace()));
+        M->getContext(),
+        getArgsInZeroAddressSpace() ? 0 : DL.getAllocaAddrSpace()));
   }
 
   Type *RetTy = FuncRetVal ? FuncRetVal->getType() : getSwitchType();
@@ -926,7 +931,7 @@ Function *CodeExtractor::constructFunctionDeclaration(
   });
 
   FunctionType *funcType = FunctionType::get(
-      RetTy, ParamTy, AllowVarArgs && oldFunction->isVarArg());
+      RetTy, ParamTy, getAllowVarArgs() && oldFunction->isVarArg());
 
   // Create the new function
   Function *newFunction =
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 41c3c2c3c0e19..03aae472103ef 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2881,7 +2881,7 @@ void llvm::InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
     // inlining, the context-sensitive inlinee profile doesn't need to be
     // subtracted from callee profile, and the inlined clone also doesn't need
     // to be scaled based on call site count.
-    if (IFI.UpdateProfile) {
+    if (IFI.getUpdateProfile()) {
       if (IFI.CallerBFI != nullptr && IFI.CalleeBFI != nullptr)
         // Update the BFI of blocks cloned into the caller.
         updateCallerBFI(OrigBB, VMap, IFI.CallerBFI, IFI.CalleeBFI,
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 3c58c381985f1..74f8a55e88da7 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -2386,8 +2386,11 @@ llvm::hasPartialIVCondition(const Loop &L, unsigned MSSAThreshold,
     WorkList.push_back(Header);
     SmallPtrSet<BasicBlock *, 4> Seen;
     Seen.insert(Header);
-    Info.PathIsNoop &=
-        all_of(*Header, [](Instruction &I) { return !I.mayHaveSideEffects(); });
+    [&] {
+      auto PackedFlagValue = all_of(
+          *Header, [](Instruction &I) { return !I.mayHaveSideEffects(); });
+      return Info.setPathIsNoop(Info.getPathIsNoop() & PackedFlagValue);
+    }();
 
     while (!WorkList.empty()) {
       BasicBlock *Current = WorkList.pop_back_val();
@@ -2397,8 +2400,11 @@ llvm::hasPartialIVCondition(const Loop &L, unsigned MSSAThreshold,
       if (!SeenIns.second)
         continue;
 
-      Info.PathIsNoop &= all_of(
-          *Current, [](Instruction &I) { return !I.mayHaveSideEffects(); });
+      [&] {
+        auto PackedFlagValue = all_of(
+            *Current, [](Instruction &I) { return !I.mayHaveSideEffects(); });
+        return Info.setPathIsNoop(Info.getPathIsNoop() & PackedFlagValue);
+      }();
       WorkList.append(succ_begin(Current), succ_end(Current));
     }
 
@@ -2442,12 +2448,15 @@ llvm::hasPartialIVCondition(const Loop &L, unsigned MSSAThreshold,
 
     // We could also allow loops with known trip counts without mustprogress,
     // but ScalarEvolution may not be available.
-    Info.PathIsNoop &= isMustProgress(&L);
+    [&] {
+      auto PackedFlagValue = isMustProgress(&L);
+      return Info.setPathIsNoop(Info.getPathIsNoop() & PackedFlagValue);
+    }();
 
     // If the path is considered a no-op so far, check if it reaches a
     // single exit block without any phis. This ensures no values from the
     // loop are used outside of the loop.
-    if (Info.PathIsNoop) {
+    if (Info.getPathIsNoop()) {
       for (auto *Exiting : ExitingBlocks) {
         if (!Seen.contains(Exiting))
           continue;
@@ -2455,9 +2464,13 @@ llvm::hasPartialIVCondition(const Loop &L, unsigned MSSAThreshold,
           if (L.contains(Succ))
             continue;
 
-          Info.PathIsNoop &= Succ->phis().empty() &&
-                             (!Info.ExitForPath || Info.ExitForPath == Succ);
-          if (!Info.PathIsNoop)
+          [&] {
+            auto PackedFlagValue =
+                Succ->phis().empty() &&
+                (!Info.ExitForPath || Info.ExitForPath == Succ);
+            return Info.setPathIsNoop(Info.getPathIsNoop() & PackedFlagValue);
+          }();
+          if (!Info.getPathIsNoop())
             break;
           assert((!Info.ExitForPath || Info.ExitForPath == Succ) &&
                  "cannot have multiple exit blocks");
@@ -2466,9 +2479,9 @@ llvm::hasPartialIVCondition(const Loop &L, unsigned MSSAThreshold,
       }
     }
     if (!Info.ExitForPath)
-      Info.PathIsNoop = false;
+      Info.setPathIsNoop(false);
 
-    Info.InstToDuplicate = std::move(InstToDuplicate);
+    Info.InstToDuplicate.assign(std::move(InstToDuplicate));
     return Info;
   };
 
diff --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
index ebca42f0e4757..a23e05601826b 100644
--- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
+++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
@@ -31,7 +31,7 @@ namespace memtag {
 
 void forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT,
                           const LoopInfo &LI, const AllocaInfo &AInfo,
-                          const SmallVectorImpl<Instruction *> &RetVec,
+                          ArrayRef<Instruction *> RetVec,
                           llvm::function_ref<void(Instruction *)> Callback) {
   if (AInfo.LifetimeEnd.size() == 1 && AInfo.LifetimeStart.size() == 1 &&
       PDT.dominates(AInfo.LifetimeEnd[0], AInfo.LifetimeStart[0])) {
@@ -121,7 +121,7 @@ void StackInfoBuilder::visit(OptimizationRemarkEmitter &ORE,
 
   if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
     if (CI->canReturnTwice()) {
-      Info.CallsReturnTwice = true;
+      Info.setCallsReturnTwice(true);
     }
   }
   if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index 157c3de56be02..baf5b633f0806 100644
--- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Analysis/AssumptionCache.h"
@@ -204,11 +205,12 @@ struct AllocaInfo {
   using DPUserVec = SmallVector<DbgVariableRecord *, 1>;
 
   SmallVector<BasicBlock *, 32> DefiningBlocks;
-  SmallVector<BasicBlock *, 32> UsingBlocks;
+  llvm::SmallVectorWithFlags<BasicBlock *, 32> UsingBlocks;
 
   StoreInst *OnlyStore;
   BasicBlock *OnlyBlock;
-  bool OnlyUsedInOneBlock;
+  bool getOnlyUsedInOneBlock() const { return UsingBlocks.getFlag(0); }
+  void setOnlyUsedInOneBlock(bool Value) { UsingBlocks.setFlag(0, Value); }
 
   /// The type used by all loads/stores of this alloca. This may differ from
   /// the alloca's declared type if all accesses use a different type.
@@ -224,7 +226,7 @@ struct AllocaInfo {
     UsingBlocks.clear();
     OnlyStore = nullptr;
     OnlyBlock = nullptr;
-    OnlyUsedInOneBlock = true;
+    setOnlyUsedInOneBlock(true);
     ValueType = nullptr;
     DPUsers.clear();
     AssignmentTracking.clear();
@@ -262,11 +264,11 @@ struct AllocaInfo {
                  "All loads where checked to have used the same type");
       }
 
-      if (OnlyUsedInOneBlock) {
+      if (getOnlyUsedInOneBlock()) {
         if (!OnlyBlock)
           OnlyBlock = User->getParent();
         else if (OnlyBlock != User->getParent())
-          OnlyUsedInOneBlock = false;
+          setOnlyUsedInOneBlock(false);
       }
     }
     SmallVector<DbgVariableRecord *> AllDPUsers;
@@ -426,10 +428,11 @@ struct PromoteMem2Reg {
   VectorWithUndo<DebugLoc> IncomingLocs;
 
   // DFS work stack.
-  SmallVector<RenamePassData, 8> Worklist;
+  llvm::SmallVectorWithFlags<RenamePassData, 8> Worklist;
 
   /// Whether the function has the no-signed-zeros-fp-math attribute set.
-  bool NoSignedZeros = false;
+  bool getNoSignedZeros() const { return Worklist.getFlag(0); }
+  void setNoSignedZeros(bool Value) { Worklist.setFlag(0, Value); }
 
 public:
   PromoteMem2Reg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
@@ -808,7 +811,8 @@ void PromoteMem2Reg::run() {
   LargeBlockInfo LBI;
   ForwardIDFCalculator IDF(DT);
 
-  NoSignedZeros = F.getFnAttribute("no-signed-zeros-fp-math").getValueAsBool();
+  setNoSignedZeros(
+      F.getFnAttribute("no-signed-zeros-fp-math").getValueAsBool());
 
   // removeIntrinsicUsers inserts StoreInst(undef). A cache miss on
   // LBI.getInstructionIndex lookup causes a full O(|BB|) basic block rescan.
@@ -852,7 +856,7 @@ void PromoteMem2Reg::run() {
 
     // If the alloca is only read and written in one basic block, just perform a
     // linear sweep over the block to eliminate it.
-    if (Info.OnlyUsedInOneBlock &&
+    if (Info.getOnlyUsedInOneBlock() &&
         promoteSingleBlockAlloca(AI, Info, LBI, SQ.DL, DT, AC,
                                  &DVRAssignsToDelete)) {
       // The alloca has been processed, move on.
@@ -1180,7 +1184,7 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred) {
         // on the phi node generated at this stage, fabs folding does not
         // happen. So, we try to infer nsz flag from the function attributes to
         // enable this fabs folding.
-        if (isa<FPMathOperator>(APN) && NoSignedZeros)
+        if (isa<FPMathOperator>(APN) && getNoSignedZeros())
           APN->setHasNoSignedZeros(true);
 
         // The currently active variable for this block is now the PHI.
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 0bca4213e995b..796c23e8fad46 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -337,7 +337,7 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, Value *LHS,
   bool IsNSW = any(Flags & SCEV::FlagNSW);
   // Don't use folder when expanding post-inc rewrites in LSRMode to preserve
   // the rewrites.
-  if (LSRMode && !PostIncLoops.empty() &&
+  if (getLSRMode() && !PostIncLoops.empty() &&
       all_of(PostIncLoops, [&](const Loop *L) {
         return !L->contains(Builder.GetInsertBlock());
       })) {
@@ -728,7 +728,7 @@ Value *SCEVExpander::visitUDivExpr(SCEVUseT<const SCEVUDivExpr *> S) {
 
   const SCEV *RHSExpr = S->getRHS();
   Value *RHS = expand(RHSExpr);
-  if (SafeUDivMode) {
+  if (getSafeUDivMode()) {
     bool GuaranteedNotPoison =
         ScalarEvolution::isGuaranteedNotToBePoison(RHSExpr);
     if (!GuaranteedNotPoison)
@@ -1057,7 +1057,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
         continue;
 
       // Check whether we can reuse this PHI node.
-      if (LSRMode) {
+      if (getLSRMode()) {
         if (!isExpandedAddRecExprPHI(&PN, TempIncV, L))
           continue;
       } else {
@@ -1353,7 +1353,7 @@ Value *SCEVExpander::visitAddRecExpr(SCEVUseT<const SCEVAddRecExpr *> S) {
   // proper type might produce non-legal types, for example expanding an i64
   // {0,+,2,+,1} addrec would need an i65 canonical IV. To avoid this just fall
   // back to non-canonical mode for nested addrecs.
-  if (!CanonicalMode || (S->getNumOperands() > 2))
+  if (!getCanonicalMode() || (S->getNumOperands() > 2))
     return expandAddRecExprLiterally(S);
 
   Type *Ty = SE.getEffectiveSCEVType(S->getType());
@@ -1535,14 +1535,14 @@ SCEVExpander::visitSignExtendExpr(SCEVUseT<const SCEVSignExtendExpr *> S) {
 Value *SCEVExpander::expandMinMaxExpr(SCEVUseT<const SCEVNAryExpr *> S,
                                       Intrinsic::ID IntrinID, Twine Name,
                                       bool IsSequential) {
-  bool PrevSafeMode = SafeUDivMode;
-  SafeUDivMode |= IsSequential;
+  bool PrevSafeMode = getSafeUDivMode();
+  setSafeUDivMode(getSafeUDivMode() | (IsSequential));
   Value *LHS = expand(S->getOperand(S->getNumOperands() - 1));
   Type *Ty = LHS->getType();
   if (IsSequential)
     LHS = Builder.CreateFreeze(LHS);
   for (int i = S->getNumOperands() - 2; i >= 0; --i) {
-    SafeUDivMode = (IsSequential && i != 0) || PrevSafeMode;
+    setSafeUDivMode((IsSequential && i != 0) || PrevSafeMode);
     Value *RHS = expand(S->getOperand(i));
     if (IsSequential && i != 0)
       RHS = Builder.CreateFreeze(RHS);
@@ -1558,7 +1558,7 @@ Value *SCEVExpander::expandMinMaxExpr(SCEVUseT<const SCEVNAryExpr *> S,
     }
     LHS = Sel;
   }
-  SafeUDivMode = PrevSafeMode;
+  setSafeUDivMode(PrevSafeMode);
   return LHS;
 }
 
@@ -1611,7 +1611,7 @@ Value *SCEVExpander::FindValueInExprValueMap(
     SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
   // If the expansion is not in CanonicalMode, and the SCEV contains any
   // sub scAddRecExpr type SCEV, it is required to expand the SCEV literally.
-  if (!CanonicalMode && SE.containsAddRecurrence(S))
+  if (!getCanonicalMode() && SE.containsAddRecurrence(S))
     return nullptr;
 
   // If S is a constant or unknown, it may be worse to reuse an existing Value.
@@ -2438,7 +2438,7 @@ Value *SCEVExpander::expandUnionPredicate(const SCEVUnionPredicate *Union,
 
 Value *SCEVExpander::fixupLCSSAFormFor(Value *V) {
   auto *DefI = dyn_cast<Instruction>(V);
-  if (!PreserveLCSSA || !DefI)
+  if (!getPreserveLCSSA() || !DefI)
     return V;
 
   BasicBlock::iterator InsertPt = Builder.GetInsertPoint();
@@ -2533,7 +2533,7 @@ struct SCEVFindUnsafe {
 } // namespace
 
 bool SCEVExpander::isSafeToExpand(const SCEV *S) const {
-  SCEVFindUnsafe Search(SE, CanonicalMode);
+  SCEVFindUnsafe Search(SE, getCanonicalMode());
   visitAll(S, Search);
   return !Search.IsUnsafe;
 }
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index d13d50fbc91ca..aebc99b0b2f7f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -14,6 +14,7 @@
 
 #include "llvm/Transforms/Utils/SimplifyIndVar.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -1069,9 +1070,13 @@ class WidenIV {
 
   // Does the module have any calls to the llvm.experimental.guard intrinsic
   // at all? If not we can avoid scanning instructions looking for guards.
-  bool HasGuards;
+  bool getHasGuards() const { return NarrowIVUsers.getFlag(0); }
+  void setHasGuards(bool Value) { NarrowIVUsers.setFlag(0, Value); }
 
-  bool UsePostIncrementRanges;
+  bool getUsePostIncrementRanges() const { return NarrowIVUsers.getFlag(1); }
+  void setUsePostIncrementRanges(bool Value) {
+    NarrowIVUsers.setFlag(1, Value);
+  }
 
   // Statistics
   unsigned NumElimExt = 0;
@@ -1179,7 +1184,7 @@ class WidenIV {
   void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);
 
 private:
-  SmallVector<NarrowIVDefUse, 8> NarrowIVUsers;
+  llvm::SmallVectorWithFlags<NarrowIVDefUse, 8, 2> NarrowIVUsers;
 };
 } // namespace
 
@@ -1235,14 +1240,15 @@ static Instruction *getInsertPointForUses(Instruction *User, Value *Def,
 }
 
 WidenIV::WidenIV(const WideIVInfo &WI, LoopInfo *LInfo, ScalarEvolution *SEv,
-          DominatorTree *DTree, SmallVectorImpl<WeakTrackingVH> &DI,
-          bool HasGuards, bool UsePostIncrementRanges)
-      : OrigPhi(WI.NarrowIV), WideType(WI.WidestNativeType), LI(LInfo),
-        L(LI->getLoopFor(OrigPhi->getParent())), SE(SEv), DT(DTree),
-        HasGuards(HasGuards), UsePostIncrementRanges(UsePostIncrementRanges),
-        DeadInsts(DI) {
-    assert(L->getHeader() == OrigPhi->getParent() && "Phi must be an IV");
-    ExtendKindMap[OrigPhi] = WI.IsSigned ? ExtendKind::Sign : ExtendKind::Zero;
+                 DominatorTree *DTree, SmallVectorImpl<WeakTrackingVH> &DI,
+                 bool HasGuards, bool UsePostIncrementRanges)
+    : OrigPhi(WI.NarrowIV), WideType(WI.WidestNativeType), LI(LInfo),
+      L(LI->getLoopFor(OrigPhi->getParent())), SE(SEv), DT(DTree),
+      DeadInsts(DI),
+      NarrowIVUsers(decltype(this->NarrowIVUsers)::withFlags(
+          unsigned(HasGuards) | (unsigned(UsePostIncrementRanges) << 1))) {
+  assert(L->getHeader() == OrigPhi->getParent() && "Phi must be an IV");
+  ExtendKindMap[OrigPhi] = WI.IsSigned ? ExtendKind::Sign : ExtendKind::Zero;
 }
 
 Value *WidenIV::createExtendInst(Value *NarrowOper, Type *WideType,
@@ -2086,7 +2092,7 @@ PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter) {
   // definition is not negative (see pushNarrowIVUsers). It's difficult to do
   // this on demand because when pushNarrowIVUsers needs this information some
   // of the dominating conditions might be already widened.
-  if (UsePostIncrementRanges)
+  if (getUsePostIncrementRanges())
     calculatePostIncRanges(OrigPhi);
 
   // The rewriter provides a value for the desired IV expression. This may
@@ -2204,7 +2210,7 @@ void WidenIV::calculatePostIncRange(Instruction *NarrowDef,
   };
 
   auto UpdateRangeFromGuards = [&](Instruction *Ctx) {
-    if (!HasGuards)
+    if (!getHasGuards())
       return;
 
     for (Instruction &I : make_range(Ctx->getIterator().getReverse(),
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 9cfe3f55140b3..89ad2abfba426 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -326,7 +326,7 @@ static bool storeToSameAddress(ScalarEvolution *SE, StoreInst *A,
 }
 
 void LoopVectorizationLegality::collectUnitStridePredicates() const {
-  if (!AllowRuntimeSCEVChecks || !TheLoop->isInnermost())
+  if (!getAllowRuntimeSCEVChecks() || !TheLoop->isInnermost())
     return;
 
   for (BasicBlock *BB : TheLoop->blocks())
@@ -343,12 +343,12 @@ int LoopVectorizationLegality::isConsecutivePtr(Type *AccessTy,
   // masked access.
   // Stride versioning requires adding a SCEV equality predicate; only consult
   // the symbolic strides when runtime SCEV checks are permitted.
-  const auto &Strides = LAI && AllowRuntimeSCEVChecks
+  const auto &Strides = LAI && getAllowRuntimeSCEVChecks()
                             ? LAI->getSymbolicStrides()
                             : SymbolicStrideMap();
   SmallVector<const SCEVPredicate *> Predicates;
   int Stride = getPtrStride(PSE, AccessTy, Ptr, TheLoop, *DT, Strides, false,
-                            AllowRuntimeSCEVChecks ? &Predicates : nullptr)
+                            getAllowRuntimeSCEVChecks() ? &Predicates : nullptr)
                    .value_or(0);
   if (Stride != 1 && Stride != -1)
     return 0;
@@ -947,7 +947,7 @@ bool LoopVectorizationLegality::canVectorizeInstr(Instruction &I) {
   // If we found a vectorized variant of a function, note that so LV can
   // make better decisions about maximum VF.
   if (CI && !VFDatabase::getMappings(*CI).empty())
-    VecCallVariantsFound = true;
+    setVecCallVariantsFound(true);
 
   // Check that the instruction return and stored types are vectorizable.
   if (!canWidenTypes(I, /*AllowStructCalls=*/true, ORE, TheLoop))
@@ -2011,7 +2011,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
 
   if (Result) {
     LLVM_DEBUG(dbgs() << "LV: Loop passed LoopVectorizationLegality checks"
-                      << (LAI->getRuntimePointerChecking()->Need
+                      << (LAI->getRuntimePointerChecking()->needsChecking()
                               ? " (with a runtime bound check)"
                               : "")
                       << "!\n");
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
index 923fec0283b0c..9f7959573e932 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
@@ -573,7 +573,7 @@ bool VFSelectionContext::runtimeChecksRequired() {
   LLVM_DEBUG(dbgs() << "LV: Performing code size checks.\n");
 
   Loop *L = const_cast<Loop *>(TheLoop);
-  if (Legal->getRuntimePointerChecking()->Need) {
+  if (Legal->getRuntimePointerChecking()->needsChecking()) {
     reportVectorizationFailure(
         "Runtime ptr check is required with -Os/-Oz",
         "runtime pointer checks needed. Enable vectorization of this "
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index bf211037d37e5..c954ba192cbd1 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -1338,7 +1338,7 @@ class GeneratedRTChecks {
     // TODO: We need to estimate the cost of alias-masking in
     // GeneratedRTChecks::getCost(). We can't check the MemCheckBlock as the
     // alias-mask is generated later in VPlan.
-    if (RtPtrChecking.Need && !LoopUsesPartialAliasMasking) {
+    if (RtPtrChecking.needsChecking() && !LoopUsesPartialAliasMasking) {
       auto *Pred = SCEVCheckBlock ? SCEVCheckBlock : Preheader;
       MemCheckBlock = SplitBlock(Pred, Pred->getTerminator(), DT, LI, nullptr,
                                  "vector.memcheck");
@@ -2643,7 +2643,8 @@ LoopVectorizationCostModel::computeMaxVF(ElementCount UserVF, unsigned UserIC) {
     return Config.computeVPlanOuterloopVF(UserVF);
   }
 
-  if (Legal->getRuntimePointerChecking()->Need && TTI.hasBranchDivergence()) {
+  if (Legal->getRuntimePointerChecking()->needsChecking() &&
+      TTI.hasBranchDivergence()) {
     // TODO: It may be useful to do since it's still likely to be dynamically
     // uniform if the target can skip.
     reportVectorizationFailure(
@@ -3640,7 +3641,7 @@ LoopVectorizationPlanner::selectInterleaveCount(VPlan &Plan, ElementCount VF,
          return Legal->blockNeedsPredication(BB);
        }));
   bool ScalarInterleavingRequiresRuntimePointerCheck =
-      (VF.isScalar() && Legal->getRuntimePointerChecking()->Need);
+      (VF.isScalar() && Legal->getRuntimePointerChecking()->needsChecking());
 
   // We want to interleave small loops in order to reduce the loop overhead and
   // potentially expose ILP opportunities.
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index a1a25390cbfc3..8ee5e6a1cf67d 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -36,6 +36,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVectorExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
@@ -289,39 +290,45 @@ class slpvectorizer::BoUpSLP {
   /// dependency between two distinct, range-checkable base objects, i.e. a
   /// dependency that could be turned into a runtime alias check.
   bool hasRuntimeCheckableBlockers() const {
-    return HasRuntimeCheckableBlockers;
+    return getHasRuntimeCheckableBlockersFlag();
   }
 
   /// Records whether a may-alias dependency between distinct, range-checkable
   /// base objects has been observed, so the caller can decide to retry with
   /// runtime alias checks enabled.
   void setHasRuntimeCheckableBlockers(bool V) {
-    HasRuntimeCheckableBlockers = V;
+    setHasRuntimeCheckableBlockersFlag(V);
   }
 
   /// Returns true if the last buildTree() kept a may-alias memory dependency
   /// that is not runtime-checkable (call or a non-simple mem access). Such a
   /// dependency cannot be dropped, so a runtime-checks retry cannot unblock the
   /// region and would be pure overhead.
-  bool hasNonCheckableMemBlocker() const { return HasNonCheckableMemBlocker; }
+  bool hasNonCheckableMemBlocker() const {
+    return getHasNonCheckableMemBlockerFlag();
+  }
 
   /// Records that a non-runtime-checkable may-alias dependency was kept.
-  void setHasNonCheckableMemBlocker(bool V) { HasNonCheckableMemBlocker = V; }
+  void setHasNonCheckableMemBlocker(bool V) {
+    setHasNonCheckableMemBlockerFlag(V);
+  }
 
   /// Returns true if the current vectorization attempt may drop
   /// runtime-checkable may-alias dependencies and guard the region with
   /// runtime alias checks.
-  bool isTryingRuntimeAliasChecks() const { return TryRuntimeAliasChecks; }
+  bool isTryingRuntimeAliasChecks() const {
+    return getTryRuntimeAliasChecksFlag();
+  }
 
   /// Enables or disables dropping runtime-checkable may-alias dependencies in
   /// favor of runtime alias checks for the current vectorization attempt.
-  void setTryRuntimeAliasChecks(bool V) { TryRuntimeAliasChecks = V; }
+  void setTryRuntimeAliasChecks(bool V) { setTryRuntimeAliasChecksFlag(V); }
 
   /// Resets the runtime alias check data.
   void resetRuntimeAliasCheckState() {
-    HasRuntimeCheckableBlockers = false;
-    HasNonCheckableMemBlocker = false;
-    RTChecksFinalized = false;
+    setHasRuntimeCheckableBlockersFlag(false);
+    setHasNonCheckableMemBlockerFlag(false);
+    setRTChecksFinalized(false);
     RTChecks.clear();
     RTOrigBodyOrder.clear();
   }
@@ -369,7 +376,7 @@ class slpvectorizer::BoUpSLP {
 
   /// Returns true if vectorization changed the CFG (i.e. a block was versioned
   /// with runtime alias checks). When true, CFG analyses must not be preserved.
-  bool isCFGChanged() const { return CFGChanged; }
+  bool isCFGChanged() const { return getCFGChanged(); }
 
   TreeEntry &getRootNode() {
     assert(!VectorizableTree.empty() && "No graph to get the first node from");
@@ -475,7 +482,7 @@ class slpvectorizer::BoUpSLP {
     EntryToLastInstruction.clear();
     LastInstructionToPos.clear();
     LoadEntriesToVectorize.clear();
-    IsGraphTransformMode = false;
+    setIsGraphTransformMode(false);
     GatheredLoadsEntriesFirst.reset();
     SplatGatheredScalarsRoots.clear();
     NumCanonicalSplatSubtreeEntries = 0;
@@ -485,9 +492,9 @@ class slpvectorizer::BoUpSLP {
     ExternalUsesWithNonUsers.clear();
     ExternalUseReplacements.clear();
     RTChecks.clear();
-    HasRuntimeCheckableBlockers = false;
-    HasNonCheckableMemBlocker = false;
-    RTChecksFinalized = false;
+    setHasRuntimeCheckableBlockersFlag(false);
+    setHasNonCheckableMemBlockerFlag(false);
+    setRTChecksFinalized(false);
     for (auto &Iter : BlocksSchedules) {
       BlockScheduling *BS = Iter.second.get();
       BS->clear();
@@ -3411,7 +3418,8 @@ class slpvectorizer::BoUpSLP {
   SetVector<unsigned> LoadEntriesToVectorize;
 
   /// true if graph nodes transforming mode is on.
-  bool IsGraphTransformMode = false;
+  bool getIsGraphTransformMode() const { return MergedLoopBTCs.getFlag(0); }
+  void setIsGraphTransformMode(bool Value) { MergedLoopBTCs.setFlag(0, Value); }
 
   /// The index of the first gathered load entry in the VectorizeTree.
   std::optional<unsigned> GatheredLoadsEntriesFirst;
@@ -3450,11 +3458,17 @@ class slpvectorizer::BoUpSLP {
 
   /// The loop nest, used to check if only a single loop nest is vectorized, not
   /// multiple, to avoid side-effects from the loop-aware cost model.
-  SmallVector<const Loop *> CurrentLoopNest;
+  llvm::SmallVectorWithFlags<
+      const Loop *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<const Loop *>::value, 2>
+      CurrentLoopNest;
 
   /// Per-depth SCEVs trip counts at every loop level where the tree builder has
   /// joined diverging sibling loops.
-  SmallVector<const SCEV *> MergedLoopBTCs;
+  llvm::SmallVectorWithFlags<
+      const SCEV *,
+      llvm::CalculateSmallVectorDefaultInlinedElements<const SCEV *>::value, 4>
+      MergedLoopBTCs;
 
   /// Maps the loops to their loop nests.
   SmallDenseMap<const Loop *, SmallVector<const Loop *>> LoopToLoopNest;
@@ -3542,7 +3556,12 @@ class slpvectorizer::BoUpSLP {
   /// When true, scheduling drops may-alias memory dependencies between
   /// distinct, range-checkable base objects and records them as runtime alias
   /// checks instead.
-  bool TryRuntimeAliasChecks = false;
+  bool getTryRuntimeAliasChecksFlag() const {
+    return MergedLoopBTCs.getFlag(1);
+  }
+  void setTryRuntimeAliasChecksFlag(bool Value) {
+    MergedLoopBTCs.setFlag(1, Value);
+  }
 
   /// Runtime alias checks collected during the last optimistic buildTree().
   RuntimeAliasCheckInfo RTChecks;
@@ -3568,18 +3587,30 @@ class slpvectorizer::BoUpSLP {
 
   /// True, if a may-alias dependency between distinct, range-checkable base
   /// objects is observed (whether or not it was dropped).
-  bool HasRuntimeCheckableBlockers = false;
+  bool getHasRuntimeCheckableBlockersFlag() const {
+    return MergedLoopBTCs.getFlag(2);
+  }
+  void setHasRuntimeCheckableBlockersFlag(bool Value) {
+    MergedLoopBTCs.setFlag(2, Value);
+  }
 
   /// True, if a kept may-alias dependency is not runtime-checkable (call or a
   /// non-simple memaccess).
-  bool HasNonCheckableMemBlocker = false;
+  bool getHasNonCheckableMemBlockerFlag() const {
+    return MergedLoopBTCs.getFlag(3);
+  }
+  void setHasNonCheckableMemBlockerFlag(bool Value) {
+    MergedLoopBTCs.setFlag(3, Value);
+  }
 
   /// Runtime checks are validated and bounded the collected checks.
-  bool RTChecksFinalized = false;
+  bool getRTChecksFinalized() const { return CurrentLoopNest.getFlag(0); }
+  void setRTChecksFinalized(bool Value) { CurrentLoopNest.setFlag(0, Value); }
 
   /// Set when a block was versioned with runtime alias checks, which changes
   /// the CFG. Used to drop CFG-analysis preservation for the run.
-  bool CFGChanged = false;
+  bool getCFGChanged() const { return CurrentLoopNest.getFlag(1); }
+  void setCFGChanged(bool Value) { CurrentLoopNest.setFlag(1, Value); }
 
   /// Guarded block body (non-PHI, non-alloca, non-terminator) in original
   /// source order.
@@ -3929,13 +3960,15 @@ class slpvectorizer::BoUpSLP {
 
   class ScheduleBundle final : public ScheduleEntity {
     /// The schedule data for the instructions in the bundle.
-    SmallVector<ScheduleEntity *> Bundle;
+    llvm::SmallVectorWithFlags<ScheduleEntity *> Bundle;
     /// True if this bundle is valid.
-    bool IsValid = true;
+    bool getIsValid() const { return !Bundle.getFlag(0); }
+    void setIsValid(bool Value) { Bundle.setFlag(0, !Value); }
     /// The TreeEntry that this instruction corresponds to.
     TreeEntry *TE = nullptr;
     ScheduleBundle(bool IsValid)
-        : ScheduleEntity(Kind::ScheduleBundle), IsValid(IsValid) {}
+        : ScheduleEntity(Kind::ScheduleBundle),
+          Bundle(decltype(this->Bundle)::withFlags(unsigned(!(IsValid)))) {}
 
   public:
     ScheduleBundle() : ScheduleEntity(Kind::ScheduleBundle) {}
@@ -4002,7 +4035,7 @@ class slpvectorizer::BoUpSLP {
 
     static ScheduleBundle invalid() { return {false}; }
 
-    operator bool() const { return IsValid; }
+    operator bool() const { return getIsValid(); }
 
 #ifndef NDEBUG
     void dump(raw_ostream &OS) const {
@@ -4182,8 +4215,8 @@ class slpvectorizer::BoUpSLP {
       ScheduleEnd = nullptr;
       FirstLoadStoreInRegion = nullptr;
       LastLoadStoreInRegion = nullptr;
-      RegionHasStackSave = false;
-      RegionHasMayThrow = false;
+      setRegionHasStackSave(false);
+      setRegionHasMayThrow(false);
 
       // Reduce the maximum schedule region size by the size of the
       // previous scheduling run.
@@ -5241,7 +5274,11 @@ class slpvectorizer::BoUpSLP {
     SmallDenseMap<Instruction *, SmallVector<ScheduleBundle *>>
         ScheduledBundles;
     /// The list of ScheduleBundles.
-    SmallVector<std::unique_ptr<ScheduleBundle>> ScheduledBundlesList;
+    llvm::SmallVectorWithFlags<std::unique_ptr<ScheduleBundle>,
+                               llvm::CalculateSmallVectorDefaultInlinedElements<
+                                   std::unique_ptr<ScheduleBundle>>::value,
+                               2>
+        ScheduledBundlesList;
 
     /// The ready-list for scheduling (only used for the dry-run).
     SetVector<ScheduleEntity *> ReadyInsts;
@@ -5263,16 +5300,28 @@ class slpvectorizer::BoUpSLP {
     /// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
     /// region?  Used to optimize the dependence calculation for the
     /// common case where there isn't.
-    bool RegionHasStackSave = false;
+    bool getRegionHasStackSave() const {
+      return ScheduledBundlesList.getFlag(0);
+    }
+    bool setRegionHasStackSave(bool Value) {
+      ScheduledBundlesList.setFlag(0, Value);
+      return Value;
+    }
 
     /// Used to skip the dependencies calculation for writes that are visible
     /// after unwinding.
-    bool RegionHasMayThrow = false;
+    bool getRegionHasMayThrow() const {
+      return ScheduledBundlesList.getFlag(1);
+    }
+    bool setRegionHasMayThrow(bool Value) {
+      ScheduledBundlesList.setFlag(1, Value);
+      return Value;
+    }
 
     /// Returns true if \p I writes memory that the caller can still see
     /// after an unwind.
     bool isWriteVisibleOnUnwind(Instruction *I) const {
-      if (!RegionHasMayThrow || !I->mayWriteToMemory())
+      if (!getRegionHasMayThrow() || !I->mayWriteToMemory())
         return false;
       MemoryLocation Loc = getLocation(I);
       if (!Loc.Ptr)
@@ -9466,7 +9515,7 @@ BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
     case LoadsState::Vectorize:
       return TreeEntry::Vectorize;
     case LoadsState::CompressVectorize:
-      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
+      if (!getIsGraphTransformMode() && VectorizableTree.size() > 1) {
         // Delay slow vectorized nodes for better vectorization attempts.
         LoadEntriesToVectorize.insert(VectorizableTree.size());
         return TreeEntry::NeedToGather;
@@ -9474,7 +9523,7 @@ BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
       return IsGatheredNode() ? TreeEntry::NeedToGather
                               : TreeEntry::CompressVectorize;
     case LoadsState::ScatterVectorize:
-      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
+      if (!getIsGraphTransformMode() && VectorizableTree.size() > 1) {
         // Delay slow vectorized nodes for better vectorization attempts.
         LoadEntriesToVectorize.insert(VectorizableTree.size());
         return TreeEntry::NeedToGather;
@@ -9482,7 +9531,7 @@ BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
       return IsGatheredNode() ? TreeEntry::NeedToGather
                               : TreeEntry::ScatterVectorize;
     case LoadsState::StridedVectorize:
-      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
+      if (!getIsGraphTransformMode() && VectorizableTree.size() > 1) {
         // Delay slow vectorized nodes for better vectorization attempts.
         LoadEntriesToVectorize.insert(VectorizableTree.size());
         return TreeEntry::NeedToGather;
@@ -9490,7 +9539,7 @@ BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
       return IsGatheredNode() ? TreeEntry::NeedToGather
                               : TreeEntry::StridedVectorize;
     case LoadsState::BlendedLoadVectorize:
-      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
+      if (!getIsGraphTransformMode() && VectorizableTree.size() > 1) {
         // Delay slow vectorized nodes for better vectorization attempts.
         LoadEntriesToVectorize.insert(VectorizableTree.size());
         return TreeEntry::NeedToGather;
@@ -11984,8 +12033,12 @@ static void scanAssociativeOperands(
   };
   // Signs ride with the columns so the parallel lists cannot drift apart.
   struct SignedColumn {
-    BoUpSLP::ValueList Col;
-    bool Negated;
+    SignedColumn(BoUpSLP::ValueList Col, bool Negated)
+        : Col(unsigned(Negated), std::move(Col)) {}
+
+    llvm::SmallVectorWithFlagsFor<BoUpSLP::ValueList, 1> Col;
+    bool getNegated() const { return Col.getFlag(0); }
+    void setNegated(bool Value) { Col.setFlag(0, Value); }
   };
   SmallVector<SignedColumn, 4> Columns = {
       {std::move(Operands[0]), false},
@@ -12029,7 +12082,7 @@ static void scanAssociativeOperands(
       ++Idx;
       continue;
     }
-    BoUpSLP::ValueList Column = std::move(Columns[Idx].Col);
+    BoUpSLP::ValueList Column = BoUpSLP::ValueList(std::move(Columns[Idx].Col));
     // The absorbing constants of the peeled lanes keep the identity as the
     // other operand: the poison operand is not frozen in the flattened node.
     SmallVector<BoUpSLP::ValueList> SubOperands = Analysis.buildOperands(
@@ -12042,17 +12095,18 @@ static void scanAssociativeOperands(
       if (!isa<PoisonValue>(V) && !ColS.isCopyableElement(V))
         ReassocScalars.push_back(V);
     // A peeled subtract negates its second operand column.
-    const bool Negated = Columns[Idx].Negated;
-    Columns[Idx].Col = std::move(SubOperands.front());
+    const bool Negated = Columns[Idx].getNegated();
+    Columns[Idx].Col.assign(std::move(SubOperands.front()));
     Columns.insert(
         std::next(Columns.begin(), Idx + 1),
         {std::move(SubOperands.back()), IsSub(ColS.getOpcode()) != Negated});
     // Do not advance Idx: re-examine the column that was just placed here.
   }
   Operands.clear();
-  for (auto &[Col, Negated] : Columns) {
-    Operands.push_back(std::move(Col));
-    NegatedColumns.push_back(Negated);
+  for (auto &Column : Columns) {
+    Operands.push_back(
+        llvm::SmallVector<llvm::Value *, 8>(std::move(Column.Col)));
+    NegatedColumns.push_back(Column.getNegated());
   }
 }
 
@@ -12384,7 +12438,7 @@ void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
             BailOutToGather();
             return;
           }
-          CurrentLoopNest.assign(NewLoopNest);
+          CurrentLoopNest.assign(NewLoopNest.begin(), NewLoopNest.end());
         } else if (CommonLen < CurrentLoopNest.size() &&
                    CommonLen < NewLoopNest.size()) {
           // Divergence below the common prefix: the tree now spans sibling
@@ -14401,15 +14455,14 @@ void BoUpSLP::transformNodes() {
   BaseGraphSize = VectorizableTree.size();
   // Turn graph transforming mode on and off, when done.
   class GraphTransformModeRAAI {
-    bool &SavedIsGraphTransformMode;
+    BoUpSLP &R;
 
   public:
-    GraphTransformModeRAAI(bool &IsGraphTransformMode)
-        : SavedIsGraphTransformMode(IsGraphTransformMode) {
-      IsGraphTransformMode = true;
+    GraphTransformModeRAAI(BoUpSLP &R) : R(R) {
+      R.setIsGraphTransformMode(true);
     }
-    ~GraphTransformModeRAAI() { SavedIsGraphTransformMode = false; }
-  } TransformContext(IsGraphTransformMode);
+    ~GraphTransformModeRAAI() { R.setIsGraphTransformMode(false); }
+  } TransformContext(*this);
   // Operands are profitable if they are:
   // 1. At least one constant
   // or
@@ -15085,7 +15138,8 @@ void BoUpSLP::transformNodes() {
 /// end of the process, to reduce the number of emitted instructions and further
 /// analysis/transformations.
 class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
-  bool IsFinalized = false;
+  bool getIsFinalized() const { return InVectors.getFlag(0); }
+  void setIsFinalized(bool Value) { InVectors.setFlag(0, Value); }
   SmallVector<int> CommonMask;
 
   // Each input vector can be tagged with extra context information
@@ -15102,7 +15156,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
                  TargetTransformInfo::VectorInstrContext::None)
         : Vec(Vec), Ctx(Ctx) {}
   };
-  SmallVector<InVector, 2> InVectors;
+  llvm::SmallVectorWithFlags<InVector, 2, 2> InVectors;
   /// Captures the original scalar VL of a single, "clean" gather() call so
   /// the values can be forwarded as the Args operand to getShuffleCost() for
   /// the final permutation in finalize(). This lets the target cost model
@@ -15126,7 +15180,8 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
   /// can delay actual cost estimation (virtual shuffle instruction emission).
   /// May help better estimate the cost if same nodes must be permuted + allows
   /// to move most of the long shuffles cost estimation to TTI.
-  bool SameNodesEstimated = true;
+  bool getSameNodesEstimated() const { return !InVectors.getFlag(1); }
+  void setSameNodesEstimated(bool Value) { InVectors.setFlag(1, !Value); }
 
   static Constant *getAllOnesValue(const DataLayout &DL, Type *Ty) {
     if (Ty->getScalarType()->isPointerTy()) {
@@ -15329,7 +15384,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
   void estimateNodesPermuteCost(const TreeEntry &E1, const TreeEntry *E2,
                                 ArrayRef<int> Mask, unsigned Part,
                                 unsigned SliceSize) {
-    if (SameNodesEstimated) {
+    if (getSameNodesEstimated()) {
       // Delay the cost estimation if the same nodes are reshuffling.
       // If we already requested the cost of reshuffling of E1 and E2 before, no
       // need to estimate another cost with the sub-Mask, instead include this
@@ -15363,7 +15418,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
                         {}, InVectors.front().Ctx, InVectors.back().Ctx);
       transformMaskAfterShuffle(CommonMask, CommonMask);
     }
-    SameNodesEstimated = false;
+    setSameNodesEstimated(false);
     if (!E2 && InVectors.size() == 1) {
       unsigned VF = E1.getVectorFactor();
       if (Value *V1 = InVectors.front().Vec.dyn_cast<Value *>()) {
@@ -15789,7 +15844,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
     InVectors.assign(1, E);
     CommonMask.assign(Mask.begin(), Mask.end());
     transformMaskAfterShuffle(CommonMask, CommonMask);
-    SameNodesEstimated = false;
+    setSameNodesEstimated(false);
     if (NumParts != 1 && UniqueBases.size() != 1) {
       UseVecBaseAsInput = true;
       VecBase =
@@ -15807,12 +15862,12 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
   }
   /// Reset the builder to handle perfect diamond match.
   void resetForSameNode() {
-    IsFinalized = false;
+    setIsFinalized(false);
     CommonMask.clear();
     InVectors.clear();
     Cost = 0;
     VectorizedVals.clear();
-    SameNodesEstimated = true;
+    setSameNodesEstimated(true);
   }
   void add(const TreeEntry &E1, const TreeEntry &E2, ArrayRef<int> Mask) {
     BVValues.reset();
@@ -15852,7 +15907,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
     const auto *It = find_if(Mask, not_equal_to(PoisonMaskElem));
     unsigned Part = std::distance(Mask.begin(), It) / SliceSize;
     estimateNodesPermuteCost(E1, nullptr, Mask, Part, SliceSize);
-    if (!SameNodesEstimated && InVectors.size() == 1)
+    if (!getSameNodesEstimated() && InVectors.size() == 1)
       InVectors.emplace_back(&E1);
   }
   /// Adds 2 input vectors and the mask for their shuffling.
@@ -16023,7 +16078,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
       function_ref<void(Value *&, SmallVectorImpl<int> &,
                         function_ref<Value *(Value *, Value *, ArrayRef<int>)>)>
           Action = {}) {
-    IsFinalized = true;
+    setIsFinalized(true);
     if (Action) {
       const PointerUnion<Value *, const TreeEntry *> &Vec =
           InVectors.front().Vec;
@@ -16131,7 +16186,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
   }
 
   ~ShuffleCostEstimator() {
-    assert((IsFinalized || CommonMask.empty()) &&
+    assert((getIsFinalized() || CommonMask.empty()) &&
            "Shuffle construction must be finalized.");
   }
 };
@@ -22552,7 +22607,8 @@ Value *BoUpSLP::gather(
 /// \endcode
 /// instead.
 class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
-  bool IsFinalized = false;
+  bool getIsFinalized() const { return InVectors.getFlag(0); }
+  void setIsFinalized(bool Value) { InVectors.setFlag(0, Value); }
   /// Combined mask for all applied operands and masks. It is built during
   /// analysis and actual emission of shuffle vector instructions.
   SmallVector<int> CommonMask;
@@ -22561,7 +22617,7 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
   /// shuffle with \p CommonMask mask, the first operand sets to be the
   /// resulting shuffle and the second operand sets to be the newly added
   /// operand. The \p CommonMask is transformed in the proper way after that.
-  SmallVector<Value *, 2> InVectors;
+  llvm::SmallVectorWithFlags<Value *, 2> InVectors;
   IRBuilderBase &Builder;
   BoUpSLP &R;
 
@@ -22856,7 +22912,7 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
   }
   /// Reset the builder to handle perfect diamond match.
   void resetForSameNode() {
-    IsFinalized = false;
+    setIsFinalized(false);
     CommonMask.clear();
     InVectors.clear();
   }
@@ -23014,7 +23070,7 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
       function_ref<void(Value *&, SmallVectorImpl<int> &,
                         function_ref<Value *(Value *, Value *, ArrayRef<int>)>)>
           Action = {}) {
-    IsFinalized = true;
+    setIsFinalized(true);
     if (Action) {
       Value *Vec = InVectors.front();
       if (InVectors.size() == 2) {
@@ -23113,7 +23169,7 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
   }
 
   ~ShuffleInstructionBuilder() {
-    assert((IsFinalized || CommonMask.empty()) &&
+    assert((getIsFinalized() || CommonMask.empty()) &&
            "Shuffle construction must be finalized.");
   }
 };
@@ -25708,7 +25764,7 @@ static bool blockBodyHasVectorInstructions(const VectorizeOptions &Opts,
 
 void BoUpSLP::captureRuntimeCheckBodySnapshot() {
   RTOrigBodyOrder.clear();
-  if (!TryRuntimeAliasChecks || !RTChecks.BB)
+  if (!getTryRuntimeAliasChecksFlag() || !RTChecks.BB)
     return;
   BasicBlock *BB = RTChecks.BB;
   // Allocas are not duplicated, keep them in the header block.
@@ -25739,7 +25795,7 @@ bool BoUpSLP::recordRuntimeAliasCheck(BasicBlock *BB, Instruction *Inst1,
                  RTChecks.BasePairs.contains({Base2, Base1});
   // After the checks have been validated and bounded, do not introduce new
   // pairs.
-  if (RTChecksFinalized)
+  if (getRTChecksFinalized())
     return Present;
   RTChecks.BB = BB;
   if (!Present)
@@ -25938,7 +25994,7 @@ bool BoUpSLP::canVersionForRuntimeChecks() {
 
   // Freeze the check set so the final scheduleBlock() keeps the same dropped
   // dependencies the bounds were just computed for.
-  RTChecksFinalized = true;
+  setRTChecksFinalized(true);
   return true;
 }
 
@@ -26002,8 +26058,8 @@ Value *BoUpSLP::emitRuntimeAliasCheck(IRBuilderBase &Builder,
 
 void BoUpSLP::versionBlocksForRuntimeChecks() {
   // Only version when this is the optimistic attempt that collected the checks.
-  if (!TryRuntimeAliasChecks || RTChecks.BasePairs.empty() || !RTChecks.BB ||
-      RTOrigBodyOrder.empty())
+  if (!getTryRuntimeAliasChecksFlag() || RTChecks.BasePairs.empty() ||
+      !RTChecks.BB || RTOrigBodyOrder.empty())
     return;
   BasicBlock *BB = RTChecks.BB;
   Function *Fn = BB->getParent();
@@ -26131,10 +26187,10 @@ void BoUpSLP::versionBlocksForRuntimeChecks() {
   // The checks have been emitted; clear so any later vectorizeTree() in the
   // same attempt does not version again.
   RTChecks.clear();
-  RTChecksFinalized = false;
+  setRTChecksFinalized(false);
   RTOrigBodyOrder.clear();
   // The CFG was modified; CFG analyses can no longer be preserved.
-  CFGChanged = true;
+  setCFGChanged(true);
 }
 
 Value *BoUpSLP::vectorizeTree() {
@@ -27510,7 +27566,7 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
           if (ScheduleData *BundleMember = getScheduleData(SD->getInst());
               BundleMember && BundleMember->hasValidDependencies()) {
             BundleMember->clearDirectDependencies();
-            if (RegionHasStackSave ||
+            if (getRegionHasStackSave() ||
                 !isGuaranteedToTransferExecutionToSuccessor(
                     BundleMember->getInst()) ||
                 isWriteVisibleOnUnwind(BundleMember->getInst()))
@@ -27540,7 +27596,7 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
             if (ScheduleData *OpSD = getScheduleData(Op);
                 OpSD && OpSD->hasValidDependencies()) {
               OpSD->clearDirectDependencies();
-              if (RegionHasStackSave ||
+              if (getRegionHasStackSave() ||
                   !isGuaranteedToTransferExecutionToSuccessor(
                       OpSD->getInst()) ||
                   isWriteVisibleOnUnwind(OpSD->getInst()))
@@ -27879,9 +27935,9 @@ void BoUpSLP::BlockScheduling::initScheduleData(Instruction *FromI,
 
     if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
         match(I, m_Intrinsic<Intrinsic::stackrestore>()))
-      RegionHasStackSave = true;
+      setRegionHasStackSave(true);
     if (I->mayThrow())
-      RegionHasMayThrow = true;
+      setRegionHasMayThrow(true);
   }
   if (NextLoadStore) {
     if (CurrentLoadStore)
@@ -28062,7 +28118,7 @@ void BoUpSLP::BlockScheduling::calculateDependencies(
       }
     }
 
-    if (RegionHasStackSave) {
+    if (getRegionHasStackSave()) {
       // If we have an inalloc alloca instruction, it needs to be scheduled
       // after any preceeding stacksave.  We also need to prevent any alloca
       // from reordering above a preceeding stackrestore.
@@ -30970,12 +31026,17 @@ class HorizontalReduction {
   RecurKind RdxKind;
   /// Checks if the optimization of original scalar identity operations on
   /// matched horizontal reductions is enabled and allowed.
-  bool IsSupportedHorRdxIdentityOp = false;
+  bool getIsSupportedHorRdxIdentityOp() const {
+    return VectorValuesAndScales.getFlag(0);
+  }
+  void setIsSupportedHorRdxIdentityOp(bool Value) {
+    VectorValuesAndScales.setFlag(0, Value);
+  }
   /// The minimum number of the reduced values.
   const unsigned ReductionLimit = Opts.slp_vectorize_non_power_of_2 ? 3 : 4;
   /// Contains vector values for reduction including their scale factor,
   /// signedness and sign of their contribution to the reduction result.
-  SmallVector<ReductionVectorPart> VectorValuesAndScales;
+  llvm::SmallVectorWithFlags<ReductionVectorPart> VectorValuesAndScales;
 
   /// Narrow reduced values mapped to the shift and the mask applied after
   /// widening.
@@ -32997,13 +33058,13 @@ class HorizontalReduction {
 
       // Check if we support repeated scalar values processing (optimization of
       // original scalar identity operations on matched horizontal reductions).
-      IsSupportedHorRdxIdentityOp =
+      setIsSupportedHorRdxIdentityOp(
           RK == ReductionOrdering::Unordered && RdxKind != RecurKind::Mul &&
           RdxKind != RecurKind::FMul && RdxKind != RecurKind::FMulAdd &&
-          (!Opts.slp_revec || !Candidates.front()->getType()->isVectorTy());
+          (!Opts.slp_revec || !Candidates.front()->getType()->isVectorTy()));
       // Gather same values.
       SmallMapVector<Value *, unsigned, 16> SameValuesCounter;
-      if (IsSupportedHorRdxIdentityOp)
+      if (getIsSupportedHorRdxIdentityOp())
         for (const auto [Idx, V] : enumerate(Candidates)) {
           Value *OrigV = TrackedToOrig[Idx];
           ++SameValuesCounter.try_emplace(OrigV).first->second;
@@ -33019,7 +33080,7 @@ class HorizontalReduction {
       // this analysis, other operations may require an extra estimation of
       // the profitability.
       bool SameScaleFactor = false;
-      bool OptReusedScalars = IsSupportedHorRdxIdentityOp &&
+      bool OptReusedScalars = getIsSupportedHorRdxIdentityOp() &&
                               SameValuesCounter.size() != Candidates.size();
       BoUpSLP::ExtraValueToDebugLocsMap ExternallyUsedValues;
       for (Value *RdxVal : ExcludedVectorizedReducedVals)
@@ -33201,7 +33262,7 @@ class HorizontalReduction {
                make_isa_range<Instruction>(ReducedVals[Cnt]))
             LocalExternallyUsedValues.insert(TrackedVals[Inst]);
         }
-        if (!IsSupportedHorRdxIdentityOp) {
+        if (!getIsSupportedHorRdxIdentityOp()) {
           // Number of uses of the candidates in the vector of values.
           assert(SameValuesCounter.empty() &&
                  "Reused values counter map is not empty");
@@ -33220,7 +33281,7 @@ class HorizontalReduction {
         const bool LoopAccCandidate =
             !GroupNegated &&
             LoopAcc.isCandidate(VectorizedTree, !VectorValuesAndScales.empty(),
-                                IsSupportedHorRdxIdentityOp, ReducedVals,
+                                getIsSupportedHorRdxIdentityOp(), ReducedVals,
                                 Candidates, I, Pos, ReduxWidth,
                                 OptReusedScalars, SameScaleFactor);
 
@@ -33248,7 +33309,7 @@ class HorizontalReduction {
             LocalExternallyUsedValues.insert(RdxVal);
         }
         // Do not need the list of reused scalars in regular mode anymore.
-        if (!IsSupportedHorRdxIdentityOp)
+        if (!getIsSupportedHorRdxIdentityOp())
           SameValuesCounter.clear();
         for (Value *RdxVal : VL)
           if (RequiredExtract.contains(RdxVal))
@@ -33460,7 +33521,7 @@ class HorizontalReduction {
         // Count vectorized reduced values to exclude them from final reduction.
         for (const auto [Idx, RdxVal] : enumerate(VL)) {
           Value *OrigV = TrackedToOrig[Pos + Idx];
-          if (IsSupportedHorRdxIdentityOp) {
+          if (getIsSupportedHorRdxIdentityOp()) {
             VectorizedVals.try_emplace(OrigV, At(SameValuesCounter, OrigV));
             continue;
           }
@@ -34833,7 +34894,7 @@ class HorizontalReduction {
   /// Emits optimized code for unique scalar value reused \p Cnt times.
   Value *emitScaleForReusedOps(Value *VectorizedValue, IRBuilderBase &Builder,
                                unsigned Cnt) {
-    assert(IsSupportedHorRdxIdentityOp &&
+    assert(getIsSupportedHorRdxIdentityOp() &&
            "The optimization of matched scalar identity horizontal reductions "
            "must be supported.");
     if (Cnt == 1)
@@ -34909,7 +34970,7 @@ class HorizontalReduction {
   emitReusedOps(Value *VectorizedValue, IRBuilderBase &Builder, BoUpSLP &R,
                 const SmallMapVector<Value *, unsigned, 16> &SameValuesCounter,
                 ArrayRef<Value *> TrackedToOrig) {
-    assert(IsSupportedHorRdxIdentityOp &&
+    assert(getIsSupportedHorRdxIdentityOp() &&
            "The optimization of matched scalar identity horizontal reductions "
            "must be supported.");
     ArrayRef<Value *> VL = R.getRootNodeScalars();
diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 526ed936cbfd0..57cddaa3a8dcb 100644
--- a/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -13,6 +13,7 @@
 #include "dsymutil.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Support/Chrono.h"
@@ -39,8 +40,8 @@ class MachODebugMapParser {
       : BinaryPath(std::string(BinaryPath)), Archs(Archs),
         DSYMSearchPaths(DSYMSearchPaths), PathPrefix(std::string(PathPrefix)),
         VariantSuffix(std::string(VariantSuffix)), BinHolder(BinHolder),
-        CurrentDebugMapObject(nullptr), SkipDebugMapObject(false),
-        ObjectFilter(ObjectFilter), ObjectFilterType(ObjectFilterType) {}
+        CurrentDebugMapObject(nullptr), ObjectFilter(ObjectFilter),
+        ObjectFilterType(ObjectFilterType) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
   /// multiple maps in case it is a universal binary.
@@ -56,7 +57,7 @@ class MachODebugMapParser {
 private:
   std::string BinaryPath;
   SmallVector<StringRef, 1> Archs;
-  SmallVector<StringRef, 1> DSYMSearchPaths;
+  llvm::SmallVectorWithFlags<StringRef, 1> DSYMSearchPaths;
   std::string PathPrefix;
   std::string VariantSuffix;
 
@@ -83,7 +84,8 @@ class MachODebugMapParser {
   DebugMapObject *CurrentDebugMapObject;
 
   /// Whether we need to skip the current debug map object.
-  bool SkipDebugMapObject;
+  bool getSkipDebugMapObject() const { return DSYMSearchPaths.getFlag(0); }
+  void setSkipDebugMapObject(bool Value) { DSYMSearchPaths.setFlag(0, Value); }
 
   /// Optional set of object paths to filter on.
   const std::optional<StringSet<>> &ObjectFilter;
@@ -177,7 +179,7 @@ void MachODebugMapParser::resetParserState() {
   CurrentObjectAliasMap.clear();
   SeenAliasValues.clear();
   CurrentDebugMapObject = nullptr;
-  SkipDebugMapObject = false;
+  setSkipDebugMapObject(false);
 }
 
 /// Commons symbols won't show up in the symbol map but might need to be
@@ -212,7 +214,7 @@ void MachODebugMapParser::switchToNewDebugMapObject(
   sys::path::append(Path, Filename);
 
   if (!shouldIncludeObject(Path)) {
-    SkipDebugMapObject = true;
+    setSkipDebugMapObject(true);
     return;
   }
 
@@ -664,7 +666,7 @@ void MachODebugMapParser::handleStabSymbolTableEntry(
     if (!CurrentDebugMapObject ||
         CurrentDebugMapObject->getType() != MachO::N_LIB) {
       if (Duplicates.count(OSO(Name, Value))) {
-        SkipDebugMapObject = true;
+        setSkipDebugMapObject(true);
         return;
       }
       switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
@@ -672,7 +674,7 @@ void MachODebugMapParser::handleStabSymbolTableEntry(
     return;
   }
 
-  if (SkipDebugMapObject)
+  if (getSkipDebugMapObject())
     return;
 
   if (Type == MachO::N_AST) {
diff --git a/llvm/tools/dsymutil/Reproducer.cpp b/llvm/tools/dsymutil/Reproducer.cpp
index 0c1d3f90af299..ed79d433c9fef 100644
--- a/llvm/tools/dsymutil/Reproducer.cpp
+++ b/llvm/tools/dsymutil/Reproducer.cpp
@@ -35,7 +35,8 @@ Reproducer::~Reproducer() = default;
 
 ReproducerGenerate::ReproducerGenerate(std::error_code &EC, int Argc,
                                        char **Argv, bool GenerateOnExit)
-    : Root(createReproducerDir(EC)), GenerateOnExit(GenerateOnExit) {
+    : Root(createReproducerDir(EC)),
+      Args(decltype(Args)::withFlags(unsigned(GenerateOnExit))) {
   llvm::append_range(Args, ArrayRef(Argv, Argc));
   auto RealFS = vfs::getRealFileSystem();
   if (!Root.empty())
@@ -44,16 +45,16 @@ ReproducerGenerate::ReproducerGenerate(std::error_code &EC, int Argc,
 }
 
 ReproducerGenerate::~ReproducerGenerate() {
-  if (GenerateOnExit && !Generated)
+  if (getGenerateOnExit() && !getGenerated())
     generate();
-  else if (!Generated && !Root.empty())
+  else if (!getGenerated() && !Root.empty())
     sys::fs::remove_directories(Root, /* IgnoreErrors */ true);
 }
 
 void ReproducerGenerate::generate() {
   if (!FC)
     return;
-  Generated = true;
+  setGenerated(true);
   FC->copyFiles(false);
   SmallString<128> Mapping(Root);
   sys::path::append(Mapping, "mapping.yaml");
diff --git a/llvm/tools/dsymutil/Reproducer.h b/llvm/tools/dsymutil/Reproducer.h
index b53b485fbea6c..f681b1e146cd7 100644
--- a/llvm/tools/dsymutil/Reproducer.h
+++ b/llvm/tools/dsymutil/Reproducer.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
 #define LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/FileCollector.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
@@ -63,13 +64,15 @@ class ReproducerGenerate : public Reproducer {
   std::shared_ptr<FileCollector> FC;
 
   /// The input arguments to build the reproducer invocation.
-  llvm::SmallVector<llvm::StringRef, 0> Args;
+  llvm::SmallVectorWithFlags<llvm::StringRef, 0, 2> Args;
 
   /// Whether to generate the reproducer on destruction.
-  bool GenerateOnExit = false;
+  bool getGenerateOnExit() const { return Args.getFlag(0); }
+  void setGenerateOnExit(bool Value) { Args.setFlag(0, Value); }
 
   /// Whether we already generated the reproducer.
-  bool Generated = false;
+  bool getGenerated() const { return Args.getFlag(1); }
+  void setGenerated(bool Value) { Args.setFlag(1, Value); }
 };
 
 /// Reproducer instance used to use an existing reproducer. The VFS returned by
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index bde187ea35ed1..d4e5aa08328d6 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -13,8 +13,9 @@
 #ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
 #define LLVM_COV_SOURCECOVERAGEVIEW_H
 
-#include "CoverageViewOptions.h"
 #include "CoverageSummaryInfo.h"
+#include "CoverageViewOptions.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <vector>
@@ -167,13 +168,14 @@ class SourceCoverageView {
   SmallVector<BranchView, 0> BranchSubViews;
 
   /// A container for all MCDC records in the source on display.
-  SmallVector<MCDCView, 0> MCDCSubViews;
+  llvm::SmallVectorWithFlags<MCDCView, 0> MCDCSubViews;
 
   /// A container for all instantiations (e.g template functions) in the source
   /// on display.
   std::vector<InstantiationView> InstantiationSubViews;
 
-  bool BinaryCounters;
+  bool getBinaryCounters() const { return MCDCSubViews.getFlag(0); }
+  void setBinaryCounters(bool Value) { MCDCSubViews.setFlag(0, Value); }
 
   /// Get the first uncovered line number for the source file.
   unsigned getFirstUncoveredLineNo();
@@ -262,7 +264,7 @@ class SourceCoverageView {
   static std::string formatCount(uint64_t N);
 
   uint64_t BinaryCount(uint64_t N) const {
-    return (N && BinaryCounters ? 1 : N);
+    return (N && getBinaryCounters() ? 1 : N);
   }
 
   std::string formatBinaryCount(uint64_t N) const {
@@ -280,8 +282,9 @@ class SourceCoverageView {
                      CoverageData &&CoverageInfo)
       : SourceName(SourceName), File(File), Options(Options),
         CoverageInfo(std::move(CoverageInfo)),
-        BinaryCounters(Options.BinaryCounters ||
-                       CoverageInfo.getSingleByteCoverage()) {}
+        MCDCSubViews(decltype(this->MCDCSubViews)::withFlags(unsigned(bool(
+            Options.BinaryCounters || CoverageInfo.getSingleByteCoverage())))) {
+  }
 
 public:
   static std::unique_ptr<SourceCoverageView>
diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp
index 295f3ce3785b4..db9bdc3a4a6b0 100644
--- a/llvm/tools/llvm-dwarfdump/Coverage.cpp
+++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm-dwarfdump.h"
 #include "llvm/ADT/SetOperations.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
@@ -432,13 +433,22 @@ struct VarKey {
 };
 
 struct VarCoverage {
-  SmallVector<DWARFDie> Parents;
+  VarCoverage(ArrayRef<DWARFDie> Parents, size_t Cov, size_t BaselineCov,
+              size_t LTCov, size_t Missing, size_t Instances,
+              bool MissingBaseline)
+      : Parents(decltype(this->Parents)::withFlags(unsigned(MissingBaseline),
+                                                   Parents)),
+        Cov(Cov), BaselineCov(BaselineCov), LTCov(LTCov), Missing(Missing),
+        Instances(Instances) {}
+
+  llvm::SmallVectorWithFlags<DWARFDie> Parents;
   size_t Cov;
   size_t BaselineCov;
   size_t LTCov;
   size_t Missing;
   size_t Instances;
-  bool MissingBaseline;
+  bool getMissingBaseline() const { return Parents.getFlag(0); }
+  void setMissingBaseline(bool Value) { Parents.setFlag(0, Value); }
 };
 
 typedef std::multimap<VarKey, VarCoverage, std::less<>> VarMap;
@@ -457,7 +467,7 @@ static std::optional<const VarKey> getVarKey(DWARFDie VariableDIE,
                 VariableDIE.getDeclLine()};
 }
 
-static void displayParents(SmallVector<DWARFDie> Parents, raw_ostream &OS) {
+static void displayParents(ArrayRef<DWARFDie> Parents, raw_ostream &OS) {
   bool First = true;
   for (const auto Parent : Parents) {
     if (auto FormValue = Parent.find(DW_AT_call_file)) {
@@ -494,7 +504,7 @@ static void displayVariableCoverage(const VarKey &Key, const VarCoverage &Var,
        << format("%.3g", ((float)Var.LTCov / Var.Instances)) << "\t"
        << format("%.3g", ((float)Var.LTCov / Var.BaselineCov));
   OS << "\n";
-  if (Var.MissingBaseline)
+  if (Var.getMissingBaseline())
     WithColor(errs(), HighlightColor::Warning).warning()
         << "DIE not found in baseline\n";
   if (Var.Missing)
@@ -596,7 +606,7 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
           for (const auto &L : BCov)
             VarCov.LTCov += SubroutineCov.count(L);
         } else {
-          VarCov.MissingBaseline = true;
+          VarCov.setMissingBaseline(true);
         }
       }
 
@@ -628,7 +638,11 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx,
         CombinedCov.BaselineCov += Var->second.BaselineCov;
         CombinedCov.LTCov += Var->second.LTCov;
         CombinedCov.Missing += Var->second.Missing;
-        CombinedCov.MissingBaseline |= Var->second.MissingBaseline;
+        [&] {
+          auto PackedFlagValue = Var->second.getMissingBaseline();
+          return CombinedCov.setMissingBaseline(
+              CombinedCov.getMissingBaseline() | PackedFlagValue);
+        }();
       }
       displayVariableCoverage(FirstVar->first, CombinedCov, true, OS);
     }
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index da21787c5096c..d653f44dfbefe 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -402,7 +402,9 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
   DumpOpts.ShowAddresses = !Diff;
   DumpOpts.ShowChildren = ShowChildren;
   DumpOpts.ShowParents = ShowParents;
-  DumpOpts.FilterChildTag = makeTagVector(FilterChildTag);
+  auto ChildTags = makeTagVector(FilterChildTag);
+  DumpOpts.FilterChildTag = decltype(DumpOpts.FilterChildTag)(
+      DumpOpts.FilterChildTag.getFlags(), std::move(ChildTags));
   DumpOpts.ShowForm = ShowForm;
   DumpOpts.SummarizeTypes = SummarizeTypes;
   DumpOpts.Verbose = Verbose;
@@ -415,8 +417,8 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
   if (Verify) {
     DumpOpts.Verbose = ErrorDetails != NoDetailsOnlySummary &&
                        ErrorDetails != NoDetailsOrSummary;
-    DumpOpts.ShowAggregateErrors = ErrorDetails != OnlyDetailsNoSummary &&
-                                   ErrorDetails != NoDetailsOnlySummary;
+    DumpOpts.setShowAggregateErrors(ErrorDetails != OnlyDetailsNoSummary &&
+                                    ErrorDetails != NoDetailsOnlySummary);
     DumpOpts.JsonErrSummaryFile = JsonErrSummaryFile;
     return DumpOpts.noImplicitRecursion();
   }
diff --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
index 2176db14f06f4..d04470a922319 100644
--- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -244,7 +244,7 @@ static Expected<uint32_t> saveSeparateDebugInfo(const Options &Opts,
   std::string OutputFilename = Opts.getSeparateDebugFileName();
   Config.Common.InputFilename = Opts.InputFileName;
   Config.Common.OutputFilename = OutputFilename;
-  Config.Common.OnlyKeepDebug = true;
+  Config.Common.setOnlyKeepDebug(true);
   uint32_t WrittenFileCRC32 = 0;
 
   if (Error Err = writeToOutput(
@@ -267,7 +267,7 @@ static Error saveNonDebugInfo(const Options &Opts, ObjectFile &InputFile,
   objcopy::ConfigManager Config;
   Config.Common.InputFilename = Opts.InputFileName;
   Config.Common.OutputFilename = Opts.OutputFileName;
-  Config.Common.StripDebug = true;
+  Config.Common.setStripDebug(true);
   std::string SeparateDebugFileName = Opts.getSeparateDebugFileName();
   Config.Common.AddGnuDebugLink = sys::path::filename(SeparateDebugFileName);
   Config.Common.GnuDebugLinkCRC32 = GnuDebugLinkCRC32;
@@ -350,8 +350,8 @@ saveSeparateLinkedDebugInfo(const Options &Opts, ObjectFile &InputFile,
   std::string OutputFilename = Opts.getSeparateDebugFileName();
   Config.Common.InputFilename = Opts.InputFileName;
   Config.Common.OutputFilename = OutputFilename;
-  Config.Common.StripDebug = true;
-  Config.Common.OnlyKeepDebug = true;
+  Config.Common.setStripDebug(true);
+  Config.Common.setOnlyKeepDebug(true);
   uint32_t WrittenFileCRC32 = 0;
 
   if (Error Err =
@@ -381,7 +381,7 @@ static Error saveSingleLinkedDebugInfo(const Options &Opts,
 
   Config.Common.InputFilename = Opts.InputFileName;
   Config.Common.OutputFilename = Opts.OutputFileName;
-  Config.Common.StripDebug = true;
+  Config.Common.setStripDebug(true);
   if (Error Err =
           addSectionsFromLinkedData(Config, InputFile, LinkedDebugInfoBits))
     return Err;
diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
index da0367f3fdbd6..4d71174dcf7f7 100644
--- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -361,7 +361,7 @@ void Analysis::printSchedClassDescHtml(const ResolvedSchedClass &RSC,
     const auto &SI = State_.getSubtargetInfo();
     const auto &SM = SI.getSchedModel();
     OS << "<tr><td>✔</td>";
-    OS << "<td>" << (RSC.WasVariant ? "✔" : "✕") << "</td>";
+    OS << "<td>" << (RSC.getWasVariant() ? "✔" : "✕") << "</td>";
     OS << "<td>" << RSC.SCDesc->NumMicroOps << "</td>";
     // Latencies.
     OS << "<td><ul>";
diff --git a/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp b/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
index 2cfbc6b91b9be..e98db2e2f8924 100644
--- a/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
@@ -236,10 +236,12 @@ ResolvedSchedClass::ResolvedSchedClass(const MCSubtargetInfo &STI,
                                        bool WasVariant)
     : SchedClassId(ResolvedSchedClassId),
       SCDesc(STI.getSchedModel().getSchedClassDesc(ResolvedSchedClassId)),
-      WasVariant(WasVariant),
-      NonRedundantWriteProcRes(getNonRedundantWriteProcRes(*SCDesc, STI)),
+      NonRedundantWriteProcRes(unsigned(WasVariant),
+                               getNonRedundantWriteProcRes(*SCDesc, STI)),
       IdealizedProcResPressure(computeIdealizedProcResPressure(
-          STI.getSchedModel(), NonRedundantWriteProcRes)) {
+          STI.getSchedModel(), SmallVector<MCWriteProcResEntry, 8>(
+                                   NonRedundantWriteProcRes.begin(),
+                                   NonRedundantWriteProcRes.end()))) {
   assert((SCDesc == nullptr || !SCDesc->isVariant()) &&
          "ResolvedSchedClass should never be variant");
 }
diff --git a/llvm/tools/llvm-exegesis/lib/SchedClassResolution.h b/llvm/tools/llvm-exegesis/lib/SchedClassResolution.h
index 2347449b8f23d..1f02c377a2ac6 100644
--- a/llvm/tools/llvm-exegesis/lib/SchedClassResolution.h
+++ b/llvm/tools/llvm-exegesis/lib/SchedClassResolution.h
@@ -15,6 +15,7 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_SCHEDCLASSRESOLUTION_H
 
 #include "BenchmarkResult.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCInstPrinter.h"
@@ -50,8 +51,11 @@ struct ResolvedSchedClass {
 
   const unsigned SchedClassId;
   const MCSchedClassDesc *const SCDesc;
-  const bool WasVariant; // Whether the original class was variant.
-  const SmallVector<MCWriteProcResEntry, 8> NonRedundantWriteProcRes;
+  bool getWasVariant() const {
+    return NonRedundantWriteProcRes.getFlag(0);
+  } // Whether the original class was variant.
+  const llvm::SmallVectorWithFlags<MCWriteProcResEntry, 8>
+      NonRedundantWriteProcRes;
   const std::vector<std::pair<uint16_t, float>> IdealizedProcResPressure;
 };
 
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 4c0f9d1d09daf..ca91aa5f5a24d 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -1072,19 +1072,19 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
           "bad format for --extract-section, expected section=file");
     Config.ExtractSection.push_back(Value);
   }
-  Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
-  Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
-  Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
-  Config.StripDWO = InputArgs.hasArg(OBJCOPY_strip_dwo);
-  Config.StripSections = InputArgs.hasArg(OBJCOPY_strip_sections);
-  Config.StripNonAlloc = InputArgs.hasArg(OBJCOPY_strip_non_alloc);
-  Config.StripUnneeded = InputArgs.hasArg(OBJCOPY_strip_unneeded);
-  Config.ExtractDWO = InputArgs.hasArg(OBJCOPY_extract_dwo);
-  Config.ExtractMainPartition =
-      InputArgs.hasArg(OBJCOPY_extract_main_partition);
-  ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
-  Config.Verbose = InputArgs.hasArg(OBJCOPY_verbose);
-  Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
+  Config.setStripAll(InputArgs.hasArg(OBJCOPY_strip_all));
+  Config.setStripAllGNU(InputArgs.hasArg(OBJCOPY_strip_all_gnu));
+  Config.setStripDebug(InputArgs.hasArg(OBJCOPY_strip_debug));
+  Config.setStripDWO(InputArgs.hasArg(OBJCOPY_strip_dwo));
+  Config.setStripSections(InputArgs.hasArg(OBJCOPY_strip_sections));
+  Config.setStripNonAlloc(InputArgs.hasArg(OBJCOPY_strip_non_alloc));
+  Config.setStripUnneeded(InputArgs.hasArg(OBJCOPY_strip_unneeded));
+  Config.setExtractDWO(InputArgs.hasArg(OBJCOPY_extract_dwo));
+  Config.setExtractMainPartition(
+      InputArgs.hasArg(OBJCOPY_extract_main_partition));
+  ELFConfig.setLocalizeHidden(InputArgs.hasArg(OBJCOPY_localize_hidden));
+  Config.setVerbose(InputArgs.hasArg(OBJCOPY_verbose));
+  Config.setWeaken(InputArgs.hasArg(OBJCOPY_weaken));
   if (auto *Arg =
           InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
     Config.DiscardMode = Arg->getOption().matches(OBJCOPY_discard_all)
@@ -1092,17 +1092,17 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
                              : DiscardType::Locals;
   }
 
-  ELFConfig.VerifyNoteSections = InputArgs.hasFlag(
-      OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true);
+  ELFConfig.setVerifyNoteSections(InputArgs.hasFlag(
+      OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true));
 
-  Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
-  ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
+  Config.setOnlyKeepDebug(InputArgs.hasArg(OBJCOPY_only_keep_debug));
+  ELFConfig.setKeepFileSymbols(InputArgs.hasArg(OBJCOPY_keep_file_symbols));
   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
-  Config.DecompressDebugSections =
-      InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
+  Config.setDecompressDebugSections(
+      InputArgs.hasArg(OBJCOPY_decompress_debug_sections));
   if (Config.DiscardMode == DiscardType::All) {
-    Config.StripDebug = true;
-    ELFConfig.KeepFileSymbols = true;
+    Config.setStripDebug(true);
+    ELFConfig.setKeepFileSymbols(true);
   }
   for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
@@ -1212,15 +1212,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
       return std::move(E);
   }
 
-  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
+  ELFConfig.setAllowBrokenLinks(InputArgs.hasArg(OBJCOPY_allow_broken_links));
 
-  Config.DeterministicArchives = InputArgs.hasFlag(
+  Config.setDeterministicArchives(InputArgs.hasFlag(
       OBJCOPY_enable_deterministic_archives,
-      OBJCOPY_disable_deterministic_archives, /*default=*/true);
+      OBJCOPY_disable_deterministic_archives, /*default=*/true));
 
-  Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
+  Config.setPreserveDates(InputArgs.hasArg(OBJCOPY_preserve_dates));
 
-  if (Config.PreserveDates &&
+  if (Config.getPreserveDates() &&
       (Config.OutputFilename == "-" || Config.InputFilename == "-"))
     return createStringError(errc::invalid_argument,
                              "--preserve-dates requires a file");
@@ -1269,7 +1269,7 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
           "cannot specify both --remove-note and --update-section");
   }
 
-  if (Config.DecompressDebugSections &&
+  if (Config.getDecompressDebugSections() &&
       Config.CompressionType != DebugCompressionType::None) {
     return createStringError(
         errc::invalid_argument,
@@ -1277,7 +1277,7 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
         "--decompress-debug-sections");
   }
 
-  if (Config.ExtractPartition && Config.ExtractMainPartition)
+  if (Config.ExtractPartition && Config.getExtractMainPartition())
     return createStringError(errc::invalid_argument,
                              "cannot specify --extract-partition together with "
                              "--extract-main-partition");
@@ -1566,21 +1566,21 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
       = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
                                          : MatchStyle::Literal;
-  ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
-  Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug);
+  ELFConfig.setAllowBrokenLinks(InputArgs.hasArg(STRIP_allow_broken_links));
+  Config.setStripDebug(InputArgs.hasArg(STRIP_strip_debug));
 
   if (auto *Arg = InputArgs.getLastArg(STRIP_discard_all, STRIP_discard_locals))
     Config.DiscardMode = Arg->getOption().matches(STRIP_discard_all)
                              ? DiscardType::All
                              : DiscardType::Locals;
-  Config.StripSections = InputArgs.hasArg(STRIP_strip_sections);
-  Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded);
+  Config.setStripSections(InputArgs.hasArg(STRIP_strip_sections));
+  Config.setStripUnneeded(InputArgs.hasArg(STRIP_strip_unneeded));
   if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all))
-    Config.StripAll = Arg->getOption().getID() == STRIP_strip_all;
-  Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
+    Config.setStripAll(Arg->getOption().getID() == STRIP_strip_all);
+  Config.setStripAllGNU(InputArgs.hasArg(STRIP_strip_all_gnu));
   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
-  Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
-  ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
+  Config.setOnlyKeepDebug(InputArgs.hasArg(STRIP_only_keep_debug));
+  ELFConfig.setKeepFileSymbols(InputArgs.hasArg(STRIP_keep_file_symbols));
   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
 
   for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
@@ -1603,23 +1603,23 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
 
-  if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.StripDebug &&
-      !Config.OnlyKeepDebug && !Config.StripUnneeded &&
-      Config.DiscardMode == DiscardType::None && !Config.StripAllGNU &&
+  if (!InputArgs.hasArg(STRIP_no_strip_all) && !Config.getStripDebug() &&
+      !Config.getOnlyKeepDebug() && !Config.getStripUnneeded() &&
+      Config.DiscardMode == DiscardType::None && !Config.getStripAllGNU() &&
       Config.SymbolsToRemove.empty())
-    Config.StripAll = true;
+    Config.setStripAll(true);
 
   if (Config.DiscardMode == DiscardType::All) {
-    Config.StripDebug = true;
-    ELFConfig.KeepFileSymbols = true;
+    Config.setStripDebug(true);
+    ELFConfig.setKeepFileSymbols(true);
   }
 
-  Config.DeterministicArchives =
-      InputArgs.hasFlag(STRIP_enable_deterministic_archives,
-                        STRIP_disable_deterministic_archives, /*default=*/true);
+  Config.setDeterministicArchives(InputArgs.hasFlag(
+      STRIP_enable_deterministic_archives, STRIP_disable_deterministic_archives,
+      /*default=*/true));
 
-  Config.PreserveDates = InputArgs.hasArg(STRIP_preserve_dates);
-  Config.Verbose = InputArgs.hasArg(STRIP_verbose);
+  Config.setPreserveDates(InputArgs.hasArg(STRIP_preserve_dates));
+  Config.setVerbose(InputArgs.hasArg(STRIP_verbose));
   Config.InputFormat = FileFormat::Unspecified;
   Config.OutputFormat = FileFormat::Unspecified;
 
@@ -1648,8 +1648,9 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
     }
   }
 
-  if (Config.PreserveDates && (is_contained(Positional, "-") ||
-                               InputArgs.getLastArgValue(STRIP_output) == "-"))
+  if (Config.getPreserveDates() &&
+      (is_contained(Positional, "-") ||
+       InputArgs.getLastArgValue(STRIP_output) == "-"))
     return createStringError(errc::invalid_argument,
                              "--preserve-dates requires a file");
 
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 1b98b4bc1a772..51d347a214e5c 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -172,7 +172,7 @@ static Error executeObjcopy(ConfigManager &ConfigMgr) {
       return createFileError(Config.InputFilename, BufOrErr.getError());
     MemoryBufferHolder = std::move(*BufOrErr);
 
-    if (Config.Verbose)
+    if (Config.getVerbose())
       printCopyMessage(
           Config.InputFilename, toFileFormatName(Config.InputFormat),
           Config.OutputFilename, toFileFormatName(Config.OutputFormat));
@@ -199,7 +199,7 @@ static Error executeObjcopy(ConfigManager &ConfigMgr) {
       if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
         return E;
     } else {
-      if (Config.Verbose)
+      if (Config.getVerbose())
         printCopyMessage(Config.InputFilename,
                          getObjectFormatName(*BinaryHolder.getBinary()),
                          Config.OutputFilename,
@@ -219,14 +219,14 @@ static Error executeObjcopy(ConfigManager &ConfigMgr) {
       if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
         return E;
     } else {
-      Config.ExtractDWO = true;
-      Config.StripDWO = false;
+      Config.setExtractDWO(true);
+      Config.setStripDWO(false);
       // Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
       // file using specified ObjcopyFunc function.
       if (Error E = writeToOutput(Config.SplitDWO, ObjcopyFunc))
         return E;
-      Config.ExtractDWO = false;
-      Config.StripDWO = true;
+      Config.setExtractDWO(false);
+      Config.setStripDWO(true);
       // Apply transformations described by Config, remove .dwo tables and
       // store result into Config.OutputFilename using specified ObjcopyFunc
       // function.
@@ -235,13 +235,13 @@ static Error executeObjcopy(ConfigManager &ConfigMgr) {
     }
   }
 
-  if (Error E =
-          PermsApplierOrErr->apply(Config.OutputFilename, Config.PreserveDates))
+  if (Error E = PermsApplierOrErr->apply(Config.OutputFilename,
+                                         Config.getPreserveDates()))
     return E;
 
   if (!Config.SplitDWO.empty())
     if (Error E =
-            PermsApplierOrErr->apply(Config.SplitDWO, Config.PreserveDates,
+            PermsApplierOrErr->apply(Config.SplitDWO, Config.getPreserveDates(),
                                      static_cast<sys::fs::perms>(0666)))
       return E;
 
diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index a47391c81ef21..384c096e8f6ea 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -187,7 +187,9 @@ void VirtualUnwinder::unwindBranch(UnwindState &State) {
 std::shared_ptr<StringBasedCtxKey> FrameStack::getContextKey() {
   std::shared_ptr<StringBasedCtxKey> KeyStr =
       std::make_shared<StringBasedCtxKey>();
-  KeyStr->Context = Binary->getExpandedContext(Stack, KeyStr->WasLeafInlined);
+  bool WasLeafInlined = KeyStr->getWasLeafInlined();
+  KeyStr->Context.assign(Binary->getExpandedContext(Stack, WasLeafInlined));
+  KeyStr->setWasLeafInlined(WasLeafInlined);
   return KeyStr;
 }
 
@@ -1084,7 +1086,9 @@ void UnsymbolizedProfileReader::readUnsymbolizedProfile(StringRef FileName) {
     if (Line.starts_with("[")) {
       ProfileIsCS = true;
       auto I = ContextStrSet.insert(Line);
-      SampleContext::createCtxVectorFromStr(I.first->getKey(), Key->Context);
+      SampleContextFrameVector Context;
+      SampleContext::createCtxVectorFromStr(I.first->getKey(), Context);
+      Key->Context.assign(std::move(Context));
       TraceIt.advance();
     }
     auto Ret = SampleCounters.try_emplace(Hashable<ContextKey>(Key));
diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h
index 04f8388fc2f0d..66c4754eacf30 100644
--- a/llvm/tools/llvm-profgen/PerfReader.h
+++ b/llvm/tools/llvm-profgen/PerfReader.h
@@ -11,6 +11,7 @@
 #include "ErrorHandling.h"
 #include "ProfiledBinary.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
@@ -335,17 +336,20 @@ struct ContextKey {
 
 // String based context id
 struct StringBasedCtxKey : public ContextKey {
-  SampleContextFrameVector Context;
+  llvm::SmallVectorWithFlagsFor<SampleContextFrameVector, 1> Context;
 
-  bool WasLeafInlined;
-  StringBasedCtxKey() : ContextKey(CK_StringBased), WasLeafInlined(false){};
+  bool getWasLeafInlined() const { return Context.getFlag(0); }
+  void setWasLeafInlined(bool Value) { Context.setFlag(0, Value); }
+  StringBasedCtxKey() : ContextKey(CK_StringBased) {};
   static bool classof(const ContextKey *K) {
     return K->getKind() == CK_StringBased;
   }
 
   bool isEqual(const ContextKey *K) const override {
     const StringBasedCtxKey *Other = dyn_cast<StringBasedCtxKey>(K);
-    return Context == Other->Context;
+    return (
+        llvm::ArrayRef<llvm::sampleprof::SampleContextFrame>(Context) ==
+        llvm::ArrayRef<llvm::sampleprof::SampleContextFrame>(Other->Context));
   }
 
   void genHashCode() override {
@@ -357,8 +361,7 @@ struct StringBasedCtxKey : public ContextKey {
 struct AddrBasedCtxKey : public ContextKey {
   SmallVector<uint64_t, 16> Context;
 
-  bool WasLeafInlined;
-  AddrBasedCtxKey() : ContextKey(CK_AddrBased), WasLeafInlined(false){};
+  AddrBasedCtxKey() : ContextKey(CK_AddrBased) {}
   static bool classof(const ContextKey *K) {
     return K->getKind() == CK_AddrBased;
   }
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index efc2d91bbb064..0e563c335cb43 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -991,7 +991,7 @@ void CSProfileGenerator::generateLineNumBasedProfile() {
     if (!CtxKey->Context.empty()) {
       // Get or create function profile for the range
       ContextNode =
-          getOrCreateContextNode(CtxKey->Context, CtxKey->WasLeafInlined);
+          getOrCreateContextNode(CtxKey->Context, CtxKey->getWasLeafInlined());
       // Fill in function body samples
       populateBodySamplesForFunction(*ContextNode->getFunctionSamples(),
                                      CI.second.RangeCounter);
diff --git a/llvm/tools/llvm-reduce/TestRunner.cpp b/llvm/tools/llvm-reduce/TestRunner.cpp
index ad9f925ebccc7..26ee104391071 100644
--- a/llvm/tools/llvm-reduce/TestRunner.cpp
+++ b/llvm/tools/llvm-reduce/TestRunner.cpp
@@ -18,9 +18,11 @@ TestRunner::TestRunner(StringRef TestName, ArrayRef<std::string> RawTestArgs,
                        std::unique_ptr<TargetMachine> TM, StringRef ToolName,
                        StringRef OutputName, bool InputIsBitcode,
                        bool OutputBitcode)
-    : TestName(TestName), ToolName(ToolName), Program(std::move(Program)),
-      TM(std::move(TM)), OutputFilename(OutputName),
-      InputIsBitcode(InputIsBitcode), EmitBitcode(OutputBitcode) {
+    : TestName(TestName), ToolName(ToolName),
+      TestArgs(decltype(this->TestArgs)::withFlags(
+          unsigned(InputIsBitcode) | (unsigned(OutputBitcode) << 1))),
+      Program(std::move(Program)), TM(std::move(TM)),
+      OutputFilename(OutputName) {
   assert(this->Program && "Initialized with null program?");
 
   TestArgs.push_back(TestName); // argv[0]
@@ -34,7 +36,7 @@ static constexpr std::array<std::optional<StringRef>, 3> NullRedirects;
 /// Runs the interestingness test, passes file to be tested as first argument
 /// and other specified test arguments after that.
 int TestRunner::run(StringRef Filename) const {
-  SmallVector<StringRef> ExecArgs(TestArgs);
+  SmallVector<StringRef> ExecArgs(TestArgs.begin(), TestArgs.end());
   ExecArgs.push_back(Filename);
 
   std::string ErrMsg;
@@ -57,14 +59,14 @@ int TestRunner::run(StringRef Filename) const {
 void TestRunner::writeOutput(StringRef Message) {
   std::error_code EC;
   raw_fd_ostream Out(OutputFilename, EC,
-                     EmitBitcode && !Program->isMIR() ? sys::fs::OF_None
-                                                      : sys::fs::OF_Text);
+                     getEmitBitcode() && !Program->isMIR() ? sys::fs::OF_None
+                                                           : sys::fs::OF_Text);
   if (EC) {
     WithColor::error(errs(), ToolName)
         << "opening output file: " << EC.message() << '\n';
     exit(1);
   }
 
-  Program->writeOutput(Out, EmitBitcode);
+  Program->writeOutput(Out, getEmitBitcode());
   errs() << Message << OutputFilename << '\n';
 }
diff --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h
index 0218dad263b05..a2bd5afe527fc 100644
--- a/llvm/tools/llvm-reduce/TestRunner.h
+++ b/llvm/tools/llvm-reduce/TestRunner.h
@@ -10,6 +10,7 @@
 #define LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H
 
 #include "ReducerWorkItem.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
@@ -47,19 +48,27 @@ class TestRunner {
 
   void writeOutput(StringRef Message);
 
-  bool inputIsBitcode() const {
-    return InputIsBitcode;
-  }
+  bool inputIsBitcode() const { return getInputIsBitcode(); }
 
 private:
   StringRef TestName;
   StringRef ToolName;
-  SmallVector<StringRef> TestArgs;
+  llvm::SmallVectorWithFlags<
+      StringRef,
+      llvm::CalculateSmallVectorDefaultInlinedElements<StringRef>::value, 2>
+      TestArgs;
   std::unique_ptr<ReducerWorkItem> Program;
   std::unique_ptr<TargetMachine> TM;
   StringRef OutputFilename;
-  const bool InputIsBitcode;
-  bool EmitBitcode;
+  bool getInputIsBitcode() const { return TestArgs.getFlag(0); }
+  bool getEmitBitcode() const { return TestArgs.getFlag(1); }
+  void setEmitBitcode(bool Value) { TestArgs.setFlag(1, Value); }
+
+public:
+  TestRunner(const TestRunner &) = default;
+  TestRunner(TestRunner &&) = default;
+  TestRunner &operator=(const TestRunner &) = delete;
+  TestRunner &operator=(TestRunner &&) = delete;
 };
 
 } // namespace llvm
diff --git a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 455dfd9a89cef..b1ef1c70ee43d 100644
--- a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -197,7 +198,7 @@ class TrivialMemoryManager : public RTDyldMemoryManager {
   };
 
   SmallVector<SectionInfo, 16> FunctionMemory;
-  SmallVector<SectionInfo, 16> DataMemory;
+  llvm::SmallVectorWithFlags<SectionInfo, 16> DataMemory;
 
   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
                                unsigned SectionID,
@@ -258,7 +259,7 @@ class TrivialMemoryManager : public RTDyldMemoryManager {
                          EC.message());
 
     PreallocSlab = MB;
-    UsePreallocation = true;
+    setUsePreallocation(true);
     SlabSize = Size;
   }
 
@@ -281,7 +282,8 @@ class TrivialMemoryManager : public RTDyldMemoryManager {
 private:
   std::map<std::string, uint64_t> DummyExterns;
   sys::MemoryBlock PreallocSlab;
-  bool UsePreallocation = false;
+  bool getUsePreallocation() const { return DataMemory.getFlag(0); }
+  void setUsePreallocation(bool Value) { DataMemory.setFlag(0, Value); }
   uintptr_t SlabSize = 0;
   uintptr_t CurrentSlabOffset = 0;
   SectionIDMap *SecIDMap = nullptr;
@@ -301,7 +303,7 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
   if (SecIDMap)
     (*SecIDMap)[SectionName] = SectionID;
 
-  if (UsePreallocation)
+  if (getUsePreallocation())
     return allocateFromSlab(Size, Alignment, true /* isCode */,
                             SectionName, SectionID);
 
@@ -330,7 +332,7 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
   if (SecIDMap)
     (*SecIDMap)[SectionName] = SectionID;
 
-  if (UsePreallocation)
+  if (getUsePreallocation())
     return allocateFromSlab(Size, Alignment, false /* isCode */, SectionName,
                             SectionID);
 
diff --git a/llvm/unittests/ADT/SmallVectorWithFlagsTest.cpp b/llvm/unittests/ADT/SmallVectorWithFlagsTest.cpp
index ada094ef83da3..e0e19cda42f98 100644
--- a/llvm/unittests/ADT/SmallVectorWithFlagsTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorWithFlagsTest.cpp
@@ -72,6 +72,10 @@ TYPED_TEST(SmallVectorWithFlagsTypedTest,
     T *Data = V.data();
     size_t Capacity = V.capacity();
     for (unsigned Flags = 0; Flags < (1u << TypeParam::NumFlagBits); ++Flags) {
+      TypeParam Constructed = TypeParam::withFlags(Flags, Size, element<T>(3));
+      EXPECT_EQ(Flags, Constructed.getFlags());
+      EXPECT_EQ(Size, Constructed.size());
+      EXPECT_EQ(ArrayRef<T>(V), ArrayRef<T>(Constructed));
       V.setFlags(Flags);
       EXPECT_EQ(Flags, V.getFlags());
       for (unsigned Bit = 0; Bit < TypeParam::NumFlagBits; ++Bit)
@@ -116,10 +120,9 @@ TYPED_TEST(SmallVectorWithFlagsTypedTest, CapacityMatchesPlainSmallVector) {
 }
 
 TYPED_TEST(SmallVectorWithFlagsTypedTest, ElementOperationsPreserveFlags) {
-  TypeParam V;
   using T = typename TypeParam::value_type;
   unsigned Flags = (1u << TypeParam::NumFlagBits) - 1;
-  V.setFlags(Flags);
+  TypeParam V = TypeParam::withFlags(Flags);
   for (unsigned I = 0; I < 32; ++I) {
     V.push_back(element<T>(I));
     EXPECT_EQ(Flags, V.getFlags());
@@ -509,6 +512,74 @@ struct MoveConstructOnly {
   int Value;
 };
 
+TEST(SmallVectorWithFlagsTest, MoveFromPlainVectorWithExplicitFlags) {
+  for (unsigned Size : {0u, 1u, 16u}) {
+    SmallVector<MoveConstructOnly, 1> Source;
+    for (unsigned I = 0; I < Size; ++I)
+      Source.emplace_back(I);
+    MoveConstructOnly *Data = Source.data();
+    SmallVectorWithFlagsFor<decltype(Source), 2> Dest(3, std::move(Source));
+    EXPECT_EQ(Dest.getFlags(), 3u);
+    EXPECT_EQ(Dest.size(), Size);
+    EXPECT_TRUE(Source.empty());
+    if (Size > 1)
+      EXPECT_EQ(Dest.data(), Data);
+    for (unsigned I = 0; I < Size; ++I)
+      EXPECT_EQ(Dest[I].Value, static_cast<int>(I));
+  }
+}
+
+TEST(SmallVectorWithFlagsTest, AssignPlainVectorPreservesFlags) {
+  for (unsigned Size : {0u, 1u, 16u}) {
+    for (bool Reserve : {false, true}) {
+      SmallVector<int, 1> Source(Size, 7);
+      if (Reserve)
+        Source.reserve(32);
+      int *Data = Source.data();
+      bool HasHeapBuffer = Source.capacity() > 1;
+      SmallVectorWithFlags<int, 2, 2> Dest{1, 2, 3};
+      Dest.setFlags(3);
+      Dest.assign(std::move(Source));
+      EXPECT_EQ(Dest.getFlags(), 3u);
+      EXPECT_EQ(Dest.size(), Size);
+      EXPECT_TRUE(Source.empty());
+      if (HasHeapBuffer)
+        EXPECT_EQ(Dest.data(), Data);
+      for (int Value : Dest)
+        EXPECT_EQ(Value, 7);
+
+      // Output interfaces can temporarily own the elements in a plain vector.
+      // Retain both the flags and an empty reserved buffer across that loan.
+      SmallVector<int, 2> Payload;
+      Payload = std::move(Dest);
+      EXPECT_TRUE(Dest.empty());
+      EXPECT_EQ(Dest.getFlags(), 3u);
+      if (HasHeapBuffer)
+        EXPECT_EQ(Payload.data(), Data);
+      Dest.assign(std::move(Payload));
+      EXPECT_EQ(Dest.getFlags(), 3u);
+      EXPECT_EQ(Dest.size(), Size);
+      if (HasHeapBuffer)
+        EXPECT_EQ(Dest.data(), Data);
+    }
+  }
+
+  // Character vectors use a 64-bit capacity word on 64-bit hosts.
+  SmallVectorWithFlags<char, 0, 4> Buffer;
+  Buffer.setFlags(11);
+  Buffer.reserve(32);
+  char *Data = Buffer.data();
+  SmallVector<char, 0> Payload;
+  Payload = std::move(Buffer);
+  EXPECT_EQ(Payload.data(), Data);
+  EXPECT_EQ(Buffer.getFlags(), 11u);
+  Payload.append({'x', 'y', 'z'});
+  Buffer.assign(std::move(Payload));
+  EXPECT_EQ(Buffer.data(), Data);
+  EXPECT_EQ(Buffer.getFlags(), 11u);
+  EXPECT_THAT(Buffer, ElementsAre('x', 'y', 'z'));
+}
+
 TEST(SmallVectorWithFlagsTest, MoveConstructNonMoveAssignableElements) {
   for (unsigned Size : {0u, 1u, 16u}) {
     SmallVectorWithFlags<MoveConstructOnly, 1> Source;
@@ -590,6 +661,41 @@ TEST(SmallVectorWithFlagsTest, MoveIntoPlainSmallVector) {
   EXPECT_TRUE(MoveOnly.empty());
 }
 
+TEST(SmallVectorWithFlagsTest, OrdinaryVectorConstruction) {
+  const SmallVector<int, 2> Plain = {1, 2, 3, 4};
+  SmallVectorWithFlags<int, 2, 3> Copy(Plain);
+  EXPECT_EQ(ArrayRef<int>(Copy), ArrayRef<int>(Plain));
+  EXPECT_EQ(Copy.getFlags(), 0u);
+  auto FlaggedCopy = decltype(Copy)::withFlags(5, Plain);
+  EXPECT_EQ(ArrayRef<int>(FlaggedCopy), ArrayRef<int>(Plain));
+  EXPECT_EQ(FlaggedCopy.getFlags(), 5u);
+
+  SmallVector<std::unique_ptr<int>, 1> Owned;
+  Owned.push_back(std::make_unique<int>(7));
+  Owned.push_back(std::make_unique<int>(9));
+  auto *Buffer = Owned.data();
+  SmallVectorWithFlags<std::unique_ptr<int>, 1, 3> Moved(std::move(Owned));
+  EXPECT_EQ(Moved.data(), Buffer);
+  EXPECT_EQ(*Moved[0], 7);
+  EXPECT_EQ(*Moved[1], 9);
+  EXPECT_EQ(Moved.getFlags(), 0u);
+  EXPECT_TRUE(Owned.empty());
+}
+
+TEST(SmallVectorWithFlagsTest, InitializerListAssignmentPreservesFlags) {
+  SmallVectorWithFlags<int, 2, 3> V;
+  V.setFlags(5);
+  V = {1, 2, 3, 4};
+  EXPECT_EQ(ArrayRef<int>(V), (ArrayRef<int>{1, 2, 3, 4}));
+  EXPECT_EQ(V.getFlags(), 5u);
+  V = {9};
+  EXPECT_EQ(ArrayRef<int>(V), (ArrayRef<int>{9}));
+  EXPECT_EQ(V.getFlags(), 5u);
+  V = {};
+  EXPECT_TRUE(V.empty());
+  EXPECT_EQ(V.getFlags(), 5u);
+}
+
 TEST(SmallVectorWithFlagsTest, OwningElements) {
   SmallVectorWithFlags<std::unique_ptr<int>, 1> V;
   V.setFlag(0, true);
diff --git a/llvm/unittests/Bitstream/BitstreamWriterTest.cpp b/llvm/unittests/Bitstream/BitstreamWriterTest.cpp
index 933965abdbadf..e68fa3c3e5604 100644
--- a/llvm/unittests/Bitstream/BitstreamWriterTest.cpp
+++ b/llvm/unittests/Bitstream/BitstreamWriterTest.cpp
@@ -9,6 +9,7 @@
 #include "llvm/Bitstream/BitstreamWriter.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Bitstream/BitCodeEnums.h"
 #include "llvm/Bitstream/BitstreamReader.h"
 #include "llvm/Support/Error.h"
@@ -21,6 +22,23 @@ using namespace llvm;
 
 namespace {
 
+TEST(BitstreamWriterTest, OwnedBufferTransfer) {
+  SmallVectorWithFlags<char, 0> Bytes;
+  Bytes.setFlag(0, true);
+  {
+    BitstreamWriter Writer;
+    Writer.Emit(0x1234, 16);
+    Writer.FlushToWord();
+    auto *Buffer = Writer.getBuffer().data();
+    Bytes.assign(std::move(Writer.getBuffer()));
+    EXPECT_EQ(Bytes.data(), Buffer);
+    EXPECT_TRUE(Writer.getBuffer().empty());
+  }
+  EXPECT_TRUE(Bytes.getFlag(0));
+  EXPECT_EQ(StringRef(Bytes.data(), Bytes.size()),
+            StringRef("\x34\x12\0\0", 4));
+}
+
 TEST(BitstreamWriterTest, emitBlob) {
   SmallString<64> Buffer;
   BitstreamWriter W(Buffer);
diff --git a/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp b/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
index 2f5ae1ac52c1c..bd2a7f31e168d 100644
--- a/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGNodeConstructionTest.cpp
@@ -9,7 +9,9 @@
 #include "SelectionDAGTestBase.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
 
 using namespace llvm;
 
@@ -538,3 +540,43 @@ TEST_F(SelectionDAGNodeConstructionTest, VectorRepeat) {
   EXPECT_EQ(NXV1.getOperand(0).getOperand(0), V1);
   EXPECT_TRUE(isNullConstant(NXV1.getOperand(0).getOperand(1)));
 }
+
+TEST_F(SelectionDAGNodeConstructionTest, TokenFactorPreservesVectorFlags) {
+  SmallVectorWithFlags<SDValue, 8, 3> Chains;
+  Chains.setFlags(5);
+  Chains.assign(SDNode::getMaxNumOperands() + 1, DAG->getEntryNode());
+  SDValue Root = DAG->getTokenFactor(SDLoc(), Chains);
+  EXPECT_EQ(Root.getValueType(), MVT::Other);
+  EXPECT_EQ(Chains.size(), 2u);
+  EXPECT_EQ(Chains.getFlags(), 5u);
+}
+
+TEST_F(SelectionDAGNodeConstructionTest,
+       CallFlagsSurviveArgumentGrowthAndCopy) {
+  TargetLowering::CallLoweringInfo CLI(*DAG);
+  EXPECT_TRUE(CLI.getIsReturnValueUsed());
+  EXPECT_FALSE(CLI.getIsTailCall());
+  CLI.setSExtResult().setConvergent().setTailCall();
+  CLI.setNoMerge(true);
+  CLI.Outs.assign(65, ISD::OutputArg({}, MVT::i32, MVT::i32, nullptr, 0, 0));
+  CLI.Ins.assign(65,
+                 ISD::InputArg({}, MVT::i32, MVT::i32, nullptr, true, 0, 0));
+  CLI.InVals.assign(17, DAG->getEntryNode());
+
+  auto Copy = CLI;
+  CLI.Outs.clear();
+  CLI.Ins.clear();
+  CLI.InVals.clear();
+  for (const auto *Info : {&CLI, &Copy}) {
+    EXPECT_TRUE(Info->getRetSExt());
+    EXPECT_TRUE(Info->getIsReturnValueUsed());
+    EXPECT_TRUE(Info->getIsConvergent());
+    EXPECT_TRUE(Info->getNoMerge());
+    EXPECT_TRUE(Info->getIsTailCall());
+    EXPECT_FALSE(Info->getRetZExt());
+  }
+  EXPECT_EQ(Copy.Outs.size(), 65u);
+  EXPECT_EQ(Copy.Ins.size(), 65u);
+  EXPECT_EQ(Copy.InVals.size(), 17u);
+  EXPECT_EQ(Copy.InVals.front(), DAG->getEntryNode());
+}
diff --git a/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
index 896315638634f..c0000b0182f21 100644
--- a/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
+++ b/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
@@ -8,6 +8,7 @@
 
 #include "MCJITTestBase.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ExecutionEngine/MCJIT.h"
@@ -22,13 +23,13 @@ namespace {
 
 class TestObjectCache : public ObjectCache {
 public:
-  TestObjectCache() : DuplicateInserted(false) { }
+  TestObjectCache() {}
 
   void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
     // If we've seen this module before, note that.
     const std::string ModuleID = M->getModuleIdentifier();
     if (ObjMap.contains(ModuleID))
-      DuplicateInserted = true;
+      setDuplicateInserted(true);
     // Store a copy of the buffer in our map.
     ObjMap[ModuleID] = copyBuffer(Obj);
   }
@@ -44,7 +45,7 @@ class TestObjectCache : public ObjectCache {
   }
 
   // Test-harness-specific functions
-  bool wereDuplicatesInserted() { return DuplicateInserted; }
+  bool wereDuplicatesInserted() { return getDuplicateInserted(); }
 
   bool wasModuleLookedUp(const Module *M) {
     return ModulesLookedUp.contains(M->getModuleIdentifier());
@@ -71,8 +72,9 @@ class TestObjectCache : public ObjectCache {
 
   StringMap<const MemoryBuffer *> ObjMap;
   StringSet<>                     ModulesLookedUp;
-  SmallVector<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;
-  bool                            DuplicateInserted;
+  llvm::SmallVectorWithFlags<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;
+  bool getDuplicateInserted() const { return AllocatedBuffers.getFlag(0); }
+  void setDuplicateInserted(bool Value) { AllocatedBuffers.setFlag(0, Value); }
 };
 
 class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase {
diff --git a/llvm/unittests/Frontend/HLSLSemanticSignaturePackingTest.cpp b/llvm/unittests/Frontend/HLSLSemanticSignaturePackingTest.cpp
index 6013c9d25500f..554c1e88f2012 100644
--- a/llvm/unittests/Frontend/HLSLSemanticSignaturePackingTest.cpp
+++ b/llvm/unittests/Frontend/HLSLSemanticSignaturePackingTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Frontend/HLSL/SemanticSignaturePacking.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Testing/Support/Error.h"
@@ -42,19 +43,20 @@ class HLSLSemanticSignaturePackingTest : public testing::Test {
   struct TestConfig {
     Triple::EnvironmentType ShaderStage;
     IOType IOTy;
-    bool UseNative16BitTypes;
-    SmallVector<ElementConfig> Elements;
+    bool getUseNative16BitTypes() const { return Elements.getFlag(0); }
+    void setUseNative16BitTypes(bool Value) { Elements.setFlag(0, Value); }
+    llvm::SmallVectorWithFlags<ElementConfig> Elements;
 
     TestConfig(Triple::EnvironmentType ShaderStage, IOType IOTy,
                std::initializer_list<ElementConfig> Elements)
-        : ShaderStage(ShaderStage), IOTy(IOTy), UseNative16BitTypes(false),
-          Elements(Elements) {}
+        : ShaderStage(ShaderStage), IOTy(IOTy), Elements(Elements) {}
 
     TestConfig(Triple::EnvironmentType ShaderStage, IOType IOTy,
                bool UseNative16BitTypes,
                std::initializer_list<ElementConfig> Elements)
         : ShaderStage(ShaderStage), IOTy(IOTy),
-          UseNative16BitTypes(UseNative16BitTypes), Elements(Elements) {}
+          Elements(decltype(this->Elements)::withFlags(
+              unsigned(UseNative16BitTypes), Elements)) {}
   };
 
   enum class PackingMethod {
@@ -95,10 +97,11 @@ class HLSLSemanticSignaturePackingTest : public testing::Test {
       return packSignatureIndexed(Elements, Config.ShaderStage, Config.IOTy);
     case PackingMethod::PrefixStable:
       return packSignaturePrefixStable(Elements, Config.ShaderStage,
-                                       Config.IOTy, Config.UseNative16BitTypes);
+                                       Config.IOTy,
+                                       Config.getUseNative16BitTypes());
     case PackingMethod::Optimized:
       return packSignatureOptimized(Elements, Config.ShaderStage, Config.IOTy,
-                                    Config.UseNative16BitTypes);
+                                    Config.getUseNative16BitTypes());
     }
     llvm_unreachable("invalid packing method");
   }
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index e3e22ce05e6a4..2fb8362dfc4e7 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -8721,7 +8721,7 @@ TEST_F(OpenMPIRBuilderTest, EmitOffloadingArraysNonContigCountExpression) {
   CombinedInfo.Names.push_back(
       Builder.CreateGlobalString("data", "data_name", 0, M.get()));
 
-  CombinedInfo.NonContigInfo.IsNonContiguous = true;
+  CombinedInfo.NonContigInfo.setIsNonContiguous(true);
   CombinedInfo.NonContigInfo.Dims.push_back(1);
   CombinedInfo.NonContigInfo.Offsets.push_back({Builder.getInt64(0)});
   CombinedInfo.NonContigInfo.Counts.push_back({CountExpr});
diff --git a/llvm/unittests/IR/LegacyPassManagerTest.cpp b/llvm/unittests/IR/LegacyPassManagerTest.cpp
index 3a3982763bb06..fbb64e8fd7e06 100644
--- a/llvm/unittests/IR/LegacyPassManagerTest.cpp
+++ b/llvm/unittests/IR/LegacyPassManagerTest.cpp
@@ -38,6 +38,29 @@
 
 using namespace llvm;
 
+TEST(AnalysisUsageTest, PreservesAllAcrossUsedSetUpdatesAndCopies) {
+  char IDs[8] = {};
+  AnalysisUsage Usage;
+  EXPECT_FALSE(Usage.getPreservesAll());
+  Usage.setPreservesAll();
+  for (char &ID : IDs)
+    Usage.addUsedIfAvailableID(ID);
+  Usage.addUsedIfAvailableID(IDs[0]);
+  EXPECT_TRUE(Usage.getPreservesAll());
+  EXPECT_EQ(Usage.getUsedSet().size(), std::size(IDs));
+
+  AnalysisUsage Copy = Usage;
+  EXPECT_TRUE(Copy.getPreservesAll());
+  EXPECT_EQ(Copy.getUsedSet(), Usage.getUsedSet());
+  AnalysisUsage Moved = std::move(Copy);
+  EXPECT_TRUE(Moved.getPreservesAll());
+  EXPECT_EQ(Moved.getUsedSet(), Usage.getUsedSet());
+
+  Moved = AnalysisUsage();
+  EXPECT_FALSE(Moved.getPreservesAll());
+  EXPECT_TRUE(Moved.getUsedSet().empty());
+}
+
 namespace llvm {
 void initializeModuleNDMPass(PassRegistry &);
 void initializeFPassPass(PassRegistry &);
diff --git a/llvm/unittests/MC/LoongArch/LoongArchMCDisassemblerTest.cpp b/llvm/unittests/MC/LoongArch/LoongArchMCDisassemblerTest.cpp
index de99f26945542..38ead8f982b98 100644
--- a/llvm/unittests/MC/LoongArch/LoongArchMCDisassemblerTest.cpp
+++ b/llvm/unittests/MC/LoongArch/LoongArchMCDisassemblerTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -79,12 +80,13 @@ class LoongArchMCSymbolizerTest : public MCSymbolizer {
   explicit LoongArchMCSymbolizerTest(MCContext &Ctx)
       : MCSymbolizer(Ctx, nullptr) {}
 
-  SmallVector<Call, 1> Calls;
-  bool AddSymbolicOperand = false;
+  llvm::SmallVectorWithFlags<Call, 1> Calls;
+  bool getAddSymbolicOperand() const { return Calls.getFlag(0); }
+  void setAddSymbolicOperand(bool Value) { Calls.setFlag(0, Value); }
 
   void reset(bool AddSymbol = false) {
     Calls.clear();
-    AddSymbolicOperand = AddSymbol;
+    setAddSymbolicOperand(AddSymbol);
   }
 
   bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &CommentStream,
@@ -93,7 +95,7 @@ class LoongArchMCSymbolizerTest : public MCSymbolizer {
                                 uint64_t InstSize) override {
     Calls.push_back(
         {&CommentStream, Value, Address, IsBranch, Offset, OpSize, InstSize});
-    if (!AddSymbolicOperand)
+    if (!getAddSymbolicOperand())
       return false;
 
     Inst.addOperand(MCOperand::createExpr(
diff --git a/llvm/unittests/ProfileData/DataAccessProfTest.cpp b/llvm/unittests/ProfileData/DataAccessProfTest.cpp
index 2f93e16f28c1c..a1555fdb70c01 100644
--- a/llvm/unittests/ProfileData/DataAccessProfTest.cpp
+++ b/llvm/unittests/ProfileData/DataAccessProfTest.cpp
@@ -23,6 +23,7 @@ using ::testing::ElementsAre;
 using ::testing::Field;
 using ::testing::HasSubstr;
 using ::testing::IsEmpty;
+using ::testing::Property;
 
 static std::string ErrorToString(Error E) {
   std::string ErrMsg;
@@ -155,18 +156,18 @@ TEST(MemProf, DataAccessProfile) {
         ElementsAre(
             AllOf(Field(&DataAccessProfRecordRef::SymbolID, 0),
                   Field(&DataAccessProfRecordRef::AccessCount, 100),
-                  Field(&DataAccessProfRecordRef::IsStringLiteral, false),
+                  Property(&DataAccessProfRecordRef::isStringLiteral, false),
                   Field(&DataAccessProfRecordRef::Locations, IsEmpty())),
             AllOf(Field(&DataAccessProfRecordRef::SymbolID, 2),
                   Field(&DataAccessProfRecordRef::AccessCount, 123),
-                  Field(&DataAccessProfRecordRef::IsStringLiteral, false),
+                  Property(&DataAccessProfRecordRef::isStringLiteral, false),
                   Field(&DataAccessProfRecordRef::Locations,
                         ElementsAre(
                             AllOf(Field(&SourceLocationRef::FileName, "file2"),
                                   Field(&SourceLocationRef::Line, 3))))),
             AllOf(Field(&DataAccessProfRecordRef::SymbolID, 135246),
                   Field(&DataAccessProfRecordRef::AccessCount, 1000),
-                  Field(&DataAccessProfRecordRef::IsStringLiteral, true),
+                  Property(&DataAccessProfRecordRef::isStringLiteral, true),
                   Field(&DataAccessProfRecordRef::Locations,
                         ElementsAre(
                             AllOf(Field(&SourceLocationRef::FileName, "file1"),
diff --git a/llvm/unittests/Support/OptimizedStructLayoutTest.cpp b/llvm/unittests/Support/OptimizedStructLayoutTest.cpp
index 0bcae0dcd5603..92482489f3282 100644
--- a/llvm/unittests/Support/OptimizedStructLayoutTest.cpp
+++ b/llvm/unittests/Support/OptimizedStructLayoutTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Support/OptimizedStructLayout.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -21,14 +22,15 @@ class LayoutTest {
     uint64_t ExpectedOffset;
   };
 
-  SmallVector<Field, 16> Fields;
-  bool Verified = false;
+  llvm::SmallVectorWithFlags<Field, 16> Fields;
+  bool getVerified() const { return Fields.getFlag(0); }
+  void setVerified(bool Value) { Fields.setFlag(0, Value); }
 
 public:
   LayoutTest() = default;
   LayoutTest(const LayoutTest &) = delete;
   LayoutTest &operator=(const LayoutTest &) = delete;
-  ~LayoutTest() { assert(Verified); }
+  ~LayoutTest() { assert(getVerified()); }
 
   LayoutTest &flexible(uint64_t Size, uint64_t Alignment,
                        uint64_t ExpectedOffset) {
@@ -58,7 +60,7 @@ class LayoutTest {
       EXPECT_EQ(LF.Offset, F.ExpectedOffset);
     }
 
-    Verified = true;
+    setVerified(true);
   }
 };
 
diff --git a/llvm/unittests/Support/YAMLIOTest.cpp b/llvm/unittests/Support/YAMLIOTest.cpp
index 78e19c5ff4f2c..ea92431f27199 100644
--- a/llvm/unittests/Support/YAMLIOTest.cpp
+++ b/llvm/unittests/Support/YAMLIOTest.cpp
@@ -3659,3 +3659,36 @@ TYPED_TEST(YAMLIO, FixedSizeArrayMismatch) {
     EXPECT_TRUE(!!yin.error());
   }
 }
+
+TEST(YAMLIO, SmallVectorWithFlagsSequence) {
+  llvm::SmallVectorWithFlags<int, 2, 3> Values;
+  Values.setFlags(5);
+  llvm::SmallVectorWithFlagsImpl<int, 3> &Base = Values;
+  Input In("[1, 2, 3, 4, 5]");
+  In >> Base;
+  EXPECT_FALSE(In.error());
+  EXPECT_THAT(Values, ::testing::ElementsAre(1, 2, 3, 4, 5));
+  EXPECT_EQ(Values.getFlags(), 5u);
+
+  auto Serialize = [](auto &Sequence) {
+    std::string Text;
+    {
+      llvm::raw_string_ostream Stream(Text);
+      Output Out(Stream);
+      Out << Sequence;
+    }
+    return Text;
+  };
+  llvm::SmallVector<int, 2> Plain(Values.begin(), Values.end());
+  EXPECT_EQ(Serialize(Values), Serialize(Plain));
+  EXPECT_EQ(Serialize(Base), Serialize(Plain));
+  EXPECT_EQ(Values.getFlags(), 5u);
+
+  Values.clear();
+  EXPECT_EQ(Values.getFlags(), 5u);
+  Input Replacement("[9]");
+  Replacement >> Values;
+  EXPECT_FALSE(Replacement.error());
+  EXPECT_THAT(Values, ::testing::ElementsAre(9));
+  EXPECT_EQ(Values.getFlags(), 5u);
+}
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index b756582603ffd..de48d51ccb3a4 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -106,6 +106,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -552,7 +553,8 @@ struct MatchableInfo {
   SmallVector<AsmOperand, 8> AsmOperands;
 
   /// Predicates - The required subtarget features to match this instruction.
-  SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
+  llvm::SmallVectorWithFlags<const SubtargetFeatureInfo *, 4, 2>
+      RequiredFeatures;
 
   /// ConversionFnKind - The enum value which is passed to the generated
   /// convertToMCInst to convert parsed operands into an MCInst for this
@@ -560,23 +562,34 @@ struct MatchableInfo {
   std::string ConversionFnKind;
 
   /// If this instruction is deprecated in some form.
-  bool HasDeprecation = false;
+  bool getHasDeprecation() const { return RequiredFeatures.getFlag(0); }
+  bool setHasDeprecation(bool Value) {
+    RequiredFeatures.setFlag(0, Value);
+    return Value;
+  }
 
   /// If this is an alias, this is use to determine whether or not to using
   /// the conversion function defined by the instruction's AsmMatchConverter
   /// or to use the function generated by the alias.
-  bool UseInstAsmMatchConverter;
+  bool getUseInstAsmMatchConverter() const {
+    return RequiredFeatures.getFlag(1);
+  }
+  void setUseInstAsmMatchConverter(bool Value) {
+    RequiredFeatures.setFlag(1, Value);
+  }
 
   MatchableInfo(const CodeGenInstruction &CGI)
       : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef),
         ResInstSize(TheDef->getValueAsInt("Size")), DefRec(&CGI),
-        UseInstAsmMatchConverter(true) {}
+        RequiredFeatures(decltype(this->RequiredFeatures)::withFlags(2)) {}
 
   MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
       : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
         ResInstSize(Alias->ResultInst->TheDef->getValueAsInt("Size")),
-        DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit(
-                                     "UseInstAsmMatchConverter")) {}
+        DefRec(Alias.release()),
+        RequiredFeatures(decltype(this->RequiredFeatures)::withFlags(
+            (unsigned(bool(TheDef->getValueAsBit("UseInstAsmMatchConverter")))
+             << 1))) {}
 
   // Could remove this and the dtor if PointerUnion supported unique_ptr
   // elements with a dynamic failure/assertion (like the one below) in the case
@@ -585,10 +598,12 @@ struct MatchableInfo {
       : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
         TheDef(RHS.TheDef), ResInstSize(RHS.ResInstSize), DefRec(RHS.DefRec),
         ResOperands(RHS.ResOperands), Mnemonic(RHS.Mnemonic),
-        AsmOperands(RHS.AsmOperands), RequiredFeatures(RHS.RequiredFeatures),
-        ConversionFnKind(RHS.ConversionFnKind),
-        HasDeprecation(RHS.HasDeprecation),
-        UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
+        AsmOperands(RHS.AsmOperands),
+        RequiredFeatures(decltype(this->RequiredFeatures)::withFlags(
+            unsigned(bool(RHS.getHasDeprecation())) |
+                (unsigned(bool(RHS.getUseInstAsmMatchConverter())) << 1),
+            RHS.RequiredFeatures)),
+        ConversionFnKind(RHS.ConversionFnKind) {
     assert(!isa<const CodeGenInstAlias *>(DefRec));
   }
 
@@ -985,8 +1000,8 @@ void MatchableInfo::initialize(
   if (!DepMask)
     DepMask = TheDef->getValue("ComplexDeprecationPredicate");
 
-  HasDeprecation =
-      DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
+  setHasDeprecation(
+      DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false);
 }
 
 /// Append an AsmOperand for the given substring of AsmString.
@@ -2140,7 +2155,7 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
     // Check if we have a custom match function.
     StringRef AsmMatchConverter =
         II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
-    if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {
+    if (!AsmMatchConverter.empty() && II->getUseInstAsmMatchConverter()) {
       std::string Signature = ("ConvertCustom_" + AsmMatchConverter).str();
       II->ConversionFnKind = Signature;
 
@@ -3767,7 +3782,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
   bool HasDeprecation = false;
   for (const auto &MI : Info.Matchables) {
     MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
-    HasDeprecation |= MI->HasDeprecation;
+    HasDeprecation |= MI->getHasDeprecation();
 
     // Store a pascal-style length byte in the mnemonic.
     std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.lower();
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index b497c4dcd7806..6e96d17c74402 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -512,7 +512,7 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
   else if (R->getName() == "IntrNoMerge")
     isNoMerge = true;
   else if (R->getName() == "IntrConvergent")
-    isConvergent = true;
+    setIsConvergent(true);
   else if (R->getName() == "IntrNoReturn")
     isNoReturn = true;
   else if (R->getName() == "IntrNoCallback")
@@ -520,21 +520,21 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
   else if (R->getName() == "IntrNoSync")
     isNoSync = true;
   else if (R->getName() == "IntrNoFree")
-    isNoFree = true;
+    setIsNoFree(true);
   else if (R->getName() == "IntrWillReturn")
-    isWillReturn = !isNoReturn;
+    setIsWillReturn(!isNoReturn);
   else if (R->getName() == "IntrCold")
-    isCold = true;
+    setIsCold(true);
   else if (R->getName() == "IntrSpeculatable")
-    isSpeculatable = true;
+    setIsSpeculatable(true);
   else if (R->getName() == "IntrHasSideEffects")
-    hasSideEffects = true;
+    setHasSideEffects(true);
   else if (R->getName() == "IntrStrictFP")
-    isStrictFP = true;
+    setIsStrictFP(true);
   else if (R->getName() == "IntrNoCreateUndefOrPoison")
-    isNoCreateUndefOrPoison = true;
+    setIsNoCreateUndefOrPoison(true);
   else if (R->getName() == "IntrTriviallyScalarizable")
-    isTriviallyScalarizable = true;
+    setIsTriviallyScalarizable(true);
   else if (R->isSubClassOf("NoCapture")) {
     unsigned ArgNo = R->getValueAsInt("ArgNo");
     addArgAttribute(ArgNo, NoCapture);
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
index bd8a35dfc4de8..d265745fb7af8 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/ModRef.h"
 #include <string>
 #include <tuple>
@@ -94,32 +95,70 @@ struct CodeGenIntrinsic {
   bool isNoSync = false;
 
   /// True if the intrinsic is no-free.
-  bool isNoFree = false;
+  bool getIsNoFree() const { return ParamDefaultValues.getFlag(0); }
+  bool setIsNoFree(bool Value) {
+    ParamDefaultValues.setFlag(0, Value);
+    return Value;
+  }
 
   /// True if the intrinsic is will-return.
-  bool isWillReturn = false;
+  bool getIsWillReturn() const { return ParamDefaultValues.getFlag(1); }
+  bool setIsWillReturn(bool Value) {
+    ParamDefaultValues.setFlag(1, Value);
+    return Value;
+  }
 
   /// True if the intrinsic is cold.
-  bool isCold = false;
+  bool getIsCold() const { return ParamDefaultValues.getFlag(2); }
+  bool setIsCold(bool Value) {
+    ParamDefaultValues.setFlag(2, Value);
+    return Value;
+  }
 
   /// True if the intrinsic is marked as convergent.
-  bool isConvergent = false;
+  bool getIsConvergent() const { return ParamDefaultValues.getFlag(3); }
+  bool setIsConvergent(bool Value) {
+    ParamDefaultValues.setFlag(3, Value);
+    return Value;
+  }
 
   /// True if the intrinsic has side effects that aren't captured by any
   /// of the other flags.
-  bool hasSideEffects = false;
+  bool getHasSideEffects() const { return PrettyPrintFunctions.getFlag(0); }
+  bool setHasSideEffects(bool Value) {
+    PrettyPrintFunctions.setFlag(0, Value);
+    return Value;
+  }
 
   // True if the intrinsic is marked as speculatable.
-  bool isSpeculatable = false;
+  bool getIsSpeculatable() const { return PrettyPrintFunctions.getFlag(1); }
+  bool setIsSpeculatable(bool Value) {
+    PrettyPrintFunctions.setFlag(1, Value);
+    return Value;
+  }
 
   // True if the intrinsic is marked as strictfp.
-  bool isStrictFP = false;
+  bool getIsStrictFP() const { return PrettyPrintFunctions.getFlag(2); }
+  bool setIsStrictFP(bool Value) {
+    PrettyPrintFunctions.setFlag(2, Value);
+    return Value;
+  }
 
   // True if the intrinsic is marked as IntrNoCreateUndefOrPoison.
-  bool isNoCreateUndefOrPoison = false;
+  bool getIsNoCreateUndefOrPoison() const {
+    return PrettyPrintFunctions.getFlag(3);
+  }
+  bool setIsNoCreateUndefOrPoison(bool Value) {
+    PrettyPrintFunctions.setFlag(3, Value);
+    return Value;
+  }
 
   // True if the intrinsic is marked as IntrTriviallyScalarizable.
-  bool isTriviallyScalarizable = false;
+  bool getIsTriviallyScalarizable() const { return ImmArgRangeSets.getFlag(0); }
+  bool setIsTriviallyScalarizable(bool Value) {
+    ImmArgRangeSets.setFlag(0, Value);
+    return Value;
+  }
 
   enum ArgAttrKind {
     NoCapture,
@@ -163,7 +202,7 @@ struct CodeGenIntrinsic {
   SmallVector<SmallVector<ArgAttribute, 0>> ArgumentAttributes;
 
   /// Range-set constraints for immediate arguments, indexed by argument number.
-  SmallVector<ImmArgRangeSet> ImmArgRangeSets;
+  llvm::SmallVectorWithFlags<ImmArgRangeSet> ImmArgRangeSets;
 
   void addArgAttribute(unsigned Idx, ArgAttrKind AK, uint64_t V = 0,
                        uint64_t V2 = 0);
@@ -180,10 +219,18 @@ struct CodeGenIntrinsic {
   };
 
   /// Vector that stores ArgInfo (ArgIndex, ArgName, FunctionName).
-  SmallVector<PrettyPrintArgInfo> PrettyPrintFunctions;
+  llvm::SmallVectorWithFlags<PrettyPrintArgInfo,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 PrettyPrintArgInfo>::value,
+                             4>
+      PrettyPrintFunctions;
 
   /// Default values for parameters. Index = param index.
-  SmallVector<std::optional<uint64_t>> ParamDefaultValues;
+  llvm::SmallVectorWithFlags<std::optional<uint64_t>,
+                             llvm::CalculateSmallVectorDefaultInlinedElements<
+                                 std::optional<uint64_t>>::value,
+                             4>
+      ParamDefaultValues;
 
   void addPrettyPrintFunction(unsigned ArgIdx, StringRef ArgName,
                               StringRef FuncName);
diff --git a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
index 61a4aa31aa222..5a9c3885c31ff 100644
--- a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
@@ -367,10 +367,11 @@ void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
 
 void IntrinsicEmitter::EmitIntrinsicToScalarizableTable(
     const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
-  EmitIntrinsicBitTable(
-      Ints, OS, "GET_INTRINSIC_SCALARIZABLE_TABLE", "STable",
-      "Intrinsic ID to trivially scalarizable bitset.",
-      [](const CodeGenIntrinsic &Int) { return Int.isTriviallyScalarizable; });
+  EmitIntrinsicBitTable(Ints, OS, "GET_INTRINSIC_SCALARIZABLE_TABLE", "STable",
+                        "Intrinsic ID to trivially scalarizable bitset.",
+                        [](const CodeGenIntrinsic &Int) {
+                          return Int.getIsTriviallyScalarizable();
+                        });
 }
 
 using TypeSigTy = SmallVector<unsigned char>;
@@ -497,7 +498,7 @@ static constexpr FixedEncodingTy IIT_Table[] = {{
 static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) {
   MemoryEffects ME = Int.ME;
   // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
-  if (ME.doesNotAccessMemory() && Int.hasSideEffects)
+  if (ME.doesNotAccessMemory() && Int.getHasSideEffects())
     ME = MemoryEffects::unknown();
   return ME;
 }
@@ -506,11 +507,12 @@ static bool compareFnAttributes(const CodeGenIntrinsic *L,
                                 const CodeGenIntrinsic *R) {
   auto TieBoolAttributes = [](const CodeGenIntrinsic *I) -> auto {
     // Sort throwing intrinsics after non-throwing intrinsics.
-    return std::tie(I->canThrow, I->isNoDuplicate, I->isNoMerge, I->isNoReturn,
-                    I->isNoCallback, I->isNoSync, I->isNoFree, I->isWillReturn,
-                    I->isCold, I->isConvergent, I->isSpeculatable,
-                    I->hasSideEffects, I->isStrictFP,
-                    I->isNoCreateUndefOrPoison);
+    return std::make_tuple(I->canThrow, I->isNoDuplicate, I->isNoMerge,
+                           I->isNoReturn, I->isNoCallback, I->isNoSync,
+                           I->getIsNoFree(), I->getIsWillReturn(),
+                           I->getIsCold(), I->getIsConvergent(),
+                           I->getIsSpeculatable(), I->getHasSideEffects(),
+                           I->getIsStrictFP(), I->getIsNoCreateUndefOrPoison());
   };
 
   auto TieL = TieBoolAttributes(L);
@@ -533,9 +535,10 @@ static bool compareFnAttributes(const CodeGenIntrinsic *L,
 // intrinsic has NoUnwind attribute.
 static bool hasFnAttributes(const CodeGenIntrinsic &Int) {
   return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync ||
-         Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate ||
-         Int.isNoMerge || Int.isConvergent || Int.isSpeculatable ||
-         Int.isStrictFP || Int.isNoCreateUndefOrPoison ||
+         Int.getIsNoFree() || Int.getIsWillReturn() || Int.getIsCold() ||
+         Int.isNoDuplicate || Int.isNoMerge || Int.getIsConvergent() ||
+         Int.getIsSpeculatable() || Int.getIsStrictFP() ||
+         Int.getIsNoCreateUndefOrPoison() ||
          getEffectiveME(Int) != MemoryEffects::unknown();
 }
 
@@ -681,23 +684,23 @@ static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
       addAttribute("NoCallback");
     if (Int.isNoSync)
       addAttribute("NoSync");
-    if (Int.isNoFree)
+    if (Int.getIsNoFree())
       addAttribute("NoFree");
-    if (Int.isWillReturn)
+    if (Int.getIsWillReturn())
       addAttribute("WillReturn");
-    if (Int.isCold)
+    if (Int.getIsCold())
       addAttribute("Cold");
     if (Int.isNoDuplicate)
       addAttribute("NoDuplicate");
     if (Int.isNoMerge)
       addAttribute("NoMerge");
-    if (Int.isConvergent)
+    if (Int.getIsConvergent())
       addAttribute("Convergent");
-    if (Int.isSpeculatable)
+    if (Int.getIsSpeculatable())
       addAttribute("Speculatable");
-    if (Int.isStrictFP)
+    if (Int.getIsStrictFP())
       addAttribute("StrictFP");
-    if (Int.isNoCreateUndefOrPoison)
+    if (Int.getIsNoCreateUndefOrPoison())
       addAttribute("NoCreateUndefOrPoison");
 
     const MemoryEffects ME = getEffectiveME(Int);
diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
index d3b7a1af36195..b55c600b0a2db 100644
--- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp
@@ -3189,7 +3189,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(const Init *TheInit,
     // chain.
     if (Int.IS.RetTys.empty())
       Operator = getDAGPatterns().get_intrinsic_void_sdnode();
-    else if (!Int.ME.doesNotAccessMemory() || Int.hasSideEffects)
+    else if (!Int.ME.doesNotAccessMemory() || Int.getHasSideEffects())
       // Has side-effects, requires chain.
       Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
     else // Otherwise, no chain.
@@ -3829,7 +3829,8 @@ class InstAnalyzer {
 
       // Consider intrinsics that don't specify any restrictions on memory
       // effects as having a side-effect.
-      if (IntInfo->ME == MemoryEffects::unknown() || IntInfo->hasSideEffects)
+      if (IntInfo->ME == MemoryEffects::unknown() ||
+          IntInfo->getHasSideEffects())
         hasSideEffects = true;
     }
   }
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 500b6e21293f1..bc5e33b8a2a12 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -54,7 +54,7 @@ using namespace llvm;
 CodeGenSubRegIndex::CodeGenSubRegIndex(const Record *R, unsigned Enum,
                                        const CodeGenHwModes &CGH)
     : TheDef(R), Name(R->getName().str()), EnumValue(Enum),
-      AllSuperRegsCovered(true), Artificial(true) {
+      ConcatenationOf(decltype(this->ConcatenationOf)::withFlags(3)) {
   if (R->getValue("Namespace"))
     Namespace = R->getValueAsString("Namespace").str();
 
@@ -67,8 +67,8 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(const Record *R, unsigned Enum,
 CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
                                        unsigned Enum)
     : TheDef(nullptr), Name(N.str()), Namespace(Nspace.str()),
-      Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true),
-      Artificial(true) {}
+      Range(SubRegRange(-1, -1)), EnumValue(Enum),
+      ConcatenationOf(decltype(this->ConcatenationOf)::withFlags(3)) {}
 
 std::string CodeGenSubRegIndex::getQualifiedName() const {
   std::string N = getNamespace();
@@ -163,11 +163,11 @@ void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
 
 CodeGenRegister::CodeGenRegister(const Record *R, unsigned Enum)
     : TheDef(R), EnumValue(Enum),
-      CostPerUse(R->getValueAsListOfInts("CostPerUse")),
-      CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
-      Constant(R->getValueAsBit("isConstant")), SubRegsComplete(false),
-      SuperRegsComplete(false), TopoSig(~0u) {
-  Artificial = R->getValueAsBit("isArtificial");
+      CostPerUse(R->getValueAsListOfInts("CostPerUse")), TopoSig(~0u),
+      RegUnitLaneMasks(decltype(this->RegUnitLaneMasks)::withFlags(
+          unsigned(!(bool(R->getValueAsBit("CoveredBySubRegs")))) |
+          (unsigned(bool(R->getValueAsBit("isConstant"))) << 3))) {
+  setArtificial(R->getValueAsBit("isArtificial"));
 }
 
 void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
@@ -185,7 +185,7 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
   // sub-register.
   //
   // This is used by computeSecondarySubRegs() to find candidates.
-  if (CoveredBySubRegs && !ExplicitSubRegs.empty())
+  if (getCoveredBySubRegs() && !ExplicitSubRegs.empty())
     ExplicitSubRegs.front()->LeadingSuperRegs.push_back(this);
 
   // Add ad hoc alias links. This is a symmetric relationship between two
@@ -212,16 +212,16 @@ bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
 const CodeGenRegister::SubRegMap &
 CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
   // Only compute this map once.
-  if (SubRegsComplete)
+  if (getSubRegsComplete())
     return SubRegs;
-  SubRegsComplete = true;
+  setSubRegsComplete(true);
 
-  HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;
+  setHasDisjunctSubRegs(ExplicitSubRegs.size() > 1);
 
   // First insert the explicit subregs and make sure they are fully indexed.
   for (auto [SR, Idx] : zip_equal(ExplicitSubRegs, ExplicitSubRegIndices)) {
-    if (!SR->Artificial)
-      Idx->Artificial = false;
+    if (!SR->getArtificial())
+      Idx->setArtificial(false);
     if (!SubRegs.try_emplace(Idx, SR).second)
       PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
                                             " appears twice in Register " +
@@ -238,7 +238,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
   // Here the order is important - earlier subregs take precedence.
   for (CodeGenRegister *ESR : ExplicitSubRegs) {
     const SubRegMap &Map = ESR->computeSubRegs(RegBank);
-    HasDisjunctSubRegs |= ESR->HasDisjunctSubRegs;
+    setHasDisjunctSubRegs(int(getHasDisjunctSubRegs()) |
+                          (ESR->getHasDisjunctSubRegs()));
 
     for (const auto &SR : Map) {
       if (!SubRegs.insert(SR).second)
@@ -309,8 +310,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
     }
 
     // Compute AllSuperRegsCovered.
-    if (!CoveredBySubRegs)
-      SRI->AllSuperRegsCovered = false;
+    if (!getCoveredBySubRegs())
+      SRI->setAllSuperRegsCovered(false);
 
     // Ensure that every sub-register has a unique name.
     DenseMap<const CodeGenRegister *, CodeGenSubRegIndex *>::iterator Ins =
@@ -331,7 +332,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
   // that getConcatSubRegIndex() won't invent any concatenated indices that the
   // user already specified.
   for (auto [Idx, SR] : enumerate(ExplicitSubRegs)) {
-    if (!SR->CoveredBySubRegs || SR->Artificial)
+    if (!SR->getCoveredBySubRegs() || SR->getArtificial())
       continue;
 
     // SR is composed of multiple sub-regs. Find their names in this register.
@@ -339,7 +340,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
     SmallVector<CodeGenSubRegIndex *, 8> Parts;
     for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j) {
       CodeGenSubRegIndex &I = *SR->ExplicitSubRegIndices[j];
-      if (I.Artificial) {
+      if (I.getArtificial()) {
         AnyArtificial = true;
         break;
       }
@@ -373,7 +374,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
   // the added complexity.
   for (CodeGenRegister *AR : ExplicitAliases) {
     // Only visit each edge once.
-    if (AR->SubRegsComplete)
+    if (AR->getSubRegsComplete())
       continue;
     // Create a RegUnit representing this alias edge, and add it to both
     // registers.
@@ -404,7 +405,7 @@ void CodeGenRegister::checkSubRegIndexSizes(CodeGenRegBank &RegBank) const {
   // tiled by them; for those an explicit SubRegIndex extending past the
   // register is a genuine bug. A register that is not covered by its
   // sub-registers makes no such promise, so don't second-guess its layout.
-  if (!CoveredBySubRegs)
+  if (!getCoveredBySubRegs())
     return;
 
   // This register's own bit size is the largest register class containing it.
@@ -553,9 +554,9 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
 
 void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
   // Only visit each register once.
-  if (SuperRegsComplete)
+  if (getSuperRegsComplete())
     return;
-  SuperRegsComplete = true;
+  setSuperRegsComplete(true);
 
   // Make sure all sub-registers have been visited first, so the super-reg
   // lists will be topologically ordered.
@@ -582,7 +583,7 @@ void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
 
 void CodeGenRegister::addSubRegsPreOrder(
     SetVector<const CodeGenRegister *> &OSet, CodeGenRegBank &RegBank) const {
-  assert(SubRegsComplete && "Must precompute sub-registers");
+  assert(getSubRegsComplete() && "Must precompute sub-registers");
   for (CodeGenRegister *SR : ExplicitSubRegs) {
     if (OSet.insert(SR))
       SR->addSubRegsPreOrder(OSet, RegBank);
@@ -748,7 +749,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
     : TheDef(R), Name(R->getName().str()),
       RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1),
       TSFlags(0) {
-  GeneratePressureSet = R->getValueAsBit("GeneratePressureSet");
+  setGeneratePressureSet(R->getValueAsBit("GeneratePressureSet"));
   for (const Record *Type : R->getValueAsListOfDefs("RegTypes"))
     VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes()));
 
@@ -759,13 +760,13 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
 
   // Default allocation order always contains all registers.
   MemberBV.resize(RegBank.getRegisters().size());
-  Artificial = true;
+  setArtificial(true);
   for (const Record *Element : *Elements) {
     Orders[0].push_back(Element);
     const CodeGenRegister *Reg = RegBank.getReg(Element);
     Members.push_back(Reg);
     MemberBV.set(CodeGenRegBank::getRegIndex(Reg));
-    Artificial &= Reg->Artificial;
+    setArtificial(int(getArtificial()) & (Reg->getArtificial()));
     if (!Reg->getSuperRegs().empty())
       RegsWithSuperRegsTopoSigs.set(Reg->getTopoSig());
   }
@@ -802,7 +803,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
   }
 
   int CopyCostParsed = R->getValueAsInt("CopyCost");
-  Allocatable = R->getValueAsBit("isAllocatable");
+  setAllocatable(R->getValueAsBit("isAllocatable"));
   AltOrderSelect = R->getValueAsString("AltOrderSelect");
   int SpillStackIDParsed = R->getValueAsInt("SpillStackID");
   if (!isUInt<8>(SpillStackIDParsed))
@@ -813,7 +814,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
     PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,31]");
   this->AllocationPriority = AllocationPriority;
 
-  GlobalPriority = R->getValueAsBit("GlobalPriority");
+  setGlobalPriority(R->getValueAsBit("GlobalPriority"));
 
   const BitsInit *TSF = R->getValueAsBitsInit("TSFlags");
   TSFlags = uint8_t(*TSF->convertInitializerToInt());
@@ -834,16 +835,16 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
                                            StringRef Name, Key Props)
     : Members(*Props.Members), TheDef(nullptr), Name(Name.str()),
       RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1),
-      RSI(Props.RSI), CopyCost(0), Allocatable(true), AllocationPriority(0),
-      GlobalPriority(false), TSFlags(0), SpillStackID(0) {
+      VTs(decltype(this->VTs)::withFlags(1)), RSI(Props.RSI), CopyCost(0),
+      AllocationPriority(0), TSFlags(0), SpillStackID(0) {
   MemberBV.resize(RegBank.getRegisters().size());
-  Artificial = true;
-  GeneratePressureSet = false;
+  setArtificial(true);
+  setGeneratePressureSet(false);
   for (const auto R : Members) {
     MemberBV.set(CodeGenRegBank::getRegIndex(R));
     if (!R->getSuperRegs().empty())
       RegsWithSuperRegsTopoSigs.set(R->getTopoSig());
-    Artificial &= R->Artificial;
+    setArtificial(int(getArtificial()) & (R->getArtificial()));
   }
 }
 
@@ -856,8 +857,9 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
   // allocatable super-classes and inherit from the nearest allocatable one if
   // any.
   auto NearestAllocSCRIt =
-      find_if(reverse(SuperClasses),
-              [&](const CodeGenRegisterClass *S) { return S->Allocatable; });
+      find_if(reverse(SuperClasses), [&](const CodeGenRegisterClass *S) {
+        return S->getAllocatable();
+      });
   CodeGenRegisterClass &Super = NearestAllocSCRIt == SuperClasses.rend()
                                     ? *SuperClasses.back()
                                     : **NearestAllocSCRIt;
@@ -865,15 +867,17 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
   // Most properties are copied directly.
   // Exceptions are members, size, and alignment
   Namespace = Super.Namespace;
-  VTs = Super.VTs;
+  if (VTs.data() != Super.VTs.data())
+    VTs.assign(Super.VTs.begin(), Super.VTs.end());
   CopyCost = Super.CopyCost;
-  Allocatable = Super.Allocatable;
+  setAllocatable(Super.getAllocatable());
   AltOrderSelect = Super.AltOrderSelect;
   AllocationPriority = Super.AllocationPriority;
-  GlobalPriority = Super.GlobalPriority;
+  setGlobalPriority(Super.getGlobalPriority());
   TSFlags = Super.TSFlags;
   SpillStackID = Super.SpillStackID;
-  GeneratePressureSet |= Super.GeneratePressureSet;
+  setGeneratePressureSet(int(getGeneratePressureSet()) |
+                         (Super.getGeneratePressureSet()));
 
   // Copy all allocation orders, filter out foreign registers from the larger
   // super-class.
@@ -912,11 +916,11 @@ unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank &RegBank) const {
   if (TheDef && !TheDef->isValueUnset("Weight"))
     return TheDef->getValueAsInt("Weight");
 
-  if (Artificial)
+  if (getArtificial())
     return 0;
 
   for (const CodeGenRegister *Reg : Members) {
-    if (!Reg->Artificial)
+    if (!Reg->getArtificial())
       return Reg->getWeight(RegBank);
   }
 
@@ -933,9 +937,9 @@ bool CodeGenRegisterClass::Key::operator<(
   auto IA = Members->begin(), EA = Members->end();
   auto IB = B.Members->begin(), EB = B.Members->end();
   for (;;) {
-    while (IgnoreArtificialMembers && IA != EA && (*IA)->Artificial)
+    while (IgnoreArtificialMembers && IA != EA && (*IA)->getArtificial())
       ++IA;
-    while (IgnoreArtificialMembers && IB != EB && (*IB)->Artificial)
+    while (IgnoreArtificialMembers && IB != EB && (*IB)->getArtificial())
       ++IB;
     if (IA == EA && IB == EB)
       break;
@@ -1019,7 +1023,7 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
     CodeGenRegisterClass &RC = *I;
     RC.SubClasses.resize(NumRegClasses);
     RC.SubClasses.set(RC.EnumValue);
-    if (RC.Artificial)
+    if (RC.getArtificial())
       continue;
 
     // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
@@ -1223,7 +1227,8 @@ CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
                                const CodeGenHwModes &Modes,
                                const bool RegistersAreIntervals)
     : Records(Records), CGH(Modes),
-      RegistersAreIntervals(RegistersAreIntervals) {
+      RegUnits(decltype(this->RegUnits)::withFlags(
+          unsigned(RegistersAreIntervals))) {
   // Configure register Sets to understand register classes and tuples.
   Sets.addFieldExpander("RegisterClass", "MemberList");
   Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
@@ -1303,7 +1308,7 @@ CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
 
   // Infer even more sub-registers by combining leading super-registers.
   for (CodeGenRegister &Reg : Registers)
-    if (Reg.CoveredBySubRegs)
+    if (Reg.getCoveredBySubRegs())
       Reg.computeSecondarySubRegs(*this);
 
   // After the sub-register graph is complete, compute the topologically
@@ -1314,11 +1319,11 @@ CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
   // For each pair of Reg:SR, if both are non-artificial, mark the
   // corresponding sub-register index as non-artificial.
   for (CodeGenRegister &Reg : Registers) {
-    if (Reg.Artificial)
+    if (Reg.getArtificial())
       continue;
     for (auto [SRI, SR] : Reg.getSubRegs()) {
-      if (!SR->Artificial)
-        SRI->Artificial = false;
+      if (!SR->getArtificial())
+        SRI->setArtificial(false);
     }
   }
 
@@ -1339,7 +1344,7 @@ CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
     RegClasses.emplace_back(*this, R);
     CodeGenRegisterClass &RC = RegClasses.back();
     RegClassNames.insert(RC.getName());
-    if (!RC.Artificial)
+    if (!RC.getArtificial())
       addToMaps(&RC);
   }
 
@@ -1708,7 +1713,7 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
     LaneBitmask Mask = Idx.computeLaneMask();
     // If some super-registers without CoveredBySubRegs use this index, we can
     // no longer assume that the lanes are covering their registers.
-    if (!Idx.AllSuperRegsCovered)
+    if (!Idx.getAllSuperRegsCovered())
       CoveringLanes &= ~Mask;
   }
 
@@ -1849,7 +1854,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
   IntEqClasses UberSetIDs(Registers.size() + 1);
   BitVector AllocatableRegs(Registers.size() + 1);
   for (CodeGenRegisterClass &RegClass : RegBank.getRegClasses()) {
-    if (!RegClass.Allocatable)
+    if (!RegClass.getAllocatable())
       continue;
 
     // Ignore artificial registers. They may be members of register
@@ -1858,7 +1863,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
     // their register units.
     CodeGenRegister::Vec Regs;
     for (const CodeGenRegister *Reg : RegClass.getMembers()) {
-      if (!Reg->Artificial)
+      if (!Reg->getArtificial())
         Regs.push_back(Reg);
     }
 
@@ -2059,7 +2064,7 @@ static bool isContiguous(const CodeGenRegister::RegUnitList &Units) {
 // requests this property. This will renumber regunits to ensure the
 // interval property holds, or error out if it cannot be satisfied.
 void CodeGenRegBank::enforceRegUnitIntervals() {
-  if (!RegistersAreIntervals)
+  if (!getRegistersAreIntervals())
     return;
 
   LLVM_DEBUG(dbgs() << "Enforcing regunit intervals for target\n");
@@ -2232,7 +2237,8 @@ void CodeGenRegBank::computeRegUnitSets() {
   // Compute a unique RegUnitSet for each RegClass.
   auto &RegClasses = getRegClasses();
   for (CodeGenRegisterClass &RC : RegClasses) {
-    if (!RC.Allocatable || RC.Artificial || !RC.GeneratePressureSet)
+    if (!RC.getAllocatable() || RC.getArtificial() ||
+        !RC.getGeneratePressureSet())
       continue;
 
     // Compute a sorted list of units in this class.
@@ -2313,7 +2319,7 @@ void CodeGenRegBank::computeRegUnitSets() {
   // For each register class, list the UnitSets that are supersets.
   RegClassUnitSets.resize(RegClasses.size());
   for (CodeGenRegisterClass &RC : RegClasses) {
-    if (!RC.Allocatable)
+    if (!RC.getAllocatable())
       continue;
 
     // Recompute the sorted list of units in this class.
@@ -2338,9 +2344,9 @@ void CodeGenRegBank::computeRegUnitSets() {
       }
     }
     LLVM_DEBUG(dbgs() << '\n');
-    assert(
-        (!RegClassUnitSets[RC.EnumValue].empty() || !RC.GeneratePressureSet) &&
-        "missing unit set for regclass");
+    assert((!RegClassUnitSets[RC.EnumValue].empty() ||
+            !RC.getGeneratePressureSet()) &&
+           "missing unit set for regclass");
   }
 
   // For each register unit, ensure that we have the list of UnitSets that
@@ -2407,7 +2413,7 @@ void CodeGenRegBank::computeRegUnitLaneMasks() {
     // interference and liveness queries. Backfill the missing lanes onto the
     // sub-register's own native units.
     for (auto [SubRegIndex, SubReg] : SubRegs) {
-      if (SubReg->CoveredBySubRegs || SubReg->getSubRegs().empty())
+      if (SubReg->getCoveredBySubRegs() || SubReg->getSubRegs().empty())
         continue;
       LaneBitmask Unclaimed = SubRegIndex->LaneMask;
       for (unsigned SUI : SubReg->getNativeRegUnits())
@@ -2443,11 +2449,13 @@ void CodeGenRegBank::computeDerivedInfo() {
 
   // Compute register class HasDisjunctSubRegs/CoveredBySubRegs flag.
   for (CodeGenRegisterClass &RC : RegClasses) {
-    RC.HasDisjunctSubRegs = false;
-    RC.CoveredBySubRegs = true;
+    RC.setHasDisjunctSubRegs(false);
+    RC.setCoveredBySubRegs(true);
     for (const CodeGenRegister *Reg : RC.getMembers()) {
-      RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
-      RC.CoveredBySubRegs &= Reg->CoveredBySubRegs;
+      RC.setHasDisjunctSubRegs(int(RC.getHasDisjunctSubRegs()) |
+                               (Reg->getHasDisjunctSubRegs()));
+      RC.setCoveredBySubRegs(int(RC.getCoveredBySubRegs()) &
+                             (Reg->getCoveredBySubRegs()));
     }
   }
 
@@ -2501,7 +2509,7 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
     // Skip casses where the intersection is composed of artificial
     // registers.
     if (llvm::all_of(Intersection, [](const CodeGenRegister *Reg) {
-          return Reg->Artificial;
+          return Reg->getArtificial();
         }))
       continue;
 
@@ -2529,7 +2537,7 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
   // Compute the set of registers supporting each SubRegIndex.
   SubReg2SetMap SRSets;
   for (const CodeGenRegister *R : RC->getMembers()) {
-    if (R->Artificial)
+    if (R->getArtificial())
       continue;
     const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
     for (auto [I, _] : SRM)
@@ -2545,14 +2553,14 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
       continue;
     // In most cases, all RC registers support the SubRegIndex.
     auto IsNotArtificial = [](const CodeGenRegister *R) {
-      return !R->Artificial;
+      return !R->getArtificial();
     };
     if (I->second.size() ==
         (size_t)count_if(RC->getMembers(), IsNotArtificial)) {
       RC->setSubClassWithSubReg(&SubIdx, RC);
       continue;
     }
-    if (SubIdx.Artificial)
+    if (SubIdx.getArtificial())
       continue;
     // This is a real subset.  See if we have a matching class.
     CodeGenRegisterClass *SubRC =
@@ -2595,7 +2603,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(
     SubRegs.clear();
     TopoSigs.reset();
     for (const CodeGenRegister *Super : RC->getMembers()) {
-      if (Super->Artificial)
+      if (Super->getArtificial())
         continue;
       const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second;
       assert(Sub && "Missing sub-register");
@@ -2611,7 +2619,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(
     for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end());
          I != std::next(E); ++I) {
       CodeGenRegisterClass &SubRC = *I;
-      if (SubRC.Artificial)
+      if (SubRC.getArtificial())
         continue;
       // Topological shortcut: SubRC members have the wrong shape.
       if (!TopoSigs.anyCommon(SubRC.getRegsWithSuperRegsTopoSigs()))
@@ -2619,7 +2627,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(
       // Compute the subset of RC that maps into SubRC.
       CodeGenRegister::Vec SubSetVec;
       auto IsNotArtificial = [](const CodeGenRegister *R) {
-        return !R->Artificial;
+        return !R->getArtificial();
       };
       auto NonArtificialMembers =
           make_filter_range(RC->getMembers(), IsNotArtificial);
@@ -2713,7 +2721,7 @@ void CodeGenRegBank::computeInferredRegisterClasses() {
   // Watch out for iterator invalidation here.
   for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) {
     CodeGenRegisterClass *RC = &*I;
-    if (RC->Artificial)
+    if (RC->getArtificial())
       continue;
 
     // Synthesize answers for getSubClassWithSubReg().
@@ -2868,7 +2876,7 @@ CodeGenRegBank::getSuperRegForSubReg(const ValueTypeByHwMode &ValueTy,
       continue;
 
     // If necessary, check that it is allocatable.
-    if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
+    if (MustBeAllocatable && !SubClassWithSubReg->getAllocatable())
       continue;
 
     // We have a register class which supports both the value type and
@@ -2912,7 +2920,7 @@ CodeGenRegBank::computeCoveredRegisters(ArrayRef<const Record *> Regs) {
   // Second, find all super-registers that are completely covered by the set.
   for (unsigned i = 0; i != Set.size(); ++i) {
     for (const CodeGenRegister *Super : Set[i]->getSuperRegs()) {
-      if (!Super->CoveredBySubRegs || Set.contains(Super))
+      if (!Super->getCoveredBySubRegs() || Set.contains(Super))
         continue;
       // This new super-register is covered by its sub-registers.
       bool AllSubsInSet = true;
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h
index a37028714306e..e4d533c342e09 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/SparseBitVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -75,15 +76,23 @@ class CodeGenSubRegIndex {
 
   /// A list of subregister indexes concatenated resulting in this
   /// subregister index. This is the reverse of CodeGenRegBank::ConcatIdx.
-  SmallVector<CodeGenSubRegIndex *, 4> ConcatenationOf;
+  llvm::SmallVectorWithFlags<CodeGenSubRegIndex *, 4, 2> ConcatenationOf;
 
   // Are all super-registers containing this SubRegIndex covered by their
   // sub-registers?
-  bool AllSuperRegsCovered;
+  bool getAllSuperRegsCovered() const { return ConcatenationOf.getFlag(0); }
+  bool setAllSuperRegsCovered(bool Value) {
+    ConcatenationOf.setFlag(0, Value);
+    return Value;
+  }
   // A subregister index is "artificial" if every subregister obtained
   // from applying this index is artificial. Artificial subregister
   // indexes are not used to create new register classes.
-  bool Artificial;
+  bool getArtificial() const { return ConcatenationOf.getFlag(1); }
+  bool setArtificial(bool Value) {
+    ConcatenationOf.setFlag(1, Value);
+    return Value;
+  }
 
   CodeGenSubRegIndex(const Record *R, unsigned Enum, const CodeGenHwModes &CGH);
   CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
@@ -176,10 +185,14 @@ class CodeGenRegister {
   const Record *TheDef;
   unsigned EnumValue;
   std::vector<int64_t> CostPerUse;
-  bool CoveredBySubRegs = true;
-  bool HasDisjunctSubRegs = false;
-  bool Artificial = true;
-  bool Constant = false;
+  bool getCoveredBySubRegs() const { return !RegUnitLaneMasks.getFlag(0); }
+  void setCoveredBySubRegs(bool Value) { RegUnitLaneMasks.setFlag(0, !Value); }
+  bool getHasDisjunctSubRegs() const { return RegUnitLaneMasks.getFlag(1); }
+  void setHasDisjunctSubRegs(bool Value) { RegUnitLaneMasks.setFlag(1, Value); }
+  bool getArtificial() const { return !RegUnitLaneMasks.getFlag(2); }
+  void setArtificial(bool Value) { RegUnitLaneMasks.setFlag(2, !Value); }
+  bool getConstant() const { return RegUnitLaneMasks.getFlag(3); }
+  void setConstant(bool Value) { RegUnitLaneMasks.setFlag(3, Value); }
 
   // Map SubRegIndex -> Register.
   using SubRegMap =
@@ -213,7 +226,7 @@ class CodeGenRegister {
   void checkSubRegIndexSizes(CodeGenRegBank &) const;
 
   const SubRegMap &getSubRegs() const {
-    assert(SubRegsComplete && "Must precompute sub-registers");
+    assert(getSubRegsComplete() && "Must precompute sub-registers");
     return SubRegs;
   }
 
@@ -233,7 +246,7 @@ class CodeGenRegister {
   // This is valid after computeSubRegs visits all registers during RegBank
   // construction.
   const SuperRegList &getSuperRegs() const {
-    assert(SubRegsComplete && "Must precompute sub-registers");
+    assert(getSubRegsComplete() && "Must precompute sub-registers");
     return SuperRegs;
   }
 
@@ -250,7 +263,7 @@ class CodeGenRegister {
   // sub-register indices mapping to the same kind of sub-registers
   // (TopoSig-wise).
   unsigned getTopoSig() const {
-    assert(SuperRegsComplete && "TopoSigs haven't been computed yet.");
+    assert(getSuperRegsComplete() && "TopoSigs haven't been computed yet.");
     return TopoSig;
   }
 
@@ -277,7 +290,8 @@ class CodeGenRegister {
   RegUnitList getNativeRegUnits() const { return NativeRegUnits; }
 
   void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
-    RegUnitLaneMasks = LaneMasks;
+    if (RegUnitLaneMasks.data() != LaneMasks.data())
+      RegUnitLaneMasks.assign(LaneMasks.begin(), LaneMasks.end());
   }
 
   // Inherit register units from subregisters.
@@ -295,8 +309,10 @@ class CodeGenRegister {
   using Vec = std::vector<const CodeGenRegister *>;
 
 private:
-  bool SubRegsComplete;
-  bool SuperRegsComplete;
+  bool getSubRegsComplete() const { return ExplicitAliases.getFlag(0); }
+  void setSubRegsComplete(bool Value) { ExplicitAliases.setFlag(0, Value); }
+  bool getSuperRegsComplete() const { return ExplicitAliases.getFlag(1); }
+  void setSuperRegsComplete(bool Value) { ExplicitAliases.setFlag(1, Value); }
   unsigned TopoSig;
 
   // The sub-registers explicit in the .td file form a tree.
@@ -304,7 +320,7 @@ class CodeGenRegister {
   SmallVector<CodeGenRegister *, 8> ExplicitSubRegs;
 
   // Explicit ad hoc aliases, symmetrized to form an undirected graph.
-  SmallVector<CodeGenRegister *, 8> ExplicitAliases;
+  llvm::SmallVectorWithFlags<CodeGenRegister *, 8, 2> ExplicitAliases;
 
   // Super-registers where this is the first explicit sub-register.
   SuperRegList LeadingSuperRegs;
@@ -313,7 +329,7 @@ class CodeGenRegister {
   SuperRegList SuperRegs;
   DenseMap<const CodeGenRegister *, CodeGenSubRegIndex *> SubReg2Idx;
   RegUnitList RegUnits;
-  RegUnitLaneMaskList RegUnitLaneMasks;
+  llvm::SmallVectorWithFlagsFor<RegUnitLaneMaskList, 4> RegUnitLaneMasks;
 };
 
 inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) {
@@ -338,7 +354,7 @@ class CodeGenRegisterClass {
   BitVector SubClasses;
   // List of super-classes, topologocally ordered to have the larger classes
   // first.  This is the same as sorting by EnumValue.
-  SmallVector<CodeGenRegisterClass *, 4> SuperClasses;
+  llvm::SmallVectorWithFlags<CodeGenRegisterClass *, 4, 2> SuperClasses;
   const Record *TheDef;
   std::string Name;
 
@@ -372,25 +388,31 @@ class CodeGenRegisterClass {
 public:
   unsigned EnumValue;
   StringRef Namespace;
-  SmallVector<ValueTypeByHwMode, 4> VTs;
+  llvm::SmallVectorWithFlags<ValueTypeByHwMode, 4, 4> VTs;
   RegSizeInfoByHwMode RSI;
   uint8_t CopyCost;
-  bool Allocatable;
+  bool getAllocatable() const { return VTs.getFlag(0); }
+  void setAllocatable(bool Value) { VTs.setFlag(0, Value); }
   StringRef AltOrderSelect;
   uint8_t AllocationPriority;
-  bool GlobalPriority;
+  bool getGlobalPriority() const { return VTs.getFlag(1); }
+  void setGlobalPriority(bool Value) { VTs.setFlag(1, Value); }
   uint8_t TSFlags;
   uint8_t SpillStackID;
   /// Contains the combination of the lane masks of all subregisters.
   LaneBitmask LaneMask;
   /// True if there are at least 2 subregisters which do not interfere.
-  bool HasDisjunctSubRegs;
-  bool CoveredBySubRegs;
+  bool getHasDisjunctSubRegs() const { return VTs.getFlag(2); }
+  void setHasDisjunctSubRegs(bool Value) { VTs.setFlag(2, Value); }
+  bool getCoveredBySubRegs() const { return VTs.getFlag(3); }
+  void setCoveredBySubRegs(bool Value) { VTs.setFlag(3, Value); }
   /// A register class is artificial if all its members are artificial.
-  bool Artificial;
+  bool getArtificial() const { return SuperClasses.getFlag(0); }
+  void setArtificial(bool Value) { SuperClasses.setFlag(0, Value); }
   /// Generate register pressure set for this register class and any class
   /// synthesized from it.
-  bool GeneratePressureSet;
+  bool getGeneratePressureSet() const { return SuperClasses.getFlag(1); }
+  void setGeneratePressureSet(bool Value) { SuperClasses.setFlag(1, Value); }
 
   // Return the Record that defined this class, or NULL if the class was
   // created by TableGen.
@@ -647,7 +669,7 @@ class CodeGenRegBank {
 
   const CodeGenHwModes &CGH;
 
-  const bool RegistersAreIntervals;
+  bool getRegistersAreIntervals() const { return RegUnits.getFlag(0); }
 
   std::deque<CodeGenSubRegIndex> SubRegIndices;
   DenseMap<const Record *, CodeGenSubRegIndex *> Def2SubRegIdx;
@@ -670,7 +692,7 @@ class CodeGenRegBank {
   std::map<TopoSigId, unsigned> TopoSigs;
 
   // Includes native (0..NumNativeRegUnits-1) and adopted register units.
-  SmallVector<RegUnit, 8> RegUnits;
+  llvm::SmallVectorWithFlags<RegUnit, 8> RegUnits;
 
   // Register classes.
   std::list<CodeGenRegisterClass> RegClasses;
@@ -818,9 +840,9 @@ class CodeGenRegBank {
     RegUnit &RU = RegUnits.emplace_back();
     RU.Roots[0] = R0;
     RU.Roots[1] = R1;
-    RU.Artificial = R0->Artificial;
+    RU.Artificial = R0->getArtificial();
     if (R1)
-      RU.Artificial |= R1->Artificial;
+      RU.Artificial |= R1->getArtificial();
     return RegUnits.size() - 1;
   }
 
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.cpp b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
index ba6c938d88bcd..d23752dfe60d3 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
@@ -272,7 +272,8 @@ void CodeGenTarget::ReadInstructions() const {
   for (const Record *R : Insts) {
     auto [II, _] =
         InstructionMap.try_emplace(R, std::make_unique<CodeGenInstruction>(R));
-    HasVariableLengthEncodings |= II->second->isVariableLengthEncoding();
+    setHasVariableLengthEncodings(int(getHasVariableLengthEncodings()) |
+                                  II->second->isVariableLengthEncoding());
   }
 }
 
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.h b/llvm/utils/TableGen/Common/CodeGenTarget.h
index c04d331357b28..1fc9342e41757 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.h
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGenTypes/MachineValueType.h"
 #include <cassert>
@@ -62,11 +63,16 @@ class CodeGenTarget {
       InstructionMap;
   mutable std::unique_ptr<CodeGenRegBank> RegBank;
   mutable ArrayRef<const Record *> RegAltNameIndices;
-  mutable SmallVector<ValueTypeByHwMode, 8> LegalValueTypes;
+  mutable llvm::SmallVectorWithFlags<ValueTypeByHwMode, 8> LegalValueTypes;
   mutable std::optional<std::vector<const Record *>> RegClassByHwModeList;
   CodeGenHwModes CGH;
   ArrayRef<const Record *> MacroFusions;
-  mutable bool HasVariableLengthEncodings = false;
+  bool getHasVariableLengthEncodings() const {
+    return LegalValueTypes.getFlag(0);
+  }
+  void setHasVariableLengthEncodings(bool Value) const {
+    LegalValueTypes.setFlag(0, Value);
+  }
 
   void ReadInstructions() const;
   void ReadLegalValueTypes() const;
@@ -238,7 +244,9 @@ class CodeGenTarget {
   }
 
   /// Return whether instructions have variable length encodings on this target.
-  bool hasVariableLengthEncodings() const { return HasVariableLengthEncodings; }
+  bool hasVariableLengthEncodings() const {
+    return getHasVariableLengthEncodings();
+  }
 
   /// isLittleEndianEncoding - are instruction bit patterns defined as  [0..n]?
   ///
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
index 40ff769e7bf24..35a31e5cef69d 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
@@ -477,7 +477,8 @@ void SwitchMatcher::emit(MatchTable &Table) {
 //===- RuleMatcher --------------------------------------------------------===//
 
 RuleMatcher::RuleMatcher(ArrayRef<SMLoc> SrcLoc, bool UsesRecordOperand)
-    : Matcher(Matcher::MK_Rule), UsesRecordOperand(UsesRecordOperand),
+    : Matcher(Matcher::MK_Rule),
+      Roots(decltype(this->Roots)::withFlags(unsigned(!(UsesRecordOperand)))),
       SrcLoc(SrcLoc), RuleID(NextRuleID++) {}
 
 uint64_t RuleMatcher::NextRuleID = 0;
@@ -1485,12 +1486,14 @@ bool MIFlagsInstructionPredicateMatcher::isIdentical(
     return false;
   const auto &Other =
       static_cast<const MIFlagsInstructionPredicateMatcher &>(B);
-  return Flags == Other.Flags && CheckNot == Other.CheckNot;
+  return (llvm::ArrayRef<llvm::StringRef>(Flags) ==
+          llvm::ArrayRef<llvm::StringRef>(Other.Flags)) &&
+         getCheckNot() == Other.getCheckNot();
 }
 
 void MIFlagsInstructionPredicateMatcher::emitPredicateOpcodes(
     MatchTable &Table) const {
-  Table << MatchTable::Opcode(CheckNot ? "GIM_MIFlagsNot" : "GIM_MIFlags")
+  Table << MatchTable::Opcode(getCheckNot() ? "GIM_MIFlagsNot" : "GIM_MIFlags")
         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
         << MatchTable::NamedValue(4, join(Flags, " | "))
         << MatchTable::LineBreak;
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
index 83a8b87ca3d61..43c4b0fbeeeb4 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGenTypes/LowLevelType.h"
@@ -296,7 +297,7 @@ class RuleMatcher : public Matcher {
   /// extended to support multiple positions to support div/rem fusion or
   /// load-multiple instructions.
   using RootsTy = SmallVector<InstructionMatcher *, 1>;
-  RootsTy Roots;
+  llvm::SmallVectorWithFlagsFor<RootsTy, 1> Roots;
 
   /// A list of actions that need to be taken when all predicates in this rule
   /// have succeeded.
@@ -342,7 +343,8 @@ class RuleMatcher : public Matcher {
   /// When false, it means the back-end uses other means that we do not know
   /// about and we thus need to assume ANY operand can be accessed by ANY C++
   /// code (GenericInstructionPredicateMatcher)
-  bool UsesRecordOperand = true;
+  bool getUsesRecordOperand() const { return !Roots.getFlag(0); }
+  void setUsesRecordOperand(bool Value) { Roots.setFlag(0, !Value); }
 
   std::vector<std::string> RequiredSimplePredicates;
   std::vector<const Record *> RequiredFeatures;
@@ -394,7 +396,7 @@ class RuleMatcher : public Matcher {
     return RequiredFeatures;
   }
 
-  bool usesRecordOperand() const { return UsesRecordOperand; }
+  bool usesRecordOperand() const { return getUsesRecordOperand(); }
 
   void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; }
   int getHwModeIdx() const { return HwModeIdx; }
@@ -525,7 +527,9 @@ class RuleMatcher : public Matcher {
     return make_range(PhysRegOperands.begin(), PhysRegOperands.end());
   }
 
-  iterator_range<RootsTy::iterator> roots() { return Roots; }
+  iterator_range<RootsTy::iterator> roots() {
+    return {Roots.begin(), Roots.end()};
+  }
   bool roots_empty() const { return Roots.empty(); }
   void roots_pop_front();
 };
@@ -1552,15 +1556,19 @@ class GenericInstructionPredicateMatcher : public InstructionPredicateMatcher {
 };
 
 class MIFlagsInstructionPredicateMatcher : public InstructionPredicateMatcher {
-  SmallVector<StringRef, 2> Flags;
-  bool CheckNot; // false = GIM_MIFlags, true = GIM_MIFlagsNot
+  llvm::SmallVectorWithFlags<StringRef, 2> Flags;
+  bool getCheckNot() const { return Flags.getFlag(0); }
+  void setCheckNot(bool Value) {
+    Flags.setFlag(0, Value);
+  } // false = GIM_MIFlags, true = GIM_MIFlagsNot
 
 public:
   MIFlagsInstructionPredicateMatcher(unsigned InsnVarID,
                                      ArrayRef<StringRef> FlagsToCheck,
                                      bool CheckNot = false)
       : InstructionPredicateMatcher(IPM_MIFlags, InsnVarID),
-        Flags(FlagsToCheck), CheckNot(CheckNot) {
+        Flags(decltype(this->Flags)::withFlags(unsigned(CheckNot),
+                                               FlagsToCheck)) {
     sort(Flags);
   }
 
diff --git a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp
index 8e4a8507e1aca..df84f4ac47aa8 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp
@@ -94,11 +94,11 @@ bool PatternParser::parsePatternList(
 static const CodeGenInstruction &
 getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) {
   StringRef Opc;
-  if (I->isConvergent) {
-    Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"
-                            : "G_INTRINSIC_CONVERGENT";
+  if (I->getIsConvergent()) {
+    Opc = I->getHasSideEffects() ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"
+                                 : "G_INTRINSIC_CONVERGENT";
   } else {
-    Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC";
+    Opc = I->getHasSideEffects() ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC";
   }
 
   RecordKeeper &RK = I->TheDef->getRecords();
diff --git a/llvm/utils/TableGen/Common/InstructionEncoding.cpp b/llvm/utils/TableGen/Common/InstructionEncoding.cpp
index 1d36bd6d9f95c..96fa3c7256c02 100644
--- a/llvm/utils/TableGen/Common/InstructionEncoding.cpp
+++ b/llvm/utils/TableGen/Common/InstructionEncoding.cpp
@@ -411,7 +411,7 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
   DecoderNamespace = EncodingDef->getValueAsString("DecoderNamespace");
   DecoderMethod = EncodingDef->getValueAsString("DecoderMethod");
   if (!DecoderMethod.empty())
-    HasCompleteDecoder = EncodingDef->getValueAsBit("hasCompleteDecoder");
+    setHasCompleteDecoder(EncodingDef->getValueAsBit("hasCompleteDecoder"));
 
   const RecordVal *InstField = EncodingDef->getValue("Inst");
   if (const auto *DI = dyn_cast<DagInit>(InstField->getValue())) {
@@ -431,10 +431,10 @@ InstructionEncoding::InstructionEncoding(const Record *EncodingDef,
   if (DecoderMethod.empty()) {
     // A generated decoder is always successful if none of the operand
     // decoders can fail (all are always successful).
-    HasCompleteDecoder = all_of(Operands, [](const OperandInfo &Op) {
+    setHasCompleteDecoder(all_of(Operands, [](const OperandInfo &Op) {
       // By default, a generated operand decoder is assumed to always succeed.
       // This can be overridden by the user.
       return Op.Decoder.empty() || Op.HasCompleteDecoder;
-    });
+    }));
   }
 }
diff --git a/llvm/utils/TableGen/Common/InstructionEncoding.h b/llvm/utils/TableGen/Common/InstructionEncoding.h
index 44b45137b8f8c..5d15ce956ac22 100644
--- a/llvm/utils/TableGen/Common/InstructionEncoding.h
+++ b/llvm/utils/TableGen/Common/InstructionEncoding.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/KnownBits.h"
 #include <optional>
@@ -80,10 +81,11 @@ class InstructionEncoding {
   /// Whether the custom decoding function always succeeds. If a custom decoder
   /// function is specified, the value is taken from the target description,
   /// otherwise it is inferred.
-  bool HasCompleteDecoder;
+  bool getHasCompleteDecoder() const { return Operands.getFlag(0); }
+  void setHasCompleteDecoder(bool Value) { Operands.setFlag(0, Value); }
 
   /// Information about the operands' contribution to this encoding.
-  SmallVector<OperandInfo, 16> Operands;
+  llvm::SmallVectorWithFlags<OperandInfo, 16> Operands;
 
 public:
   InstructionEncoding(const Record *EncodingDef,
@@ -127,7 +129,7 @@ class InstructionEncoding {
 
   /// Returns whether the decoder (either generated or specified by the user)
   /// always succeeds.
-  bool hasCompleteDecoder() const { return HasCompleteDecoder; }
+  bool hasCompleteDecoder() const { return getHasCompleteDecoder(); }
 
   /// Returns information about the operands' contribution to this encoding.
   ArrayRef<OperandInfo> getOperands() const { return Operands; }
diff --git a/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp
index 3a2ef55656067..fa04472b5046a 100644
--- a/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp
+++ b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp
@@ -127,7 +127,7 @@ getCustomCoders(ArrayRef<const Init *> Args) {
 }
 
 VarLenInst::VarLenInst(const DagInit *DI, const RecordVal *TheDef)
-    : TheDef(TheDef), NumBits(0U), HasDynamicSegment(false) {
+    : TheDef(TheDef), NumBits(0U) {
   buildRec(DI);
   for (const auto &S : Segments)
     NumBits += S.BitWidth;
@@ -168,7 +168,7 @@ void VarLenInst::buildRec(const DagInit *DI) {
     if (DI->getNumArgs() < 2)
       PrintFatalError(TheDef->getLoc(),
                       "Expecting at least 2 arguments for `operand`");
-    HasDynamicSegment = true;
+    setHasDynamicSegment(true);
     const Init *OperandName = DI->getArg(0), *NumBits = DI->getArg(1);
     if (!isa<StringInit>(OperandName) || !isa<IntInit>(NumBits))
       PrintFatalError(TheDef->getLoc(), "Invalid argument types for `operand`");
@@ -187,7 +187,7 @@ void VarLenInst::buildRec(const DagInit *DI) {
     if (DI->getNumArgs() < 3)
       PrintFatalError(TheDef->getLoc(),
                       "Expecting at least 3 arguments for `slice`");
-    HasDynamicSegment = true;
+    setHasDynamicSegment(true);
     const Init *OperandName = DI->getArg(0), *HiBit = DI->getArg(1),
                *LoBit = DI->getArg(2);
     if (!isa<StringInit>(OperandName) || !isa<IntInit>(HiBit) ||
diff --git a/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h
index ca0f9c3f8b4f3..9a98cbe70eb6d 100644
--- a/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h
+++ b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_UTILS_TABLEGEN_COMMON_VARLENCODEEMITTERGEN_H
 #define LLVM_UTILS_TABLEGEN_COMMON_VARLENCODEEMITTERGEN_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/TableGen/Record.h"
 
 namespace llvm {
@@ -30,14 +31,15 @@ class VarLenInst {
   size_t NumBits;
 
   // Set if any of the segment is not fixed value.
-  bool HasDynamicSegment;
+  bool getHasDynamicSegment() const { return Segments.getFlag(0); }
+  void setHasDynamicSegment(bool Value) { Segments.setFlag(0, Value); }
 
-  SmallVector<EncodingSegment, 4> Segments;
+  llvm::SmallVectorWithFlags<EncodingSegment, 4> Segments;
 
   void buildRec(const DagInit *DI);
 
 public:
-  VarLenInst() : TheDef(nullptr), NumBits(0U), HasDynamicSegment(false) {}
+  VarLenInst() : TheDef(nullptr), NumBits(0U) {}
 
   explicit VarLenInst(const DagInit *DI, const RecordVal *TheDef);
 
@@ -50,7 +52,7 @@ class VarLenInst {
   const_iterator end() const { return Segments.end(); }
   size_t getNumSegments() const { return Segments.size(); }
 
-  bool isFixedValueOnly() const { return !HasDynamicSegment; }
+  bool isFixedValueOnly() const { return !getHasDynamicSegment(); }
 };
 
 void emitVarLenCodeEmitter(const RecordKeeper &R, raw_ostream &OS);
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index f8ebdfccda46f..ae45cd9824fe3 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -28,6 +28,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -289,7 +290,7 @@ class FilterChooser {
 
   /// Encoding IDs for this filter chooser to work on.
   /// Sorted by non-decreasing encoding width.
-  SmallVector<unsigned, 0> EncodingIDs;
+  llvm::SmallVectorWithFlags<unsigned, 0> EncodingIDs;
 
   // Array of bit values passed down from our parent.
   // Set to all unknown for Parent == nullptr.
@@ -323,7 +324,8 @@ class FilterChooser {
   std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
 
   /// Set to true if decoding conflict was encountered.
-  bool HasConflict = false;
+  bool getHasConflict() const { return EncodingIDs.getFlag(0); }
+  void setHasConflict(bool Value) { EncodingIDs.setFlag(0, Value); }
 
 public:
   /// Constructs a top-level filter chooser.
@@ -362,7 +364,7 @@ class FilterChooser {
   }
 
   /// Returns true if any decoding conflicts were encountered.
-  bool hasConflict() const { return HasConflict; }
+  bool hasConflict() const { return getHasConflict(); }
 
 private:
   /// Applies the given filter to the set of encodings this FilterChooser
@@ -438,7 +440,10 @@ void FilterChooser::applyFilter(const Filter &F) {
     // group of instructions whose segment values are variable.
     VariableFC = std::make_unique<FilterChooser>(Encodings, F.VariableIDs,
                                                  FilterBits, *this);
-    HasConflict |= VariableFC->HasConflict;
+    [&] {
+      auto PackedFlagValue = VariableFC->getHasConflict();
+      return setHasConflict(getHasConflict() | PackedFlagValue);
+    }();
   }
 
   // Otherwise, create sub choosers.
@@ -454,7 +459,7 @@ void FilterChooser::applyFilter(const Filter &F) {
         FilterVal,
         std::make_unique<FilterChooser>(Encodings, InferiorEncodingIDs,
                                         InferiorFilterBits, *this));
-    HasConflict |= It->second->HasConflict;
+    setHasConflict(int(getHasConflict()) | It->second->getHasConflict());
   }
 }
 
@@ -802,7 +807,8 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
       if (!Islands.empty()) {
         // Found an instruction with island(s).  Now just assign a filter.
         return std::make_unique<Filter>(
-            Encodings, EncodingIDs, Islands[0].StartBit, Islands[0].NumBits);
+            Encodings, ArrayRef<unsigned>(EncodingIDs), Islands[0].StartBit,
+            Islands[0].NumBits);
       }
     }
   }
@@ -833,8 +839,9 @@ FilterChooser::findBestFilter(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
   std::vector<std::unique_ptr<Filter>> Filters;
 
   auto addCandidateFilter = [&](unsigned StartBit, unsigned EndBit) {
-    Filters.push_back(std::make_unique<Filter>(Encodings, EncodingIDs, StartBit,
-                                               EndBit - StartBit));
+    Filters.push_back(std::make_unique<Filter>(Encodings,
+                                               ArrayRef<unsigned>(EncodingIDs),
+                                               StartBit, EndBit - StartBit));
   };
 
   unsigned FilterWidth = FilterBits.getBitWidth();
@@ -1038,7 +1045,7 @@ void FilterChooser::doFilter() {
   // Print out useful conflict information for postmortem analysis.
   errs() << "Decoding Conflict:\n";
   dump();
-  HasConflict = true;
+  setHasConflict(true);
 }
 
 void FilterChooser::dump() const {
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index be335ce3bc34c..3f72b9f3052e9 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -553,7 +553,7 @@ GlobalISelEmitter::getEquivNode(const Record &Equiv,
   }
 
   if (!Equiv.isValueUnset("IfConvergent") &&
-      N.getIntrinsicInfo(CGP)->isConvergent)
+      N.getIntrinsicInfo(CGP)->getIsConvergent())
     return &Target.getInstruction(Equiv.getValueAsDef("IfConvergent"));
 
   bool IsAnyExtLoad = false;
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index ccce8fb0fedbf..d15025c28a9c3 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -247,7 +247,7 @@ void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS,
     const CodeGenRegister::Vec &Regs = RC.getMembers();
     OS << "    {" << RC.getWeight(RegBank) << ", ";
     unsigned WeightLimit = 0;
-    if (Regs.empty() || RC.Artificial)
+    if (Regs.empty() || RC.getArtificial())
       OS << '0';
     else {
       std::vector<unsigned> RegUnits;
@@ -1080,8 +1080,8 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
        << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i])
        << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
        << (Offset << RegUnitBits | FirstRU) << ", "
-       << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << ", " << Reg.Constant << ", "
-       << Reg.Artificial << " },\n";
+       << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << ", " << Reg.getConstant()
+       << ", " << Reg.getArtificial() << " },\n";
     ++i;
   }
   OS << "};\n\n"; // End of register descriptors...
@@ -1241,7 +1241,8 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
        << RCIndices.RegSetSize << ", /* RegSetSize */\n      "
        << RC.getQualifiedIdName() << ",\n      "
        << static_cast<unsigned>(RC.CopyCost) << ", /* CopyCost */\n      "
-       << (RC.Allocatable ? "true" : "false") << ", /* Allocatable */\n      "
+       << (RC.getAllocatable() ? "true" : "false")
+       << ", /* Allocatable */\n      "
        << (RC.getBaseClassOrder() ? "true" : "false") << ",\n      "
        << GetOff("SubClassMasks", RCIndices.SubClassMaskIdx) << ",\n      "
        << GetOff("SuperRegIdxSeqs",
@@ -1249,12 +1250,12 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS,
        << ",\n      ";
     printMask(OS, RC.LaneMask);
     OS << ",\n      " << (unsigned)RC.AllocationPriority << ",\n      "
-       << (RC.GlobalPriority ? "true" : "false") << ",\n      "
+       << (RC.getGlobalPriority() ? "true" : "false") << ",\n      "
        << format("0x%02x", RC.TSFlags) << ", /* TSFlags */\n      "
        << (unsigned)RC.SpillStackID << ", /* SpillStackID */\n      "
-       << (RC.HasDisjunctSubRegs ? "true" : "false")
+       << (RC.getHasDisjunctSubRegs() ? "true" : "false")
        << ", /* HasDisjunctSubRegs */\n      "
-       << (RC.CoveredBySubRegs ? "true" : "false")
+       << (RC.getCoveredBySubRegs() ? "true" : "false")
        << ", /* CoveredBySubRegs */\n      "
        << GetOff("SuperClasses", RCIndices.SuperClassIdx) << ",\n      "
        << RC.getSuperClasses().size() << "\n    },\n";
@@ -1523,7 +1524,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS,
   for (const auto &RC : RegisterClasses) {
     ArrayRef<const Record *> Order = RC.getOrder();
 
-    if (RC.Allocatable)
+    if (RC.getAllocatable())
       AllocatableRegs.insert(Order.begin(), Order.end());
   }
 
@@ -1955,7 +1956,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS,
     // Add all constant physical registers to the preserved mask:
     SetTheory::RecSet ConstantSet;
     for (const auto &Reg : RegBank.getRegisters()) {
-      if (Reg.Constant)
+      if (Reg.getConstant())
         ConstantSet.insert(Reg.TheDef);
     }
     Covered |= RegBank.computeCoveredRegisters(ConstantSet.getArrayRef());
@@ -2041,7 +2042,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS,
      << "isConstantPhysReg(MCRegister PhysReg) const {\n"
      << "  return\n";
   for (const auto &Reg : Regs)
-    if (Reg.Constant)
+    if (Reg.getConstant())
       OS << "      PhysReg == " << getQualifiedName(Reg.TheDef) << " ||\n";
   OS << "      false;\n";
   OS << "}\n\n";
@@ -2135,9 +2136,9 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
        << '\n';
     OS << "\tNumRegs: " << RC.getMembers().size() << '\n';
     OS << "\tLaneMask: " << PrintLaneMask(RC.LaneMask) << '\n';
-    OS << "\tHasDisjunctSubRegs: " << RC.HasDisjunctSubRegs << '\n';
-    OS << "\tCoveredBySubRegs: " << RC.CoveredBySubRegs << '\n';
-    OS << "\tAllocatable: " << RC.Allocatable << '\n';
+    OS << "\tHasDisjunctSubRegs: " << RC.getHasDisjunctSubRegs() << '\n';
+    OS << "\tCoveredBySubRegs: " << RC.getCoveredBySubRegs() << '\n';
+    OS << "\tAllocatable: " << RC.getAllocatable() << '\n';
     OS << "\tAllocationPriority: " << unsigned(RC.AllocationPriority) << '\n';
     OS << "\tWeight: " << RC.getWeight(RegBank) << '\n';
     OS << "\tBaseClassOrder: " << RC.getBaseClassOrder() << '\n';
@@ -2159,21 +2160,21 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
       OS << " " << SRC->getName();
     }
     OS << '\n';
-    if (RC.Artificial)
+    if (RC.getArtificial())
       OS << "\tArtificial: 1\n";
   }
 
   for (const CodeGenSubRegIndex &SRI : RegBank.getSubRegIndices()) {
     OS << "SubRegIndex " << SRI.getName() << ":\n";
     OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n';
-    OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n';
+    OS << "\tAllSuperRegsCovered: " << SRI.getAllSuperRegsCovered() << '\n';
     OS << "\tOffset: " << printByHwMode(SRI.Range, [](const SubRegRange &Info) {
       return Info.Offset;
     }) << '\n';
     OS << "\tSize: " << printByHwMode(SRI.Range, [](const SubRegRange &Info) {
       return Info.Size;
     }) << '\n';
-    if (SRI.Artificial)
+    if (SRI.getArtificial())
       OS << "\tArtificial: 1\n";
   }
 
@@ -2183,15 +2184,15 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
     for (const auto &Cost : R.CostPerUse)
       OS << Cost << " ";
     OS << '\n';
-    OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n';
-    OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n';
+    OS << "\tCoveredBySubregs: " << R.getCoveredBySubRegs() << '\n';
+    OS << "\tHasDisjunctSubRegs: " << R.getHasDisjunctSubRegs() << '\n';
     for (auto &[SubIdx, SubReg] : R.getSubRegs()) {
       OS << "\tSubReg " << SubIdx->getName() << " = " << SubReg->getName()
          << '\n';
     }
     for (unsigned U : R.getNativeRegUnits())
       OS << "\tRegUnit " << U << '\n';
-    if (R.Artificial)
+    if (R.getArtificial())
       OS << "\tArtificial: 1\n";
   }
 }
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index c43471b32911d..ef7277006bbcc 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
@@ -80,9 +81,11 @@ struct GenericField {
 struct SearchIndex {
   std::string Name;
   SMLoc Loc; // Source location of PrimaryKey or Key field definition.
-  SmallVector<GenericField, 1> Fields;
-  bool EarlyOut = false;
-  bool ReturnRange = false;
+  llvm::SmallVectorWithFlags<GenericField, 1, 2> Fields;
+  bool getEarlyOut() const { return Fields.getFlag(0); }
+  void setEarlyOut(bool Value) { Fields.setFlag(0, Value); }
+  bool getReturnRange() const { return Fields.getFlag(1); }
+  void setReturnRange(bool Value) { Fields.setFlag(1, Value); }
 };
 
 struct GenericTable {
@@ -94,9 +97,10 @@ struct GenericTable {
   std::vector<const Record *> Entries;
 
   std::unique_ptr<SearchIndex> PrimaryKey;
-  SmallVector<std::unique_ptr<SearchIndex>, 2> Indices;
+  llvm::SmallVectorWithFlags<std::unique_ptr<SearchIndex>, 2> Indices;
 
-  bool AllowSparseTable;
+  bool getAllowSparseTable() const { return Indices.getFlag(0); }
+  void setAllowSparseTable(bool Value) { Indices.setFlag(0, Value); }
 
   const GenericField *getFieldByName(StringRef Name) const {
     for (const auto &Field : Fields) {
@@ -442,7 +446,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
     }
   }
 
-  if (Index.EarlyOut || IsContiguous) {
+  if (Index.getEarlyOut() || IsContiguous) {
     const GenericField &Field = Index.Fields[0];
     std::string FirstRepr = primaryRepresentation(
         Index.Loc, Field, IndexRows[0]->getValueInit(Field.Name));
@@ -454,7 +458,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
        << ">(" << Field.Name << ", " << FirstRepr << ", " << LastRepr << "))\n";
     OS << "    return nullptr;\n\n";
 
-    if (IsContiguous && !Index.EarlyOut) {
+    if (IsContiguous && !Index.getEarlyOut()) {
       OS << "  auto Table = ArrayRef(" << IndexName << ");\n";
       OS << "  size_t Idx = " << Field.Name << " - " << FirstRepr << ";\n";
       OS << "  return ";
@@ -538,7 +542,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
     OS << "    }\n";
   };
   emitComparator(false, true);
-  bool ShouldReturnRange = Index.ReturnRange;
+  bool ShouldReturnRange = Index.getReturnRange();
   if (ShouldReturnRange) {
     OS << "    bool operator()(const KeyType &LHS, const " << IndexTypeName
        << " &RHS) const {\n";
@@ -580,7 +584,7 @@ void SearchableTableEmitter::emitLookupFunction(const GenericTable &Table,
 void SearchableTableEmitter::emitLookupDeclaration(const GenericTable &Table,
                                                    const SearchIndex &Index,
                                                    raw_ostream &OS) {
-  if (Index.ReturnRange)
+  if (Index.getReturnRange())
     OS << "llvm::iterator_range<const " << Table.CppTypeName << " *> ";
   else
     OS << "const " << Table.CppTypeName << " *";
@@ -621,7 +625,7 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
   SmallVector<const Record *, 0> SparseEntries;
   ArrayRef<const Record *> Entries;
   unsigned DirectLookupSlots = 0;
-  if (Table.AllowSparseTable) {
+  if (Table.getAllowSparseTable()) {
     const auto *KeyBits = cast<BitsRecTy>(Table.PrimaryKey->Fields[0].RecType);
     DirectLookupSlots = 1u << KeyBits->getNumBits();
     SparseEntries.resize(DirectLookupSlots);
@@ -658,7 +662,7 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
           OS << primaryRepresentation(Table.Locs[0], Field, Value);
         }
       }
-    } else if (Table.AllowSparseTable) {
+    } else if (Table.getAllowSparseTable()) {
       // For empty rows emit a sentinel value as a key, so we can return null
       // during lookup. Value is constructed such that LookupKey != KeyField.
       for (const auto &Field : Table.Fields) {
@@ -677,7 +681,7 @@ void SearchableTableEmitter::emitGenericTable(const GenericTable &Table,
   // The lookup function might add more strings.
   std::string LookupFunction;
   raw_string_ostream LFOS(LookupFunction);
-  if (Table.AllowSparseTable) {
+  if (Table.getAllowSparseTable()) {
     LFOS << "\n";
     emitLookupDeclaration(Table, *Table.PrimaryKey, LFOS);
     LFOS << " {\n";
@@ -741,8 +745,8 @@ std::unique_ptr<SearchIndex> SearchableTableEmitter::parseSearchIndex(
   auto Index = std::make_unique<SearchIndex>();
   Index->Name = Name.str();
   Index->Loc = KeyRecVal->getLoc();
-  Index->EarlyOut = EarlyOut;
-  Index->ReturnRange = ReturnRange;
+  Index->setEarlyOut(EarlyOut);
+  Index->setReturnRange(ReturnRange);
 
   for (const auto &FieldName : Key) {
     const GenericField *Field = Table.getFieldByName(FieldName);
@@ -979,7 +983,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
                           return compareBy(LHS, RHS, *Table->PrimaryKey);
                         });
 
-      Table->AllowSparseTable = canUseSparseTable(TableRec, Table);
+      Table->setAllowSparseTable(canUseSparseTable(TableRec, Table));
     }
 
     TableMap.try_emplace(TableRec, Table.get());
@@ -1003,7 +1007,7 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
         IndexRec->getValueAsBit("EarlyOut"), /*ReturnRange*/ false));
 
     // Sparse tables with secondary search indices are not supported.
-    Table.AllowSparseTable = false;
+    Table.setAllowSparseTable(false);
   }
 
   // Translate legacy tables.
diff --git a/mlir/examples/transform-opt/mlir-transform-opt.cpp b/mlir/examples/transform-opt/mlir-transform-opt.cpp
index 4b12e7610d0a8..76d81a019cccd 100644
--- a/mlir/examples/transform-opt/mlir-transform-opt.cpp
+++ b/mlir/examples/transform-opt/mlir-transform-opt.cpp
@@ -20,6 +20,7 @@
 #include "mlir/Parser/Parser.h"
 #include "mlir/Support/FileUtilities.h"
 #include "mlir/Tools/mlir-opt/MlirOptMain.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -175,8 +176,9 @@ class TransformSourceMgr {
   /// Deconstructs the source manager. Note that `checkResults` must have been
   /// called on this instance before deconstructing it.
   ~TransformSourceMgr() {
-    assert(resultChecked && "must check the result of diagnostic handlers by "
-                            "running TransformSourceMgr::checkResult");
+    assert(getResultChecked() &&
+           "must check the result of diagnostic handlers by "
+           "running TransformSourceMgr::checkResult");
   }
 
   /// Parses the given buffer and creates the top-level operation of the kind
@@ -213,7 +215,7 @@ class TransformSourceMgr {
   /// this source manager, performs the verification, reports errors and returns
   /// the result of the verification. Otherwise passes through the given value.
   llvm::LogicalResult checkResult(llvm::LogicalResult result) {
-    resultChecked = true;
+    setResultChecked(true);
     if (!verifyDiagnostics)
       return result;
 
@@ -229,7 +231,8 @@ class TransformSourceMgr {
 
   /// Indicates that diagnostic message verification has taken place, and the
   /// deconstruction is therefore safe.
-  bool resultChecked = false;
+  bool getResultChecked() const { return diagHandlers.getFlag(0); }
+  void setResultChecked(bool Value) { diagHandlers.setFlag(0, Value); }
 
   /// Storage for per-buffer source managers and diagnostic handlers. These are
   /// wrapped into unique pointers in order to make it safe to capture
@@ -237,7 +240,7 @@ class TransformSourceMgr {
   /// pointer objects are moved by the pointer addresses won't change. Also, for
   /// handlers, this allows to store the pointer to the base class.
   SmallVector<std::unique_ptr<llvm::SourceMgr>> sourceMgrs;
-  SmallVector<DiagnosticHandlerWrapper> diagHandlers;
+  llvm::SmallVectorWithFlags<DiagnosticHandlerWrapper> diagHandlers;
 };
 } // namespace
 
diff --git a/mlir/include/mlir/ABI/ABIRewriteContext.h b/mlir/include/mlir/ABI/ABIRewriteContext.h
index 7760d015d8919..3c6d653ce9443 100644
--- a/mlir/include/mlir/ABI/ABIRewriteContext.h
+++ b/mlir/include/mlir/ABI/ABIRewriteContext.h
@@ -25,6 +25,7 @@
 #include "mlir/IR/Value.h"
 #include "mlir/Interfaces/FunctionInterfaces.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/Alignment.h"
 
 #include <cassert>
@@ -148,7 +149,8 @@ struct ArgClassification {
 /// all arguments.
 struct FunctionClassification {
   ArgClassification returnInfo;
-  SmallVector<ArgClassification> argInfos;
+  // Flag bit 0 marks a source-language void return.
+  llvm::SmallVectorWithFlags<ArgClassification> argInfos;
 
   /// Whether the classified return type was the source language's void.
   ///
@@ -163,12 +165,13 @@ struct FunctionClassification {
   ///
   /// Left false when unknown, which costs a needless rewrite rather than a
   /// skipped one.
-  bool returnsVoid = false;
+  bool returnsVoid() const { return argInfos.getFlag(0); }
+  void setReturnsVoid(bool IsVoid) { argInfos.setFlag(0, IsVoid); }
 
   /// Whether any value in the signature is passed differently from how it is
   /// written, so a rewriter has work to do.
   bool needsRewrite() const {
-    if (!returnsVoid && !returnInfo.isPassThrough())
+    if (!returnsVoid() && !returnInfo.isPassThrough())
       return true;
     return !llvm::all_of(argInfos, [](const ArgClassification &ac) {
       return ac.isPassThrough();
diff --git a/mlir/include/mlir/Analysis/Presburger/Simplex.h b/mlir/include/mlir/Analysis/Presburger/Simplex.h
index d89bbe37a6b3e..33f862e964550 100644
--- a/mlir/include/mlir/Analysis/Presburger/Simplex.h
+++ b/mlir/include/mlir/Analysis/Presburger/Simplex.h
@@ -21,6 +21,7 @@
 #include "mlir/Analysis/Presburger/PWMAFunction.h"
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <optional>
 
 namespace mlir {
@@ -318,12 +319,13 @@ class SimplexBase {
 
   /// Return the number of fixed columns, as described in the constructor above,
   /// this is the number of columns beyond those for the variables in var.
-  unsigned getNumFixedCols() const { return usingBigM ? 3u : 2u; }
+  unsigned getNumFixedCols() const { return getUsingBigM() ? 3u : 2u; }
   unsigned getNumRows() const { return tableau.getNumRows(); }
   unsigned getNumColumns() const { return tableau.getNumColumns(); }
 
   /// Stores whether or not a big M column is present in the tableau.
-  bool usingBigM;
+  bool getUsingBigM() const { return var.getFlag(0); }
+  void setUsingBigM(bool Value) { var.setFlag(0, Value); }
 
   /// The number of redundant rows in the tableau. These are the first
   /// nRedundant rows.
@@ -338,7 +340,8 @@ class SimplexBase {
 
   /// This is true if the tableau has been detected to be empty, false
   /// otherwise.
-  bool empty;
+  bool getEmpty() const { return var.getFlag(1); }
+  void setEmpty(bool Value) { var.setFlag(1, Value); }
 
   /// Holds a log of operations, used for rolling back to a previous state.
   SmallVector<UndoLogEntry, 8> undoLog;
@@ -358,7 +361,8 @@ class SimplexBase {
   SmallVector<int, 8> rowUnknown, colUnknown;
 
   /// These hold information about each unknown.
-  SmallVector<Unknown, 8> con, var;
+  SmallVector<Unknown, 8> con;
+  llvm::SmallVectorWithFlags<Unknown, 8, 2> var;
 };
 
 /// Simplex class using the lexicographic pivot rule. Used for lexicographic
diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
index bec14fffec96c..3e9ee0328e3a3 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
@@ -14,6 +14,7 @@
 #include "mlir/Support/LLVM.h"
 #include "llvm/ADT/DenseMapInfoVariant.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <optional>
 
 #include "mlir/Dialect/Bufferization/IR/BufferizationEnums.h.inc"
@@ -361,7 +362,12 @@ struct BufferizationOptions {
   /// `functionArgTypeConverterFn`.
   ///
   /// If `bufferizeFunctionBoundaries` is not set, this flag has no effect.
-  bool inferFunctionResultLayout = true;
+  bool getInferFunctionResultLayout() const {
+    return !stateInitializers.getFlag(0);
+  }
+  void setInferFunctionResultLayout(bool Value) {
+    stateInitializers.setFlag(0, !Value);
+  }
 
   /// Type conversion from tensors to memrefs. This type conversion is used if
   /// no memref type could be inferred during bufferization. By default, returns
@@ -402,7 +408,7 @@ struct BufferizationOptions {
 
   /// Initializer functions for analysis state. These can be used to
   /// initialize dialect-specific analysis state.
-  SmallVector<AnalysisStateInitFn> stateInitializers;
+  llvm::SmallVectorWithFlags<AnalysisStateInitFn> stateInitializers;
 };
 
 /// Traversal parameters for `findValueInReverseUseDefChain`.
diff --git a/mlir/include/mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.h b/mlir/include/mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.h
index cb2489335a317..e4c86a3cc4843 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.h
@@ -18,6 +18,7 @@
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/PatternMatch.h"
 #include "mlir/IR/Value.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/LogicalResult.h"
 
 namespace mlir {
@@ -69,18 +70,29 @@ class PtxBuilder {
   // Register constraints (read, write, readwrite) and register data types
   std::string registerConstraints;
   // Modifiers
-  SmallVector<PTXRegisterMod> registerModifiers;
+  llvm::SmallVectorWithFlags<
+      PTXRegisterMod,
+      llvm::CalculateSmallVectorDefaultInlinedElements<PTXRegisterMod>::value,
+      2>
+      registerModifiers;
   // Has return value as write-only or read-write
-  bool hasResult = false;
+  bool getHasResult() const { return registerModifiers.getFlag(0); }
+  void setHasResult(bool Value) { registerModifiers.setFlag(0, Value); }
   // Indicates if the Op will handle the register mapping manually.
-  bool needsManualRegisterMapping = false;
+  bool getNeedsManualRegisterMapping() const {
+    return registerModifiers.getFlag(1);
+  }
+  void setNeedsManualRegisterMapping(bool Value) {
+    registerModifiers.setFlag(1, Value);
+  }
 
 public:
   /// Single constructor that only initializes members.
   PtxBuilder(Operation *op, PatternRewriter &rewriter,
              bool needsManualRegisterMapping = false)
       : interfaceOp(op), rewriter(rewriter),
-        needsManualRegisterMapping(needsManualRegisterMapping) {}
+        registerModifiers(decltype(this->registerModifiers)::withFlags(
+            (unsigned(needsManualRegisterMapping) << 1))) {}
 
   /// Add an operand with the read/write input type.
   LogicalResult insertValue(Value v,
diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
index 575b8c20b790c..f4a77bb267452 100644
--- a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
+++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
@@ -9,6 +9,7 @@
 #ifndef MLIR_DIALECT_LINALG_TRANSFORMS_TRANSFORMS_H
 #define MLIR_DIALECT_LINALG_TRANSFORMS_TRANSFORMS_H
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <utility>
 
 #include "mlir/Conversion/VectorToSCF/VectorToSCF.h"
@@ -356,16 +357,17 @@ struct PadTilingInterfaceOptions {
     return *this;
   }
   /// A list of iterator dimensions sizes to pad to.
-  SmallVector<OpFoldResult> paddingSizes;
+  llvm::SmallVectorWithFlags<OpFoldResult> paddingSizes;
   PadTilingInterfaceOptions &setPaddingSizes(ArrayRef<OpFoldResult> m) {
     paddingSizes.assign(m.begin(), m.end());
     return *this;
   }
   /// Pad iterator `paddingDimension[i]` to next multiple of `paddingSizes[i]`
   /// if true. Otherwise pad to `paddingSizes[i]`.
-  bool padToMultipleOf;
+  bool getPadToMultipleOfFlag() const { return paddingSizes.getFlag(0); }
+  void setPadToMultipleOfFlag(bool Value) { paddingSizes.setFlag(0, Value); }
   PadTilingInterfaceOptions &setPadToMultipleOf(bool b) {
-    padToMultipleOf = b;
+    setPadToMultipleOfFlag(b);
     return *this;
   }
 };
@@ -1421,29 +1423,54 @@ struct BlockPackMatmulOptions {
   /// Scalable flags for block factors. When true, the corresponding block
   /// factor is considered scalable. Must be empty (all static) or have the same
   /// size as blockFactors.
-  SmallVector<bool, 3> scalableBlockFactors;
+  llvm::SmallVectorWithFlags<bool, 3> scalableBlockFactors;
 
   /// If true, allows packing of dimensions that only partially fit into the
   /// block factors.
-  bool allowPadding = true;
+  bool getAllowPadding() const {
+    return !mnkPaddedSizesNextMultipleOf.getFlag(0);
+  }
+  void setAllowPadding(bool Value) {
+    mnkPaddedSizesNextMultipleOf.setFlag(0, !Value);
+  }
 
   /// Next multiples of the packing sizes.
-  SmallVector<int64_t, 3> mnkPaddedSizesNextMultipleOf;
+  llvm::SmallVectorWithFlags<int64_t, 3, 4> mnkPaddedSizesNextMultipleOf;
 
   /// Permutation of matmul (M, N, K) dimensions order.
   SmallVector<int64_t, 3> mnkOrder = {0, 1, 2};
 
   /// Transpose LHS outer block layout [MB][KB] -> [KB][MB].
-  bool lhsTransposeOuterBlocks = false;
+  bool getLhsTransposeOuterBlocks() const {
+    return mnkPaddedSizesNextMultipleOf.getFlag(1);
+  }
+  void setLhsTransposeOuterBlocks(bool Value) {
+    mnkPaddedSizesNextMultipleOf.setFlag(1, Value);
+  }
 
   /// Transpose LHS inner block layout [mb][kb] -> [kb][mb].
-  bool lhsTransposeInnerBlocks = false;
+  bool getLhsTransposeInnerBlocks() const {
+    return mnkPaddedSizesNextMultipleOf.getFlag(2);
+  }
+  void setLhsTransposeInnerBlocks(bool Value) {
+    mnkPaddedSizesNextMultipleOf.setFlag(2, Value);
+  }
 
   /// Transpose RHS outer block layout [KB][NB] -> [NB][KB].
-  bool rhsTransposeOuterBlocks = true;
+  bool getRhsTransposeOuterBlocks() const {
+    return !mnkPaddedSizesNextMultipleOf.getFlag(3);
+  }
+  void setRhsTransposeOuterBlocks(bool Value) {
+    mnkPaddedSizesNextMultipleOf.setFlag(3, !Value);
+  }
 
   /// Transpose RHS inner block layout [kb][nb] -> [nb][kb].
-  bool rhsTransposeInnerBlocks = true;
+  bool getRhsTransposeInnerBlocks() const {
+    return !scalableBlockFactors.getFlag(0);
+  }
+  void setRhsTransposeInnerBlocks(bool Value) {
+    scalableBlockFactors.setFlag(0, !Value);
+  }
 };
 
 /// Function type which is used to control matmul packing.
diff --git a/mlir/include/mlir/Dialect/Shard/IR/ShardOps.h b/mlir/include/mlir/Dialect/Shard/IR/ShardOps.h
index e4ba0293d398f..fbc92ef951943 100644
--- a/mlir/include/mlir/Dialect/Shard/IR/ShardOps.h
+++ b/mlir/include/mlir/Dialect/Shard/IR/ShardOps.h
@@ -106,8 +106,8 @@ inline bool isReductionLoop(utils::IteratorType iType) {
 }
 
 // Remove empty subarrays of `array` until a minimum lengh of one is reached.
-template <typename T>
-void removeTrailingEmptySubArray(SmallVector<SmallVector<T>> &array) {
+template <typename RangeT>
+void removeTrailingEmptySubArray(RangeT &array) {
   while (array.size() > 1 && array.back().empty())
     array.pop_back();
 }
diff --git a/mlir/include/mlir/Dialect/Shard/Interfaces/ShardingInterface.h b/mlir/include/mlir/Dialect/Shard/Interfaces/ShardingInterface.h
index 46f6ed410ebed..ba9d091e9aa2b 100644
--- a/mlir/include/mlir/Dialect/Shard/Interfaces/ShardingInterface.h
+++ b/mlir/include/mlir/Dialect/Shard/Interfaces/ShardingInterface.h
@@ -13,6 +13,7 @@
 #include "mlir/Dialect/Utils/StructuredOpsUtils.h"
 #include "mlir/IR/Value.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace mlir {
 
@@ -28,20 +29,24 @@ using ShardingArrayRef = ArrayRef<SmallVector<GridAxis>>;
 struct ShardingOption {
   // An array of int array. The sub-array at the i-th position signifies the
   // grid axes the i-th loop will be sharded on.
-  ShardingArray shardingArray = {};
+  llvm::SmallVectorWithFlagsFor<ShardingArray, 1> shardingArray = {};
   FlatSymbolRefAttr grid = nullptr;
   // `empty` being true indicates that no sharding information can be inferred
   // at present. Note that it is different from the case where an operation is
   // not sharded.
-  bool empty = false;
+  bool getEmpty() const { return shardingArray.getFlag(0); }
+  bool setEmpty(bool Value) {
+    shardingArray.setFlag(0, Value);
+    return Value;
+  }
   ShardingOption() = default;
   ShardingOption(ShardingArray shardingArray, FlatSymbolRefAttr grid)
-      : shardingArray(std::move(shardingArray)), grid(grid) {
+      : shardingArray(0, std::move(shardingArray)), grid(grid) {
     assert(this->grid);
   }
   static ShardingOption makeEmpty() {
     auto res = ShardingOption();
-    res.empty = true;
+    res.setEmpty(true);
     return res;
   }
 };
diff --git a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
index b8d278152dc05..3d0eec4384745 100644
--- a/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
+++ b/mlir/include/mlir/Dialect/SparseTensor/Utils/Merger.h
@@ -18,6 +18,7 @@
 #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h"
 #include "mlir/IR/Value.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include <optional>
 
@@ -466,7 +467,7 @@ class Merger {
   }
 
   /// Sets whether the output tensor is sparse or not.
-  void setHasSparseOut(bool s) { hasSparseOut = s; }
+  void setHasSparseOut(bool s) { latSets.setFlag(0, s); }
 
   /// Establishes the two-way map that i <-> <t, lvl, lt>.
   void setLoopDependentTensorLevel(LoopId i, TensorId t, Level lvl,
@@ -627,7 +628,6 @@ class Merger {
   const TensorId syntheticTensor;
   const unsigned numTensors;
   const unsigned numLoops;
-  bool hasSparseOut;
 
   // Below we use `std::vector` for things which have a priori fixed
   // sizes, whereas we use `llvm::SmallVector` for things with variable
@@ -662,7 +662,8 @@ class Merger {
 
   llvm::SmallVector<TensorExp> tensorExps;
   llvm::SmallVector<LatPoint> latPoints;
-  llvm::SmallVector<SmallVector<LatPointId>> latSets;
+  // Flag bit 0 marks a sparse output tensor.
+  llvm::SmallVectorWithFlags<SmallVector<LatPointId>> latSets;
 };
 
 } // namespace sparse_tensor
diff --git a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
index 9f82efb802672..75ef5cbdc6686 100644
--- a/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
+++ b/mlir/include/mlir/Dialect/Tosa/Utils/ConversionUtils.h
@@ -129,7 +129,7 @@ TosaOp createOpAndInferShape(ImplicitLocOpBuilder &builder, Type resultTy,
   // Compute the knowledge based on the inferred type.
   auto inferredKnowledge = ValueKnowledge::getPessimisticValueState();
   inferredKnowledge.dtype = mlir::cast<ShapedType>(resultTy).getElementType();
-  inferredKnowledge.hasRank = predictedShape.hasRank();
+  inferredKnowledge.setHasRank(predictedShape.hasRank());
   if (predictedShape.hasRank()) {
     for (auto dim : predictedShape.getDims()) {
       inferredKnowledge.sizes.push_back(dim);
@@ -139,7 +139,7 @@ TosaOp createOpAndInferShape(ImplicitLocOpBuilder &builder, Type resultTy,
   // Compute the new type based on the joined version.
   auto newKnowledge = ValueKnowledge::join(currentKnowledge, inferredKnowledge);
   Type newTy =
-      newKnowledge.hasRank
+      newKnowledge.hasRank()
           ? Type{mlir::RankedTensorType::get(llvm::ArrayRef(newKnowledge.sizes),
                                              newKnowledge.dtype)}
           : Type{mlir::UnrankedTensorType::get(newKnowledge.dtype)};
diff --git a/mlir/include/mlir/Dialect/Tosa/Utils/ShapeUtils.h b/mlir/include/mlir/Dialect/Tosa/Utils/ShapeUtils.h
index bdacb98710d33..e6a3392f992ae 100644
--- a/mlir/include/mlir/Dialect/Tosa/Utils/ShapeUtils.h
+++ b/mlir/include/mlir/Dialect/Tosa/Utils/ShapeUtils.h
@@ -17,7 +17,7 @@
 #include "mlir/IR/Types.h"
 #include "mlir/Interfaces/InferTypeOpInterface.h"
 #include "llvm/ADT/Sequence.h"
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 namespace mlir {
 namespace tosa {
@@ -33,20 +33,21 @@ namespace tosa {
 struct ValueKnowledge {
   ValueKnowledge() = delete;
   ValueKnowledge(bool hasRank, llvm::ArrayRef<int64_t> newSizes, Type dtype)
-      : hasError(false), hasRank(hasRank), dtype(dtype) {
+      : dtype(dtype) {
+    setHasRank(hasRank);
     sizes.reserve(newSizes.size());
     for (auto size : newSizes)
       sizes.push_back(size);
   }
 
-  operator bool() const { return !hasError; }
+  operator bool() const { return !hasError(); }
 
   // Get the static knowledge intrinsic to `type`.
   static ValueKnowledge getKnowledgeFromType(Type type) {
     ValueKnowledge result = getPessimisticValueState();
     if (auto shapedType = dyn_cast<ShapedType>(type)) {
       if (shapedType.hasRank()) {
-        result.hasRank = true;
+        result.setHasRank(true);
         result.sizes.reserve(shapedType.getRank());
         for (auto dim : shapedType.getShape())
           result.sizes.push_back(dim);
@@ -63,17 +64,19 @@ struct ValueKnowledge {
   }
 
   ShapedTypeComponents getShapedTypeComponents() const {
-    return hasRank ? ShapedTypeComponents(sizes) : ShapedTypeComponents();
+    return hasRank() ? ShapedTypeComponents(sizes) : ShapedTypeComponents();
   }
 
   Type getType() const {
-    if (hasRank)
+    if (hasRank())
       return RankedTensorType::get(llvm::ArrayRef(sizes), dtype);
     return UnrankedTensorType::get(dtype);
   }
 
   bool operator==(const ValueKnowledge &rhs) const {
-    return hasRank == rhs.hasRank && sizes == rhs.sizes && dtype == rhs.dtype;
+    return hasRank() == rhs.hasRank() &&
+           ArrayRef<int64_t>(sizes) == ArrayRef<int64_t>(rhs.sizes) &&
+           dtype == rhs.dtype;
   }
 
   // Given two pieces of static knowledge, calculate conservatively the
@@ -84,33 +87,33 @@ struct ValueKnowledge {
     // knowledge" default-initialized state to a state with more knowledge
     // consistent with lhs and rhs.
     ValueKnowledge result = getPessimisticValueState();
-    result.hasError = true;
+    result.setHasError(true);
 
     if (!lhs || !rhs || lhs.dtype != rhs.dtype)
       return result;
 
-    result.hasError = false;
+    result.setHasError(false);
     result.dtype = lhs.dtype;
 
-    if (!lhs.hasRank && !rhs.hasRank)
+    if (!lhs.hasRank() && !rhs.hasRank())
       return result;
 
-    if (!rhs.hasRank) {
-      result.hasRank = true;
-      result.sizes = lhs.sizes;
+    if (!rhs.hasRank()) {
+      result.setHasRank(true);
+      result.sizes.assign(lhs.sizes.begin(), lhs.sizes.end());
       return result;
     }
 
-    if (!lhs.hasRank) {
-      result.hasRank = true;
-      result.sizes = rhs.sizes;
+    if (!lhs.hasRank()) {
+      result.setHasRank(true);
+      result.sizes.assign(rhs.sizes.begin(), rhs.sizes.end());
       return result;
     }
 
     if (lhs.sizes.size() != rhs.sizes.size())
       return result;
 
-    result.hasRank = true;
+    result.setHasRank(true);
     result.sizes.resize(lhs.sizes.size(), ShapedType::kDynamic);
     for (auto i : llvm::seq<unsigned>(0, result.sizes.size())) {
       int64_t lhsSize = lhs.sizes[i];
@@ -123,7 +126,7 @@ struct ValueKnowledge {
       } else if (lhsSize == rhsSize) {
         resultSize = lhsSize;
       } else {
-        result.hasError = true;
+        result.setHasError(true);
       }
     }
 
@@ -136,25 +139,25 @@ struct ValueKnowledge {
   static ValueKnowledge meet(const ValueKnowledge &lhs,
                              const ValueKnowledge &rhs) {
     ValueKnowledge result = getPessimisticValueState();
-    result.hasError = true;
+    result.setHasError(true);
 
     if (!lhs || !rhs || lhs.dtype != rhs.dtype)
       return result;
 
-    result.hasError = false;
+    result.setHasError(false);
     result.dtype = lhs.dtype;
 
-    if (!lhs.hasRank || !rhs.hasRank) {
-      result.hasRank = false;
+    if (!lhs.hasRank() || !rhs.hasRank()) {
+      result.setHasRank(false);
       return result;
     }
 
     if (lhs.sizes.size() != rhs.sizes.size()) {
-      result.hasRank = false;
+      result.setHasRank(false);
       return result;
     }
 
-    result.hasRank = true;
+    result.setHasRank(true);
     result.sizes.resize(lhs.sizes.size(), ShapedType::kDynamic);
     for (int i = 0, e = lhs.sizes.size(); i < e; i++) {
       if (lhs.sizes[i] == rhs.sizes[i]) {
@@ -166,12 +169,17 @@ struct ValueKnowledge {
   }
 
   // Whether the value information has an error.
-  bool hasError;
+  bool hasError() const { return sizes.getFlag(0); }
+  void setHasError(bool value) { sizes.setFlag(0, value); }
   // Whether the value has known rank.
-  bool hasRank;
+  bool hasRank() const { return sizes.getFlag(1); }
+  void setHasRank(bool value) { sizes.setFlag(1, value); }
   // If `hasRank`, the sizes along each rank. Unknown sizes are represented as
   // `ShapedType::kDynamic`.
-  llvm::SmallVector<int64_t> sizes;
+  llvm::SmallVectorWithFlags<
+      int64_t, llvm::CalculateSmallVectorDefaultInlinedElements<int64_t>::value,
+      2>
+      sizes;
   // The dtype of a tensor.
   // This is equal to nullptr if we don't know that it is a specific concrete
   // type.
diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
index 8fe94ebcf658f..d6a963d4ebbbe 100644
--- a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
+++ b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h
@@ -14,6 +14,7 @@
 #include "mlir/Support/LLVM.h"
 #include "mlir/Support/TypeID.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include <optional>
 
@@ -129,7 +130,7 @@ class TransformDialectExtension
 
     // Only load generated dialects if the user intends to apply
     // transformations specified by the extension.
-    if (!buildOnly)
+    if (!isBuildOnly())
       for (const DialectLoader &loader : generatedDialectLoaders)
         loader(context);
 
@@ -143,7 +144,8 @@ class TransformDialectExtension
   /// Extension constructor. The argument indicates whether to skip generated
   /// dialects when applying the extension.
   explicit TransformDialectExtension(bool buildOnly = false)
-      : buildOnly(buildOnly) {
+      : generatedDialectLoaders(
+            decltype(generatedDialectLoaders)::withFlags(unsigned(buildOnly))) {
     static_cast<DerivedTy *>(this)->init();
   }
 
@@ -254,10 +256,10 @@ class TransformDialectExtension
 
   /// Callbacks loading the generated dialects, i.e. the dialects produced when
   /// applying the transformations.
-  SmallVector<DialectLoader> generatedDialectLoaders;
+  llvm::SmallVectorWithFlags<DialectLoader> generatedDialectLoaders;
 
   /// Indicates that the extension is in build-only mode.
-  bool buildOnly;
+  bool isBuildOnly() const { return generatedDialectLoaders.getFlag(0); }
 };
 
 template <typename OpTy>
diff --git a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
index 5bd71d68d253a..63af8ca16af3c 100644
--- a/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
+++ b/mlir/include/mlir/ExecutionEngine/ExecutionEngine.h
@@ -14,6 +14,7 @@
 #define MLIR_EXECUTIONENGINE_EXECUTIONENGINE_H_
 
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
@@ -256,9 +257,10 @@ class ExecutionEngine {
 
   /// Destroy functions in the libraries loaded by the ExecutionEngine that are
   /// called when this ExecutionEngine is destructed.
-  SmallVector<LibraryDestroyFn> destroyFns;
+  llvm::SmallVectorWithFlags<LibraryDestroyFn> destroyFns;
 
-  bool isInitialized = false;
+  bool getIsInitialized() const { return destroyFns.getFlag(0); }
+  void setIsInitialized(bool Value) { destroyFns.setFlag(0, Value); }
 };
 
 } // namespace mlir
diff --git a/mlir/include/mlir/Interfaces/InferTypeOpInterface.h b/mlir/include/mlir/Interfaces/InferTypeOpInterface.h
index 1bfb66e681d8d..e89cc11978941 100644
--- a/mlir/include/mlir/Interfaces/InferTypeOpInterface.h
+++ b/mlir/include/mlir/Interfaces/InferTypeOpInterface.h
@@ -23,6 +23,8 @@
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
+
 namespace mlir {
 
 class ShapedTypeComponents;
@@ -95,6 +97,9 @@ class ShapeAdaptor {
   void dump() const;
 
 private:
+  template <typename ShapeStorageT>
+  void getDimsImpl(ShapeStorageT &res) const;
+
   // Union storing either ShapedTypeComponents, ShapedType (stored as Type and
   // casted), or DenseIntElementsAttribute (stored as Atrtribute).
   PointerUnion<ShapedTypeComponents *, Type, Attribute> val = nullptr;
@@ -110,45 +115,51 @@ class ShapeAdaptor {
 /// Used by ShapedType type inferences.
 class ShapedTypeComponents {
   /// Internal storage type for shape.
-  using ShapeStorageT = SmallVector<int64_t, 3>;
+  using ShapeStorageT = llvm::SmallVectorWithFlags<int64_t, 3>;
 
 public:
   /// Default construction is an unranked shape.
   ShapedTypeComponents() : elementType(nullptr), attr(nullptr) {};
   ShapedTypeComponents(Type elementType)
-      : elementType(elementType), attr(nullptr), ranked(false) {}
+      : elementType(elementType), attr(nullptr) {}
   ShapedTypeComponents(ShapedType shapedType) : attr(nullptr) {
-    ranked = shapedType.hasRank();
+    dims.setFlag(0, shapedType.hasRank());
     elementType = shapedType.getElementType();
-    if (ranked)
-      dims = llvm::to_vector<4>(shapedType.getShape());
+    if (hasRank()) {
+      ArrayRef<int64_t> shape = shapedType.getShape();
+      dims.assign(shape.begin(), shape.end());
+    }
   }
   ShapedTypeComponents(ShapeAdaptor adaptor) : attr(nullptr) {
-    ranked = adaptor.hasRank();
+    dims.setFlag(0, adaptor.hasRank());
     elementType = adaptor.getElementType();
-    if (ranked)
+    if (hasRank())
       adaptor.getDims(*this);
   }
   template <typename Arg, typename = std::enable_if_t<
                               std::is_constructible<ShapeStorageT, Arg>::value>>
   ShapedTypeComponents(Arg &&arg, Type elementType = nullptr,
                        Attribute attr = nullptr)
-      : dims(std::forward<Arg>(arg)), elementType(elementType), attr(attr),
-        ranked(true) {}
+      : dims(std::forward<Arg>(arg)), elementType(elementType), attr(attr) {
+    dims.setFlag(0, true);
+  }
   ShapedTypeComponents(ArrayRef<int64_t> vec, Type elementType = nullptr,
                        Attribute attr = nullptr)
-      : dims(vec.begin(), vec.end()), elementType(elementType), attr(attr),
-        ranked(true) {}
+      : dims(1, vec.begin(), vec.end()), elementType(elementType), attr(attr) {}
+
+  ShapedTypeComponents(SmallVectorImpl<int64_t> &&vec,
+                       Type elementType = nullptr, Attribute attr = nullptr)
+      : dims(1, std::move(vec)), elementType(elementType), attr(attr) {}
 
   /// Return the dimensions of the shape.
   /// Requires: shape is ranked.
   ArrayRef<int64_t> getDims() const {
-    assert(ranked && "requires ranked shape");
+    assert(hasRank() && "requires ranked shape");
     return dims;
   }
 
   /// Return whether the shape has a rank.
-  bool hasRank() const { return ranked; };
+  bool hasRank() const { return dims.getFlag(0); };
 
   /// Return the element type component.
   Type getElementType() const { return elementType; };
@@ -162,7 +173,6 @@ class ShapedTypeComponents {
   ShapeStorageT dims;
   Type elementType;
   Attribute attr;
-  bool ranked{false};
 };
 
 /// Range of values and shapes (corresponding effectively to Shapes dialect's
diff --git a/mlir/include/mlir/Support/CyclicReplacerCache.h b/mlir/include/mlir/Support/CyclicReplacerCache.h
index 786bc49040d7e..dc14445eb4fc1 100644
--- a/mlir/include/mlir/Support/CyclicReplacerCache.h
+++ b/mlir/include/mlir/Support/CyclicReplacerCache.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <functional>
 #include <optional>
 #include <set>
@@ -139,19 +140,20 @@ class CyclicReplacerCache {
   };
   /// Every element currently in the progress of being replaced pushes a frame
   /// onto this stack.
-  llvm::SmallVector<ReplacementFrame> replacementStack;
+  llvm::SmallVectorWithFlags<ReplacementFrame> replacementStack;
   /// Maps from each input element to its indices on the replacement stack.
   llvm::DenseMap<InT, llvm::SmallVector<size_t, 2>> cyclicElementFrame;
   /// If set to true, we are currently asking an element to break a cycle. No
   /// more recursive invocations is allowed while this is true (the replacement
   /// stack can no longer grow).
-  bool resolvingCycle = false;
+  bool isResolvingCycle() const { return replacementStack.getFlag(0); }
+  void setResolvingCycle(bool value) { replacementStack.setFlag(0, value); }
 };
 
 template <typename InT, typename OutT>
 typename CyclicReplacerCache<InT, OutT>::CacheEntry
 CyclicReplacerCache<InT, OutT>::lookupOrInit(InT element) {
-  assert(!resolvingCycle &&
+  assert(!isResolvingCycle() &&
          "illegal recursive invocation while breaking cycle");
 
   if (auto it = standaloneCache.find(element); it != standaloneCache.end())
@@ -168,9 +170,9 @@ CyclicReplacerCache<InT, OutT>::lookupOrInit(InT element) {
   auto [it, inserted] = cyclicElementFrame.try_emplace(element);
   if (!inserted) {
     // This is a repeat of a known element. Try to break cycle here.
-    resolvingCycle = true;
+    setResolvingCycle(true);
     std::optional<OutT> result = cycleBreaker(element);
-    resolvingCycle = false;
+    setResolvingCycle(false);
     if (result) {
       // Cycle was broken.
       size_t dependentFrame = it->second.back();
diff --git a/mlir/include/mlir/TableGen/Class.h b/mlir/include/mlir/TableGen/Class.h
index e6bedc7cc896d..4451028b17f52 100644
--- a/mlir/include/mlir/TableGen/Class.h
+++ b/mlir/include/mlir/TableGen/Class.h
@@ -28,6 +28,7 @@
 #include "mlir/TableGen/CodeGenHelpers.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
@@ -675,7 +676,8 @@ class Class {
   template <typename NameT,
             typename = std::enable_if_t<!std::is_same<NameT, Class>::value>>
   Class(NameT &&name, bool isStruct = false)
-      : className(stringify(std::forward<NameT>(name))), isStruct(isStruct) {}
+      : className(stringify(std::forward<NameT>(name))),
+        fields(decltype(fields)::withFlags(unsigned(isStruct))) {}
 
   /// Add a new constructor to this class and prune and constructors made
   /// redundant by it. Returns null if the constructor was not added. Else,
@@ -886,9 +888,10 @@ class Class {
   /// The pending list of methods and constructors.
   std::vector<std::unique_ptr<Method>> methods;
   /// The pending list of private class fields.
-  SmallVector<Field> fields;
+  // Flag bit 0 selects a struct declaration.
+  llvm::SmallVectorWithFlags<Field> fields;
   /// Whether this is a `class` or a `struct`.
-  bool isStruct;
+  bool isStructDeclaration() const { return fields.getFlag(0); }
 
   /// A list of declarations in the class, emitted in order.
   std::vector<std::unique_ptr<ClassDeclaration>> declarations;
diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h
index bb36c077708e9..1d9b251de91b3 100644
--- a/mlir/include/mlir/TableGen/Operator.h
+++ b/mlir/include/mlir/TableGen/Operator.h
@@ -25,6 +25,7 @@
 #include "mlir/TableGen/Type.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/SMLoc.h"
@@ -335,7 +336,7 @@ class Operator {
   void print(llvm::raw_ostream &os) const;
 
   /// Return whether all the result types are known.
-  bool allResultTypesKnown() const { return allResultsHaveKnownTypes; };
+  bool allResultTypesKnown() const { return builders.getFlag(0); };
 
   ///  Return all arguments or type constraints with same type as result[index].
   /// Requires: all result types are known.
@@ -428,7 +429,8 @@ class Operator {
   SmallVector<OperandAttrOrProp, 4> attrPropOrOperandMapping;
 
   /// The builders of this operator.
-  SmallVector<Builder> builders;
+  // Flag bit 0 records whether every result type can be inferred.
+  llvm::SmallVectorWithFlags<Builder> builders;
 
   /// The number of native attributes stored in the leading positions of
   /// `attributes`.
@@ -436,9 +438,6 @@ class Operator {
 
   /// The TableGen definition of this op.
   const llvm::Record &def;
-
-  /// Whether the type of all results are known.
-  bool allResultsHaveKnownTypes;
 };
 
 } // namespace tblgen
diff --git a/mlir/include/mlir/Tools/PDLL/ODS/Operation.h b/mlir/include/mlir/Tools/PDLL/ODS/Operation.h
index e49db88ef9c93..0933eff9d00f2 100644
--- a/mlir/include/mlir/Tools/PDLL/ODS/Operation.h
+++ b/mlir/include/mlir/Tools/PDLL/ODS/Operation.h
@@ -9,6 +9,7 @@
 #ifndef MLIR_TOOLS_PDLL_ODS_OPERATION_H_
 #define MLIR_TOOLS_PDLL_ODS_OPERATION_H_
 
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include <string>
 
 #include "mlir/Support/LLVM.h"
@@ -168,7 +169,7 @@ class Operation {
   ArrayRef<OperandOrResult> getResults() const { return results; }
 
   /// Return if the operation is known to support result type inferrence.
-  bool hasResultTypeInferrence() const { return supportsTypeInferrence; }
+  bool hasResultTypeInferrence() const { return getSupportsTypeInferrence(); }
 
 private:
   Operation(StringRef name, StringRef summary, StringRef desc,
@@ -185,7 +186,8 @@ class Operation {
   std::string nativeClassName;
 
   /// Flag indicating if the operation is known to support type inferrence.
-  bool supportsTypeInferrence;
+  bool getSupportsTypeInferrence() const { return attributes.getFlag(0); }
+  void setSupportsTypeInferrence(bool Value) { attributes.setFlag(0, Value); }
 
   /// The source location of this operation.
   SMRange location;
@@ -197,7 +199,7 @@ class Operation {
   SmallVector<OperandOrResult> results;
 
   /// The attributes of the operation.
-  SmallVector<Attribute> attributes;
+  llvm::SmallVectorWithFlags<Attribute> attributes;
 
   /// Allow access to the private constructor.
   friend class Dialect;
diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp
index f2e6f83e99e57..0db359360060d 100644
--- a/mlir/lib/Analysis/Presburger/Simplex.cpp
+++ b/mlir/lib/Analysis/Presburger/Simplex.cpp
@@ -48,8 +48,8 @@ scaleAndAddForAssert(ArrayRef<DynamicAPInt> a, const DynamicAPInt &scale,
 }
 
 SimplexBase::SimplexBase(unsigned nVar, bool mustUseBigM)
-    : usingBigM(mustUseBigM), nRedundant(0), nSymbol(0),
-      tableau(0, getNumFixedCols() + nVar), empty(false) {
+    : nRedundant(0), nSymbol(0), tableau(0, (mustUseBigM ? 3u : 2u) + nVar),
+      var(decltype(this->var)::withFlags(unsigned(mustUseBigM))) {
   var.reserve(nVar);
   colUnknown.reserve(nVar + 1);
   colUnknown.insert(colUnknown.begin(), getNumFixedCols(), nullIndex);
@@ -127,7 +127,7 @@ unsigned SimplexBase::addRow(ArrayRef<DynamicAPInt> coeffs,
 
   unsigned newRow = addZeroRow(makeRestricted);
   tableau(newRow, 1) = coeffs.back();
-  if (usingBigM) {
+  if (getUsingBigM()) {
     // When the lexicographic pivot rule is used, instead of the variables
     //
     // x, y, z ...
@@ -564,7 +564,7 @@ SymbolicLexOpt SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
   while (level > 0) {
     assert(level >= stack.size());
     if (level > stack.size()) {
-      if (empty || domainSimplex.findIntegerLexMin().isEmpty()) {
+      if (getEmpty() || domainSimplex.findIntegerLexMin().isEmpty()) {
         // No integer points; return.
         --level;
         continue;
@@ -703,7 +703,7 @@ std::optional<unsigned> LexSimplex::maybeGetViolatedRow() const {
 /// orientation, which always succeeds unless the constraints have no solution
 /// in which case we just give up and return.
 LogicalResult LexSimplex::restoreRationalConsistency() {
-  if (empty)
+  if (getEmpty())
     return failure();
   while (std::optional<unsigned> maybeViolatedRow = maybeGetViolatedRow())
     if (moveRowUnknownToColumn(*maybeViolatedRow).failed())
@@ -1066,7 +1066,7 @@ std::optional<unsigned> Simplex::findPivotRow(std::optional<unsigned> skipRow,
   return retRow;
 }
 
-bool SimplexBase::isEmpty() const { return empty; }
+bool SimplexBase::isEmpty() const { return getEmpty(); }
 
 void SimplexBase::swapRows(unsigned i, unsigned j) {
   if (i == j)
@@ -1093,10 +1093,10 @@ void SimplexBase::markEmpty() {
   // If the set is already empty, then we shouldn't add another UnmarkEmpty log
   // entry, since in that case the Simplex will be erroneously marked as
   // non-empty when rolling back past this point.
-  if (empty)
+  if (getEmpty())
     return;
   undoLog.emplace_back(UndoLogEntry::UnmarkEmpty);
-  empty = true;
+  setEmpty(true);
 }
 
 /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
@@ -1253,7 +1253,7 @@ void SimplexBase::undo(UndoLogEntry entry) {
     var.pop_back();
     colUnknown.pop_back();
   } else if (entry == UndoLogEntry::UnmarkEmpty) {
-    empty = false;
+    setEmpty(false);
   } else if (entry == UndoLogEntry::UnmarkLastRedundant) {
     nRedundant--;
   } else if (entry == UndoLogEntry::RestoreBasis) {
@@ -1362,7 +1362,7 @@ MaybeOptimum<Fraction> Simplex::computeRowOptimum(Direction direction,
 /// or std::nullopt if it is unbounded.
 MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
                                                ArrayRef<DynamicAPInt> coeffs) {
-  if (empty)
+  if (getEmpty())
     return OptimumKind::Empty;
 
   SimplexRollbackScopeExit scopeExit(*this);
@@ -1373,7 +1373,7 @@ MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
 
 MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
                                                Unknown &u) {
-  if (empty)
+  if (getEmpty())
     return OptimumKind::Empty;
   if (u.orientation == Orientation::Column) {
     unsigned column = u.pos;
@@ -1396,8 +1396,9 @@ MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
 }
 
 bool Simplex::isBoundedAlongConstraint(unsigned constraintIndex) {
-  assert(!empty && "It is not meaningful to ask whether a direction is bounded "
-                   "in an empty set.");
+  assert(!getEmpty() &&
+         "It is not meaningful to ask whether a direction is bounded "
+         "in an empty set.");
   // The constraint's perpendicular is already bounded below, since it is a
   // constraint. If it is also bounded above, we can return true.
   return computeOptimum(Direction::Up, con[constraintIndex]).isBounded();
@@ -1428,7 +1429,7 @@ void Simplex::markRowRedundant(Unknown &u) {
 void Simplex::detectRedundant(unsigned offset, unsigned count) {
   assert(offset + count <= con.size() && "invalid range!");
   // It is not meaningful to talk about redundancy for empty sets.
-  if (empty)
+  if (getEmpty())
     return;
 
   // Iterate through the constraints and check for each one if it can attain
@@ -1468,7 +1469,7 @@ void Simplex::detectRedundant(unsigned offset, unsigned count) {
 }
 
 bool Simplex::isUnbounded() {
-  if (empty)
+  if (getEmpty())
     return false;
 
   SmallVector<DynamicAPInt, 8> dir(var.size() + 1);
@@ -1501,7 +1502,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) {
   Simplex result(numVar);
 
   result.tableau.reserveRows(numCon);
-  result.empty = a.empty || b.empty;
+  result.setEmpty(a.getEmpty() || b.getEmpty());
 
   auto concat = [](ArrayRef<Unknown> v, ArrayRef<Unknown> w) {
     SmallVector<Unknown, 8> result;
@@ -1511,7 +1512,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) {
     return result;
   };
   result.con = concat(a.con, b.con);
-  result.var = concat(a.var, b.var);
+  result.var.assign(concat(a.var, b.var));
 
   auto indexFromBIndex = [&](int index) {
     return index >= 0 ? a.getNumVariables() + index
@@ -1568,7 +1569,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) {
 }
 
 std::optional<SmallVector<Fraction, 8>> Simplex::getRationalSample() const {
-  if (empty)
+  if (getEmpty())
     return {};
 
   SmallVector<Fraction, 8> sample;
@@ -1593,7 +1594,7 @@ void LexSimplexBase::addInequality(ArrayRef<DynamicAPInt> coeffs) {
 }
 
 MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
-  if (empty)
+  if (getEmpty())
     return OptimumKind::Empty;
 
   SmallVector<Fraction, 8> sample;
@@ -1614,7 +1615,7 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
     // If the variable is in row position, its sample value is the
     // entry in the constant column divided by the denominator.
     DynamicAPInt denom = tableau(u.pos, 0);
-    if (usingBigM)
+    if (getUsingBigM())
       if (tableau(u.pos, 2) != denom)
         return OptimumKind::Unbounded;
     sample.emplace_back(tableau(u.pos, 1), denom);
@@ -1625,7 +1626,7 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
 std::optional<SmallVector<DynamicAPInt, 8>>
 Simplex::getSamplePointIfIntegral() const {
   // If the tableau is empty, no sample point exists.
-  if (empty)
+  if (getEmpty())
     return {};
 
   // The value will always exist since the Simplex is non-empty.
@@ -1994,7 +1995,7 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) {
 /// To avoid potentially arbitrarily large recursion depths leading to stack
 /// overflows, this algorithm is implemented iteratively.
 std::optional<SmallVector<DynamicAPInt, 8>> Simplex::findIntegerSample() {
-  if (empty)
+  if (getEmpty())
     return {};
 
   unsigned nDims = var.size();
@@ -2127,7 +2128,7 @@ bool Simplex::isFlatAlong(ArrayRef<DynamicAPInt> coeffs) {
 
 void SimplexBase::print(raw_ostream &os) const {
   os << "rows = " << getNumRows() << ", columns = " << getNumColumns() << "\n";
-  if (empty)
+  if (getEmpty())
     os << "Simplex marked empty!\n";
   os << "var: ";
   for (unsigned i = 0; i < var.size(); ++i) {
@@ -2214,7 +2215,7 @@ Simplex::IneqType Simplex::findIneqType(ArrayRef<DynamicAPInt> coeffs) {
 /// Checks whether the type of the inequality with coefficients `coeffs`
 /// is Redundant.
 bool Simplex::isRedundantInequality(ArrayRef<DynamicAPInt> coeffs) {
-  assert(!empty &&
+  assert(!getEmpty() &&
          "It is not meaningful to ask about redundancy in an empty set!");
   return findIneqType(coeffs) == IneqType::Redundant;
 }
@@ -2224,7 +2225,7 @@ bool Simplex::isRedundantInequality(ArrayRef<DynamicAPInt> coeffs) {
 /// always zero under the existing constraints. `coeffs` is always zero
 /// when the minimum and maximum value that `coeffs` can take are both zero.
 bool Simplex::isRedundantEquality(ArrayRef<DynamicAPInt> coeffs) {
-  assert(!empty &&
+  assert(!getEmpty() &&
          "It is not meaningful to ask about redundancy in an empty set!");
   MaybeOptimum<Fraction> minimum = computeOptimum(Direction::Down, coeffs);
   MaybeOptimum<Fraction> maximum = computeOptimum(Direction::Up, coeffs);
diff --git a/mlir/lib/AsmParser/AffineParser.cpp b/mlir/lib/AsmParser/AffineParser.cpp
index 405970d4fb15e..99d0c4fad02d2 100644
--- a/mlir/lib/AsmParser/AffineParser.cpp
+++ b/mlir/lib/AsmParser/AffineParser.cpp
@@ -19,6 +19,7 @@
 #include "mlir/IR/IntegerSet.h"
 #include "mlir/IR/OpImplementation.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
@@ -64,8 +65,9 @@ class AffineParser : public Parser {
           nullptr,
       function_ref<void(bool, OpAsmParser::UnresolvedOperand)> addOperand =
           nullptr)
-      : Parser(state), allowParsingSSAIds(allowParsingSSAIds),
-        parseElement(parseElement), addOperand(addOperand) {}
+      : Parser(state), parseElement(parseElement), addOperand(addOperand),
+        dimsAndSymbols(decltype(this->dimsAndSymbols)::withFlags(
+            unsigned(allowParsingSSAIds))) {}
 
   ParseResult parseAffineMapRange(unsigned numDims, unsigned numSymbols,
                                   AffineMap &result);
@@ -110,12 +112,14 @@ class AffineParser : public Parser {
   AffineExpr parseAffineConstraint(bool *isEq);
 
 private:
-  bool allowParsingSSAIds;
+  bool getAllowParsingSSAIds() const { return dimsAndSymbols.getFlag(0); }
+  void setAllowParsingSSAIds(bool Value) { dimsAndSymbols.setFlag(0, Value); }
   function_ref<FailureOr<OpAsmParser::UnresolvedOperand>()> parseElement;
   function_ref<void(bool, OpAsmParser::UnresolvedOperand)> addOperand;
   unsigned numDimOperands = 0;
   unsigned numSymbolOperands = 0;
-  SmallVector<std::pair<std::pair<StringRef, unsigned>, AffineExpr>, 4>
+  llvm::SmallVectorWithFlags<
+      std::pair<std::pair<StringRef, unsigned>, AffineExpr>, 4>
       dimsAndSymbols;
 };
 } // namespace
@@ -313,7 +317,7 @@ AffineExpr AffineParser::parseBareIdExpr() {
 
 /// Parse an SSA id which may appear in an affine expression.
 AffineExpr AffineParser::parseSSAIdExpr(bool isSymbol) {
-  if (!allowParsingSSAIds)
+  if (!getAllowParsingSSAIds())
     return emitWrongTokenError("unexpected ssa identifier"), nullptr;
   if (getToken().isNot(Token::percent_identifier))
     return emitWrongTokenError("expected ssa identifier"), nullptr;
diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index 6634d1d784a1e..7438dcaa41193 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -891,20 +891,24 @@ class AttrTypeReader {
 
   LogicalResult readAttribute(uint64_t index, Attribute &result,
                               uint64_t depth = 0) {
-    return readEntry(attributes, index, result, "attribute", depth);
+    return readEntry(MutableArrayRef(attributes.data(), attributes.size()),
+                     index, result, "attribute", depth);
   }
 
   LogicalResult readType(uint64_t index, Type &result, uint64_t depth = 0) {
-    return readEntry(types, index, result, "type", depth);
+    return readEntry(MutableArrayRef(types.data(), types.size()), index, result,
+                     "type", depth);
   }
 
   /// Resolve the attribute or type at the given index. Returns nullptr on
   /// failure.
   Attribute resolveAttribute(size_t index, uint64_t depth = 0) {
-    return resolveEntry(attributes, index, "Attribute", depth);
+    return resolveEntry(MutableArrayRef(attributes.data(), attributes.size()),
+                        index, "Attribute", depth);
   }
   Type resolveType(size_t index, uint64_t depth = 0) {
-    return resolveEntry(types, index, "Type", depth);
+    return resolveEntry(MutableArrayRef(types.data(), types.size()), index,
+                        "Type", depth);
   }
 
   Attribute getAttributeOrSentinel(size_t index) {
@@ -966,18 +970,18 @@ class AttrTypeReader {
   }
 
   /// Whether currently resolving.
-  bool isResolving() const { return resolving; }
+  bool isResolving() const { return getResolving(); }
 
 private:
   /// Resolve the given entry at `index`.
   template <typename T>
-  T resolveEntry(SmallVectorImpl<Entry<T>> &entries, uint64_t index,
+  T resolveEntry(MutableArrayRef<Entry<T>> entries, uint64_t index,
                  StringRef entryType, uint64_t depth = 0);
 
   /// Read the entry at the given index, returning failure if the entry is not
   /// yet resolved.
   template <typename T>
-  LogicalResult readEntry(SmallVectorImpl<Entry<T>> &entries, uint64_t index,
+  LogicalResult readEntry(MutableArrayRef<Entry<T>> entries, uint64_t index,
                           T &result, StringRef entryType, uint64_t depth);
 
   /// Parse an entry using the given reader that was encoded using a custom
@@ -1007,7 +1011,7 @@ class AttrTypeReader {
 
   /// The set of attribute and type entries.
   SmallVector<AttrEntry> attributes;
-  SmallVector<TypeEntry> types;
+  llvm::SmallVectorWithFlags<TypeEntry> types;
 
   /// A location used for error emission.
   Location fileLoc;
@@ -1025,7 +1029,8 @@ class AttrTypeReader {
   std::vector<std::pair<uint64_t, EntryKind>> deferredWorklist;
 
   /// Flag indicating if we are currently resolving an attribute or type.
-  bool resolving = false;
+  bool getResolving() const { return types.getFlag(0); }
+  void setResolving(bool Value) { types.setFlag(0, Value); }
 };
 
 class DialectReader : public DialectBytecodeReader {
@@ -1357,7 +1362,9 @@ LogicalResult AttrTypeReader::initialize(
   };
 
   // Process each of the attributes, and then the types.
-  if (failed(parseEntries(attributes)) || failed(parseEntries(types)))
+  if (failed(parseEntries(
+          MutableArrayRef(attributes.data(), attributes.size()))) ||
+      failed(parseEntries(MutableArrayRef(types.data(), types.size()))))
     return failure();
 
   // Ensure that we read everything from the section.
@@ -1370,12 +1377,12 @@ LogicalResult AttrTypeReader::initialize(
 }
 
 template <typename T>
-T AttrTypeReader::resolveEntry(SmallVectorImpl<Entry<T>> &entries,
+T AttrTypeReader::resolveEntry(MutableArrayRef<Entry<T>> entries,
                                uint64_t index, StringRef entryType,
                                uint64_t depth) {
-  bool oldResolving = resolving;
-  resolving = true;
-  llvm::scope_exit restoreResolving([&]() { resolving = oldResolving; });
+  bool oldResolving = getResolving();
+  setResolving(true);
+  llvm::scope_exit restoreResolving([&]() { setResolving(oldResolving); });
 
   if (index >= entries.size()) {
     emitError(fileLoc) << "invalid " << entryType << " index: " << index;
@@ -1460,7 +1467,7 @@ T AttrTypeReader::resolveEntry(SmallVectorImpl<Entry<T>> &entries,
 }
 
 template <typename T>
-LogicalResult AttrTypeReader::readEntry(SmallVectorImpl<Entry<T>> &entries,
+LogicalResult AttrTypeReader::readEntry(MutableArrayRef<Entry<T>> entries,
                                         uint64_t index, T &result,
                                         StringRef entryType, uint64_t depth) {
   if (index >= entries.size())
@@ -1595,9 +1602,10 @@ class mlir::BytecodeReader::Impl {
   Impl(Location fileLoc, const ParserConfig &config, bool lazyLoading,
        llvm::MemoryBufferRef buffer,
        const std::shared_ptr<llvm::SourceMgr> &bufferOwnerRef)
-      : config(config), fileLoc(fileLoc), lazyLoading(lazyLoading),
+      : config(config), fileLoc(fileLoc),
         attrTypeReader(stringReader, resourceReader, dialectsMap, version,
                        fileLoc, config),
+        dialects(decltype(this->dialects)::withFlags(unsigned(lazyLoading))),
         // Use the builtin unrealized conversion cast operation to represent
         // forward references to values that aren't yet defined.
         forwardRefOpState(UnknownLoc::get(config.getContext()),
@@ -1745,7 +1753,8 @@ class mlir::BytecodeReader::Impl {
     RegionReadState(MutableArrayRef<Region> regions, EncodingReader *reader,
                     bool isIsolatedFromAbove)
         : curRegion(regions.begin()), endRegion(regions.end()), reader(reader),
-          isIsolatedFromAbove(isIsolatedFromAbove) {}
+          curBlocks(decltype(this->curBlocks)::withFlags(
+              unsigned(isIsolatedFromAbove))) {}
 
     /// The current regions being read.
     MutableArrayRef<Region>::iterator curRegion, endRegion;
@@ -1760,7 +1769,7 @@ class mlir::BytecodeReader::Impl {
     unsigned numValues = 0;
 
     /// The current blocks of the region being read.
-    SmallVector<Block *> curBlocks;
+    llvm::SmallVectorWithFlags<Block *> curBlocks;
     Region::iterator curBlock = {};
 
     /// The number of operations remaining to be read from the current block
@@ -1768,7 +1777,8 @@ class mlir::BytecodeReader::Impl {
     uint64_t numOpsRemaining = 0;
 
     /// A flag indicating if the regions being read are isolated from above.
-    bool isIsolatedFromAbove = false;
+    bool getIsIsolatedFromAbove() const { return curBlocks.getFlag(0); }
+    void setIsIsolatedFromAbove(bool Value) { curBlocks.setFlag(0, Value); }
   };
 
   LogicalResult parseIRSection(ArrayRef<uint8_t> sectionData, Block *block);
@@ -1867,7 +1877,8 @@ class mlir::BytecodeReader::Impl {
   Location fileLoc;
 
   /// Flag that indicates if lazyloading is enabled.
-  bool lazyLoading;
+  bool getLazyLoading() const { return dialects.getFlag(0); }
+  void setLazyLoading(bool Value) { dialects.setFlag(0, Value); }
 
   /// Keep track of operations that have been lazy loaded (their regions haven't
   /// been materialized), along with the `RegionReadState` that allows to
@@ -1886,7 +1897,7 @@ class mlir::BytecodeReader::Impl {
   StringRef producer;
 
   /// The table of IR units referenced within the bytecode file.
-  SmallVector<std::unique_ptr<BytecodeDialect>> dialects;
+  llvm::SmallVectorWithFlags<std::unique_ptr<BytecodeDialect>> dialects;
   llvm::StringMap<BytecodeDialect *> dialectsMap;
   SmallVector<BytecodeOperationName> opNames;
 
@@ -2033,7 +2044,7 @@ LogicalResult BytecodeReader::Impl::parseVersion(EncodingReader &reader) {
   }
   // Override any request to lazy-load if the bytecode version is too old.
   if (version < bytecode::kLazyLoading)
-    lazyLoading = false;
+    setLazyLoading(false);
   return success();
 }
 
@@ -2514,7 +2525,8 @@ BytecodeReader::Impl::parseRegions(std::vector<RegionReadState> &regionStack,
 
             // If the user has a callback set, they have the opportunity to
             // control lazyloading as we go.
-            if (lazyLoading && (!lazyOpsCallback || !lazyOpsCallback(*op))) {
+            if (getLazyLoading() &&
+                (!lazyOpsCallback || !lazyOpsCallback(*op))) {
               lazyLoadableOps.emplace_back(*op, std::move(childState));
               lazyLoadableOpsMap.try_emplace(*op,
                                              std::prev(lazyLoadableOps.end()));
@@ -2544,7 +2556,7 @@ BytecodeReader::Impl::parseRegions(std::vector<RegionReadState> &regionStack,
 
   // When the regions have been fully parsed, pop them off of the read stack. If
   // the regions were isolated from above, we also pop the last value scope.
-  if (readState.isIsolatedFromAbove) {
+  if (readState.getIsIsolatedFromAbove()) {
     assert(!valueScopes.empty() && "Expect a valueScope after reading region");
     valueScopes.pop_back();
   }
diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
index e39b20492e5ed..05179e2e1a4c9 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
@@ -482,8 +482,8 @@ void BufferizationOptions::setFunctionBoundaryTypeConversion(
     // If not builtin, fallback to unknown type conversion.
     return options.unknownTypeConverterFn(type, memorySpace, options);
   };
-  inferFunctionResultLayout =
-      layoutMapOption == LayoutMapOption::InferLayoutMap;
+  setInferFunctionResultLayout(layoutMapOption ==
+                               LayoutMapOption::InferLayoutMap);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
index 41d9a37844c9a..22048c43f2f77 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
@@ -590,7 +590,7 @@ LogicalResult mlir::bufferization::bufferizeModuleOp(
     }
 
     // Change buffer return types to more precise layout maps.
-    if (options.inferFunctionResultLayout)
+    if (options.getInferFunctionResultLayout())
       foldMemRefCasts(funcOp);
   }
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/BasicPtxBuilderInterface.cpp b/mlir/lib/Dialect/LLVMIR/IR/BasicPtxBuilderInterface.cpp
index 64cec0eadd2cb..799f301ef9973 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/BasicPtxBuilderInterface.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/BasicPtxBuilderInterface.cpp
@@ -161,7 +161,7 @@ LogicalResult PtxBuilder::insertValue(Value v, PTXRegisterMod itype) {
     }
     if (itype == PTXRegisterMod::ReadWrite)
       ptxOperands.push_back(v);
-    hasResult = true;
+    setHasResult(true);
   };
 
   llvm::raw_string_ostream ss(registerConstraints);
@@ -198,10 +198,9 @@ LogicalResult PtxBuilder::insertValue(Value v, PTXRegisterMod itype) {
 }
 
 /// Check if the operation needs to pack and unpack results.
-static bool
-needsPackUnpack(BasicPtxBuilderInterface interfaceOp,
-                bool needsManualRegisterMapping,
-                SmallVectorImpl<PTXRegisterMod> &registerModifiers) {
+static bool needsPackUnpack(BasicPtxBuilderInterface interfaceOp,
+                            bool needsManualRegisterMapping,
+                            ArrayRef<PTXRegisterMod> registerModifiers) {
   if (needsManualRegisterMapping)
     return false;
   const unsigned writeOnlyVals = interfaceOp->getNumResults();
@@ -215,11 +214,9 @@ needsPackUnpack(BasicPtxBuilderInterface interfaceOp,
 /// Pack the result types of the interface operation.
 /// If the operation has multiple results, it packs them into a struct
 /// type. Otherwise, it returns the original result types.
-static SmallVector<Type>
-packResultTypes(BasicPtxBuilderInterface interfaceOp,
-                bool needsManualRegisterMapping,
-                SmallVectorImpl<PTXRegisterMod> &registerModifiers,
-                SmallVectorImpl<Value> &ptxOperands) {
+static SmallVector<Type> packResultTypes(
+    BasicPtxBuilderInterface interfaceOp, bool needsManualRegisterMapping,
+    ArrayRef<PTXRegisterMod> registerModifiers, ArrayRef<Value> ptxOperands) {
   MLIRContext *ctx = interfaceOp->getContext();
   TypeRange resultRange = interfaceOp->getResultTypes();
 
@@ -452,8 +449,9 @@ LLVM::InlineAsmOp PtxBuilder::build() {
   auto asmDialectAttr = LLVM::AsmDialectAttr::get(interfaceOp->getContext(),
                                                   LLVM::AsmDialect::AD_ATT);
 
-  SmallVector<Type> resultTypes = packResultTypes(
-      interfaceOp, needsManualRegisterMapping, registerModifiers, ptxOperands);
+  SmallVector<Type> resultTypes =
+      packResultTypes(interfaceOp, getNeedsManualRegisterMapping(),
+                      registerModifiers, ptxOperands);
 
   // Remove the last comma from the constraints string.
   if (!registerConstraints.empty() &&
@@ -462,7 +460,7 @@ LLVM::InlineAsmOp PtxBuilder::build() {
   registerConstraints = canonicalizeRegisterConstraints(registerConstraints);
 
   std::string ptxInstruction = interfaceOp.getPtx();
-  if (!needsManualRegisterMapping)
+  if (!getNeedsManualRegisterMapping())
     ptxInstruction = rewriteAsmPlaceholders(ptxInstruction);
 
   // Add the predicate to the asm string.
@@ -515,18 +513,18 @@ void PtxBuilder::buildAndReplaceOp() {
   LDBG() << "\n Generated PTX \n\t" << inlineAsmOp;
 
   // Case 0: no result at all → just erase wrapper op.
-  if (!hasResult) {
+  if (!getHasResult()) {
     rewriter.eraseOp(interfaceOp);
     return;
   }
 
-  if (needsManualRegisterMapping) {
+  if (getNeedsManualRegisterMapping()) {
     rewriter.replaceOp(interfaceOp, inlineAsmOp->getResults());
     return;
   }
 
   // Case 1: Simple path, single scalar inline asm result.
-  if (!needsPackUnpack(interfaceOp, needsManualRegisterMapping,
+  if (!needsPackUnpack(interfaceOp, getNeedsManualRegisterMapping(),
                        registerModifiers)) {
     // Sub-case 1a: the wrapper op has a declared result -- replace it
     // directly with the inline asm result.
diff --git a/mlir/lib/Dialect/Linalg/Transforms/BlockPackMatmul.cpp b/mlir/lib/Dialect/Linalg/Transforms/BlockPackMatmul.cpp
index 99a7de99619dc..78c64fc53e5ec 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/BlockPackMatmul.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/BlockPackMatmul.cpp
@@ -173,7 +173,7 @@ linalg::blockPackMatmul(RewriterBase &rewriter, linalg::LinalgOp linalgOp,
   // Scalable tile sizes are non-constant at compile time, so they can never
   // satisfy the full-tile divisibility check. Reject early before creating
   // any ops to avoid modifying IR before returning notifyMatchFailure.
-  if (!options->allowPadding && hasScalable)
+  if (!options->getAllowPadding() && hasScalable)
     return rewriter.notifyMatchFailure(
         linalgOp, "scalable block factors require padding");
 
@@ -194,7 +194,7 @@ linalg::blockPackMatmul(RewriterBase &rewriter, linalg::LinalgOp linalgOp,
   }
 
   // If padding is disabled, make sure that dimensions can be packed cleanly.
-  if (!options->allowPadding &&
+  if (!options->getAllowPadding() &&
       !validateFullTilesOnDims(linalgOp, mnkTiles, options->mnkOrder)) {
     return rewriter.notifyMatchFailure(linalgOp,
                                        "expect packing full tiles only");
@@ -231,8 +231,8 @@ linalg::blockPackMatmul(RewriterBase &rewriter, linalg::LinalgOp linalgOp,
   // Transpose LHS matrix according to the options.
   FailureOr<PackTransposeResult> packedLhs = transposePackedMatmul(
       rewriter, packedMatmul->packedLinalgOp, packedMatmul->packOps[0], maps[0],
-      contractDims->m, options->lhsTransposeOuterBlocks,
-      options->lhsTransposeInnerBlocks);
+      contractDims->m, options->getLhsTransposeOuterBlocks(),
+      options->getLhsTransposeInnerBlocks());
   if (failed(packedLhs))
     return failure();
 
@@ -243,8 +243,8 @@ linalg::blockPackMatmul(RewriterBase &rewriter, linalg::LinalgOp linalgOp,
   // Transpose RHS matrix according to the options.
   FailureOr<PackTransposeResult> packedRhs = transposePackedMatmul(
       rewriter, packedMatmul->packedLinalgOp, packedMatmul->packOps[1], maps[1],
-      contractDims->k, options->rhsTransposeOuterBlocks,
-      options->rhsTransposeInnerBlocks);
+      contractDims->k, options->getRhsTransposeOuterBlocks(),
+      options->getRhsTransposeInnerBlocks());
   if (failed(packedRhs))
     return failure();
 
@@ -351,15 +351,15 @@ struct LinalgBlockPackMatmul
       if (llvm::none_of(options.scalableBlockFactors, [](bool b) { return b; }))
         options.scalableBlockFactors.clear();
 
-      options.allowPadding = allowPadding;
-      options.mnkPaddedSizesNextMultipleOf =
-          SmallVector<int64_t>{*mnkPaddedSizesNextMultipleOf};
+      options.setAllowPadding(allowPadding);
+      options.mnkPaddedSizesNextMultipleOf.assign(
+          SmallVector<int64_t>{*mnkPaddedSizesNextMultipleOf});
       if (!mnkOrder.empty())
         options.mnkOrder = SmallVector<int64_t>{*mnkOrder};
-      options.lhsTransposeOuterBlocks = lhsTransposeOuterBlocks;
-      options.lhsTransposeInnerBlocks = lhsTransposeInnerBlocks;
-      options.rhsTransposeOuterBlocks = rhsTransposeOuterBlocks;
-      options.rhsTransposeInnerBlocks = rhsTransposeInnerBlocks;
+      options.setLhsTransposeOuterBlocks(lhsTransposeOuterBlocks);
+      options.setLhsTransposeInnerBlocks(lhsTransposeInnerBlocks);
+      options.setRhsTransposeOuterBlocks(rhsTransposeOuterBlocks);
+      options.setRhsTransposeInnerBlocks(rhsTransposeInnerBlocks);
       return options;
     };
 
diff --git a/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp b/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
index 8c6ad2e65bd79..5850687e2db7c 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
@@ -50,8 +50,8 @@ getFullRankPaddingSizes(Builder &b, ArrayRef<OpFoldResult> indexingSizes,
     //   - 1 if we are padding to the next multiple of.
     //   - indexingSizes[idx] otherwise
     if (isZeroInteger(paddingSizes[idx])) {
-      paddingSizes[idx] =
-          options.padToMultipleOf ? b.getIndexAttr(1) : indexingSizes[idx];
+      paddingSizes[idx] = options.getPadToMultipleOfFlag() ? b.getIndexAttr(1)
+                                                           : indexingSizes[idx];
     }
     LLVM_DEBUG(DBGS() << "----idx: " << idx << " : " << paddingSizes[idx]
                       << "\n");
@@ -149,7 +149,7 @@ linalg::computePaddedShape(OpBuilder &builder, TypedValue<RankedTensorType> v,
 
       // If we are padding to the next multiple of, compose with ceil(sz) * sz.
       OpFoldResult paddingDimOfr;
-      if (options.padToMultipleOf) {
+      if (options.getPadToMultipleOfFlag()) {
         AffineExpr d0, s0;
         bindDims(builder.getContext(), d0);
         bindSymbols(builder.getContext(), s0);
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index 57270ec07eaf1..f4a714ce7f1e2 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "mlir/Dialect/Affine/Utils.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "mlir/Analysis/SliceAnalysis.h"
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
@@ -303,7 +304,7 @@ struct VectorizationState {
   /// Holds the value sizes of the iteration space to vectorize. Static
   /// dimensions are represented by 'arith.constant' and dynamic
   /// dimensions by 'tensor/memref.dim'.
-  SmallVector<Value> iterSpaceValueSizes;
+  llvm::SmallVectorWithFlags<Value> iterSpaceValueSizes;
 
   /// Holds the canonical vector shape used to vectorize the iteration space.
   SmallVector<int64_t> canonicalVecShape;
@@ -326,7 +327,12 @@ struct VectorizationState {
   /// dimension, masking can be safely skipped, despite the presence of dynamic
   /// shapes. Use this flag with care and only for cases where you are
   /// confident the assumption holds.
-  bool assumeDynamicDimsMatchVecSizes = false;
+  bool getAssumeDynamicDimsMatchVecSizes() const {
+    return iterSpaceValueSizes.getFlag(0);
+  }
+  void setAssumeDynamicDimsMatchVecSizes(bool Value) {
+    iterSpaceValueSizes.setFlag(0, Value);
+  }
 };
 
 LogicalResult
@@ -369,7 +375,7 @@ LogicalResult VectorizationState::initState(RewriterBase &rewriter,
                                             ArrayRef<int64_t> inputVectorSizes,
                                             ArrayRef<bool> inputScalableVecDims,
                                             bool assumeDimsMatchVec) {
-  assumeDynamicDimsMatchVecSizes = assumeDimsMatchVec;
+  setAssumeDynamicDimsMatchVecSizes(assumeDimsMatchVec);
   // Initialize the insertion point.
   rewriter.setInsertionPoint(linalgOp);
 
@@ -463,7 +469,7 @@ Value VectorizationState::getOrCreateMaskFor(
     return Value();
   }
 
-  if (assumeDynamicDimsMatchVecSizes) {
+  if (getAssumeDynamicDimsMatchVecSizes()) {
     // While for _dynamic_ dim sizes we can _assume_ that the corresponding
     // vector sizes match, we still need to check the _static_ dim sizes. Only
     // then we can be 100% sure that masking is not required.
@@ -511,7 +517,7 @@ VectorizationState::maskOperation(RewriterBase &rewriter, Operation *opToMask,
 
   if (!mask) {
     LDBG() << "No mask required";
-    if (assumeDynamicDimsMatchVecSizes) {
+    if (getAssumeDynamicDimsMatchVecSizes()) {
       llvm::TypeSwitch<Operation *>(opToMask)
           .Case<vector::TransferReadOp, vector::TransferWriteOp>(
               [&](auto xferOp) {
diff --git a/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp b/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp
index 153c95c02dc4f..6a70db405ffae 100644
--- a/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp
+++ b/mlir/lib/Dialect/NVGPU/TransformOps/NVGPUTransformOps.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "mlir/Analysis/SliceAnalysis.h"
 #include "mlir/Conversion/GPUCommon/GPUCommonPass.h"
@@ -441,8 +442,15 @@ struct MmaSyncBuilder {
     std::tuple<IndexCalculator, IndexCalculator, IndexCalculator> indexFns;
     std::tuple<SmallVector<int64_t>, SmallVector<int64_t>, SmallVector<int64_t>>
         vectorShapes;
-    SmallVector<int64_t> mmaShape;
-    bool tf32Enabled;
+    llvm::SmallVectorWithFlags<int64_t> mmaShape;
+    bool getTf32Enabled() const { return mmaShape.getFlag(0); }
+    void setTf32Enabled(bool Value) { mmaShape.setFlag(0, Value); }
+
+    MmaSyncInfo(decltype(indexFns) indexFns,
+                decltype(vectorShapes) vectorShapes,
+                SmallVector<int64_t> mmaShape, bool tf32Enabled)
+        : indexFns(std::move(indexFns)), vectorShapes(std::move(vectorShapes)),
+          mmaShape(unsigned(tf32Enabled), std::move(mmaShape)) {}
   };
 
   /// Return the specific index calculator for the given `linalgOp` or failure
@@ -789,8 +797,8 @@ FailureOr<Operation *> MmaSyncBuilder::buildMmaSync(LinalgOp linalgOp) {
                                             rhsIndexFn, rhsShape);
   Value res = buildMmaSyncMemRefLoadOperand(b, loc, laneId, resMemRef,
                                             resIndexFn, resShape);
-  res =
-      MmaSyncOp::create(b, loc, lhs, rhs, res, info.mmaShape, info.tf32Enabled);
+  res = MmaSyncOp::create(b, loc, lhs, rhs, res, info.mmaShape,
+                          info.getTf32Enabled());
   buildMmaSyncMemRefStoreOperand(b, loc, res, laneId, resMemRef, resIndexFn,
                                  resShape);
   return res.getDefiningOp();
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCCGToGPU.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCCGToGPU.cpp
index f8560857bb47b..774103ac48933 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCCGToGPU.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCCGToGPU.cpp
@@ -88,6 +88,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/OpenACC/Transforms/Passes.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/Arith/Utils/Utils.h"
@@ -468,8 +469,15 @@ class ACCCGToGPULowering {
 
   gpu::LaunchOp getLaunch() const { return launch; }
 
-  bool hasFailed = false;
-  bool insideAccumulateGridStride = false;
+  bool getHasFailed() const { return deferredBarrierSeqLoops.getFlag(0); }
+  void setHasFailed(bool Value) { deferredBarrierSeqLoops.setFlag(0, Value); }
+  bool getInsideAccumulateGridStride() const {
+    return deferredBarrierSeqLoops.getFlag(1);
+  }
+  bool setInsideAccumulateGridStride(bool Value) {
+    deferredBarrierSeqLoops.setFlag(1, Value);
+    return Value;
+  }
   Value reductionSharedBuf;
   // Reduction-accumulator slot (memref) -> the block-reduced value stored into
   // it; lets a block combine use the register instead of reloading.
@@ -703,19 +711,45 @@ class ACCCGToGPULowering {
   const ACCCGToGPUOptions &options;
   gpu::LaunchOp launch;
   IRMapping mapping;
-  llvm::SmallVector<scf::ParallelOp> loopReductions;
+  llvm::SmallVectorWithFlags<
+      scf::ParallelOp,
+      llvm::CalculateSmallVectorDefaultInlinedElements<scf::ParallelOp>::value,
+      3>
+      loopReductions;
   llvm::DenseMap<gpu::Processor, Value> threadIdMap;
   llvm::DenseMap<gpu::Processor, Value> dimensionMap;
   // True if ThreadY reduction exists, which triggers subgroup alignment
-  bool hasThreadYReduction = false;
+  bool getHasThreadYReduction() const {
+    return deferredBarrierSeqLoops.getFlag(2);
+  }
+  void setHasThreadYReduction(bool Value) {
+    deferredBarrierSeqLoops.setFlag(2, Value);
+  }
   // True if a ThreadX reduction exists, whose shuffles stay inside a row
-  bool hasThreadXReduction = false;
+  bool getHasThreadXReduction() const {
+    return deferredBarrierSeqLoops.getFlag(3);
+  }
+  void setHasThreadXReduction(bool Value) {
+    deferredBarrierSeqLoops.setFlag(3, Value);
+  }
   // True if an array reduction spans any thread dimension
-  bool hasThreadLevelArrayReduction = false;
+  bool getHasThreadLevelArrayReduction() const {
+    return loopReductions.getFlag(0);
+  }
+  bool setHasThreadLevelArrayReduction(bool Value) {
+    loopReductions.setFlag(0, Value);
+    return Value;
+  }
   // True if any ThreadX routine call exists in the kernel
-  bool hasThreadLevelRoutineCall = false;
+  bool getHasThreadLevelRoutineCall() const {
+    return loopReductions.getFlag(1);
+  }
+  void setHasThreadLevelRoutineCall(bool Value) {
+    loopReductions.setFlag(1, Value);
+  }
   // True when a per-row ThreadY barrier is emitted
-  bool hasThreadYBarrier = false;
+  bool getHasThreadYBarrier() const { return loopReductions.getFlag(2); }
+  void setHasThreadYBarrier(bool Value) { loopReductions.setFlag(2, Value); }
 
   // Reusable privatize broadcast slots per type; disabled for kernels.
   llvm::DenseMap<Type, Value> privatizeBroadcastCache;
@@ -737,8 +771,8 @@ class ACCCGToGPULowering {
   /// a row may sit anywhere in a subgroup. Array accumulates use atomics
   /// instead and still need alignment.
   bool isWorkerOnlyShuffleLaunch() const {
-    return hasThreadYReduction && !hasThreadXReduction &&
-           !hasThreadLevelArrayReduction && staticBlockDimZ == 1 &&
+    return getHasThreadYReduction() && !getHasThreadXReduction() &&
+           !getHasThreadLevelArrayReduction() && staticBlockDimZ == 1 &&
            staticBlockDimY > 1 && staticBlockDimY <= options.subgroupSize &&
            options.subgroupSize % staticBlockDimX == 0;
   }
@@ -747,7 +781,7 @@ class ACCCGToGPULowering {
   SharedMemoryBudget sharedMemBudget;
   SmallVector<std::string> sharedMemPrivateVarNames;
   SmallVector<std::string> threadPrivateVarNames;
-  llvm::SmallVector<Operation *, 4> deferredBarrierSeqLoops;
+  llvm::SmallVectorWithFlags<Operation *, 4, 4> deferredBarrierSeqLoops;
 
   Value getThreadId(Location loc, gpu::Dimension dim) {
     return gpu::ThreadIdOp::create(rewriter, loc, rewriter.getIndexType(), dim);
@@ -890,7 +924,7 @@ ACCCGToGPULowering::isEligibleForSharedMemory(acc::PrivateLocalOp privateLocal,
   FailureOr<bool> isCandidate = isPrivateLocalSharedMemoryCandidate(
       privateLocal, computeRegion, module, defaultPolicy, &accSupport);
   if (failed(isCandidate)) {
-    hasFailed = true;
+    setHasFailed(true);
     return std::nullopt;
   }
   if (!isCandidate.value())
@@ -943,14 +977,16 @@ LogicalResult ACCCGToGPULowering::rewrite() {
   // ThreadX is tracked too, to tell worker-only reductions from row shuffles.
   computeRegion->walk([&](acc::ReductionAccumulateOp op) {
     for (auto parDim : op.getParDimsAttr().getArray()) {
-      hasThreadXReduction |= parDim.isThreadX();
-      hasThreadYReduction |= parDim.isThreadY();
+      setHasThreadXReduction(int(getHasThreadXReduction()) |
+                             (parDim.isThreadX()));
+      setHasThreadYReduction(int(getHasThreadYReduction()) |
+                             (parDim.isThreadY()));
     }
   });
   computeRegion->walk([&](acc::ReductionAccumulateArrayOp op) {
     for (auto parDim : op.getParDimsAttr().getArray()) {
       if (!parDim.isAnyBlock())
-        hasThreadLevelArrayReduction = true;
+        setHasThreadLevelArrayReduction(true);
     }
   });
 
@@ -962,7 +998,7 @@ LogicalResult ACCCGToGPULowering::rewrite() {
     if (mlir::acc::GPUParallelDimAttr parDim =
             getAccRoutineCallParDim(callOp, defaultPolicy)) {
       if (parDim.isThreadX() || parDim.isThreadY()) {
-        hasThreadLevelRoutineCall = true;
+        setHasThreadLevelRoutineCall(true);
         return WalkResult::interrupt();
       }
     }
@@ -1212,11 +1248,11 @@ LogicalResult ACCCGToGPULowering::rewrite() {
     // work, so keep its shape instead.
     if (isSingleThreadWorkerLaunch())
       skipAlign = true;
-    if (needsThreadYAlign && !needsThreadXAlign && !hasThreadYBarrier &&
+    if (needsThreadYAlign && !needsThreadXAlign && !getHasThreadYBarrier() &&
         isWorkerOnlyShuffleLaunch())
       skipAlign = true;
 
-    if ((isShuffleEnabled || hasThreadYBarrier) && !skipAlign) {
+    if ((isShuffleEnabled || getHasThreadYBarrier()) && !skipAlign) {
       rewriter.setInsertionPoint(launch);
 
       Value curBlockDimX = launch.getBlockSizeX();
@@ -1303,7 +1339,7 @@ LogicalResult ACCCGToGPULowering::rewrite() {
     }
   }
 
-  if (hasFailed)
+  if (getHasFailed())
     return failure();
 
   if (!threadPrivateVarNames.empty()) {
@@ -1730,7 +1766,7 @@ ACCCGToGPULowering::computeActiveAndInactiveParDims(Operation *op,
             diagnosticOp->getLoc(),
             "operations in the same predicate region require incompatible "
             "ThreadY predication");
-        hasFailed = true;
+        setHasFailed(true);
         return {};
       }
       mlir::acc::insertParDim(ancestorParDims, threadY);
@@ -1815,7 +1851,7 @@ void ACCCGToGPULowering::createPerRowBarrier(Location loc) {
     return;
   }
 
-  hasThreadYBarrier = true;
+  setHasThreadYBarrier(true);
 
   if (staticBlockDimX <= options.subgroupSize) {
     emitGPUBarrierSubgroup(rewriter, loc);
@@ -2340,7 +2376,7 @@ bool ACCCGToGPULowering::needsInLoopReuseBarrier(Operation *loopOp) {
   // workgroup thread reaches such a call and the callee synchronizes
   // internally, so threads leave it in no particular order and can then be
   // running different iterations of this loop at the same time.
-  if (!hasThreadLevelRoutineCall)
+  if (!getHasThreadLevelRoutineCall())
     return false;
   bool callsThreadLevelRoutine = false;
   loopOp->walk([&](CallOpInterface callOp) -> WalkResult {
@@ -2408,7 +2444,7 @@ void ACCCGToGPULowering::processPredicateRegion(
             SmallVector<mlir::acc::GPUParallelDimAttr>>
       parDimsPair = computeActiveAndInactiveParDims(
           interOp, &interOp.getRegion().front());
-  if (hasFailed)
+  if (getHasFailed())
     return;
 
   // If ThreadY reduction exists, subgroup alignment is applied
@@ -2418,7 +2454,7 @@ void ACCCGToGPULowering::processPredicateRegion(
   // routine call, all ThreadX threads must reach the call so the routine's
   // workgroup-wide barriers (e.g. shared memory alloca sync) converge.
   // A single-thread worker launch is left unaligned, so it has no such lanes.
-  if (hasThreadYReduction && !isSingleThreadWorkerLaunch()) {
+  if (getHasThreadYReduction() && !isSingleThreadWorkerLaunch()) {
     MLIRContext *ctx = computeRegion->getContext();
     mlir::acc::GPUParallelDimAttr threadXParDim =
         mlir::acc::GPUParallelDimAttr::threadXDim(ctx);
@@ -2435,7 +2471,7 @@ void ACCCGToGPULowering::processPredicateRegion(
     // We use the pre-computed hasThreadLevelRoutineCall as an early-out
     // optimization.
     bool regionHasThreadLevelRoutineCall = false;
-    if (hasThreadLevelRoutineCall) {
+    if (getHasThreadLevelRoutineCall()) {
       interOp.getRegion().walk([&](CallOpInterface callOp) {
         if (mlir::acc::GPUParallelDimAttr parDim =
                 getAccRoutineCallParDim(callOp, defaultPolicy)) {
@@ -3330,7 +3366,7 @@ void ACCCGToGPULowering::processParallelOp(scf::ParallelOp parallelOp) {
 
   mlir::acc::GPUParallelDimAttr parDim = pDimsAttr.getArray().front();
 
-  bool savedGridStrideFlag = insideAccumulateGridStride;
+  bool savedGridStrideFlag = getInsideAccumulateGridStride();
   Value savedReductionBuf = reductionSharedBuf;
   if (parDim.isThreadX()) {
     bool found = false;
@@ -3350,7 +3386,7 @@ void ACCCGToGPULowering::processParallelOp(scf::ParallelOp parallelOp) {
       return WalkResult::advance();
     });
     if (found)
-      insideAccumulateGridStride = true;
+      setInsideAccumulateGridStride(true);
   }
 
   // common loop body processing for both par0 and 1+
@@ -3399,7 +3435,7 @@ void ACCCGToGPULowering::processParallelOp(scf::ParallelOp parallelOp) {
         }
       }
     }
-    if (insideAccumulateGridStride || hasAccumulateSibling) {
+    if (getInsideAccumulateGridStride() || hasAccumulateSibling) {
       for (auto launchArg : computeRegion.getLaunchArgs()) {
         if (acc::ParWidthOp pw = launchArg.getDefiningOp<acc::ParWidthOp>()) {
           if (pw.getParDim().isThreadX()) {
@@ -3480,8 +3516,8 @@ void ACCCGToGPULowering::processParallelOp(scf::ParallelOp parallelOp) {
     });
     loopReductions.push_back(parallelOp);
   }
-  insideAccumulateGridStride = savedGridStrideFlag;
-  if (!insideAccumulateGridStride && !savedReductionBuf)
+  setInsideAccumulateGridStride(savedGridStrideFlag);
+  if (!getInsideAccumulateGridStride() && !savedReductionBuf)
     reductionSharedBuf = Value();
 }
 
diff --git a/mlir/lib/Dialect/Shard/Interfaces/ShardingInterface.cpp b/mlir/lib/Dialect/Shard/Interfaces/ShardingInterface.cpp
index cbdc274940d1e..d5b72b1c8b77a 100644
--- a/mlir/lib/Dialect/Shard/Interfaces/ShardingInterface.cpp
+++ b/mlir/lib/Dialect/Shard/Interfaces/ShardingInterface.cpp
@@ -354,7 +354,7 @@ shard::detail::defaultGetShardingOption(Operation *op,
   // 3. Finalize sharding option
   removeTrailingEmptySubArray(shardingOption.shardingArray);
   if (!anyShardingInResultsOrOperands)
-    shardingOption.empty = true;
+    shardingOption.setEmpty(true);
   return shardingOption;
 }
 
@@ -486,7 +486,7 @@ static LogicalResult addShardOp(OpBuilder &b, OpOperand &opOperand,
 
 LogicalResult shard::detail::defaultAddShardingAnnotations(
     Operation *op, OpBuilder &b, const ShardingOption &shardingOption) {
-  assert(!shardingOption.empty && shardingOption.grid);
+  assert(!shardingOption.getEmpty() && shardingOption.grid);
 
   ShardingInterface shardingOp = llvm::cast<ShardingInterface>(op);
   SmallVector<utils::IteratorType> loopTypes =
diff --git a/mlir/lib/Dialect/Shard/Transforms/ShardingPropagation.cpp b/mlir/lib/Dialect/Shard/Transforms/ShardingPropagation.cpp
index a4f343c7c87b1..bce1ecfa448b3 100644
--- a/mlir/lib/Dialect/Shard/Transforms/ShardingPropagation.cpp
+++ b/mlir/lib/Dialect/Shard/Transforms/ShardingPropagation.cpp
@@ -68,8 +68,9 @@ static llvm::raw_ostream &operator<<(llvm::raw_ostream &stream,
 
 [[maybe_unused]] static llvm::raw_ostream &operator<<(llvm::raw_ostream &stream,
                                                       const ShardingOption &v) {
-  return stream << "{empty = " << v.empty << ", grid" << v.grid
-                << ", shardingArray = " << v.shardingArray << "}";
+  stream << "{empty = " << v.getEmpty() << ", grid" << v.grid
+         << ", shardingArray = ";
+  return printRange(stream, v.shardingArray) << "}";
 }
 
 template <typename Stream, typename... Ts, size_t... Is>
@@ -222,7 +223,7 @@ static FailureOr<ShardingOption> selectShardingOption(
     for (ArrayRef<Sharding> operandShardings : possibleOperandShardingAttrs) {
       FailureOr<ShardingOption> shardingOption =
           shardingOp.getShardingOption(operandShardings, resultShardings);
-      if (failed(shardingOption) || shardingOption->empty) {
+      if (failed(shardingOption) || shardingOption->getEmpty()) {
         continue;
       }
       // These shardings may not be the same as those in operandShardings and
@@ -342,7 +343,7 @@ static LogicalResult visitOp(Operation *op, OpBuilder &builder) {
   LLVM_DEBUG(DBGS() << "Selected sharding option: " << *shardingOption << "\n");
 
   // sharding info is empty, return immediately
-  if (shardingOption->empty)
+  if (shardingOption->getEmpty())
     return success();
 
   if (failed(shardingOp.addShardingAnnotations(builder, *shardingOption))) {
diff --git a/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.cpp b/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.cpp
index b207dfe0d2be2..e333b196fc9e5 100644
--- a/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.cpp
+++ b/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.cpp
@@ -79,8 +79,7 @@ bool LvlSpec::isValid(Ranks const &ranks) const {
 
 DimLvlMap::DimLvlMap(unsigned symRank, ArrayRef<DimSpec> dimSpecs,
                      ArrayRef<LvlSpec> lvlSpecs)
-    : symRank(symRank), dimSpecs(dimSpecs), lvlSpecs(lvlSpecs),
-      mustPrintLvlVars(false) {
+    : symRank(symRank), dimSpecs(dimSpecs), lvlSpecs(lvlSpecs) {
   // First, check integrity of the variable-binding structure.
   // NOTE: This establishes the invariant that calls to `VarSet::add`
   // below cannot cause OOB errors.
@@ -96,7 +95,7 @@ DimLvlMap::DimLvlMap(unsigned symRank, ArrayRef<DimSpec> dimSpecs,
     // This LvlVar can be elided iff it isn't overtly used.
     lvlSpec.setElideVar(!isUsed);
     // If any LvlVar cannot be elided, then must forward-declare all LvlVars.
-    mustPrintLvlVars = mustPrintLvlVars || isUsed;
+    setMustPrintLvlVars(getMustPrintLvlVars() || isUsed);
   }
 }
 
diff --git a/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.h b/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.h
index 266fd7a3c5837..b29fc2a0ea3bb 100644
--- a/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.h
+++ b/mlir/lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.h
@@ -10,6 +10,7 @@
 #define MLIR_DIALECT_SPARSETENSOR_IR_DETAIL_DIMLVLMAP_H
 
 #include "Var.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h"
 #include "llvm/ADT/STLForwardCompat.h"
@@ -267,8 +268,9 @@ class DimLvlMap final {
   // All these fields are const-after-ctor.
   unsigned symRank;
   SmallVector<DimSpec> dimSpecs;
-  SmallVector<LvlSpec> lvlSpecs;
-  bool mustPrintLvlVars;
+  llvm::SmallVectorWithFlags<LvlSpec> lvlSpecs;
+  bool getMustPrintLvlVars() const { return lvlSpecs.getFlag(0); }
+  void setMustPrintLvlVars(bool Value) { lvlSpecs.setFlag(0, Value); }
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
index f388a2e44ebdb..4aaa3ee857055 100644
--- a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp
@@ -226,7 +226,6 @@ Merger::Merger(unsigned numInputOutputTensors, unsigned numLoops,
     : outTensor(numInputOutputTensors - 1),
       syntheticTensor(numInputOutputTensors),
       numTensors(numInputOutputTensors + 1), numLoops(numLoops),
-      hasSparseOut(false),
       lvlTypes(numTensors,
                std::vector<LevelType>(numLoops, LevelFormat::Undef)),
       loopToLvl(numTensors,
@@ -959,7 +958,7 @@ LatSetId Merger::buildLattices(ExprId e, LoopId i) {
     TensorId t = syntheticTensor;
     if (kind == TensorExp::Kind::kTensor) {
       t = expr.tensor;
-      if (hasSparseOut && t == outTensor)
+      if (latSets.getFlag(0) && t == outTensor)
         t = syntheticTensor;
     }
     latSets[s].push_back(addLat(t, i, e));
diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
index e8f34201b7d18..be30cfba8248a 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaInferShapes.cpp
@@ -362,7 +362,7 @@ struct TosaInferShapes
             auto inferredKnowledge = ValueKnowledge::getPessimisticValueState();
             inferredKnowledge.dtype =
                 cast<ShapedType>(resultTy).getElementType();
-            inferredKnowledge.hasRank = predictedShape.hasRank();
+            inferredKnowledge.setHasRank(predictedShape.hasRank());
             if (predictedShape.hasRank()) {
               for (auto dim : predictedShape.getDims()) {
                 inferredKnowledge.sizes.push_back(dim);
diff --git a/mlir/lib/ExecutionEngine/ExecutionEngine.cpp b/mlir/lib/ExecutionEngine/ExecutionEngine.cpp
index c8f4e81ddf07b..eddfcabc026ff 100644
--- a/mlir/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/mlir/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -307,7 +307,7 @@ ExecutionEngine::create(Operation *m, const ExecutionEngineOptions &options,
     auto destroyFn = reinterpret_cast<LibraryDestroyFn>(destroySim);
     destroyFns.push_back(destroyFn);
   }
-  engine->destroyFns = std::move(destroyFns);
+  engine->destroyFns.assign(std::move(destroyFns));
 
   // Callback to create the object layer with symbol resolution to current
   // process and dynamically linked libraries.
@@ -451,8 +451,8 @@ Error ExecutionEngine::invokePacked(StringRef name,
 }
 
 void ExecutionEngine::initialize() {
-  if (isInitialized)
+  if (getIsInitialized())
     return;
   cantFail(jit->initialize(jit->getMainJITDylib()));
-  isInitialized = true;
+  setIsInitialized(true);
 }
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index c5d66c27557c5..206f452a752b2 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -27,6 +27,7 @@
 #include "mlir/IR/OperationSupport.h"
 #include "mlir/IR/Remarks.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/CommandLine.h"
@@ -146,10 +147,20 @@ class MLIRContextImpl {
   /// In most cases, creating operation in unregistered dialect is not desired
   /// and indicate a misconfiguration of the compiler. This option enables to
   /// detect such use cases
-  bool allowUnregisteredDialects = false;
+  bool getAllowUnregisteredDialects() const {
+    return sortedRegisteredOperations.getFlag(0);
+  }
+  void setAllowUnregisteredDialects(bool Value) {
+    sortedRegisteredOperations.setFlag(0, Value);
+  }
 
   /// Enable support for multi-threading within MLIR.
-  bool threadingIsEnabled = true;
+  bool getThreadingIsEnabled() const {
+    return !sortedRegisteredOperations.getFlag(1);
+  }
+  void setThreadingIsEnabled(bool Value) {
+    sortedRegisteredOperations.setFlag(1, !Value);
+  }
 
   /// Track if we are currently executing in a threaded execution environment
   /// (like the pass-manager): this is only a debugging feature to help reducing
@@ -160,10 +171,20 @@ class MLIRContextImpl {
 
   /// If the operation should be attached to diagnostics printed via the
   /// Operation::emit methods.
-  bool printOpOnDiagnostic = true;
+  bool getPrintOpOnDiagnostic() const {
+    return !sortedRegisteredOperations.getFlag(2);
+  }
+  void setPrintOpOnDiagnostic(bool Value) {
+    sortedRegisteredOperations.setFlag(2, !Value);
+  }
 
   /// If the current stack trace should be attached when emitting diagnostics.
-  bool printStackTraceOnDiagnostic = false;
+  bool getPrintStackTraceOnDiagnostic() const {
+    return sortedRegisteredOperations.getFlag(3);
+  }
+  void setPrintStackTraceOnDiagnostic(bool Value) {
+    sortedRegisteredOperations.setFlag(3, Value);
+  }
 
   //===--------------------------------------------------------------------===//
   // Other
@@ -191,7 +212,8 @@ class MLIRContextImpl {
 
   /// This is a sorted container of registered operations for a deterministic
   /// and efficient `getRegisteredOperations` implementation.
-  SmallVector<RegisteredOperationName, 0> sortedRegisteredOperations;
+  llvm::SmallVectorWithFlags<RegisteredOperationName, 0, 4>
+      sortedRegisteredOperations;
 
   /// This is a list of dialects that are created referring to this context.
   /// The MLIRContext owns the objects. These need to be declared after the
@@ -282,7 +304,9 @@ class MLIRContextImpl {
 
 public:
   MLIRContextImpl(bool threadingIsEnabled)
-      : threadingIsEnabled(threadingIsEnabled) {
+      : sortedRegisteredOperations(
+            decltype(this->sortedRegisteredOperations)::withFlags(
+                (unsigned(!(threadingIsEnabled)) << 1))) {
     if (threadingIsEnabled) {
       ownedThreadPool = std::make_unique<llvm::DefaultThreadPool>();
       threadPool = ownedThreadPool.get();
@@ -597,19 +621,21 @@ llvm::hash_code MLIRContext::getRegistryHash() {
 }
 
 bool MLIRContext::allowsUnregisteredDialects() {
-  return impl->allowUnregisteredDialects;
+  return impl->getAllowUnregisteredDialects();
 }
 
 void MLIRContext::allowUnregisteredDialects(bool allowing) {
   assert(impl->multiThreadedExecutionContext == 0 &&
          "changing MLIRContext `allow-unregistered-dialects` configuration "
          "while in a multi-threaded execution context");
-  impl->allowUnregisteredDialects = allowing;
+  impl->setAllowUnregisteredDialects(allowing);
 }
 
 /// Return true if multi-threading is enabled by the context.
 #if LLVM_ENABLE_THREADS
-bool MLIRContext::isMultithreadingEnabled() { return impl->threadingIsEnabled; }
+bool MLIRContext::isMultithreadingEnabled() {
+  return impl->getThreadingIsEnabled();
+}
 #endif
 
 /// Set the flag specifying if multi-threading is disabled by the context.
@@ -622,7 +648,7 @@ void MLIRContext::disableMultithreading(bool disable) {
          "changing MLIRContext `disable-threading` configuration while "
          "in a multi-threaded execution context");
 
-  impl->threadingIsEnabled = !disable;
+  impl->setThreadingIsEnabled(!disable);
 
   // Update the threading mode for each of the uniquers.
   impl->affineUniquer.disableMultithreading(disable);
@@ -779,7 +805,7 @@ bool MLIRContext::isInTransientScope() const {
 /// Return true if we should attach the operation to diagnostics emitted via
 /// Operation::emit.
 bool MLIRContext::shouldPrintOpOnDiagnostic() {
-  return impl->printOpOnDiagnostic;
+  return impl->getPrintOpOnDiagnostic();
 }
 
 /// Set the flag specifying if we should attach the operation to diagnostics
@@ -788,13 +814,13 @@ void MLIRContext::printOpOnDiagnostic(bool enable) {
   assert(impl->multiThreadedExecutionContext == 0 &&
          "changing MLIRContext `print-op-on-diagnostic` configuration while in "
          "a multi-threaded execution context");
-  impl->printOpOnDiagnostic = enable;
+  impl->setPrintOpOnDiagnostic(enable);
 }
 
 /// Return true if we should attach the current stacktrace to diagnostics when
 /// emitted.
 bool MLIRContext::shouldPrintStackTraceOnDiagnostic() {
-  return impl->printStackTraceOnDiagnostic;
+  return impl->getPrintStackTraceOnDiagnostic();
 }
 
 /// Set the flag specifying if we should attach the current stacktrace when
@@ -803,7 +829,7 @@ void MLIRContext::printStackTraceOnDiagnostic(bool enable) {
   assert(impl->multiThreadedExecutionContext == 0 &&
          "changing MLIRContext `print-stacktrace-on-diagnostic` configuration "
          "while in a multi-threaded execution context");
-  impl->printStackTraceOnDiagnostic = enable;
+  impl->setPrintStackTraceOnDiagnostic(enable);
 }
 
 /// Return information about all registered operations.
diff --git a/mlir/lib/Interfaces/InferTypeOpInterface.cpp b/mlir/lib/Interfaces/InferTypeOpInterface.cpp
index c31e0ae7470e2..dd765e558c409 100644
--- a/mlir/lib/Interfaces/InferTypeOpInterface.cpp
+++ b/mlir/lib/Interfaces/InferTypeOpInterface.cpp
@@ -94,7 +94,8 @@ Type ShapeAdaptor::getElementType() const {
   return cast<ShapedTypeComponents *>(val)->getElementType();
 }
 
-void ShapeAdaptor::getDims(SmallVectorImpl<int64_t> &res) const {
+template <typename ShapeStorageT>
+void ShapeAdaptor::getDimsImpl(ShapeStorageT &res) const {
   assert(hasRank());
   if (auto t = llvm::dyn_cast_if_present<Type>(val)) {
     ArrayRef<int64_t> vals = cast<ShapedType>(t).getShape();
@@ -111,10 +112,14 @@ void ShapeAdaptor::getDims(SmallVectorImpl<int64_t> &res) const {
   }
 }
 
+void ShapeAdaptor::getDims(SmallVectorImpl<int64_t> &res) const {
+  getDimsImpl(res);
+}
+
 void ShapeAdaptor::getDims(ShapedTypeComponents &res) const {
   assert(hasRank());
-  res.ranked = true;
-  getDims(res.dims);
+  getDimsImpl(res.dims);
+  res.dims.setFlag(0, true);
 }
 
 int64_t ShapeAdaptor::getDimSize(int index) const {
diff --git a/mlir/lib/TableGen/Class.cpp b/mlir/lib/TableGen/Class.cpp
index 81f1aee73a7f0..79e1634cb974c 100644
--- a/mlir/lib/TableGen/Class.cpp
+++ b/mlir/lib/TableGen/Class.cpp
@@ -339,7 +339,7 @@ void Class::writeDeclTo(raw_indented_ostream &os) const {
   }
 
   // Declare the class.
-  os << (isStruct ? "struct" : "class") << ' ' << className << ' ';
+  os << (isStructDeclaration() ? "struct" : "class") << ' ' << className << ' ';
 
   // Declare the parent classes, if any.
   if (!parents.empty()) {
@@ -401,7 +401,8 @@ Visibility Class::getLastVisibilityDecl() const {
   auto reverseDecls = llvm::reverse(declarations);
   auto it = llvm::find_if(reverseDecls, llvm::IsaPred<VisibilityDeclaration>);
   return it == reverseDecls.end()
-             ? (isStruct ? Visibility::Public : Visibility::Private)
+             ? (isStructDeclaration() ? Visibility::Public
+                                      : Visibility::Private)
              : cast<VisibilityDeclaration>(**it).getVisibility();
 }
 
diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp
index 767f00db2fe81..b189b604894a8 100644
--- a/mlir/lib/TableGen/Operator.cpp
+++ b/mlir/lib/TableGen/Operator.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/Debug.h"
@@ -400,7 +401,7 @@ void Operator::populateTypeInferenceInfo(
   // to determine if the result types an be inferred.
   auto &recordKeeper = def.getRecords();
   auto *inferTrait = recordKeeper.getDef(inferTypeOpInterface);
-  allResultsHaveKnownTypes = false;
+  builders.setFlag(0, false);
   if (!inferTrait)
     return;
 
@@ -430,7 +431,7 @@ void Operator::populateTypeInferenceInfo(
     for (int i = 0; i < getNumResults(); ++i)
       resultTypeMapping.emplace_back(operandIdx, "$_self");
 
-    allResultsHaveKnownTypes = true;
+    builders.setFlag(0, true);
     traits.push_back(Trait::create(inferTrait->getDefInit()));
     return;
   }
@@ -442,9 +443,10 @@ void Operator::populateTypeInferenceInfo(
   /// is known to have a fully-inferred type, `inferred` is set to true.
   struct ResultTypeInference {
     /// The list of incoming type inference edges.
-    SmallVector<InferredResultType> sources;
+    llvm::SmallVectorWithFlags<InferredResultType> sources;
     /// This flag is set to true when the result type is known to be inferrable.
-    bool inferred = false;
+    bool getInferred() const { return sources.getFlag(0); }
+    void setInferred(bool Value) { sources.setFlag(0, Value); }
   };
 
   // This vector represents the type inference graph, with one node for each
@@ -457,7 +459,7 @@ void Operator::populateTypeInferenceInfo(
     if (getResult(idx).constraint.getBuilderCall()) {
       infer.sources.emplace_back(InferredResultType::mapResultIndex(idx),
                                  "$_self");
-      infer.inferred = true;
+      infer.setInferred(true);
     }
   }
 
@@ -487,16 +489,17 @@ void Operator::populateTypeInferenceInfo(
       int resultIndex = InferredResultType::unmapResultIndex(target);
       ResultTypeInference &infer = inference[resultIndex];
       // If the type of the result has already been inferred, do nothing.
-      if (infer.inferred)
+      if (infer.getInferred())
         continue;
       int sourceIndex =
           argumentsAndResultsIndex.lookup(def.getValueAsString("lhs"));
       infer.sources.emplace_back(sourceIndex,
                                  def.getValueAsString("transformer").str());
       // Locally propagate inferredness.
-      infer.inferred =
+      infer.setInferred(
           InferredResultType::isArgIndex(sourceIndex) ||
-          inference[InferredResultType::unmapResultIndex(sourceIndex)].inferred;
+          inference[InferredResultType::unmapResultIndex(sourceIndex)]
+              .getInferred());
       continue;
     }
 
@@ -515,13 +518,13 @@ void Operator::populateTypeInferenceInfo(
           InferredResultType::isArgIndex(shapedIndex)) {
         int resultIndex = InferredResultType::unmapResultIndex(elementsIndex);
         ResultTypeInference &infer = inference[resultIndex];
-        if (!infer.inferred) {
+        if (!infer.getInferred()) {
           infer.sources.emplace_back(
               shapedIndex,
               "::llvm::SmallVector<::mlir::Type>(::llvm::cast<::mlir::"
               "ShapedType>($_self).getNumElements(), "
               "::llvm::cast<::mlir::ShapedType>($_self).getElementType())");
-          infer.inferred = true;
+          infer.setInferred(true);
         }
       }
 
@@ -547,7 +550,7 @@ void Operator::populateTypeInferenceInfo(
       if (InferredResultType::isResultIndex(index))
         resultIndices.push_back(InferredResultType::unmapResultIndex(index));
       if (InferredResultType::isArgIndex(index) ||
-          inference[InferredResultType::unmapResultIndex(index)].inferred)
+          inference[InferredResultType::unmapResultIndex(index)].getInferred())
         fullyInferredIndex = index;
     }
     if (fullyInferredIndex) {
@@ -555,9 +558,9 @@ void Operator::populateTypeInferenceInfo(
       // aren't already inferred -- a 1 -> N fanout.
       for (int resultIndex : resultIndices) {
         ResultTypeInference &infer = inference[resultIndex];
-        if (!infer.inferred) {
+        if (!infer.getInferred()) {
           infer.sources.assign(1, {*fullyInferredIndex, "$_self"});
-          infer.inferred = true;
+          infer.setInferred(true);
         }
       }
     } else {
@@ -576,7 +579,7 @@ void Operator::populateTypeInferenceInfo(
   // Propagate inferredness until a fixed point.
   std::vector<ResultTypeInference *> worklist;
   for (ResultTypeInference &infer : inference)
-    if (!infer.inferred)
+    if (!infer.getInferred())
       worklist.push_back(&infer);
   bool changed;
   do {
@@ -589,7 +592,7 @@ void Operator::populateTypeInferenceInfo(
             assert(InferredResultType::isResultIndex(source.getIndex()));
             return inference[InferredResultType::unmapResultIndex(
                                  source.getIndex())]
-                .inferred;
+                .getInferred();
           });
       if (iter == infer.sources.end()) {
         ++cur;
@@ -597,17 +600,17 @@ void Operator::populateTypeInferenceInfo(
       }
 
       changed = true;
-      infer.inferred = true;
+      infer.setInferred(true);
       // Make this the only source for the result. This breaks any cycles.
       infer.sources.assign(1, *iter);
       cur = worklist.erase(cur);
     }
   } while (changed);
 
-  allResultsHaveKnownTypes = worklist.empty();
+  builders.setFlag(0, worklist.empty());
 
   // If the types could be computed, then add type inference trait.
-  if (allResultsHaveKnownTypes) {
+  if (allResultTypesKnown()) {
     traits.push_back(Trait::create(inferTrait->getDefInit()));
     for (const ResultTypeInference &infer : inference)
       resultTypeMapping.push_back(infer.sources.front());
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index bb928c4f10ce2..cdc7d50fd3bf8 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -20,6 +20,7 @@
 #include "mlir/Support/LLVM.h"
 #include "mlir/Target/Cpp/CppEmitter.h"
 #include "llvm/ADT/ScopedHashTable.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/Casting.h"
@@ -252,7 +253,7 @@ struct CppEmitter {
 
   /// Returns if all variables for op results and basic block arguments need to
   /// be declared at the beginning of a function.
-  bool shouldDeclareVariablesAtTop() { return declareVariablesAtTop; };
+  bool shouldDeclareVariablesAtTop() { return getDeclareVariablesAtTop(); };
 
   /// Returns whether this file op should be emitted
   bool shouldEmitFile(FileOp file) {
@@ -294,7 +295,12 @@ struct CppEmitter {
   /// Boolean to enforce that all variables for op results and block
   /// arguments are declared at the beginning of the function. This also
   /// includes results from ops located in nested regions.
-  bool declareVariablesAtTop;
+  bool getDeclareVariablesAtTop() const {
+    return emittedExpressionPrecedence.getFlag(0);
+  }
+  void setDeclareVariablesAtTop(bool Value) {
+    emittedExpressionPrecedence.setFlag(0, Value);
+  }
 
   /// Only emit file ops whos id matches this value.
   std::string fileId;
@@ -319,7 +325,7 @@ struct CppEmitter {
   unsigned int valueCount{0};
 
   /// State of the current expression being emitted.
-  SmallVector<int> emittedExpressionPrecedence;
+  llvm::SmallVectorWithFlags<int> emittedExpressionPrecedence;
 
   void pushExpressionPrecedence(int precedence) {
     emittedExpressionPrecedence.push_back(precedence);
@@ -1568,9 +1574,11 @@ static LogicalResult printOperation(CppEmitter &emitter,
 
 CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
                        StringRef fileId)
-    : os(os), declareVariablesAtTop(declareVariablesAtTop),
-      fileId(fileId.str()), defaultValueMapperScope(valueMapper),
-      defaultBlockMapperScope(blockMapper) {
+    : os(os), fileId(fileId.str()), defaultValueMapperScope(valueMapper),
+      defaultBlockMapperScope(blockMapper),
+      emittedExpressionPrecedence(
+          decltype(this->emittedExpressionPrecedence)::withFlags(
+              unsigned(declareVariablesAtTop))) {
   labelInScopeCount.push(0);
 }
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 07b9d683d309d..6e6cf3a2a0f7f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 
 #include "AttrKindDetail.h"
 #include "DebugTranslation.h"
@@ -92,7 +93,7 @@ class InstructionCapturingInserter : public llvm::IRBuilderCallbackInserter {
   /// Constructs the inserter.
   InstructionCapturingInserter()
       : llvm::IRBuilderCallbackInserter([this](llvm::Instruction *instruction) {
-          if (LLVM_LIKELY(enabled))
+          if (LLVM_LIKELY(getEnabledFlag()))
             capturedInstructions.push_back(instruction);
         }) {}
 
@@ -124,21 +125,28 @@ class InstructionCapturingInserter : public llvm::IRBuilderCallbackInserter {
     InstructionCapturingInserter *inserter = nullptr;
 
     /// List of instructions in the inserter prior to this scope.
-    SmallVector<llvm::Instruction *> previouslyCollectedInstructions;
+    llvm::SmallVectorWithFlags<llvm::Instruction *>
+        previouslyCollectedInstructions;
 
     /// Whether the inserter was enabled prior to this scope.
-    bool wasEnabled;
+    bool getWasEnabled() const {
+      return previouslyCollectedInstructions.getFlag(0);
+    }
+    void setWasEnabled(bool Value) {
+      previouslyCollectedInstructions.setFlag(0, Value);
+    }
   };
 
   /// Enable or disable the capturing mechanism.
-  void setEnabled(bool enabled = true) { this->enabled = enabled; }
+  void setEnabled(bool enabled = true) { this->setEnabledFlag(enabled); }
 
 private:
   /// List of captured instructions.
-  SmallVector<llvm::Instruction *> capturedInstructions;
+  llvm::SmallVectorWithFlags<llvm::Instruction *> capturedInstructions;
 
   /// Whether the collection is enabled.
-  bool enabled = false;
+  bool getEnabledFlag() const { return capturedInstructions.getFlag(0); }
+  void setEnabledFlag(bool Value) { capturedInstructions.setFlag(0, Value); }
 };
 
 using CapturingIRBuilder =
@@ -153,8 +161,8 @@ InstructionCapturingInserter::CollectionScope::CollectionScope(
 
   auto &capturingIRBuilder = static_cast<CapturingIRBuilder &>(irBuilder);
   inserter = &capturingIRBuilder.getInserter();
-  wasEnabled = inserter->enabled;
-  if (wasEnabled)
+  setWasEnabled(inserter->getEnabledFlag());
+  if (getWasEnabled())
     previouslyCollectedInstructions.swap(inserter->capturedInstructions);
   inserter->setEnabled(true);
 }
@@ -163,14 +171,17 @@ InstructionCapturingInserter::CollectionScope::~CollectionScope() {
   if (!inserter)
     return;
 
+  const bool savedWasEnabled = getWasEnabled();
+  // Preserve this scope's saved state when swapping the flagged vectors.
   previouslyCollectedInstructions.swap(inserter->capturedInstructions);
+  setWasEnabled(savedWasEnabled);
   // If collection was enabled (likely in another, surrounding scope), keep
   // the instructions collected in this scope.
-  if (wasEnabled) {
+  if (getWasEnabled()) {
     llvm::append_range(inserter->capturedInstructions,
                        previouslyCollectedInstructions);
   }
-  inserter->setEnabled(wasEnabled);
+  inserter->setEnabled(getWasEnabled());
 }
 
 /// Translates the given data layout spec attribute to the LLVM IR data layout.
diff --git a/mlir/lib/Tools/PDLL/ODS/Operation.cpp b/mlir/lib/Tools/PDLL/ODS/Operation.cpp
index b836ece5071bb..97f69772e6738 100644
--- a/mlir/lib/Tools/PDLL/ODS/Operation.cpp
+++ b/mlir/lib/Tools/PDLL/ODS/Operation.cpp
@@ -20,5 +20,6 @@ Operation::Operation(StringRef name, StringRef summary, StringRef desc,
                      llvm::SMLoc loc)
     : name(name.str()), summary(summary.str()), description(desc.str()),
       nativeClassName(nativeClassName.str()),
-      supportsTypeInferrence(supportsTypeInferrence),
-      location(loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)) {}
+      location(loc, llvm::SMLoc::getFromPointer(loc.getPointer() + 1)),
+      attributes(decltype(this->attributes)::withFlags(
+          unsigned(supportsTypeInferrence))) {}
diff --git a/mlir/test/lib/Dialect/Bufferization/TestOneShotModuleBufferize.cpp b/mlir/test/lib/Dialect/Bufferization/TestOneShotModuleBufferize.cpp
index 036e05bfc2e02..78a30272528bf 100644
--- a/mlir/test/lib/Dialect/Bufferization/TestOneShotModuleBufferize.cpp
+++ b/mlir/test/lib/Dialect/Bufferization/TestOneShotModuleBufferize.cpp
@@ -133,7 +133,7 @@ struct TestOneShotModuleBufferizePass
     };
     // Function signature update only works with memref.cast. Disable it to
     // align behaviour for upstream and user casts.
-    opt.inferFunctionResultLayout = false;
+    opt.setInferFunctionResultLayout(false);
 
     bufferization::BufferizationState bufferizationState;
 
diff --git a/mlir/unittests/Dialect/CMakeLists.txt b/mlir/unittests/Dialect/CMakeLists.txt
index 5fd835189ccc7..87f10951552f0 100644
--- a/mlir/unittests/Dialect/CMakeLists.txt
+++ b/mlir/unittests/Dialect/CMakeLists.txt
@@ -18,5 +18,6 @@ add_subdirectory(SCF)
 add_subdirectory(SparseTensor)
 add_subdirectory(SPIRV)
 add_subdirectory(SMT)
+add_subdirectory(Tosa)
 add_subdirectory(Transform)
 add_subdirectory(Utils)
diff --git a/mlir/unittests/Dialect/Tosa/CMakeLists.txt b/mlir/unittests/Dialect/Tosa/CMakeLists.txt
new file mode 100644
index 0000000000000..ae21954cb3f27
--- /dev/null
+++ b/mlir/unittests/Dialect/Tosa/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_mlir_unittest(MLIRTosaTests
+  ShapeUtilsTest.cpp
+)
+
+mlir_target_link_libraries(MLIRTosaTests
+  PRIVATE
+  MLIRIR
+  MLIRInferTypeOpInterface
+)
diff --git a/mlir/unittests/Dialect/Tosa/ShapeUtilsTest.cpp b/mlir/unittests/Dialect/Tosa/ShapeUtilsTest.cpp
new file mode 100644
index 0000000000000..b4f20cc52e0e3
--- /dev/null
+++ b/mlir/unittests/Dialect/Tosa/ShapeUtilsTest.cpp
@@ -0,0 +1,46 @@
+//===- ShapeUtilsTest.cpp - Tosa shape knowledge tests ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Tosa/Utils/ShapeUtils.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+using namespace mlir::tosa;
+
+TEST(ValueKnowledgeTest, EqualityIgnoresErrors) {
+  SmallVector<int64_t> dimensions(16, 7);
+  ValueKnowledge valid(true, dimensions, {});
+  ValueKnowledge invalid = valid;
+  invalid.setHasError(true);
+  EXPECT_TRUE(valid);
+  EXPECT_FALSE(invalid);
+  EXPECT_EQ(valid, invalid);
+  EXPECT_NE(valid.sizes.getFlags(), invalid.sizes.getFlags());
+}
+
+TEST(ValueKnowledgeTest, JoinAndMeetPreserveRankAndErrors) {
+  SmallVector<int64_t> dimensions(16, 7);
+  ValueKnowledge ranked(true, dimensions, {});
+  ValueKnowledge unranked = ValueKnowledge::getPessimisticValueState();
+  for (ValueKnowledge result : {ValueKnowledge::join(ranked, unranked),
+                                ValueKnowledge::join(unranked, ranked),
+                                ValueKnowledge::meet(ranked, ranked)}) {
+    EXPECT_TRUE(result);
+    EXPECT_TRUE(result.hasRank());
+    EXPECT_EQ(ArrayRef<int64_t>(result.sizes), ArrayRef<int64_t>(dimensions));
+  }
+  ValueKnowledge result = ValueKnowledge::meet(ranked, unranked);
+  EXPECT_TRUE(result);
+  EXPECT_FALSE(result.hasRank());
+
+  ValueKnowledge conflicting(true, {8}, {});
+  ValueKnowledge singleDimension(true, {7}, {});
+  result = ValueKnowledge::join(singleDimension, conflicting);
+  EXPECT_FALSE(result);
+  EXPECT_TRUE(result.hasRank());
+}
diff --git a/mlir/unittests/Interfaces/InferTypeOpInterfaceTest.cpp b/mlir/unittests/Interfaces/InferTypeOpInterfaceTest.cpp
index 5b4722478dded..9ab931a19c158 100644
--- a/mlir/unittests/Interfaces/InferTypeOpInterfaceTest.cpp
+++ b/mlir/unittests/Interfaces/InferTypeOpInterfaceTest.cpp
@@ -22,6 +22,38 @@
 
 using namespace mlir;
 
+TEST(ShapedTypeComponentsTest, RankedScalarAndUnrankedCopies) {
+  ShapedTypeComponents unranked;
+  ShapedTypeComponents scalar(ArrayRef<int64_t>{});
+  EXPECT_FALSE(unranked.hasRank());
+  EXPECT_TRUE(scalar.hasRank());
+  EXPECT_TRUE(scalar.getDims().empty());
+
+  unranked = scalar;
+  EXPECT_TRUE(unranked.hasRank());
+  unranked = ShapedTypeComponents();
+  EXPECT_FALSE(unranked.hasRank());
+}
+
+TEST(ShapedTypeComponentsTest, HeapBackedMovesAndShapeAdaptor) {
+  SmallVector<int64_t> dimensions(16, 7);
+  SmallVector<int64_t> input = dimensions;
+  int64_t *data = input.data();
+  ShapedTypeComponents shape(std::move(input));
+  EXPECT_EQ(shape.getDims().data(), data);
+  ShapedTypeComponents moved(std::move(shape));
+  EXPECT_TRUE(moved.hasRank());
+  EXPECT_EQ(moved.getDims(), ArrayRef<int64_t>(dimensions));
+
+  ShapedTypeComponents result;
+  ShapeAdaptor(moved).getDims(result);
+  EXPECT_TRUE(result.hasRank());
+  EXPECT_EQ(result.getDims(), ArrayRef<int64_t>(dimensions));
+  SmallVector<int64_t> output;
+  ShapeAdaptor(result).getDims(output);
+  EXPECT_EQ(output, dimensions);
+}
+
 class ValueShapeRangeTest : public testing::Test {
 protected:
   void SetUp() override {
diff --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h
index 086904f6b99dd..f320c104bb2de 100644
--- a/polly/include/polly/ScopInfo.h
+++ b/polly/include/polly/ScopInfo.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVectorWithFlags.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -263,7 +264,7 @@ class ScopArrayInfo final {
   Value *getBasePtr() const { return BasePtr; }
 
   // Set IsOnHeap to the value in parameter.
-  void setIsOnHeap(bool value) { IsOnHeap = value; }
+  void setIsOnHeap(bool value) { setIsOnHeapFlag(value); }
 
   /// For indirect accesses return the origin SAI of the BP, else null.
   const ScopArrayInfo *getBasePtrOriginSAI() const { return BasePtrOriginSAI; }
@@ -343,7 +344,7 @@ class ScopArrayInfo final {
   ///
   /// This property is only relevant if the array is allocated by Polly instead
   /// of pre-existing. If false, it is allocated using alloca instead malloca.
-  bool isOnHeap() const { return IsOnHeap; }
+  bool isOnHeap() const { return getIsOnHeapFlag(); }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   /// Dump a readable representation to stderr.
@@ -404,13 +405,14 @@ class ScopArrayInfo final {
   isl::id Id;
 
   /// True if the newly allocated array is on heap.
-  bool IsOnHeap = false;
+  bool getIsOnHeapFlag() const { return DimensionSizesPw.getFlag(0); }
+  void setIsOnHeapFlag(bool Value) { DimensionSizesPw.setFlag(0, Value); }
 
   /// The sizes of each dimension as SCEV*.
   SmallVector<const SCEV *, 4> DimensionSizes;
 
   /// The sizes of each dimension as isl::pw_aff.
-  SmallVector<isl::pw_aff, 4> DimensionSizesPw;
+  llvm::SmallVectorWithFlags<isl::pw_aff, 4> DimensionSizesPw;
 
   /// The type of this scop array info object.
   ///
@@ -566,7 +568,7 @@ class MemoryAccess final {
   Instruction *AccessInstruction = nullptr;
 
   /// Incoming block and value of a PHINode.
-  SmallVector<std::pair<BasicBlock *, Value *>, 4> Incoming;
+  llvm::SmallVectorWithFlags<std::pair<BasicBlock *, Value *>, 4> Incoming;
 
   /// The value associated with this memory access.
   ///
@@ -581,7 +583,8 @@ class MemoryAccess final {
   AssertingVH<Value> AccessValue;
 
   /// Are all the subscripts affine expression?
-  bool IsAffine = true;
+  bool getIsAffine() const { return !Incoming.getFlag(0); }
+  void setIsAffine(bool Value) { Incoming.setFlag(0, !Value); }
 
   /// Subscript expression for each dimension.
   SubscriptsTy Subscripts;
@@ -1079,7 +1082,7 @@ class MemoryAccess final {
 #endif
 
   /// Is the memory access affine?
-  bool isAffine() const { return IsAffine; }
+  bool isAffine() const { return getIsAffine(); }
 };
 
 raw_ostream &operator<<(raw_ostream &OS, MemoryAccess::ReductionType RT);
@@ -1669,13 +1672,18 @@ class Scop final {
   AccFuncVector AccessFunctions;
 
   /// Flag to indicate that the scheduler actually optimized the SCoP.
-  bool IsOptimized = false;
+  bool getIsOptimized() const { return InvariantEquivClasses.getFlag(0); }
+  void setIsOptimized(bool Value) { InvariantEquivClasses.setFlag(0, Value); }
 
   /// True if the underlying region has a single exiting block.
-  bool HasSingleExitEdge;
+  bool getHasSingleExitEdge() const { return InvariantEquivClasses.getFlag(1); }
+  void setHasSingleExitEdge(bool Value) {
+    InvariantEquivClasses.setFlag(1, Value);
+  }
 
   /// Flag to remember if the SCoP contained an error block or not.
-  bool HasErrorBlock = false;
+  bool getHasErrorBlock() const { return InvariantEquivClasses.getFlag(2); }
+  void setHasErrorBlock(bool Value) { InvariantEquivClasses.setFlag(2, Value); }
 
   /// Max loop depth.
   unsigned MaxLoopDepth = 0;
@@ -1811,11 +1819,17 @@ class Scop final {
   isl::schedule Schedule;
 
   /// Is this Scop marked as not to be transformed by an optimization heuristic?
-  bool HasDisableHeuristicsHint = false;
+  bool getHasDisableHeuristicsHint() const {
+    return InvariantEquivClasses.getFlag(3);
+  }
+  void setHasDisableHeuristicsHint(bool Value) {
+    InvariantEquivClasses.setFlag(3, Value);
+  }
 
   /// Whether the schedule has been modified after derived from the CFG by
   /// ScopBuilder.
-  bool ScheduleModified = false;
+  bool getScheduleModified() const { return MinMaxAliasGroups.getFlag(0); }
+  void setScheduleModified(bool Value) { MinMaxAliasGroups.setFlag(0, Value); }
 
   /// The set of minimal/maximal accesses for each alias group.
   ///
@@ -1830,14 +1844,15 @@ class Scop final {
   ///
   /// During code generation we will create a runtime alias check for each alias
   /// group to ensure the SCoP is executed in an alias free environment.
-  MinMaxVectorPairVectorTy MinMaxAliasGroups;
+  llvm::SmallVectorWithFlagsFor<MinMaxVectorPairVectorTy, 1> MinMaxAliasGroups;
 
   /// Mapping from invariant loads to the representing invariant load of
   ///        their equivalence class.
   ValueToValueMap InvEquivClassVMap;
 
   /// List of invariant accesses.
-  InvariantEquivClassesTy InvariantEquivClasses;
+  llvm::SmallVectorWithFlagsFor<InvariantEquivClassesTy, 4>
+      InvariantEquivClasses;
 
   /// The smallest array index not yet assigned.
   long ArrayIdx = 0;
@@ -2130,18 +2145,16 @@ class Scop final {
   InvariantEquivClassTy *lookupInvariantEquivClass(Value *Val);
 
   /// Return the set of invariant accesses.
-  InvariantEquivClassesTy &getInvariantAccesses() {
-    return InvariantEquivClasses;
-  }
+  auto &getInvariantAccesses() { return InvariantEquivClasses; }
 
   /// Check if the scop has any invariant access.
   bool hasInvariantAccesses() { return !InvariantEquivClasses.empty(); }
 
   /// Mark the SCoP as optimized by the scheduler.
-  void markAsOptimized() { IsOptimized = true; }
+  void markAsOptimized() { setIsOptimized(true); }
 
   /// Check if the SCoP has been optimized by the scheduler.
-  bool isOptimized() const { return IsOptimized; }
+  bool isOptimized() const { return getIsOptimized(); }
 
   /// Return the ID of the Scop
   int getID() const { return ID; }
@@ -2276,9 +2289,7 @@ class Scop final {
   bool hasTrivialInvalidContext() const { return InvalidContext.is_empty(); }
 
   /// Return all alias groups for this SCoP.
-  const MinMaxVectorPairVectorTy &getAliasGroups() const {
-    return MinMaxAliasGroups;
-  }
+  const auto &getAliasGroups() const { return MinMaxAliasGroups; }
 
   void addAliasGroup(MinMaxVectorTy &MinMaxAccessesReadWrite,
                      MinMaxVectorTy &MinMaxAccessesReadOnly) {
@@ -2451,13 +2462,13 @@ class Scop final {
   bool isProfitable(bool ScalarsAreUnprofitable) const;
 
   /// Return true if the SCoP contained at least one error block.
-  bool hasErrorBlock() const { return HasErrorBlock; }
+  bool hasErrorBlock() const { return getHasErrorBlock(); }
 
   /// Notify SCoP that it contains an error block
-  void notifyErrorBlock() { HasErrorBlock = true; }
+  void notifyErrorBlock() { setHasErrorBlock(true); }
 
   /// Return true if the underlying region has a single exiting block.
-  bool hasSingleExitEdge() const { return HasSingleExitEdge; }
+  bool hasSingleExitEdge() const { return getHasSingleExitEdge(); }
 
   /// Print the static control part.
   ///
@@ -2576,7 +2587,7 @@ class Scop final {
 
   /// Whether the schedule is the original schedule as derived from the CFG by
   /// ScopBuilder.
-  bool isOriginalSchedule() const { return !ScheduleModified; }
+  bool isOriginalSchedule() const { return !getScheduleModified(); }
 
   /// Intersects the domains of all statements in the SCoP.
   ///
@@ -2672,10 +2683,12 @@ class Scop final {
 
   /// Is this Scop marked as not to be transformed by an optimization heuristic?
   /// In this case, only user-directed transformations are allowed.
-  bool hasDisableHeuristicsHint() const { return HasDisableHeuristicsHint; }
+  bool hasDisableHeuristicsHint() const {
+    return getHasDisableHeuristicsHint();
+  }
 
   /// Mark this Scop to not apply an optimization heuristic.
-  void markDisableHeuristics() { HasDisableHeuristicsHint = true; }
+  void markDisableHeuristics() { setHasDisableHeuristicsHint(true); }
 };
 
 /// Print Scop scop to raw_ostream OS.
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 6757f3ba057ea..522d23ab5ae49 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -919,7 +919,8 @@ MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
     : Kind(Kind), AccType(AccType), Statement(Stmt), InvalidDomain(),
       BaseAddr(BaseAddress), ElementType(ElementType),
       Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst),
-      AccessValue(AccessValue), IsAffine(Affine),
+      Incoming(decltype(this->Incoming)::withFlags(unsigned(!(Affine)))),
+      AccessValue(AccessValue),
       Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(),
       NewAccessRelation() {
   static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
@@ -1651,8 +1652,10 @@ Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
            DominatorTree &DT, ScopDetection::DetectionContext &DC,
            OptimizationRemarkEmitter &ORE, int ID)
     : IslCtx(isl_ctx_alloc(), isl_ctx_free), SE(&ScalarEvolution), DT(&DT),
-      R(R), name(std::nullopt), HasSingleExitEdge(R.getExitingBlock()), DC(DC),
-      ORE(ORE), Affinator(this, LI), ID(ID) {
+      R(R), name(std::nullopt), DC(DC), ORE(ORE), Affinator(this, LI),
+      InvariantEquivClasses(decltype(this->InvariantEquivClasses)::withFlags(
+          (unsigned(bool(R.getExitingBlock())) << 1))),
+      ID(ID) {
 
   // Options defaults that are different from ISL's.
   isl_options_set_schedule_serialize_sccs(IslCtx.get(), true);
@@ -2361,12 +2364,12 @@ void Scop::setSchedule(isl::union_map NewSchedule) {
   auto S = isl::schedule::from_domain(getDomains());
   Schedule = S.insert_partial_schedule(
       isl::multi_union_pw_aff::from_union_map(NewSchedule));
-  ScheduleModified = true;
+  setScheduleModified(true);
 }
 
 void Scop::setScheduleTree(isl::schedule NewSchedule) {
   Schedule = NewSchedule;
-  ScheduleModified = true;
+  setScheduleModified(true);
 }
 
 bool Scop::restrictDomains(isl::union_set Domain) {



More information about the llvm-branch-commits mailing list