431 Commits

Author SHA1 Message Date
Martin Sebor
b19194c032 [InstCombine] handle subobjects of constant aggregates
Remove the known limitation of the library function call folders to only
work with top-level arrays of characters (as per the TODO comment in
the code) and allows them to also fold calls involving subobjects of
constant aggregates such as member arrays.
2022-06-21 11:55:14 -06:00
Martin Sebor
5fb67e32f8 [InstCombine] Fold memcmp of constant arrays and variable size
The memcmp simplifier is limited to folding to constants calls with constant
arrays and constant sizes.  This change adds the ability to simplify
memcmp(A, B, N) calls with constant A and B and variable N to the pseudocode
equivalent of

N <= Pos ? 0 : (A < B ? -1 : B < A ? +1 : 0)

where Pos is the offset of the first mismatch between A and B.

Differential Revision: https://reviews.llvm.org/D127766
2022-06-17 10:35:35 -06:00
Nikita Popov
2dac2c4f76 [SimplifyLibCalls] Drop duplicate check (NFC)
The same condition already exists inside optimizeMemCmpConstantSize().
2022-06-15 09:37:09 +02:00
Martin Sebor
dd2a6d78ee [InstCombine] Fold memchr of sequences of same characters
Enhance memchr libcall folder to handle constant arrays consisting
of one or two sequences of cosecutive equal characters.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D126515
2022-06-07 13:45:10 -06:00
Martin Sebor
fb6627fa0c [InstCombine] Add substr helper function (NFC).
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D126515
2022-06-07 13:27:36 -06:00
Martin Sebor
46c0ec9df4 [InstCombine] Fold memrchr calls with sequences of identical bytes.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123631
2022-05-24 17:00:11 -06:00
Sanjay Patel
be7f09f7b2 [IR] create and use helper functions that test the signbit; NFCI 2022-05-16 11:26:23 -04:00
Jonas Paulsson
304378fd09 Reapply "[BuildLibCalls] Introduce getOrInsertLibFunc() for use when building
libcalls." (was 0f8c626). This reverts commit 14d9390.

The patch previously failed to recognize cases where user had defined a
function alias with an identical name as that of the library
function. Module::getFunction() would then return nullptr which is what the
sanitizer discovered.

In this updated version a new function isLibFuncEmittable() has as well been
introduced which is now used instead of TLI->has() anytime a library function
is to be emitted . It additionally also makes sure there is e.g. no function
alias with the same name in the module.

Reviewed By: Eli Friedman

