[llvm] 495816c - [RISCV] Add i16->i32 G_ZEXT/G_SEXT patterns for RV64.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 6 21:59:20 PST 2024


Author: Craig Topper
Date: 2024-12-06T21:49:35-08:00
New Revision: 495816cbc83b0760442568da18317df0955a289f

URL: https://github.com/llvm/llvm-project/commit/495816cbc83b0760442568da18317df0955a289f
DIFF: https://github.com/llvm/llvm-project/commit/495816cbc83b0760442568da18317df0955a289f.diff

LOG: [RISCV] Add i16->i32 G_ZEXT/G_SEXT patterns for RV64.

Because we support s16 and s32 types for FP some operations like
G_PHI, G_SELECT, G_FREEZE can exist with s16 and s32 operands
even when they will be assigned to the GPR reg bank. These
instructions can be surrounded with G_ZEXT and G_SEXT that convert
from s16 to s32 so we need to be able to select them.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVGISel.td
    llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb.ll
    llvm/test/CodeGen/RISCV/GlobalISel/rv64zbkb.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVGISel.td b/llvm/lib/Target/RISCV/RISCVGISel.td
index 361d3f3c7494cd..7cb419b610e603 100644
--- a/llvm/lib/Target/RISCV/RISCVGISel.td
+++ b/llvm/lib/Target/RISCV/RISCVGISel.td
@@ -223,17 +223,23 @@ let Predicates = [IsRV32, NoStdExtZbb, NoStdExtZbkb] in
 def : Pat<(XLenVT (zext (i16 GPR:$src))),
           (SRLI (XLenVT (SLLI GPR:$src, 16)), 16)>;
 
-let Predicates = [IsRV64, NoStdExtZbb, NoStdExtZbkb] in
+let Predicates = [IsRV64, NoStdExtZbb, NoStdExtZbkb] in {
 def : Pat<(i64 (zext (i16 GPR:$src))),
           (SRLI (XLenVT (SLLI GPR:$src, 48)), 48)>;
+def : Pat<(i32 (zext (i16 GPR:$src))),
+          (SRLI (XLenVT (SLLI GPR:$src, 48)), 48)>;
+}
 
 let Predicates = [IsRV32, NoStdExtZbb] in
 def : Pat<(XLenVT (sext (i16 GPR:$src))),
           (SRAI (XLenVT (SLLI GPR:$src, 16)), 16)>;
 
-let Predicates = [IsRV64, NoStdExtZbb] in
+let Predicates = [IsRV64, NoStdExtZbb] in {
 def : Pat<(i64 (sext (i16 GPR:$src))),
           (SRAI (XLenVT (SLLI GPR:$src, 48)), 48)>;
+def : Pat<(i32 (sext (i16 GPR:$src))),
+          (SRAI (XLenVT (SLLI GPR:$src, 48)), 48)>;
+}
 
 //===----------------------------------------------------------------------===//
 // Zb* RV64 patterns not used by SelectionDAG.
@@ -243,15 +249,21 @@ let Predicates = [HasStdExtZba, IsRV64] in {
 def : Pat<(zext (i32 GPR:$src)), (ADD_UW GPR:$src, (XLenVT X0))>;
 }
 
-let Predicates= [HasStdExtZbb] in
-def : Pat<(XLenVT (sext (i16 GPR:$rs))), (SEXT_H GPR:$rs)>;
+let Predicates = [HasStdExtZbb] in
+def : Pat<(i32 (sext (i16 GPR:$rs))), (SEXT_H GPR:$rs)>;
+let Predicates = [HasStdExtZbb, IsRV64] in
+def : Pat<(i64 (sext (i16 GPR:$rs))), (SEXT_H GPR:$rs)>;
 
 let Predicates = [HasStdExtZbb, IsRV32] in
 def : Pat<(i32 (zext (i16 GPR:$rs))), (ZEXT_H_RV32 GPR:$rs)>;
-let Predicates = [HasStdExtZbb, IsRV64] in
+let Predicates = [HasStdExtZbb, IsRV64] in {
 def : Pat<(i64 (zext (i16 GPR:$rs))), (ZEXT_H_RV64 GPR:$rs)>;
+def : Pat<(i32 (zext (i16 GPR:$rs))), (ZEXT_H_RV64 GPR:$rs)>;
+}
 
 let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32] in
 def : Pat<(i32 (zext (i16 GPR:$rs))), (PACK GPR:$rs, (XLenVT X0))>;
