summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AVR/AVRFrameLowering.cpp
AgeCommit message (Collapse)Author
2025-02-20[FrameLowering] Use MCRegister instead of Register in CalleeSavedInfo. NFC ↵Craig Topper
(#128095) Callee saved registers should always be phyiscal registers. They are often passed directly to other functions that take MCRegister like getMinimalPhysRegClass or TargetRegisterClass::contains. Unfortunately, sometimes the MCRegister is compared to a Register which gave an ambiguous comparison error when the MCRegister is on the LHS. Adding a MCRegister==Register comparison operator created more ambiguous comparison errors elsewhere. These cases were usually comparing against a base or frame pointer register that is a physical register in a Register. For those I added an explicit conversion of Register to MCRegister to fix the error.
2024-11-18[Target] Remove unused includes (NFC) (#116577)Kazu Hirata
Identified with misc-include-cleaner.
2024-10-18[llvm] Consistently respect `naked` fn attribute in ↵Alex Rønne Petersen
`TargetFrameLowering::hasFP()` (#106014) Some targets (e.g. PPC and Hexagon) already did this. I think it's best to do this consistently so that frontend authors don't run into inconsistent results when they emit `naked` functions. For example, in Zig, we had to change our emit code to also set `frame-pointer=none` to get reliable results across targets. Note: I don't have commit access.
2023-12-03[llvm] Stop including vector (NFC)Kazu Hirata
Identified with clangd.
2023-02-28[AVR] Fix incorrect flags of livein registers when spilling themBen Shi
In AVRFrameLowering::spillCalleeSavedRegisters(), when a 16-bit livein register is spilled, two PUSH instructions are generated for the higher and lower 8-bit registers. But these two 8-bit registers are marked as killed in the two PUSH instructions, so any future use of them will cause a crash. This patch fixes the above issue by adding the two sub 8-bit registers to the livein list. Fixes https://github.com/llvm/llvm-project/issues/56423 Reviewed By: jacquesguan Differential Revision: https://reviews.llvm.org/D144720
2022-12-22[AVR] Do not emit instructions invalid for attiny10Ayke van Laethem
The attiny4/attiny5/attiny9/attiny10 have a slightly modified instruction set that drops a number of useful instructions. This patch makes sure to not emit them on these "reduced tiny" cores. The affected instructions are: * lds and sts (load/store directly from data) * ldd and std (load/store with displacement) * adiw and sbiw (add/sub register pairs) * various other instructions that were emitted without checking whether the chip actually supports them (movw, adiw, etc) There is a variant on lds and sts on these chips, but it can only address a limited portion of the address space and is mainly useful to load/store I/O registers (as an extension to the in and out instructions). I have not implemented it here, implementing it can be done in a separate patch. This patch is not optimal. I'm sure it can be improved a lot. For example, we could teach the instruction selector to not select lddw/stdw instructions so that the weird pointer adjustments are not necessary. But for now I've focused just on correctness, not on code quality. Updates: https://github.com/llvm/llvm-project/issues/53459 Differential Revision: https://reviews.llvm.org/D131867
2022-11-28[AVR] Do not use R0/R1 on avrtinyAyke van Laethem
This patch makes sure the compiler uses R16/R17 on avrtiny (attiny10 etc) instead of R0/R1. Some notes: * For the NEGW and ROLB instructions, it adds an explicit zero register. This is necessary because the zero register is different on avrtiny (and InstrInfo Uses lines need a fixed register). * Not entirely sure about putting all tests in features/avr-tiny.ll, but it doesn't seem like the "target-cpu"="attiny10" attribute works. Updates: https://github.com/llvm/llvm-project/issues/53459 Differential Revision: https://reviews.llvm.org/D138582
2022-08-15[AVR] Only push and clear R1 in interrupts when necessaryAyke van Laethem
R1 is a reserved register, but LLVM gives the APIs to know when it is used or not. So this patch uses these APIs to only save/clear/restore R1 in interrupts when necessary. The main issue here was getting inline assembly to work. One could argue that this is the job of Clang, but for consistency I've made sure that R1 is always usable in inline assembly even if that means clearing it when it might not be needed. Information on inline assembly in AVR can be found here: https://www.nongnu.org/avr-libc/user-manual/inline_asm.html#asm_code Essentially, this seems to suggest that r1 can be freely used in avr-gcc inline assembly, even without specifying it as an input operand. Differential Revision: https://reviews.llvm.org/D117426
2022-05-05[AVR] Always expand STDSPQRr & STDWSPQRrPatryk Wychowaniec
Currently, STDSPQRr and STDWSPQRr are expanded only during AVRFrameLowering - this means that if any of those instructions happen to appear _outside_ of the typical FrameSetup / FrameDestroy context, they wouldn't get substituted, eventually leading to a crash: ``` LLVM ERROR: Not supported instr: <MCInst XXX <MCOperand Reg:1> <MCOperand Imm:15> <MCOperand Reg:53>> ``` This commit fixes this issue by moving expansion of those two opcodes into AVRExpandPseudo. This bug was originally discovered due to the Rust compiler_builtins library. Its 0.1.37 release contained a 128-bit software division/remainder routine that exercised this buggy branch in the code. Reviewed By: benshi001 Differential Revision: https://reviews.llvm.org/D123528
2022-02-02[AVR] Avoid reusing the same variable name (NFC)Nikita Popov
Apparently GCC 5.4 (a supported compiler) has a bug where it will use the "MachineInstr &MI" defined by the range-based for loop to evaluate the for loop expression. Pick a different variable name to avoid this.
2022-02-02[AVR] Fix atomicrmw result valueAyke van Laethem
This patch fixes the atomicrmw result value to be the value before the operation instead of the value after the operation. This was a bug, left as a FIXME in the code (see https://reviews.llvm.org/D97127). From the LangRef: > The contents of memory at the location specified by the <pointer> > operand are atomically read, modified, and written back. The original > value at the location is returned. Doing this expansion early allows the register allocator to arrange registers in such a way that commutable operations are simply swapped around as needed, which results in shorter code while still being correct. Differential Revision: https://reviews.llvm.org/D117725
2022-01-19[AVR] Do not clear r0 at interrupt entryAyke van Laethem
There is no reason to do this: it's a scratch register and can therefore hold any arbitrary value. And because it is in an interrupt, this code is performance critical so it should be as short as possible. I believe r0 was cleared because of the following: 1. There used to be a bug that the cleared register was r0, not r1 as it should have been. 2. This was fixed in https://reviews.llvm.org/D99467, but left the code to clear r0. This patch completes D99467 by removing the `clr r0` instruction. Differential Revision: https://reviews.llvm.org/D116756
2022-01-19[AVR] Remove redundant dynalloca SP save/restore passAyke van Laethem
I think this pass was previously used under the assumption that most functions would not need a frame pointer and it would be more efficient to store the old stack pointer in a regular register pair. Unfortunately, right now we're forced to always reserve the Y register as a frame pointer: whether or not this is needed is only known after regsiter allocation at which point it doesn't make sense anymore to mark it as non-reserved. Therefore, it makes sense to use the Y register to store the old stack pointer in functions with dynamic allocas (with a variable size or not in the entry block). Knowing this can make the code around dynamic allocas a lot simpler: simply save/restore the frame pointer. This is especially relevant in functions that have a frame pointer anyway (for example, because they have stack spills). The stack restore in the epilogue will implicitly restore the old stack pointer, so there is no need to store the old stack pointer separately. It even reduces register pressure as a side effect. Differential Revision: https://reviews.llvm.org/D97815
2022-01-19[NFC] Use Register instead of unsignedJim Lin
2021-12-12[Target] Use llvm::reverse (NFC)Kazu Hirata
2021-11-05[Target] Use make_early_inc_range (NFC)Kazu Hirata
2021-09-16[llvm] Use drop_begin (NFC)Kazu Hirata
2021-09-04[NFC] Run clang-format on llvm/lib/Trget/AVR/Shivam Gupta
The current inconsistency confuse contributors which coding guidlines to follow. It would be better to have it consistent using clang-format tool. Reviewed By: mhjacobson Differential Revision: https://reviews.llvm.org/D109270
2021-06-29[AVR] Fix a bug in prologue of ISRBen Shi
The r1 register should be cleared in prologue of ISR as it is used as constant zero. Reviewed By: dylanmckay Differential Revision: https://reviews.llvm.org/D99467
2021-03-04[AVR] Fix lifeness issues in the AVR backendAyke van Laethem
This patch is a large number of small changes that should hopefully not affect the generated machine code but are still important to get right so that the machine verifier won't complain about them. The llvm/test/CodeGen/AVR/pseudo/*.mir changes are also necessary because without the liveins the used registers are considered undefined by the machine verifier and it will complain about them. Differential Revision: https://reviews.llvm.org/D97172
2020-10-01[AVR] fix interrupt stack pointer restorationAndrew Dona-Couch
This patch fixes a corruption of the stack pointer and several registers in any AVR interrupt with non-empty stack frame. Previously, the callee-saved registers were popped before restoring the stack pointer, causing the pointer math to use the wrong base value while also corrupting the caller's register. This change fixes the code to restore the stack pointer last before exiting the interrupt service routine. https://bugs.llvm.org/show_bug.cgi?id=47253 Reviewed By: dylanmckay Differential Revision: https://reviews.llvm.org/D87735 Patch by Andrew Dona-Couch.
2020-07-14[NFC] Add 'override' keyword where missing in include/ and lib/.Logan Smith
This fixes warnings raised by Clang's new -Wsuggest-override, in preparation for enabling that warning in the LLVM build. This patch also removes the virtual keyword where redundant, but only in places where doing so improves consistency within a given file. It also removes a couple unnecessary virtual destructor declarations in derived classes where the destructor inherited from the base class is already virtual. Differential Revision: https://reviews.llvm.org/D83709
2020-06-16[AVR] Remove faulty stack pushing behaviorAyke van Laethem
An instruction like this will need to allocate some stack space for the last parameter: %x = call addrspace(1) i16 @bar(i64 undef, i64 undef, i16 undef, i16 0) This worked fine when passing an actual value (in this case 0). However, when passing undef, no value was pushed to the stack and therefore no push instructions were created. This caused an unbalanced stack leading to interesting results. This commit fixes that by replacing the push logic with a regular stack adjustment and stack-relative load/stores. This is less efficient but at least it correctly compiles the code. I can think of a few improvements in the future: * The stack should have been adjusted in the function prologue when there are no allocas in the function. * Many (if not most) stack adjustments can be replaced by pushing/popping the values directly. Exactly like the previous code attempted but didn't do correctly. * Small stack adjustments can be done more efficiently with a few push/pop instructions (pushing/popping bogus values), both for code size and for speed. All in all, as long as there are no allocas in the function I think that it is almost always more efficient to emit regular push/pop instructions. This is however left for future optimizations. Differential Revision: https://reviews.llvm.org/D78581
2020-06-16[AVR] Fix stack size in functions with a frame pointerAyke van Laethem
This patch fixes a bug in stack save/restore code. Because the frame pointer was saved/restored manually (not by marking it as clobbered) the StackSize variable was not updated accordingly. Most code still worked, but code that tried to load a parameter passed on the stack did not. This commit fixes this by marking the frame pointer as a callee-clobbered register. This will let it be saved without any effort in prolog/epilog code and will make sure the correct address is calculated for loading parameters that are passed on the stack. This approach is used by most other targets (such as X86, AArch64 and RISC-V). Differential Revision: https://reviews.llvm.org/D78579
2020-03-31Remove unused variableGuillaume Chatelet
2020-03-31[AVR] Generalize the previous interrupt bugfix to signal handlers tooDylan McKay
2020-03-31[AVR] Respect the 'interrupt' function attributeDylan McKay
In the past, AVR functions were only lowered with interrupt-specific machine code if the function was defined with the "avr-interrupt" or "avr-signal" calling conventions. This patch modifies the backend so that if the function does not have a special calling convention, but does have an "interrupt" attribute, that function is interpreted as a function with interrupts. This also extracts the "is this function an interrupt" logic from several disparate places in the backend into one AVRMachineFunctionInfo attribute. Bug found by Wilhelm Meier.
2020-03-23[Alignment][NFC] Use TFL::getStackAlign()Guillaume Chatelet
Summary: This is patch is part of a series to introduce an Alignment type. See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html See this patch for the introduction of the type: https://reviews.llvm.org/D64790 Reviewers: courbet Subscribers: dylanmckay, sdardis, nemanjai, hiraditya, kbarton, asb, rbar, johnrusso, simoncook, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, Jim, lenary, s.egerton, pzheng, sameer.abuasal, apazos, luismarques, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D76551
2020-03-05[AVR][NFC] Use Register instead of unsignedJim Lin
Summary: Use Register type for variables instead of unsigned type. Reviewers: dylanmckay Reviewed By: dylanmckay Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D75595
2020-02-29ArrayRef'ize restoreCalleeSavedRegisters. NFCI.Benjamin Kramer
restoreCalleeSavedRegisters can mutate the contents of the CalleeSavedInfos, so use a MutableArrayRef.
2020-02-08ArrayRef'ize spillCalleeSavedRegisters. NFCI.Benjamin Kramer
2020-01-24[Alignment][NFC] Deprecate Align::None()Guillaume Chatelet
Summary: This is a follow up on https://reviews.llvm.org/D71473#inline-647262. There's a caveat here that `Align(1)` relies on the compiler understanding of `Log2_64` implementation to produce good code. One could use `Align()` as a replacement but I believe it is less clear that the alignment is one in that case. Reviewers: xbolva00, courbet, bollu Subscribers: arsenm, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, hiraditya, kbarton, jrtc27, atanasyan, jsji, Jim, kerbowa, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D73099
2019-10-17[Alignment][NFC] Use Align for TargetFrameLowering/SubtargetGuillaume Chatelet
Summary: This is patch is part of a series to introduce an Alignment type. See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html See this patch for the introduction of the type: https://reviews.llvm.org/D64790 Reviewers: courbet Subscribers: jholewinski, arsenm, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, hiraditya, aheejin, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, jsji, Jim, lenary, s.egerton, pzheng, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D68993 llvm-svn: 375084
2019-08-15Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVMDaniel Sanders
Summary: This clang-tidy check is looking for unsigned integer variables whose initializer starts with an implicit cast from llvm::Register and changes the type of the variable to llvm::Register (dropping the llvm:: where possible). Partial reverts in: X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned& MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register PPCFastISel.cpp - No Register::operator-=() PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned& MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor Manual fixups in: ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned& HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register. PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned& Depends on D65919 Reviewers: arsenm, bogner, craig.topper, RKSimon Reviewed By: arsenm Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65962 llvm-svn: 369041
2019-06-28[AVR] Don't look for the TargetFrameLowering in the FrameLowering implementationDylan McKay
c.f. r364349 llvm-svn: 364632
2019-06-25Don't look for the TargetFrameLowering in the implementationMatt Arsenault
The same oddity was apparently copy-pasted between multiple targets. llvm-svn: 364349
2019-01-19Update the file headers across all of the LLVM projects in the monorepoChandler Carruth
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
2017-12-15MachineFunction: Return reference from getFunction(); NFCMatthias Braun
The Function can never be nullptr so we can return a reference. llvm-svn: 320884
2017-08-10Add "Restored" flag to CalleeSavedInfoKrzysztof Parzyszek
The liveness-tracking code assumes that the registers that were saved in the function's prolog are live outside of the function. Specifically, that registers that were saved are also live-on-exit from the function. This isn't always the case as illustrated by the LR register on ARM. Differential Revision: https://reviews.llvm.org/D36160 llvm-svn: 310619
2017-05-09Add extra operand to CALLSEQ_START to keep frame part set up previouslySerge Pavlov
Using arguments with attribute inalloca creates problems for verification of machine representation. This attribute instructs the backend that the argument is prepared in stack prior to CALLSEQ_START..CALLSEQ_END sequence (see http://llvm.org/docs/InAlloca.htm for details). Frame size stored in CALLSEQ_START in this case does not count the size of this argument. However CALLSEQ_END still keeps total frame size, as caller can be responsible for cleanup of entire frame. So CALLSEQ_START and CALLSEQ_END keep different frame size and the difference is treated by MachineVerifier as stack error. Currently there is no way to distinguish this case from actual errors. This patch adds additional argument to CALLSEQ_START and its target-specific counterparts to keep size of stack that is set up prior to the call frame sequence. This argument allows MachineVerifier to calculate actual frame size associated with frame setup instruction and correctly process the case of inalloca arguments. The changes made by the patch are: - Frame setup instructions get the second mandatory argument. It affects all targets that use frame pseudo instructions and touched many files although the changes are uniform. - Access to frame properties are implemented using special instructions rather than calls getOperand(N).getImm(). For X86 and ARM such replacement was made previously. - Changes that reflect appearance of additional argument of frame setup instruction. These involve proper instruction initialization and methods that access instruction arguments. - MachineVerifier retrieves frame size using method, which reports sum of frame parts initialized inside frame instruction pair and outside it. The patch implements approach proposed by Quentin Colombet in https://bugs.llvm.org/show_bug.cgi?id=27481#c1. It fixes 9 tests failed with machine verifier enabled and listed in PR27481. Differential Revision: https://reviews.llvm.org/D32394 llvm-svn: 302527
2017-05-03Revert "[AVR] Enable the frame pointer for all functions"Dylan McKay
This reverts commit 358ad02d999e88853d2cfc954bd2f668308a51f7. llvm-svn: 302014
2017-05-02[AVR] Save/restore the frame pointer for all functionsDylan McKay
A recent commit I made made it so that we only did this for signal or interrupt handlers. This broke normal functions. llvm-svn: 301893
2017-05-02[AVR] Fix a bug where the frame pointer is clobberedDylan McKay
Because it was a callee-saved register, we automatically generated code to spill and unspill its original value so that it is restored after the function returns. The problem is that this code was being generated before the epilogue. The epilogue itself uses the Y register, which could be prematurely restored by the CSR restoration process. This removes R29R28 from the CSR list and changes the prologue/epilogue code to handle it explicitly. llvm-svn: 301887
2017-05-01[AVR] Enable the frame pointer for all functionsDylan McKay
This is a temporary measure while we figure out a way to get the frame pointer working correctly. llvm-svn: 301881
2017-04-24Move size and alignment information of regclass to TargetRegisterInfoKrzysztof Parzyszek
1. RegisterClass::getSize() is split into two functions: - TargetRegisterInfo::getRegSizeInBits(const TargetRegisterClass &RC) const; - TargetRegisterInfo::getSpillSize(const TargetRegisterClass &RC) const; 2. RegisterClass::getAlignment() is replaced by: - TargetRegisterInfo::getSpillAlignment(const TargetRegisterClass &RC) const; This will allow making those values depend on subtarget features in the future. Differential Revision: https://reviews.llvm.org/D31783 llvm-svn: 301221
2016-12-13[AVR] Add an 'relax memory operation' passDylan McKay
Summary: This pass will be used to relax instructions which use out of bounds memory accesses to equivalent operations that can work with the addresses. The pass currently implements relaxation for the STDWPtrQRr instruction. Without this pass, an assertion error would be hit in the pseudo expansion pass. In the future, we will need to add more instructions to this pass. We can do that on a case-by-case basic. Reviewers: arsenm, kparzysz Subscribers: wdng, llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D27650 llvm-svn: 289517
2016-10-08Fix incorrect assertion in AVRFrameLowering.cppDylan McKay
This wasn't looking at the right instruction, and would always fail. llvm-svn: 283640
2016-10-08[AVR] Don't worry about call frame size when initializing frame pointerDylan McKay
We previously only used the frame pointer if the frame pointer was too big. This was to work around a bug (described in this old commit) https://sourceforge.net/p/avr-llvm/code/204/tree//llvm/trunk/AVR/AVRFrameLowering.cpp?diff=50d64d912718465cb887d17a:203 I mistakenly invered the condition assuming it was a typo. I am now removing it because it doesn't seem to be a problem anymore (plus it's a dirty hack). llvm-svn: 283639
2016-10-08[AVR] Don't shadow container while iterating in range-based loopDylan McKay
This works on clang, but fails on GCC 4.6 llvm-svn: 283638
2016-10-05[AVR] Update return type of dynamic alloca passDylan McKay
It was recently changed from 'const char*' to StringRef llvm-svn: 283312