Differential Revision: https://reviews.llvm.org/D123198
2022-05-02 19:37:00 +02:00
Martin Sebor
efa0f12c0b [InstCombine] Fold strnlen calls in equality to zero.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123818
2022-04-27 12:03:24 -06:00
Martin Sebor
ffed0cfcdb [SimplifyLibCalls] avoid slicing 64-bit integers in an ILP32 build (PR #54739)
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123472
2022-04-26 17:20:56 -06:00
Martin Sebor
449adafabe [InstCombine] Fold strnlen of constant strings.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123817
2022-04-26 16:15:28 -06:00
Martin Sebor
ce8f42d4af [InstCombine] Fold memrchr calls with a constant character.
Reviewed By: nikic

Differential Revision: //reviews.llvm.org/D123629
2022-04-26 14:02:50 -06:00
Martin Sebor
10c99ce67d [InstCombine] Fold memrchr calls with constant size, bail on excessive.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123626
Differential Revision: https://reviews.llvm.org/D123628
2022-04-26 14:02:50 -06:00
Martin Sebor
25febbd155 [InstCombine] Fold strnlen with a bound of zero and one.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123816
2022-04-26 14:02:50 -06:00
Martin Sebor
2807c420cd [InstCombine] add a strnlen handler stub.
Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D123815
2022-04-26 14:02:49 -06:00
Fangrui Song
14d9390721 Revert D123198 "[BuildLibCalls] Introduce getOrInsertLibFunc() for use when building libcalls."
test/Transforms/InstCombine/pr39177.ll failed in a -DLLVM_USE_SANITIZER=Undefined build.
```
lib/Transforms/Utils/BuildLibCalls.cpp:1217:17: runtime error: reference binding to null pointer of type 'llvm::Function'
```
`Function &F = *M->getFunction(Name);`

This reverts commit 0f8c626723d2bbd547e78dcab5ab260dfbc437e1.
2022-04-19 22:26:10 -07:00
Jonas Paulsson
0f8c626723 [BuildLibCalls] Introduce getOrInsertLibFunc() for use when building libcalls.
A new set of overloaded functions named getOrInsertLibFunc() are now supposed
to be used instead of getOrInsertFunction() when building a libcall from
within an LLVM optimizer(). The idea is that this new function also makes
sure that any mandatory argument attributes are added to the function
prototype (after calling getOrInsertFunction()).

inferLibFuncAttributes() is renamed to inferNonMandatoryLibFuncAttrs() as it
only adds attributes that are not necessary for correctness but merely
helping with later optimizations.

Generally, the front end is responsible for building a correct function
prototype with the needed argument attributes. If the middle end however is
the one creating the call, e.g. when replacing one libcall with another, it
then must take this responsibility.

This continues the work of properly handling argument extension if required
by the target ABI when building a lib call. getOrInsertLibFunc() now does
this for all libcalls currently built by any LLVM optimizer. It is expected
that when in the future a new optimization builds a new libcall with an
integer argument it is to be added to getOrInsertLibFunc() with the proper
handling. Note that not all targets have it in their ABI to sign/zero extend
integer arguments to the full register width, but this will be done
selectively as determined by getExtAttrForI32Param().

Review: Eli Friedman, Nikita Popov, Dávid Bolvanský

Differential Revision: https://reviews.llvm.org/D123198
2022-04-19 21:22:07 +02:00
serge-sans-paille
262eba01b3 Revert "[ValueTracking] Make getStringLenth aware of strdup"
This reverts commit e810d558093cff40caaa1aff24d289c76c59916d.

The commit was not taken into account the fact that strduped string could be
modified. Checking if such modification happens would make the function very
costly, without a test case in mind it's not worth the effort.
2022-04-13 19:17:28 +02:00
Nikita Popov
8c74169990 [SimplifyLibCalls] Don't mark memchr() memory as fully dereferenceable
C11 specifies memchr() as follows:

> The memchr function locates the first occurrence of c (converted
> to an unsigned char) in the initial n characters (each interpreted
> as unsigned char) of the object pointed to by s. The implementation
> shall behave as if it reads the characters sequentially and stops
> as soon as a matching character is found.

In particular, it is well-defined to specify a memchr size larger
than the underlying object, as long as the character is found before
the end of the object.

Differential Revision: https://reviews.llvm.org/D123665
2022-04-13 16:46:18 +02:00
serge-sans-paille
e810d55809 [ValueTracking] Make getStringLenth aware of strdup
During strlen compile-time evaluation, make it possible to track size of
strduped strings.

Differential Revision: https://reviews.llvm.org/D123497
2022-04-12 14:47:29 +02:00
Nikita Popov
9af8cc8d17 [SimplifyLibCalls] Remove unnecessary inbounds check
Even if the GEP is not inbounds, the GEP will have provenance of
the global, and accessing past the extent of the global would be
undefined behavior.
2022-04-11 16:51:09 +02:00
Nikita Popov
1dc1d5a0d2 [SimplifyLibCalls] Use KnownBits helper APIs (NFC)
Use helper APIs for isNonNegative() and getMaxValue() instead of
flipping the zero value and having a long comment explaining why
that is necessary.
2022-04-06 16:01:24 +02:00
Martin Sebor
5ccfd5f6d4 [SimplifyLibCalls] Optimize memchr() with known char+str and unknown length
If both the character and string are known, but the length
potentially isn't, we can optimize the memchr() call to a select
of either the known position of the character or null.

Split off from https://reviews.llvm.org/D122836.
2022-04-04 11:01:33 +02:00
Martin Sebor
5197d2791f [SimplifyLibCalls] Move handling of constant char earlier (NFC)
Handle the simple constant char case before the bitmask optimization.
This will allow extending the code to handle a non-constant size
argument in a followup change.

Split out from https://reviews.llvm.org/D122836.
2022-04-04 11:01:33 +02:00
Martin Sebor
d18991debf [SimplifyLibCalls] Fold memchr() with size 1
If the memchr() size is 1, then we can convert the call into a
single-byte comparison. This works even if both the string and the
character are unknown.

Split off from https://reviews.llvm.org/D122836.
2022-04-04 10:41:20 +02:00
serge-sans-paille
a494ae43be Cleanup includes: TransformsUtils
Estimation on the impact on preprocessor output:
before: 1065307662
after:  1064800684

Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup
Differential Revision: https://reviews.llvm.org/D120741
2022-03-01 21:00:07 +01:00
Kazu Hirata
a1a8d10a17 [Transforms] Use default member initialization in LibCallSimplifier (NFC) 2022-02-06 16:36:27 -08:00
Nikita Popov
98db33349b [SLC] Fix pointer diff type in sprintf() optimization
We should always be calculating a byte-wise difference here.
Previously this calculated the pointer difference while taking
the pointer element type into account, which is incorrect.
2022-01-25 15:22:56 +01:00
Nikita Popov
30d4a7e295 [IRBuilder] Require explicit element type in CreatePtrDiff()
For opaque pointer compatibility, we cannot derive the element
type from the pointer type.
2022-01-25 12:43:57 +01:00
Serge Guelton
d2cc6c2d0c Use a sorted array instead of a map to store AttrBuilder string attributes
Using and std::map<SmallString, SmallString> for target dependent attributes is
inefficient: it makes its constructor slightly heavier, and involves extra
allocation for each new string attribute. Storing the attribute key/value as
strings implies extra allocation/copy step.

Use a sorted vector instead. Given the low number of attributes generally
involved, this is cheaper, as showcased by

https://llvm-compile-time-tracker.com/compare.php?from=5de322295f4ade692dc4f1823ae4450ad3c48af2&to=05bc480bf641a9e3b466619af43a2d123ee3f71d&stat=instructions

Differential Revision: https://reviews.llvm.org/D116599
2022-01-10 14:49:53 +01:00
Nick Desaulniers
95ba0e4563 [SimplifyLibCalls] propagate tail flags on CallInsts
I noticed we weren't propagating tail flags on calls when
FortifiedLibCallSimplifier.optimizeCall() was replacing calls to runtime
checked calls to the non-checked routines (when safe to do so). Make
sure to check this before replacing the original calls!

Also, avoid any libcall transforms when notail/musttail is present.

PR46734
Fixes: https://github.com/llvm/llvm-project/issues/46079

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D107872
2021-12-13 11:18:30 -08:00
Kazu Hirata
6fe949c4ed [Target, Transforms] Use StringRef::contains (NFC) 2021-10-22 08:52:33 -07:00
Bjorn Pettersson
7f84fa4ad4 [TargetLibraryInfo] Refactor size_t checks in isValidProtoForLibFunc. NFC
In TargetLibraryInfoImpl::isValidProtoForLibFunc we no longer
need the IsSizeTTy lambda function and the SizeTTy object. Instead
we just follow the regular structure of checking for integer types
given an exepected number of bits.
2021-10-04 15:46:39 +02:00
Kazu Hirata
4f0225f6d2 [Transforms] Migrate from getNumArgOperands to arg_size (NFC)
Note that getNumArgOperands is considered a legacy name.  See
llvm/include/llvm/IR/InstrTypes.h for details.
2021-10-01 09:57:40 -07:00
Dávid Bolvanský
9c476172b9 [InstCombine] stpcpy(d,s) -> strcpy(d,s) if the result is not used 2021-09-05 12:12:07 +02:00
Arthur Eubanks
44a3241f10 [NFC] Replace some attribute methods that use confusing indexes 2021-08-19 14:10:26 -07:00
Arthur Eubanks
3f4d00bc3b [NFC] More get/removeAttribute() cleanup 2021-08-17 21:05:41 -07:00
Arthur Eubanks
80ea2bb574 [NFC] Rename AttributeList::getParam/Ret/FnAttributes() -> get*Attributes()
This is more consistent with similar methods.
2021-08-13 11:16:52 -07:00
Dawid Jurczak
f8cdde7195 [SimplifyLibCalls][NFC] Clean up LibCallSimplifier from 'memset + malloc into calloc' transformation
FoldMallocMemset can be safely removed because since https://reviews.llvm.org/D103009
such transformation is already performed in DSE.

Differential Revision: https://reviews.llvm.org/D103451
2021-08-05 16:08:32 +02:00
Sanjay Patel
87d604ffe4 [SimplifyLibCalls] avoid crash on pointer math
We could try harder to screen out libcalls by
function signature (and that would be a much larger
change than for sprintf alone), but that might make
the transition to type-less pointers more difficult.

https://llvm.org/PR51200
2021-07-26 11:08:45 -04:00
Sanjay Patel
d8260269c3 [SimplifyLibCalls] reduce code duplication; NFC 2021-07-26 11:08:45 -04:00
Juneyoung Lee
1605593440 [SimplifyLibCalls] Fix memchr opt to use CreateLogicalAnd
This fixes a bug at LibCallSimplifier::optimizeMemChr which does the following transformation:

```
// memchr("\r\n", C, 2) != nullptr -> (1 << C & ((1 << '\r') | (1 << '\n')))
// != 0
//   after bounds check.
```

As written above, a bounds check on C (whether it is less than integer bitwidth) is done before doing `1 << C` otherwise 1 << C will overflow.
If the bounds check is false, the result of (1 << C & ...) must not be used at all, otherwise the result of shift (which is poison) will contaminate the whole results.
A correct way to encode this is `select i1 (bounds check), (1 << C & ...), false`  because select does not allow the unused operand to contaminate the result.
However, this optimization was introducing `and (bounds check), (1 << C & ...)` which cannot do that.

The bug was found from compilation of this C++ code: https://reviews.llvm.org/rG2fd3037ac615#1007197

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D104901
2021-06-26 05:59:35 +09:00
Arthur Eubanks
1aa02b37e7 Revert "[BuildLibCalls/SimplifyLibCalls] Fix attributes on created CallInst instructions."
This reverts commit 1eda5453f2dcc9a9a4b4578fe74163c529974503.

Causes https://crbug.com/1223647:
Incompatible argument and return types for 'returned' attribute
  tail call void @llvm.memset.p0i8.i64(i8* noalias noundef returned writeonly align 1 dereferenceable(255) %arraydecay, i8 0, i64 255, i1 false), !dbg !985
2021-06-24 19:24:34 -07:00
Jonas Paulsson
1eda5453f2 [BuildLibCalls/SimplifyLibCalls] Fix attributes on created CallInst instructions.
- When emitting libcalls, do not only pass the calling convention from the
  function prototype but also the attributes.

- Do not pass attributes from e.g. libc memcpy to llvm.memcpy.

Review: Reid Kleckner, Eli Friedman, Arthur Eubanks

Differential Revision: https://reviews.llvm.org/D103992
2021-06-24 14:47:24 -05:00
Bjorn Pettersson
4c7f820b2b Update @llvm.powi to handle different int sizes for the exponent
This can be seen as a follow up to commit 0ee439b705e82a4fe20e2,
that changed the second argument of __powidf2, __powisf2 and
__powitf2 in compiler-rt from si_int to int. That was to align with
how those runtimes are defined in libgcc.
One thing that seem to have been missing in that patch was to make
sure that the rest of LLVM also handle that the argument now depends
on the size of int (not using the si_int machine mode for 32-bit).
When using __builtin_powi for a target with 16-bit int clang crashed.
And when emitting libcalls to those rtlib functions, typically when
lowering @llvm.powi), the backend would always prepare the exponent
argument as an i32 which caused miscompiles when the rtlib was
compiled with 16-bit int.

