598 Commits
Author SHA1 Message Date
Matt ArsenaultandClaude Opus 64c74930fe CodeGen: Read the exception model from the module flag (#232964)
Module::getExceptionModel() now falls back to the triple's default
model instead of falling back to the TargetMachine.

The pass pipeline is built before the module is known, so schedule each
EH preparation pass when the target supports a model, and let the pass
check the module's model. Add TargetMachine::supportsExceptionModel so
the pass config can skip definitely irrelevant passes. SjLjEHPrepare is
now scheduled on every target with exception handling, and WinEHPrepare
only on COFF and Wasm targets. WinEHPrepare and WasmEHPrepare are
scheduled for Wasm by the base pass configs, replacing the WebAssembly
override.

This is almost the last step towards removing
TargetOptions::ExceptionModel.

Co-authored-by: Claude Opus <noreply@anthropic.com>
2026-10-23 08:16:31 -07:00
Matt ArsenaultandClaude Opus 005b0ce22d MachineVerifier: Reject dead and live defs of the same register (#233110)
Previously an instruction could have a dead and a live def of the same
physical register, which has no consistent interpretation.

Some passes, namely register pressure tracking, implicitly rely on the
dead flag adjustments performed by running LiveVariables. In cases of
repeated defs, LiveVariables strips dead flags. When a super-register
is only partially used, it marks the super-register def dead and adds
a live implicit-def of the used sub-register.

Prior to #222627, pressure tracking treated live defs as winning. That
PR fixed some asserts by switching to a dead wins system where any
dead flag taints those regunits for the whole instruction. #225079
reverts the remainder of #222627, back closer to the interpretation of
this verifier check.

Only a dead def with a live def of the same register is
rejected. Mixed dead flags on overlapping defs of different registers
describe a partially used register: a dead super-register def with a
live sub-register def is the form LiveVariables uses when only the
sub-register is read, and a dead sub-register def with a live
super-register def is produced when the sub-register is redefined
before it is read.

Co-authored-by: Claude Opus <noreply@anthropic.com>
2026-10-19 16:33:12 +02:00
David Green a6a3689b76 [AArch64][GlobalISel] Remove G_DUP, replacing it with G_SPLAT_VECTOR (#230475)
This removes the target specific G_DUP, relying on the target
independant G_SPLAT_VECTOR instead. Most of the lowering is otherwise
kept the same, the largest change is to relax the verifier to allow
G_SPLAT_VECTOR to produce fixed-width vectors.
2026-10-14 13:13:38 +00:00
Matt ArsenaultandClaude 20738ea80b CodeGen: Drop dead LiveVariables optional-analysis paths (#230147)
Nothing queries the LiveVariables analysis anymore, so remove uses that only
ran when the analysis was available. Remove the verifier handling and the 
update in SplitCriticalEdge.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
2026-10-08 19:55:25 +00:00
Matt ArsenaultandClaude fbc222615d CodeGen: Pass instruction and operand index to isPCRelRegisterOperandLegal (#219420)
Replace the MachineOperand argument to the
TargetInstrInfo::isPCRelRegisterOperandLegal hook with the containing
instruction and operand index. The M68k implementation only used the
operand
to recover its parent instruction and operand number, so this drops the
dependence on MachineOperand::getParent().

Co-authored-by: Claude (Claude-Opus-4.8) <noreply@anthropic.com>

Co-authored-by: Claude (Claude-Opus-4.8) <noreply@anthropic.com>
2026-09-20 08:59:29 -05:00
Fangrui Song c37874b85b [CodeGen] Reject undef tied use sharing a virtual register with another read (#222832)
A virtual use operand, tied to a def of a different register, sharing
the register with another read, carries obligation that is hard to
follow by passes. For example, twoaddressinstruction would use different
physical registers, breaking the expectation of the `IsUndef` flag:

```
define void @f() {
  %y = freeze i32 undef
  %m = mul i32 %y, %y
  call void asm sideeffect "# use $0", "{cx}"(i32 %m)
  ret void
}

%2 = IMUL32rr undef %1(tied-def 0), undef %1   ; before twoaddressinstruction
%2 = IMUL32rr undef %2(tied-def 0), undef %1   ; after
imull %eax, %ecx                               ; different regs
```

RegAllocFast had the same issue until #222249. Let's just reject the
shape to retire the obligation. `%0 = XOR undef %0, undef %0` stays
legal, since rewriting that tie changes nothing.

ProcessImplicitDefs and DetectDeadLanes stop producing the rejected
form: such reads keep their IMPLICIT_DEF. Physical registers are
unaffected, so post-RA expansions like Expand2AddrUndef keep
`$eax = XOR32rr undef $eax, undef $eax`.

Aided by Opus 5
2026-09-19 19:37:15 -07:00
Aiden Grossman d34b9a8dbb [CodeGen] Add const MBB overload to analyzeBranch (#221847) 2026-09-08 08:58:58 -07:00
Folkert de Vries 72152fc6e2 [LLVM] Add llvm.vector.reduce.{min, max}imumnum (#218295)
fixes https://github.com/llvm/llvm-project/issues/185827

Really this is just a mechanical addition, using the fallback mechanism
for reductions (i.e. no custom lowerings yet).
2026-08-26 13:04:16 +02:00
Florian Mayer f83fcfbdc7 [MachineVerifier] do not use !NoPHI to check if a MF has phi nodes (#211941)
We were violating the property expressed in MachineFunction.h:

```
The properties are stated in "positive" form; i.e. a pass could require
that the property hold, but not that it does not hold.
```

Resolves a false positive "MBB has allocatable live-in, [...]" error in
our downstream target.
2026-07-27 18:41:31 +00:00
Alexis Engelke 4d8ec19680 [CodeGen][NFC] Remove RegisterClasses pointer array (#207204)
All MCRegisterClasses are stored consecutively in memory. Therefore, we
can remove the RegisterClassses pointer array and save 17kiB in
.data.rel.ro.
2026-07-03 06:33:37 +00:00
Ömer Sinan Ağacan 1338c5cb84 [GlobalISel] Implement llvm.memset.inline (#203198) 2026-06-16 08:10:08 +01:00
Cullen Rhodes c4484e8422 [CodeGen] De-type getMinimalPhysRegClass and related APIs (#197495)
Follow-up #193438 to de-type getMinimalPhysRegClass so it can be replaced with
the precomputed getDefaultMinimalPhysRegClass. Type is also removed from
related APIs.

There's very few uses of getMinimalPhysRegClass with a non-default type
(MVT::Other) and none at all for getCommonMinimalPhysRegClass. Rather than
trying to also handle the type when precomputing at compile-time it seems
better to remove the type altogether and simplify the APIs. This also improves
compile-time for a number of targets and configurations:

CTMark geomean:
- stage1-O3: -0.23%
- stage1-ReleaseThinLTO: -0.19%
- stage1-ReleaseLTO-g: -0.15%
- stage1-aarch64-O3: -0.57%
- stage2-O3: -0.23%
- clang: -0.13%

https://llvm-compile-time-tracker.com/compare.php?from=eae0b6b2498305ee29dc85a405ede9ccdc10ce7d&to=08c052a2db407d2a21d468001fd2035d3720acf7&stat=instructions%3Au

Assisted-by: codex
2026-06-02 06:49:26 +01:00
Gábor Spaits d3be056162 [GlobalISel]Allow mixing fixed and scalable vectors for G_INSERT_SUBVECTOR and G_EXTRACT_SUBVECTOR (#198012)
Allow `G_INSERT_SUBVECTOR` and `G_EXTRACT_SUBVECTOR` to
be used with a scalable and a fix length vector types, similar to the
OP's SelectionDAG version.
2026-05-20 10:19:19 +02:00
David Green ab6166ed34 [GlobalISel][AArch64] Allow bitcasts between fp types. (#196195)
This was failing the verifier as it was not considering different fp
types as a valid conversion for a bitcast.
2026-05-07 06:52:31 +01:00
Evgenii Kudriashov 3b32d6e525 [X86][GlobalISel] Support fp80 for G_FPTRUNC and G_FPEXT (#141611)
Introduce `G_FPEXTLOAD` and `G_FPTRUNCSTORE` for extending load and
truncating store of a floating point value.

* Introduce `IfFPExtend` and `IfFPTrunc` into `GINodeEquiv` to dispatch
SDAG patterns to the newly introduced opcodes similarly to `G_SEXTLOAD`
and `G_ZEXTLOAD`.
* Added narrowing and widening for the opcodes. However they aren't used
anywhere.
* Supported lowering of `G_FPEXTLOAD` and `G_FPTRUNCSTORE` for X86 by
using X87.
* Added `lowerFPExtAndTruncMem` as default lowering for `G_FPTRUNC` and
`G_FPEXT` using memory.
* Dropped autogenerated line from `legalizer-info-validation.mir` as
scripts can't update them anymore.
* Updated `match-table-cxx.td` with regexps. This is not the first PR
that updates the whole test after opcode introduction.
2026-05-02 22:16:30 +02:00
Fangrui Song 13e98d8341 [MC] Take MCAsmInfo by reference in MCContext and TargetMachine. NFC (#194280)
Both MCContext::MCContext and TargetMachine::getMCAsmInfo treat
MCAsmInfo as a pointer that must be non-null. Make the contract
explicit:

* MCContext's constructor takes `const MCAsmInfo &MAI`.
* TargetMachine::getMCAsmInfo returns `const MCAsmInfo &`.

Make this change now since the MCContext ctor has recently been updated.
2026-04-27 07:48:54 +00:00
Alan Li 5e0efc0f1d Reland "[GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) (#155107)" (#188502)
This is a reland of https://github.com/llvm/llvm-project/pull/155107
along with a fix for old gcc builds.

This patch is reverted in
https://github.com/llvm/llvm-project/pull/188344 due to compilation
failures described in
https://github.com/llvm/llvm-project/pull/155107#issuecomment-4121292756

The fix to old gcc builds is to remove `constexpr` modifiers in the
original patch in 0721d8e776
2026-04-04 05:57:13 -07:00
Jay Foad fbfb83978c [MachineVerifier] Disallow subregister defs in SSA form (#189403) 2026-03-31 09:50:08 +01:00
Mehdi Amini 6a045c29a9 Revert "[GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) (#155107)" (#188344)
This reverts commit b1aa6a4506 and commit
ce44d63e0d.

This fails the build with some older gcc:

llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to
non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned
int)’
     return integer(getSizeInBits());
                                   ^
2026-03-24 21:40:36 +00:00
b1aa6a4506 [GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) (#155107)
Added extra information in LLT to support ambiguous fp types during
GlobalISel. Original idea by @tgymnich

Main differences from https://github.com/llvm/llvm-project/pull/122503
are:
* Do not deprecate LLT::scalar
* Allow targets to enable/disable IR translation with extenden LLT via
`TargetOption::EnableGlobalISelExtendedLLT` (disabled by default)
* `IRTranslator` use `TargetLoweringInfo` for appropriate `LLT`
generation.
* For this reason added flag in GlobalISelMatchTable` to allow switch
between legacy and new extended LLT names
* Revert using stubs like `LLT::float32` for float types as they are
real now. Added `TODO` for such cases.

Also MIRParser now may parse new type indentifiers.

---------

Co-authored-by: Tim Gymnich <tim@gymni.ch>
Co-authored-by: Ryan Cowan <ryan.cowan@arm.com>
2026-03-24 08:40:39 -04:00
Rahul Joshi ae66e34c01 [NFC][CodeGen] Add helper function to check SubReg validity (#181489)
Add function `isSubRegValidForRegClass` to check if a sub-register index
can be used with a register class and use it in MIR verifier and a few
other places.
2026-02-19 12:39:11 -08:00
Rahul Joshi e87ac29433 [NFC][CodeGen] Refactor subregister index verification for MIR (#181921)
Refactor register class/subreg-index verification against the
instruction specified class:
- Avoid inflating the register's class (i.e., no need to call
`getLargestLegalSuperClass`).
- Check validity with `getMatchingSuperRegClass(RC, DRC, SubIdx) == RC`.
- Add some explanatory comments for this check.
- Extended a unit test to exercise this verification failure.
2026-02-19 10:25:16 -08:00
Rahul Joshi eb85fc740c [NFC][CodeGen] Minor code cleanup in MIR FrameIndex verification (#181551)
Use variable names conforming to LLVM CS and shorten the code a bit
using `dyn_cast_if_present`.
2026-02-16 13:29:09 -08:00
Rahul Joshi 26f962465e [LLVM][CodeGen] Remove pass initialization calls from pass constructors (#173061)
- Remove pass initialization calls from pass constructors.
- For some passes, add the initialization to `initializeCodeGen` or
`initializeGlobalISel`.
- Remove redundant initializations from llc and X86 target for some
passes.
2026-01-21 08:44:51 -08:00
Nikita Popov 792670a400 [X86][WinEH] Insert nop after unwinding inline assembly (#176393)
As discussed on https://github.com/llvm/llvm-project/pull/144745, insert
a nop after unwinding inline assembly, as it may end on a call.

While the change itself is trivial, I ended up having to do two
infrastructure changes:
* The unwind flag needs to be propagated to ExtraInfo of the
MachineInstr.
* The MachineInstr needs to be passed through to emitInlineAsmEnd(), and
the method needs to be non-const.

Fixes https://github.com/llvm/llvm-project/issues/157073.
2026-01-19 09:09:04 +01:00
Nathan Corbyn b7a20c1cc4 [GlobalISel] Don't permit G_*MIN/G_*MAX of pointer vectors (#168872)
- Use `LLT::changeElementType()` instead of `LLT::changeElementSize()`
in `LegalizerHelper::lowerMinMax()` to avoid a crash in the case that
the destination type is a pointer vector;
- Reject `G_*MIN`/`G_*MAX` of pointers and pointer vectors in
`MachineVerifier`;
- Don't combine `G_SELECT`+`G_ICMP` pairs into `G_*MIN`/`G_*MAX` generic
instructions when the operands are pointers / pointer vectors.

Fixes #166556
2025-12-17 09:03:41 +00:00
Vikash Gupta cd86b2ab32 [CodeGen] Add MO_LaneMask type and a new COPY_LANEMASK instruction (#151944)
Introduce MO_LaneMask as new machine operand type. This can be used to
hold liveness infomation at sub-register granularity for register-type
operands. We also introduce a new COPY_LANEMASK instruction that uses
MO_lanemask operand to perform partial copy from source register
opernad.

One such use case of MO_LaneMask can be seen in #151123, where it can be
used to store live regUnits information corresponding to the source
register of the COPY instructions, later can be used during CopyPhysReg
expansion.
2025-12-03 13:56:15 +05:30
Sergei Barannikov d1cc1376a0 [CodeGen] Add TRI::regunits() iterating over all register units (NFC) (#167901) 2025-11-13 17:27:35 +00:00
Matt Arsenault 55422e804b CodeGen: Remove TRI argument from getRegClass (#158225)
TargetInstrInfo now directly holds a reference to TargetRegisterInfo
and does not need TRI passed in anywhere.
2025-11-10 15:43:55 -08:00
Abhay Kanhere d998f92a00 [CodeGen] MachineVerifier to check early-clobber constraint (#151421)
Currently MachineVerifier is missing verifying early-clobber operand
constraint.
The only other machine operand constraint -  TiedTo is already verified.
2025-11-04 18:39:31 -08:00
David Green a1e59bdc17 [GlobalISel] Make scalar G_SHUFFLE_VECTOR illegal. (#140508)
I'm not sure if this is the best way forward or not, but we have a lot
of issues with forgetting that shuffle_vectors can be scalar again and
again. (There is another example from the recent known-bits code added
recently). As a scalar-dst shuffle vector is just an extract, and a
scalar-source shuffle vector is just a build vector, this patch makes
scalar shuffle vector illegal and adjusts the irbuilder to create the
correct node as required.

Most targets do this already through lowering or combines. Making scalar
shuffles illegal simplifies gisel as a whole, it just requires that
transforms that create shuffles of new sizes to account for the scalar
shuffle being illegal (mostly IRBuilder and LessElements).
2025-10-24 08:21:35 +01:00
DST ce70773cff Fix some typos in machine verifier comments and trace output (#160049)
Stumbled across a typo in the `MachineVerifier` file and since I had it
open, I changed some other comments.

Not important but why not leave it a bit cleaner 🙂

---------

Signed-off-by: Daniel Stadelmann <dasta_7@hotmail.com>
2025-09-29 10:23:09 +00:00
Matt Arsenault 1dbb932fd8 GlobalISel: Relax verifier between physreg and typed vreg (#159281)
Accept mismatched register size and type size if the type is legal
for the register class.

For AMDGPU boolean registers have 2 possible interpretations depending
on the use context type. e.g., these are both equally valid:

  %0:_(s1) = COPY $vcc
  %1:_(s64) = COPY $vcc

vcc is a 64-bit register, which can be interpreted as a 1-bit or 64-bit
value depending on the use context. SelectionDAG has never required
exact
match between the register size and the used value type. You can assign
a type with a smaller size to a larger register class. Relax the
verifier
to match.  There are several hacks holding together these copies in
various places, and this is preparation to remove one of them.

The x86 test change is from what I would consider an X86 usage bug. X86
defines an FR32 register class and F16 register class, but the F16
register
class is functionally an alias of F32 with the same members and size.
There's
no need to have the F16 class.
2025-09-17 19:43:50 +09:00
Matt Arsenault 7289f2cd0c CodeGen: Remove MachineFunction argument from getRegClass (#158188)
This is a low level utility to parse the MCInstrInfo and should
not depend on the state of the function.
2025-09-12 19:22:02 +09:00
jyli0116 4c27279ec4 [GlobalISel] Add Saturated Truncate Instructions (#147526)
Introduces saturated truncate instructions to Global ISel:
G_TRUNC_SSAT_S, G_TRUNC_SSAT_U, G_TRUNC_USAT_U. These were previously
introduced to SDAG to reduce redundant code.

The patch only initially introduces the instruction, a later patch will
follow to add combines and legalization for each instruction.
2025-07-09 18:56:17 +01:00
Rahul Joshi 1fdf02ad5a [LLVM][CodeGen] Add convenience accessors for MachineFunctionProperties (#140002)
Add per-property has<Prop>/set<Prop>/reset<Prop> functions to
MachineFunctionProperties.
2025-05-22 08:07:52 -07:00
Kazu Hirata 1019457891 [CodeGen] Use *Set::insert_range (NFC) (#132651)
We can use *Set::insert_range to collapse:

  for (auto Elem : Range)
    Set.insert(E);

down to:

  Set.insert_range(Range);
2025-03-23 21:20:44 -07:00
Kazu Hirata 1b189cab5e [llvm] Use *Set::insert_range (NFC) (#132509)
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently
gained C++23-style insert_range.  This patch uses insert_range in
conjunction with llvm::{predecessors,successors} and
MachineBasicBlock::{predecessors,successors}.
2025-03-22 08:07:33 -07:00
Kazu Hirata 599005686a [llvm] Use *Set::insert_range (NFC) (#132325)
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently
gained C++23-style insert_range.  This patch replaces:

  Dest.insert(Src.begin(), Src.end());

with:

  Dest.insert_range(Src);

This patch does not touch custom begin like succ_begin for now.
2025-03-20 22:24:06 -07:00
Nikita Popov 0738f70615 [Intrinsics] Add Intrinsic::getFnAttributes() (NFC) (#132029)
Most places that call Intrinsic::getAttributes() are only interested in
the function attributes, so add a separate function for that.

The motivation for this is that I'd like to add the ability to specify
range attributes on intrinsics, which requires knowing the function
type. This avoids needing to know the type for most attribute queries.
2025-03-20 09:20:39 +01:00
David Green bd1be8a242 [CodeGen][GlobalISel] Add a getVectorIdxWidth and getVectorIdxLLT. (#131526)
From #106446, this adds a variant of getVectorIdxTy that returns an LLT.
Many uses only look at the width, so a getVectorIdxWidth was added as
the common base.
2025-03-18 08:31:11 +00:00
Matt Arsenault 4670f0d827 MachineVerifier: Print name of failing subregister index (#129491)
I'm not sure of a good example to test the "does not fully support"
case.
2025-03-04 11:25:34 +07:00
Craig Topper 444859634f [MachineVerifier] Use Register instead of unsigned for DenseSet key. NFC (#128234) 2025-02-21 21:25:21 -08:00
Christudasan Devadasan 1d22318b81 [MachineVerifier][NewPM] Add method to run MF through verifier. (#125701) 2025-02-05 11:54:26 +05:30
Craig Topper 473953a15f [CodeGen] Use non-static Register::virtRegIndex() instead of static Register::virtReg2Index. NFC (#125031)
These are the the ones where we already had a Register object being
used. Some places are still using unsigned which I did not convert.
2025-01-30 00:14:08 -08:00
Matt Arsenault 6017480461 MachineVerifier: Fix check for range type (#124894)
We need to permit scalar extending loads with range annotations.

Fix expensive_checks failures after 11db7fb09b
2025-01-30 10:56:12 +07:00
11db7fb09b [GlobalISel] Catching inconsistencies in load memory, result, and range metadata type (#121247)
This is a fix for:
https://github.com/llvm/llvm-project/issues/97290
Please let me know if that is the right way to address the issue. Thank
you!

---------

Co-authored-by: Renat Idrisov <parsifal-47@users.noreply.github.com>
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
2025-01-28 20:54:34 +07:00
Craig Topper ac1ba1f9dd [CodeGen] Introduce a VirtRegOrUnit class to hold virtual reg or physical reg unit. NFC (#123768)
LiveIntervals and MachineVerifier were previously using Register to
store this, but reg units are different than physical registers. One
important difference is that 0 is a valid reg unit number, but it is not
a valid phyiscal register.

This patch introduces a new VirtRegOrUnit class that is distinct from
Register. It can be be converted to/from a virtual Register or a
MCRegUnit. I've made all conversions explicit and used assertions to
check the validity.

I also fixed a place in MachineVerifier that was ignoring reg unit 0.
2025-01-24 18:30:28 -08:00
Craig Topper f5f32cef61 [CodeGen] Use MCRegister instead of MCPhysReg in RegisterMaskPair. NFC (#123688)
Update some other places to avoid implicit conversions this introduces,
but I probably missed some.
2025-01-21 07:04:35 -08:00
Guy David da9df6c52a MachineVerifier: Check stack protector is top-most in frame (#122635)
Mitigate against potential bugs that might place it elsewhere and render
the mechanism useless.
2025-01-14 16:24:09 +02:00