https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119006
Bug ID: 119006
Summary: IPA ICF and LTO cause strcmp condition to be omitted
Product: gcc
Version: 14.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: ipa
Assignee: unassigned at gcc dot gnu.org
Reporter: jeff-gcc at caffeinated dot me.uk
Target Milestone: ---
When compiled with -O2 -flto (or more minimally: -O -finline
-fipa-icf-functions -foptimize-strlen -ftree-dse -ftree-vrp -flto), GCC
miscompiles the following code:
template struct FixedString {
FixedString(const char* str_) { *this = str_; }
bool operator==(const char* rhs_) const { return rhs_ and not
__builtin_strcmp(_str, rhs_); }
bool operator!=(const char* rhs_) const { return !(*this == rhs_); }
char _str[N + 1];
};
int fixedStringUser(const FixedString<10>& lhs, const char* rhs) {
return lhs == rhs;
}
void checkString(FixedString<127> reason_) {
if (reason_ != "StrOverTenChars") asm volatile("nop");
}
int main(int argc, char** argv) {
FixedString<127> fs = argv[1];
if (argc > 2) checkString(fs);
}
During LTO WPA, ICF replaces FixedString<127>::operator== with
FixedString<10>::operator==, and then LTRANS reasons that strcmp of a buffer
which can hold a string up to length 10 cannot be equal to a string longer than
10 characters, forgetting that the LHS is actually max length 127. This results
in `checkString` being reduced to the body of the `if` condition, i.e. just the
`asm volatile("nop")`.
Testing on godbolt (https://gcc.godbolt.org/z/bv3YqzTG5) shows that this has
been present since GCC11, and is still present in trunk.