[llvm] [VectorCombine] Fold insertelement chains of scalar parts to a bitcast and shuffle (PR #226224)

via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 05:56:36 PDT 2026


ParkHanbum wrote:

Sorry, this is maybe unrelated to the patch, but this time it seems to be an issue with x86 bitcast cost modeling.

```
"$i24_review_dir/latest/opt" -S -passes=vector-combine \
  -mtriple=x86_64 -mattr=+avx2 -debug-only=vector-combine \
  "$i24_review_dir/i24-repro.ll" \
  -o /private/tmp/i24-after.ll


b2sy at mac build %  cat "$i24_review_dir/i24-repro.ll"                     
target datalayout = "e-p:64:64"

define <2 x i24> @reverse_i24(i48 %x) {
  %s0 = lshr i48 %x, 24
  %t0 = trunc i48 %s0 to i24
  %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
  %t1 = trunc i48 %x to i24
  %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
  ret <2 x i24> %v1
}

define <2 x i24> @identity_i24(i48 %x) {
  %t0 = trunc i48 %x to i24
  %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
  %s1 = lshr i48 %x, 24
  %t1 = trunc i48 %s1 to i24
  %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
  ret <2 x i24> %v1
}
b2sy at mac build % "$i24_review_dir/latest/opt" -S -passes=vector-combine \
  -mtriple=x86_64 -mattr=+avx2 -debug-only=vector-combine \
  "$i24_review_dir/i24-repro.ll"


VECTORCOMBINE on reverse_i24
VC: Visiting:   %s0 = lshr i48 %x, 24
VC: Visiting:   %t0 = trunc i48 %s0 to i24
VC: Visiting:   %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
VC: Visiting:   %t1 = trunc i48 %x to i24
VC: Visiting:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
Found an insertelement chain of scalar parts:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
  OldCost: 3 vs NewCost: 2
VC: Replacing:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
         With:   %2 = shufflevector <2 x i24> %1, <2 x i24> poison, <2 x i32> <i32 1, i32 0>
VC: Erasing:   %2 = insertelement <2 x i24> %v0, i24 %t1, i64 1
VC: Erased:   %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
VC: Erased:   %t0 = trunc i48 %s0 to i24
VC: Erased:   %s0 = lshr i48 %x, 24
VC: Erased:   %t1 = trunc i48 %x to i24
VC: Visiting:   ret <2 x i24> %v1
VC: Visiting:   %v1 = shufflevector <2 x i24> %1, <2 x i24> poison, <2 x i32> <i32 1, i32 0>
VC: Visiting:   ret <2 x i24> %v1


VECTORCOMBINE on identity_i24
VC: Visiting:   %t0 = trunc i48 %x to i24
VC: Visiting:   %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
VC: Visiting:   %s1 = lshr i48 %x, 24
VC: Visiting:   %t1 = trunc i48 %s1 to i24
VC: Visiting:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
Found an insertelement chain of scalar parts:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
  OldCost: 3 vs NewCost: 1
VC: Replacing:   %v1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
         With:   %1 = bitcast i48 %x to <2 x i24>
VC: Erasing:   %1 = insertelement <2 x i24> %v0, i24 %t1, i64 1
VC: Erased:   %v0 = insertelement <2 x i24> poison, i24 %t0, i64 0
VC: Erased:   %t0 = trunc i48 %x to i24
VC: Erased:   %t1 = trunc i48 %s1 to i24
VC: Erased:   %s1 = lshr i48 %x, 24
VC: Visiting:   ret <2 x i24> %v1
VC: Visiting:   %v1 = bitcast i48 %x to <2 x i24>
VC: Visiting:   ret <2 x i24> %v1
; ModuleID = '/Users/b2sy/work/llvm/review/pr226224-final-20261004/i24-repro.ll'
source_filename = "/Users/b2sy/work/llvm/review/pr226224-final-20261004/i24-repro.ll"
target datalayout = "e-p:64:64"
target triple = "x86_64"

define <2 x i24> @reverse_i24(i48 %x) #0 {
  %1 = bitcast i48 %x to <2 x i24>
  %v1 = shufflevector <2 x i24> %1, <2 x i24> poison, <2 x i32> <i32 1, i32 0>
  ret <2 x i24> %v1
}

define <2 x i24> @identity_i24(i48 %x) #0 {
  %v1 = bitcast i48 %x to <2 x i24>
  ret <2 x i24> %v1
}

attributes #0 = { "target-features"="+avx2" }
```

As you can see, the cost model estimates the `i24` bitcast transformation to be cheaper.


```
b2sy at mac build % "$i24_llvm_bin/llc" -mtriple=x86_64 -mattr=+avx2 \
  /private/tmp/i24-before.ll -o /private/tmp/i24-before.s

"$i24_llvm_bin/llc" -mtriple=x86_64 -mattr=+avx2 \
  /private/tmp/i24-after.ll -o /private/tmp/i24-after.s

```

However, the generated code does not.
```
b2sy at mac build % diff -y /private/tmp/i24-before.s /private/tmp/i24-after.s 
	.att_syntax							.att_syntax
	.file	"i24-repro.ll"						.file	"i24-repro.ll"
	.text								.text
	.globl	reverse_i24                     # -- Begin fu		.globl	reverse_i24                     # -- Begin fu
	.prefalign	4, .Lfunc_end0, nop				.prefalign	4, .Lfunc_end0, nop
	.type	reverse_i24, at function					.type	reverse_i24, at function
reverse_i24:                            # @reverse_i24		reverse_i24:                            # @reverse_i24
	.cfi_startproc							.cfi_startproc
# %bb.0:							# %bb.0:
	vmovq	%rdi, %xmm0				      |		movl	%edi, -8(%rsp)
	shrq	$24, %rdi				      |		movzwl	%di, %eax
	andl	$16777215, %edi                 # imm = 0xFFF |		shrq	$32, %rdi
	vmovd	%edi, %xmm1				      |		movw	%di, -4(%rsp)
							      >		movzwl	-5(%rsp), %ecx
							      >		movzbl	-3(%rsp), %edx
							      >		shlq	$16, %rdx
							      >		orq	%rcx, %rdx
							      >		movzbl	-6(%rsp), %ecx
							      >		shlq	$16, %rcx
							      >		orq	%rax, %rcx
							      >		vmovq	%rcx, %xmm0
							      >		vmovq	%rdx, %xmm1
	vpunpcklqdq	%xmm0, %xmm1, %xmm0     # xmm0 = xmm1		vpunpcklqdq	%xmm0, %xmm1, %xmm0     # xmm0 = xmm1
	retq								retq
.Lfunc_end0:							.Lfunc_end0:
	.size	reverse_i24, .Lfunc_end0-reverse_i24			.size	reverse_i24, .Lfunc_end0-reverse_i24
	.cfi_endproc							.cfi_endproc
                                        # -- End function	                                        # -- End function
	.globl	identity_i24                    # -- Begin fu		.globl	identity_i24                    # -- Begin fu
	.prefalign	4, .Lfunc_end1, nop				.prefalign	4, .Lfunc_end1, nop
	.type	identity_i24, at function					.type	identity_i24, at function
identity_i24:                           # @identity_i24		identity_i24:                           # @identity_i24
	.cfi_startproc							.cfi_startproc
# %bb.0:							# %bb.0:
	vmovq	%rdi, %xmm0				      |		movl	%edi, -8(%rsp)
	shrq	$24, %rdi				      |		movzwl	%di, %eax
	andl	$16777215, %edi                 # imm = 0xFFF |		shrq	$32, %rdi
	vmovd	%edi, %xmm1				      |		movw	%di, -4(%rsp)
							      >		movzbl	-6(%rsp), %ecx
							      >		shlq	$16, %rcx
							      >		orq	%rax, %rcx
							      >		vmovq	%rcx, %xmm0
							      >		movzwl	-5(%rsp), %eax
							      >		movzbl	-3(%rsp), %ecx
							      >		shlq	$16, %rcx
							      >		orq	%rax, %rcx
							      >		vmovq	%rcx, %xmm1
	vpunpcklqdq	%xmm1, %xmm0, %xmm0     # xmm0 = xmm0		vpunpcklqdq	%xmm1, %xmm0, %xmm0     # xmm0 = xmm0
	retq								retq
.Lfunc_end1:							.Lfunc_end1:
	.size	identity_i24, .Lfunc_end1-identity_i24			.size	identity_i24, .Lfunc_end1-identity_i24
	.cfi_endproc							.cfi_endproc
                                        # -- End function	                                        # -- End function
	.section	".note.GNU-stack","", at progbits			.section	".note.GNU-stack","", at progbits

```

cc @RKSimon 

Other than that, I don’t have anything else to review.

https://github.com/llvm/llvm-project/pull/226224


More information about the llvm-commits mailing list