The solution used here is to use an overloaded type for the second
argument in @llvm.powi. This way clang can use the "correct" type
when lowering __builtin_powi, and then later when emitting the libcall
it is assumed that the type used in @llvm.powi matches the rtlib
function.

One thing that needed some extra attention was that when vectorizing
calls several passes did not support that several arguments could
be overloaded in the intrinsics. This patch allows overload of a
scalar operand by adding hasVectorInstrinsicOverloadedScalarOpd, with
an entry for powi.

Differential Revision: https://reviews.llvm.org/D99439
2021-06-17 09:38:28 +02:00
Bjorn Pettersson
9c54ee4378 [SimplifyLibCalls] Take size of int into consideration when emitting ldexp/ldexpf
When rewriting
  powf(2.0, itofp(x)) -> ldexpf(1.0, x)
  exp2(sitofp(x)) -> ldexp(1.0, sext(x))
  exp2(uitofp(x)) -> ldexp(1.0, zext(x))

the wrong type was used for the second argument in the ldexp/ldexpf
libc call, for target architectures with 16 bit "int" type.
The transform incorrectly used a bitcasted function pointer with
a 32-bit argument when emitting the ldexp/ldexpf call for such
targets.

The fault is solved by using the correct function prototype
in the call, by asking TargetLibraryInfo about the size of "int".
TargetLibraryInfo by default derives the size of the int type by
assuming that it is 16 bits for 16-bit architectures, and
32 bits otherwise. If this isn't true for a target it should be
possible to override that default in the TargetLibraryInfo
initializer.

