[llvm] 1bde29e - [GlobalISel] Add `combine_or_of_and` from SelectionDAG (#198754)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 03:12:27 PDT 2026
Author: Osman Yasar
Date: 2026-06-03T11:12:22+01:00
New Revision: 1bde29e83bc4d077d9f553d89846c4eba402f3e6
URL: https://github.com/llvm/llvm-project/commit/1bde29e83bc4d077d9f553d89846c4eba402f3e6
DIFF: https://github.com/llvm/llvm-project/commit/1bde29e83bc4d077d9f553d89846c4eba402f3e6.diff
LOG: [GlobalISel] Add `combine_or_of_and` from SelectionDAG (#198754)
This PR adds the pattern `// fold or (and x, y), x --> x` from
SelectionDAG.
Added:
llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.ll
llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.mir
Modified:
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir
Removed:
################################################################################
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 5f8213d9c7ec3..5c3dca9cd6e23 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2165,6 +2165,23 @@ def add_shift : GICombineRule<
(apply (G_SHL $new_shl, $y, $n),
(G_SUB $dst, $x, $new_shl))>;
+// FIXME: Tablegen should be able to handle commutativity of G_AND and G_OR.
+// Remove once commutativity is handled automatically.
+def combine_or_of_and_frags : GICombinePatFrag<
+ (outs root: $dst), (ins $x, $y),
+ [
+ (pattern (G_AND $and, $x, $y), (G_OR $dst, $and, $x)),
+ (pattern (G_AND $and, $y, $x), (G_OR $dst, $and, $x)),
+ (pattern (G_AND $and, $x, $y), (G_OR $dst, $x, $and)),
+ (pattern (G_AND $and, $y, $x), (G_OR $dst, $x, $and))
+ ]>;
+
+// fold or (and x, y), x --> x
+def combine_or_of_and: GICombineRule<
+ (defs root:$dst),
+ (match (combine_or_of_and_frags $dst, $x, $y)),
+ (apply (GIReplaceReg $dst, $x))>;
+
def freeze_of_non_undef_non_poison : GICombineRule<
(defs root:$root),
(match (G_FREEZE $root, $src),
@@ -2471,7 +2488,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
truncsat_combines, lshr_of_trunc_of_lshr, ctls_combines, add_shift, sub_one_from_sub,
binop_with_neg, sub_minus_one, sub_of_mul_const,
avgfloor_u_match, avgfloor_s_match,
- avgceil_u_match, avgceil_s_match]>;
+ avgceil_u_match, avgceil_s_match, combine_or_of_and]>;
// A combine group used to for prelegalizer combiners at -O0. The combines in
// this group have been selected based on experiments to balance code size and
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.ll
new file mode 100644
index 0000000000000..32293c73df48c
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.ll
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -global-isel=0 -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -global-isel=1 -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+define i64 @or_and_xy_x(i64 %x, i64 %y) {
+; CHECK-LABEL: or_and_xy_x:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(and(x, y), x) -> x
+ %and = and i64 %x, %y
+ %or = or i64 %and, %x
+ ret i64 %or
+}
+
+define i64 @or_and_yx_x(i64 %x, i64 %y) {
+; CHECK-LABEL: or_and_yx_x:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(and(y, x), x) -> x
+ %and = and i64 %y, %x
+ %or = or i64 %and, %x
+ ret i64 %or
+}
+
+define i64 @or_x_and_xy(i64 %x, i64 %y) {
+; CHECK-LABEL: or_x_and_xy:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(x, and(x, y)) -> x
+ %and = and i64 %x, %y
+ %or = or i64 %x, %and
+ ret i64 %or
+}
+
+define i64 @or_x_and_yx(i64 %x, i64 %y) {
+; CHECK-LABEL: or_x_and_yx:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(x, and(y, x)) -> x
+ %and = and i64 %y, %x
+ %or = or i64 %x, %and
+ ret i64 %or
+}
+
+define <4 x i16> @or_and_xy_x_vector(<4 x i16> %x, <4 x i16> %y) {
+; CHECK-LABEL: or_and_xy_x_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(and(x, y), x) -> x
+ %and = and <4 x i16> %x, %y
+ %or = or <4 x i16> %and, %x
+ ret <4 x i16> %or
+}
+
+define <4 x i16> @or_and_yx_x_vector(<4 x i16> %x, <4 x i16> %y) {
+; CHECK-LABEL: or_and_yx_x_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(and(y, x), x) -> x
+ %and = and <4 x i16> %y, %x
+ %or = or <4 x i16> %and, %x
+ ret <4 x i16> %or
+}
+
+define <4 x i16> @or_x_and_xy_vector(<4 x i16> %x, <4 x i16> %y) {
+; CHECK-LABEL: or_x_and_xy_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(x, and(x, y)) -> x
+ %and = and <4 x i16> %x, %y
+ %or = or <4 x i16> %x, %and
+ ret <4 x i16> %or
+}
+
+define <4 x i16> @or_x_and_yx_vector(<4 x i16> %x, <4 x i16> %y) {
+; CHECK-LABEL: or_x_and_yx_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ret
+entry:
+; fold or(x, and(y, x)) -> x
+ %and = and <4 x i16> %y, %x
+ %or = or <4 x i16> %x, %and
+ ret <4 x i16> %or
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.mir
new file mode 100644
index 0000000000000..189c57269a1e0
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-of-and.mir
@@ -0,0 +1,161 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
+
+---
+name: combine_or_of_and
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1
+
+ ; CHECK-LABEL: name: combine_or_of_and
+ ; CHECK: liveins: $x0, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x0 = COPY %x(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %x:_(s64) = COPY $x0
+ %y:_(s64) = COPY $x1
+ %and:_(s64) = G_AND %x, %y
+ %dst:_(s64) = G_OR %and, %x
+ $x0 = COPY %dst
+ RET_ReallyLR implicit $x0
+...
+---
+name: combine_or_of_and_commuted
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1
+
+ ; CHECK-LABEL: name: combine_or_of_and_commuted
+ ; CHECK: liveins: $x0, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x0 = COPY %x(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %x:_(s64) = COPY $x0
+ %y:_(s64) = COPY $x1
+ %and:_(s64) = G_AND %y, %x
+ %dst:_(s64) = G_OR %and, %x
+ $x0 = COPY %dst
+ RET_ReallyLR implicit $x0
+...
+---
+name: combine_or_of_and_commuted2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1
+ ; CHECK-LABEL: name: combine_or_of_and_commuted2
+ ; CHECK: liveins: $x0, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x0 = COPY %x(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %x:_(s64) = COPY $x0
+ %y:_(s64) = COPY $x1
+ %and:_(s64) = G_AND %x, %y
+ %dst:_(s64) = G_OR %x, %and
+ $x0 = COPY %dst
+ RET_ReallyLR implicit $x0
+...
+---
+name: combine_or_of_and_commuted3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1
+ ; CHECK-LABEL: name: combine_or_of_and_commuted3
+ ; CHECK: liveins: $x0, $x1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x0 = COPY %x(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %x:_(s64) = COPY $x0
+ %y:_(s64) = COPY $x1
+ %and:_(s64) = G_AND %y, %x
+ %dst:_(s64) = G_OR %x, %and
+ $x0 = COPY %dst
+ RET_ReallyLR implicit $x0
+...
+---
+name: combine_or_of_and_vector
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1
+
+ ; CHECK-LABEL: name: combine_or_of_and_vector
+ ; CHECK: liveins: $d0, $d1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s16>) = COPY $d0
+ ; CHECK-NEXT: $d0 = COPY %x(<4 x s16>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %x:_(<4 x s16>) = COPY $d0
+ %y:_(<4 x s16>) = COPY $d1
+ %and:_(<4 x s16>) = G_AND %x, %y
+ %dst:_(<4 x s16>) = G_OR %and, %x
+ $d0 = COPY %dst
+ RET_ReallyLR implicit $d0
+...
+---
+name: combine_or_of_and_vector_commuted
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1
+
+ ; CHECK-LABEL: name: combine_or_of_and_vector_commuted
+ ; CHECK: liveins: $d0, $d1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s16>) = COPY $d0
+ ; CHECK-NEXT: $d0 = COPY %x(<4 x s16>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %x:_(<4 x s16>) = COPY $d0
+ %y:_(<4 x s16>) = COPY $d1
+ %and:_(<4 x s16>) = G_AND %y, %x
+ %dst:_(<4 x s16>) = G_OR %and, %x
+ $d0 = COPY %dst
+ RET_ReallyLR implicit $d0
+...
+---
+name: combine_or_of_and_vector_commuted2
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1
+
+ ; CHECK-LABEL: name: combine_or_of_and_vector_commuted2
+ ; CHECK: liveins: $d0, $d1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s16>) = COPY $d0
+ ; CHECK-NEXT: $d0 = COPY %x(<4 x s16>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %x:_(<4 x s16>) = COPY $d0
+ %y:_(<4 x s16>) = COPY $d1
+ %and:_(<4 x s16>) = G_AND %x, %y
+ %dst:_(<4 x s16>) = G_OR %x, %and
+ $d0 = COPY %dst
+ RET_ReallyLR implicit $d0
+...
+---
+name: combine_or_of_and_vector_commuted3
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $d0, $d1
+
+ ; CHECK-LABEL: name: combine_or_of_and_vector_commuted3
+ ; CHECK: liveins: $d0, $d1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s16>) = COPY $d0
+ ; CHECK-NEXT: $d0 = COPY %x(<4 x s16>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $d0
+ %x:_(<4 x s16>) = COPY $d0
+ %y:_(<4 x s16>) = COPY $d1
+ %and:_(<4 x s16>) = G_AND %y, %x
+ %dst:_(<4 x s16>) = G_OR %x, %and
+ $d0 = COPY %dst
+ RET_ReallyLR implicit $d0
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir
index 7867d54b0727f..e59d308fbafa6 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-narrow-binop-feeding-add.mir
@@ -260,11 +260,8 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %binop_lhs:_(s64) = COPY $x0
; CHECK-NEXT: %binop_rhs:_(s64) = COPY $x1
- ; CHECK-NEXT: %not_a_mask:_(s64) = G_CONSTANT i64 26
; CHECK-NEXT: %binop:_(s64) = G_ADD %binop_lhs, %binop_rhs
- ; CHECK-NEXT: %and:_(s64) = G_AND %binop, %not_a_mask
- ; CHECK-NEXT: %or:_(s64) = G_OR %and, %binop
- ; CHECK-NEXT: $x0 = COPY %or(s64)
+ ; CHECK-NEXT: $x0 = COPY %binop(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%binop_lhs:_(s64) = COPY $x0
%binop_rhs:_(s64) = COPY $x1
More information about the llvm-commits
mailing list