[llvm] c249a9a - [GISel] Funnel shift combiner port from SelectionDAG ISel to GlobalISel (#135132)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 27 21:50:44 PDT 2025
Author: Axel Sorenson
Date: 2025-08-27T21:50:40-07:00
New Revision: c249a9ab62df716e1c7aa553bc2477233d07bc15
URL: https://github.com/llvm/llvm-project/commit/c249a9ab62df716e1c7aa553bc2477233d07bc15
DIFF: https://github.com/llvm/llvm-project/commit/c249a9ab62df716e1c7aa553bc2477233d07bc15.diff
LOG: [GISel] Funnel shift combiner port from SelectionDAG ISel to GlobalISel (#135132)
The funnel shift combiner rule from
https://github.com/llvm/llvm-project/commit/4a3708cd6b062a6afe2697cc8b39329e3f2faa25
is currently missing from GlobalISel. The following is a port of that
combiner to GlobalISel.
Added:
Modified:
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/test/CodeGen/AArch64/funnel-shift.ll
llvm/test/CodeGen/RISCV/GlobalISel/shift.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 9564b581c5ebb..1b7c1235c9805 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1040,6 +1040,34 @@ def funnel_shift_overshift: GICombineRule<
(apply [{ Helper.applyFunnelShiftConstantModulo(*${root}); }])
>;
+// Transform: fshl x, z, y | shl x, y -> fshl x, z, y
+// Transform: shl x, y | fshl x, z, y -> fshl x, z, y
+// FIXME: TableGen didn't handle G_OR commutativity on its own,
+// necessitating the use of !foreach to handle it manually.
+def funnel_shift_or_shift_to_funnel_shift_left_frags : GICombinePatFrag<
+ (outs root: $dst, $out1, $out2), (ins),
+ !foreach(inst, [(G_OR $dst, $out1, $out2), (G_OR $dst, $out2, $out1)],
+ (pattern (G_FSHL $out1, $x, $z, $y), (G_SHL $out2, $x, $y), inst))>;
+def funnel_shift_or_shift_to_funnel_shift_left: GICombineRule<
+ (defs root:$root),
+ (match (funnel_shift_or_shift_to_funnel_shift_left_frags $root, $out1, $out2)),
+ (apply (GIReplaceReg $root, $out1))
+>;
+
+// Transform: fshr z, x, y | srl x, y -> fshr z, x, y
+// Transform: srl x, y | fshr z, x, y -> fshr z, x, y
+// FIXME: TableGen didn't handle G_OR commutativity on its own,
+// necessitating the use of !foreach to handle it manually.
+def funnel_shift_or_shift_to_funnel_shift_right_frags : GICombinePatFrag<
+ (outs root: $dst, $out1, $out2), (ins),
+ !foreach(inst, [(G_OR $dst, $out1, $out2), (G_OR $dst, $out2, $out1)],
+ (pattern (G_FSHR $out1, $z, $x, $y), (G_LSHR $out2, $x, $y), inst))>;
+def funnel_shift_or_shift_to_funnel_shift_right: GICombineRule<
+ (defs root:$root),
+ (match (funnel_shift_or_shift_to_funnel_shift_right_frags $root, $out1, $out2)),
+ (apply (GIReplaceReg $root, $out1))
+>;
+
def rotate_out_of_range : GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_ROTR, G_ROTL):$root,
@@ -1112,7 +1140,9 @@ def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift,
funnel_shift_to_rotate,
funnel_shift_right_zero,
funnel_shift_left_zero,
- funnel_shift_overshift]>;
+ funnel_shift_overshift,
+ funnel_shift_or_shift_to_funnel_shift_left,
+ funnel_shift_or_shift_to_funnel_shift_right]>;
def bitfield_extract_from_sext_inreg : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
diff --git a/llvm/test/CodeGen/AArch64/funnel-shift.ll b/llvm/test/CodeGen/AArch64/funnel-shift.ll
index e5aa360f804c1..f9fd2ad1b5b6c 100644
--- a/llvm/test/CodeGen/AArch64/funnel-shift.ll
+++ b/llvm/test/CodeGen/AArch64/funnel-shift.ll
@@ -674,14 +674,12 @@ define i32 @or_shl_fshl_simplify(i32 %x, i32 %y, i32 %s) {
; CHECK-GI-LABEL: or_shl_fshl_simplify:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, #31 // =0x1f
-; CHECK-GI-NEXT: and w9, w2, #0x1f
-; CHECK-GI-NEXT: lsr w10, w0, #1
-; CHECK-GI-NEXT: lsl w11, w1, w2
+; CHECK-GI-NEXT: lsr w9, w0, #1
+; CHECK-GI-NEXT: and w10, w2, #0x1f
; CHECK-GI-NEXT: bic w8, w8, w2
-; CHECK-GI-NEXT: lsl w9, w1, w9
-; CHECK-GI-NEXT: lsr w8, w10, w8
-; CHECK-GI-NEXT: orr w9, w9, w11
-; CHECK-GI-NEXT: orr w0, w9, w8
+; CHECK-GI-NEXT: lsl w10, w1, w10
+; CHECK-GI-NEXT: lsr w8, w9, w8
+; CHECK-GI-NEXT: orr w0, w10, w8
; CHECK-GI-NEXT: ret
%shy = shl i32 %y, %s
%fun = call i32 @llvm.fshl.i32(i32 %y, i32 %x, i32 %s)
@@ -702,14 +700,12 @@ define i32 @or_lshr_fshr_simplify(i32 %x, i32 %y, i32 %s) {
; CHECK-GI-LABEL: or_lshr_fshr_simplify:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, #31 // =0x1f
-; CHECK-GI-NEXT: and w9, w2, #0x1f
-; CHECK-GI-NEXT: lsl w10, w0, #1
-; CHECK-GI-NEXT: lsr w11, w1, w2
+; CHECK-GI-NEXT: lsl w9, w0, #1
+; CHECK-GI-NEXT: and w10, w2, #0x1f
; CHECK-GI-NEXT: bic w8, w8, w2
-; CHECK-GI-NEXT: lsr w9, w1, w9
-; CHECK-GI-NEXT: lsl w8, w10, w8
-; CHECK-GI-NEXT: orr w9, w11, w9
-; CHECK-GI-NEXT: orr w0, w9, w8
+; CHECK-GI-NEXT: lsl w8, w9, w8
+; CHECK-GI-NEXT: lsr w9, w1, w10
+; CHECK-GI-NEXT: orr w0, w8, w9
; CHECK-GI-NEXT: ret
%shy = lshr i32 %y, %s
%fun = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %s)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll b/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll
index 75e318a58fd45..776eaedb2a5cc 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/shift.ll
@@ -105,3 +105,51 @@ define i16 @test_shl_i48_2(i48 %x, i48 %y) {
%trunc = trunc i48 %shl to i16
ret i16 %trunc
}
+
+define i32 @test_fshl_i32(i32 %x, i32 %_, i32 %y) {
+; RV32-LABEL: test_fshl_i32:
+; RV32: # %bb.0:
+; RV32-NEXT: not a3, a2
+; RV32-NEXT: sll a0, a0, a2
+; RV32-NEXT: srli a1, a1, 1
+; RV32-NEXT: srl a1, a1, a3
+; RV32-NEXT: or a0, a0, a1
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_fshl_i32:
+; RV64: # %bb.0:
+; RV64-NEXT: not a3, a2
+; RV64-NEXT: sllw a0, a0, a2
+; RV64-NEXT: srliw a1, a1, 1
+; RV64-NEXT: srlw a1, a1, a3
+; RV64-NEXT: or a0, a0, a1
+; RV64-NEXT: ret
+ %fshl = call i32 @llvm.fshl.i32(i32 %x, i32 %_, i32 %y)
+ %shl = shl i32 %x, %y
+ %or = or i32 %fshl, %shl
+ ret i32 %or
+}
+
+define i32 @test_fshr_i32(i32 %_, i32 %x, i32 %y) {
+; RV32-LABEL: test_fshr_i32:
+; RV32: # %bb.0:
+; RV32-NEXT: not a3, a2
+; RV32-NEXT: slli a0, a0, 1
+; RV32-NEXT: sll a0, a0, a3
+; RV32-NEXT: srl a1, a1, a2
+; RV32-NEXT: or a0, a0, a1
+; RV32-NEXT: ret
+;
+; RV64-LABEL: test_fshr_i32:
+; RV64: # %bb.0:
+; RV64-NEXT: not a3, a2
+; RV64-NEXT: slli a0, a0, 1
+; RV64-NEXT: sllw a0, a0, a3
+; RV64-NEXT: srlw a1, a1, a2
+; RV64-NEXT: or a0, a0, a1
+; RV64-NEXT: ret
+ %fshr = call i32 @llvm.fshr.i32(i32 %_, i32 %x, i32 %y)
+ %lshr = lshr i32 %x, %y
+ %or = or i32 %lshr, %fshr
+ ret i32 %or
+}
More information about the llvm-commits
mailing list