https://github.com/Michael-Chen-NJU updated 
https://github.com/llvm/llvm-project/pull/219348

From e480ab1e9b26f64c9301fb54455cc64e264269aa Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <[email protected]>
Date: Fri, 28 Aug 2026 10:06:25 +0800
Subject: [PATCH 1/2] [Clang][RISCV] Add packed widening add/sub intrinsics

Add packed widening add/sub header wrappers for the RISC-V P extension using 
generic vector IR.

Select the RV32 direct packed widening add/sub forms and the RV64 spec-listed 
decompositions, with Clang, LLVM CodeGen, and cross-project header coverage.
---
 clang/lib/Headers/riscv_packed_simd.h         |  17 ++
 clang/test/CodeGen/RISCV/rvp-intrinsics.c     | 208 ++++++++++++++++++
 .../riscv_packed_simd.c                       |  74 +++++++
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  71 ++++++
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td      |  35 +++
 llvm/test/CodeGen/RISCV/rvp-simd-32.ll        | 156 ++++++++++++-
 6 files changed, 556 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Headers/riscv_packed_simd.h 
b/clang/lib/Headers/riscv_packed_simd.h
index 946dd936d49cd..a3f72211d0feb 100644
--- a/clang/lib/Headers/riscv_packed_simd.h
+++ b/clang/lib/Headers/riscv_packed_simd.h
@@ -142,6 +142,12 @@ typedef uint32_t uint32x2_t 
__attribute__((__vector_size__(8)));
   static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1) {          
\
     return __builtin_convertvector(__rs1, rty);                                
\
   }
+#define __packed_widen_binary_op(name, rty, ty, op)                            
\
+  static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1,            
\
+                                                          ty __rs2) {          
\
+    return __builtin_convertvector(__rs1, rty)                                 
\
+        op __builtin_convertvector(__rs2, rty);                                
\
+  }
 #define __packed_widen_mul(name, rty, ty)                                      
\
   static __inline__ rty __DEFAULT_FN_ATTRS __riscv_##name(ty __rs1,            