-let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in
+let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in {
 def : Pat<(i64 (zext (i16 GPR:$rs))), (PACKW GPR:$rs, (XLenVT X0))>;
+def : Pat<(i32 (zext (i16 GPR:$rs))), (PACKW GPR:$rs, (XLenVT X0))>;
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb.ll
index 16c588fa2f2ce5..25700b165e8ac8 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb.ll
@@ -1271,3 +1271,69 @@ define i64 @bswap_i64(i64 %a) {
   %1 = call i64 @llvm.bswap.i64(i64 %a)
   ret i64 %1
 }
+
+; This creates a i16->i32 G_ZEXT that we need to be able to select
+define i32 @zext_i16_i32(i1 %z, ptr %x, i32 %y) {
+; RV64I-LABEL: zext_i16_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    andi a3, a0, 1
+; RV64I-NEXT:    bnez a3, .LBB35_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    ret
+; RV64I-NEXT:  .LBB35_2:
+; RV64I-NEXT:    lh a0, 0(a1)
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBB-LABEL: zext_i16_i32:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    andi a3, a0, 1
+; RV64ZBB-NEXT:    bnez a3, .LBB35_2
+; RV64ZBB-NEXT:  # %bb.1:
+; RV64ZBB-NEXT:    mv a0, a2
+; RV64ZBB-NEXT:    ret
+; RV64ZBB-NEXT:  .LBB35_2:
+; RV64ZBB-NEXT:    lh a0, 0(a1)
+; RV64ZBB-NEXT:    zext.h a0, a0
+; RV64ZBB-NEXT:    ret
+  %w = load i16, ptr %x
+  %a = freeze i16 %w
+  %b = zext i16 %a to i32
+  %c = select i1 %z, i32 %b, i32 %y
+  ret i32 %c
+}
+
+; This creates a i16->i32 G_SEXT that we need to be able to select
+define i32 @sext_i16_i32(i1 %z, ptr %x, i32 %y) {
+; RV64I-LABEL: sext_i16_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    andi a3, a0, 1
+; RV64I-NEXT:    bnez a3, .LBB36_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    ret
+; RV64I-NEXT:  .LBB36_2:
+; RV64I-NEXT:    lh a0, 0(a1)
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srai a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBB-LABEL: sext_i16_i32:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    andi a3, a0, 1
+; RV64ZBB-NEXT:    bnez a3, .LBB36_2
+; RV64ZBB-NEXT:  # %bb.1:
+; RV64ZBB-NEXT:    mv a0, a2
+; RV64ZBB-NEXT:    ret
+; RV64ZBB-NEXT:  .LBB36_2:
+; RV64ZBB-NEXT:    lh a0, 0(a1)
+; RV64ZBB-NEXT:    sext.h a0, a0
+; RV64ZBB-NEXT:    ret
+  %w = load i16, ptr %x
+  %a = freeze i16 %w
+  %b = sext i16 %a to i32
+  %c = select i1 %z, i32 %b, i32 %y
+  ret i32 %c
+}

diff  --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbkb.ll
index 338476a1bec83f..09ee5caa12c1c0 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbkb.ll
@@ -442,3 +442,70 @@ define i64 @zext_i16_to_i64(i16 %a) nounwind {
   %1 = zext i16 %a to i64
   ret i64 %1
 }
+
+; This creates a i16->i32 G_ZEXT that we need to be able to select
+define i32 @zext_i16_i32_2(i1 %z, ptr %x, i32 %y) {
+; RV64I-LABEL: zext_i16_i32_2:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    andi a3, a0, 1
+; RV64I-NEXT:    bnez a3, .LBB20_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    ret
+; RV64I-NEXT:  .LBB20_2:
+; RV64I-NEXT:    lh a0, 0(a1)
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: zext_i16_i32_2:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    andi a3, a0, 1
+; RV64ZBKB-NEXT:    bnez a3, .LBB20_2
+; RV64ZBKB-NEXT:  # %bb.1:
+; RV64ZBKB-NEXT:    mv a0, a2
+; RV64ZBKB-NEXT:    ret
+; RV64ZBKB-NEXT:  .LBB20_2:
+; RV64ZBKB-NEXT:    lh a0, 0(a1)
+; RV64ZBKB-NEXT:    zext.h a0, a0
+; RV64ZBKB-NEXT:    ret
+  %w = load i16, ptr %x
+  %a = freeze i16 %w
+  %b = zext i16 %a to i32
+  %c = select i1 %z, i32 %b, i32 %y
+  ret i32 %c
+}
+
+; This creates a i16->i32 G_SEXT that we need to be able to select
+define i32 @sext_i16_i32(i1 %z, ptr %x, i32 %y) {
+; RV64I-LABEL: sext_i16_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    andi a3, a0, 1
+; RV64I-NEXT:    bnez a3, .LBB21_2
+; RV64I-NEXT:  # %bb.1:
+; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    ret
+; RV64I-NEXT:  .LBB21_2:
+; RV64I-NEXT:    lh a0, 0(a1)
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srai a0, a0, 48
+; RV64I-NEXT:    ret
+;
+; RV64ZBKB-LABEL: sext_i16_i32:
+; RV64ZBKB:       # %bb.0:
+; RV64ZBKB-NEXT:    andi a3, a0, 1
+; RV64ZBKB-NEXT:    bnez a3, .LBB21_2
+; RV64ZBKB-NEXT:  # %bb.1:
+; RV64ZBKB-NEXT:    mv a0, a2
+; RV64ZBKB-NEXT:    ret
+; RV64ZBKB-NEXT:  .LBB21_2:
+; RV64ZBKB-NEXT:    lh a0, 0(a1)
+; RV64ZBKB-NEXT:    slli a0, a0, 48
+; RV64ZBKB-NEXT:    srai a0, a0, 48
+; RV64ZBKB-NEXT:    ret
+  %w = load i16, ptr %x
+  %a = freeze i16 %w
+  %b = sext i16 %a to i32
+  %c = select i1 %z, i32 %b, i32 %y
+  ret i32 %c
+}


        


More information about the llvm-commits mailing list