[llvm] [InstCombine] Limit canonicalization of extractelement(cast) to constant index or same basic block. (PR #166227)

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 19 06:03:36 PST 2025


https://github.com/azwolski updated https://github.com/llvm/llvm-project/pull/166227

>From aa49b2bcda4b664c4cc6a65731f53c39cd39c7f0 Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 11:53:52 +0100
Subject: [PATCH 1/7] [InstCombine] Limit canonicalization of
 extractelement(cast) to constant index

---
 llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 18a45c6799bac..87b5f3a58e72b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -588,7 +588,7 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
       // Canonicalize extractelement(cast) -> cast(extractelement).
       // Bitcasts can change the number of vector elements, and they cost
       // nothing.
-      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast)) {
+      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast) && isa<ConstantInt>(Index)) {
         Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
         return CastInst::Create(CI->getOpcode(), EE, EI.getType());
       }

>From 298613cffab3be828db15b6025ba310bb7e5a716 Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 11:55:30 +0100
Subject: [PATCH 2/7] [InstCombine] Update vec_extract_var_elt.ll test checks

---
 llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
index 205b4b88c473a..c01cdae81b81c 100644
--- a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
+++ b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
@@ -5,10 +5,10 @@ define void @test_poison(float %b, ptr %p) {
 ; CHECK-LABEL: define void @test_poison(
 ; CHECK-SAME: float [[B:%.*]], ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = load <8 x float>, ptr [[P]], align 32
+; CHECK-NEXT:    [[A:%.*]] = fptosi <8 x float> [[TMP1]] to <8 x i32>
 ; CHECK-NEXT:    [[TMP2:%.*]] = fptosi float [[B]] to i32
 ; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], -2
-; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <8 x float> [[TMP1]], i32 [[TMP3]]
-; CHECK-NEXT:    [[TMP5:%.*]] = fptosi float [[TMP4]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <8 x i32> [[A]], i32 [[TMP3]]
 ; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x i32> poison, i32 [[TMP5]], i64 7
 ; CHECK-NEXT:    [[TMP7:%.*]] = sitofp <8 x i32> [[TMP6]] to <8 x float>
 ; CHECK-NEXT:    store <8 x float> [[TMP7]], ptr [[P]], align 32
@@ -45,14 +45,14 @@ define void @test_loop(<4 x float> %in) {
 ; CHECK-SAME: <4 x float> [[IN:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
 ; CHECK-NEXT:    [[R:%.*]] = call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> [[IN]], i32 9)
+; CHECK-NEXT:    [[VI:%.*]] = fptosi <4 x float> [[R]] to <4 x i32>
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LATCH:.*]] ]
 ; CHECK-NEXT:    [[COND:%.*]] = icmp samesign ult i32 [[I]], 4
 ; CHECK-NEXT:    br i1 [[COND]], label %[[BODY:.*]], label %[[DONE:.*]]
 ; CHECK:       [[BODY]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = extractelement <4 x float> [[R]], i32 [[I]]
-; CHECK-NEXT:    [[ELEM:%.*]] = fptosi float [[TMP0]] to i32
+; CHECK-NEXT:    [[ELEM:%.*]] = extractelement <4 x i32> [[VI]], i32 [[I]]
 ; CHECK-NEXT:    call void @use(i32 [[ELEM]])
 ; CHECK-NEXT:    br label %[[LATCH]]
 ; CHECK:       [[LATCH]]:

>From 91e0c1b2cdd8564470cacfbf9c45ab6ca6713ee7 Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 14:52:47 +0100
Subject: [PATCH 3/7] [InstCombine] Refactor canonicalization of
 extractelement(cast) to constant index or same basic block.

---
 llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 87b5f3a58e72b..5af7c4caab074 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -588,9 +588,12 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
       // Canonicalize extractelement(cast) -> cast(extractelement).
       // Bitcasts can change the number of vector elements, and they cost
       // nothing.
-      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast) && isa<ConstantInt>(Index)) {
-        Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
-        return CastInst::Create(CI->getOpcode(), EE, EI.getType());
+      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast)){
+        Instruction *U = cast<Instruction>(*CI->user_begin());
+        if (U->getParent() == CI->getParent() || isa<ConstantInt>(Index)){
+          Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
+          return CastInst::Create(CI->getOpcode(), EE, EI.getType());
+        }
       }
     }
   }

>From 742d97e9a1168669b22bbb03680489416b48595b Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 21:11:27 +0100
Subject: [PATCH 4/7] [InstCombine] Add test_poison_branch test and update
 vec_extract_var_elt.ll test checks

