Skip to content

Commit c249a9a

Browse files
authored
[GISel] Funnel shift combiner port from SelectionDAG ISel to GlobalISel (#135132)
The funnel shift combiner rule from 4a3708c is currently missing from GlobalISel. The following is a port of that combiner to GlobalISel.
1 parent 5fdd3a1 commit c249a9a

File tree

3 files changed

+89
-15
lines changed

3 files changed

+89
-15
lines changed

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,34 @@ def funnel_shift_overshift: GICombineRule<
10401040
(apply [{ Helper.applyFunnelShiftConstantModulo(*${root}); }])
10411041
>;
10421042

1043+
// Transform: fshl x, z, y | shl x, y -> fshl x, z, y
1044+
// Transform: shl x, y | fshl x, z, y -> fshl x, z, y
1045+
// FIXME: TableGen didn't handle G_OR commutativity on its own,
1046+
// necessitating the use of !foreach to handle it manually.
1047+
def funnel_shift_or_shift_to_funnel_shift_left_frags : GICombinePatFrag<
1048+
(outs root: $dst, $out1, $out2), (ins),
1049+
!foreach(inst, [(G_OR $dst, $out1, $out2), (G_OR $dst, $out2, $out1)],
1050+
(pattern (G_FSHL $out1, $x, $z, $y), (G_SHL $out2, $x, $y), inst))>;
1051+
def funnel_shift_or_shift_to_funnel_shift_left: GICombineRule<
1052+
(defs root:$root),
1053+
(match (funnel_shift_or_shift_to_funnel_shift_left_frags $root, $out1, $out2)),
1054+
(apply (GIReplaceReg $root, $out1))
1055+
>;
1056+
1057+
// Transform: fshr z, x, y | srl x, y -> fshr z, x, y
1058+
// Transform: srl x, y | fshr z, x, y -> fshr z, x, y
1059+
// FIXME: TableGen didn't handle G_OR commutativity on its own,
1060+
// necessitating the use of !foreach to handle it manually.
1061+
def funnel_shift_or_shift_to_funnel_shift_right_frags : GICombinePatFrag<
1062+
(outs root: $dst, $out1, $out2), (ins),
1063+
!foreach(inst, [(G_OR $dst, $out1, $out2), (G_OR $dst, $out2, $out1)],
1064+
(pattern (G_FSHR $out1, $z, $x, $y), (G_LSHR $out2, $x, $y), inst))>;
1065+
def funnel_shift_or_shift_to_funnel_shift_right: GICombineRule<
1066+
(defs root:$root),
1067+
(match (funnel_shift_or_shift_to_funnel_shift_right_frags $root, $out1, $out2)),
1068+
(apply (GIReplaceReg $root, $out1))
1069+
>;
1070+
10431071
def rotate_out_of_range : GICombineRule<
10441072
(defs root:$root),
10451073
(match (wip_match_opcode G_ROTR, G_ROTL):$root,
@@ -1112,7 +1140,9 @@ def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift,
11121140
funnel_shift_to_rotate,
11131141
funnel_shift_right_zero,
11141142
funnel_shift_left_zero,
1115-
funnel_shift_overshift]>;
1143+
funnel_shift_overshift,
1144+
funnel_shift_or_shift_to_funnel_shift_left,
1145+
funnel_shift_or_shift_to_funnel_shift_right]>;
11161146

11171147
def bitfield_extract_from_sext_inreg : GICombineRule<
11181148
(defs root:$root, build_fn_matchinfo:$info),

