aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachinePipeliner.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-08-18[llvm] Replace SmallSet with SmallPtrSet (NFC) (#154068)Kazu Hirata1-3/+3
This patch replaces SmallSet<T *, N> with SmallPtrSet<T *, N>. Note that SmallSet.h "redirects" SmallSet to SmallPtrSet for pointer element types: template <typename PointeeType, unsigned N> class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {}; We only have 140 instances that rely on this "redirection", with the vast majority of them under llvm/. Since relying on the redirection doesn't improve readability, this patch replaces SmallSet with SmallPtrSet for pointer element types.
2025-07-22[MachinePipeliner] Fix incorrect dependency direction (#149436)Ryotaro Kasuga1-2/+2
This patch fixes a bug introduced in #145878. A dependency was added in the wrong direction, causing an assertion failure due to broken topological order.
2025-07-11[MachinePipeliner] Add validation for missed loop-carried memory deps (#145878)Ryotaro Kasuga1-40/+154
This patch adds an additional validation step to ensure that the generated schedule does not violate loop-carried memory dependencies. Prior to this patch, incorrect schedules could be produced due to the lack of checks for the following types of dependencies: - load-to-store backward (from bottom to top within the BB) dependencies - store-to-load dependencies - store-to-store dependencies One possible solution to this issue is to add these dependencies directly to the dependency graph, although doing so may lead to performance degradation. In addition, no known cases of incorrect code generation caused by these missing dependencies have been observed in practice. Given these factors, this patch introduces a post-scheduling validation phase to check for such previously missed dependencies, instead of adding them to the graph before searching for a schedule. Since no actual problems have been identified so far, it is likely that most generated schedules are already valid. Therefore, this additional validation is not expected to cause performance degradation in practice. Split off from #135148 . The remaining tasks are as follows: - Address other missing loop-carried dependencies (e.g., output dependencies between physical registers, barrier instructions, and instructions that may raise floating-point exceptions) - Remove code that are currently retained to maintain the existing behavior but probably unnecessary. - Eliminate `SwingSchedulerDAG::isLoopCarriedDep` and use `SwingSchedulerDDG` to traverse edges after dependency analysis part.
2025-06-05[MachinePipeliner] Introduce a new class for loop-carried deps (#137663)Ryotaro Kasuga1-29/+219
In MachinePipeliner, loop-carried memory dependencies are represented by DAG, which makes things complicated and causes some necessary dependencies to be missing. This patch introduces a new class to manage loop-carried memory dependencies to simplify the logic. The ultimate goal is to add currently missing dependencies, but this is a first step of that, and this patch doesn't intend to change current behavior. This patch also adds new tests that show the missed dependencies, which should be fixed in the future. Split off from #135148
2025-05-24[CodeGen] Remove unused includes (NFC) (#141320)Kazu Hirata1-1/+0
These are identified by misc-include-cleaner. I've filtered out those that break builds. Also, I'm staying away from llvm-config.h, config.h, and Compiler.h, which likely cause platform- or compiler-specific build failures.
2025-05-14[MachinePipeliner] Extract some process into a separate function (#137662)Ryotaro Kasuga1-66/+59
This patch moves a process in `addLoopCarriedDependences` that checks for a loop-carried dependency between two instructions to another function. This patch is preliminary to a later patch and is not intended to change current behavior. Split off from #135148
2025-04-23[MachinePipeliner] Use AliasAnalysis properly when analyzing loop-carried ↵Ryotaro Kasuga1-88/+137
dependencies (#136691) MachinePipeliner uses AliasAnalysis to collect loop-carried memory dependencies. To analyze loop-carried dependencies, we need to explicitly tell AliasAnalysis that the values may come from different iterations. Before this patch, MachinePipeliner didn't do this, so some loop-carried dependencies might be missed. For example, in the following case, there is a loop-carried dependency from the load to the store, but it wasn't considered. ``` def @f(ptr noalias %p0, ptr noalias %p1) { entry: br label %body loop: %idx0 = phi ptr [ %p0, %entry ], [ %p1, %body ] %idx1 = phi ptr [ %p1, %entry ], [ %p0, %body ] %v0 = load %idx0 ... store %v1, %idx1 ... } ``` Further, the handling of the underlying objects was not sound. If there is no information about memory operands (i.e., `memoperands()` is empty), it must be handled conservatively. However, Machinepipeliner uses a dummy value (namely `UnknownValue`). It is distinguished from other "known" objects, causing necessary dependencies to be missed. (NOTE: in such cases, `buildSchedGraph` adds non-loop-carried dependencies correctly, so perhaps a critical problem has not occurred.) This patch fixes the above problems. This change has increased false dependencies that didn't exist before. Therefore, this patch also introduces additional alias checks with the underlying objects. Split off from #135148
2025-03-23[CodeGen] Use *Set::insert_range (NFC) (#132651)Kazu Hirata1-2/+1
We can use *Set::insert_range to collapse: for (auto Elem : Range) Set.insert(E); down to: Set.insert_range(Range);
2025-03-21[MachinePipeliner] Fix incorrect handlings of unpipelineable insts (#126057)Ryotaro Kasuga1-0/+26
There was a case where `normalizeNonPipelinedInstructions` didn't schedule unpipelineable instructions correctly, which could generate illegal code. This patch fixes this issue by rejecting the schedule if we fail to insert the unpipelineable instructions at stage 0. Here is a part of the debug output for `sms-unpipeline-insts3.mir` before applying this patch. ``` SU(0): %27:gpr32 = PHI %21:gpr32all, %bb.3, %28:gpr32all, %bb.4 Successors: SU(14): Data Latency=0 Reg=%27 SU(15): Anti Latency=1 ... SU(14): %41:gpr32 = ADDWrr %27:gpr32, %12:gpr32common Predecessors: SU(0): Data Latency=0 Reg=%27 SU(16): Ord Latency=0 Artificial Successors: SU(15): Data Latency=1 Reg=%41 SU(15): %28:gpr32all = COPY %41:gpr32 Predecessors: SU(14): Data Latency=1 Reg=%41 SU(0): Anti Latency=1 SU(16): %30:ppr = WHILELO_PWW_S %27:gpr32, %15:gpr32, implicit-def $nzcv Predecessors: SU(0): Data Latency=0 Reg=%27 Successors: SU(14): Ord Latency=0 Artificial ... Do not pipeline SU(16) Do not pipeline SU(1) Do not pipeline SU(0) Do not pipeline SU(15) Do not pipeline SU(14) SU(0) is not pipelined; moving from cycle 19 to 0 Instr: ... SU(1) is not pipelined; moving from cycle 10 to 0 Instr: ... SU(15) is not pipelined; moving from cycle 28 to 19 Instr: ... SU(16) is not pipelined; moving from cycle 19 to 0 Instr: ... Schedule Found? 1 (II=10) ... cycle 9 (1) (14) %41:gpr32 = ADDWrr %27:gpr32, %12:gpr32common cycle 9 (1) (15) %28:gpr32all = COPY %41:gpr32 ``` The SUs are traversed in the order of the original basic block, so in this case a new cycle of each instruction is determined in the order of `SU(0)`, `SU(1)`, `SU(14)`, `SU(15)`, `SU(16)`. Since there is an artificial dependence from `SU(16)` to `SU(14)`, which is contradict to the original SU order, the new cycle of `SU(14)` must be greater than or equal to the cycle of `SU(16)` at that time. This results in the failure of scheduling `SU(14)` at stage 0. For now, we reject the schedule for such cases.
2025-03-20[llvm] Use *Set::insert_range (NFC) (#132325)Kazu Hirata1-5/+5
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-06[MachinePipeliner] Use Register. NFC (#130165)Craig Topper1-29/+30
2025-03-03[NFC]Make file-local cl::opt global variables static (#126486)chrisPyr1-1/+1
#125983
2025-02-05[MachinePipeliner] Improve loop carried dependence analysis (#94185)Yuta Mukai1-74/+192
The previous implementation had false positive/negative cases in the analysis of the loop carried dependency. A missed dependency case is caused by incorrect analysis of address increments. This is fixed by strict analysis of recursive definitions. See added test swp-carried-dep4.mir. Excessive dependency detection is fixed by improving the formula for determining the overlap of address ranges to be accessed. See added test swp-carried-dep5.mir.
2025-02-05[CodeGen] Move MISched target hooks into TargetMachine (#125700)Christudasan Devadasan1-1/+1
The createSIMachineScheduler & createPostMachineScheduler target hooks are currently placed in the PassConfig interface. Moving it out to TargetMachine so that both legacy and the new pass manager can effectively use them.
2025-01-22[CodeGen] Rename RegisterMaskPair to VRegMaskOrUnit. NFC (#123799)Craig Topper1-5/+3
This holds a physical register unit or virtual register and mask. While I was here I've used emplace_back and removed an unneeded use of a template.
2025-01-18[CodeGen] Use Register/MCRegister::isPhysical. NFCCraig Topper1-1/+1
2024-12-24[MachinePipeliner] Add an abstract layer to manipulate Data Dependenc… ↵Ryotaro Kasuga1-232/+300
(#109918) …e Graph In MachinePipeliner, a DAG class is used to represent the Data Dependence Graph. Data Dependence Graph generally contains cycles, so it's not appropriate to use DAG classes. In fact, some "hacks" are used to express back-edges in the current implementation. This patch adds a new class to provide a better interface for manipulating dependencies. Our approach is as follows: - To build the graph, we use the ScheduleDAGInstrs class as it is, because it has powerful functions and the current implementation depends heavily on it. - After the graph construction is finished (i.e., during scheduling), we use the new class DataDependenceGraph to manipulate the dependencies. Since we don't change the dependencies during scheduling, the new class only provides functions to read them. Also, this patch is just a refactoring, i.e., scheduling results should not change with or without this patch.
2024-12-20[MachinePipeliner] Remove unused private field MFWang Pengcheng1-2/+1
2024-12-20[MachinePipeliner] Skip reserved registers when computing register pressure ↵Pengcheng Wang1-6/+6
(#120694) We used to skip fixed registers, but fixed registers are not enough because there are some runtime unusable registers like registers reserved by `-ffixed-xxx` options. Here we change to use reserved registers so that the estimated pressure is more accurate.
2024-12-18[MachinePipeliner] Use `RegisterClassInfo::getRegPressureSetLimit` (#119827)Pengcheng Wang1-42/+1
`RegisterClassInfo::getRegPressureSetLimit` is a wrapper of `TargetRegisterInfo::getRegPressureSetLimit` with some logics to adjust the limit by removing reserved registers. It seems that we shouldn't use `TargetRegisterInfo::getRegPressureSetLimit` directly, just like the comment "This limit must be adjusted dynamically for reserved registers" said. Thus we should use `RegisterClassInfo::getRegPressureSetLimit` and remove replicated code. Separate from https://github.com/llvm/llvm-project/pull/118787
2024-12-16[NFC] Remove some unnecessary semicolonsDavid Green1-4/+4
All inside LLVM_DEBUG, some of which have been cleaned up by adding block scopes to allow them to format more nicely.
2024-11-12[CodeGen] Remove unused includes (NFC) (#115996)Kazu Hirata1-3/+0
Identified with misc-include-cleaner.
2024-09-28[CodeGen] Avoid repeated hash lookups (NFC) (#110203)Kazu Hirata1-5/+3
2024-09-18[MachinePipeliner] Fix incorrect use of getPressureSets. (#109179)Craig Topper1-12/+17
The code was passing a physical register directly to getPressureSets which expects a register unit. Fix this by looping over the register units and calling getPressureSets for each of them. Found while trying to add a RegisterUnit class to stop storing register units in `Register`. 0 is a valid register unit but not a valid Register.
2024-09-03[MachinePipeliner] Make Recurrence MII More Accurate (#105475)Michael Marjieh1-7/+9
Current RecMII calculation is bigger than it needs to be. The calculation was refined in this patch.
2024-08-06[MachinePipeliner] Fix instruction order with physical register (#99264)Ryotaro KASUGA1-4/+7
dependencies in same cycle Dependency checks were insufficient when reordering instructions with physical register dependencies (i.e. Anti/Output dependencies). This could result in generating incorrect code.
2024-07-24[llvm][CodeGen] Added a new restriction for II by pragma in window scheduler ↵Kai Yan1-2/+10
(#99448) Added a new restriction for window scheduling. Window scheduling is disabled when llvm.loop.pipeline.initiationinterval is set.
2024-07-13[CodeGen] Use range-based for loops (NFC) (#98706)Kazu Hirata1-8/+8
2024-07-10[CodeGen][NewPM] Port `LiveIntervals` to new pass manager (#98118)paperchalice1-6/+8
- Add `LiveIntervalsAnalysis`. - Add `LiveIntervalsPrinterPass`. - Use `LiveIntervalsWrapperPass` in legacy pass manager. - Use `std::unique_ptr` instead of raw pointer for `LICalc`, so destructor and default move constructor can handle it correctly. This would be the last analysis required by `PHIElimination`.
2024-07-09[CodeGen][NewPM] Port `machine-loops` to new pass manager (#97793)paperchalice1-3/+3
- Add `MachineLoopAnalysis`. - Add `MachineLoopPrinterPass`. - Convert to `MachineLoopInfoWrapperPass` in legacy pass manager.
2024-07-03Reapply "[MachinePipeliner] Fix constraints aren't considered in cert… ↵Ryotaro KASUGA1-31/+39
(#97259) …ain cases" (#97246) This reverts commit e6a961dbef773b16bda2cebc4bf9f3d1e0da42fc. There is no difference from the original change. I re-ran the failed test and it passed. So the failure wasn't caused by this change. test result: https://lab.llvm.org/buildbot/#/builders/176/builds/585
2024-07-01Revert "[MachinePipeliner] Fix constraints aren't considered in certain ↵Ryotaro KASUGA1-39/+31
cases" (#97246) Reverts llvm/llvm-project#95356 Due to ppc64le test failures caught by the LLVM Buildbot. https://lab.llvm.org/buildbot/#/builders/176/builds/576
2024-07-01[MachinePipeliner] Fix constraints aren't considered in certain cases (#95356)Ryotaro KASUGA1-31/+39
when scheduling When scheduling an instruction, if both any predecessors and any successors of the instruction are already scheduled, `SchedStart` isn't taken into account. It may result generating incorrect code. This patch fixes the problem. Also, this patch merges `SchedStart` into `EarlyStart` (same for `SchedEnd`). Fixes https://github.com/llvm/llvm-project/issues/93936
2024-06-13[llvm][CodeGen] Add a new software pipeliner 'Window Scheduler' (#84443)Hua Tian1-1/+42
This commit implements the Window Scheduler as described in the RFC: https://discourse.llvm.org/t/rfc-window-scheduling-algorithm-for-machinepipeliner-in-llvm/74718 This Window Scheduler implements the window algorithm designed by Steven Muchnick in the book "Advanced Compiler Design And Implementation", with some improvements: 1. Copy 3 times of the loop kernel and construct the corresponding DAG to identify dependencies between MIs; 2. Use heuristic algorithm to obtain a set of window offsets. The window algorithm is equivalent to modulo scheduling algorithm with a stage of 2. It is mainly applied in targets where hardware resource conflicts are severe, and the SMS algorithm often fails in such cases. On our own DSA, this window algorithm typically can achieve a performance improvement of over 10%. Co-authored-by: Kai Yan <aklkaiyan@tencent.com> Co-authored-by: Ran Xiao <lennyxiao@tencent.com> --------- Co-authored-by: Kai Yan <aklkaiyan@tencent.com> Co-authored-by: Ran Xiao <lennyxiao@tencent.com>
2024-06-12[ModuloSchedule][AArch64] Implement modulo variable expansion for pipelining ↵Yuta Mukai1-0/+9
(#65609) Modulo variable expansion is a technique that resolves overlap of variable lifetimes by unrolling. The existing implementation solves it by making a copy by move instruction for processors with ordinary registers such as Arm and x86. This method may result in a very large number of move instructions, which can cause performance problems. Modulo variable expansion is enabled by specifying -pipeliner-mve-cg. A backend must implement some newly defined interfaces in PipelinerLoopInfo. They were implemented for AArch64. Discourse thread: https://discourse.llvm.org/t/implementing-modulo-variable-expansion-for-machinepipeliner
2024-06-11[CodeGen][NewPM] Split `MachineDominatorTree` into a concrete analysis ↵paperchalice1-3/+3
result (#94571) Prepare for new pass manager version of `MachineDominatorTreeAnalysis`. We may need a machine dominator tree version of `DomTreeUpdater` to handle `SplitCriticalEdge` in some CodeGen passes.
2024-04-12[AArch64] Improve scheduling latency into Bundles (#86310)David Green1-1/+2
By default the scheduling info of instructions into a BUNDLE are given a latency of 0 as they operate on the implicit register of the bundle. This modifies that for AArch64 so that the latency is adjusted to use the latency from the instruction in the bundle instead. This essentially assumes that the bundled instructions are executed in a single cycle, which for AArch64 is probably OK considering they are mostly used for MOVPFX bundles, where this can help create slightly better scheduling especially for in-order cores.
2024-04-08Replace copy with a reference. (#87975)Malay Sanghi1-2/+2
2024-04-03Reapply "[CodeGen] Fix register pressure computation in MachinePipeli… ↵Ryotaro KASUGA1-1/+1
(#87312) …ner (#87030)" Fix broken test. This reverts commit b8ead2198f27924f91b90b6c104c1234ccc8972e.
2024-04-01Revert "[CodeGen] Fix register pressure computation in MachinePipeliner ↵Gulfem Savrun Yeniceri1-1/+1
(#87030)" This reverts commit a4dec9d6bc67c4d8fbd4a4f54ffaa0399def9627 because the test failed in the following builder: https://luci-milo.appspot.com/ui/p/fuchsia/builders/prod/clang-linux-x64/b8751864477467126481/overview
2024-04-01[CodeGen] Fix register pressure computation in MachinePipeliner (#87030)Ryotaro KASUGA1-1/+1
`RegisterClassInfo::getRegPressureSetLimit` has been changed to return a smaller value than before so the limit may become negative in later calculations. As a workaround, change to use `TargetRegisterInfo::getRegPressureSetLimit`. Also improve tests.
2024-03-17[CodeGen] Use LocationSize for MMO getSize (#84751)David Green1-6/+7
This is part of #70452 that changes the type used for the external interface of MMO to LocationSize as opposed to uint64_t. This means the constructors take LocationSize, and convert ~UINT64_C(0) to LocationSize::beforeOrAfter(). The getSize methods return a LocationSize. This allows us to be more precise with unknown sizes, not accidentally treating them as unsigned values, and in the future should allow us to add proper scalable vector support but none of that is included in this patch. It should mostly be an NFC. Global ISel is still expected to use the underlying LLT as it needs, and are not expected to see unknown sizes for generic operations. Most of the changes are hopefully fairly mechanical, adding a lot of getValue() calls and protecting them with hasValue() where needed.
2024-03-05Replace copy with a reference. (#82485)MalaySanghiIntel1-2/+2
These are relatively larger structures and we don't update them so ref should be fine
2024-02-22[MachinePipeliner] Fix elements being added while the list is iterated (#80805)Yuta Mukai1-1/+0
There is no need to add the elements of Objs twice, so the addition is removed.
2024-02-03[CodeGen] Use range-based for loops (NFC)Kazu Hirata1-2/+2
2024-01-22[CodeGen][MachinePipeliner] Fix -Wpessimizing-move in MachinePipeliner.cpp (NFC)Jie Fu1-4/+4
/Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1044:19: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] 1044 | CycleInstrs = std::move(Schedule.reorderInstructions(SSD, CycleInstrs)); | ^ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1044:19: note: remove std::move call here 1044 | CycleInstrs = std::move(Schedule.reorderInstructions(SSD, CycleInstrs)); | ^~~~~~~~~~ ~ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1395:21: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] 1395 | auto LastUses = std::move(computeLastUses(OrderedInsts, Stages)); | ^ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1395:21: note: remove std::move call here 1395 | auto LastUses = std::move(computeLastUses(OrderedInsts, Stages)); | ^~~~~~~~~~ ~ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1502:9: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] 1502 | std::move(computeMaxSetPressure(OrderedInsts, Stages, MaxStage + 1)); | ^ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:1502:9: note: remove std::move call here 1502 | std::move(computeMaxSetPressure(OrderedInsts, Stages, MaxStage + 1)); | ^~~~~~~~~~ ~ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:3381:19: error: moving a temporary object prevents copy elision [-Werror,-Wpessimizing-move] 3381 | cycleInstrs = std::move(reorderInstructions(SSD, cycleInstrs)); | ^ /Users/jiefu/llvm-project/llvm/lib/CodeGen/MachinePipeliner.cpp:3381:19: note: remove std::move call here 3381 | cycleInstrs = std::move(reorderInstructions(SSD, cycleInstrs)); | ^~~~~~~~~~ ~ 4 errors generated.
2024-01-22[CodeGen][MachinePipeliner] Limit register pressure when scheduling (#74807)Ryotaro KASUGA1-20/+462
In software pipelining, when searching for the Initiation Interval (II), `MachinePipeliner` tries to reduce register pressure, but doesn't check how many variables can actually be alive at the same time. As a result, a lot of register spills/fills can be generated after register allocation, which might cause performance degradation. To prevent such cases, this patch adds a check phase that calculates the maximum register pressure of the scheduled loop and reject it if the pressure is too high. This can be enabled this by specifying `pipeliner-register-pressure`. Additionally, an II search range is currently fixed at 10, which is too small to find a schedule when the above algorithm is applied. Therefore this patch also adds a new option `pipeliner-ii-search-range` to specify the length of the range to search. There is one more new option `pipeliner-register-pressure-margin`, which can be used to estimate a register pressure limit less than actual for conservative analysis. Discourse thread: https://discourse.llvm.org/t/considering-register-pressure-when-deciding-initiation-interval-in-machinepipeliner/74725
2023-12-11[MachinePipeliner] Fix store-store dependences (#72575)bcahoon1-3/+5
The pipeliner needs to mark store-store order dependences as loop carried dependences. Otherwise, the stores may be scheduled further apart than the MII. The order dependences implies that the first instance of the dependent store is scheduled before the second instance of the source store instruction.
2023-10-24[ADT] Rename llvm::erase_value to llvm::erase (NFC) (#70156)Kazu Hirata1-1/+1
C++20 comes with std::erase to erase a value from std::vector. This patch renames llvm::erase_value to llvm::erase for consistency with C++20. We could make llvm::erase more similar to std::erase by having it return the number of elements removed, but I'm not doing that for now because nobody seems to care about that in our code base. Since there are only 50 occurrences of erase_value in our code base, this patch replaces all of them with llvm::erase and deprecates llvm::erase_value.
2023-09-01[llvm] Fix duplicate word typos. NFCFangrui Song1-1/+1
Those fixes were taken from https://reviews.llvm.org/D137338