---
 .../InstCombine/vec_extract_var_elt.ll        | 43 ++++++++++++++++---
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
index c01cdae81b81c..35d11b0cdf43f 100644
--- a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
+++ b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
@@ -5,10 +5,10 @@ define void @test_poison(float %b, ptr %p) {
 ; CHECK-LABEL: define void @test_poison(
 ; CHECK-SAME: float [[B:%.*]], ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = load <8 x float>, ptr [[P]], align 32
-; CHECK-NEXT:    [[A:%.*]] = fptosi <8 x float> [[TMP1]] to <8 x i32>
 ; CHECK-NEXT:    [[TMP2:%.*]] = fptosi float [[B]] to i32
 ; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], -2
-; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <8 x i32> [[A]], i32 [[TMP3]]
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <8 x float> [[TMP1]], i32 [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = fptosi float [[TMP4]] to i32
 ; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <8 x i32> poison, i32 [[TMP5]], i64 7
 ; CHECK-NEXT:    [[TMP7:%.*]] = sitofp <8 x i32> [[TMP6]] to <8 x float>
 ; CHECK-NEXT:    store <8 x float> [[TMP7]], ptr [[P]], align 32
@@ -39,13 +39,45 @@ define i32 @test_bitcast(i32 %i) {
 }
 
 declare void @use(i32)
+declare void @use_vi(<4 x i32>)
+
+define void @test_poison_branch(<4 x float> %in, i32 %a, i1 %cond) {
+; CHECK-LABEL: define void @test_poison_branch(
+; CHECK-SAME: <4 x float> [[IN:%.*]], i32 [[A:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[I:%.*]] = add i32 [[A]], -2
+; CHECK-NEXT:    br i1 [[COND]], label %[[TRUE:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @use(i32 [[I]])
+; CHECK-NEXT:    br label %[[DONE:.*]]
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = extractelement <4 x float> [[IN]], i32 [[I]]
+; CHECK-NEXT:    [[ELEM:%.*]] = fptosi float [[TMP0]] to i32
+; CHECK-NEXT:    call void @use(i32 [[ELEM]])
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %vi = fptosi <4 x float> %in to <4 x i32>
+  %i = add i32 %a, -2
+  br i1 %cond, label %true, label %false
+true:
+  call void @use(i32 %i)
+  br label %done
+false:
+  %elem = extractelement <4 x i32> %vi, i32 %i
+  call void @use(i32 %elem)
+  br label %done
+done:
+  ret void
+}
 
 define void @test_loop(<4 x float> %in) {
 ; CHECK-LABEL: define void @test_loop(
 ; CHECK-SAME: <4 x float> [[IN:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[R:%.*]] = call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> [[IN]], i32 9)
-; CHECK-NEXT:    [[VI:%.*]] = fptosi <4 x float> [[R]] to <4 x i32>
+; CHECK-NEXT:    [[VI:%.*]] = fptosi <4 x float> [[IN]] to <4 x i32>
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[NEXT:%.*]], %[[LATCH:.*]] ]
@@ -62,8 +94,7 @@ define void @test_loop(<4 x float> %in) {
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %r = call <4 x float> @llvm.x86.sse41.round.ps(<4 x float> %in, i32 9)
-  %vi = fptosi <4 x float> %r to <4 x i32>
+  %vi = fptosi <4 x float> %in to <4 x i32>
   br label %loop
 loop:
   %i = phi i32 [ 0, %entry ], [ %next, %latch ]

>From 4d8d8fdd9099e4384a215ed5d2e90e9aa690975e Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 21:13:40 +0100
Subject: [PATCH 5/7] [InstCombine] Remove unused declaration of @use_vi in
 vec_extract_var_elt.ll

---
 llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
index 35d11b0cdf43f..f96b7070f9f2a 100644
--- a/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
+++ b/llvm/test/Transforms/InstCombine/vec_extract_var_elt.ll
@@ -39,7 +39,6 @@ define i32 @test_bitcast(i32 %i) {
 }
 
 declare void @use(i32)
-declare void @use_vi(<4 x i32>)
 
 define void @test_poison_branch(<4 x float> %in, i32 %a, i1 %cond) {
 ; CHECK-LABEL: define void @test_poison_branch(

>From 4a1267a38008d8472c80114b32fafc62d800e9c8 Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Mon, 3 Nov 2025 21:31:20 +0100
Subject: [PATCH 6/7] [InstCombine] Fix formatting in visitExtractElementInst

---
 llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 5af7c4caab074..44c3863dd97b5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -588,9 +588,9 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
       // Canonicalize extractelement(cast) -> cast(extractelement).
       // Bitcasts can change the number of vector elements, and they cost
       // nothing.
-      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast)){
+      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast)) {
         Instruction *U = cast<Instruction>(*CI->user_begin());
-        if (U->getParent() == CI->getParent() || isa<ConstantInt>(Index)){
+        if (U->getParent() == CI->getParent() || isa<ConstantInt>(Index)) {
           Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
           return CastInst::Create(CI->getOpcode(), EE, EI.getType());
         }

>From 99da1283f75dad503a96408d19d1cfc9d7b7e872 Mon Sep 17 00:00:00 2001
From: Antoni Zwolski <antoni.zwolski at intel.com>
Date: Wed, 19 Nov 2025 14:47:22 +0100
Subject: [PATCH 7/7] [InstCombine] Simplify conditional checks for
 extractelement(cast) canonicalization

---
 .../Transforms/InstCombine/InstCombineVectorOps.cpp    | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index 44c3863dd97b5..5d992f48d0544 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -588,12 +588,10 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
       // Canonicalize extractelement(cast) -> cast(extractelement).
       // Bitcasts can change the number of vector elements, and they cost
       // nothing.
-      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast)) {
-        Instruction *U = cast<Instruction>(*CI->user_begin());
-        if (U->getParent() == CI->getParent() || isa<ConstantInt>(Index)) {
-          Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
-          return CastInst::Create(CI->getOpcode(), EE, EI.getType());
-        }
+      if (CI->hasOneUse() && (CI->getOpcode() != Instruction::BitCast) &&
+          (EI.getParent() == CI->getParent() || isa<ConstantInt>(Index))) {
+        Value *EE = Builder.CreateExtractElement(CI->getOperand(0), Index);
+        return CastInst::Create(CI->getOpcode(), EE, EI.getType());
       }
     }
   }



More information about the llvm-commits mailing list