Skip to content

Commit 5d1f27f

Browse files
authored
GlobalISel: neg (and x, 1) --> SIGN_EXTEND_INREG x, 1 (#131367)
The pattern ```LLVM %shl = shl i32 %x, 31 %ashr = ashr i32 %shl, 31 ``` would be combined to `G_EXT_INREG %x, 1` by GlobalISel. However InstCombine normalizes this pattern to: ```LLVM %and = and i32 %x, 1 %neg = sub i32 0, %and ``` This adds a combiner for this variant as well.
1 parent 46457ed commit 5d1f27f

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,17 @@ def shl_ashr_to_sext_inreg : GICombineRule<
747747
(apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}])
748748
>;
749749

750+
// Fold sub 0, (and x, 1) -> sext_inreg x, 1
751+
def neg_and_one_to_sext_inreg : GICombineRule<
752+
(defs root:$dst),
753+
(match (G_AND $and, $x, 1),
754+
(G_SUB $dst, 0, $and),
755+
[{ return MRI.hasOneNonDBGUse(${and}.getReg()) &&
756+
Helper.isLegalOrBeforeLegalizer(
757+
{TargetOpcode::G_SEXT_INREG, {MRI.getType(${x}.getReg())}}); }]),
758+
(apply (G_SEXT_INREG $dst, $x, 1))
759+
>;
760+
750761
// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
751762
def overlapping_and: GICombineRule <
752763
(defs root:$root, build_fn_matchinfo:$info),
@@ -2013,7 +2024,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
20132024
undef_combines, identity_combines, phi_combines,
20142025
simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big,
20152026
reassocs, ptr_add_immed_chain, cmp_combines,
2016-
shl_ashr_to_sext_inreg, sext_inreg_of_load,
2027+
shl_ashr_to_sext_inreg, neg_and_one_to_sext_inreg, sext_inreg_of_load,
20172028
width_reduction_combines, select_combines,
20182029
known_bits_simplifications, trunc_shift,
20192030
not_cmp_fold, opt_brcond_by_inverting_cond,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -o - -mtriple aarch64-- -run-pass=aarch64-prelegalizer-combiner %s | FileCheck %s
3+
---
4+
name: test_combine_neg_and_one_to_sext_inreg_s32
5+
body: |
6+
bb.1:
7+
liveins: $w0
8+
; CHECK-LABEL: name: test_combine_neg_and_one_to_sext_inreg_s32
9+
; CHECK: liveins: $w0
10+
; CHECK-NEXT: {{ $}}
11+
; CHECK-NEXT: %x:_(s32) = COPY $w0
12+
; CHECK-NEXT: %res:_(s32) = G_SEXT_INREG %x, 1
13+
; CHECK-NEXT: $w0 = COPY %res(s32)
14+
%x:_(s32) = COPY $w0
15+
%one:_(s32) = G_CONSTANT i32 1
16+
%zero:_(s32) = G_CONSTANT i32 0
17+
%and:_(s32) = G_AND %x:_, %one:_
18+
%res:_(s32) = G_SUB %zero:_, %and:_
19+
$w0 = COPY %res:_(s32)
20+
...
21+
---
22+
name: test_combine_neg_and_one_to_sext_inreg_s64
23+
body: |
24+
bb.1:
25+
liveins: $x0
26+
; CHECK-LABEL: name: test_combine_neg_and_one_to_sext_inreg_s64
27+
; CHECK: liveins: $x0
28+
; CHECK-NEXT: {{ $}}
29+
; CHECK-NEXT: %x:_(s64) = COPY $x0
30+
; CHECK-NEXT: %res:_(s64) = G_SEXT_INREG %x, 1
31+
; CHECK-NEXT: $x0 = COPY %res(s64)
32+
%x:_(s64) = COPY $x0
33+
%one:_(s64) = G_CONSTANT i64 1
34+
%zero:_(s64) = G_CONSTANT i64 0
35+
%and:_(s64) = G_AND %x:_, %one:_
36+
%res:_(s64) = G_SUB %zero:_, %and:_
37+
$x0 = COPY %res:_(s64)
38+
...
39+
---
40+
name: test_combine_neg_and_one_to_sext_inreg_multiuse_should_not_transform
41+
body: |
42+
bb.1:
43+
liveins: $x0
44+
; CHECK-LABEL: name: test_combine_neg_and_one_to_sext_inreg_multiuse_should_not_transform
45+
; CHECK: liveins: $x0
46+
; CHECK-NEXT: {{ $}}
47+
; CHECK-NEXT: %x:_(s64) = COPY $x0
48+
; CHECK-NEXT: %one:_(s64) = G_CONSTANT i64 1
49+
; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
50+
; CHECK-NEXT: %and:_(s64) = G_AND %x, %one
51+
; CHECK-NEXT: %res:_(s64) = G_SUB %zero, %and
52+
; CHECK-NEXT: $x0 = COPY %res(s64)
53+
; CHECK-NEXT: $x1 = COPY %and(s64)
54+
%x:_(s64) = COPY $x0
55+
%one:_(s64) = G_CONSTANT i64 1
56+
%zero:_(s64) = G_CONSTANT i64 0
57+
%and:_(s64) = G_AND %x:_, %one:_
58+
%res:_(s64) = G_SUB %zero:_, %and:_
59+
$x0 = COPY %res:_(s64)
60+
$x1 = COPY %and:_(s64)
61+
...
62+
---
63+
name: test_combine_neg_and_one_to_sext_inreg_v2i32
64+
body: |
65+
bb.1:
66+
liveins: $d0
67+
; CHECK-LABEL: name: test_combine_neg_and_one_to_sext_inreg_v2i32
68+
; CHECK: liveins: $d0
69+
; CHECK-NEXT: {{ $}}
70+
; CHECK-NEXT: %x:_(<2 x s32>) = COPY $d0
71+
; CHECK-NEXT: %res:_(<2 x s32>) = G_SEXT_INREG %x, 1
72+
; CHECK-NEXT: $d0 = COPY %res(<2 x s32>)
73+
%x:_(<2 x s32>) = COPY $d0
74+
%one:_(s32) = G_CONSTANT i32 1
75+
%ones:_(<2 x s32>) = G_BUILD_VECTOR %one, %one
76+
%zero:_(s32) = G_CONSTANT i32 0
77+
%zeros:_(<2 x s32>) = G_BUILD_VECTOR %zero, %zero
78+
%and:_(<2 x s32>) = G_AND %x:_, %ones:_
79+
%res:_(<2 x s32>) = G_SUB %zeros:_, %and:_
80+
$d0 = COPY %res:_(<2 x s32>)
81+
...

0 commit comments

Comments
 (0)