summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/CodeGen/GlobalISel
Commit message (Collapse)AuthorAgeFilesLines
...
* GlobalISel: Fix CSE handling of buildConstantMatt Arsenault2019-02-042-4/+49
| | | | | | | | | | | | | | | | This fixes two problems with CSE done in buildConstant. First, this would hit an assert when used with a vector result type. Solve this by allowing CSE on the vector elements, but not on the result vector for now. Second, this was also performing the CSE based on the input ConstantInt pointer. The underlying buildConstant could potentially convert the constant depending on the result type, giving in a different ConstantInt*. Stop allowing the APInt and ConstantInt forms from automatically casting to the result type to avoid any similar problems in the future. llvm-svn: 353077
* GlobalISel: Improve gtest usageMatt Arsenault2019-02-048-157/+188
| | | | | | | Don't unnecessarily use ASSERT_*, and print the MachineFunction on failure. llvm-svn: 353072
* GlobalISel: Fix moreElementsToNextPow2Matt Arsenault2019-02-041-0/+40
| | | | | | | | | This was completely broken. The condition was inverted, and changed the element type for vectors of pointers. Fixes bug 40592. llvm-svn: 353069
* GlobalISel: Allow bitcount ops to have different result typeMatt Arsenault2019-01-311-33/+47
| | | | | | For AMDGPU the result is always 32-bit for 64-bit inputs. llvm-svn: 352717
* GlobalISel: Make buildConstant handle vectorsMatt Arsenault2019-01-223-7/+43
| | | | | | | Produce a splat build_vector similar to how SelectionDAG::getConstant does. llvm-svn: 351880
* Update the file headers across all of the LLVM projects in the monorepoChandler Carruth2019-01-195-20/+15
| | | | | | | | | | | | | | | | | 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
* [GISel]: Add support for CSEing continuously during GISel passes.Aditya Nandakumar2019-01-164-49/+142
| | | | | | | | | | https://reviews.llvm.org/D52803 This patch adds support to continuously CSE instructions during each of the GISel passes. It consists of a GISelCSEInfo analysis pass that can be used by the CSEMIRBuilder. llvm-svn: 351283
* [globalisel][combiner] Make the CombinerChangeObserver a ↵Daniel Sanders2018-12-141-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MachineFunction::Delegate Summary: This allows us to register it with the MachineFunction delegate and be notified automatically about erasure and creation of instructions. However, we still need explicit notification for modifications such as those caused by setReg() or replaceRegWith(). There is a catch with this though. The notification for creation is delivered before any operands can be added. While appropriate for scheduling combiner work. This is unfortunate for debug output since an opcode by itself doesn't provide sufficient information on what happened. As a result, the work list remembers the instructions (when debug output is requested) and emits a more complete dump later. Another nit is that the MachineFunction::Delegate provides const pointers which is inconvenient since we want to use it to schedule future modification. To resolve this GISelWorkList now has an optional pointer to the MachineFunction which describes the scope of the work it is permitted to schedule. If a given MachineInstr* is in this function then it is permitted to schedule work to be performed on the MachineInstr's. An alternative to this would be to remove the const from the MachineFunction::Delegate interface, however delegates are not permitted to modify the MachineInstr's they receive. In addition to this, the observer has three interface changes. * erasedInstr() is now erasingInstr() to indicate it is about to be erased but still exists at the moment. * changingInstr() and changedInstr() have been added to report changes before and after they are made. This allows us to trace the changes in the debug output. * As a convenience changingAllUsesOfReg() and finishedChangingAllUsesOfReg() will report changingInstr() and changedInstr() for each use of a given register. This is primarily useful for changes caused by MachineRegisterInfo::replaceRegWith() With this in place, both combine rules have been updated to report their changes to the observer. Finally, make some cosmetic changes to the debug output and make Combiner and CombinerHelp Reviewers: aditya_nandakumar, bogner, volkan, rtereshin, javed.absar Reviewed By: aditya_nandakumar Subscribers: mgorny, rovka, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D52947 llvm-svn: 349167
* [globalisel] Add GISelChangeObserver::changingInstr()Daniel Sanders2018-12-121-0/+1
| | | | | | | | | | | | | | | | | | | | | Summary: In addition to knowing that an instruction is changed. It's also useful to know when it's about to change. For example, it might print the instruction so you can track the changes in a debug log, it might remove it from some queue while it's being worked on, or it might want to change several instructions as a single transaction and act on all the changes at once. Added changingInstr() to all existing uses of changedInstr() Reviewers: aditya_nandakumar Reviewed By: aditya_nandakumar Subscribers: rovka, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D55623 llvm-svn: 348992
* [globalisel] Rename GISelChangeObserver's erasedInstr() to erasingInstr() ↵Daniel Sanders2018-12-121-1/+1
| | | | | | | | | | | | | | | | | | | | | | and related nits. NFC Summary: There's little of interest that can be done to an already-erased instruction. You can't inspect it, write it to a debug log, etc. It ought to be notification that we're about to erase it. Rename the function to clarify the timing of the event and reflect current usage. Also fixed one case where we were trying to print an erased instruction. Reviewers: aditya_nandakumar Reviewed By: aditya_nandakumar Subscribers: rovka, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D55611 llvm-svn: 348976
* [GISel]: Refactor MachineIRBuilder to allow passing additional parameters to ↵Aditya Nandakumar2018-12-112-31/+33
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | build Instrs https://reviews.llvm.org/D55294 Previously MachineIRBuilder::buildInstr used to accept variadic arguments for sources (which were either unsigned or MachineInstrBuilder). While this worked well in common cases, it doesn't allow us to build instructions that have multiple destinations. Additionally passing in other optional parameters in the end (such as flags) is not possible trivially. Also a trivial call such as B.buildInstr(Opc, Reg1, Reg2, Reg3) can be interpreted differently based on the opcode (2defs + 1 src for unmerge vs 1 def + 2srcs). This patch refactors the buildInstr to buildInstr(Opc, ArrayRef<DstOps>, ArrayRef<SrcOps>) where DstOps and SrcOps are typed unions that know how to add itself to MachineInstrBuilder. After this patch, most invocations would look like B.buildInstr(Opc, {s32, DstReg}, {SrcRegs..., SrcMIBs..}); Now all the other calls (such as buildAdd, buildSub etc) forward to buildInstr. It also makes it possible to build instructions with multiple defs. Additionally in a subsequent patch, we should make it possible to add flags directly while building instructions. Additionally, the main buildInstr method is now virtual and other builders now only have to override buildInstr (for say constant folding/cseing) is straightforward. Also attached here (https://reviews.llvm.org/F7675680) is a clang-tidy patch that should upgrade the API calls if necessary. llvm-svn: 348815
* [GISel]: Provide standard interface to observe changes in GISel passesAditya Nandakumar2018-12-052-14/+36
| | | | | | | | | | | | | https://reviews.llvm.org/D54980 This provides a standard API across GISel passes to observe and notify passes about changes (insertions/deletions/mutations) to MachineInstrs. This patch also removes the recordInsertion method in MachineIRBuilder and instead provides method to setObserver. Reviewed by: vkeles. llvm-svn: 348406
* [ARM GlobalISel] Support G_CTLZ and G_CTLZ_ZERO_UNDEFDiana Picus2018-11-261-0/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | We can now select CLZ via the TableGen'erated code, so support G_CTLZ and G_CTLZ_ZERO_UNDEF throughout the pipeline for types <= s32. Legalizer: If the CLZ instruction is available, use it for both G_CTLZ and G_CTLZ_ZERO_UNDEF. Otherwise, use a libcall for G_CTLZ_ZERO_UNDEF and lower G_CTLZ in terms of it. In order to achieve this we need to add support to the LegalizerHelper for the legalization of G_CTLZ_ZERO_UNDEF for s32 as a libcall (__clzsi2). We also need to allow lowering of G_CTLZ in terms of G_CTLZ_ZERO_UNDEF if that is supported as a libcall, as opposed to just if it is Legal or Custom. Due to a minor refactoring of the helper function in charge of this, we will also allow the same behaviour for G_CTTZ and G_CTPOP. This is not going to be a problem in practice since we don't yet have support for treating G_CTTZ and G_CTPOP as libcalls (not even in DAGISel). Reg bank select: Map G_CTLZ to GPR. G_CTLZ_ZERO_UNDEF should not make it to this point. Instruction select: Nothing to do. llvm-svn: 347545
* MachineModuleInfo: Store more specific reference to LLVMTargetMachine; NFCMatthias Braun2018-11-052-15/+17
| | | | | | | | MachineModuleInfo can only be used in code using lib/CodeGen, hence we can keep a more specific reference to LLVMTargetMachine rather than just TargetMachine around. llvm-svn: 346182
* [GISel]: Add legalization support for Widening UADDO/USUBOAditya Nandakumar2018-08-291-0/+75
| | | | | | | | | | | https://reviews.llvm.org/D51384 Added code in LegalizerHelper to widen UADDO/USUBO along with unit tests. Reviewed by volkan. llvm-svn: 340892
* [GISel]: Add legalization support for widening bit counting operationsAditya Nandakumar2018-08-221-0/+157
| | | | | | | | | | https://reviews.llvm.org/D51053 Added legalization for WidenScalar of various bitcounting opcodes. Reviewed by arsenm. llvm-svn: 340429
* Revert "Revert rr340111 "[GISel]: Add Legalization/lowering code for bit ↵Aditya Nandakumar2018-08-213-0/+379
| | | | | | | | | | | | | | | counting operations"" This reverts commit d1341152d91398e9a882ba2ee924147ea2f9b589. This patch originally made use of Nested MachineIRBuilder buildInstr calls, and since order of argument processing is not well defined, the instructions were built slightly in a different order (still correct). I've removed the nested buildInstr calls to have a defined order now. Patch was tested by Mikael. llvm-svn: 340309
* Revert rr340111 "[GISel]: Add Legalization/lowering code for bit counting ↵Reid Kleckner2018-08-203-379/+0
| | | | | | | | operations" It causes LegalizerHelperTest.LowerBitCountingCTTZ1 to fail. llvm-svn: 340186
* [GISel]: Add Legalization/lowering code for bit counting operationsAditya Nandakumar2018-08-183-0/+379
| | | | | | | | | | https://reviews.llvm.org/D48847#inline-448257 Ported legalization expansions for CTLZ/CTTZ from DAG to GISel. Reviewed by rtereshin. llvm-svn: 340111
* [GISel]: Pattern matchers for GFSUB, GFNEGAditya Nandakumar2018-05-311-0/+14
| | | | | | | | | | https://reviews.llvm.org/D47547 Add matching templates for G_FSUB, and G_FNEG. Reviewed by: aemerson. llvm-svn: 333685
* [GISel] Refactor MachineIRBuilder to allow transformations whileAditya Nandakumar2018-04-091-0/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | building. https://reviews.llvm.org/D45067 This change attempts to do two things: 1) It separates out the state that is stored in the MachineIRBuilder(InsertionPt, MF, MRI, InsertFunction etc) into a separate object called MachineIRBuilderState. 2) Add the ability to constant fold operations while building instructions (optionally). MachineIRBuilder is now refactored into a MachineIRBuilderBase which contains lots of non foldable build methods and their implementation. Instructions which can be constant folded/transformed are now in a class called FoldableInstructionBuilder which uses CRTP to use the implementation of the derived class for buildBinaryOps. Additionally buildInstr in the derived class can be used to implement other kinds of transformations. Also because of separation of state, given a MachineIRBuilder in an API, if one wishes to use another MachineIRBuilder, a new one can be constructed from the state locally. For eg, void doFoo(MachineIRBuilder &B) { MyCustomBuilder CustomB(B.getState()); // Use CustomB for building. } reviewed by : aemerson llvm-svn: 329596
* [GISel]: Fix incorrect type used in Pattern Match for ICstAditya Nandakumar2018-03-131-5/+5
| | | | | | getConstantVRegVal() returns int64_t but we use uint64_t. llvm-svn: 327461
* [GISel]: Add helpers for easy building G_FCONSTANT along with matchersAditya Nandakumar2018-03-091-0/+36
| | | | | | | | | | | | | | | | | | Added helpers to build G_FCONSTANT, along with matching ConstantFP and unit tests for the same. Sample usage. auto MIB = Builder.buildFConstant(s32, 0.5); // Build IEEESingle For Matching the above const ConstantFP* Tmp; mi_match(DstReg, MRI, m_GFCst(Tmp)); https://reviews.llvm.org/D44128 reviewed by: volkan llvm-svn: 327152
* GlobalISel: IRTranslate llvm.fabs.* intrinsicVolkan Keles2018-03-051-0/+29
| | | | | | | | | | | | | | | | Summary: Fabs is a common floating-point operation, especially for some expansions. This patch adds a new generic opcode for llvm.fabs.* intrinsic in order to avoid building/matching this intrinsic. Reviewers: qcolombet, aditya_nandakumar, dsanders, rovka Reviewed By: aditya_nandakumar Subscribers: kristof.beyls, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D43864 llvm-svn: 326749
* [GISel]: Fix base case for m_any_of PatternMatcher.Aditya Nandakumar2018-02-231-0/+6
| | | | | | | | The base case for any_of was incorrectly returning true. Also add test case which uses m_any_of(preds...) where none of the predicates are true. llvm-svn: 325848
* [GISel]: Add pattern matchers for G_BITCAST/PTRTOINT/INTTOPTRAditya Nandakumar2018-02-191-0/+14
| | | | | | | Adds pattern matchers for the above along with unit tests for the same. https://reviews.llvm.org/D43479 llvm-svn: 325542
* GlobalISel: Add templated functions and pattern matcher support for some ↵Volkan Keles2018-02-141-2/+28
| | | | | | | | | | | | | | | | | | more opcodes Summary: This patch adds templated functions to MachineIRBuilder for some opcodes and adds pattern matcher support for G_AND and G_OR. Reviewers: aditya_nandakumar Reviewed By: aditya_nandakumar Subscribers: rovka, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D43309 llvm-svn: 325162
* [GISel]: Add Pattern Matcher for G_FMUL.Aditya Nandakumar2018-02-131-0/+9
| | | | | | https://reviews.llvm.org/D43206 llvm-svn: 325044
* Followup on Proposal to move MIR physical register namespace to '$' sigil.Puyan Lotfi2018-01-311-3/+3
| | | | | | | | | | | | Discussed here: http://lists.llvm.org/pipermail/llvm-dev/2018-January/120320.html In preparation for adding support for named vregs we are changing the sigil for physical registers in MIR to '$' from '%'. This will prevent name clashes of named physical register with named vregs. llvm-svn: 323922
* [globalisel][legalizer] Fix a fallthrough case in the unittests debug printingDaniel Sanders2018-01-291-1/+1
| | | | llvm-svn: 323711
* [globalisel][legalizer] Adapt LegalizerInfo to support inter-type ↵Daniel Sanders2018-01-291-50/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dependencies and other things. Summary: As discussed in D42244, we have difficulty describing the legality of some operations. We're not able to specify relationships between types. For example, declaring the following setAction({..., 0, s32}, Legal) setAction({..., 0, s64}, Legal) setAction({..., 1, s32}, Legal) setAction({..., 1, s64}, Legal) currently declares these type combinations as legal: {s32, s32} {s64, s32} {s32, s64} {s64, s64} but we currently have no means to say that, for example, {s64, s32} is not legal. Some operations such as G_INSERT/G_EXTRACT/G_MERGE_VALUES/ G_UNMERGE_VALUES have relationships between the types that are currently described incorrectly. Additionally, G_LOAD/G_STORE currently have no means to legalize non-atomics differently to atomics. The necessary information is in the MMO but we have no way to use this in the legalizer. Similarly, there is currently no way for the register type and the memory type to differ so there is no way to cleanly represent extending-load/truncating-store in a way that can't be broken by optimizers (resulting in illegal MIR). It's also difficult to control the legalization strategy. We've added support for legalizing non-power of 2 types but there's still some hardcoded assumptions about the strategy. The main one I've noticed is that type0 is always legalized before type1 which is not a good strategy for `type0 = G_EXTRACT type1, ...` if you need to widen the container. It will converge on the same result eventually but it will take a much longer route when legalizing type0 than if you legalize type1 first. Lastly, the definition of legality and the legalization strategy is kept separate which is not ideal. It's helpful to be able to look at a one piece of code and see both what is legal and the method the legalizer will use to make illegal MIR more legal. This patch adds a layer onto the LegalizerInfo (to be removed when all targets have been migrated) which resolves all these issues. Here are the rules for shift and division: for (unsigned BinOp : {G_LSHR, G_ASHR, G_SDIV, G_UDIV}) getActionDefinitions(BinOp) .legalFor({s32, s64}) // If type0 is s32/s64 then it's Legal .clampScalar(0, s32, s64) // If type0 is <s32 then WidenScalar to s32 // If type0 is >s64 then NarrowScalar to s64 .widenScalarToPow2(0) // Round type0 scalars up to powers of 2 .unsupported(); // Otherwise, it's unsupported This describes everything needed to both define legality and describe how to make illegal things legal. Here's an example of a complex rule: getActionDefinitions(G_INSERT) .unsupportedIf([=](const LegalityQuery &Query) { // If type0 is smaller than type1 then it's unsupported return Query.Types[0].getSizeInBits() <= Query.Types[1].getSizeInBits(); }) .legalIf([=](const LegalityQuery &Query) { // If type0 is s32/s64/p0 and type1 is a power of 2 other than 2 or 4 then it's legal // We don't need to worry about large type1's because unsupportedIf caught that. const LLT &Ty0 = Query.Types[0]; const LLT &Ty1 = Query.Types[1]; if (Ty0 != s32 && Ty0 != s64 && Ty0 != p0) return false; return isPowerOf2_32(Ty1.getSizeInBits()) && (Ty1.getSizeInBits() == 1 || Ty1.getSizeInBits() >= 8); }) .clampScalar(0, s32, s64) .widenScalarToPow2(0) .maxScalarIf(typeInSet(0, {s32}), 1, s16) // If type0 is s32 and type1 is bigger than s16 then NarrowScalar type1 to s16 .maxScalarIf(typeInSet(0, {s64}), 1, s32) // If type0 is s64 and type1 is bigger than s32 then NarrowScalar type1 to s32 .widenScalarToPow2(1) // Round type1 scalars up to powers of 2 .unsupported(); This uses a lambda to say that G_INSERT is unsupported when type0 is bigger than type1 (in practice, this would be a default rule for G_INSERT). It also uses one to describe the legal cases. This particular predicate is equivalent to: .legalFor({{s32, s1}, {s32, s8}, {s32, s16}, {s64, s1}, {s64, s8}, {s64, s16}, {s64, s32}}) In terms of performance, I saw a slight (~6%) performance improvement when AArch64 was around 30% ported but it's pretty much break even right now. I'm going to take a look at constexpr as a means to reduce the initialization cost. Future work: * Make it possible for opcodes to share rulesets. There's no need for G_LSHR/G_ASHR/G_SDIV/G_UDIV to have separate rule and ruleset objects. There's no technical barrier to this, it just hasn't been done yet. * Replace the type-index numbers with an enum to get .clampScalar(Type0, s32, s64) * Better names for things like .maxScalarIf() (clampMaxScalar?) and the vector rules. * Improve initialization cost using constexpr Possible future work: * It's possible to make these rulesets change the MIR directly instead of returning a description of how to change the MIR. This should remove a little overhead caused by parsing the description and routing to the right code, but the real motivation is that it removes the need for LegalizeAction::Custom. With Custom removed, there's no longer a requirement that Custom legalization change the opcode to something that's considered legal. Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar, volkan, reames, bogner Reviewed By: bogner Subscribers: hintonda, bogner, aemerson, mgorny, javed.absar, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D42251 llvm-svn: 323681
* [globalisel] Make LegalizerInfo::LegalizeAction available outside of ↵Daniel Sanders2018-01-291-92/+80
| | | | | | | | | | | | LegalizerInfo. NFC Summary: The improvements to the LegalizerInfo discussed in D42244 require that LegalizerInfo::LegalizeAction be available for use in other classes. As such, it needs to be moved out of LegalizerInfo. This has been done separately to the next patch to minimize the noise in that patch. llvm-svn: 323669
* Add support for pattern matching MachineInsts.Aditya Nandakumar2018-01-252-1/+337
| | | | | | | | | https://reviews.llvm.org/D42439 Add Instcombine like matchers for MachineInstructions. There are only globalISel matchers for now. llvm-svn: 323400
* [globalisel] Fix long lines from r323342Daniel Sanders2018-01-241-30/+54
| | | | | | They would be fixed in a later patch but they shouldn't have been introduced. llvm-svn: 323372
* [globalisel] Introduce LegalityQuery to better encapsulate the legalizer ↵Daniel Sanders2018-01-241-58/+59
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | decisions. NFC. Summary: `getAction(const InstrAspect &) const` breaks encapsulation by exposing the smaller components that are used to decide how to legalize an instruction. This is a problem because we need to change the implementation of LegalizerInfo so that it's able to describe particular type combinations rather than just cartesian products of types. For example, declaring the following setAction({..., 0, s32}, Legal) setAction({..., 0, s64}, Legal) setAction({..., 1, s32}, Legal) setAction({..., 1, s64}, Legal) currently declares these type combinations as legal: {s32, s32} {s64, s32} {s32, s64} {s64, s64} but we currently have no means to say that, for example, {s64, s32} is not legal. Some operations such as G_INSERT/G_EXTRACT/G_MERGE_VALUES/ G_UNMERGE_VALUES has relationships between the types that are currently described incorrectly. Additionally, G_LOAD/G_STORE currently have no means to legalize non-atomics differently to atomics. The necessary information is in the MMO but we have no way to use this in the legalizer. Similarly, there is currently no way for the register type and the memory type to differ so there is no way to cleanly represent extending-load/truncating-store in a way that can't be broken by optimizers (resulting in illegal MIR). This patch introduces LegalityQuery which provides all the information needed by the legalizer to make a decision on whether something is legal and how to legalize it. Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar, volkan, reames, bogner Reviewed By: bogner Subscribers: bogner, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D42244 llvm-svn: 323342
* Fix a bunch more layering of CodeGen headers that are in TargetDavid Blaikie2017-11-171-1/+1
| | | | | | | | All these headers already depend on CodeGen headers so moving them into CodeGen fixes the layering (since CodeGen depends on Target, not the other way around). llvm-svn: 318490
* Silence MSVC error C2398Kristof Beyls2017-11-071-2/+2
| | | | | | | | Reported by http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/6000/steps/build-unified-tree/logs/stdio The error messages were all similar to: llvm\unittests\CodeGen\GlobalISel\LegalizerInfoTest.cpp(54): error C2398: Element '1': conversion from '' to 'unsigned int' requires a narrowing conversion llvm-svn: 317578
* [GlobalISel] Enable legalizing non-power-of-2 sized types.Kristof Beyls2017-11-071-30/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This changes the interface of how targets describe how to legalize, see the below description. 1. Interface for targets to describe how to legalize. In GlobalISel, the API in the LegalizerInfo class is the main interface for targets to specify which types are legal for which operations, and what to do to turn illegal type/operation combinations into legal ones. For each operation the type sizes that can be legalized without having to change the size of the type are specified with a call to setAction. This isn't different to how GlobalISel worked before. For example, for a target that supports 32 and 64 bit adds natively: for (auto Ty : {s32, s64}) setAction({G_ADD, 0, s32}, Legal); or for a target that needs a library call for a 32 bit division: setAction({G_SDIV, s32}, Libcall); The main conceptual change to the LegalizerInfo API, is in specifying how to legalize the type sizes for which a change of size is needed. For example, in the above example, how to specify how all types from i1 to i8388607 (apart from s32 and s64 which are legal) need to be legalized and expressed in terms of operations on the available legal sizes (again, i32 and i64 in this case). Before, the implementation only allowed specifying power-of-2-sized types (e.g. setAction({G_ADD, 0, s128}, NarrowScalar). A worse limitation was that if you'd wanted to specify how to legalize all the sized types as allowed by the LLVM-IR LangRef, i1 to i8388607, you'd have to call setAction 8388607-3 times and probably would need a lot of memory to store all of these specifications. Instead, the legalization actions that need to change the size of the type are specified now using a "SizeChangeStrategy". For example: setLegalizeScalarToDifferentSizeStrategy( G_ADD, 0, widenToLargerAndNarrowToLargest); This example indicates that for type sizes for which there is a larger size that can be legalized towards, do it by Widening the size. For example, G_ADD on s17 will be legalized by first doing WidenScalar to make it s32, after which it's legal. The "NarrowToLargest" indicates what to do if there is no larger size that can be legalized towards. E.g. G_ADD on s92 will be legalized by doing NarrowScalar to s64. Another example, taken from the ARM backend is: for (unsigned Op : {G_SDIV, G_UDIV}) { setLegalizeScalarToDifferentSizeStrategy(Op, 0, widenToLargerTypesUnsupportedOtherwise); if (ST.hasDivideInARMMode()) setAction({Op, s32}, Legal); else setAction({Op, s32}, Libcall); } For this example, G_SDIV on s8, on a target without a divide instruction, would be legalized by first doing action (WidenScalar, s32), followed by (Libcall, s32). The same principle is also followed for when the number of vector lanes on vector data types need to be changed, e.g.: setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal); setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal); setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal); setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal); setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal); setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal); setLegalizeVectorElementToDifferentSizeStrategy( G_ADD, 0, widenToLargerTypesUnsupportedOtherwise); As currently implemented here, vector types are legalized by first making the vector element size legal, followed by then making the number of lanes legal. The strategy to follow in the first step is set by a call to setLegalizeVectorElementToDifferentSizeStrategy, see example above. The strategy followed in the second step "moreToWiderTypesAndLessToWidest" (see code for its definition), indicating that vectors are widened to more elements so they map to natively supported vector widths, or when there isn't a legal wider vector, split the vector to map it to the widest vector supported. Therefore, for the above specification, some example legalizations are: * getAction({G_ADD, LLT::vector(3, 3)}) returns {WidenScalar, LLT::vector(3, 8)} * getAction({G_ADD, LLT::vector(3, 8)}) then returns {MoreElements, LLT::vector(8, 8)} * getAction({G_ADD, LLT::vector(20, 8)}) returns {FewerElements, LLT::vector(16, 8)} 2. Key implementation aspects. How to legalize a specific (operation, type index, size) tuple is represented by mapping intervals of integers representing a range of size types to an action to take, e.g.: setScalarAction({G_ADD, LLT:scalar(1)}, {{1, WidenScalar}, // bit sizes [ 1, 31[ {32, Legal}, // bit sizes [32, 33[ {33, WidenScalar}, // bit sizes [33, 64[ {64, Legal}, // bit sizes [64, 65[ {65, NarrowScalar} // bit sizes [65, +inf[ }); Please note that most of the code to do the actual lowering of non-power-of-2 sized types is currently missing, this is just trying to make it possible for targets to specify what is legal, and how non-legal types should be legalized. Probably quite a bit of further work is needed in the actual legalizing and the other passes in GlobalISel to support non-power-of-2 sized types. I hope the documentation in LegalizerInfo.h and the examples provided in the various {Target}LegalizerInfo.cpp and LegalizerInfoTest.cpp explains well enough how this is meant to be used. This drops the need for LLT::{half,double}...Size(). Differential Revision: https://reviews.llvm.org/D30529 llvm-svn: 317560
* [GlobalISel] Make GlobalISel a non-optional library.Quentin Colombet2017-08-031-5/+3
| | | | | | | | With this change, the GlobalISel library gets always built. In particular, this is not possible to opt GlobalISel out of the build using the LLVM_BUILD_GLOBAL_ISEL variable any more. llvm-svn: 309990
* [GlobalISel] Make multi-step legalization work.Kristof Beyls2017-06-301-0/+19
| | | | | | | | | | | | | | | | In r301116, a custom lowering needed to be introduced to be able to legalize 8 and 16-bit divisions on ARM targets without a division instruction, since 2-step legalization (WidenScalar from 8 bit to 32 bit, then Libcall the 32-bit division) doesn't work. This fixes this and makes this kind of multi-step legalization, where first the size of the type needs to be changed and then some action is needed that doesn't require changing the size of the type, straighforward to specify. Differential Revision: https://reviews.llvm.org/D32529 llvm-svn: 306806
* GlobalISel: rename legalizer components to match others.Tim Northover2016-10-143-121/+121
| | | | | | | | | | The previous names were both misleading (the MachineLegalizer actually contained the info tables) and inconsistent with the selector & translator (in having a "Machine") prefix. This should make everything sensible again. The only functional change is the name of a couple of command-line options. llvm-svn: 284287
* [GlobalISel] Get the AArch64 tests to work on LinuxDiana Picus2016-10-141-0/+1
| | | | | | | | | | Mostly this just means changing the triple from aarch64-apple-ios to the generic aarch64--. Only one test needs more significant changes, but GlobalISel already does the right thing so it's ok to just change the checks. Differential Revision: https://reviews.llvm.org/D25532 llvm-svn: 284223
* GlobalISel: fix misuse of using declaration in test.Tim Northover2016-10-061-48/+41
| | | | | | Clang didn't diagnose it before. Oops. llvm-svn: 283451
* GlobalISel: cache pointer sizes in LLTTim Northover2016-09-151-7/+8
| | | | | | | Otherwise everything that needs to work out what size they are has to keep a DataLayout handy, which is a bit silly and very annoying. llvm-svn: 281597
* GlobalISel: use multi-dimensional arrays for legalize actions.Tim Northover2016-08-291-0/+2
| | | | | | | | | | | Instead of putting all possible requests into a single table, we can perform the extremely dense lookup based on opcode and type-index in constant time using multi-dimensional array-like things. This roughly halves the time spent doing legalization, which was dominated by queries against the Actions table. llvm-svn: 280011
* GlobalISel: legalize sdiv and srem operations.Tim Northover2016-08-261-0/+2
| | | | llvm-svn: 279842
* GlobalISel: extend legalizer interface to handle multiple types.Tim Northover2016-08-231-22/+42
| | | | | | | | Instructions like G_ICMP have multiple types that may need to be legalized (the boolean output and nearly arbitrary inputs in this case). So the legalizer must be capable of deciding what to do for each of them separately. llvm-svn: 279554
* GlobalISel: implement Legalization querying framework.Tim Northover2016-07-202-0/+111
This adds an (incomplete, inefficient) framework for deciding what to do with some operation on a given type. llvm-svn: 276184
OpenPOWER on IntegriCloud