\
                                                           ty __rs2) {          
\
@@ -604,6 +610,16 @@ __packed_widen_high4(pwcvth_u16x4, uint16x4_t, uint8x4_t)
 __packed_widen_high2(pwcvth_i32x2, int32x2_t, int16x2_t)
 __packed_widen_high2(pwcvth_u32x2, uint32x2_t, uint16x2_t)
 
+/* Packed Widening Addition and Subtraction */
+__packed_widen_binary_op(pwadd_i16x4, int16x4_t, int8x4_t, +)
+__packed_widen_binary_op(pwadd_i32x2, int32x2_t, int16x2_t, +)
+__packed_widen_binary_op(pwaddu_u16x4, uint16x4_t, uint8x4_t, +)
+__packed_widen_binary_op(pwaddu_u32x2, uint32x2_t, uint16x2_t, +)
+__packed_widen_binary_op(pwsub_i16x4, int16x4_t, int8x4_t, -)
+__packed_widen_binary_op(pwsub_i32x2, int32x2_t, int16x2_t, -)
+__packed_widen_binary_op(pwsubu_u16x4, uint16x4_t, uint8x4_t, -)
+__packed_widen_binary_op(pwsubu_u32x2, uint32x2_t, uint16x2_t, -)
+
 /* Packed Widening Multiply (32-bit) */
 __packed_widen_mul(pwmul_i16x4, int16x4_t, int8x4_t)
 __packed_widen_mul(pwmul_i32x2, int32x2_t, int16x2_t)
@@ -1004,6 +1020,7 @@ __packed_reinterpret(u32x2_i32x2, int32x2_t, uint32x2_t)
 #undef __packed_merge_builtin
 #undef __packed_unary_builtin
 #undef __packed_widen_convert
+#undef __packed_widen_binary_op
 #undef __packed_widen_mul
 #undef __packed_widen_mulsu
 #undef __packed_widen_high2
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c 
b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index 74a7cb60a6afa..af45d4235b068 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -8032,6 +8032,214 @@ uint32x2_t test_pwcvtu_u32x2(uint16x2_t rs1) {
   return __riscv_pwcvtu_u32x2(rs1);
 }
 
+// RV32-LABEL: define dso_local i64 @test_pwadd_i16x4(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16>
+// RV32-NEXT:    [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16>
+// RV32-NEXT:    [[ADD_I:%.*]] = add nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[ADD_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwadd_i16x4(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16>
+// RV64-NEXT:    [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16>
+// RV64-NEXT:    [[ADD_I:%.*]] = add nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[ADD_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+int16x4_t test_pwadd_i16x4(int8x4_t rs1, int8x4_t rs2) {
+  return __riscv_pwadd_i16x4(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwadd_i32x2(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32>
+// RV32-NEXT:    [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32>
+// RV32-NEXT:    [[ADD_I:%.*]] = add nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[ADD_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwadd_i32x2(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32>
+// RV64-NEXT:    [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32>
+// RV64-NEXT:    [[ADD_I:%.*]] = add nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[ADD_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+int32x2_t test_pwadd_i32x2(int16x2_t rs1, int16x2_t rs2) {
+  return __riscv_pwadd_i32x2(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwaddu_u16x4(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16>
+// RV32-NEXT:    [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16>
+// RV32-NEXT:    [[ADD_I:%.*]] = add nuw nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[ADD_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwaddu_u16x4(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16>
+// RV64-NEXT:    [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16>
+// RV64-NEXT:    [[ADD_I:%.*]] = add nuw nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[ADD_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint16x4_t test_pwaddu_u16x4(uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pwaddu_u16x4(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwaddu_u32x2(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32>
+// RV32-NEXT:    [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32>
+// RV32-NEXT:    [[ADD_I:%.*]] = add nuw nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[ADD_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwaddu_u32x2(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32>
+// RV64-NEXT:    [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32>
+// RV64-NEXT:    [[ADD_I:%.*]] = add nuw nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[ADD_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint32x2_t test_pwaddu_u32x2(uint16x2_t rs1, uint16x2_t rs2) {
+  return __riscv_pwaddu_u32x2(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwsub_i16x4(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16>
+// RV32-NEXT:    [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16>
+// RV32-NEXT:    [[SUB_I:%.*]] = sub nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[SUB_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwsub_i16x4(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[CONV_I:%.*]] = sext <4 x i8> [[TMP0]] to <4 x i16>
+// RV64-NEXT:    [[CONV3_I:%.*]] = sext <4 x i8> [[TMP1]] to <4 x i16>
+// RV64-NEXT:    [[SUB_I:%.*]] = sub nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[SUB_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+int16x4_t test_pwsub_i16x4(int8x4_t rs1, int8x4_t rs2) {
+  return __riscv_pwsub_i16x4(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwsub_i32x2(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32>
+// RV32-NEXT:    [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32>
+// RV32-NEXT:    [[SUB_I:%.*]] = sub nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[SUB_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwsub_i32x2(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[CONV_I:%.*]] = sext <2 x i16> [[TMP0]] to <2 x i32>
+// RV64-NEXT:    [[CONV3_I:%.*]] = sext <2 x i16> [[TMP1]] to <2 x i32>
+// RV64-NEXT:    [[SUB_I:%.*]] = sub nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[SUB_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+int32x2_t test_pwsub_i32x2(int16x2_t rs1, int16x2_t rs2) {
+  return __riscv_pwsub_i32x2(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwsubu_u16x4(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV32-NEXT:    [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16>
+// RV32-NEXT:    [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16>
+// RV32-NEXT:    [[SUB_I:%.*]] = sub nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[SUB_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwsubu_u16x4(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <4 x i8>
+// RV64-NEXT:    [[CONV_I:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16>
+// RV64-NEXT:    [[CONV3_I:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16>
+// RV64-NEXT:    [[SUB_I:%.*]] = sub nsw <4 x i16> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <4 x i16> [[SUB_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint16x4_t test_pwsubu_u16x4(uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pwsubu_u16x4(rs1, rs2);
+}
+
+// RV32-LABEL: define dso_local i64 @test_pwsubu_u32x2(
+// RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV32-NEXT:  [[ENTRY:.*:]]
+// RV32-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV32-NEXT:    [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32>
+// RV32-NEXT:    [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32>
+// RV32-NEXT:    [[SUB_I:%.*]] = sub nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV32-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[SUB_I]] to i64
+// RV32-NEXT:    ret i64 [[TMP2]]
+//
+// RV64-LABEL: define dso_local i64 @test_pwsubu_u32x2(
+// RV64-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
+// RV64-NEXT:  [[ENTRY:.*:]]
+// RV64-NEXT:    [[TMP0:%.*]] = bitcast i32 [[RS1_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[TMP1:%.*]] = bitcast i32 [[RS2_COERCE]] to <2 x i16>
+// RV64-NEXT:    [[CONV_I:%.*]] = zext <2 x i16> [[TMP0]] to <2 x i32>
+// RV64-NEXT:    [[CONV3_I:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i32>
+// RV64-NEXT:    [[SUB_I:%.*]] = sub nsw <2 x i32> [[CONV_I]], [[CONV3_I]]
+// RV64-NEXT:    [[TMP2:%.*]] = bitcast <2 x i32> [[SUB_I]] to i64
+// RV64-NEXT:    ret i64 [[TMP2]]
+//
+uint32x2_t test_pwsubu_u32x2(uint16x2_t rs1, uint16x2_t rs2) {
+  return __riscv_pwsubu_u32x2(rs1, rs2);
+}
+
 // RV32-LABEL: define dso_local i64 @test_pwmul_i16x4(
 // RV32-SAME: i32 noundef [[RS1_COERCE:%.*]], i32 noundef [[RS2_COERCE:%.*]]) 
#[[ATTR0]] {
 // RV32-NEXT:  [[ENTRY:.*:]]
diff --git a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c 
b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
index 28e3a8911739d..4730f860cb6bf 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2269,6 +2269,80 @@ uint32x2_t test_pwcvtu_u32x2(uint16x2_t rs1) {
   return __riscv_pwcvtu_u32x2(rs1);
 }
 
+// CHECK-LABEL: test_pwadd_i16x4:
+// RV32:        pwadd.b
+// RV64:        zip8p
+// RV64:        psrai.h
+// RV64:        psext.h.b
+// RV64:        padd.h
+int16x4_t test_pwadd_i16x4(int8x4_t rs1, int8x4_t rs2) {
+  return __riscv_pwadd_i16x4(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwadd_i32x2:
+// RV32:        pwadd.h
+// RV64:        zip16p
+// RV64:        pli.h
+// RV64:        pm2add.h
+int32x2_t test_pwadd_i32x2(int16x2_t rs1, int16x2_t rs2) {
+  return __riscv_pwadd_i32x2(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwaddu_u16x4:
+// RV32:        pwaddu.b
+// RV64:        pwcvtu.wb
+// RV64:        pwcvtu.wb
+// RV64:        padd.h
+uint16x4_t test_pwaddu_u16x4(uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pwaddu_u16x4(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwaddu_u32x2:
+// RV32:        pwaddu.h
+// RV64:        zip16p
+// RV64:        pli.h
+// RV64:        pm2addu.h
+uint32x2_t test_pwaddu_u32x2(uint16x2_t rs1, uint16x2_t rs2) {
+  return __riscv_pwaddu_u32x2(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwsub_i16x4:
+// RV32:        pwsub.b
+// RV64:        zip8p
+// RV64:        psrai.h
+// RV64:        psext.h.b
+// RV64:        psub.h
+int16x4_t test_pwsub_i16x4(int8x4_t rs1, int8x4_t rs2) {
+  return __riscv_pwsub_i16x4(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwsub_i32x2:
+// RV32:        pwsub.h
+// RV64:        zip16p
+// RV64:        pli.h
+// RV64:        pm2sub.h
+int32x2_t test_pwsub_i32x2(int16x2_t rs1, int16x2_t rs2) {
+  return __riscv_pwsub_i32x2(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwsubu_u16x4:
+// RV32:        pwsubu.b
+// RV64:        pwcvtu.wb
+// RV64:        pwcvtu.wb
+// RV64:        psub.h
+uint16x4_t test_pwsubu_u16x4(uint8x4_t rs1, uint8x4_t rs2) {
+  return __riscv_pwsubu_u16x4(rs1, rs2);
+}
+
+// CHECK-LABEL: test_pwsubu_u32x2:
+// RV32:        pwsubu.h
+// RV64:        pwcvtu.wh
+// RV64:        pwcvtu.wh
+// RV64:        psub.w
+uint32x2_t test_pwsubu_u32x2(uint16x2_t rs1, uint16x2_t rs2) {
+  return __riscv_pwsubu_u32x2(rs1, rs2);
+}
+
 // CHECK-LABEL: test_pwcvth_i16x4:
 // RV32:        pwcvth.b
 // RV64:        pwcvth.wb
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 470599784314a..794ac85f1cd78 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17975,6 +17975,73 @@ static SDValue combineAddMulh(SDNode *N, SelectionDAG 
&DAG,
   return DAG.getNode(RISCVISD::MULHSU, DL, VT, X, Mulh.getOperand(1));
 }
 
+static SDValue combinePExtWideningAddSub(SDNode *N, SelectionDAG &DAG,
+                                         const RISCVSubtarget &Subtarget) {
+  // Recognize the RV64 decompositions listed for the 32-bit packed widening
+  // add/sub operations. Mixed signed/unsigned PM2 forms are outside that 
group.
+  if (!Subtarget.hasStdExtP() || !Subtarget.is64Bit())
+    return SDValue();
+
+  unsigned Opcode = N->getOpcode();
+  if (Opcode != ISD::ADD && Opcode != ISD::SUB)
+    return SDValue();
+
+  EVT VT = N->getValueType(0);
+  if (VT != MVT::v4i16 && VT != MVT::v2i32)
+    return SDValue();
+
+  SDValue N0 = N->getOperand(0);
+  SDValue N1 = N->getOperand(1);
+  bool N0IsSExt = N0.getOpcode() == ISD::SIGN_EXTEND;
+  bool N0IsZExt = N0.getOpcode() == ISD::ZERO_EXTEND;
+  bool N1IsSExt = N1.getOpcode() == ISD::SIGN_EXTEND;
+  bool N1IsZExt = N1.getOpcode() == ISD::ZERO_EXTEND;
+  if (!(N0IsSExt || N0IsZExt) || !(N1IsSExt || N1IsZExt) || !N0.hasOneUse() ||
+      !N1.hasOneUse())
+    return SDValue();
+
+  SDValue A = N0.getOperand(0);
+  SDValue B = N1.getOperand(0);
+  MVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
+  MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16;
+  if (A.getValueType() != SrcVT || B.getValueType() != SrcVT)
+    return SDValue();
+
+  if (VT == MVT::v4i16 && (!N0IsSExt || !N1IsSExt))
+    return SDValue();
+
+  bool IsPM2Halfword =
+      VT == MVT::v2i32 &&
+      ((N0IsSExt && N1IsSExt) || (Opcode == ISD::ADD && N0IsZExt && N1IsZExt));
+  if (VT == MVT::v2i32 && !IsPM2Halfword)
+    return SDValue();
+
+  SDLoc DL(N);
+  A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT));
+  B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT));
+
+  SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B);
+  if (VT == MVT::v4i16) {
+    SDValue ZipAsVT = DAG.getBitcast(VT, Zip);
+    SDValue Low = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, ZipAsVT,
+                              DAG.getValueType(MVT::v4i8));
+    SDValue High = DAG.getNode(RISCVISD::PSRA, DL, VT, ZipAsVT,
+                               DAG.getConstant(8, DL, MVT::i64));
+    return DAG.getNode(Opcode, DL, VT, Low, High);
+  }
+
+  SDValue Ones = DAG.getConstant(1, DL, LegalSrcVT);
+  if (N0IsSExt && N1IsSExt) {
+    unsigned Opc = Opcode == ISD::ADD ? RISCVISD::PM2ADD_H : 
RISCVISD::PM2SUB_H;
+    return DAG.getNode(Opc, DL, VT, Zip, Ones);
+  }
+
+  if (Opcode == ISD::ADD && N0IsZExt && N1IsZExt)
+    return DAG.getNode(RISCVISD::PM2ADDU_H, DL, VT, Zip, Ones);
+
+  return SDValue();
+}
+
 static SDValue performADDCombine(SDNode *N,
                                  TargetLowering::DAGCombinerInfo &DCI,
                                  const RISCVSubtarget &Subtarget) {
@@ -17993,6 +18060,8 @@ static SDValue performADDCombine(SDNode *N,
     return V;
   if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))
     return V;
+  if (SDValue V = combinePExtWideningAddSub(N, DAG, Subtarget))
+    return V;
   if (SDValue V = combineBinOpOfZExt(N, DAG))
     return V;
   if (SDValue V = combineAddMulh(N, DAG, Subtarget))
@@ -18122,6 +18191,8 @@ static SDValue performSUBCombine(SDNode *N, 
SelectionDAG &DAG,
     }
   }
 
+  if (SDValue V = combinePExtWideningAddSub(N, DAG, Subtarget))
+    return V;
   if (SDValue V = combineBinOpOfZExt(N, DAG))
     return V;
   if (SDValue V = combineSubShiftToOrcB(N, DAG, Subtarget))
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 06cf949cca56b..6727679f4875b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1879,6 +1879,16 @@ def riscv_pmulsu_halves_00
 def riscv_pmulsu_halves_11
     : RVSDNode<"PMULSU_HALVES_11", SDT_RISCVPackedWideningMulByHalves>;
 
+def SDT_RISCVPM2Halfword
+    : SDTypeProfile<1, 2, [SDTCisVT<0, v2i32>,
+                           SDTCisVT<1, v4i16>,
+                           SDTCisSameAs<1, 2>]>;
+def riscv_pm2add_h
+    : RVSDNode<"PM2ADD_H", SDT_RISCVPM2Halfword, [SDNPCommutative]>;
+def riscv_pm2addu_h
+    : RVSDNode<"PM2ADDU_H", SDT_RISCVPM2Halfword, [SDNPCommutative]>;
+def riscv_pm2sub_h : RVSDNode<"PM2SUB_H", SDT_RISCVPM2Halfword>;
+
 def SDT_RISCVWideningShiftLeft : SDTypeProfile<2, 2, [SDTCisVT<0, i32>,
                                                       SDTCisSameAs<0, 1>,
                                                       SDTCisSameAs<0, 2>,
@@ -2391,6 +2401,24 @@ let append Predicates = [IsRV32] in {
             (PACK zexti16:$rs1,
                   (XLenVT (PPAIRE_B zexti8:$op1rs1, GPR:$op1rs2)))>;
 
+  // Packed widening addition and subtraction patterns.
+  def : Pat<(v4i16 (add (sext (v4i8 GPR:$rs1)), (sext (v4i8 GPR:$rs2)))),
+            (PWADD_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (add (sext (v2i16 GPR:$rs1)), (sext (v2i16 GPR:$rs2)))),
+            (PWADD_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i16 (add (zext (v4i8 GPR:$rs1)), (zext (v4i8 GPR:$rs2)))),
+            (PWADDU_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (add (zext (v2i16 GPR:$rs1)), (zext (v2i16 GPR:$rs2)))),
+            (PWADDU_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i16 (sub (sext (v4i8 GPR:$rs1)), (sext (v4i8 GPR:$rs2)))),
+            (PWSUB_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (sub (sext (v2i16 GPR:$rs1)), (sext (v2i16 GPR:$rs2)))),
+            (PWSUB_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v4i16 (sub (zext (v4i8 GPR:$rs1)), (zext (v4i8 GPR:$rs2)))),
+            (PWSUBU_B GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (sub (zext (v2i16 GPR:$rs1)), (zext (v2i16 GPR:$rs2)))),
+            (PWSUBU_H GPR:$rs1, GPR:$rs2)>;
+
   // Packed widening multiply patterns.
   def : Pat<(v4i16 (riscv_pwmul (v4i8 GPR:$rs1), (v4i8 GPR:$rs2))),
             (PWMUL_B GPR:$rs1, GPR:$rs2)>;
@@ -2988,6 +3016,13 @@ let append Predicates = [IsRV64] in {
   def : Pat<(v2i32 (riscv_pmulsu_halves_00 (v4i16 GPR:$rs1), (v4i16 
GPR:$rs2))),
             (PMULSU_W_H00 GPR:$rs1, GPR:$rs2)>;
 
+  def : Pat<(v2i32 (riscv_pm2add_h (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
+            (PM2ADD_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (riscv_pm2addu_h (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
+            (PM2ADDU_H GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(v2i32 (riscv_pm2sub_h (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
+            (PM2SUB_H GPR:$rs1, GPR:$rs2)>;
+
   // 32-bit logical shift left/right patterns
   def : PatGprImm<riscv_pshl, PSLLI_W, uimm5, v2i32>;
   def : PatGprImm<riscv_psrl, PSRLI_W, uimm5, v2i32>;
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll 
b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
index f1209617b6a90..49b27f436543d 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
@@ -1356,7 +1356,153 @@ define <2 x i16> 
@test_pssha_s_i16x2_neg_imm_too_large(<2 x i16> %a) {
   ret <2 x i16> %res
 }
 
-; Test packed widening multiply signed for v4i8
+; Test packed widening addition and subtraction.
+define <4 x i16> @test_pwadd_b(<4 x i8> %a, <4 x i8> %b) {
+; RV32-LABEL: test_pwadd_b:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwadd.b a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwadd_b:
+; RV64:       # %bb.0:
+; RV64-NEXT:    zip8p a0, a0, a1
+; RV64-NEXT:    psrai.h a1, a0, 8
+; RV64-NEXT:    psext.h.b a0, a0
+; RV64-NEXT:    padd.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = sext <4 x i8> %a to <4 x i16>
+  %b_ext = sext <4 x i8> %b to <4 x i16>
+  %res = add <4 x i16> %a_ext, %b_ext
+  ret <4 x i16> %res
+}
+
+define <2 x i32> @test_pwadd_h(<2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: test_pwadd_h:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwadd.h a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwadd_h:
+; RV64:       # %bb.0:
+; RV64-NEXT:    zip16p a0, a0, a1
+; RV64-NEXT:    pli.h a1, 1
+; RV64-NEXT:    pm2add.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = sext <2 x i16> %a to <2 x i32>
+  %b_ext = sext <2 x i16> %b to <2 x i32>
+  %res = add <2 x i32> %a_ext, %b_ext
+  ret <2 x i32> %res
+}
+
+define <4 x i16> @test_pwaddu_b(<4 x i8> %a, <4 x i8> %b) {
+; RV32-LABEL: test_pwaddu_b:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwaddu.b a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwaddu_b:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pwcvtu.wb a0, a0
+; RV64-NEXT:    pwcvtu.wb a1, a1
+; RV64-NEXT:    padd.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = zext <4 x i8> %a to <4 x i16>
+  %b_ext = zext <4 x i8> %b to <4 x i16>
+  %res = add <4 x i16> %a_ext, %b_ext
+  ret <4 x i16> %res
+}
+
+define <2 x i32> @test_pwaddu_h(<2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: test_pwaddu_h:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwaddu.h a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwaddu_h:
+; RV64:       # %bb.0:
+; RV64-NEXT:    zip16p a0, a0, a1
+; RV64-NEXT:    pli.h a1, 1
+; RV64-NEXT:    pm2addu.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = zext <2 x i16> %a to <2 x i32>
+  %b_ext = zext <2 x i16> %b to <2 x i32>
+  %res = add <2 x i32> %a_ext, %b_ext
+  ret <2 x i32> %res
+}
+
+define <4 x i16> @test_pwsub_b(<4 x i8> %a, <4 x i8> %b) {
+; RV32-LABEL: test_pwsub_b:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwsub.b a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwsub_b:
+; RV64:       # %bb.0:
+; RV64-NEXT:    zip8p a0, a0, a1
+; RV64-NEXT:    psrai.h a1, a0, 8
+; RV64-NEXT:    psext.h.b a0, a0
+; RV64-NEXT:    psub.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = sext <4 x i8> %a to <4 x i16>
+  %b_ext = sext <4 x i8> %b to <4 x i16>
+  %res = sub <4 x i16> %a_ext, %b_ext
+  ret <4 x i16> %res
+}
+
+define <2 x i32> @test_pwsub_h(<2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: test_pwsub_h:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwsub.h a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwsub_h:
+; RV64:       # %bb.0:
+; RV64-NEXT:    zip16p a0, a0, a1
+; RV64-NEXT:    pli.h a1, 1
+; RV64-NEXT:    pm2sub.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = sext <2 x i16> %a to <2 x i32>
+  %b_ext = sext <2 x i16> %b to <2 x i32>
+  %res = sub <2 x i32> %a_ext, %b_ext
+  ret <2 x i32> %res
+}
+
+define <4 x i16> @test_pwsubu_b(<4 x i8> %a, <4 x i8> %b) {
+; RV32-LABEL: test_pwsubu_b:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwsubu.b a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwsubu_b:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pwcvtu.wb a0, a0
+; RV64-NEXT:    pwcvtu.wb a1, a1
+; RV64-NEXT:    psub.h a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = zext <4 x i8> %a to <4 x i16>
+  %b_ext = zext <4 x i8> %b to <4 x i16>
+  %res = sub <4 x i16> %a_ext, %b_ext
+  ret <4 x i16> %res
+}
+
+define <2 x i32> @test_pwsubu_h(<2 x i16> %a, <2 x i16> %b) {
+; RV32-LABEL: test_pwsubu_h:
+; RV32:       # %bb.0:
+; RV32-NEXT:    pwsubu.h a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_pwsubu_h:
+; RV64:       # %bb.0:
+; RV64-NEXT:    pwcvtu.wh a0, a0
+; RV64-NEXT:    pwcvtu.wh a1, a1
+; RV64-NEXT:    psub.w a0, a0, a1
+; RV64-NEXT:    ret
+  %a_ext = zext <2 x i16> %a to <2 x i32>
+  %b_ext = zext <2 x i16> %b to <2 x i32>
+  %res = sub <2 x i32> %a_ext, %b_ext
+  ret <2 x i32> %res
+}
+
 define <4 x i16> @test_pwmul_b(<4 x i8> %a, <4 x i8> %b) {
 ; RV32-LABEL: test_pwmul_b:
 ; RV32:       # %bb.0:
@@ -2408,10 +2554,10 @@ define <2 x i16> @test_select_v2i16(i1 %cond, <2 x i16> 
%a, <2 x i16> %b) {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    andi a3, a0, 1
 ; CHECK-NEXT:    mv a0, a1
-; CHECK-NEXT:    bnez a3, .LBB170_2
+; CHECK-NEXT:    bnez a3, [[SELECT_BB:.LBB[0-9]+_2]]
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    mv a0, a2
-; CHECK-NEXT:  .LBB170_2:
+; CHECK-NEXT:  [[SELECT_BB]]:
 ; CHECK-NEXT:    ret
   %res = select i1 %cond, <2 x i16> %a, <2 x i16> %b
   ret <2 x i16> %res
@@ -2422,10 +2568,10 @@ define <4 x i8> @test_select_v4i8(i1 %cond, <4 x i8> 
%a, <4 x i8> %b) {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    andi a3, a0, 1
 ; CHECK-NEXT:    mv a0, a1
-; CHECK-NEXT:    bnez a3, .LBB171_2
+; CHECK-NEXT:    bnez a3, [[SELECT_BB:.LBB[0-9]+_2]]
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    mv a0, a2
-; CHECK-NEXT:  .LBB171_2:
+; CHECK-NEXT:  [[SELECT_BB]]:
 ; CHECK-NEXT:    ret
   %res = select i1 %cond, <4 x i8> %a, <4 x i8> %b
   ret <4 x i8> %res

From a0d24919ac0662eb5b385af8e55c034fd64a9121 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <[email protected]>
Date: Fri, 28 Aug 2026 22:09:24 +0800
Subject: [PATCH 2/2] [RISCV] Simplify widening add/sub extend matching

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 794ac85f1cd78..ff9540d10463a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17992,13 +17992,11 @@ static SDValue combinePExtWideningAddSub(SDNode *N, 
SelectionDAG &DAG,
 
   SDValue N0 = N->getOperand(0);
   SDValue N1 = N->getOperand(1);
-  bool N0IsSExt = N0.getOpcode() == ISD::SIGN_EXTEND;
-  bool N0IsZExt = N0.getOpcode() == ISD::ZERO_EXTEND;
-  bool N1IsSExt = N1.getOpcode() == ISD::SIGN_EXTEND;
-  bool N1IsZExt = N1.getOpcode() == ISD::ZERO_EXTEND;
-  if (!(N0IsSExt || N0IsZExt) || !(N1IsSExt || N1IsZExt) || !N0.hasOneUse() ||
-      !N1.hasOneUse())
+  unsigned ExtendOpcode = N0.getOpcode();
+  if ((ExtendOpcode != ISD::SIGN_EXTEND && ExtendOpcode != ISD::ZERO_EXTEND) ||
+      N1.getOpcode() != ExtendOpcode || !N0.hasOneUse() || !N1.hasOneUse())
     return SDValue();
+  bool IsSExt = ExtendOpcode == ISD::SIGN_EXTEND;
 
   SDValue A = N0.getOperand(0);
   SDValue B = N1.getOperand(0);
@@ -18007,12 +18005,10 @@ static SDValue combinePExtWideningAddSub(SDNode *N, 
SelectionDAG &DAG,
   if (A.getValueType() != SrcVT || B.getValueType() != SrcVT)
     return SDValue();
 
-  if (VT == MVT::v4i16 && (!N0IsSExt || !N1IsSExt))
+  if (VT == MVT::v4i16 && !IsSExt)
     return SDValue();
 
-  bool IsPM2Halfword =
-      VT == MVT::v2i32 &&
-      ((N0IsSExt && N1IsSExt) || (Opcode == ISD::ADD && N0IsZExt && N1IsZExt));
+  bool IsPM2Halfword = VT == MVT::v2i32 && (IsSExt || Opcode == ISD::ADD);
   if (VT == MVT::v2i32 && !IsPM2Halfword)
     return SDValue();
 
@@ -18031,12 +18027,12 @@ static SDValue combinePExtWideningAddSub(SDNode *N, 
SelectionDAG &DAG,
   }
 
   SDValue Ones = DAG.getConstant(1, DL, LegalSrcVT);
-  if (N0IsSExt && N1IsSExt) {
+  if (IsSExt) {
     unsigned Opc = Opcode == ISD::ADD ? RISCVISD::PM2ADD_H : 
RISCVISD::PM2SUB_H;
     return DAG.getNode(Opc, DL, VT, Zip, Ones);
   }
 
-  if (Opcode == ISD::ADD && N0IsZExt && N1IsZExt)
+  if (Opcode == ISD::ADD)
     return DAG.getNode(RISCVISD::PM2ADDU_H, DL, VT, Zip, Ones);
 
   return SDValue();

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to