Differential Revision: https://reviews.llvm.org/D99438
2021-06-02 11:40:34 +02:00
Dawid Jurczak
5f5974aeac [SimplifyLibCalls] Transform printf("%s", str) --> puts(str)/noop
Before this change LLVM cannot simplify printf in following cases:

printf("%s", "") --> noop
printf("%s", str"\n") --> puts(str)

From the other hand GCC can perform such transformations for many years:
https://godbolt.org/z/7nnqbedfe

Differential Revision: https://reviews.llvm.org/D100724
2021-04-28 10:29:07 -04:00
Dawid Jurczak
57f443c348 [SimplifyLibCalls][NFC] Use StringRef::back instead explicit indexing.
Split off from D100724.

Reviewed By: xbolva00

Differential Revision: https://reviews.llvm.org/D101032
2021-04-22 15:02:47 +02:00
sstefan1
656ebd519e [SimplifyLibCalls] Don't change alignment when creating memset
Fix for PR49984
This was discovered during Attributor testing.
Memset was always created with alignment of 1
and in case when strncpy alignment was changed
it triggered an assertion in the AttrBuilder.
Memset will now be created with appropriate alignment.

Differential Revision: https://reviews.llvm.org/D100875
2021-04-21 20:34:13 +02:00
Yuanfang Chen
c5fda0e662 Reland "Revert "[InstCombine] when calling conventions are compatible, don't convert the call to undef idiom""
This reverts commit a3fabc79ae9d7dd76545b2abc2a3bfb66c6d3175 (relands
f4d682d6ce6c5b3a41a0acf297507c82f5c21eef with fix for the compile-time
regression issue).
2021-04-12 14:50:54 -07:00