llvm/test/CodeGen/AArch64/funnel-shift.ll

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -674,14 +674,12 @@ define i32 @or_shl_fshl_simplify(i32 %x, i32 %y, i32 %s) {
674674
; CHECK-GI-LABEL: or_shl_fshl_simplify:
675675
; CHECK-GI: // %bb.0:
676676
; CHECK-GI-NEXT: mov w8, #31 // =0x1f
677-
; CHECK-GI-NEXT: and w9, w2, #0x1f
678-
; CHECK-GI-NEXT: lsr w10, w0, #1
679-
; CHECK-GI-NEXT: lsl w11, w1, w2
677+
; CHECK-GI-NEXT: lsr w9, w0, #1
678+
; CHECK-GI-NEXT: and w10, w2, #0x1f
680679
; CHECK-GI-NEXT: bic w8, w8, w2
681-
; CHECK-GI-NEXT: lsl w9, w1, w9
682-
; CHECK-GI-NEXT: lsr w8, w10, w8
683-
; CHECK-GI-NEXT: orr w9, w9, w11
684-
; CHECK-GI-NEXT: orr w0, w9, w8
680+
; CHECK-GI-NEXT: lsl w10, w1, w10
681+
; CHECK-GI-NEXT: lsr w8, w9, w8
682+
; CHECK-GI-NEXT: orr w0, w10, w8
685683
; CHECK-GI-NEXT: ret
686684
%shy = shl i32 %y, %s
687685
%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) {
702700
; CHECK-GI-LABEL: or_lshr_fshr_simplify:
703701
; CHECK-GI: // %bb.0:
704702
; CHECK-GI-NEXT: mov w8, #31 // =0x1f
705-
; CHECK-GI-NEXT: and w9, w2, #0x1f
706-
; CHECK-GI-NEXT: lsl w10, w0, #1
707-
; CHECK-GI-NEXT: lsr w11, w1, w2
703+
; CHECK-GI-NEXT: lsl w9, w0, #1
704+
; CHECK-GI-NEXT: and w10, w2, #0x1f
708705
; CHECK-GI-NEXT: bic w8, w8, w2
709-
; CHECK-GI-NEXT: lsr w9, w1, w9
710-
; CHECK-GI-NEXT: lsl w8, w10, w8
711-
; CHECK-GI-NEXT: orr w9, w11, w9
712-
; CHECK-GI-NEXT: orr w0, w9, w8
706+
; CHECK-GI-NEXT: lsl w8, w9, w8
707+
; CHECK-GI-NEXT: lsr w9, w1, w10
708+
; CHECK-GI-NEXT: orr w0, w8, w9
713709
; CHECK-GI-NEXT: ret
714710
%shy = lshr i32 %y, %s
715711
%fun = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %s)

llvm/test/CodeGen/RISCV/GlobalISel/shift.ll

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,51 @@ define i16 @test_shl_i48_2(i48 %x, i48 %y) {
105105
%trunc = trunc i48 %shl to i16
106106
ret i16 %trunc
107107
}
108+
109+
define i32 @test_fshl_i32(i32 %x, i32 %_, i32 %y) {
110+
; RV32-LABEL: test_fshl_i32:
111+
; RV32: # %bb.0:
112+
; RV32-NEXT: not a3, a2
113+
; RV32-NEXT: sll a0, a0, a2
114+
; RV32-NEXT: srli a1, a1, 1
115+
; RV32-NEXT: srl a1, a1, a3
116+
; RV32-NEXT: or a0, a0, a1
117+
; RV32-NEXT: ret
118+
;
119+
; RV64-LABEL: test_fshl_i32:
120+
; RV64: # %bb.0:
121+
; RV64-NEXT: not a3, a2
122+
; RV64-NEXT: sllw a0, a0, a2
123+
; RV64-NEXT: srliw a1, a1, 1
124+
; RV64-NEXT: srlw a1, a1, a3
125+
; RV64-NEXT: or a0, a0, a1
126+
; RV64-NEXT: ret
127+
%fshl = call i32 @llvm.fshl.i32(i32 %x, i32 %_, i32 %y)
128+
%shl = shl i32 %x, %y
129+
%or = or i32 %fshl, %shl
130+
ret i32 %or
131+
}
132+
133+
define i32 @test_fshr_i32(i32 %_, i32 %x, i32 %y) {
134+
; RV32-LABEL: test_fshr_i32:
135+
; RV32: # %bb.0:
136+
; RV32-NEXT: not a3, a2
137+
; RV32-NEXT: slli a0, a0, 1
138+
; RV32-NEXT: sll a0, a0, a3
139+
; RV32-NEXT: srl a1, a1, a2
140+
; RV32-NEXT: or a0, a0, a1
141+
; RV32-NEXT: ret
142+
;
143+
; RV64-LABEL: test_fshr_i32:
144+
; RV64: # %bb.0:
145+
; RV64-NEXT: not a3, a2
146+
; RV64-NEXT: slli a0, a0, 1
147+
; RV64-NEXT: sllw a0, a0, a3
148+
; RV64-NEXT: srlw a1, a1, a2
149+
; RV64-NEXT: or a0, a0, a1
150+
; RV64-NEXT: ret
151+
%fshr = call i32 @llvm.fshr.i32(i32 %_, i32 %x, i32 %y)
152+
%lshr = lshr i32 %x, %y
153+
%or = or i32 %lshr, %fshr
154+
ret i32 %or
155+
}

0 commit comments

Comments
 (0)