16 changes: 8 additions & 8 deletions lld/MachO/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ void ObjCSelRefsHelper::initialize() {
auto Reloc = isec->relocs[0];
if (const auto *sym = Reloc.referent.dyn_cast<Symbol *>()) {
if (const auto *d = dyn_cast<Defined>(sym)) {
auto *cisec = cast<CStringInputSection>(d->isec);
auto *cisec = cast<CStringInputSection>(d->isec());
auto methname = cisec->getStringRefAtOffset(d->value);
methnameToSelref[CachedHashStringRef(methname)] = isec;
}
Expand Down Expand Up @@ -1127,7 +1127,7 @@ void FunctionStartsSection::finalizeContents() {
if (auto *objFile = dyn_cast<ObjFile>(file)) {
for (const Symbol *sym : objFile->symbols) {
if (const auto *defined = dyn_cast_or_null<Defined>(sym)) {
if (!defined->isec || !isCodeSection(defined->isec) ||
if (!defined->isec() || !isCodeSection(defined->isec()) ||
!defined->isLive())
continue;
addrs.push_back(defined->getVA());
Expand Down Expand Up @@ -1228,7 +1228,7 @@ void SymtabSection::emitStabs() {
if (!file || !file->compileUnit)
continue;

symbolsNeedingStabs.emplace_back(defined, defined->isec->getFile()->id);
symbolsNeedingStabs.emplace_back(defined, defined->isec()->getFile()->id);
}
}

Expand All @@ -1243,7 +1243,7 @@ void SymtabSection::emitStabs() {
InputFile *lastFile = nullptr;
for (SortingPair &pair : symbolsNeedingStabs) {
Defined *defined = pair.first;
InputSection *isec = defined->isec;
InputSection *isec = defined->isec();
ObjFile *file = cast<ObjFile>(isec->getFile());

if (lastFile == nullptr || lastFile != file) {
Expand All @@ -1256,7 +1256,7 @@ void SymtabSection::emitStabs() {
}

StabsEntry symStab;
symStab.sect = defined->isec->parent->index;
symStab.sect = defined->isec()->parent->index;
symStab.strx = stringTableSection.addString(defined->getName());
symStab.value = defined->getVA();

Expand Down Expand Up @@ -1407,7 +1407,7 @@ template <class LP> void SymtabSectionImpl<LP>::writeTo(uint8_t *buf) const {
nList->n_value = defined->value;
} else {
nList->n_type = scope | N_SECT;
nList->n_sect = defined->isec->parent->index;
nList->n_sect = defined->isec()->parent->index;
// For the N_SECT symbol type, n_value is the address of the symbol
nList->n_value = defined->getVA();
}
Expand Down Expand Up @@ -2000,7 +2000,7 @@ void ObjCMethListSection::setUp() {
assert(reloc && "Relocation expected at method list name slot");
auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
assert(def && "Expected valid Defined at method list name slot");
auto *cisec = cast<CStringInputSection>(def->isec);
auto *cisec = cast<CStringInputSection>(def->isec());
assert(cisec && "Expected method name to be in a CStringInputSection");
auto methname = cisec->getStringRefAtOffset(def->value);
if (!ObjCSelRefsHelper::getSelRef(methname))
Expand Down Expand Up @@ -2107,7 +2107,7 @@ void ObjCMethListSection::writeRelativeOffsetForIsec(
uint32_t symVA = def->getVA();

if (useSelRef) {
auto *cisec = cast<CStringInputSection>(def->isec);
auto *cisec = cast<CStringInputSection>(def->isec());
auto methname = cisec->getStringRefAtOffset(def->value);
ConcatInputSection *selRef = ObjCSelRefsHelper::getSelRef(methname);
assert(selRef && "Expected all selector names to already be already be "
Expand Down
39 changes: 20 additions & 19 deletions lld/MachO/UnwindInfoSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,16 @@ UnwindInfoSection::UnwindInfoSection()
// function symbols for each unique address regardless of whether they have
// associated unwind info.
void UnwindInfoSection::addSymbol(const Defined *d) {
if (d->unwindEntry)
if (d->unwindEntry())
allEntriesAreOmitted = false;
// We don't yet know the final output address of this symbol, but we know that
// they are uniquely determined by a combination of the isec and value, so
// we use that as the key here.
auto p = symbols.insert({{d->isec, d->value}, d});
auto p = symbols.insert({{d->isec(), d->value}, d});
// If we have multiple symbols at the same address, only one of them can have
// an associated unwind entry.
if (!p.second && d->unwindEntry) {
assert(p.first->second == d || !p.first->second->unwindEntry);
if (!p.second && d->unwindEntry()) {
assert(p.first->second == d || !p.first->second->unwindEntry());
p.first->second = d;
}
}
Expand All @@ -204,16 +204,16 @@ void UnwindInfoSectionImpl::prepare() {
// entries to the GOT. Hence the use of a MapVector for
// UnwindInfoSection::symbols.
for (const Defined *d : make_second_range(symbols))
if (d->unwindEntry) {
if (d->unwindEntry->getName() == section_names::compactUnwind) {
prepareRelocations(d->unwindEntry);
if (d->unwindEntry()) {
if (d->unwindEntry()->getName() == section_names::compactUnwind) {
prepareRelocations(d->unwindEntry());
} else {
// We don't have to add entries to the GOT here because FDEs have
// explicit GOT relocations, so Writer::scanRelocations() will add those
// GOT entries. However, we still need to canonicalize the personality
// pointers (like prepareRelocations() does for CU entries) in order
// to avoid overflowing the 3-personality limit.
FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry];
FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];
fde.personality = canonicalizePersonality(fde.personality);
}
}
Expand Down Expand Up @@ -279,7 +279,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
if (auto *defined = dyn_cast<Defined>(s)) {
// Check if we have created a synthetic symbol at the same address.
Symbol *&personality =
personalityTable[{defined->isec, defined->value}];
personalityTable[{defined->isec(), defined->value}];
if (personality == nullptr) {
personality = defined;
in.got->addEntry(defined);
Expand Down Expand Up @@ -321,7 +321,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
Symbol *UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) {
if (auto *defined = dyn_cast_or_null<Defined>(personality)) {
// Check if we have created a synthetic symbol at the same address.
Symbol *&synth = personalityTable[{defined->isec, defined->value}];
Symbol *&synth = personalityTable[{defined->isec(), defined->value}];
if (synth == nullptr)
synth = defined;
else if (synth != defined)
Expand All @@ -340,12 +340,12 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
CompactUnwindEntry &cu = cuEntries[i];
const Defined *d = symbolsVec[i].second;
cu.functionAddress = d->getVA();
if (!d->unwindEntry)
if (!d->unwindEntry())
return;

// If we have DWARF unwind info, create a slimmed-down CU entry that points
// to it.
if (d->unwindEntry->getName() == section_names::ehFrame) {
if (d->unwindEntry()->getName() == section_names::ehFrame) {
// The unwinder will look for the DWARF entry starting at the hint,
// assuming the hint points to a valid CFI record start. If it
// fails to find the record, it proceeds in a linear search through the
Expand All @@ -355,11 +355,11 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
// but since we don't keep track of that, just encode zero -- the start of
// the section is always the start of a CFI record.
uint64_t dwarfOffsetHint =
d->unwindEntry->outSecOff <= DWARF_SECTION_OFFSET
? d->unwindEntry->outSecOff
d->unwindEntry()->outSecOff <= DWARF_SECTION_OFFSET
? d->unwindEntry()->outSecOff
: 0;
cu.encoding = target->modeDwarfEncoding | dwarfOffsetHint;
const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry];
const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry()];
cu.functionLength = fde.funcLength;
// Omit the DWARF personality from compact-unwind entry so that we
// don't need to encode it.
Expand All @@ -368,14 +368,15 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
return;
}

assert(d->unwindEntry->getName() == section_names::compactUnwind);
assert(d->unwindEntry()->getName() == section_names::compactUnwind);

auto buf = reinterpret_cast<const uint8_t *>(d->unwindEntry->data.data()) -
target->wordSize;
auto buf =
reinterpret_cast<const uint8_t *>(d->unwindEntry()->data.data()) -
target->wordSize;
cu.functionLength =
support::endian::read32le(buf + cuLayout.functionLengthOffset);
cu.encoding = support::endian::read32le(buf + cuLayout.encodingOffset);
for (const Reloc &r : d->unwindEntry->relocs) {
for (const Reloc &r : d->unwindEntry()->relocs) {
if (r.offset == cuLayout.personalityOffset)
cu.personality = r.referent.get<Symbol *>();
else if (r.offset == cuLayout.lsdaOffset)
Expand Down
6 changes: 2 additions & 4 deletions lld/MachO/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,10 +725,9 @@ void Writer::scanSymbols() {
if (auto *defined = dyn_cast<Defined>(sym)) {
if (!defined->isLive())
continue;
defined->canonicalize();
if (defined->overridesWeakDef)
addNonWeakDefinition(defined);
if (!defined->isAbsolute() && isCodeSection(defined->isec))
if (!defined->isAbsolute() && isCodeSection(defined->isec()))
in.unwindInfo->addSymbol(defined);
} else if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
// This branch intentionally doesn't check isLive().
Expand Down Expand Up @@ -756,9 +755,8 @@ void Writer::scanSymbols() {
if (auto *defined = dyn_cast_or_null<Defined>(sym)) {
if (!defined->isLive())
continue;
defined->canonicalize();
if (!defined->isExternal() && !defined->isAbsolute() &&
isCodeSection(defined->isec))
isCodeSection(defined->isec()))
in.unwindInfo->addSymbol(defined);
}
}
Expand Down
2 changes: 0 additions & 2 deletions lldb/cmake/modules/LLDBConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ option(LLDB_SKIP_STRIP "Whether to skip stripping of binaries when installing ll
option(LLDB_SKIP_DSYM "Whether to skip generating a dSYM when installing lldb." OFF)
option(LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS
"Fail to configure if certain requirements are not met for testing." OFF)
option(LLDB_TEST_USE_VENDOR_PACKAGES
"Use packages from lldb/third_party/Python/module instead of system deps." OFF)

set(LLDB_GLOBAL_INIT_DIRECTORY "" CACHE STRING
"Path to the global lldbinit directory. Relative paths are resolved relative to the
Expand Down
8 changes: 0 additions & 8 deletions lldb/packages/Python/lldbsuite/test/lldb_pylint_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,6 @@ def child_dirs(parent_dir):
0, os.path.join(packages_python_child_dir, "test_runner", "lib")
)

# Handle third_party module/package directory.
third_party_module_dir = os.path.join(
check_dir, "third_party", "Python", "module"
)
for child_dir in child_dirs(third_party_module_dir):
# Yes, we embed the module in the module parent dir
sys.path.insert(0, child_dir)

# We're done.
break

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,14 @@ Status PlatformRemoteGDBServer::RunShellCommand(
signo_ptr, command_output, timeout);
}

bool PlatformRemoteGDBServer::CalculateMD5(const FileSpec &file_spec,
uint64_t &low, uint64_t &high) {
if (!IsConnected())
return false;

return m_gdb_client_up->CalculateMD5(file_spec, low, high);
}

void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
m_trap_handlers.push_back(ConstString("_sigtramp"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ class PlatformRemoteGDBServer : public Platform, private UserIDResolver {

void CalculateTrapHandlerSymbolNames() override;

bool CalculateMD5(const FileSpec &file_spec, uint64_t &low,
uint64_t &high) override;

const lldb::UnixSignalsSP &GetRemoteUnixSignals() override;

size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3419,7 +3419,7 @@ bool GDBRemoteCommunicationClient::GetFileExists(
}

bool GDBRemoteCommunicationClient::CalculateMD5(
const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
const lldb_private::FileSpec &file_spec, uint64_t &low, uint64_t &high) {
std::string path(file_spec.GetPath(false));
lldb_private::StreamString stream;
stream.PutCString("vFile:MD5:");
Expand All @@ -3433,8 +3433,44 @@ bool GDBRemoteCommunicationClient::CalculateMD5(
return false;
if (response.Peek() && *response.Peek() == 'x')
return false;
low = response.GetHexMaxU64(false, UINT64_MAX);
high = response.GetHexMaxU64(false, UINT64_MAX);

// GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 concatenates low and
// high hex strings. We can't use response.GetHexMaxU64 because that can't
// handle the concatenated hex string. What would happen is parsing the low
// would consume the whole response packet which would give incorrect
// results. Instead, we get the byte string for each low and high hex
// separately, and parse them.
//
// An alternate way to handle this is to change the server to put a
// delimiter between the low/high parts, and change the client to parse the
// delimiter. However, we choose not to do this so existing lldb-servers
// don't have to be patched

// The checksum is 128 bits encoded as hex
// This means low/high are halves of 64 bits each, in otherwords, 8 bytes.
// Each byte takes 2 hex characters in the response.
const size_t MD5_HALF_LENGTH = sizeof(uint64_t) * 2;

// Get low part
auto part =
response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
if (part.size() != MD5_HALF_LENGTH)
return false;
response.SetFilePos(response.GetFilePos() + part.size());

if (part.getAsInteger(/*radix=*/16, low))
return false;

// Get high part
part =
response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
if (part.size() != MD5_HALF_LENGTH)
return false;
response.SetFilePos(response.GetFilePos() + part.size());

if (part.getAsInteger(/*radix=*/16, high))
return false;

return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
*command_output, // Pass nullptr if you don't want the command output
const Timeout<std::micro> &timeout);

bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low);
bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high);

lldb::DataBufferSP ReadRegister(
lldb::tid_t tid,
Expand Down
26 changes: 26 additions & 0 deletions lldb/source/Target/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,32 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
if (!source_file)
return Status(source_file.takeError());
Status error;

bool requires_upload = true;
uint64_t dest_md5_low, dest_md5_high;
bool success = CalculateMD5(destination, dest_md5_low, dest_md5_high);
if (!success) {
LLDB_LOGF(log, "[PutFile] couldn't get md5 sum of destination");
} else {
auto local_md5 = llvm::sys::fs::md5_contents(source.GetPath());
if (!local_md5) {
LLDB_LOGF(log, "[PutFile] couldn't get md5 sum of source");
} else {
const auto [local_md5_high, local_md5_low] = local_md5->words();
LLDB_LOGF(log, "[PutFile] destination md5: %016" PRIx64 "%016" PRIx64,
dest_md5_high, dest_md5_low);
LLDB_LOGF(log, "[PutFile] local md5: %016" PRIx64 "%016" PRIx64,
local_md5_high, local_md5_low);
requires_upload =
local_md5_high != dest_md5_high || local_md5_low != dest_md5_low;
}
}

if (!requires_upload) {
LLDB_LOGF(log, "[PutFile] skipping PutFile because md5sums match");
return error;
}

uint32_t permissions = source_file.get()->GetPermissions(error);
if (permissions == 0)
permissions = lldb::eFilePermissionsFileDefault;
Expand Down
3 changes: 0 additions & 3 deletions lldb/test/API/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,3 @@ def delete_module_cache(path):
# Propagate XDG_CACHE_HOME
if "XDG_CACHE_HOME" in os.environ:
config.environment["XDG_CACHE_HOME"] = os.environ["XDG_CACHE_HOME"]

if is_configured("use_vendor_packages"):
config.environment["LLDB_TEST_USE_VENDOR_PACKAGES"] = "1"
1 change: 0 additions & 1 deletion lldb/test/API/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ config.libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@"
# The API tests use their own module caches.
config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api")
config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api")
config.use_vendor_packages = @LLDB_TEST_USE_VENDOR_PACKAGES@

# Plugins
lldb_build_intel_pt = '@LLDB_BUILD_INTEL_PT@'
Expand Down
3 changes: 1 addition & 2 deletions lldb/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,7 @@ llvm_canonicalize_cmake_booleans(
LLDB_HAS_LIBCXX
LLDB_TOOL_LLDB_SERVER_BUILD
LLDB_USE_SYSTEM_DEBUGSERVER
LLDB_IS_64_BITS
LLDB_TEST_USE_VENDOR_PACKAGES)
LLDB_IS_64_BITS)

# Configure the individual test suites.
add_subdirectory(API)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,3 +592,26 @@ TEST_F(GDBRemoteCommunicationClientTest, WriteMemoryTags) {
std::vector<uint8_t>{0x99}, "QMemTags:456789,0:80000000:99",
"E03", false);
}

TEST_F(GDBRemoteCommunicationClientTest, CalculateMD5) {
FileSpec file_spec("/foo/bar", FileSpec::Style::posix);
uint64_t low, high;
std::future<bool> async_result = std::async(std::launch::async, [&] {
return client.CalculateMD5(file_spec, low, high);
});

lldb_private::StreamString stream;
stream.PutCString("vFile:MD5:");
stream.PutStringAsRawHex8(file_spec.GetPath(false));
HandlePacket(server, stream.GetString().str(),
"F,"
"deadbeef01020304"
"05060708deadbeef");
ASSERT_TRUE(async_result.get());

// Server and client puts/parses low, and then high
const uint64_t expected_low = 0xdeadbeef01020304;
const uint64_t expected_high = 0x05060708deadbeef;
EXPECT_EQ(expected_low, low);
EXPECT_EQ(expected_high, high);
}
14 changes: 0 additions & 14 deletions lldb/use_lldb_suite_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,11 @@
import sys


def add_third_party_module_dirs(lldb_root):
third_party_modules_dir = os.path.join(lldb_root, "third_party", "Python", "module")
if not os.path.isdir(third_party_modules_dir):
return

module_dirs = os.listdir(third_party_modules_dir)
for module_dir in module_dirs:
module_dir = os.path.join(third_party_modules_dir, module_dir)
sys.path.insert(0, module_dir)


def add_lldbsuite_packages_dir(lldb_root):
packages_dir = os.path.join(lldb_root, "packages", "Python")
sys.path.insert(0, packages_dir)


lldb_root = os.path.dirname(inspect.getfile(inspect.currentframe()))

# Use environment variables to avoid plumbing flags, lit configs, etc.
if os.getenv("LLDB_TEST_USE_VENDOR_PACKAGES"):
add_third_party_module_dirs(lldb_root)
add_lldbsuite_packages_dir(lldb_root)
1 change: 0 additions & 1 deletion lldb/utils/lldb-dotest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ set(LLDB_LIBS_DIR "${LLVM_LIBRARY_OUTPUT_INTDIR}")
llvm_canonicalize_cmake_booleans(
LLDB_BUILD_INTEL_PT
LLDB_HAS_LIBCXX
LLDB_TEST_USE_VENDOR_PACKAGES
)

if ("libcxx" IN_LIST LLVM_ENABLE_RUNTIMES)
Expand Down
4 changes: 0 additions & 4 deletions lldb/utils/lldb-dotest/lldb-dotest.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ has_libcxx = @LLDB_HAS_LIBCXX@
libcxx_libs_dir = "@LIBCXX_LIBRARY_DIR@"
libcxx_include_dir = "@LIBCXX_GENERATED_INCLUDE_DIR@"
libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@"
use_vendor_packages = @LLDB_TEST_USE_VENDOR_PACKAGES@

if __name__ == '__main__':
if use_vendor_packages:
os.putenv("LLDB_TEST_USE_VENDOR_PACKAGES", "1")

wrapper_args = sys.argv[1:]
dotest_args = []
# split on an empty string will produce [''] and if you
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
if (EnableSyntheticCounts && !PGOOpt)
MPM.addPass(SyntheticCountsPropagation());

if (EnablePGOForceFunctionAttrs)
if (EnablePGOForceFunctionAttrs && PGOOpt)
MPM.addPass(PGOForceFunctionAttrsPass(PGOOpt->ColdOptType));

MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/true));
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,6 @@ def HasStdExtAOrZalrsc
def FeatureStdExtZama16b
: SubtargetFeature<"zama16b", "HasStdExtZama16b", "true",
"'Zama16b' (Atomic 16-byte misaligned loads, stores and AMOs)">;
def HasStdExtZama16b : Predicate<"Subtarget->hasStdExtZama16b()">,
AssemblerPredicate<(all_of FeatureStdExtZama16b),
"'Zama16b' (Atomic 16-byte misaligned loads, stores and AMOs)">;

def FeatureStdExtZawrs : SubtargetFeature<"zawrs", "HasStdExtZawrs", "true",
"'Zawrs' (Wait on Reservation Set)">;
Expand Down
4 changes: 4 additions & 0 deletions llvm/test/Instrumentation/PGOForceFunctionAttrs/basic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

; Should be no changes without profile data
; RUN: opt < %s -passes=pgo-force-function-attrs -S -pgo-cold-func-opt=minsize | FileCheck %s --check-prefixes=NONE,CHECK
; RUN: opt < %s -passes='default<O2>' -enable-pgo-force-function-attrs -S -pgo-cold-func-opt=minsize | FileCheck %s --check-prefixes=O2

; NONE-NOT: Function Attrs:
; OPTSIZE: Function Attrs: optsize{{$}}
Expand Down Expand Up @@ -37,6 +38,9 @@
; CHECK-NOT: Function Attrs: {{.*}}minsize
; CHECK-NOT: Function Attrs: {{.*}}optnone

; O2: define void @cold_attr(){{.*}} #[[ATTR:[0-9]+]]
; O2-NOT: #[[ATTR]] = {{.*}}minsize

@s = global i32 0

define void @cold() !prof !27 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# RUN: cp %s %t && not %update_test_body %t 2>&1 | FileCheck %s

# CHECK: error: -: no part separator was found

.ifdef GEN
true
.endif
1 change: 0 additions & 1 deletion llvm/utils/gn/secondary/lldb/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ write_lit_cfg("lit_api_site_cfg") {
"LLDB_TEST_USER_ARGS=",
"LLDB_ENABLE_PYTHON=0",
"LLDB_HAS_LIBCXX=False", # FIXME: support this (?)
"LLDB_TEST_USE_VENDOR_PACKAGES=False",
"LLDB_LIBS_DIR=", # FIXME: for shared builds only (?)
"LLDB_TEST_ARCH=$current_cpu",
"LLDB_TEST_COMPILER=" + rebase_path("$root_build_dir/bin/clang"),
Expand Down
2 changes: 1 addition & 1 deletion mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ def NVVM_BarrierArriveOp : NVVM_PTXBuilder_Op<"barrier.arrive">
let extraClassDefinition = [{
std::string $cppClass::getPtx() {
std::string ptx = "bar.arrive ";
if (getBarrierId()) { ptx += "%0, %1'"; }
if (getBarrierId()) { ptx += "%0, %1"; }
else { ptx += "0, %0;"; }
return ptx;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,13 @@ void populateVectorLinearizeTypeConversionsAndLegality(
TypeConverter &typeConverter, RewritePatternSet &patterns,
ConversionTarget &target, unsigned targetBitWidth);

/// Populates patterns for linearizing ND (N >= 2) vector operations to 1D
/// vector shuffle operations.
void populateVectorLinearizeShuffleLikeOpsPatterns(TypeConverter &typeConverter,
RewritePatternSet &patterns,
ConversionTarget &target,
unsigned targetBitWidth);

} // namespace vector
} // namespace mlir

Expand Down
270 changes: 270 additions & 0 deletions mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeUtilities.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/ArrayRef.h"
#include <cstdint>
#include <numeric>

using namespace mlir;

Expand Down Expand Up @@ -103,6 +110,251 @@ struct LinearizeVectorizable final
return success();
}

private:
unsigned targetVectorBitWidth;
};

/// This pattern converts the ExtractStridedSliceOp into a ShuffleOp that works
/// on a linearized vector.
/// Following,
/// vector.extract_strided_slice %source
/// { offsets = [..], strides = [..], sizes = [..] }
/// is converted to :
/// %source_1d = vector.shape_cast %source
/// %out_1d = vector.shuffle %source_1d, %source_1d [ shuffle_indices_1d ]
/// %out_nd = vector.shape_cast %out_1d
/// `shuffle_indices_1d` is computed using the offsets and sizes of the
/// extraction.
struct LinearizeVectorExtractStridedSlice final
: public mlir::OpConversionPattern<mlir::vector::ExtractStridedSliceOp> {
using OpConversionPattern::OpConversionPattern;
LinearizeVectorExtractStridedSlice(
const TypeConverter &typeConverter, MLIRContext *context,
unsigned targetVectBitWidth = std::numeric_limits<unsigned>::max(),
PatternBenefit benefit = 1)
: OpConversionPattern(typeConverter, context, benefit),
targetVectorBitWidth(targetVectBitWidth) {}

LogicalResult
matchAndRewrite(vector::ExtractStridedSliceOp extractOp, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Type dstType = getTypeConverter()->convertType(extractOp.getType());
assert(!(extractOp.getVector().getType().isScalable() ||
dstType.cast<VectorType>().isScalable()) &&
"scalable vectors are not supported.");
if (!isLessThanTargetBitWidth(extractOp, targetVectorBitWidth))
return rewriter.notifyMatchFailure(
extractOp, "Can't flatten since targetBitWidth <= OpSize");

ArrayAttr offsets = extractOp.getOffsets();
ArrayAttr sizes = extractOp.getSizes();
ArrayAttr strides = extractOp.getStrides();
if (!isConstantIntValue(strides[0], 1))
return rewriter.notifyMatchFailure(
extractOp, "Strided slice with stride != 1 is not supported.");
Value srcVector = adaptor.getVector();
// If kD offsets are specified for nD source vector (n > k), the granularity
// of the extraction is greater than 1. In this case last (n-k) dimensions
// form the extraction granularity.
// Example :
// vector.extract_strided_slice %src {
// offsets = [0, 0], sizes = [2, 2], strides = [1, 1]} :
// vector<4x8x8xf32> to vector<2x2x8xf32>
// Here, extraction granularity is 8.
int64_t extractGranularitySize = 1;
int64_t nD = extractOp.getSourceVectorType().getRank();
int64_t kD = (int64_t)offsets.size();
int64_t k = kD;
while (k < nD) {
extractGranularitySize *= extractOp.getSourceVectorType().getShape()[k];
++k;
}
// Get total number of extracted slices.
int64_t nExtractedSlices = 1;
for (Attribute size : sizes) {
nExtractedSlices *= size.cast<IntegerAttr>().getInt();
}
// Compute the strides of the source vector considering first k dimensions.
llvm::SmallVector<int64_t, 4> sourceStrides(kD, extractGranularitySize);
for (int i = kD - 2; i >= 0; --i) {
sourceStrides[i] = sourceStrides[i + 1] *
extractOp.getSourceVectorType().getShape()[i + 1];
}
// Final shuffle indices has nExtractedSlices * extractGranularitySize
// elements.
llvm::SmallVector<int64_t, 4> indices(nExtractedSlices *
extractGranularitySize);
// Compute the strides of the extracted kD vector.
llvm::SmallVector<int64_t, 4> extractedStrides(kD, 1);
// Compute extractedStrides.
for (int i = kD - 2; i >= 0; --i) {
extractedStrides[i] =
extractedStrides[i + 1] * sizes[i + 1].cast<IntegerAttr>().getInt();
}
// Iterate over all extracted slices from 0 to nExtractedSlices - 1
// and compute the multi-dimensional index and the corresponding linearized
// index within the source vector.
for (int64_t i = 0; i < nExtractedSlices; ++i) {
int64_t index = i;
// Compute the corresponding multi-dimensional index.
llvm::SmallVector<int64_t, 4> multiDimIndex(kD, 0);
for (int64_t j = 0; j < kD; ++j) {
multiDimIndex[j] = (index / extractedStrides[j]);
index -= multiDimIndex[j] * extractedStrides[j];
}
// Compute the corresponding linearized index in the source vector
// i.e. shift the multiDimIndex by the offsets.
int64_t linearizedIndex = 0;
for (int64_t j = 0; j < kD; ++j) {
linearizedIndex +=
(offsets[j].cast<IntegerAttr>().getInt() + multiDimIndex[j]) *
sourceStrides[j];
}
// Fill the indices array form linearizedIndex to linearizedIndex +
// extractGranularitySize.
for (int64_t j = 0; j < extractGranularitySize; ++j) {
indices[i * extractGranularitySize + j] = linearizedIndex + j;
}
}
// Perform a shuffle to extract the kD vector.
rewriter.replaceOpWithNewOp<vector::ShuffleOp>(
extractOp, dstType, srcVector, srcVector,
rewriter.getI64ArrayAttr(indices));
return success();
}

private:
unsigned targetVectorBitWidth;
};

/// This pattern converts the ShuffleOp that works on nD (n > 1)
/// vectors to a ShuffleOp that works on linearized vectors.
/// Following,
/// vector.shuffle %v1, %v2 [ shuffle_indices ]
/// is converted to :
/// %v1_1d = vector.shape_cast %v1
/// %v2_1d = vector.shape_cast %v2
/// %out_1d = vector.shuffle %v1_1d, %v2_1d [ shuffle_indices_1d ]
/// %out_nd = vector.shape_cast %out_1d
// `shuffle_indices_1d` is computed using the sizes and `shuffle_indices`
/// of the original shuffle operation.
struct LinearizeVectorShuffle final
: public OpConversionPattern<vector::ShuffleOp> {
using OpConversionPattern::OpConversionPattern;
LinearizeVectorShuffle(
const TypeConverter &typeConverter, MLIRContext *context,
unsigned targetVectBitWidth = std::numeric_limits<unsigned>::max(),
PatternBenefit benefit = 1)
: OpConversionPattern(typeConverter, context, benefit),
targetVectorBitWidth(targetVectBitWidth) {}

LogicalResult
matchAndRewrite(vector::ShuffleOp shuffleOp, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Type dstType = getTypeConverter()->convertType(shuffleOp.getType());
assert(!(shuffleOp.getV1VectorType().isScalable() ||
shuffleOp.getV2VectorType().isScalable() ||
dstType.cast<VectorType>().isScalable()) &&
"scalable vectors are not supported.");
if (!isLessThanTargetBitWidth(shuffleOp, targetVectorBitWidth))
return rewriter.notifyMatchFailure(
shuffleOp, "Can't flatten since targetBitWidth <= OpSize");

Value vec1 = adaptor.getV1();
Value vec2 = adaptor.getV2();
int shuffleSliceLen = 1;
int rank = shuffleOp.getV1().getType().getRank();

// If rank > 1, we need to do the shuffle in the granularity of slices
// instead of scalars. Size of the slice is equal to the rank-1 innermost
// dims. Mask of the shuffle op specifies which slice to take from the
// outermost dim.
if (rank > 1) {
llvm::ArrayRef<int64_t> shape = shuffleOp.getV1().getType().getShape();
for (unsigned i = 1; i < shape.size(); ++i) {
shuffleSliceLen *= shape[i];
}
}

// For each value in the mask, we generate the indices of the source vectors
// that needs to be shuffled to the destination vector. If shuffleSliceLen >
// 1 we need to shuffle the slices (consecutive shuffleSliceLen number of
// elements) instead of scalars.
ArrayAttr mask = shuffleOp.getMask();
int64_t totalSizeOfShuffledElmnts = mask.size() * shuffleSliceLen;
llvm::SmallVector<int64_t, 2> indices(totalSizeOfShuffledElmnts);
for (auto [i, value] :
llvm::enumerate(mask.getAsValueRange<IntegerAttr>())) {

int64_t v = value.getZExtValue();
std::iota(indices.begin() + shuffleSliceLen * i,
indices.begin() + shuffleSliceLen * (i + 1),
shuffleSliceLen * v);
}

rewriter.replaceOpWithNewOp<vector::ShuffleOp>(
shuffleOp, dstType, vec1, vec2, rewriter.getI64ArrayAttr(indices));
return success();
}

private:
unsigned targetVectorBitWidth;
};

/// This pattern converts the ExtractOp to a ShuffleOp that works on a
/// linearized vector.
/// Following,
/// vector.extract %source [ position ]
/// is converted to :
/// %source_1d = vector.shape_cast %source
/// %out_1d = vector.shuffle %source_1d, %source_1d [ shuffle_indices_1d ]
/// %out_nd = vector.shape_cast %out_1d
/// `shuffle_indices_1d` is computed using the position of the original extract.
struct LinearizeVectorExtract final
: public OpConversionPattern<vector::ExtractOp> {
using OpConversionPattern::OpConversionPattern;
LinearizeVectorExtract(
const TypeConverter &typeConverter, MLIRContext *context,
unsigned targetVectBitWidth = std::numeric_limits<unsigned>::max(),
PatternBenefit benefit = 1)
: OpConversionPattern(typeConverter, context, benefit),
targetVectorBitWidth(targetVectBitWidth) {}
LogicalResult
matchAndRewrite(vector::ExtractOp extractOp, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Type dstTy = getTypeConverter()->convertType(extractOp.getType());
assert(!(extractOp.getVector().getType().isScalable() ||
dstTy.cast<VectorType>().isScalable()) &&
"scalable vectors are not supported.");
if (!isLessThanTargetBitWidth(extractOp, targetVectorBitWidth))
return rewriter.notifyMatchFailure(
extractOp, "Can't flatten since targetBitWidth <= OpSize");

// Dynamic position is not supported.
if (extractOp.hasDynamicPosition())
return rewriter.notifyMatchFailure(extractOp,
"dynamic position is not supported.");

llvm::ArrayRef<int64_t> shape = extractOp.getVector().getType().getShape();
int64_t size = extractOp.getVector().getType().getNumElements();

// Compute linearized offset.
int64_t linearizedOffset = 0;
llvm::ArrayRef<int64_t> offsets = extractOp.getStaticPosition();
for (auto [i, off] : llvm::enumerate(offsets)) {
size /= shape[i];
linearizedOffset += offsets[i] * size;
}

llvm::SmallVector<int64_t, 2> indices(size);
std::iota(indices.begin(), indices.end(), linearizedOffset);
rewriter.replaceOpWithNewOp<vector::ShuffleOp>(
extractOp, dstTy, adaptor.getVector(), adaptor.getVector(),
rewriter.getI64ArrayAttr(indices));

return success();
}

private:
unsigned targetVectorBitWidth;
};
Expand Down Expand Up @@ -145,3 +397,21 @@ void mlir::vector::populateVectorLinearizeTypeConversionsAndLegality(
patterns.add<LinearizeConstant, LinearizeVectorizable>(
typeConverter, patterns.getContext(), targetBitWidth);
}

void mlir::vector::populateVectorLinearizeShuffleLikeOpsPatterns(
TypeConverter &typeConverter, RewritePatternSet &patterns,
ConversionTarget &target, unsigned int targetBitWidth) {
target.addDynamicallyLegalOp<vector::ShuffleOp>(
[=](vector::ShuffleOp shuffleOp) -> bool {
return isLessThanTargetBitWidth(shuffleOp, targetBitWidth)
? (typeConverter.isLegal(shuffleOp) &&
shuffleOp.getResult()
.getType()
.cast<mlir::VectorType>()
.getRank() == 1)
: true;
});
patterns.add<LinearizeVectorShuffle, LinearizeVectorExtract,
LinearizeVectorExtractStridedSlice>(
typeConverter, patterns.getContext(), targetBitWidth);
}
2 changes: 1 addition & 1 deletion mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ func.func @fence_proxy() {
llvm.func @llvm_nvvm_barrier_arrive(%barID : i32, %numberOfThreads : i32) {
// CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive 0, $0;", "r" %[[numberOfThreads]] : (i32) -> ()
nvvm.barrier.arrive number_of_threads = %numberOfThreads
// CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive $0, $1'", "r,r" %[[barId]], %[[numberOfThreads]] : (i32, i32) -> ()
// CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive $0, $1", "r,r" %[[barId]], %[[numberOfThreads]] : (i32, i32) -> ()
nvvm.barrier.arrive id = %barID number_of_threads = %numberOfThreads
llvm.return
}
92 changes: 92 additions & 0 deletions mlir/test/Dialect/Vector/linearize.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,95 @@ func.func @test_0d_vector() -> vector<f32> {
// ALL: return %[[CST]]
return %0 : vector<f32>
}

// -----
// ALL-LABEL: test_extract_strided_slice_1
// ALL-SAME: (%[[ORIG_ARG:.*]]: vector<4x8xf32>) -> vector<2x2xf32> {
func.func @test_extract_strided_slice_1(%arg0 : vector<4x8xf32>) -> vector<2x2xf32> {
// DEFAULT: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<4x8xf32> to vector<32xf32>
// DEFAULT: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// DEFAULT-SAME: [4, 5, 12, 13] : vector<32xf32>, vector<32xf32>
// DEFAULT: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<4xf32> to vector<2x2xf32>
// DEFAULT: return %[[RES]] : vector<2x2xf32

// BW-128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<4x8xf32> to vector<32xf32>
// BW-128: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// BW-128-SAME: [4, 5, 12, 13] : vector<32xf32>, vector<32xf32>
// BW-128: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<4xf32> to vector<2x2xf32>
// BW-128: return %[[RES]] : vector<2x2xf32>

// BW-0: %[[RES:.*]] = vector.extract_strided_slice %[[ARG:.*]] {offsets = [0, 4], sizes = [2, 2], strides = [1, 1]} : vector<4x8xf32> to vector<2x2xf32>
// BW-0: return %[[RES]] : vector<2x2xf32>
%0 = vector.extract_strided_slice %arg0 { sizes = [2, 2], strides = [1, 1], offsets = [0, 4]}
: vector<4x8xf32> to vector<2x2xf32>
return %0 : vector<2x2xf32>
}

// -----
// ALL-LABEL: test_extract_strided_slice_2
// ALL-SAME: (%[[ORIG_ARG:.*]]: vector<2x8x2xf32>) -> vector<1x4x2xf32> {
func.func @test_extract_strided_slice_2(%arg0 : vector<2x8x2xf32>) -> vector<1x4x2xf32> {
// DEFAULT: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x8x2xf32> to vector<32xf32>
// DEFAULT: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// DEFAULT-SAME: [20, 21, 22, 23, 24, 25, 26, 27] : vector<32xf32>, vector<32xf32>
// DEFAULT: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<8xf32> to vector<1x4x2xf32>
// DEFAULT: return %[[RES]] : vector<1x4x2xf32>

// BW-128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x8x2xf32> to vector<32xf32>
// BW-128: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// BW-128-SAME: [20, 21, 22, 23, 24, 25, 26, 27] : vector<32xf32>, vector<32xf32>
// BW-128: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<8xf32> to vector<1x4x2xf32>
// BW-128: return %[[RES]] : vector<1x4x2xf32>

// BW-0: %[[RES:.*]] = vector.extract_strided_slice %[[ORIG_ARG]] {offsets = [1, 2], sizes = [1, 4], strides = [1, 1]} : vector<2x8x2xf32> to vector<1x4x2xf32>
// BW-0: return %[[RES]] : vector<1x4x2xf32>
%0 = vector.extract_strided_slice %arg0 { offsets = [1, 2], strides = [1, 1], sizes = [1, 4] }
: vector<2x8x2xf32> to vector<1x4x2xf32>
return %0 : vector<1x4x2xf32>
}

// -----
// ALL-LABEL: test_vector_shuffle
// ALL-SAME: (%[[ORIG_ARG0:.*]]: vector<4x2xf32>, %[[ORIG_ARG1:.*]]: vector<4x2xf32>) -> vector<8x2xf32> {
func.func @test_vector_shuffle(%arg0: vector<4x2xf32>, %arg1: vector<4x2xf32>) -> vector<8x2xf32> {
// DEFAULT: %[[ARG0:.*]] = vector.shape_cast %[[ORIG_ARG0]] : vector<4x2xf32> to vector<8xf32>
// DEFAULT: %[[ARG1:.*]] = vector.shape_cast %[[ORIG_ARG1]] : vector<4x2xf32> to vector<8xf32>
// DEFAULT: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG0]], %[[ARG1]]
// DEFAULT-SAME: [0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32>
// DEFAULT: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<16xf32> to vector<8x2xf32>
// DEFAULT: return %[[RES]] : vector<8x2xf32>

// BW-128: %[[ARG0:.*]] = vector.shape_cast %[[ORIG_ARG0]] : vector<4x2xf32> to vector<8xf32>
// BW-128: %[[ARG1:.*]] = vector.shape_cast %[[ORIG_ARG1]] : vector<4x2xf32> to vector<8xf32>
// BW-128: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG0]], %[[ARG1]]
// BW-128-SAME: [0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15] : vector<8xf32>, vector<8xf32>
// BW-128: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<16xf32> to vector<8x2xf32>
// BW-128: return %[[RES]] : vector<8x2xf32>

// BW-0: %[[RES:.*]] = vector.shuffle %[[ORIG_ARG0]], %[[ORIG_ARG1]] [0, 4, 1, 5, 2, 6, 3, 7] : vector<4x2xf32>, vector<4x2xf32>
// BW-0: return %[[RES]] : vector<8x2xf32>
%0 = vector.shuffle %arg0, %arg1 [0, 4, 1, 5, 2, 6, 3, 7] : vector<4x2xf32>, vector<4x2xf32>
return %0 : vector<8x2xf32>
}

// -----
// ALL-LABEL: test_vector_extract
// ALL-SAME: (%[[ORIG_ARG:.*]]: vector<2x8x2xf32>) -> vector<8x2xf32> {
func.func @test_vector_extract(%arg0: vector<2x8x2xf32>) -> vector<8x2xf32> {
// DEFAULT: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x8x2xf32> to vector<32xf32>
// DEFAULT: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// DEFAULT-SAME: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] : vector<32xf32>, vector<32xf32>
// DEFAULT: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<16xf32> to vector<8x2xf32>
// DEFAULT: return %[[RES]] : vector<8x2xf32>

// BW-128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x8x2xf32> to vector<32xf32>
// BW-128: %[[SHUFFLE:.*]] = vector.shuffle %[[ARG]], %[[ARG]]
// BW-128-SAME: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] : vector<32xf32>, vector<32xf32>
// BW-128: %[[RES:.*]] = vector.shape_cast %[[SHUFFLE]] : vector<16xf32> to vector<8x2xf32>
// BW-128: return %[[RES]] : vector<8x2xf32>

// BW-0: %[[RES:.*]] = vector.extract %[[ORIG_ARG]][1] : vector<8x2xf32> from vector<2x8x2xf32>
// BW-0: return %[[RES]] : vector<8x2xf32>
%0 = vector.extract %arg0[1]: vector<8x2xf32> from vector<2x8x2xf32>
return %0 : vector<8x2xf32>
}
2 changes: 2 additions & 0 deletions mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,8 @@ struct TestVectorLinearize final

vector::populateVectorLinearizeTypeConversionsAndLegality(
typeConverter, patterns, target, targetVectorBitwidth);
vector::populateVectorLinearizeShuffleLikeOpsPatterns(
typeConverter, patterns, target, targetVectorBitwidth);
if (failed(applyPartialConversion(getOperation(), target,
std::move(patterns))))
return signalPassFailure();
Expand Down
3 changes: 3 additions & 0 deletions utils/bazel/llvm-project-overlay/libc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,7 @@ libc_support_library(
deps = [
":__support_common",
":__support_cpp_bit",
":__support_macros_sanitizer",
],
)

Expand Down Expand Up @@ -2998,6 +2999,7 @@ libc_function(
hdrs = ["src/unistd/pipe.h"],
deps = [
":__support_common",
":__support_macros_sanitizer",
":__support_osutil_syscall",
":errno",
],
Expand Down Expand Up @@ -3025,6 +3027,7 @@ libc_function(
}),
deps = [
":__support_common",
":__support_macros_sanitizer",
":__support_osutil_syscall",
":errno",
],
Expand Down
1 change: 1 addition & 0 deletions utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11632,6 +11632,7 @@ cc_library(
":DialectUtils",
":FuncDialect",
":IR",
":IndexDialect",
":InferTypeOpInterface",
":LinalgDialect",
":MathDialect",
Expand Down