[IR] Skip removeDeadConstantUsers use-list walks to save ~0.25% wall time (#240626)
GlobalOpt's `deleteIfDead` calls `removeDeadConstantUsers()` on every
global before checking whether it is dead. For a function, that walks
the whole use list, which is mostly call sites, and loads each user only
to find that it is an instruction. Those loads usually miss in cache. In
AMD IBS profiles of `opt -O2` on four large LLVM TUs (X86ISelLowering,
AArch64ISelLowering, DAGCombiner, ScalarEvolution),
`removeDeadConstantUsers` accounts for 10-19% of the loads served from
L3 or DRAM, but only about 0.5% of cycles.
Only constants that are not globals can be dead users, and with opaque
pointers most functions have none. This patch adds a `GlobalValue` bit,
`MayHaveConstantUsers`. The bit is set when such a constant takes the
global as an operand: in `ConstantUniqueMap::create` and
`replaceOperandsInPlace`, and for `DSOLocalEquivalent` and `NoCFIValue`.
`removeDeadConstantUsers` returns immediately when the bit is clear. It
clears the bit after a walk that leaves no live non-global constant
users. Only those constant-creation paths set the bit, and they are
[18 lines not shown]
[MemoryBuiltins] Check alloc/free type first to save ~0.1% instrs (#240677)
Profiling showed that `isAlloc*Fn` and `getFreedOperand` execute many
instructions to detect malloc-like and free-like instructions.
Rejecting calls with the wrong return type before querying attributes
and TargetLibraryInfo in these allocator classification routines reduces
opt's user instruction count by about 0.5% on a call-heavy InstCombine
microbenchmark, with no change in output.
Allocation functions return a pointer to the new block of memory, and
deallocation functions return void: LangRef requires this of
`allockind("free")` functions, and `isLibFreeFunction` already requires
it of library free functions. InstCombine calls `getFreedOperand` and
`isRemovableAlloc` on every call it visits, so the `nobuiltin`,
`allockind`, and TLI queries that these checks skip add up.
Compile-time tracker:
https://llvm-compile-time-tracker.com/compare.php?from=6e58f6f5536016c55365ac55be11e6ac783d64cf&to=bbbd87d2271c7f02d7bca8f881220647da532d99&stat=instructions:u
[6 lines not shown]
[InstSimplify] Check call args are constant first to save ~0.04% instrs (#240676)
`tryConstantFoldCall` runs two checks before continuing to fold:
1. It calls `canConstantFoldCallTo`, which checks if the call is marked
nobuiltin and that it is a known library call (cached)
2. It scans the arguments and bails out if any of them are non-Constant
It turns out that querying attributes and TLI is more expensive than
scanning for Constant arguments, so do that first. This patch swaps the
order so the common case exits early.
Compile-time tracker:
https://llvm-compile-time-tracker.com/compare.php?from=6e58f6f5536016c55365ac55be11e6ac783d64cf&to=ebc6a8a748f0d3338efc8c2633f057418ebca43a&stat=instructions:u
This is worth ~0.15% on my workload, but only ~0.04% on the CTT Clang
build. Again, I think this might show that my workload is intrinsic-call
heavy, but I haven't confirmed that yet.
LLM-aided
[Clang][CFI] Skip unused diagnostic data in trap and minimal-runtime vtable checks (#241640)
`EmitVTableCheck` emitted the static diagnostic data and, without
cross-DSO CFI, an `"all-vtables"` type test before deciding how to
report
a failure. Trap mode and the minimal runtime use neither, so they were
left as dead globals and instructions. Local trap mode also called
`EmitTrapCheck` directly instead of `EmitCheck`, so
`-fsanitize-skip-hot-cutoff` and `-ubsan-guard-checks` did not apply to
vtable checks.
Skip the static diagnostic data in trap mode and local minimal-runtime
checks, emit the `"all-vtables"` test only for local full-runtime
checks, and route local trap and minimal-runtime checks through
`EmitCheck`.
Assisted-by: Gemini
[GlobalISel] Fix MSVC build of KnownBitsTest after #241624 (#242097)
MSVC 2019 rejects the capture-less `ComputeSBFX` lambda in
`TestKnownBitsSBFXOperandTypes`, added in #241624, because it uses the
local `constexpr` `SrcBits` (error C3493, followed by C2064 at the call
sites). Make `SrcBits` static so that no capture is needed. Also compute
the loop bound with a 64-bit shift to avoid warning C4334.
Fixes the build on
https://lab.llvm.org/buildbot/#/builders/46/builds/44256.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
[CIR] Fold constant int/bool casts and narrow a constant ternary's re… (#241645)
…gions
CastOp::fold now folds constant `int_to_bool` and `bool_to_int` casts,
so canonicalize turns them into a `cir.const #true`/`#false` or the
matching integer constant. The folder reads its constant operand from
the fold adaptor instead of looking for a defining `cir.const`, so it
also works on attributes a caller supplies, as SCCP does.
`cir.ternary` implements `getEntrySuccessorRegions`: a constant
condition enters only one region, which lets SCCP and dead code analysis
see through a constant ternary. To declare it, the region-branch base
classes take an optional list of extra `RegionBranchOpInterface`
methods.
Besides general simplification, it also remove the need for custom
folding in https://github.com/llvm/llvm-project/pull/239774
[RISCV] Fix ReadAdvance for rotate instructions in Andes45 scheduling model (#241703)
The ReadRotate* reads were the only ReadAdvance entries in the model
with a nonzero value. Rotates execute on Andes45ALU like the other
integer ALU instructions, whose reads all have a ReadAdvance of 0, so
use 0 for the rotates as well.
Co-authored-by: Claude Fable 5.1 <noreply at anthropic.com>
[sanitizer_common] Measure strstr's haystack only if there is no match (#239871)
StrstrCheck, used by the interceptors of strstr and strcasestr, calls
internal_strlen on the haystack unconditionally, but uses that length
only if there was no match. A match at the start of a long string
therefore costs time proportional to the length of the string, and the
usual loop
`while ((p = strstr(p, needle))) { ...; p++; }`
is quadratic in the size of the buffer.
Compute the length only when it is needed. The ranges that are checked
are the same as before.
One case differs: for a haystack that has no terminator in front of an
unmapped page, the old code crashes in internal_strlen even if strstr
finds a match. Unless strict_string_checks is set, the new code does not
read past what strstr itself reads.
The new test strstr-match.c pins down which part of the haystack is
[6 lines not shown]
[AMDGPU] Trim unused leading components of tbuffer loads (#240750)
Trim unused leading components of `tbuffer.load` in
`simplifyAMDGCNMemoryIntrinsicDemanded`. Untyped buffer loads already do
this; tbuffer loads were a TODO.
The format describes the whole element, so moving the offset alone is
not enough. Skipping `k` leading components:
- adds `k * BitsPerComp / 8` to the offset. The component size comes
from the format, not the result type (they differ for d16 and for
8/16-bit formats returning `float`).
- switches to the format with `k` fewer components, so the element still
ends at the same byte and bounds checking is unchanged.
The trim is skipped if no such format exists (e.g. there is no
`16_16_16`, packed formats) or if a demanded lane is past the end of the
format. The format table depends on the subtarget, hence the new
`GCNSubtarget` parameter.
[4 lines not shown]
[CIR] Support annotations on locals, parameters, fields, and __builtin_annotation (#240666)
ClangIR only handled `__attribute__((annotate(...)))` on globals and
functions. Everywhere else it was either silently dropped or not
implemented:
```cpp
struct S { int v __attribute__((annotate("on_field"))); }; // NYI
int f(int p __attribute__((annotate("on_param")))) { // dropped, no diagnostic
int x __attribute__((annotate("on_local"))); // dropped, no diagnostic
return __builtin_annotation(p, "on_builtin"); // NYI
}
```
Further, Global annotations crashed on targets whose globals don't live
in address space 0, such as SYCL device code on SPIR-V and AMDGPU:
```
error: 'llvm.mlir.addressof' op pointer address space must match address space of the referenced global or alias
```
This patch adds three ops that mirror the LLVM dialect's annotation
[31 lines not shown]
[clang] Include definition ranges in macro info dumps (#241185)
`MacroInfo::dump()` omits the macro's definition range, making it harder
to trace the original definition after `#pragma pop_macro` restores it.
Print the definition range while preserving the no-argument overload for
debugger use.
[clang] Include source locations in macro directive dumps (#240172)
`#pragma clang __debug macro` dumps macro directive history without
showing where each directive occurred.
Pass the `SourceManager` to `MacroDirective::dump()` and print each
directive's location alongside its address, making definitions and
undefinitions easier to trace.
[clang][NFC] Remove unused MacroDirective PCH origin tracking (#240171)
`MacroDirective::IsFromPCH` is never set, and its accessors have no
callers. Macro history serialization instead uses the identifier's
deserialization and change state.
Remove the unused flag, accessors, and corresponding `dump()` output.