<div dir="ltr"><div>I have a question: Could there be a way for this legalization to be deployed in a way so that the individual targets can opt out?</div><div><br></div><div>The legalization code for the open source targets seems non-trivial and out of tree targets that aren't doing the legalization yet will break.<br></div><div>Would be nice if there were a way to still be up to date on the latest top of tree without implementing the legalization while not breaking.<br></div><div><br></div><div>PL<br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 8, 2017 at 8:38 AM, Kristof Beyls via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> On 7 Nov 2017, at 19:05, Amara Emerson <<a href="mailto:aemerson@apple.com">aemerson@apple.com</a>> wrote:<br>
><br>
> Thanks Kristof, nice to see this go in. We have a non power of 2 section in the GISel docs (<a href="https://llvm.org/docs/GlobalISel.html#non-power-of-2-types" rel="noreferrer" target="_blank">https://llvm.org/docs/<wbr>GlobalISel.html#non-power-of-<wbr>2-types</a>) that need expanding, could you update that when you get a chance? Looks like this commit message is a good explanation.<br>
><br>
> Cheers,<br>
> Amara<br>
<br>
Thanks for the suggestion, Amara.<br>
I was planning to do that and am hoping to find a bit of time in the next couple of days for it.<br>
<br>
>> On 7 Nov 2017, at 10:34, Kristof Beyls via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> Author: kbeyls<br>
>> Date: Tue Nov 7 02:34:34 2017<br>
>> New Revision: 317560<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=317560&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=317560&view=rev</a><br>
>> Log:<br>
>> [GlobalISel] Enable legalizing non-power-of-2 sized types.<br>
>><br>
>> This changes the interface of how targets describe how to legalize, see<br>
>> the below description.<br>
>><br>
>> 1. Interface for targets to describe how to legalize.<br>
>><br>
>> In GlobalISel, the API in the LegalizerInfo class is the main interface<br>
>> for targets to specify which types are legal for which operations, and<br>
>> what to do to turn illegal type/operation combinations into legal ones.<br>
>><br>
>> For each operation the type sizes that can be legalized without having<br>
>> to change the size of the type are specified with a call to setAction.<br>
>> This isn't different to how GlobalISel worked before. For example, for a<br>
>> target that supports 32 and 64 bit adds natively:<br>
>><br>
>> for (auto Ty : {s32, s64})<br>
>> setAction({G_ADD, 0, s32}, Legal);<br>
>><br>
>> or for a target that needs a library call for a 32 bit division:<br>
>><br>
>> setAction({G_SDIV, s32}, Libcall);<br>
>><br>
>> The main conceptual change to the LegalizerInfo API, is in specifying<br>
>> how to legalize the type sizes for which a change of size is needed. For<br>
>> example, in the above example, how to specify how all types from i1 to<br>
>> i8388607 (apart from s32 and s64 which are legal) need to be legalized<br>
>> and expressed in terms of operations on the available legal sizes<br>
>> (again, i32 and i64 in this case). Before, the implementation only<br>
>> allowed specifying power-of-2-sized types (e.g. setAction({G_ADD, 0,<br>
>> s128}, NarrowScalar). A worse limitation was that if you'd wanted to<br>
>> specify how to legalize all the sized types as allowed by the LLVM-IR<br>
>> LangRef, i1 to i8388607, you'd have to call setAction 8388607-3 times<br>
>> and probably would need a lot of memory to store all of these<br>
>> specifications.<br>
>><br>
>> Instead, the legalization actions that need to change the size of the<br>
>> type are specified now using a "SizeChangeStrategy". For example:<br>
>><br>
>> setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> G_ADD, 0, widenToLargerAndNarrowToLarges<wbr>t);<br>
>><br>
>> This example indicates that for type sizes for which there is a larger<br>
>> size that can be legalized towards, do it by Widening the size.<br>
>> For example, G_ADD on s17 will be legalized by first doing WidenScalar<br>
>> to make it s32, after which it's legal.<br>
>> The "NarrowToLargest" indicates what to do if there is no larger size<br>
>> that can be legalized towards. E.g. G_ADD on s92 will be legalized by<br>
>> doing NarrowScalar to s64.<br>
>><br>
>> Another example, taken from the ARM backend is:<br>
>> for (unsigned Op : {G_SDIV, G_UDIV}) {<br>
>> setLegalizeScalarToDifferentSi<wbr>zeStrategy(Op, 0,<br>
>> widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> if (ST.hasDivideInARMMode())<br>
>> setAction({Op, s32}, Legal);<br>
>> else<br>
>> setAction({Op, s32}, Libcall);<br>
>> }<br>
>><br>
>> For this example, G_SDIV on s8, on a target without a divide<br>
>> instruction, would be legalized by first doing action (WidenScalar,<br>
>> s32), followed by (Libcall, s32).<br>
>><br>
>> The same principle is also followed for when the number of vector lanes<br>
>> on vector data types need to be changed, e.g.:<br>
>><br>
>> setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal);<br>
>> setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal);<br>
>> setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal);<br>
>> setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal);<br>
>> setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal);<br>
>> setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal);<br>
>> setLegalizeVectorElementToDiff<wbr>erentSizeStrategy(<br>
>> G_ADD, 0, widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>><br>
>> As currently implemented here, vector types are legalized by first<br>
>> making the vector element size legal, followed by then making the number<br>
>> of lanes legal. The strategy to follow in the first step is set by a<br>
>> call to setLegalizeVectorElementToDiff<wbr>erentSizeStrategy, see example<br>
>> above. The strategy followed in the second step<br>
>> "<wbr>moreToWiderTypesAndLessToWides<wbr>t" (see code for its definition),<br>
>> indicating that vectors are widened to more elements so they map to<br>
>> natively supported vector widths, or when there isn't a legal wider<br>
>> vector, split the vector to map it to the widest vector supported.<br>
>><br>
>> Therefore, for the above specification, some example legalizations are:<br>
>> * getAction({G_ADD, LLT::vector(3, 3)})<br>
>> returns {WidenScalar, LLT::vector(3, 8)}<br>
>> * getAction({G_ADD, LLT::vector(3, 8)})<br>
>> then returns {MoreElements, LLT::vector(8, 8)}<br>
>> * getAction({G_ADD, LLT::vector(20, 8)})<br>
>> returns {FewerElements, LLT::vector(16, 8)}<br>
>><br>
>><br>
>> 2. Key implementation aspects.<br>
>><br>
>> How to legalize a specific (operation, type index, size) tuple is<br>
>> represented by mapping intervals of integers representing a range of<br>
>> size types to an action to take, e.g.:<br>
>><br>
>> setScalarAction({G_ADD, LLT:scalar(1)},<br>
>> {{1, WidenScalar}, // bit sizes [ 1, 31[<br>
>> {32, Legal}, // bit sizes [32, 33[<br>
>> {33, WidenScalar}, // bit sizes [33, 64[<br>
>> {64, Legal}, // bit sizes [64, 65[<br>
>> {65, NarrowScalar} // bit sizes [65, +inf[<br>
>> });<br>
>><br>
>> Please note that most of the code to do the actual lowering of<br>
>> non-power-of-2 sized types is currently missing, this is just trying to<br>
>> make it possible for targets to specify what is legal, and how non-legal<br>
>> types should be legalized. Probably quite a bit of further work is<br>
>> needed in the actual legalizing and the other passes in GlobalISel to<br>
>> support non-power-of-2 sized types.<br>
>><br>
>> I hope the documentation in LegalizerInfo.h and the examples provided in the<br>
>> various {Target}LegalizerInfo.cpp and LegalizerInfoTest.cpp explains well<br>
>> enough how this is meant to be used.<br>
>><br>
>> This drops the need for LLT::{half,double}...Size().<br>
>><br>
>><br>
>> Differential Revision: <a href="https://reviews.llvm.org/D30529" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D30529</a><br>
>><br>
>><br>
>> Modified:<br>
>> llvm/trunk/include/llvm/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfo.h<br>
>> llvm/trunk/include/llvm/<wbr>Support/LowLevelTypeImpl.h<br>
>> llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerHelper.cpp<br>
>> llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerInfo.cpp<br>
>> llvm/trunk/lib/Support/<wbr>LowLevelType.cpp<br>
>> llvm/trunk/lib/Target/AArch64/<wbr>AArch64LegalizerInfo.cpp<br>
>> llvm/trunk/lib/Target/ARM/<wbr>ARMLegalizerInfo.cpp<br>
>> llvm/trunk/lib/Target/X86/<wbr>X86LegalizerInfo.cpp<br>
>> llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/arm64-<wbr>fallback.ll<br>
>> llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>add.mir<br>
>> llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>inserts.mir<br>
>> llvm/trunk/test/CodeGen/ARM/<wbr>GlobalISel/arm-instruction-<wbr>select.mir<br>
>> llvm/trunk/unittests/CodeGen/<wbr>GlobalISel/LegalizerInfoTest.<wbr>cpp<br>
>> llvm/trunk/unittests/CodeGen/<wbr>LowLevelTypeTest.cpp<br>
>><br>
>> Modified: llvm/trunk/include/llvm/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfo.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/CodeGen/GlobalISel/<wbr>LegalizerInfo.h?rev=317560&r1=<wbr>317559&r2=317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/include/llvm/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfo.h (original)<br>
>> +++ llvm/trunk/include/llvm/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfo.h Tue Nov 7 02:34:34 2017<br>
>> @@ -26,6 +26,7 @@<br>
>> #include <cassert><br>
>> #include <tuple><br>
>> #include <utility><br>
>> +#include <unordered_map><br>
>><br>
>> namespace llvm {<br>
>><br>
>> @@ -120,27 +121,144 @@ public:<br>
>> }<br>
>> }<br>
>><br>
>> + typedef std::pair<uint16_t, LegalizeAction> SizeAndAction;<br>
>> + typedef std::vector<SizeAndAction> SizeAndActionsVec;<br>
>> + using SizeChangeStrategy =<br>
>> + std::function<<wbr>SizeAndActionsVec(const SizeAndActionsVec &v)>;<br>
>> +<br>
>> /// More friendly way to set an action for common types that have an LLT<br>
>> /// representation.<br>
>> + /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize<br>
>> + /// returns false.<br>
>> void setAction(const InstrAspect &Aspect, LegalizeAction Action) {<br>
>> + assert(!<wbr>needsLegalizingToDifferentSize<wbr>(Action));<br>
>> TablesInitialized = false;<br>
>> - unsigned Opcode = Aspect.Opcode - FirstOp;<br>
>> - if (Actions[Opcode].size() <= Aspect.Idx)<br>
>> - Actions[Opcode].resize(Aspect.<wbr>Idx + 1);<br>
>> - Actions[Aspect.Opcode - FirstOp][Aspect.Idx][Aspect.<wbr>Type] = Action;<br>
>> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;<br>
>> + if (SpecifiedActions[OpcodeIdx].<wbr>size() <= Aspect.Idx)<br>
>> + SpecifiedActions[OpcodeIdx].<wbr>resize(Aspect.Idx + 1);<br>
>> + SpecifiedActions[OpcodeIdx][<wbr>Aspect.Idx][Aspect.Type] = Action;<br>
>> }<br>
>><br>
>> - /// If an operation on a given vector type (say <M x iN>) isn't explicitly<br>
>> - /// specified, we proceed in 2 stages. First we legalize the underlying scalar<br>
>> - /// (so that there's at least one legal vector with that scalar), then we<br>
>> - /// adjust the number of elements in the vector so that it is legal. The<br>
>> - /// desired action in the first step is controlled by this function.<br>
>> - void setScalarInVectorAction(<wbr>unsigned Opcode, LLT ScalarTy,<br>
>> - LegalizeAction Action) {<br>
>> - assert(!ScalarTy.isVector());<br>
>> - ScalarInVectorActions[std::<wbr>make_pair(Opcode, ScalarTy)] = Action;<br>
>> + /// The setAction calls record the non-size-changing legalization actions<br>
>> + /// to take on specificly-sized types. The SizeChangeStrategy defines what<br>
>> + /// to do when the size of the type needs to be changed to reach a legally<br>
>> + /// sized type (i.e., one that was defined through a setAction call).<br>
>> + /// e.g.<br>
>> + /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);<br>
>> + /// setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + /// G_ADD, 0, widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> + /// will end up defining getAction({G_ADD, 0, T}) to return the following<br>
>> + /// actions for different scalar types T:<br>
>> + /// LLT::scalar(1)..LLT::scalar(<wbr>31): {WidenScalar, 0, LLT::scalar(32)}<br>
>> + /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}<br>
>> + /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}<br>
>> + ///<br>
>> + /// If no SizeChangeAction gets defined, through this function,<br>
>> + /// the default is unsupportedForDifferentSizes.<br>
>> + void setLegalizeScalarToDifferentSi<wbr>zeStrategy(const unsigned Opcode,<br>
>> + const unsigned TypeIdx,<br>
>> + SizeChangeStrategy S) {<br>
>> + const unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + if (ScalarSizeChangeStrategies[<wbr>OpcodeIdx].size() <= TypeIdx)<br>
>> + ScalarSizeChangeStrategies[<wbr>OpcodeIdx].resize(TypeIdx + 1);<br>
>> + ScalarSizeChangeStrategies[<wbr>OpcodeIdx][TypeIdx] = S;<br>
>> + }<br>
>> +<br>
>> + /// See also setLegalizeScalarToDifferentSi<wbr>zeStrategy.<br>
>> + /// This function allows to set the SizeChangeStrategy for vector elements.<br>
>> + void setLegalizeVectorElementToDiff<wbr>erentSizeStrategy(const unsigned Opcode,<br>
>> + const unsigned TypeIdx,<br>
>> + SizeChangeStrategy S) {<br>
>> + const unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + if (<wbr>VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx].size() <= TypeIdx)<br>
>> + VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx].resize(TypeIdx + 1);<br>
>> + VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx][TypeIdx] = S;<br>
>> + }<br>
>> +<br>
>> + /// A SizeChangeStrategy for the common case where legalization for a<br>
>> + /// particular operation consists of only supporting a specific set of type<br>
>> + /// sizes. E.g.<br>
>> + /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);<br>
>> + /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);<br>
>> + /// setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + /// G_DIV, 0, unsupportedForDifferentSizes);<br>
>> + /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,<br>
>> + /// and Unsupported for all other scalar types T.<br>
>> + static SizeAndActionsVec<br>
>> + unsupportedForDifferentSizes(<wbr>const SizeAndActionsVec &v) {<br>
>> + return increaseToLargerTypesAndDecrea<wbr>seToLargest(v, Unsupported,<br>
>> + Unsupported);<br>
>> + }<br>
>> +<br>
>> + /// A SizeChangeStrategy for the common case where legalization for a<br>
>> + /// particular operation consists of widening the type to a large legal type,<br>
>> + /// unless there is no such type and then instead it should be narrowed to the<br>
>> + /// largest legal type.<br>
>> + static SizeAndActionsVec<br>
>> + widenToLargerTypesAndNarrowToL<wbr>argest(const SizeAndActionsVec &v) {<br>
>> + assert(v.size() > 0 &&<br>
>> + "At least one size that can be legalized towards is needed"<br>
>> + " for this SizeChangeStrategy");<br>
>> + return increaseToLargerTypesAndDecrea<wbr>seToLargest(v, WidenScalar,<br>
>> + NarrowScalar);<br>
>> }<br>
>><br>
>> + static SizeAndActionsVec<br>
>> + widenToLargerTypesUnsupportedO<wbr>therwise(const SizeAndActionsVec &v) {<br>
>> + return increaseToLargerTypesAndDecrea<wbr>seToLargest(v, WidenScalar,<br>
>> + Unsupported);<br>
>> + }<br>
>> +<br>
>> + static SizeAndActionsVec<br>
>> + narrowToSmallerAndUnsupportedI<wbr>fTooSmall(const SizeAndActionsVec &v) {<br>
>> + return decreaseToSmallerTypesAndIncre<wbr>aseToSmallest(v, NarrowScalar,<br>
>> + Unsupported);<br>
>> + }<br>
>> +<br>
>> + static SizeAndActionsVec<br>
>> + narrowToSmallerAndWidenToSmall<wbr>est(const SizeAndActionsVec &v) {<br>
>> + assert(v.size() > 0 &&<br>
>> + "At least one size that can be legalized towards is needed"<br>
>> + " for this SizeChangeStrategy");<br>
>> + return decreaseToSmallerTypesAndIncre<wbr>aseToSmallest(v, NarrowScalar,<br>
>> + WidenScalar);<br>
>> + }<br>
>> +<br>
>> + /// A SizeChangeStrategy for the common case where legalization for a<br>
>> + /// particular vector operation consists of having more elements in the<br>
>> + /// vector, to a type that is legal. Unless there is no such type and then<br>
>> + /// instead it should be legalized towards the widest vector that's still<br>
>> + /// legal. E.g.<br>
>> + /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);<br>
>> + /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);<br>
>> + /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);<br>
>> + /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);<br>
>> + /// setLegalizeVectorElementToDiff<wbr>erentSizeStrategy(<br>
>> + /// G_ADD, 0, moreToWiderTypesAndLessToWides<wbr>t);<br>
>> + /// will result in the following getAction results:<br>
>> + /// * getAction({G_ADD, LLT::vector(8,8)}) returns<br>
>> + /// (Legal, vector(8,8)).<br>
>> + /// * getAction({G_ADD, LLT::vector(9,8)}) returns<br>
>> + /// (MoreElements, vector(16,8)).<br>
>> + /// * getAction({G_ADD, LLT::vector(8,32)}) returns<br>
>> + /// (FewerElements, vector(4,32)).<br>
>> + static SizeAndActionsVec<br>
>> + moreToWiderTypesAndLessToWides<wbr>t(const SizeAndActionsVec &v) {<br>
>> + return increaseToLargerTypesAndDecrea<wbr>seToLargest(v, MoreElements,<br>
>> + FewerElements);<br>
>> + }<br>
>> +<br>
>> + /// Helper function to implement many typical SizeChangeStrategy functions.<br>
>> + static SizeAndActionsVec<br>
>> + increaseToLargerTypesAndDecrea<wbr>seToLargest(const SizeAndActionsVec &v,<br>
>> + LegalizeAction IncreaseAction,<br>
>> + LegalizeAction DecreaseAction);<br>
>> + /// Helper function to implement many typical SizeChangeStrategy functions.<br>
>> + static SizeAndActionsVec<br>
>> + decreaseToSmallerTypesAndIncre<wbr>aseToSmallest(const SizeAndActionsVec &v,<br>
>> + LegalizeAction DecreaseAction,<br>
>> + LegalizeAction IncreaseAction);<br>
>> +<br>
>> /// Determine what action should be taken to legalize the given generic<br>
>> /// instruction opcode, type-index and type. Requires computeTables to have<br>
>> /// been called.<br>
>> @@ -158,58 +276,6 @@ public:<br>
>> std::tuple<LegalizeAction, unsigned, LLT><br>
>> getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;<br>
>><br>
>> - /// Iterate the given function (typically something like doubling the width)<br>
>> - /// on Ty until we find a legal type for this operation.<br>
>> - Optional<LLT> findLegalizableSize(const InstrAspect &Aspect,<br>
>> - function_ref<LLT(LLT)> NextType) const {<br>
>> - if (Aspect.Idx >= Actions[Aspect.Opcode - FirstOp].size())<br>
>> - return None;<br>
>> -<br>
>> - LegalizeAction Action;<br>
>> - const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];<br>
>> - LLT Ty = Aspect.Type;<br>
>> - do {<br>
>> - Ty = NextType(Ty);<br>
>> - auto ActionIt = Map.find(Ty);<br>
>> - if (ActionIt == Map.end()) {<br>
>> - auto DefaultIt = DefaultActions.find(Aspect.<wbr>Opcode);<br>
>> - if (DefaultIt == DefaultActions.end())<br>
>> - return None;<br>
>> - Action = DefaultIt->second;<br>
>> - } else<br>
>> - Action = ActionIt->second;<br>
>> - } while (<wbr>needsLegalizingToDifferentSize<wbr>(Action));<br>
>> - return Ty;<br>
>> - }<br>
>> -<br>
>> - /// Find what type it's actually OK to perform the given operation on, given<br>
>> - /// the general approach we've decided to take.<br>
>> - Optional<LLT> findLegalType(const InstrAspect &Aspect, LegalizeAction Action) const;<br>
>> -<br>
>> - std::pair<LegalizeAction, LLT> findLegalAction(const InstrAspect &Aspect,<br>
>> - LegalizeAction Action) const {<br>
>> - auto LegalType = findLegalType(Aspect, Action);<br>
>> - if (!LegalType)<br>
>> - return std::make_pair(LegalizeAction:<wbr>:Unsupported, LLT());<br>
>> - return std::make_pair(Action, *LegalType);<br>
>> - }<br>
>> -<br>
>> - /// Find the specified \p Aspect in the primary (explicitly set) Actions<br>
>> - /// table. Returns either the action the target requested or NotFound if there<br>
>> - /// was no setAction call.<br>
>> - LegalizeAction findInActions(const InstrAspect &Aspect) const {<br>
>> - if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)<br>
>> - return NotFound;<br>
>> - if (Aspect.Idx >= Actions[Aspect.Opcode - FirstOp].size())<br>
>> - return NotFound;<br>
>> - const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];<br>
>> - auto ActionIt = Map.find(Aspect.Type);<br>
>> - if (ActionIt == Map.end())<br>
>> - return NotFound;<br>
>> -<br>
>> - return ActionIt->second;<br>
>> - }<br>
>> -<br>
>> bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;<br>
>><br>
>> virtual bool legalizeCustom(MachineInstr &MI,<br>
>> @@ -217,20 +283,181 @@ public:<br>
>> MachineIRBuilder &MIRBuilder) const;<br>
>><br>
>> private:<br>
>> - static const int FirstOp = TargetOpcode::PRE_ISEL_<wbr>GENERIC_OPCODE_START;<br>
>> - static const int LastOp = TargetOpcode::PRE_ISEL_<wbr>GENERIC_OPCODE_END;<br>
>> + /// The SizeAndActionsVec is a representation mapping between all natural<br>
>> + /// numbers and an Action. The natural number represents the bit size of<br>
>> + /// the InstrAspect. For example, for a target with native support for 32-bit<br>
>> + /// and 64-bit additions, you'd express that as:<br>
>> + /// setScalarAction(G_ADD, 0,<br>
>> + /// {{1, WidenScalar}, // bit sizes [ 1, 31[<br>
>> + /// {32, Legal}, // bit sizes [32, 33[<br>
>> + /// {33, WidenScalar}, // bit sizes [33, 64[<br>
>> + /// {64, Legal}, // bit sizes [64, 65[<br>
>> + /// {65, NarrowScalar} // bit sizes [65, +inf[<br>
>> + /// });<br>
>> + /// It may be that only 64-bit pointers are supported on your target:<br>
>> + /// setPointerAction(G_GEP, 0, LLT:pointer(1),<br>
>> + /// {{1, Unsupported}, // bit sizes [ 1, 63[<br>
>> + /// {64, Legal}, // bit sizes [64, 65[<br>
>> + /// {65, Unsupported}, // bit sizes [65, +inf[<br>
>> + /// });<br>
>> + void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,<br>
>> + const SizeAndActionsVec &SizeAndActions) {<br>
>> + const unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];<br>
>> + setActions(TypeIndex, Actions, SizeAndActions);<br>
>> + }<br>
>> + void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,<br>
>> + const unsigned AddressSpace,<br>
>> + const SizeAndActionsVec &SizeAndActions) {<br>
>> + const unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + if (AddrSpace2PointerActions[<wbr>OpcodeIdx].find(AddressSpace) ==<br>
>> + AddrSpace2PointerActions[<wbr>OpcodeIdx].end())<br>
>> + AddrSpace2PointerActions[<wbr>OpcodeIdx][AddressSpace] = {{}};<br>
>> + SmallVector<SizeAndActionsVec, 1> &Actions =<br>
>> + AddrSpace2PointerActions[<wbr>OpcodeIdx].find(AddressSpace)-<wbr>>second;<br>
>> + setActions(TypeIndex, Actions, SizeAndActions);<br>
>> + }<br>
>><br>
>> - using TypeMap = DenseMap<LLT, LegalizeAction>;<br>
>> - using SIVActionMap = DenseMap<std::pair<unsigned, LLT>, LegalizeAction>;<br>
>> + /// If an operation on a given vector type (say <M x iN>) isn't explicitly<br>
>> + /// specified, we proceed in 2 stages. First we legalize the underlying scalar<br>
>> + /// (so that there's at least one legal vector with that scalar), then we<br>
>> + /// adjust the number of elements in the vector so that it is legal. The<br>
>> + /// desired action in the first step is controlled by this function.<br>
>> + void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,<br>
>> + const SizeAndActionsVec &SizeAndActions) {<br>
>> + unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + SmallVector<SizeAndActionsVec, 1> &Actions =<br>
>> + ScalarInVectorActions[<wbr>OpcodeIdx];<br>
>> + setActions(TypeIndex, Actions, SizeAndActions);<br>
>> + }<br>
>><br>
>> - SmallVector<TypeMap, 1> Actions[LastOp - FirstOp + 1];<br>
>> - SIVActionMap ScalarInVectorActions;<br>
>> - DenseMap<std::pair<unsigned, LLT>, uint16_t> MaxLegalVectorElts;<br>
>> - DenseMap<unsigned, LegalizeAction> DefaultActions;<br>
>> + /// See also setScalarInVectorAction.<br>
>> + /// This function let's you specify the number of elements in a vector that<br>
>> + /// are legal for a legal element size.<br>
>> + void setVectorNumElementAction(<wbr>const unsigned Opcode,<br>
>> + const unsigned TypeIndex,<br>
>> + const unsigned ElementSize,<br>
>> + const SizeAndActionsVec &SizeAndActions) {<br>
>> + const unsigned OpcodeIdx = Opcode - FirstOp;<br>
>> + if (NumElements2Actions[<wbr>OpcodeIdx].find(ElementSize) ==<br>
>> + NumElements2Actions[OpcodeIdx]<wbr>.end())<br>
>> + NumElements2Actions[OpcodeIdx]<wbr>[ElementSize] = {{}};<br>
>> + SmallVector<SizeAndActionsVec, 1> &Actions =<br>
>> + NumElements2Actions[OpcodeIdx]<wbr>.find(ElementSize)->second;<br>
>> + setActions(TypeIndex, Actions, SizeAndActions);<br>
>> + }<br>
>> +<br>
>> + /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,<br>
>> + /// i.e. it's OK if it doesn't start from size 1.<br>
>> + static void checkPartialSizeAndActionsVect<wbr>or(const SizeAndActionsVec& v) {<br>
>> +#ifndef NDEBUG<br>
>> + // The sizes should be in increasing order<br>
>> + int prev_size = -1;<br>
>> + for(auto SizeAndAction: v) {<br>
>> + assert(SizeAndAction.first > prev_size);<br>
>> + prev_size = SizeAndAction.first;<br>
>> + }<br>
>> + // - for every Widen action, there should be a larger bitsize that<br>
>> + // can be legalized towards (e.g. Legal, Lower, Libcall or Custom<br>
>> + // action).<br>
>> + // - for every Narrow action, there should be a smaller bitsize that<br>
>> + // can be legalized towards.<br>
>> + int SmallestNarrowIdx = -1;<br>
>> + int LargestWidenIdx = -1;<br>
>> + int SmallestLegalizableToSameSizeI<wbr>dx = -1;<br>
>> + int LargestLegalizableToSameSizeId<wbr>x = -1;<br>
>> + for(size_t i=0; i<v.size(); ++i) {<br>
>> + switch (v[i].second) {<br>
>> + case FewerElements:<br>
>> + case NarrowScalar:<br>
>> + if (SmallestNarrowIdx == -1)<br>
>> + SmallestNarrowIdx = i;<br>
>> + break;<br>
>> + case WidenScalar:<br>
>> + case MoreElements:<br>
>> + LargestWidenIdx = i;<br>
>> + break;<br>
>> + case Unsupported:<br>
>> + break;<br>
>> + default:<br>
>> + if (<wbr>SmallestLegalizableToSameSizeI<wbr>dx == -1)<br>
>> + SmallestLegalizableToSameSizeI<wbr>dx = i;<br>
>> + LargestLegalizableToSameSizeId<wbr>x = i;<br>
>> + }<br>
>> + }<br>
>> + if (SmallestNarrowIdx != -1) {<br>
>> + assert(<wbr>SmallestLegalizableToSameSizeI<wbr>dx != -1);<br>
>> + assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeI<wbr>dx);<br>
>> + }<br>
>> + if (LargestWidenIdx != -1)<br>
>> + assert(LargestWidenIdx < LargestLegalizableToSameSizeId<wbr>x);<br>
>> +#endif<br>
>> + }<br>
>> +<br>
>> + /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with<br>
>> + /// from size 1.<br>
>> + static void checkFullSizeAndActionsVector(<wbr>const SizeAndActionsVec& v) {<br>
>> +#ifndef NDEBUG<br>
>> + // Data structure invariant: The first bit size must be size 1.<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first == 1);<br>
>> + checkPartialSizeAndActionsVect<wbr>or(v);<br>
>> +#endif<br>
>> + }<br>
>> +<br>
>> + /// Sets actions for all bit sizes on a particular generic opcode, type<br>
>> + /// index and scalar or pointer type.<br>
>> + void setActions(unsigned TypeIndex,<br>
>> + SmallVector<SizeAndActionsVec, 1> &Actions,<br>
>> + const SizeAndActionsVec &SizeAndActions) {<br>
>> + checkFullSizeAndActionsVector(<wbr>SizeAndActions);<br>
>> + if (Actions.size() <= TypeIndex)<br>
>> + Actions.resize(TypeIndex + 1);<br>
>> + Actions[TypeIndex] = SizeAndActions;<br>
>> + }<br>
>> +<br>
>> + static SizeAndAction findAction(const SizeAndActionsVec &Vec,<br>
>> + const uint32_t Size);<br>
>> +<br>
>> + /// Returns the next action needed to get the scalar or pointer type closer<br>
>> + /// to being legal<br>
>> + /// E.g. findLegalAction({G_REM, 13}) should return<br>
>> + /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will<br>
>> + /// probably be called, which should return (Lower, 32).<br>
>> + /// This is assuming the setScalarAction on G_REM was something like:<br>
>> + /// setScalarAction(G_REM, 0,<br>
>> + /// {{1, WidenScalar}, // bit sizes [ 1, 31[<br>
>> + /// {32, Lower}, // bit sizes [32, 33[<br>
>> + /// {33, NarrowScalar} // bit sizes [65, +inf[<br>
>> + /// });<br>
>> + std::pair<LegalizeAction, LLT><br>
>> + findScalarLegalAction(const InstrAspect &Aspect) const;<br>
>> +<br>
>> + /// Returns the next action needed towards legalizing the vector type.<br>
>> + std::pair<LegalizeAction, LLT><br>
>> + findVectorLegalAction(const InstrAspect &Aspect) const;<br>
>> +<br>
>> + static const int FirstOp = TargetOpcode::PRE_ISEL_<wbr>GENERIC_OPCODE_START;<br>
>> + static const int LastOp = TargetOpcode::PRE_ISEL_<wbr>GENERIC_OPCODE_END;<br>
>><br>
>> - bool TablesInitialized = false;<br>
>> + // Data structures used temporarily during construction of legality data:<br>
>> + typedef DenseMap<LLT, LegalizeAction> TypeMap;<br>
>> + SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];<br>
>> + SmallVector<<wbr>SizeChangeStrategy, 1><br>
>> + ScalarSizeChangeStrategies[<wbr>LastOp - FirstOp + 1];<br>
>> + SmallVector<<wbr>SizeChangeStrategy, 1><br>
>> + VectorElementSizeChangeStrateg<wbr>ies[LastOp - FirstOp + 1];<br>
>> + bool TablesInitialized;<br>
>> +<br>
>> + // Data structures used by getAction:<br>
>> + SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];<br>
>> + SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];<br>
>> + std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>><br>
>> + AddrSpace2PointerActions[<wbr>LastOp - FirstOp + 1];<br>
>> + std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>><br>
>> + NumElements2Actions[LastOp - FirstOp + 1];<br>
>> };<br>
>><br>
>> -} // end namespace llvm<br>
>> +} // end namespace llvm.<br>
>><br>
>> #endif // LLVM_CODEGEN_GLOBALISEL_<wbr>LEGALIZERINFO_H<br>
>><br>
>> Modified: llvm/trunk/include/llvm/<wbr>Support/LowLevelTypeImpl.h<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/LowLevelTypeImpl.h?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/Support/LowLevelTypeImpl.<wbr>h?rev=317560&r1=317559&r2=<wbr>317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/include/llvm/<wbr>Support/LowLevelTypeImpl.h (original)<br>
>> +++ llvm/trunk/include/llvm/<wbr>Support/LowLevelTypeImpl.h Tue Nov 7 02:34:34 2017<br>
>> @@ -137,51 +137,6 @@ public:<br>
>> return scalar(getScalarSizeInBits());<br>
>> }<br>
>><br>
>> - /// Get a low-level type with half the size of the original, by halving the<br>
>> - /// size of the scalar type involved. For example `s32` will become `s16`,<br>
>> - /// `<2 x s32>` will become `<2 x s16>`.<br>
>> - LLT halfScalarSize() const {<br>
>> - assert(!IsPointer && getScalarSizeInBits() > 1 &&<br>
>> - getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");<br>
>> - return LLT{/*isPointer=*/false, IsVector ? true : false,<br>
>> - IsVector ? getNumElements() : (uint16_t)0,<br>
>> - getScalarSizeInBits() / 2, /*AddressSpace=*/0};<br>
>> - }<br>
>> -<br>
>> - /// Get a low-level type with twice the size of the original, by doubling the<br>
>> - /// size of the scalar type involved. For example `s32` will become `s64`,<br>
>> - /// `<2 x s32>` will become `<2 x s64>`.<br>
>> - LLT doubleScalarSize() const {<br>
>> - assert(!IsPointer && "cannot change size of this type");<br>
>> - return LLT{/*isPointer=*/false, IsVector ? true : false,<br>
>> - IsVector ? getNumElements() : (uint16_t)0,<br>
>> - getScalarSizeInBits() * 2, /*AddressSpace=*/0};<br>
>> - }<br>
>> -<br>
>> - /// Get a low-level type with half the size of the original, by halving the<br>
>> - /// number of vector elements of the scalar type involved. The source must be<br>
>> - /// a vector type with an even number of elements. For example `<4 x s32>`<br>
>> - /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.<br>
>> - LLT halfElements() const {<br>
>> - assert(isVector() && getNumElements() % 2 == 0 && "cannot half odd vector");<br>
>> - if (getNumElements() == 2)<br>
>> - return scalar(getScalarSizeInBits());<br>
>> -<br>
>> - return LLT{/*isPointer=*/false, /*isVector=*/true,<br>
>> - (uint16_t)(getNumElements() / 2), getScalarSizeInBits(),<br>
>> - /*AddressSpace=*/0};<br>
>> - }<br>
>> -<br>
>> - /// Get a low-level type with twice the size of the original, by doubling the<br>
>> - /// number of vector elements of the scalar type involved. The source must be<br>
>> - /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling<br>
>> - /// the number of elements in sN produces <2 x sN>.<br>
>> - LLT doubleElements() const {<br>
>> - return LLT{IsPointer ? true : false, /*isVector=*/true,<br>
>> - (uint16_t)(getNumElements() * 2), getScalarSizeInBits(),<br>
>> - IsPointer ? getAddressSpace() : 0};<br>
>> - }<br>
>> -<br>
>> void print(raw_ostream &OS) const;<br>
>><br>
>> bool operator==(const LLT &RHS) const {<br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerHelper.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>CodeGen/GlobalISel/<wbr>LegalizerHelper.cpp?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerHelper.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerHelper.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -173,12 +173,18 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>><br>
>> MIRBuilder.setInstr(MI);<br>
>><br>
>> + int64_t SizeOp0 = MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits();<br>
>> + int64_t NarrowSize = NarrowTy.getSizeInBits();<br>
>> +<br>
>> switch (MI.getOpcode()) {<br>
>> default:<br>
>> return UnableToLegalize;<br>
>> case TargetOpcode::G_IMPLICIT_DEF: {<br>
>> - int NumParts = MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() /<br>
>> - NarrowTy.getSizeInBits();<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>><br>
>> SmallVector<unsigned, 2> DstRegs;<br>
>> for (int i = 0; i < NumParts; ++i) {<br>
>> @@ -191,9 +197,12 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> return Legalized;<br>
>> }<br>
>> case TargetOpcode::G_ADD: {<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> // Expand in terms of carry-setting/consuming G_ADDE instructions.<br>
>> - int NumParts = MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() /<br>
>> - NarrowTy.getSizeInBits();<br>
>> + int NumParts = SizeOp0 / NarrowTy.getSizeInBits();<br>
>><br>
>> SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;<br>
>> extractParts(MI.getOperand(1).<wbr>getReg(), NarrowTy, NumParts, Src1Regs);<br>
>> @@ -221,9 +230,12 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> if (TypeIdx != 1)<br>
>> return UnableToLegalize;<br>
>><br>
>> - int64_t NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(1).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> + int64_t SizeOp1 = MRI.getType(MI.getOperand(1).<wbr>getReg()).getSizeInBits();<br>
>> + // FIXME: add support for when SizeOp1 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp1 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp1 / NarrowSize;<br>
>><br>
>> SmallVector<unsigned, 2> SrcRegs, DstRegs;<br>
>> SmallVector<uint64_t, 2> Indexes;<br>
>> @@ -270,12 +282,12 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> return Legalized;<br>
>> }<br>
>> case TargetOpcode::G_INSERT: {<br>
>> - if (TypeIdx != 0)<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> return UnableToLegalize;<br>
>><br>
>> - int64_t NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>><br>
>> SmallVector<unsigned, 2> SrcRegs, DstRegs;<br>
>> SmallVector<uint64_t, 2> Indexes;<br>
>> @@ -330,9 +342,11 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> return Legalized;<br>
>> }<br>
>> case TargetOpcode::G_LOAD: {<br>
>> - unsigned NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>> LLT OffsetTy = LLT::scalar(<br>
>> MRI.getType(MI.getOperand(1).<wbr>getReg()).getScalarSizeInBits(<wbr>));<br>
>><br>
>> @@ -357,9 +371,11 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> return Legalized;<br>
>> }<br>
>> case TargetOpcode::G_STORE: {<br>
>> - unsigned NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>> LLT OffsetTy = LLT::scalar(<br>
>> MRI.getType(MI.getOperand(1).<wbr>getReg()).getScalarSizeInBits(<wbr>));<br>
>><br>
>> @@ -381,9 +397,11 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> return Legalized;<br>
>> }<br>
>> case TargetOpcode::G_CONSTANT: {<br>
>> - unsigned NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>> const APInt &Cst = MI.getOperand(1).getCImm()-><wbr>getValue();<br>
>> LLVMContext &Ctx = MIRBuilder.getMF().<wbr>getFunction()->getContext();<br>
>><br>
>> @@ -410,9 +428,12 @@ LegalizerHelper::<wbr>LegalizeResult Legalize<br>
>> // ...<br>
>> // AN = BinOp<Ty/N> BN, CN<br>
>> // A = G_MERGE_VALUES A1, ..., AN<br>
>> - unsigned NarrowSize = NarrowTy.getSizeInBits();<br>
>> - int NumParts =<br>
>> - MRI.getType(MI.getOperand(0).<wbr>getReg()).getSizeInBits() / NarrowSize;<br>
>> +<br>
>> + // FIXME: add support for when SizeOp0 isn't an exact multiple of<br>
>> + // NarrowSize.<br>
>> + if (SizeOp0 % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>> + int NumParts = SizeOp0 / NarrowSize;<br>
>><br>
>> // List the registers where the destination will be scattered.<br>
>> SmallVector<unsigned, 2> DstRegs;<br>
>> @@ -854,7 +875,12 @@ LegalizerHelper::<wbr>fewerElementsVector(Mac<br>
>> case TargetOpcode::G_ADD: {<br>
>> unsigned NarrowSize = NarrowTy.getSizeInBits();<br>
>> unsigned DstReg = MI.getOperand(0).getReg();<br>
>> - int NumParts = MRI.getType(DstReg).<wbr>getSizeInBits() / NarrowSize;<br>
>> + unsigned Size = MRI.getType(DstReg).<wbr>getSizeInBits();<br>
>> + int NumParts = Size / NarrowSize;<br>
>> + // FIXME: Don't know how to handle the situation where the small vectors<br>
>> + // aren't all the same size yet.<br>
>> + if (Size % NarrowSize != 0)<br>
>> + return UnableToLegalize;<br>
>><br>
>> MIRBuilder.setInstr(MI);<br>
>><br>
>><br>
>> Modified: llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfo.cpp?rev=317560&<wbr>r1=317559&r2=317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/CodeGen/<wbr>GlobalISel/LegalizerInfo.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -28,46 +28,130 @@<br>
>> #include "llvm/Support/MathExtras.h"<br>
>> #include "llvm/Target/TargetOpcodes.h"<br>
>> #include <algorithm><br>
>> -#include <cassert><br>
>> -#include <tuple><br>
>> -#include <utility><br>
>> -<br>
>> +#include <map><br>
>> using namespace llvm;<br>
>><br>
>> -LegalizerInfo::LegalizerInfo(<wbr>) {<br>
>> - DefaultActions[TargetOpcode::<wbr>G_IMPLICIT_DEF] = NarrowScalar;<br>
>> -<br>
>> - // FIXME: these two can be legalized to the fundamental load/store Jakob<br>
>> - // proposed. Once loads & stores are supported.<br>
>> - DefaultActions[TargetOpcode::<wbr>G_ANYEXT] = Legal;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_TRUNC] = Legal;<br>
>> -<br>
>> - DefaultActions[TargetOpcode::<wbr>G_INTRINSIC] = Legal;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_INTRINSIC_W_SIDE_EFFECTS] = Legal;<br>
>> -<br>
>> - DefaultActions[TargetOpcode::<wbr>G_ADD] = NarrowScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_LOAD] = NarrowScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_STORE] = NarrowScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_OR] = NarrowScalar;<br>
>> -<br>
>> - DefaultActions[TargetOpcode::<wbr>G_BRCOND] = WidenScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_INSERT] = NarrowScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_EXTRACT] = NarrowScalar;<br>
>> - DefaultActions[TargetOpcode::<wbr>G_FNEG] = Lower;<br>
>> +LegalizerInfo::LegalizerInfo(<wbr>) : TablesInitialized(false) {<br>
>> + // Set defaults.<br>
>> + // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the<br>
>> + // fundamental load/store Jakob proposed. Once loads & stores are supported.<br>
>> + setScalarAction(TargetOpcode::<wbr>G_ANYEXT, 1, {{1, Legal}});<br>
>> + setScalarAction(TargetOpcode::<wbr>G_ZEXT, 1, {{1, Legal}});<br>
>> + setScalarAction(TargetOpcode::<wbr>G_SEXT, 1, {{1, Legal}});<br>
>> + setScalarAction(TargetOpcode::<wbr>G_TRUNC, 0, {{1, Legal}});<br>
>> + setScalarAction(TargetOpcode::<wbr>G_TRUNC, 1, {{1, Legal}});<br>
>> +<br>
>> + setScalarAction(TargetOpcode::<wbr>G_INTRINSIC, 0, {{1, Legal}});<br>
>> + setScalarAction(TargetOpcode::<wbr>G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});<br>
>> +<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> +<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedI<wbr>fTooSmall);<br>
>> + setScalarAction(TargetOpcode::<wbr>G_FNEG, 0, {{1, Lower}});<br>
>> }<br>
>><br>
>> void LegalizerInfo::computeTables() {<br>
>> - for (unsigned Opcode = 0; Opcode <= LastOp - FirstOp; ++Opcode) {<br>
>> - for (unsigned Idx = 0, End = Actions[Opcode].size(); Idx != End; ++Idx) {<br>
>> - for (auto &Action : Actions[Opcode][Idx]) {<br>
>> - LLT Ty = Action.first;<br>
>> - if (!Ty.isVector())<br>
>> - continue;<br>
>> -<br>
>> - auto &Entry = MaxLegalVectorElts[std::make_<wbr>pair(Opcode + FirstOp,<br>
>> - Ty.getElementType())];<br>
>> - Entry = std::max(Entry, Ty.getNumElements());<br>
>> + assert(TablesInitialized == false);<br>
>> +<br>
>> + for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {<br>
>> + const unsigned Opcode = FirstOp + OpcodeIdx;<br>
>> + for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].<wbr>size();<br>
>> + ++TypeIdx) {<br>
>> + // 0. Collect information specified through the setAction API, i.e.<br>
>> + // for specific bit sizes.<br>
>> + // For scalar types:<br>
>> + SizeAndActionsVec ScalarSpecifiedActions;<br>
>> + // For pointer types:<br>
>> + std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;<br>
>> + // For vector types:<br>
>> + std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;<br>
>> + for (auto LLT2Action : SpecifiedActions[OpcodeIdx][<wbr>TypeIdx]) {<br>
>> + const LLT Type = LLT2Action.first;<br>
>> + const LegalizeAction Action = LLT2Action.second;<br>
>> +<br>
>> + auto SizeAction = std::make_pair(Type.<wbr>getSizeInBits(), Action);<br>
>> + if (Type.isPointer())<br>
>> + AddressSpace2SpecifiedActions[<wbr>Type.getAddressSpace()].push_<wbr>back(<br>
>> + SizeAction);<br>
>> + else if (Type.isVector())<br>
>> + ElemSize2SpecifiedActions[<wbr>Type.getElementType().<wbr>getSizeInBits()]<br>
>> + .push_back(SizeAction);<br>
>> + else<br>
>> + ScalarSpecifiedActions.push_<wbr>back(SizeAction);<br>
>> + }<br>
>> +<br>
>> + // 1. Handle scalar types<br>
>> + {<br>
>> + // Decide how to handle bit sizes for which no explicit specification<br>
>> + // was given.<br>
>> + SizeChangeStrategy S = &unsupportedForDifferentSizes;<br>
>> + if (TypeIdx < ScalarSizeChangeStrategies[<wbr>OpcodeIdx].size() &&<br>
>> + ScalarSizeChangeStrategies[<wbr>OpcodeIdx][TypeIdx] != nullptr)<br>
>> + S = ScalarSizeChangeStrategies[<wbr>OpcodeIdx][TypeIdx];<br>
>> + std::sort(<wbr>ScalarSpecifiedActions.begin()<wbr>, ScalarSpecifiedActions.end());<br>
>> + checkPartialSizeAndActionsVect<wbr>or(ScalarSpecifiedActions);<br>
>> + setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));<br>
>> + }<br>
>> +<br>
>> + // 2. Handle pointer types<br>
>> + for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {<br>
>> + std::sort(<wbr>PointerSpecifiedActions.<wbr>second.begin(),<br>
>> + PointerSpecifiedActions.<wbr>second.end());<br>
>> + checkPartialSizeAndActionsVect<wbr>or(PointerSpecifiedActions.<wbr>second);<br>
>> + // For pointer types, we assume that there isn't a meaningfull way<br>
>> + // to change the number of bits used in the pointer.<br>
>> + setPointerAction(<br>
>> + Opcode, TypeIdx, PointerSpecifiedActions.first,<br>
>> + unsupportedForDifferentSizes(<wbr>PointerSpecifiedActions.<wbr>second));<br>
>> + }<br>
>> +<br>
>> + // 3. Handle vector types<br>
>> + SizeAndActionsVec ElementSizesSeen;<br>
>> + for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {<br>
>> + std::sort(<wbr>VectorSpecifiedActions.second.<wbr>begin(),<br>
>> + VectorSpecifiedActions.second.<wbr>end());<br>
>> + const uint16_t ElementSize = VectorSpecifiedActions.first;<br>
>> + ElementSizesSeen.push_back({<wbr>ElementSize, Legal});<br>
>> + checkPartialSizeAndActionsVect<wbr>or(VectorSpecifiedActions.<wbr>second);<br>
>> + // For vector types, we assume that the best way to adapt the number<br>
>> + // of elements is to the next larger number of elements type for which<br>
>> + // the vector type is legal, unless there is no such type. In that case,<br>
>> + // legalize towards a vector type with a smaller number of elements.<br>
>> + SizeAndActionsVec NumElementsActions;<br>
>> + for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {<br>
>> + assert(BitsizeAndAction.first % ElementSize == 0);<br>
>> + const uint16_t NumElements = BitsizeAndAction.first / ElementSize;<br>
>> + NumElementsActions.push_back({<wbr>NumElements, BitsizeAndAction.second});<br>
>> + }<br>
>> + setVectorNumElementAction(<br>
>> + Opcode, TypeIdx, ElementSize,<br>
>> + moreToWiderTypesAndLessToWides<wbr>t(NumElementsActions));<br>
>> }<br>
>> + std::sort(ElementSizesSeen.<wbr>begin(), ElementSizesSeen.end());<br>
>> + SizeChangeStrategy VectorElementSizeChangeStrateg<wbr>y =<br>
>> + &unsupportedForDifferentSizes;<br>
>> + if (TypeIdx < VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx].size() &&<br>
>> + VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx][TypeIdx] != nullptr)<br>
>> + VectorElementSizeChangeStrateg<wbr>y =<br>
>> + VectorElementSizeChangeStrateg<wbr>ies[OpcodeIdx][TypeIdx];<br>
>> + setScalarInVectorAction(<br>
>> + Opcode, TypeIdx, VectorElementSizeChangeStrateg<wbr>y(ElementSizesSeen));<br>
>> }<br>
>> }<br>
>><br>
>> @@ -90,69 +174,24 @@ LegalizerInfo::getAction(const InstrAspe<br>
>> Aspect.Opcode == TargetOpcode::G_UNMERGE_<wbr>VALUES)<br>
>> return std::make_pair(Legal, Aspect.Type);<br>
>><br>
>> - LLT Ty = Aspect.Type;<br>
>> - LegalizeAction Action = findInActions(Aspect);<br>
>> - // LegalizerHelper is not able to handle non-power-of-2 types right now, so do<br>
>> - // not try to legalize them unless they are marked as Legal or Custom.<br>
>> - // FIXME: This is a temporary hack until the general non-power-of-2<br>
>> - // legalization works.<br>
>> - if (!isPowerOf2_64(Ty.<wbr>getSizeInBits()) &&<br>
>> - !(Action == Legal || Action == Custom))<br>
>> - return std::make_pair(Unsupported, LLT());<br>
>> -<br>
>> - if (Action != NotFound)<br>
>> - return findLegalAction(Aspect, Action);<br>
>> -<br>
>> - unsigned Opcode = Aspect.Opcode;<br>
>> - if (!Ty.isVector()) {<br>
>> - auto DefaultAction = DefaultActions.find(Aspect.<wbr>Opcode);<br>
>> - if (DefaultAction != DefaultActions.end() && DefaultAction->second == Legal)<br>
>> - return std::make_pair(Legal, Ty);<br>
>> -<br>
>> - if (DefaultAction != DefaultActions.end() && DefaultAction->second == Lower)<br>
>> - return std::make_pair(Lower, Ty);<br>
>> -<br>
>> - if (DefaultAction == DefaultActions.end() ||<br>
>> - DefaultAction->second != NarrowScalar)<br>
>> - return std::make_pair(Unsupported, LLT());<br>
>> - return findLegalAction(Aspect, NarrowScalar);<br>
>> - }<br>
>> -<br>
>> - LLT EltTy = Ty.getElementType();<br>
>> - int NumElts = Ty.getNumElements();<br>
>> -<br>
>> - auto ScalarAction = ScalarInVectorActions.find(<wbr>std::make_pair(Opcode, EltTy));<br>
>> - if (ScalarAction != ScalarInVectorActions.end() &&<br>
>> - ScalarAction->second != Legal)<br>
>> - return findLegalAction(Aspect, ScalarAction->second);<br>
>> -<br>
>> - // The element type is legal in principle, but the number of elements is<br>
>> - // wrong.<br>
>> - auto MaxLegalElts = MaxLegalVectorElts.lookup(std:<wbr>:make_pair(Opcode, EltTy));<br>
>> - if (MaxLegalElts > NumElts)<br>
>> - return findLegalAction(Aspect, MoreElements);<br>
>> -<br>
>> - if (MaxLegalElts == 0) {<br>
>> - // Scalarize if there's no legal vector type, which is just a special case<br>
>> - // of FewerElements.<br>
>> - return std::make_pair(FewerElements, EltTy);<br>
>> - }<br>
>> -<br>
>> - return findLegalAction(Aspect, FewerElements);<br>
>> + if (Aspect.Type.isScalar() || Aspect.Type.isPointer())<br>
>> + return findScalarLegalAction(Aspect);<br>
>> + assert(Aspect.Type.isVector())<wbr>;<br>
>> + return findVectorLegalAction(Aspect);<br>
>> }<br>
>><br>
>> std::tuple<LegalizerInfo::<wbr>LegalizeAction, unsigned, LLT><br>
>> LegalizerInfo::getAction(const MachineInstr &MI,<br>
>> const MachineRegisterInfo &MRI) const {<br>
>> SmallBitVector SeenTypes(8);<br>
>> - const MCInstrDesc &MCID = MI.getDesc();<br>
>> - const MCOperandInfo *OpInfo = MCID.OpInfo;<br>
>> - for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) {<br>
>> + const MCOperandInfo *OpInfo = MI.getDesc().OpInfo;<br>
>> + // FIXME: probably we'll need to cache the results here somehow?<br>
>> + for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) {<br>
>> if (!OpInfo[i].isGenericType())<br>
>> continue;<br>
>><br>
>> - // We don't want to repeatedly check the same operand index, that<br>
>> - // could get expensive.<br>
>> + // We must only record actions once for each TypeIdx; otherwise we'd<br>
>> + // try to legalize operands multiple times down the line.<br>
>> unsigned TypeIdx = OpInfo[i].getGenericTypeIndex(<wbr>);<br>
>> if (SeenTypes[TypeIdx])<br>
>> continue;<br>
>> @@ -172,38 +211,164 @@ bool LegalizerInfo::isLegal(const Machin<br>
>> return std::get<0>(getAction(MI, MRI)) == Legal;<br>
>> }<br>
>><br>
>> -Optional<LLT> LegalizerInfo::findLegalType(<wbr>const InstrAspect &Aspect,<br>
>> - LegalizeAction Action) const {<br>
>> - switch(Action) {<br>
>> - default:<br>
>> - llvm_unreachable("Cannot find legal type");<br>
>> +bool LegalizerInfo::legalizeCustom(<wbr>MachineInstr &MI, MachineRegisterInfo &MRI,<br>
>> + MachineIRBuilder &MIRBuilder) const {<br>
>> + return false;<br>
>> +}<br>
>> +<br>
>> +LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +LegalizerInfo::<wbr>increaseToLargerTypesAndDecrea<wbr>seToLargest(<br>
>> + const SizeAndActionsVec &v, LegalizeAction IncreaseAction,<br>
>> + LegalizeAction DecreaseAction) {<br>
>> + SizeAndActionsVec result;<br>
>> + unsigned LargestSizeSoFar = 0;<br>
>> + if (v.size() >= 1 && v[0].first != 1)<br>
>> + result.push_back({1, IncreaseAction});<br>
>> + for (size_t i = 0; i < v.size(); ++i) {<br>
>> + result.push_back(v[i]);<br>
>> + LargestSizeSoFar = v[i].first;<br>
>> + if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {<br>
>> + result.push_back({<wbr>LargestSizeSoFar + 1, IncreaseAction});<br>
>> + LargestSizeSoFar = v[i].first + 1;<br>
>> + }<br>
>> + }<br>
>> + result.push_back({<wbr>LargestSizeSoFar + 1, DecreaseAction});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +LegalizerInfo::<wbr>decreaseToSmallerTypesAndIncre<wbr>aseToSmallest(<br>
>> + const SizeAndActionsVec &v, LegalizeAction DecreaseAction,<br>
>> + LegalizeAction IncreaseAction) {<br>
>> + SizeAndActionsVec result;<br>
>> + if (v.size() == 0 || v[0].first != 1)<br>
>> + result.push_back({1, IncreaseAction});<br>
>> + for (size_t i = 0; i < v.size(); ++i) {<br>
>> + result.push_back(v[i]);<br>
>> + if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {<br>
>> + result.push_back({v[i].first + 1, DecreaseAction});<br>
>> + }<br>
>> + }<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +LegalizerInfo::SizeAndAction<br>
>> +LegalizerInfo::findAction(<wbr>const SizeAndActionsVec &Vec, const uint32_t Size) {<br>
>> + assert(Size >= 1);<br>
>> + // Find the last element in Vec that has a bitsize equal to or smaller than<br>
>> + // the requested bit size.<br>
>> + // That is the element just before the first element that is bigger than Size.<br>
>> + auto VecIt = std::upper_bound(<br>
>> + Vec.begin(), Vec.end(), Size,<br>
>> + [](const uint32_t Size, const SizeAndAction lhs) -> bool {<br>
>> + return Size < lhs.first;<br>
>> + });<br>
>> + assert(VecIt != Vec.begin() && "Does Vec not start with size 1?");<br>
>> + --VecIt;<br>
>> + int VecIdx = VecIt - Vec.begin();<br>
>> +<br>
>> + LegalizeAction Action = Vec[VecIdx].second;<br>
>> + switch (Action) {<br>
>> case Legal:<br>
>> case Lower:<br>
>> case Libcall:<br>
>> case Custom:<br>
>> - return Aspect.Type;<br>
>> + return {Size, Action};<br>
>> + case FewerElements:<br>
>> + // FIXME: is this special case still needed and correct?<br>
>> + // Special case for scalarization:<br>
>> + if (Vec == SizeAndActionsVec({{1, FewerElements}}))<br>
>> + return {1, FewerElements};<br>
>> case NarrowScalar: {<br>
>> - return findLegalizableSize(<br>
>> - Aspect, [&](LLT Ty) -> LLT { return Ty.halfScalarSize(); });<br>
>> - }<br>
>> - case WidenScalar: {<br>
>> - return findLegalizableSize(Aspect, [&](LLT Ty) -> LLT {<br>
>> - return Ty.getSizeInBits() < 8 ? LLT::scalar(8) : Ty.doubleScalarSize();<br>
>> - });<br>
>> - }<br>
>> - case FewerElements: {<br>
>> - return findLegalizableSize(<br>
>> - Aspect, [&](LLT Ty) -> LLT { return Ty.halfElements(); });<br>
>> + // The following needs to be a loop, as for now, we do allow needing to<br>
>> + // go over "Unsupported" bit sizes before finding a legalizable bit size.<br>
>> + // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,<br>
>> + // we need to iterate over s9, and then to s32 to return (s32, Legal).<br>
>> + // If we want to get rid of the below loop, we should have stronger asserts<br>
>> + // when building the SizeAndActionsVecs, probably not allowing<br>
>> + // "Unsupported" unless at the ends of the vector.<br>
>> + for (int i = VecIdx - 1; i >= 0; --i)<br>
>> + if (!<wbr>needsLegalizingToDifferentSize<wbr>(Vec[i].second) &&<br>
>> + Vec[i].second != Unsupported)<br>
>> + return {Vec[i].first, Action};<br>
>> + llvm_unreachable("");<br>
>> }<br>
>> + case WidenScalar:<br>
>> case MoreElements: {<br>
>> - return findLegalizableSize(<br>
>> - Aspect, [&](LLT Ty) -> LLT { return Ty.doubleElements(); });<br>
>> + // See above, the following needs to be a loop, at least for now.<br>
>> + for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)<br>
>> + if (!<wbr>needsLegalizingToDifferentSize<wbr>(Vec[i].second) &&<br>
>> + Vec[i].second != Unsupported)<br>
>> + return {Vec[i].first, Action};<br>
>> + llvm_unreachable("");<br>
>> }<br>
>> + case Unsupported:<br>
>> + return {Size, Unsupported};<br>
>> + case NotFound:<br>
>> + llvm_unreachable("NotFound");<br>
>> }<br>
>> }<br>
>><br>
>> -bool LegalizerInfo::legalizeCustom(<wbr>MachineInstr &MI,<br>
>> - MachineRegisterInfo &MRI,<br>
>> - MachineIRBuilder &MIRBuilder) const {<br>
>> - return false;<br>
>> +std::pair<LegalizerInfo::<wbr>LegalizeAction, LLT><br>
>> +LegalizerInfo::<wbr>findScalarLegalAction(const InstrAspect &Aspect) const {<br>
>> + assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());<br>
>> + if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)<br>
>> + return {NotFound, LLT()};<br>
>> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;<br>
>> + if (Aspect.Type.isPointer() &&<br>
>> + AddrSpace2PointerActions[<wbr>OpcodeIdx].find(Aspect.Type.<wbr>getAddressSpace()) ==<br>
>> + AddrSpace2PointerActions[<wbr>OpcodeIdx].end()) {<br>
>> + return {NotFound, LLT()};<br>
>> + }<br>
>> + const SmallVector<SizeAndActionsVec, 1> &Actions =<br>
>> + Aspect.Type.isPointer()<br>
>> + ? AddrSpace2PointerActions[<wbr>OpcodeIdx]<br>
>> + .find(Aspect.Type.<wbr>getAddressSpace())<br>
>> + ->second<br>
>> + : ScalarActions[OpcodeIdx];<br>
>> + if (Aspect.Idx >= Actions.size())<br>
>> + return {NotFound, LLT()};<br>
>> + const SizeAndActionsVec &Vec = Actions[Aspect.Idx];<br>
>> + // FIXME: speed up this search, e.g. by using a results cache for repeated<br>
>> + // queries?<br>
>> + auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());<br>
>> + return {SizeAndAction.second,<br>
>> + Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.<wbr>first)<br>
>> + : LLT::pointer(Aspect.Type.<wbr>getAddressSpace(),<br>
>> + SizeAndAction.first)};<br>
>> +}<br>
>> +<br>
>> +std::pair<LegalizerInfo::<wbr>LegalizeAction, LLT><br>
>> +LegalizerInfo::<wbr>findVectorLegalAction(const InstrAspect &Aspect) const {<br>
>> + assert(Aspect.Type.isVector())<wbr>;<br>
>> + // First legalize the vector element size, then legalize the number of<br>
>> + // lanes in the vector.<br>
>> + if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)<br>
>> + return {NotFound, Aspect.Type};<br>
>> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;<br>
>> + const unsigned TypeIdx = Aspect.Idx;<br>
>> + if (TypeIdx >= ScalarInVectorActions[<wbr>OpcodeIdx].size())<br>
>> + return {NotFound, Aspect.Type};<br>
>> + const SizeAndActionsVec &ElemSizeVec =<br>
>> + ScalarInVectorActions[<wbr>OpcodeIdx][TypeIdx];<br>
>> +<br>
>> + LLT IntermediateType;<br>
>> + auto ElementSizeAndAction =<br>
>> + findAction(ElemSizeVec, Aspect.Type.<wbr>getScalarSizeInBits());<br>
>> + IntermediateType =<br>
>> + LLT::vector(Aspect.Type.<wbr>getNumElements(), ElementSizeAndAction.first);<br>
>> + if (ElementSizeAndAction.second != Legal)<br>
>> + return {ElementSizeAndAction.second, IntermediateType};<br>
>> +<br>
>> + auto i = NumElements2Actions[OpcodeIdx]<wbr>.find(<br>
>> + IntermediateType.<wbr>getScalarSizeInBits());<br>
>> + if (i == NumElements2Actions[OpcodeIdx]<wbr>.end()) {<br>
>> + return {NotFound, IntermediateType};<br>
>> + }<br>
>> + const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];<br>
>> + auto NumElementsAndAction =<br>
>> + findAction(NumElementsVec, IntermediateType.<wbr>getNumElements());<br>
>> + return {NumElementsAndAction.second,<br>
>> + LLT::vector(<wbr>NumElementsAndAction.first,<br>
>> + IntermediateType.<wbr>getScalarSizeInBits())};<br>
>> }<br>
>><br>
>> Modified: llvm/trunk/lib/Support/<wbr>LowLevelType.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/LowLevelType.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Support/LowLevelType.cpp?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/Support/<wbr>LowLevelType.cpp (original)<br>
>> +++ llvm/trunk/lib/Support/<wbr>LowLevelType.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -43,7 +43,7 @@ void LLT::print(raw_ostream &OS) const {<br>
>> assert(isScalar() && "unexpected type");<br>
>> OS << "s" << getScalarSizeInBits();<br>
>> } else<br>
>> - llvm_unreachable("trying to print an invalid type");<br>
>> + OS << "LLT_invalid";<br>
>> }<br>
>><br>
>> const constexpr LLT::BitFieldInfo LLT::ScalarSizeFieldInfo;<br>
>><br>
>> Modified: llvm/trunk/lib/Target/AArch64/<wbr>AArch64LegalizerInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/Target/<wbr>AArch64/AArch64LegalizerInfo.<wbr>cpp?rev=317560&r1=317559&r2=<wbr>317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/Target/AArch64/<wbr>AArch64LegalizerInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Target/AArch64/<wbr>AArch64LegalizerInfo.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -23,6 +23,110 @@<br>
>><br>
>> using namespace llvm;<br>
>><br>
>> +/// FIXME: The following static functions are SizeChangeStrategy functions<br>
>> +/// that are meant to temporarily mimic the behaviour of the old legalization<br>
>> +/// based on doubling/halving non-legal types as closely as possible. This is<br>
>> +/// not entirly possible as only legalizing the types that are exactly a power<br>
>> +/// of 2 times the size of the legal types would require specifying all those<br>
>> +/// sizes explicitly.<br>
>> +/// In practice, not specifying those isn't a problem, and the below functions<br>
>> +/// should disappear quickly as we add support for legalizing non-power-of-2<br>
>> +/// sized types further.<br>
>> +static void<br>
>> +<wbr>addAndInterleaveWithUnsupporte<wbr>d(LegalizerInfo::<wbr>SizeAndActionsVec &result,<br>
>> + const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + for (unsigned i = 0; i < v.size(); ++i) {<br>
>> + result.push_back(v[i]);<br>
>> + if (i + 1 < v[i].first && i + 1 < v.size() &&<br>
>> + v[i + 1].first != v[i].first + 1)<br>
>> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});<br>
>> + }<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_narrow_128_ToLargest(<wbr>const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 2);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {{1, LegalizerInfo::WidenScalar},<br>
>> + {2, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + assert(Largest + 1 < 128);<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + result.push_back({128, LegalizerInfo::NarrowScalar});<br>
>> + result.push_back({129, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_16(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 17);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {{1, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar},<br>
>> + {17, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_8(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 9);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_8_16(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 17);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_8_16_narrowToLargest(<wbr>const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 17);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::NarrowScalar});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_8_16_32(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 33);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported},<br>
>> + {32, LegalizerInfo::WidenScalar}, {33, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> AArch64LegalizerInfo::<wbr>AArch64LegalizerInfo() {<br>
>> using namespace TargetOpcode;<br>
>> const LLT p0 = LLT::pointer(0, 64);<br>
>> @@ -42,8 +146,7 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> for (auto Ty : {s16, s32, s64, p0})<br>
>> setAction({G_PHI, Ty}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8})<br>
>> - setAction({G_PHI, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_PHI, 0, widen_1_8);<br>
>><br>
>> for (auto Ty : { s32, s64 })<br>
>> setAction({G_BSWAP, Ty}, Legal);<br>
>> @@ -54,15 +157,15 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> for (auto Ty : {s32, s64, v2s32, v4s32, v2s64})<br>
>> setAction({BinOp, Ty}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({BinOp, Ty}, WidenScalar);<br>
>> + if (BinOp != G_ADD)<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(BinOp, 0,<br>
>> + widen_1_8_16_narrowToLargest);<br>
>> }<br>
>><br>
>> setAction({G_GEP, p0}, Legal);<br>
>> setAction({G_GEP, 1, s64}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16, s32})<br>
>> - setAction({G_GEP, 1, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_GEP, 1, widen_1_8_16_32);<br>
>><br>
>> setAction({G_PTR_MASK, p0}, Legal);<br>
>><br>
>> @@ -70,16 +173,17 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> for (auto Ty : {s32, s64})<br>
>> setAction({BinOp, Ty}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({BinOp, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(BinOp, 0, widen_1_8_16);<br>
>> }<br>
>><br>
>> for (unsigned BinOp : {G_SREM, G_UREM})<br>
>> for (auto Ty : { s1, s8, s16, s32, s64 })<br>
>> setAction({BinOp, Ty}, Lower);<br>
>><br>
>> - for (unsigned Op : {G_SMULO, G_UMULO})<br>
>> - setAction({Op, s64}, Lower);<br>
>> + for (unsigned Op : {G_SMULO, G_UMULO}) {<br>
>> + setAction({Op, 0, s64}, Lower);<br>
>> + setAction({Op, 1, s1}, Legal);<br>
>> + }<br>
>><br>
>> for (unsigned Op : {G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULH, G_UMULH}) {<br>
>> for (auto Ty : { s32, s64 })<br>
>> @@ -101,8 +205,9 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> setAction({G_INSERT, Ty}, Legal);<br>
>> setAction({G_INSERT, 1, Ty}, Legal);<br>
>> }<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_INSERT, 0,<br>
>> + widen_1_8_16_narrowToLargest);<br>
>> for (auto Ty : {s1, s8, s16}) {<br>
>> - setAction({G_INSERT, Ty}, WidenScalar);<br>
>> setAction({G_INSERT, 1, Ty}, Legal);<br>
>> // FIXME: Can't widen the sources because that violates the constraints on<br>
>> // G_INSERT (It seems entirely reasonable that inputs shouldn't overlap).<br>
>> @@ -118,7 +223,8 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> for (auto Ty : {s8, s16, s32, s64, p0, v2s32})<br>
>> setAction({MemOp, Ty}, Legal);<br>
>><br>
>> - setAction({MemOp, s1}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(MemOp, 0,<br>
>> + widen_1_narrow_128_ToLargest);<br>
>><br>
>> // And everything's fine in addrspace 0.<br>
>> setAction({MemOp, 1, p0}, Legal);<br>
>> @@ -132,20 +238,16 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>><br>
>> setAction({G_CONSTANT, p0}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({TargetOpcode::G_<wbr>CONSTANT, Ty}, WidenScalar);<br>
>> -<br>
>> - setAction({TargetOpcode::G_<wbr>FCONSTANT, s16}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_CONSTANT, 0, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_FCONSTANT, 0, widen_16);<br>
>><br>
>> setAction({G_ICMP, 1, s32}, Legal);<br>
>> setAction({G_ICMP, 1, s64}, Legal);<br>
>> setAction({G_ICMP, 1, p0}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16}) {<br>
>> - setAction({G_ICMP, Ty}, WidenScalar);<br>
>> - setAction({G_FCMP, Ty}, WidenScalar);<br>
>> - setAction({G_ICMP, 1, Ty}, WidenScalar);<br>
>> - }<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_ICMP, 0, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_FCMP, 0, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_ICMP, 1, widen_1_8_16);<br>
>><br>
>> setAction({G_ICMP, s32}, Legal);<br>
>> setAction({G_FCMP, s32}, Legal);<br>
>> @@ -159,12 +261,6 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> setAction({G_ANYEXT, Ty}, Legal);<br>
>> }<br>
>><br>
>> - for (auto Ty : { s1, s8, s16, s32 }) {<br>
>> - setAction({G_ZEXT, 1, Ty}, Legal);<br>
>> - setAction({G_SEXT, 1, Ty}, Legal);<br>
>> - setAction({G_ANYEXT, 1, Ty}, Legal);<br>
>> - }<br>
>> -<br>
>> // FP conversions<br>
>> for (auto Ty : { s16, s32 }) {<br>
>> setAction({G_FPTRUNC, Ty}, Legal);<br>
>> @@ -176,12 +272,6 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> setAction({G_FPEXT, Ty}, Legal);<br>
>> }<br>
>><br>
>> - for (auto Ty : { s1, s8, s16, s32 })<br>
>> - setAction({G_TRUNC, Ty}, Legal);<br>
>> -<br>
>> - for (auto Ty : { s8, s16, s32, s64 })<br>
>> - setAction({G_TRUNC, 1, Ty}, Legal);<br>
>> -<br>
>> // Conversions<br>
>> for (auto Ty : { s32, s64 }) {<br>
>> setAction({G_FPTOSI, 0, Ty}, Legal);<br>
>> @@ -189,12 +279,10 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> setAction({G_SITOFP, 1, Ty}, Legal);<br>
>> setAction({G_UITOFP, 1, Ty}, Legal);<br>
>> }<br>
>> - for (auto Ty : { s1, s8, s16 }) {<br>
>> - setAction({G_FPTOSI, 0, Ty}, WidenScalar);<br>
>> - setAction({G_FPTOUI, 0, Ty}, WidenScalar);<br>
>> - setAction({G_SITOFP, 1, Ty}, WidenScalar);<br>
>> - setAction({G_UITOFP, 1, Ty}, WidenScalar);<br>
>> - }<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_FPTOSI, 0, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_FPTOUI, 0, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_SITOFP, 1, widen_1_8_16);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_UITOFP, 1, widen_1_8_16);<br>
>><br>
>> for (auto Ty : { s32, s64 }) {<br>
>> setAction({G_FPTOSI, 1, Ty}, Legal);<br>
>> @@ -209,8 +297,7 @@ AArch64LegalizerInfo::<wbr>AArch64LegalizerIn<br>
>> setAction({G_BRINDIRECT, p0}, Legal);<br>
>><br>
>> // Select<br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({G_SELECT, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_SELECT, 0, widen_1_8_16);<br>
>><br>
>> for (auto Ty : {s32, s64, p0})<br>
>> setAction({G_SELECT, Ty}, Legal);<br>
>><br>
>> Modified: llvm/trunk/lib/Target/ARM/<wbr>ARMLegalizerInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMLegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/Target/<wbr>ARM/ARMLegalizerInfo.cpp?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/Target/ARM/<wbr>ARMLegalizerInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Target/ARM/<wbr>ARMLegalizerInfo.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -24,6 +24,54 @@<br>
>><br>
>> using namespace llvm;<br>
>><br>
>> +/// FIXME: The following static functions are SizeChangeStrategy functions<br>
>> +/// that are meant to temporarily mimic the behaviour of the old legalization<br>
>> +/// based on doubling/halving non-legal types as closely as possible. This is<br>
>> +/// not entirly possible as only legalizing the types that are exactly a power<br>
>> +/// of 2 times the size of the legal types would require specifying all those<br>
>> +/// sizes explicitly.<br>
>> +/// In practice, not specifying those isn't a problem, and the below functions<br>
>> +/// should disappear quickly as we add support for legalizing non-power-of-2<br>
>> +/// sized types further.<br>
>> +static void<br>
>> +<wbr>addAndInterleaveWithUnsupporte<wbr>d(LegalizerInfo::<wbr>SizeAndActionsVec &result,<br>
>> + const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + for (unsigned i = 0; i < v.size(); ++i) {<br>
>> + result.push_back(v[i]);<br>
>> + if (i + 1 < v[i].first && i + 1 < v.size() &&<br>
>> + v[i + 1].first != v[i].first + 1)<br>
>> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});<br>
>> + }<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_8_16(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 17);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1_8_16(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 17);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {<br>
>> + {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},<br>
>> + {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},<br>
>> + {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> static bool AEABI(const ARMSubtarget &ST) {<br>
>> return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();<br>
>> }<br>
>> @@ -49,14 +97,15 @@ ARMLegalizerInfo::<wbr>ARMLegalizerInfo(const<br>
>> }<br>
>><br>
>> for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {<br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({Op, Ty}, WidenScalar);<br>
>> + if (Op != G_ADD)<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + Op, 0, widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> setAction({Op, s32}, Legal);<br>
>> }<br>
>><br>
>> for (unsigned Op : {G_SDIV, G_UDIV}) {<br>
>> - for (auto Ty : {s8, s16})<br>
>> - setAction({Op, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(Op, 0,<br>
>> + widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> if (ST.hasDivideInARMMode())<br>
>> setAction({Op, s32}, Legal);<br>
>> else<br>
>> @@ -64,8 +113,7 @@ ARMLegalizerInfo::<wbr>ARMLegalizerInfo(const<br>
>> }<br>
>><br>
>> for (unsigned Op : {G_SREM, G_UREM}) {<br>
>> - for (auto Ty : {s8, s16})<br>
>> - setAction({Op, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(Op, 0, widen_8_16);<br>
>> if (ST.hasDivideInARMMode())<br>
>> setAction({Op, s32}, Lower);<br>
>> else if (AEABI(ST))<br>
>> @@ -74,10 +122,8 @@ ARMLegalizerInfo::<wbr>ARMLegalizerInfo(const<br>
>> setAction({Op, s32}, Libcall);<br>
>> }<br>
>><br>
>> - for (unsigned Op : {G_SEXT, G_ZEXT}) {<br>
>> + for (unsigned Op : {G_SEXT, G_ZEXT, G_ANYEXT}) {<br>
>> setAction({Op, s32}, Legal);<br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({Op, 1, Ty}, Legal);<br>
>> }<br>
>><br>
>> for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})<br>
>> @@ -93,12 +139,11 @@ ARMLegalizerInfo::<wbr>ARMLegalizerInfo(const<br>
>> setAction({G_BRCOND, s1}, Legal);<br>
>><br>
>> setAction({G_CONSTANT, s32}, Legal);<br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({G_CONSTANT, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_CONSTANT, 0, widen_1_8_16);<br>
>><br>
>> setAction({G_ICMP, s1}, Legal);<br>
>> - for (auto Ty : {s8, s16})<br>
>> - setAction({G_ICMP, 1, Ty}, WidenScalar);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_ICMP, 1,<br>
>> + widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> for (auto Ty : {s32, p0})<br>
>> setAction({G_ICMP, 1, Ty}, Legal);<br>
>><br>
>><br>
>> Modified: llvm/trunk/lib/Target/X86/<wbr>X86LegalizerInfo.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/Target/<wbr>X86/X86LegalizerInfo.cpp?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/lib/Target/X86/<wbr>X86LegalizerInfo.cpp (original)<br>
>> +++ llvm/trunk/lib/Target/X86/<wbr>X86LegalizerInfo.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -22,6 +22,38 @@<br>
>> using namespace llvm;<br>
>> using namespace TargetOpcode;<br>
>><br>
>> +/// FIXME: The following static functions are SizeChangeStrategy functions<br>
>> +/// that are meant to temporarily mimic the behaviour of the old legalization<br>
>> +/// based on doubling/halving non-legal types as closely as possible. This is<br>
>> +/// not entirly possible as only legalizing the types that are exactly a power<br>
>> +/// of 2 times the size of the legal types would require specifying all those<br>
>> +/// sizes explicitly.<br>
>> +/// In practice, not specifying those isn't a problem, and the below functions<br>
>> +/// should disappear quickly as we add support for legalizing non-power-of-2<br>
>> +/// sized types further.<br>
>> +static void<br>
>> +<wbr>addAndInterleaveWithUnsupporte<wbr>d(LegalizerInfo::<wbr>SizeAndActionsVec &result,<br>
>> + const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + for (unsigned i = 0; i < v.size(); ++i) {<br>
>> + result.push_back(v[i]);<br>
>> + if (i + 1 < v[i].first && i + 1 < v.size() &&<br>
>> + v[i + 1].first != v[i].first + 1)<br>
>> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});<br>
>> + }<br>
>> +}<br>
>> +<br>
>> +static LegalizerInfo::<wbr>SizeAndActionsVec<br>
>> +widen_1(const LegalizerInfo::<wbr>SizeAndActionsVec &v) {<br>
>> + assert(v.size() >= 1);<br>
>> + assert(v[0].first > 1);<br>
>> + LegalizerInfo::<wbr>SizeAndActionsVec result = {{1, LegalizerInfo::WidenScalar},<br>
>> + {2, LegalizerInfo::Unsupported}};<br>
>> + addAndInterleaveWithUnsupporte<wbr>d(result, v);<br>
>> + auto Largest = result.back().first;<br>
>> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});<br>
>> + return result;<br>
>> +}<br>
>> +<br>
>> X86LegalizerInfo::<wbr>X86LegalizerInfo(const X86Subtarget &STI,<br>
>> const X86TargetMachine &TM)<br>
>> : Subtarget(STI), TM(TM) {<br>
>> @@ -37,6 +69,17 @@ X86LegalizerInfo::<wbr>X86LegalizerInfo(const<br>
>> setLegalizerInfoAVX512DQ();<br>
>> setLegalizerInfoAVX512BW();<br>
>><br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(G_PHI, 0, widen_1);<br>
>> + for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(BinOp, 0, widen_1);<br>
>> + for (unsigned MemOp : {G_LOAD, G_STORE})<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(MemOp, 0,<br>
>> + narrowToSmallerAndWidenToSmall<wbr>est);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + G_GEP, 1, widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> + setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + G_CONSTANT, 0, widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> +<br>
>> computeTables();<br>
>> }<br>
>><br>
>> @@ -47,7 +90,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> const LLT s8 = LLT::scalar(8);<br>
>> const LLT s16 = LLT::scalar(16);<br>
>> const LLT s32 = LLT::scalar(32);<br>
>> - const LLT s64 = LLT::scalar(64);<br>
>><br>
>> for (auto Ty : {p0, s1, s8, s16, s32})<br>
>> setAction({G_IMPLICIT_DEF, Ty}, Legal);<br>
>> @@ -55,15 +97,10 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> for (auto Ty : {s8, s16, s32, p0})<br>
>> setAction({G_PHI, Ty}, Legal);<br>
>><br>
>> - setAction({G_PHI, s1}, WidenScalar);<br>
>> -<br>
>> - for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {<br>
>> + for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})<br>
>> for (auto Ty : {s8, s16, s32})<br>
>> setAction({BinOp, Ty}, Legal);<br>
>><br>
>> - setAction({BinOp, s1}, WidenScalar);<br>
>> - }<br>
>> -<br>
>> for (unsigned Op : {G_UADDE}) {<br>
>> setAction({Op, s32}, Legal);<br>
>> setAction({Op, 1, s1}, Legal);<br>
>> @@ -73,7 +110,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> for (auto Ty : {s8, s16, s32, p0})<br>
>> setAction({MemOp, Ty}, Legal);<br>
>><br>
>> - setAction({MemOp, s1}, WidenScalar);<br>
>> // And everything's fine in addrspace 0.<br>
>> setAction({MemOp, 1, p0}, Legal);<br>
>> }<br>
>> @@ -85,9 +121,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> setAction({G_GEP, p0}, Legal);<br>
>> setAction({G_GEP, 1, s32}, Legal);<br>
>><br>
>> - for (auto Ty : {s1, s8, s16})<br>
>> - setAction({G_GEP, 1, Ty}, WidenScalar);<br>
>> -<br>
>> // Control-flow<br>
>> setAction({G_BRCOND, s1}, Legal);<br>
>><br>
>> @@ -95,9 +128,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> for (auto Ty : {s8, s16, s32, p0})<br>
>> setAction({TargetOpcode::G_<wbr>CONSTANT, Ty}, Legal);<br>
>><br>
>> - setAction({TargetOpcode::G_<wbr>CONSTANT, s1}, WidenScalar);<br>
>> - setAction({TargetOpcode::G_<wbr>CONSTANT, s64}, NarrowScalar);<br>
>> -<br>
>> // Extensions<br>
>> for (auto Ty : {s8, s16, s32}) {<br>
>> setAction({G_ZEXT, Ty}, Legal);<br>
>> @@ -105,12 +135,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo3<br>
>> setAction({G_ANYEXT, Ty}, Legal);<br>
>> }<br>
>><br>
>> - for (auto Ty : {s1, s8, s16}) {<br>
>> - setAction({G_ZEXT, 1, Ty}, Legal);<br>
>> - setAction({G_SEXT, 1, Ty}, Legal);<br>
>> - setAction({G_ANYEXT, 1, Ty}, Legal);<br>
>> - }<br>
>> -<br>
>> // Comparison<br>
>> setAction({G_ICMP, s1}, Legal);<br>
>><br>
>> @@ -123,7 +147,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo6<br>
>> if (!Subtarget.is64Bit())<br>
>> return;<br>
>><br>
>> - const LLT s32 = LLT::scalar(32);<br>
>> const LLT s64 = LLT::scalar(64);<br>
>><br>
>> setAction({G_IMPLICIT_DEF, s64}, Legal);<br>
>> @@ -145,7 +168,6 @@ void X86LegalizerInfo::<wbr>setLegalizerInfo6<br>
>> // Extensions<br>
>> for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {<br>
>> setAction({extOp, s64}, Legal);<br>
>> - setAction({extOp, 1, s32}, Legal);<br>
>> }<br>
>><br>
>> // Comparison<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/arm64-<wbr>fallback.ll<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/AArch64/GlobalISel/<wbr>arm64-fallback.ll?rev=317560&<wbr>r1=317559&r2=317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/arm64-<wbr>fallback.ll (original)<br>
>> +++ llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/arm64-<wbr>fallback.ll Tue Nov 7 02:34:34 2017<br>
>> @@ -167,3 +167,70 @@ end:<br>
>> %vec = load <2 x i16*>, <2 x i16*>* undef<br>
>> br label %block<br>
>> }<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR-G_<wbr>IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(s96) = G_INSERT %vreg2, %vreg0, 0; (in function: nonpow2_insertvalue_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg2<def>(s96) = G_IMPLICIT_DEF; (in function: nonpow2_insertvalue_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_insertvalue_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_insertvalue_narrowing:<br>
>> +%struct96 = type { float, float, float }<br>
>> +define void @nonpow2_insertvalue_<wbr>narrowing(float %a) {<br>
>> + %dummy = insertvalue %struct96 undef, float %a, 0<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR remark: <unknown>:0:0: unable to legalize instruction: %vreg3<def>(s96) = G_ADD %vreg2, %vreg2; (in function: nonpow2_add_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_add_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_add_narrowing:<br>
>> +define void @nonpow2_add_narrowing() {<br>
>> + %a = add i128 undef, undef<br>
>> + %b = trunc i128 %a to i96<br>
>> + %dummy = add i96 %b, %b<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg3<def>(s96) = G_OR %vreg2, %vreg2; (in function: nonpow2_or_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_or_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_or_narrowing:<br>
>> +define void @nonpow2_or_narrowing() {<br>
>> + %a = add i128 undef, undef<br>
>> + %b = trunc i128 %a to i96<br>
>> + %dummy = or i96 %b, %b<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg0<def>(s96) = G_LOAD %vreg1; mem:LD12[undef](align=16) (in function: nonpow2_load_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_load_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_load_narrowing:<br>
>> +define void @nonpow2_load_narrowing() {<br>
>> + %dummy = load i96, i96* undef<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %vreg3, %vreg0; mem:ST12[%c](align=16) (in function: nonpow2_store_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_store_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_store_narrowing:<br>
>> +define void @nonpow2_store_narrowing(i96* %c) {<br>
>> + %a = add i128 undef, undef<br>
>> + %b = trunc i128 %a to i96<br>
>> + store i96 %b, i96* %c<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg0<def>(s96) = G_CONSTANT 0; (in function: nonpow2_constant_narrowing<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_constant_narrowing<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_constant_narrowing:<br>
>> +define void @nonpow2_constant_narrowing() {<br>
>> + store i96 0, i96* undef<br>
>> + ret void<br>
>> +}<br>
>> +<br>
>> +; Currently can't handle vector lengths that aren't an exact multiple of<br>
>> +; natively supported vector lengths. Test that the fall-back works for those.<br>
>> +; FALLBACK-WITH-REPORT-ERR-G_<wbr>IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(<7 x s64>) = G_ADD %vreg0, %vreg0; (in function: nonpow2_vector_add_<wbr>fewerelements<br>
>> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg0<def>(<7 x s64>) = G_IMPLICIT_DEF; (in function: nonpow2_vector_add_<wbr>fewerelements<br>
>> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_vector_add_<wbr>fewerelements<br>
>> +; FALLBACK-WITH-REPORT-OUT-<wbr>LABEL: nonpow2_vector_add_<wbr>fewerelements:<br>
>> +define void @nonpow2_vector_add_<wbr>fewerelements() {<br>
>> + %dummy = add <7 x i64> undef, undef<br>
>> + ret void<br>
>> +}<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>add.mir<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/AArch64/GlobalISel/<wbr>legalize-add.mir?rev=317560&<wbr>r1=317559&r2=317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>add.mir (original)<br>
>> +++ llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>add.mir Tue Nov 7 02:34:34 2017<br>
>> @@ -8,6 +8,10 @@<br>
>> entry:<br>
>> ret void<br>
>> }<br>
>> + define void @test_scalar_add_big_nonpow2() {<br>
>> + entry:<br>
>> + ret void<br>
>> + }<br>
>> define void @test_scalar_add_small() {<br>
>> entry:<br>
>> ret void<br>
>> @@ -16,6 +20,10 @@<br>
>> entry:<br>
>> ret void<br>
>> }<br>
>> + define void @test_vector_add_nonpow2() {<br>
>> + entry:<br>
>> + ret void<br>
>> + }<br>
>> ...<br>
>><br>
>> ---<br>
>> @@ -58,6 +66,49 @@ body: |<br>
>> ...<br>
>><br>
>> ---<br>
>> +name: test_scalar_add_big_nonpow2<br>
>> +registers:<br>
>> + - { id: 0, class: _ }<br>
>> + - { id: 1, class: _ }<br>
>> + - { id: 2, class: _ }<br>
>> + - { id: 3, class: _ }<br>
>> + - { id: 4, class: _ }<br>
>> + - { id: 5, class: _ }<br>
>> + - { id: 6, class: _ }<br>
>> + - { id: 7, class: _ }<br>
>> + - { id: 8, class: _ }<br>
>> + - { id: 9, class: _ }<br>
>> +body: |<br>
>> + bb.0.entry:<br>
>> + liveins: %x0, %x1, %x2, %x3<br>
>> + ; CHECK-LABEL: name: test_scalar_add_big_nonpow2<br>
>> + ; CHECK-NOT: G_MERGE_VALUES<br>
>> + ; CHECK-NOT: G_UNMERGE_VALUES<br>
>> + ; CHECK-DAG: [[CARRY0_32:%[0-9]+]]:_(s32) = G_CONSTANT i32 0<br>
>> + ; CHECK-DAG: [[CARRY0:%[0-9]+]]:_(s1) = G_TRUNC [[CARRY0_32]]<br>
>> + ; CHECK: [[RES_LO:%[0-9]+]]:_(s64), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE %0, %1, [[CARRY0]]<br>
>> + ; CHECK: [[RES_MI:%[0-9]+]]:_(s64), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE %1, %2, [[CARRY1]]<br>
>> + ; CHECK: [[RES_HI:%[0-9]+]]:_(s64), {{%.*}}(s1) = G_UADDE %2, %3, [[CARRY2]]<br>
>> + ; CHECK-NOT: G_MERGE_VALUES<br>
>> + ; CHECK-NOT: G_UNMERGE_VALUES<br>
>> + ; CHECK: %x0 = COPY [[RES_LO]]<br>
>> + ; CHECK: %x1 = COPY [[RES_MI]]<br>
>> + ; CHECK: %x2 = COPY [[RES_HI]]<br>
>> +<br>
>> + %0(s64) = COPY %x0<br>
>> + %1(s64) = COPY %x1<br>
>> + %2(s64) = COPY %x2<br>
>> + %3(s64) = COPY %x3<br>
>> + %4(s192) = G_MERGE_VALUES %0, %1, %2<br>
>> + %5(s192) = G_MERGE_VALUES %1, %2, %3<br>
>> + %6(s192) = G_ADD %4, %5<br>
>> + %7(s64), %8(s64), %9(s64) = G_UNMERGE_VALUES %6<br>
>> + %x0 = COPY %7<br>
>> + %x1 = COPY %8<br>
>> + %x2 = COPY %9<br>
>> +...<br>
>> +<br>
>> +---<br>
>> name: test_scalar_add_small<br>
>> registers:<br>
>> - { id: 0, class: _ }<br>
>> @@ -124,3 +175,43 @@ body: |<br>
>> %q0 = COPY %7<br>
>> %q1 = COPY %8<br>
>> ...<br>
>> +---<br>
>> +name: test_vector_add_nonpow2<br>
>> +registers:<br>
>> + - { id: 0, class: _ }<br>
>> + - { id: 1, class: _ }<br>
>> + - { id: 2, class: _ }<br>
>> + - { id: 3, class: _ }<br>
>> + - { id: 4, class: _ }<br>
>> + - { id: 5, class: _ }<br>
>> + - { id: 6, class: _ }<br>
>> + - { id: 7, class: _ }<br>
>> + - { id: 8, class: _ }<br>
>> + - { id: 9, class: _ }<br>
>> +body: |<br>
>> + bb.0.entry:<br>
>> + liveins: %q0, %q1, %q2, %q3<br>
>> + ; CHECK-LABEL: name: test_vector_add_nonpow2<br>
>> + ; CHECK-NOT: G_EXTRACT<br>
>> + ; CHECK-NOT: G_SEQUENCE<br>
>> + ; CHECK: [[RES_LO:%[0-9]+]]:_(<2 x s64>) = G_ADD %0, %1<br>
>> + ; CHECK: [[RES_MI:%[0-9]+]]:_(<2 x s64>) = G_ADD %1, %2<br>
>> + ; CHECK: [[RES_HI:%[0-9]+]]:_(<2 x s64>) = G_ADD %2, %3<br>
>> + ; CHECK-NOT: G_EXTRACT<br>
>> + ; CHECK-NOT: G_SEQUENCE<br>
>> + ; CHECK: %q0 = COPY [[RES_LO]]<br>
>> + ; CHECK: %q1 = COPY [[RES_MI]]<br>
>> + ; CHECK: %q2 = COPY [[RES_HI]]<br>
>> +<br>
>> + %0(<2 x s64>) = COPY %q0<br>
>> + %1(<2 x s64>) = COPY %q1<br>
>> + %2(<2 x s64>) = COPY %q2<br>
>> + %3(<2 x s64>) = COPY %q3<br>
>> + %4(<6 x s64>) = G_MERGE_VALUES %0, %1, %2<br>
>> + %5(<6 x s64>) = G_MERGE_VALUES %1, %2, %3<br>
>> + %6(<6 x s64>) = G_ADD %4, %5<br>
>> + %7(<2 x s64>), %8(<2 x s64>), %9(<2 x s64>) = G_UNMERGE_VALUES %6<br>
>> + %q0 = COPY %7<br>
>> + %q1 = COPY %8<br>
>> + %q2 = COPY %9<br>
>> +...<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>inserts.mir<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/AArch64/GlobalISel/<wbr>legalize-inserts.mir?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>inserts.mir (original)<br>
>> +++ llvm/trunk/test/CodeGen/<wbr>AArch64/GlobalISel/legalize-<wbr>inserts.mir Tue Nov 7 02:34:34 2017<br>
>> @@ -9,6 +9,7 @@<br>
>> define void @test_inserts_4() { ret void }<br>
>> define void @test_inserts_5() { ret void }<br>
>> define void @test_inserts_6() { ret void }<br>
>> + define void @test_inserts_nonpow2() { ret void }<br>
>> ...<br>
>><br>
>> ---<br>
>> @@ -141,3 +142,21 @@ body: |<br>
>> %4:_(s128) = G_INSERT %3, %2, 32<br>
>> RET_ReallyLR<br>
>> ...<br>
>> +<br>
>> +---<br>
>> +name: test_inserts_nonpow2<br>
>> +body: |<br>
>> + bb.0:<br>
>> + liveins: %x0, %x1, %x2<br>
>> +<br>
>> +<br>
>> + ; CHECK-LABEL: name: test_inserts_nonpow2<br>
>> + ; CHECK: %5:_(s192) = G_MERGE_VALUES %3(s64), %1(s64), %2(s64)<br>
>> + %0:_(s64) = COPY %x0<br>
>> + %1:_(s64) = COPY %x1<br>
>> + %2:_(s64) = COPY %x2<br>
>> + %3:_(s64) = COPY %x3<br>
>> + %4:_(s192) = G_MERGE_VALUES %0, %1, %2<br>
>> + %5:_(s192) = G_INSERT %4, %3, 0<br>
>> + RET_ReallyLR<br>
>> +...<br>
>><br>
>> Modified: llvm/trunk/test/CodeGen/ARM/<wbr>GlobalISel/arm-instruction-<wbr>select.mir<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>CodeGen/ARM/GlobalISel/arm-<wbr>instruction-select.mir?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/test/CodeGen/ARM/<wbr>GlobalISel/arm-instruction-<wbr>select.mir (original)<br>
>> +++ llvm/trunk/test/CodeGen/ARM/<wbr>GlobalISel/arm-instruction-<wbr>select.mir Tue Nov 7 02:34:34 2017<br>
>> @@ -970,9 +970,10 @@ registers:<br>
>> - { id: 1, class: gprb }<br>
>> - { id: 2, class: gprb }<br>
>> - { id: 3, class: gprb }<br>
>> + - { id: 4, class: gprb }<br>
>> body: |<br>
>> bb.0:<br>
>> - liveins: %r0, %r1<br>
>> + liveins: %r0, %r1, %r2<br>
>><br>
>> %0(p0) = COPY %r0<br>
>> ; CHECK: [[VREGX:%[0-9]+]]:gpr = COPY %r0<br>
>> @@ -980,14 +981,17 @@ body: |<br>
>> %1(p0) = COPY %r1<br>
>> ; CHECK: [[VREGY:%[0-9]+]]:gpr = COPY %r1<br>
>><br>
>> - %2(s1) = G_TRUNC %1(p0)<br>
>> - ; CHECK: [[VREGC:%[0-9]+]]:gpr = COPY [[VREGY]]<br>
>> + %2(s32) = COPY %r2<br>
>> + ; CHECK: [[VREGC:%[0-9]+]]:gpr = COPY %r2<br>
>><br>
>> - %3(p0) = G_SELECT %2(s1), %0, %1<br>
>> - ; CHECK: CMPri [[VREGC]], 0, 14, _, implicit-def %cpsr<br>
>> + %3(s1) = G_TRUNC %2(s32)<br>
>> + ; CHECK: [[VREGD:%[0-9]+]]:gpr = COPY [[VREGC]]<br>
>> +<br>
>> + %4(p0) = G_SELECT %3(s1), %0, %1<br>
>> + ; CHECK: CMPri [[VREGD]], 0, 14, _, implicit-def %cpsr<br>
>> ; CHECK: [[RES:%[0-9]+]]:gpr = MOVCCr [[VREGX]], [[VREGY]], 0, %cpsr<br>
>><br>
>> - %r0 = COPY %3(p0)<br>
>> + %r0 = COPY %4(p0)<br>
>> ; CHECK: %r0 = COPY [[RES]]<br>
>><br>
>> BX_RET 14, _, implicit %r0<br>
>><br>
>> Modified: llvm/trunk/unittests/CodeGen/<wbr>GlobalISel/LegalizerInfoTest.<wbr>cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/unittests/<wbr>CodeGen/GlobalISel/<wbr>LegalizerInfoTest.cpp?rev=<wbr>317560&r1=317559&r2=317560&<wbr>view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/unittests/CodeGen/<wbr>GlobalISel/LegalizerInfoTest.<wbr>cpp (original)<br>
>> +++ llvm/trunk/unittests/CodeGen/<wbr>GlobalISel/LegalizerInfoTest.<wbr>cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -49,66 +49,91 @@ TEST(LegalizerInfoTest, ScalarRISC) {<br>
>> using namespace TargetOpcode;<br>
>> LegalizerInfo L;<br>
>> // Typical RISCy set of operations based on AArch64.<br>
>> - L.setAction({G_ADD, LLT::scalar(8)}, LegalizerInfo::WidenScalar);<br>
>> - L.setAction({G_ADD, LLT::scalar(16)}, LegalizerInfo::WidenScalar);<br>
>> - L.setAction({G_ADD, LLT::scalar(32)}, LegalizerInfo::Legal);<br>
>> - L.setAction({G_ADD, LLT::scalar(64)}, LegalizerInfo::Legal);<br>
>> + for (auto Op : {G_ADD, G_SUB}) {<br>
>> + for (unsigned Size : {32, 64})<br>
>> + L.setAction({Op, 0, LLT::scalar(Size)}, LegalizerInfo::Legal);<br>
>> + L.<wbr>setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + Op, 0, LegalizerInfo::<wbr>widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> + }<br>
>> +<br>
>> L.computeTables();<br>
>><br>
>> - // Check we infer the correct types and actually do what we're told.<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(8)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(16)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(32)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>Legal, LLT::scalar(32)));<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(64)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>Legal, LLT::scalar(64)));<br>
>> -<br>
>> - // Make sure the default for over-sized types applies.<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(128)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>NarrowScalar, LLT::scalar(64)));<br>
>> + for (auto &opcode : {G_ADD, G_SUB}) {<br>
>> + // Check we infer the correct types and actually do what we're told.<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(8)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(16)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(32)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>Legal, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(64)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>Legal, LLT::scalar(64)));<br>
>> +<br>
>> + // Make sure the default for over-sized types applies.<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(128)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>NarrowScalar, LLT::scalar(64)));<br>
>> + // Make sure we also handle unusual sizes<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(1)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(31)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(33)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(64)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(63)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(64)));<br>
>> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(65)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>NarrowScalar, LLT::scalar(64)));<br>
>> + }<br>
>> }<br>
>><br>
>> TEST(LegalizerInfoTest, VectorRISC) {<br>
>> using namespace TargetOpcode;<br>
>> LegalizerInfo L;<br>
>> // Typical RISCy set of operations based on ARM.<br>
>> - L.setScalarInVectorAction(G_<wbr>ADD, LLT::scalar(8), LegalizerInfo::Legal);<br>
>> - L.setScalarInVectorAction(G_<wbr>ADD, LLT::scalar(16), LegalizerInfo::Legal);<br>
>> - L.setScalarInVectorAction(G_<wbr>ADD, LLT::scalar(32), LegalizerInfo::Legal);<br>
>> -<br>
>> L.setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal);<br>
>> L.setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal);<br>
>> L.setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal);<br>
>> L.setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal);<br>
>> L.setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal);<br>
>> L.setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal);<br>
>> +<br>
>> + L.<wbr>setLegalizeVectorElementToDiff<wbr>erentSizeStrategy(<br>
>> + G_ADD, 0, LegalizerInfo::<wbr>widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> +<br>
>> + L.setAction({G_ADD, 0, LLT::scalar(32)}, LegalizerInfo::Legal);<br>
>> +<br>
>> L.computeTables();<br>
>><br>
>> // Check we infer the correct types and actually do what we're told for some<br>
>> // simple cases.<br>
>> - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>MoreElements, LLT::vector(8, 8)));<br>
>> ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 8)}),<br>
>> std::make_pair(LegalizerInfo::<wbr>Legal, LLT::vector(8, 8)));<br>
>> - ASSERT_EQ(<br>
>> - L.getAction({G_ADD, LLT::vector(8, 32)}),<br>
>> - std::make_pair(LegalizerInfo::<wbr>FewerElements, LLT::vector(4, 32)));<br>
>> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 7)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::vector(8, 8)));<br>
>> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>MoreElements, LLT::vector(8, 8)));<br>
>> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 32)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>FewerElements, LLT::vector(4, 32)));<br>
>> + // Check a few non-power-of-2 sizes:<br>
>> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 3)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::vector(3, 8)));<br>
>> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 8)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>MoreElements, LLT::vector(8, 8)));<br>
>> }<br>
>><br>
>> TEST(LegalizerInfoTest, MultipleTypes) {<br>
>> using namespace TargetOpcode;<br>
>> LegalizerInfo L;<br>
>> LLT p0 = LLT::pointer(0, 64);<br>
>> - LLT s32 = LLT::scalar(32);<br>
>> LLT s64 = LLT::scalar(64);<br>
>><br>
>> // Typical RISCy set of operations based on AArch64.<br>
>> L.setAction({G_PTRTOINT, 0, s64}, LegalizerInfo::Legal);<br>
>> L.setAction({G_PTRTOINT, 1, p0}, LegalizerInfo::Legal);<br>
>><br>
>> - L.setAction({G_PTRTOINT, 0, s32}, LegalizerInfo::WidenScalar);<br>
>> + L.<wbr>setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + G_PTRTOINT, 0, LegalizerInfo::<wbr>widenToLargerTypesAndNarrowToL<wbr>argest);<br>
>> +<br>
>> L.computeTables();<br>
>><br>
>> // Check we infer the correct types and actually do what we're told.<br>
>> @@ -116,16 +141,21 @@ TEST(LegalizerInfoTest, MultipleTypes) {<br>
>> std::make_pair(LegalizerInfo::<wbr>Legal, s64));<br>
>> ASSERT_EQ(L.getAction({G_<wbr>PTRTOINT, 1, p0}),<br>
>> std::make_pair(LegalizerInfo::<wbr>Legal, p0));<br>
>> + // Make sure we also handle unusual sizes<br>
>> + ASSERT_EQ(L.getAction({G_<wbr>PTRTOINT, 0, LLT::scalar(65)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>NarrowScalar, s64));<br>
>> + ASSERT_EQ(L.getAction({G_<wbr>PTRTOINT, 1, LLT::pointer(0, 32)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>Unsupported, LLT::pointer(0, 32)));<br>
>> }<br>
>><br>
>> TEST(LegalizerInfoTest, MultipleSteps) {<br>
>> using namespace TargetOpcode;<br>
>> LegalizerInfo L;<br>
>> - LLT s16 = LLT::scalar(16);<br>
>> LLT s32 = LLT::scalar(32);<br>
>> LLT s64 = LLT::scalar(64);<br>
>><br>
>> - L.setAction({G_UREM, 0, s16}, LegalizerInfo::WidenScalar);<br>
>> + L.<wbr>setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + G_UREM, 0, LegalizerInfo::<wbr>widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> L.setAction({G_UREM, 0, s32}, LegalizerInfo::Lower);<br>
>> L.setAction({G_UREM, 0, s64}, LegalizerInfo::Lower);<br>
>><br>
>> @@ -136,4 +166,33 @@ TEST(LegalizerInfoTest, MultipleSteps) {<br>
>> ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(32)}),<br>
>> std::make_pair(LegalizerInfo::<wbr>Lower, LLT::scalar(32)));<br>
>> }<br>
>> +<br>
>> +TEST(LegalizerInfoTest, SizeChangeStrategy) {<br>
>> + using namespace TargetOpcode;<br>
>> + LegalizerInfo L;<br>
>> + for (unsigned Size : {1, 8, 16, 32})<br>
>> + L.setAction({G_UREM, 0, LLT::scalar(Size)}, LegalizerInfo::Legal);<br>
>> +<br>
>> + L.<wbr>setLegalizeScalarToDifferentSi<wbr>zeStrategy(<br>
>> + G_UREM, 0, LegalizerInfo::<wbr>widenToLargerTypesUnsupportedO<wbr>therwise);<br>
>> + L.computeTables();<br>
>> +<br>
>> + // Check we infer the correct types and actually do what we're told.<br>
>> + for (unsigned Size : {1, 8, 16, 32}) {<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(Size)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>Legal, LLT::scalar(Size)));<br>
>> + }<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(2)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(8)));<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(7)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(8)));<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(9)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(16)));<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(17)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(31)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>WidenScalar, LLT::scalar(32)));<br>
>> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(33)}),<br>
>> + std::make_pair(LegalizerInfo::<wbr>Unsupported, LLT::scalar(33)));<br>
>> +}<br>
>> }<br>
>><br>
>> Modified: llvm/trunk/unittests/CodeGen/<wbr>LowLevelTypeTest.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/LowLevelTypeTest.cpp?rev=317560&r1=317559&r2=317560&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/unittests/<wbr>CodeGen/LowLevelTypeTest.cpp?<wbr>rev=317560&r1=317559&r2=<wbr>317560&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- llvm/trunk/unittests/CodeGen/<wbr>LowLevelTypeTest.cpp (original)<br>
>> +++ llvm/trunk/unittests/CodeGen/<wbr>LowLevelTypeTest.cpp Tue Nov 7 02:34:34 2017<br>
>> @@ -36,36 +36,22 @@ TEST(LowLevelTypeTest, Scalar) {<br>
>><br>
>> for (unsigned S : {1U, 17U, 32U, 64U, 0xfffffU}) {<br>
>> const LLT Ty = LLT::scalar(S);<br>
>> - const LLT HalfTy = (S % 2) == 0 ? Ty.halfScalarSize() : Ty;<br>
>> - const LLT DoubleTy = Ty.doubleScalarSize();<br>
>><br>
>> // Test kind.<br>
>> - for (const LLT TestTy : {Ty, HalfTy, DoubleTy}) {<br>
>> - ASSERT_TRUE(TestTy.isValid());<br>
>> - ASSERT_TRUE(TestTy.isScalar())<wbr>;<br>
>> -<br>
>> - ASSERT_FALSE(TestTy.isPointer(<wbr>));<br>
>> - ASSERT_FALSE(TestTy.isVector()<wbr>);<br>
>> - }<br>
>> + ASSERT_TRUE(Ty.isValid());<br>
>> + ASSERT_TRUE(Ty.isScalar());<br>
>> +<br>
>> + ASSERT_FALSE(Ty.isPointer());<br>
>> + ASSERT_FALSE(Ty.isVector());<br>
>><br>
>> // Test sizes.<br>
>> EXPECT_EQ(S, Ty.getSizeInBits());<br>
>> EXPECT_EQ(S, Ty.getScalarSizeInBits());<br>
>><br>
>> - EXPECT_EQ(S*2, DoubleTy.getSizeInBits());<br>
>> - EXPECT_EQ(S*2, DoubleTy.getScalarSizeInBits()<wbr>);<br>
>> -<br>
>> - if ((S % 2) == 0) {<br>
>> - EXPECT_EQ(S/2, HalfTy.getSizeInBits());<br>
>> - EXPECT_EQ(S/2, HalfTy.getScalarSizeInBits());<br>
>> - }<br>
>> -<br>
>> // Test equality operators.<br>
>> EXPECT_TRUE(Ty == Ty);<br>
>> EXPECT_FALSE(Ty != Ty);<br>
>><br>
>> - EXPECT_NE(Ty, DoubleTy);<br>
>> -<br>
>> // Test Type->LLT conversion.<br>
>> Type *IRTy = IntegerType::get(C, S);<br>
>> EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));<br>
>> @@ -90,62 +76,18 @@ TEST(LowLevelTypeTest, Vector) {<br>
>> // Test getElementType().<br>
>> EXPECT_EQ(STy, VTy.getElementType());<br>
>><br>
>> - const LLT HalfSzTy = ((S % 2) == 0) ? VTy.halfScalarSize() : VTy;<br>
>> - const LLT DoubleSzTy = VTy.doubleScalarSize();<br>
>> -<br>
>> - // halfElements requires an even number of elements.<br>
>> - const LLT HalfEltIfEvenTy = ((Elts % 2) == 0) ? VTy.halfElements() : VTy;<br>
>> - const LLT DoubleEltTy = VTy.doubleElements();<br>
>> -<br>
>> // Test kind.<br>
>> - for (const LLT TestTy : {VTy, HalfSzTy, DoubleSzTy, DoubleEltTy}) {<br>
>> - ASSERT_TRUE(TestTy.isValid());<br>
>> - ASSERT_TRUE(TestTy.isVector())<wbr>;<br>
>> -<br>
>> - ASSERT_FALSE(TestTy.isScalar()<wbr>);<br>
>> - ASSERT_FALSE(TestTy.isPointer(<wbr>));<br>
>> - }<br>
>> -<br>
>> - // Test halving elements to a scalar.<br>
>> - {<br>
>> - ASSERT_TRUE(HalfEltIfEvenTy.<wbr>isValid());<br>
>> - ASSERT_FALSE(HalfEltIfEvenTy.<wbr>isPointer());<br>
>> - if (Elts > 2) {<br>
>> - ASSERT_TRUE(HalfEltIfEvenTy.<wbr>isVector());<br>
>> - } else {<br>
>> - ASSERT_FALSE(HalfEltIfEvenTy.<wbr>isVector());<br>
>> - EXPECT_EQ(STy, HalfEltIfEvenTy);<br>
>> - }<br>
>> - }<br>
>> + ASSERT_TRUE(VTy.isValid());<br>
>> + ASSERT_TRUE(VTy.isVector());<br>
>><br>
>> + ASSERT_FALSE(VTy.isScalar());<br>
>> + ASSERT_FALSE(VTy.isPointer());<br>
>><br>
>> // Test sizes.<br>
>> EXPECT_EQ(S * Elts, VTy.getSizeInBits());<br>
>> EXPECT_EQ(S, VTy.getScalarSizeInBits());<br>
>> EXPECT_EQ(Elts, VTy.getNumElements());<br>
>><br>
>> - if ((S % 2) == 0) {<br>
>> - EXPECT_EQ((S / 2) * Elts, HalfSzTy.getSizeInBits());<br>
>> - EXPECT_EQ(S / 2, HalfSzTy.getScalarSizeInBits()<wbr>);<br>
>> - EXPECT_EQ(Elts, HalfSzTy.getNumElements());<br>
>> - }<br>
>> -<br>
>> - EXPECT_EQ((S * 2) * Elts, DoubleSzTy.getSizeInBits());<br>
>> - EXPECT_EQ(S * 2, DoubleSzTy.<wbr>getScalarSizeInBits());<br>
>> - EXPECT_EQ(Elts, DoubleSzTy.getNumElements());<br>
>> -<br>
>> - if ((Elts % 2) == 0) {<br>
>> - EXPECT_EQ(S * (Elts / 2), HalfEltIfEvenTy.getSizeInBits(<wbr>));<br>
>> - EXPECT_EQ(S, HalfEltIfEvenTy.<wbr>getScalarSizeInBits());<br>
>> - if (Elts > 2) {<br>
>> - EXPECT_EQ(Elts / 2, HalfEltIfEvenTy.<wbr>getNumElements());<br>
>> - }<br>
>> - }<br>
>> -<br>
>> - EXPECT_EQ(S * (Elts * 2), DoubleEltTy.getSizeInBits());<br>
>> - EXPECT_EQ(S, DoubleEltTy.<wbr>getScalarSizeInBits());<br>
>> - EXPECT_EQ(Elts * 2, DoubleEltTy.getNumElements());<br>
>> -<br>
>> // Test equality operators.<br>
>> EXPECT_TRUE(VTy == VTy);<br>
>> EXPECT_FALSE(VTy != VTy);<br>
>> @@ -153,10 +95,6 @@ TEST(LowLevelTypeTest, Vector) {<br>
>> // Test inequality operators on..<br>
>> // ..different kind.<br>
>> EXPECT_NE(VTy, STy);<br>
>> - // ..different #elts.<br>
>> - EXPECT_NE(VTy, DoubleEltTy);<br>
>> - // ..different scalar size.<br>
>> - EXPECT_NE(VTy, DoubleSzTy);<br>
>><br>
>> // Test Type->LLT conversion.<br>
>> Type *IRSTy = IntegerType::get(C, S);<br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
><br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>