llvm / llvm/llvm-project

[AVX] Prefer `VPUNPCKHBW` to `VPSHUFD` to save 1 byte in I$

Open
#191,762 1 comment 0 reactions 1 assignee Claimed by @RKSimon View on GitHub
backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

[LLVM Godbolt](https://llvm.godbo.lt/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1C1aANxakl9ZATwDKjdAGFUtAK4sGexwBk8DTAA5DwAjTGIJAGZSAAdUBUI7Bhd3Tz04hNsBPwDgljCIrmirTBskoQImYgIUjy8uS0xrLIYKqoIcoNDwqMtK6tq0hoV%2Bjv8u/J6igEpLVDdiZHYOLBoAgGp0BVQAfVpUUVp1gFJIp0iAJnXVdbwADlPsdYABflQIU6dJa9uANklHicLgBWDTTdb7Q47NwMZhsdA7JjodDEE4AdgAQscNABBbCCYgATxA2Jx6yBwK4J0iABF1iFCKIRtSvj88P9AccQRp1kQWZc2Q9IthSeSucCrqc6QoEG4qFR6KZSkRUZ8BTd7pyQQ1%2BVcNUKnnE8NsGKRdWzLpyzngBXczTarnbbrb7S7nY7XR73esnQ6fZ7/d7fW6/cGvaGA2HAxGg5G47GEzGkyGU%2BHU9H01GDaL1sRMARzfqtRLScc0TTS7jVuNNts9gcxIXbgaXiEqh8zurm8WwRCG7RobDWJgEUiUeisbj8QQiSTcWLtdTpbL5YrlSQm5rhRSNGa1Xru9ujSa952Dw6rU5k2mbxnb1n49e78%2BH4nM4/32/7x/v1%2BXz//yDR4czzAt90FYsuFLctSQ4WZaE4YFeC8DgtFIVBOB8HwADUAFl1gASQAJXWbYFiWIFIh4UgCE0ODZgAaxASRIgAOkkDRQTuO4NF%2BC4%2BIuKj9E4SRkLo9DOF4BQQF3WjULg0g4FgJA0BYGI6HCchKFU9T6AiEwbGIGEGL4OgCHCaSIBCcSGWYWduF4WyqkJAB5EJtGVThqNUthBBchhaGJeTSCwEI3GAJwxFoaSHJCzAWEMYBxGC/A8zKJUYrQzBVFKNxzK83h/HMhDgtoPAQmIZyXCwcSZzwFgCtIJViBCeJMBpeLErKow6NmBUmGABRsLwTAAHcXJiRhGv4QQRDEdgpBkQRFBUdRgt0BoDB6kxzH0crpMgWZUBiFoYoAWhcyJ1jOlhkBiNwpQALwYZqkPQ5riDwLADogWYSjKewIEcQZ6lIXxxjyAp0niRIBBB6HMiSTpIamRpmnKUZ4eGJplQx9pke6Qo%2BnaLHieqAnJkKP75kWBb4MQsTgowjgIVoZB1ggGdjPBCBcEIDcuSo6ZeDkrRpkYkBgV%2BVjgQATkkWWuC4WXIjRVW0V%2BWXhI4UTSAargNF3FC0OZqSZJo3r6Y4C5GZNySLfk8WmospJmKAA)
[Zig Godbolt](https://zig.godbo.lt/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:21,fontUsePx:'0',j:1,lang:zig,selection:(endColumn:45,endLineNumber:1,positionColumn:45,positionLineNumber:1,selectionStartColumn:45,selectionStartLineNumber:1,startColumn:45,startLineNumber:1),source:'export+fn+foo(x:+@Vector(4,+u64))+@Vector(32,+u8)+%7B%0A++++return+@splat(@truncate(x%5B1%5D))%3B%0A%7D%0A%0Aexport+fn+bar(x:+@Vector(32,+u8))+@Vector(32,+u8)+%7B%0A++++return+@splat(@truncate(x%5B8%5D))%3B%0A%7D'),l:'5',n:'0',o:'Zig+source+%231',t:'0')),k:44.228888164329966,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:z0152,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:21,fontUsePx:'0',j:1,lang:zig,libs:!(),options:'-O+ReleaseFast+-mcpu%3Dznver3+-target+x86_64-linux+-fomit-frame-pointer',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+zig+0.15.2+(Editor+%231)',t:'0')),header:(),k:55.77111183567004,l:'4',m:45.58725945587259,n:'0',o:'',s:0,t:'0'),(g:!((h:ir,i:('-fno-discard-value-names':'0',compilerName:'zig+0.15.2',demangle-symbols:'0',editorid:1,filter-attributes:'0',filter-comments:'0',filter-debug-info:'0',filter-declarations:'1',filter-instruction-metadata:'0',filter-library-functions:'1',fontScale:14,fontUsePx:'0',j:1,selection:(endColumn:1,endLineNumber:13,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:13,startColumn:1,startLineNumber:1),show-optimized:'0',treeid:0,wrap:'1'),l:'5',n:'0',o:'LLVM+IR+Viewer+zig+0.15.2+(Editor+%231,+Compiler+%231)',t:'0')),header:(),l:'4',m:54.412740544127416,n:'0',o:'',s:0,t:'0')),k:55.77111183567004,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4)
```llvm
define dso_local <32 x i8> @foo(<4 x i64> %0) local_unnamed_addr {
Entry:
%1 = bitcast <4 x i64> %0 to <32 x i8>
%2 = shufflevector <32 x i8> %1, <32 x i8> poison, <32 x i32>
ret <32 x i8> %2
}

define dso_local <32 x i8> @bar(<32 x i8> %0) local_unnamed_addr {
Entry:
%1 = shufflevector <32 x i8> %0, <32 x i8> poison, <32 x i32>
ret <32 x i8> %1
}
```

On older versions of LLVM, we used to get:

```asm
foo:
vpunpckhbw xmm0, xmm0, xmm0
vpbroadcastw ymm0, xmm0
ret

bar:
vpshufd xmm0, xmm0, 238
vpbroadcastb ymm0, xmm0
ret
```

Now we only get the `vpshufd` version. I think the `vpunpckhbw` was preferable though because it is 1 fewer byte to encode.

I would think this should be implemented in a final cleanup pass or something, because there are other optimizations I would hope don't get disabled. E.g. [(LLVM Godbolt)](https://llvm.godbo.lt/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1C1aANxakl9ZATwDKjdAGFUtAK4sGexwBk8DTAA5DwAjTGIQACYAZlIAB1QFQjsGF3dPPQSk2wE/AOCWMIiYy0xrHIYhAiZiAjSPLy5S8pSqmoI8oNDwqNiFatr6jKb%2B9s6Cot6ASktUN2Jkdg4AARCagGoAUmiAEXWxPCYFLeinAA511XW8ADZJbex1iG2naMjL67OHmfW4gmJ1stMKpWHF6AA6NbETYaACCy34qBOewORxO5w%2Bt3u0Uez1Okkxd2%2BpF%2B/0BwNBEMRMNhNKwNAC10E4WYtHRFyuWIe5JBLDBmEhNTxr3enK%2BOK2kQArBopus3AxmGx0AB9JjodAAg7ABjrLhbADsACEadhBMQAJ4gGnrSVS/XbPYKBBuKhUeimTA2Ejot6Y8WPTbSjQkl5%2BsXchJ4BQCUOnO6Yt7cl54P1nEmp97p65pjO5nNZvOFgvrbOZ0tFislsv58s14t1yv1quN6tN9ttzut7u13sNvstgfN4cdnv98eDicjrtD0ezmdTueLheT1fTsdrpdrh42u3vR3rEKEUT9dEJiMSoP29ZEdmE7HYXdX6LIw/Ho4EX2iz7J4M3pEvASnJEjiT7SgSB7Oq67qYJ63oAoB96/lKsTokB1wgY8UYxgwcYYpySaXqc5ZNCWpEkZW5F%2BlR7w0XqlE7nCtpXlKr7qugd7AQ%2BdrSHuu7EJgn4vByGHcSxNKbAaOwSXC9L%2BJgTIECyYicaJ3JAry/LgoiwroVyl7BnKCpKpgqrsVqtB4DqeqGiacJmv8VpgdeB5HgQJ5CfiSEGTK/5fv6jGwsx0r7rs6xQW6HpekQCGnOGP4%2BaRYbfngAa/Kg0axmeemEYGxHzhu64FcVy6FVuRWlSVm4rhV1VlTV5WNQ1zX1a1VW1R1TVtZVPV1e1TaBcFKGvm5HnZQFPnvLewneY%2BTE8a%2BEUwXBMVobNdohmtXGRhlOF4SJmbJvltGUadZFnRR51kYNdqsQe7GqfpgbgaG0rRPxgmPZht0SVJNIcDMtCcFKvBeBwWikKgnA%2BD4ABqACy6wAJIAErhXMCwKUG0Q8KQBCaADMwANYgPa4IGpIXA3GckQAJwU1KUq0zctP6JwkigwTkOcLwCggCG%2BPgwDpBwLASBoHydDhOQlAS3EUsRCYNjEAqRN8HQSnEHzEAhFzR7MJanC4/rNQWgA8iE2jRUbvAS2wghmwwtBWkLpBYCEbjAE4Yi0Hz3C8FgLCGMA4iu/gAk2Hgnp%2BxDwJem4Sk2%2BQzJA67lkhMQpsuFgXP/HgLBJ56xAhIkmA7JgQdGJZRgEzM7pMMACiw3gmAAO5m3EjBJ/wggiGI7BSDIgiKCo6iu7oTQGDXJjmPoeAhHzkAzKgfwpH7AC0ZsvuvLDIHEbiOgAXgwRcg5DRfEHgWCLxAMxWNFKQOAwziuA03jP%2BM3QRE0WTJAIQyNHiIkP%2BDBP6FB6CMMoD8BBtEGK/YYzRoGVAGB0eSEwIGWBQQAvQoxahgMmFwO%2BGNFgSEBsDTmrsoYcHWErJ4/xVZyggLgQgPpsaEN4ILLQUxiYgEkGccE0ozg4wNBocCkgNA4zZhwDmpAC5cA0CGMGEMqG835njWuZCOCRAoconm6ihbcNIEXJI9hJBAA%3D%3D%3D) [(Zig Godbolt)](https://zig.godbo.lt/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:21,fontUsePx:'0',j:1,lang:zig,selection:(endColumn:88,endLineNumber:2,positionColumn:5,positionLineNumber:2,selectionStartColumn:88,selectionStartLineNumber:2,startColumn:5,startLineNumber:2),source:'export+fn+foo(x:+@Vector(4,+u64))+@Vector(8,+u64)+%7B%0A++++const+y:+@Vector(8,+u64)+%3D+@bitCast(@as(@Vector(64,+u8),+@splat(@truncate(x%5B1%5D))))%3B%0A++++const+z:+@Vector(8,+u64)+%3D+@splat(x%5B1%5D)%3B%0A++++return+y+%2B%25+z%3B%0A%7D%0A%0Aexport+fn+bar(x:+@Vector(32,+u8))+@Vector(8,+u64)+%7B%0A++++const+y:+@Vector(8,+u64)+%3D+@bitCast(@as(@Vector(64,+u8),+@splat(x%5B8%5D)))%3B%0A++++const+z:+@Vector(8,+u64)+%3D+@splat(@as(@Vector(4,+u64),+@bitCast(x))%5B1%5D)%3B%0A++++return+y+%2B%25+z%3B%0A%7D'),l:'5',n:'0',o:'Zig+source+%231',t:'0')),k:44.228888164329966,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:ztrunk,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:21,fontUsePx:'0',j:1,lang:zig,libs:!(),options:'-O+ReleaseFast+-mcpu%3Dznver5+-target+x86_64-linux+-fomit-frame-pointer',overrides:!(),selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+zig+trunk+(Editor+%231)',t:'0')),header:(),k:55.77111183567004,l:'4',m:53.74917053749171,n:'0',o:'',s:0,t:'0'),(g:!((h:ir,i:('-fno-discard-value-names':'0',compilerName:'zig+trunk',demangle-symbols:'0',editorid:1,filter-attributes:'0',filter-comments:'0',filter-debug-info:'0',filter-declarations:'1',filter-instruction-metadata:'0',filter-library-functions:'1',fontScale:14,fontUsePx:'0',j:1,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),show-optimized:'0',treeid:0,wrap:'1'),l:'5',n:'0',o:'LLVM+IR+Viewer+zig+trunk+(Editor+%231,+Compiler+%231)',t:'0')),header:(),l:'4',m:46.25082946250829,n:'0',o:'',s:0,t:'0')),k:55.77111183567004,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4) (See https://github.com/llvm/llvm-project/issues/191763)

```zig
export fn foo(x: @Vector(4, u64)) @Vector(8, u64) {
const y: @Vector(8, u64) = @bitCast(@as(@Vector(64, u8), @splat(@truncate(x[1]))));
const z: @Vector(8, u64) = @splat(x[1]);
return y +% z;
}
```

Should hopefully keep the same emit:

```asm
example.foo:
vpshufd xmm0, xmm0, 238
vpbroadcastb zmm1, xmm0
vpbroadcastq zmm0, xmm0
vpaddq zmm0, zmm0, zmm1
ret
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.