[all-commits] [llvm/llvm-project] e640d9: [RISCV][GlobalISel] Fix legalizing ‘llvm.va_copy’ ...
bvlgah via All-commits
all-commits at lists.llvm.org
Thu Mar 28 03:09:41 PDT 2024
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: e640d9e725ef06b9787ab0ab884598f4f5532e48
https://github.com/llvm/llvm-project/commit/e640d9e725ef06b9787ab0ab884598f4f5532e48
Author: bvlgah <octopus.busts_0w at icloud.com>
Date: 2024-03-28 (Thu, 28 Mar 2024)
Changed paths:
M llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
M llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir
M llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll
Log Message:
-----------
[RISCV][GlobalISel] Fix legalizing ‘llvm.va_copy’ intrinsic (#86863)
Hi, I spotted a problem when running benchmarking programs on a RISCV64
device.
## Issue
Segmentation faults only occurred while running the programs compiled
with `GlobalISel` enabled.
Here is a small but complete example (it is adopted from [Google's
benchmark
framework](https://github.com/llvm/llvm-test-suite/blob/95a9f0d0b45056274f0bb4b0e0dd019023e414dc/MicroBenchmarks/libs/benchmark/src/colorprint.cc#L85-L119)
to reproduce the issue,
```cpp
#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <memory>
#include <string>
std::string FormatString(const char* msg, va_list args) {
// we might need a second shot at this, so pre-emptivly make a copy
va_list args_cp;
va_copy(args_cp, args);
std::size_t size = 256;
char local_buff[256];
auto ret = vsnprintf(local_buff, size, msg, args_cp);
va_end(args_cp);
// currently there is no error handling for failure, so this is hack.
// BM_CHECK(ret >= 0);
if (ret == 0) // handle empty expansion
return {};
else if (static_cast<size_t>(ret) < size)
return local_buff;
else {
// we did not provide a long enough buffer on our first attempt.
size = static_cast<size_t>(ret) + 1; // + 1 for the null byte
std::unique_ptr<char[]> buff(new char[size]);
ret = vsnprintf(buff.get(), size, msg, args);
// BM_CHECK(ret > 0 && (static_cast<size_t>(ret)) < size);
return buff.get();
}
}
std::string FormatString(const char* msg, ...) {
va_list args;
va_start(args, msg);
auto tmp = FormatString(msg, args);
va_end(args);
return tmp;
}
int main() {
std::string Str =
FormatString("%-*s %13s %15s %12s", static_cast<int>(20),
"Benchmark", "Time", "CPU", "Iterations");
std::cout << Str << std::endl;
}
```
Use `clang++ -fglobal-isel -o main main.cpp` to compile it.
## Cause
I have examined MIR, it shows that these segmentation faults resulted
from a small mistake about legalizing the intrinsic function
`llvm.va_copy`.
https://github.com/llvm/llvm-project/blob/36e74cfdbde208e384c72bcb52ea638303fb7d67/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp#L451-L453
`DstLst` and `Tmp` are placed in the wrong order.
## Changes
I have tweaked the test case `CodeGen/RISCV/GlobalISel/vararg.ll` so
that `s0` is used as the frame pointer (not in all checks) which points
to the starting address of the save area. I believe that it helps reason
about how `llvm.va_copy` is handled.
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list