[llvm] InstCombine: Handle extractelement in SimplifyDemandedFPClass (PR #174081)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 31 02:29:06 PST 2025


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/174081

A lot of boilerplate changes are necessary to do proper elementwise
tracking like SimplifyDemandedBits

>From 38174c754ecbc16866f9b8b0cb02512a79fa1a3e Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 31 Dec 2025 11:19:18 +0100
Subject: [PATCH] InstCombine: Handle extractelement in SimplifyDemandedFPClass

A lot of boilerplate changes are necessary to do proper elementwise
tracking like SimplifyDemandedBits
---
 .../InstCombineSimplifyDemanded.cpp           |   6 +
 ...implify-demanded-fpclass-extractelement.ll | 120 ++++++++++++++++++
 2 files changed, 126 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-extractelement.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 85672cdfe1377..26243c34a8fa7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2280,6 +2280,12 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
     Known = KnownLHS | KnownRHS;
     break;
   }
+  case Instruction::ExtractElement: {
+    // TODO: Handle demanded element mask
+    if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+      return I;
+    break;
+  }
   default:
     Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
     break;
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-extractelement.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-extractelement.ll
new file mode 100644
index 0000000000000..e571774c72f2b
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-extractelement.ll
@@ -0,0 +1,120 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare nofpclass(inf norm sub zero) <4 x half> @returns_nan()
+declare nofpclass(nan norm sub zero) <4 x half> @returns_inf()
+
+define nofpclass(inf norm sub zero) half @ret_only_nan__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[VEC]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(snan inf norm sub zero) half @ret_only_qnan__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[VEC]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(qnan inf norm sub zero) half @ret_only_snan__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[VEC]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan inf norm sub nzero) half @ret_only_pzero__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_pzero__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    ret half 0xH0000
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan inf norm sub pzero) half @ret_only_nzero__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) half @ret_only_nzero__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    ret half 0xH8000
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan inf norm sub) half @ret_only_zero__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[VEC]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan pinf norm sub zero) half @ret_only_ninf__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    ret half 0xHFC00
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan ninf norm sub zero) half @ret_only_pinf__extractelement_unknown(<4 x half> %vec, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf__extractelement_unknown(
+; CHECK-SAME: <4 x half> [[VEC:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    ret half 0xH7C00
+;
+  %ext = extractelement <4 x half> %vec, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan) half @ret_no_nan__extractelement_select_unknown_or_nan(i1 %cond, <4 x half> %unknown, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__extractelement_select_unknown_or_nan(
+; CHECK-SAME: i1 [[COND:%.*]], <4 x half> [[UNKNOWN:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[NAN:%.*]] = call <4 x half> @returns_nan()
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[UNKNOWN]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %nan = call <4 x half> @returns_nan()
+  %select = select i1 %cond, <4 x half> %nan, <4 x half> %unknown
+  %ext = extractelement <4 x half> %select, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(nan) half @ret_no_nan__extractelement_vselect_unknown_or_nan(<4 x i1> %cond, <4 x half> %unknown, i32 %idx) {
+; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan__extractelement_vselect_unknown_or_nan(
+; CHECK-SAME: <4 x i1> [[COND:%.*]], <4 x half> [[UNKNOWN:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[NAN:%.*]] = call <4 x half> @returns_nan()
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[UNKNOWN]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %nan = call <4 x half> @returns_nan()
+  %select = select <4 x i1> %cond, <4 x half> %nan, <4 x half> %unknown
+  %ext = extractelement <4 x half> %select, i32 %idx
+  ret half %ext
+}
+
+define nofpclass(inf) half @ret_no_nan__extractelement_vselect_unknown_or_inf(<4 x i1> %cond, <4 x half> %unknown, i32 %idx) {
+; CHECK-LABEL: define nofpclass(inf) half @ret_no_nan__extractelement_vselect_unknown_or_inf(
+; CHECK-SAME: <4 x i1> [[COND:%.*]], <4 x half> [[UNKNOWN:%.*]], i32 [[IDX:%.*]]) {
+; CHECK-NEXT:    [[INF:%.*]] = call <4 x half> @returns_inf()
+; CHECK-NEXT:    [[EXT:%.*]] = extractelement <4 x half> [[UNKNOWN]], i32 [[IDX]]
+; CHECK-NEXT:    ret half [[EXT]]
+;
+  %inf = call <4 x half> @returns_inf()
+  %select = select <4 x i1> %cond, <4 x half> %unknown, <4 x half> %inf
+  %ext = extractelement <4 x half> %select, i32 %idx
+  ret half %ext
+}



More information about the llvm-commits mailing list