Path: blob/main/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
35267 views
//===- AArch64ExpandImm.h - AArch64 Immediate Expansion -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the AArch64ExpandImm stuff.9//10//===----------------------------------------------------------------------===//1112#include "AArch64.h"13#include "AArch64ExpandImm.h"14#include "MCTargetDesc/AArch64AddressingModes.h"1516using namespace llvm;17using namespace llvm::AArch64_IMM;1819/// Helper function which extracts the specified 16-bit chunk from a20/// 64-bit value.21static uint64_t getChunk(uint64_t Imm, unsigned ChunkIdx) {22assert(ChunkIdx < 4 && "Out of range chunk index specified!");2324return (Imm >> (ChunkIdx * 16)) & 0xFFFF;25}2627/// Check whether the given 16-bit chunk replicated to full 64-bit width28/// can be materialized with an ORR instruction.29static bool canUseOrr(uint64_t Chunk, uint64_t &Encoding) {30Chunk = (Chunk << 48) | (Chunk << 32) | (Chunk << 16) | Chunk;3132return AArch64_AM::processLogicalImmediate(Chunk, 64, Encoding);33}3435/// Check for identical 16-bit chunks within the constant and if so36/// materialize them with a single ORR instruction. The remaining one or two37/// 16-bit chunks will be materialized with MOVK instructions.38///39/// This allows us to materialize constants like |A|B|A|A| or |A|B|C|A| (order40/// of the chunks doesn't matter), assuming |A|A|A|A| can be materialized with41/// an ORR instruction.42static bool tryToreplicateChunks(uint64_t UImm,43SmallVectorImpl<ImmInsnModel> &Insn) {44using CountMap = DenseMap<uint64_t, unsigned>;4546CountMap Counts;4748// Scan the constant and count how often every chunk occurs.49for (unsigned Idx = 0; Idx < 4; ++Idx)50++Counts[getChunk(UImm, Idx)];5152// Traverse the chunks to find one which occurs more than once.53for (const auto &Chunk : Counts) {54const uint64_t ChunkVal = Chunk.first;55const unsigned Count = Chunk.second;5657uint64_t Encoding = 0;5859// We are looking for chunks which have two or three instances and can be60// materialized with an ORR instruction.61if ((Count != 2 && Count != 3) || !canUseOrr(ChunkVal, Encoding))62continue;6364const bool CountThree = Count == 3;6566Insn.push_back({ AArch64::ORRXri, 0, Encoding });6768unsigned ShiftAmt = 0;69uint64_t Imm16 = 0;70// Find the first chunk not materialized with the ORR instruction.71for (; ShiftAmt < 64; ShiftAmt += 16) {72Imm16 = (UImm >> ShiftAmt) & 0xFFFF;7374if (Imm16 != ChunkVal)75break;76}7778// Create the first MOVK instruction.79Insn.push_back({ AArch64::MOVKXi, Imm16,80AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt) });8182// In case we have three instances the whole constant is now materialized83// and we can exit.84if (CountThree)85return true;8687// Find the remaining chunk which needs to be materialized.88for (ShiftAmt += 16; ShiftAmt < 64; ShiftAmt += 16) {89Imm16 = (UImm >> ShiftAmt) & 0xFFFF;9091if (Imm16 != ChunkVal)92break;93}94Insn.push_back({ AArch64::MOVKXi, Imm16,95AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt) });96return true;97}9899return false;100}101102/// Check whether this chunk matches the pattern '1...0...'. This pattern103/// starts a contiguous sequence of ones if we look at the bits from the LSB104/// towards the MSB.105static bool isStartChunk(uint64_t Chunk) {106if (Chunk == 0 || Chunk == std::numeric_limits<uint64_t>::max())107return false;108109return isMask_64(~Chunk);110}111112/// Check whether this chunk matches the pattern '0...1...' This pattern113/// ends a contiguous sequence of ones if we look at the bits from the LSB114/// towards the MSB.115static bool isEndChunk(uint64_t Chunk) {116if (Chunk == 0 || Chunk == std::numeric_limits<uint64_t>::max())117return false;118119return isMask_64(Chunk);120}121122/// Clear or set all bits in the chunk at the given index.123static uint64_t updateImm(uint64_t Imm, unsigned Idx, bool Clear) {124const uint64_t Mask = 0xFFFF;125126if (Clear)127// Clear chunk in the immediate.128Imm &= ~(Mask << (Idx * 16));129else130// Set all bits in the immediate for the particular chunk.131Imm |= Mask << (Idx * 16);132133return Imm;134}135136/// Check whether the constant contains a sequence of contiguous ones,137/// which might be interrupted by one or two chunks. If so, materialize the138/// sequence of contiguous ones with an ORR instruction.139/// Materialize the chunks which are either interrupting the sequence or outside140/// of the sequence with a MOVK instruction.141///142/// Assuming S is a chunk which starts the sequence (1...0...), E is a chunk143/// which ends the sequence (0...1...). Then we are looking for constants which144/// contain at least one S and E chunk.145/// E.g. |E|A|B|S|, |A|E|B|S| or |A|B|E|S|.146///147/// We are also looking for constants like |S|A|B|E| where the contiguous148/// sequence of ones wraps around the MSB into the LSB.149static bool trySequenceOfOnes(uint64_t UImm,150SmallVectorImpl<ImmInsnModel> &Insn) {151const int NotSet = -1;152const uint64_t Mask = 0xFFFF;153154int StartIdx = NotSet;155int EndIdx = NotSet;156// Try to find the chunks which start/end a contiguous sequence of ones.157for (int Idx = 0; Idx < 4; ++Idx) {158int64_t Chunk = getChunk(UImm, Idx);159// Sign extend the 16-bit chunk to 64-bit.160Chunk = (Chunk << 48) >> 48;161162if (isStartChunk(Chunk))163StartIdx = Idx;164else if (isEndChunk(Chunk))165EndIdx = Idx;166}167168// Early exit in case we can't find a start/end chunk.169if (StartIdx == NotSet || EndIdx == NotSet)170return false;171172// Outside of the contiguous sequence of ones everything needs to be zero.173uint64_t Outside = 0;174// Chunks between the start and end chunk need to have all their bits set.175uint64_t Inside = Mask;176177// If our contiguous sequence of ones wraps around from the MSB into the LSB,178// just swap indices and pretend we are materializing a contiguous sequence179// of zeros surrounded by a contiguous sequence of ones.180if (StartIdx > EndIdx) {181std::swap(StartIdx, EndIdx);182std::swap(Outside, Inside);183}184185uint64_t OrrImm = UImm;186int FirstMovkIdx = NotSet;187int SecondMovkIdx = NotSet;188189// Find out which chunks we need to patch up to obtain a contiguous sequence190// of ones.191for (int Idx = 0; Idx < 4; ++Idx) {192const uint64_t Chunk = getChunk(UImm, Idx);193194// Check whether we are looking at a chunk which is not part of the195// contiguous sequence of ones.196if ((Idx < StartIdx || EndIdx < Idx) && Chunk != Outside) {197OrrImm = updateImm(OrrImm, Idx, Outside == 0);198199// Remember the index we need to patch.200if (FirstMovkIdx == NotSet)201FirstMovkIdx = Idx;202else203SecondMovkIdx = Idx;204205// Check whether we are looking a chunk which is part of the contiguous206// sequence of ones.207} else if (Idx > StartIdx && Idx < EndIdx && Chunk != Inside) {208OrrImm = updateImm(OrrImm, Idx, Inside != Mask);209210// Remember the index we need to patch.211if (FirstMovkIdx == NotSet)212FirstMovkIdx = Idx;213else214SecondMovkIdx = Idx;215}216}217assert(FirstMovkIdx != NotSet && "Constant materializable with single ORR!");218219// Create the ORR-immediate instruction.220uint64_t Encoding = 0;221AArch64_AM::processLogicalImmediate(OrrImm, 64, Encoding);222Insn.push_back({ AArch64::ORRXri, 0, Encoding });223224const bool SingleMovk = SecondMovkIdx == NotSet;225Insn.push_back({ AArch64::MOVKXi, getChunk(UImm, FirstMovkIdx),226AArch64_AM::getShifterImm(AArch64_AM::LSL,227FirstMovkIdx * 16) });228229// Early exit in case we only need to emit a single MOVK instruction.230if (SingleMovk)231return true;232233// Create the second MOVK instruction.234Insn.push_back({ AArch64::MOVKXi, getChunk(UImm, SecondMovkIdx),235AArch64_AM::getShifterImm(AArch64_AM::LSL,236SecondMovkIdx * 16) });237238return true;239}240241static uint64_t GetRunOfOnesStartingAt(uint64_t V, uint64_t StartPosition) {242uint64_t NumOnes = llvm::countr_one(V >> StartPosition);243244uint64_t UnshiftedOnes;245if (NumOnes == 64) {246UnshiftedOnes = ~0ULL;247} else {248UnshiftedOnes = (1ULL << NumOnes) - 1;249}250return UnshiftedOnes << StartPosition;251}252253static uint64_t MaximallyReplicateSubImmediate(uint64_t V, uint64_t Subset) {254uint64_t Result = Subset;255256// 64, 32, 16, 8, 4, 2257for (uint64_t i = 0; i < 6; ++i) {258uint64_t Rotation = 1ULL << (6 - i);259uint64_t Closure = Result | llvm::rotl<uint64_t>(Result, Rotation);260if (Closure != (Closure & V)) {261break;262}263Result = Closure;264}265266return Result;267}268269// Find the logical immediate that covers the most bits in RemainingBits,270// allowing for additional bits to be set that were set in OriginalBits.271static uint64_t maximalLogicalImmWithin(uint64_t RemainingBits,272uint64_t OriginalBits) {273// Find the first set bit.274uint32_t Position = llvm::countr_zero(RemainingBits);275276// Get the first run of set bits.277uint64_t FirstRun = GetRunOfOnesStartingAt(OriginalBits, Position);278279// Replicate the run as many times as possible, as long as the bits are set in280// RemainingBits.281uint64_t MaximalImm = MaximallyReplicateSubImmediate(OriginalBits, FirstRun);282283return MaximalImm;284}285286static std::optional<std::pair<uint64_t, uint64_t>>287decomposeIntoOrrOfLogicalImmediates(uint64_t UImm) {288if (UImm == 0 || ~UImm == 0)289return std::nullopt;290291// Make sure we don't have a run of ones split around the rotation boundary.292uint32_t InitialTrailingOnes = llvm::countr_one(UImm);293uint64_t RotatedBits = llvm::rotr<uint64_t>(UImm, InitialTrailingOnes);294295// Find the largest logical immediate that fits within the full immediate.296uint64_t MaximalImm1 = maximalLogicalImmWithin(RotatedBits, RotatedBits);297298// Remove all bits that are set by this mask.299uint64_t RemainingBits = RotatedBits & ~MaximalImm1;300301// Find the largest logical immediate covering the remaining bits, allowing302// for additional bits to be set that were also set in the original immediate.303uint64_t MaximalImm2 = maximalLogicalImmWithin(RemainingBits, RotatedBits);304305// If any bits still haven't been covered, then give up.306if (RemainingBits & ~MaximalImm2)307return std::nullopt;308309// Make sure to un-rotate the immediates.310return std::make_pair(rotl(MaximalImm1, InitialTrailingOnes),311rotl(MaximalImm2, InitialTrailingOnes));312}313314// Attempt to expand an immediate as the ORR of a pair of logical immediates.315static bool tryOrrOfLogicalImmediates(uint64_t UImm,316SmallVectorImpl<ImmInsnModel> &Insn) {317auto MaybeDecomposition = decomposeIntoOrrOfLogicalImmediates(UImm);318if (MaybeDecomposition == std::nullopt)319return false;320uint64_t Imm1 = MaybeDecomposition->first;321uint64_t Imm2 = MaybeDecomposition->second;322323uint64_t Encoding1, Encoding2;324bool Imm1Success = AArch64_AM::processLogicalImmediate(Imm1, 64, Encoding1);325bool Imm2Success = AArch64_AM::processLogicalImmediate(Imm2, 64, Encoding2);326327if (Imm1Success && Imm2Success) {328// Create the ORR-immediate instructions.329Insn.push_back({AArch64::ORRXri, 0, Encoding1});330Insn.push_back({AArch64::ORRXri, 1, Encoding2});331return true;332}333334return false;335}336337// Attempt to expand an immediate as the AND of a pair of logical immediates.338// This is done by applying DeMorgan's law, under which logical immediates339// are closed.340static bool tryAndOfLogicalImmediates(uint64_t UImm,341SmallVectorImpl<ImmInsnModel> &Insn) {342// Apply DeMorgan's law to turn this into an ORR problem.343auto MaybeDecomposition = decomposeIntoOrrOfLogicalImmediates(~UImm);344if (MaybeDecomposition == std::nullopt)345return false;346uint64_t Imm1 = MaybeDecomposition->first;347uint64_t Imm2 = MaybeDecomposition->second;348349uint64_t Encoding1, Encoding2;350bool Imm1Success = AArch64_AM::processLogicalImmediate(~Imm1, 64, Encoding1);351bool Imm2Success = AArch64_AM::processLogicalImmediate(~Imm2, 64, Encoding2);352353if (Imm1Success && Imm2Success) {354// Materialize Imm1, the LHS of the AND355Insn.push_back({AArch64::ORRXri, 0, Encoding1});356// AND Imm1 with Imm2357Insn.push_back({AArch64::ANDXri, 1, Encoding2});358return true;359}360361return false;362}363364// Check whether the constant can be represented by exclusive-or of two 64-bit365// logical immediates. If so, materialize it with an ORR instruction followed366// by an EOR instruction.367//368// This encoding allows all remaining repeated byte patterns, and many repeated369// 16-bit values, to be encoded without needing four instructions. It can also370// represent some irregular bitmasks (although those would mostly only need371// three instructions otherwise).372static bool tryEorOfLogicalImmediates(uint64_t Imm,373SmallVectorImpl<ImmInsnModel> &Insn) {374// Determine the larger repetition size of the two possible logical375// immediates, by finding the repetition size of Imm.376unsigned BigSize = 64;377378do {379BigSize /= 2;380uint64_t Mask = (1ULL << BigSize) - 1;381382if ((Imm & Mask) != ((Imm >> BigSize) & Mask)) {383BigSize *= 2;384break;385}386} while (BigSize > 2);387388uint64_t BigMask = ((uint64_t)-1LL) >> (64 - BigSize);389390// Find the last bit of each run of ones, circularly. For runs which wrap391// around from bit 0 to bit 63, this is the bit before the most-significant392// zero, otherwise it is the least-significant bit in the run of ones.393uint64_t RunStarts = Imm & ~rotl<uint64_t>(Imm, 1);394395// Find the smaller repetition size of the two possible logical immediates by396// counting the number of runs of one-bits within the BigSize-bit value. Both397// sizes may be the same. The EOR may add one or subtract one from the398// power-of-two count that can be represented by a logical immediate, or it399// may be left unchanged.400int RunsPerBigChunk = popcount(RunStarts & BigMask);401402static const int8_t BigToSmallSizeTable[32] = {403-1, -1, 0, 1, 2, 2, -1, 3, 3, 3, -1, -1, -1, -1, -1, 4,4044, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5,405};406407int BigToSmallShift = BigToSmallSizeTable[RunsPerBigChunk];408409// Early-exit if the big chunk couldn't be a power-of-two number of runs410// EORed with another single run.411if (BigToSmallShift == -1)412return false;413414unsigned SmallSize = BigSize >> BigToSmallShift;415416// 64-bit values with a bit set every (1 << index) bits.417static const uint64_t RepeatedOnesTable[] = {4180xffffffffffffffff, 0x5555555555555555, 0x1111111111111111,4190x0101010101010101, 0x0001000100010001, 0x0000000100000001,4200x0000000000000001,421};422423// This RepeatedOnesTable lookup is a faster implementation of the division424// 0xffffffffffffffff / ((1 << SmallSize) - 1), and can be thought of as425// dividing the 64-bit value into fields of width SmallSize, and placing a426// one in the least significant bit of each field.427uint64_t SmallOnes = RepeatedOnesTable[countr_zero(SmallSize)];428429// Now we try to find the number of ones in each of the smaller repetitions,430// by looking at runs of ones in Imm. This can take three attempts, as the431// EOR may have changed the length of the first two runs we find.432433// Rotate a run of ones so we can count the number of trailing set bits.434int Rotation = countr_zero(RunStarts);435uint64_t RotatedImm = rotr<uint64_t>(Imm, Rotation);436for (int Attempt = 0; Attempt < 3; ++Attempt) {437unsigned RunLength = countr_one(RotatedImm);438439// Construct candidate values BigImm and SmallImm, such that if these two440// values are encodable, we have a solution. (SmallImm is constructed to be441// encodable, but this isn't guaranteed when RunLength >= SmallSize)442uint64_t SmallImm =443rotl<uint64_t>((SmallOnes << RunLength) - SmallOnes, Rotation);444uint64_t BigImm = Imm ^ SmallImm;445446uint64_t BigEncoding = 0;447uint64_t SmallEncoding = 0;448if (AArch64_AM::processLogicalImmediate(BigImm, 64, BigEncoding) &&449AArch64_AM::processLogicalImmediate(SmallImm, 64, SmallEncoding)) {450Insn.push_back({AArch64::ORRXri, 0, SmallEncoding});451Insn.push_back({AArch64::EORXri, 1, BigEncoding});452return true;453}454455// Rotate to the next run of ones456Rotation += countr_zero(rotr<uint64_t>(RunStarts, Rotation) & ~1);457RotatedImm = rotr<uint64_t>(Imm, Rotation);458}459460return false;461}462463/// \brief Expand a MOVi32imm or MOVi64imm pseudo instruction to a464/// MOVZ or MOVN of width BitSize followed by up to 3 MOVK instructions.465static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize,466unsigned OneChunks, unsigned ZeroChunks,467SmallVectorImpl<ImmInsnModel> &Insn) {468const unsigned Mask = 0xFFFF;469470// Use a MOVZ or MOVN instruction to set the high bits, followed by one or471// more MOVK instructions to insert additional 16-bit portions into the472// lower bits.473bool isNeg = false;474475// Use MOVN to materialize the high bits if we have more all one chunks476// than all zero chunks.477if (OneChunks > ZeroChunks) {478isNeg = true;479Imm = ~Imm;480}481482unsigned FirstOpc;483if (BitSize == 32) {484Imm &= (1LL << 32) - 1;485FirstOpc = (isNeg ? AArch64::MOVNWi : AArch64::MOVZWi);486} else {487FirstOpc = (isNeg ? AArch64::MOVNXi : AArch64::MOVZXi);488}489unsigned Shift = 0; // LSL amount for high bits with MOVZ/MOVN490unsigned LastShift = 0; // LSL amount for last MOVK491if (Imm != 0) {492unsigned LZ = llvm::countl_zero(Imm);493unsigned TZ = llvm::countr_zero(Imm);494Shift = (TZ / 16) * 16;495LastShift = ((63 - LZ) / 16) * 16;496}497unsigned Imm16 = (Imm >> Shift) & Mask;498499Insn.push_back({ FirstOpc, Imm16,500AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift) });501502if (Shift == LastShift)503return;504505// If a MOVN was used for the high bits of a negative value, flip the rest506// of the bits back for use with MOVK.507if (isNeg)508Imm = ~Imm;509510unsigned Opc = (BitSize == 32 ? AArch64::MOVKWi : AArch64::MOVKXi);511while (Shift < LastShift) {512Shift += 16;513Imm16 = (Imm >> Shift) & Mask;514if (Imm16 == (isNeg ? Mask : 0))515continue; // This 16-bit portion is already set correctly.516517Insn.push_back({ Opc, Imm16,518AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift) });519}520521// Now, we get 16-bit divided Imm. If high and low bits are same in522// 32-bit, there is an opportunity to reduce instruction.523if (Insn.size() > 2 && (Imm >> 32) == (Imm & 0xffffffffULL)) {524for (int Size = Insn.size(); Size > 2; Size--)525Insn.pop_back();526Insn.push_back({AArch64::ORRXrs, 0, 32});527}528}529530/// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more531/// real move-immediate instructions to synthesize the immediate.532void AArch64_IMM::expandMOVImm(uint64_t Imm, unsigned BitSize,533SmallVectorImpl<ImmInsnModel> &Insn) {534const unsigned Mask = 0xFFFF;535536// Scan the immediate and count the number of 16-bit chunks which are either537// all ones or all zeros.538unsigned OneChunks = 0;539unsigned ZeroChunks = 0;540for (unsigned Shift = 0; Shift < BitSize; Shift += 16) {541const unsigned Chunk = (Imm >> Shift) & Mask;542if (Chunk == Mask)543OneChunks++;544else if (Chunk == 0)545ZeroChunks++;546}547548// Prefer MOVZ/MOVN over ORR because of the rules for the "mov" alias.549if ((BitSize / 16) - OneChunks <= 1 || (BitSize / 16) - ZeroChunks <= 1) {550expandMOVImmSimple(Imm, BitSize, OneChunks, ZeroChunks, Insn);551return;552}553554// Try a single ORR.555uint64_t UImm = Imm << (64 - BitSize) >> (64 - BitSize);556uint64_t Encoding;557if (AArch64_AM::processLogicalImmediate(UImm, BitSize, Encoding)) {558unsigned Opc = (BitSize == 32 ? AArch64::ORRWri : AArch64::ORRXri);559Insn.push_back({ Opc, 0, Encoding });560return;561}562563// One to up three instruction sequences.564//565// Prefer MOVZ/MOVN followed by MOVK; it's more readable, and possibly the566// fastest sequence with fast literal generation.567if (OneChunks >= (BitSize / 16) - 2 || ZeroChunks >= (BitSize / 16) - 2) {568expandMOVImmSimple(Imm, BitSize, OneChunks, ZeroChunks, Insn);569return;570}571572assert(BitSize == 64 && "All 32-bit immediates can be expanded with a"573"MOVZ/MOVK pair");574575// Try other two-instruction sequences.576577// 64-bit ORR followed by MOVK.578// We try to construct the ORR immediate in three different ways: either we579// zero out the chunk which will be replaced, we fill the chunk which will580// be replaced with ones, or we take the bit pattern from the other half of581// the 64-bit immediate. This is comprehensive because of the way ORR582// immediates are constructed.583for (unsigned Shift = 0; Shift < BitSize; Shift += 16) {584uint64_t ShiftedMask = (0xFFFFULL << Shift);585uint64_t ZeroChunk = UImm & ~ShiftedMask;586uint64_t OneChunk = UImm | ShiftedMask;587uint64_t RotatedImm = (UImm << 32) | (UImm >> 32);588uint64_t ReplicateChunk = ZeroChunk | (RotatedImm & ShiftedMask);589if (AArch64_AM::processLogicalImmediate(ZeroChunk, BitSize, Encoding) ||590AArch64_AM::processLogicalImmediate(OneChunk, BitSize, Encoding) ||591AArch64_AM::processLogicalImmediate(ReplicateChunk, BitSize,592Encoding)) {593// Create the ORR-immediate instruction.594Insn.push_back({ AArch64::ORRXri, 0, Encoding });595596// Create the MOVK instruction.597const unsigned Imm16 = getChunk(UImm, Shift / 16);598Insn.push_back({ AArch64::MOVKXi, Imm16,599AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift) });600return;601}602}603604// Attempt to use a sequence of two ORR-immediate instructions.605if (tryOrrOfLogicalImmediates(Imm, Insn))606return;607608// Attempt to use a sequence of ORR-immediate followed by AND-immediate.609if (tryAndOfLogicalImmediates(Imm, Insn))610return;611612// Attempt to use a sequence of ORR-immediate followed by EOR-immediate.613if (tryEorOfLogicalImmediates(UImm, Insn))614return;615616// FIXME: Add more two-instruction sequences.617618// Three instruction sequences.619//620// Prefer MOVZ/MOVN followed by two MOVK; it's more readable, and possibly621// the fastest sequence with fast literal generation. (If neither MOVK is622// part of a fast literal generation pair, it could be slower than the623// four-instruction sequence, but we won't worry about that for now.)624if (OneChunks || ZeroChunks) {625expandMOVImmSimple(Imm, BitSize, OneChunks, ZeroChunks, Insn);626return;627}628629// Check for identical 16-bit chunks within the constant and if so materialize630// them with a single ORR instruction. The remaining one or two 16-bit chunks631// will be materialized with MOVK instructions.632if (BitSize == 64 && tryToreplicateChunks(UImm, Insn))633return;634635// Check whether the constant contains a sequence of contiguous ones, which636// might be interrupted by one or two chunks. If so, materialize the sequence637// of contiguous ones with an ORR instruction. Materialize the chunks which638// are either interrupting the sequence or outside of the sequence with a639// MOVK instruction.640if (BitSize == 64 && trySequenceOfOnes(UImm, Insn))641return;642643// We found no possible two or three instruction sequence; use the general644// four-instruction sequence.645expandMOVImmSimple(Imm, BitSize, OneChunks, ZeroChunks, Insn);646}647648649