One of Intel's major pitfalls: The Lost sse2 128bit/64bit displacement command, Ma Hang mh370 ??

Source: Internet
Author: User
Reason

Recently, I was writing some optimizations to string functions, but I was interested in it. However, I encountered a big pitfall when I wanted to implement-bit logical shift.

If you want to investigate the title, the missing sse2 128-bit/64-bit displacement command is more accurate and has been modified.

I don't want to use Ma Hang 370 to get an eye, and I didn't realize it. When I wrote down this title, I did not have the word Ma Hang 370, however, when I wrote it in half, the words Ma Hang 370 suddenly appeared. If you read my article carefully, maybe you should also think about it, where is the 128-bit/64-bit displacement command? Why? Isn't it the same as Malaysia Airlines 370? It's a mysterious and very big mystery ......

 

If you are not familiar with MMX and SSE commands, You can first look at them:

Http://tommesani.com/index.php/simd/44-mmx-shift.html,

This is easy to understand. I started learning MMX and SSE commands from here,
But this is only written to the MMX instruction set. The updated version is later.

 

Logical displacement

We naturally think of the MMX and SSE displacement commands:

Logical left shift: psllw/pslld/psllq, shift packed data left logical (compression logic left shift) logical right shift: psrlw/psrld/psrscsi, shift packed data right logical (compression logic right shift)

As the name suggests, W refers to word, d Refers to DWORD, and Q refers to qword ), psllw implements left shift by word grouping logic,

Pslld shifts left by the grouping logic of DWORD, and psllq shifts left by the grouping logic implemented by qword, all of which seem OK.

Here, the logical left shift is used as an example:

For details about the logic left shift instruction, refer:

Http://moeto.comoj.com/project/intel/instruct32_hh/vc256.htm

Or http://x86.renejeschke.de/html/file_module_x86_id_259.html,

The right shift is similar, so we will not describe it here.

 

The problem arises.

What we need to implement is the logical shift of bits. sse2 contains the pslldq/psrldq command. Here, DQ is the meaning of double qword,

Isn't this exactly the-bit shift we need? No !! Don't be too happy. Let's take a look at Intel's documents:

Pslldq -- packed shift left logical double quadword

Or

Http://moeto.comoj.com/project/intel/instruct32_hh/vc255.htm

As follows:

We can see that, unfortunately, sse2 does not achieve-bit shift by bit. pslldq can only achieve-bit shift by byte, that is, the minimum displacement must be one byte (eight bits ), this is not scientific. What's more scientific is that the displacement can only be an immediate number! Considering that Intel does not actually implement-Bit Data Processing (most SSE commands only implement a maximum of 64-bit Granularity Data Processing, for example, a double-precision floating point number is 64-bit), okay, we recognize it, !! But !! Intel, aren't you mistaken? pslldq only supports imm8 operations. What does imm8 mean? Imm8 refers to the 8-bit immediate number, which means that we can only write dead (constants) in the Assembly and cannot use any registers for displacement. What the fu * k ??

Okay, so do we... You designed the CPU. We can't help you. If pslldq supports reg32 and reg64 register displacement, it will be much more convenient, because we can first use pslldq to shift the byte displacement by enough digits, and then use psllq to shift the remaining amount (this is the latter, why do we need to use this, you will know later), but this method is not feasible now !! This imm8 completely broke my eggs... Psllq can only shift 16 bits at a time for the 128 bit register (break through the slave). This means that if we use this method, we need to use if/jump several times...

 

Big pitfall begins

Well, let's go back to the next step. Since you cannot implement 128-bit shift by bit, we can divide it into two 64-bit shifts to achieve this. It is nothing more than one judgment, if you merge multiple times, although the efficiency is not as high as 128-bit, you have to do this...
Okay, let's get started .... Go !!! Now we have changed to psllq. Run psllq xmm0, 32 or psllq xmm0, ECx (here the ECX value is 32), then? Why is xmm0 0 all zero ?? Ah, what's going on ??

Let's look back at Intel's documents again:

The focus is on the two redlines. When psllq acts on 64-bit registers, we can see that it supports the maximum count = 64-bit displacement (strictly speaking, it is max = 63, this is a habit problem );

However, when psllq acts on a 128-bit register, a strange thing happens. The maximum displacement is Count = 16 bits (15 bits in a strict sense), as shown in.

If I didn't re-read Intel's documents, but did not find any problems during debugging, who could think of moving at most 15 bits ??? Is Intel's head in the door ?? Why ?? On the MMX registers, a maximum of 63-bit displacement can be achieved. Why cannot the SSE register be used? Although we know that MMX registers and SSE registers are different and separate, MMX registers use x87 floating-point registers to implement MMX instructions, however, you have implemented 64-bit displacement in the MMX register. Why can only a maximum of 15 characters be moved in the 128-bit SSE register ?? You said it was hard to implement. I recognized it. I don't know why it was so difficult. We can only recognize it, but you implemented the 128-bit pslldq Command Based on Byte displacement, what is the explanation ?? Originally, as the name implies, pslldq should be able to achieve a 128-bit shift by bit. due to historical reasons, I can understand this problem, however, you have no reason for psllq to act on a 128-bit SSE register, but you can only shift at most 15 bits, right ?? Is this really so difficult ?? Is it really hard ???? It's really so difficult. How do you implement the 128-bit paybyte displacement of pslldq ??

 

Seek answers

With these questions, we asked Mr. Google to search for "128-bit shift" and found that N's friends had encountered this problem, for example:

Looking for SSE 128 bit shift operation for non-immediate shift value

What is SSE [email protected] # $ % good? #2: bit vector operations

 

Finally, Mr. Google told us the best answer, from Intel's forum, here:

Missing instruction in SSE: pslldq with _ bit _ shift amount?

 

Yes, as follows:

First, Intel acknowledges this missing instruction (lost command). We also realize that missing instruction is everywhere, but this is a bit too much.

The above reply to the general idea is: (E is not very good. I am using Google to assist in translation)

 

Hi Geoff,

One of our engineers provided the following responses and made some clarification.

 

This problem is correct. for SIMD (single-instruction multi-data stream), bit displacement is more difficult to implement than byte displacement in the current Instruction Set (refer to the SSE register ).

Of 128 bits ). Unfortunately, this is not a small change, implementing such a bit-based displacement command. Here there are more changes than simply adapting to the shift in the byte immediately

Distance-the actual hardware completion by bit displacement is a restricted problem.

If you have a use case about why this operation is useful, as the application will benefit from this operation, this is what we are interested in hearing. In general, we try

Design new commands to meet specific requirements, rather than simply providing support for "missing instuctions. From the actual situation, there are many such "missing instuctions"

-- The more interesting problem is that it is necessary to deal with the problems caused by "missing instuctions" in actual applications.

 

Blogger's point of view:

It is difficult to implement the 128-bit shift by bit, but I can understand that psllq can only shift up to 15 bits for SSE 12bit registers ......

In sse2, where are you at the 128bit/64bit displacement? Why 15 instead? Dear mh370, where are you? Why choose a flight to China? Why ??

 

Solution

There are many solutions. As mentioned earlier, if you want to shift the Count bit left, first use pslldq to shift the x 8 bit, which is a pure 128-bit displacement, then use psllq to shift the remaining y = (count-x * 8) bits. Here, Y is smaller than 16. However, because pslldq can only execute imm8 immediate count, you must first determine the Count value by if/jump, and execute pslldq xmm0, 32; or pslldq xmm0, 16; or pslldq xmm0, respectively, 8; pslldq xmm0, 4; pslldq xmm0, 2; then, execute psllq to shift the remaining y bits. Here, pslldq xmm0 and 32 may be replaced by other SSE shuffle commands, but they are the same. The biggest problem is that if you first determine and then execute the corresponding commands, this method is not efficient.

Let's look for some better methods:

Since we cannot implement 64-bit displacement in SSE, but it is possible in MMX registers, but we need to implement it in SSE registers, then we can first transfer the data from the SSE register to the MMX register, and then merge the data into the SSE register. Although this process is a bit cumbersome, it is still a lot more efficient than the first method above, and there is a key point. In many cases, we need to make this shift when it is close to the final output result, at this time, you don't have to merge the data back to the SSE register. You can directly use the value of the MMX register as the output. This is a little faster.

There is still no solution, so should I think about it again, or do you think about it? Some netizens posted vpslldq instructions for avx version, but they also only support imm8 instant count, and not all CPUs support avx. The blogger's own CPU does not support it.

(Because the blogger is half asleep and shut down the article written by the computer, I will take a break and complete the article when I have time)

 

Postscript

The problem we have encountered is a metaphor: We have three roads ahead, one is the road, the other is the road, the other is the unknown road, we think the road (pslldq) is the fastest, so I chose to leave the road first, and found that it was impossible to go directly. Instead, I chose psllq to go through the road. The result showed that there was a trap, which made us unable to reach the destination, it can only reach 1/4; then let's look back at the road. The road can actually pass, but it will be a quagmire after stepping on it (only supporting the 128-bit byte displacement of the number of immediate records, difficult. We can only select the third unknown path (combined simulation of various other commands ).

Intel's MMX and SSE commands have been missing for a long time, and their design is also chaotic. Another famous one is that they only implement por, pand, pandn (and not ), pnot is not implemented (that is, inverse of MMX and SSE registers). Although pnot can indeed be implemented using pandn (you need at least two registers), or pcmpeqb xmm0, xmm0 is used to implement the full-set 1 operation, but it may increase the Register occupation and may increase the instruction cycle. However, it may be difficult. Although the impact is not big, sometimes when the registers are stretched, it is still very painful.

What's even more ridiculous is that, as I told you, you will surely believe that intel is absurd. What we really need is the unsigned logic shift left/right, but if you want to implement a signed right shift (arithmetic right shift ),

You can use the psraw/psrad command to compress the right shift of arithmetic. In addition, there is no arithmetic left shift, because the arithmetic left shift is the same as the logic left shift. For details, refer:

Http://moeto.comoj.com/project/intel/instruct32_hh/vc257.htm

It is ridiculous that intel has implemented a displacement of up to 31 bits for 128 bit registers, for 64-bit registers, the maximum displacement is 31 (see the above link). What do you know ???

Is there a problem with our IQ or with Intel's IQ ?!!

See:

PS: Correct. The above example is incorrect (I saw it wrong). Intel does not implement psraq. The above example is psrad, which is for DWORD rather than qword, therefore, this implementation is correct, and there is no problem here.

This problem is also mentioned in another famous post:

Thousands of points for assembly optimization: uint96x96to192 (...)

So far, no psraq command has been implemented.

. <End>.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.