[llvm] 9cd1001 - [GlobalISel] Add or_and_and pattern from SelectionDAG (#204618)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 5 08:39:29 PDT 2026
Author: Osman Yasar
Date: 2026-07-05T16:39:24+01:00
New Revision: 9cd1001509c89f468ab262194a77f5e191ca9040
URL: https://github.com/llvm/llvm-project/commit/9cd1001509c89f468ab262194a77f5e191ca9040
DIFF: https://github.com/llvm/llvm-project/commit/9cd1001509c89f468ab262194a77f5e191ca9040.diff
LOG: [GlobalISel] Add or_and_and pattern from SelectionDAG (#204618)
This PR adds the `fold or (xor x, y), (x and/or y) --> or x, y` pattern
from SelectionDAG to GlobalISel.
Added:
Modified:
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.ll
llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.mir
Removed:
################################################################################
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 1b0602af68367..c4661917b3906 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1368,15 +1368,33 @@ def and_xor_or_to_and : GICombineRule<
def and_xor_or_to_xor_and : GICombineRule<
(defs root:$root),
(match (G_XOR $not, $y, -1),
- (G_OR $and, $x, $y),
- (G_AND $root, $and, $not)),
+ (G_OR $or, $x, $y),
+ (G_AND $root, $or, $not)),
(apply (G_XOR $xor, $y, -1),
(G_AND $root, $x, $xor))>;
+// fold or (xor x, y), (x or y) --> or x, y
+def or_xor_or : GICombineRule<
+ (defs root:$root),
+ (match (G_XOR $xor, $x, $y),
+ (G_OR $or, $x, $y),
+ (G_OR $root, $xor, $or)),
+ (apply (G_OR $root, $x, $y))>;
+
+// fold or (xor x, y), (x and y) --> or x, y
+def or_xor_and : GICombineRule<
+ (defs root:$root),
+ (match (G_XOR $xor, $x, $y),
+ (G_AND $and, $x, $y),
+ (G_OR $root, $xor, $and)),
+ (apply (G_OR $root, $x, $y))>;
+
def or_and_xor_combines : GICombineGroup<[or_and_xor_to_or,
or_and_xor_to_xor_or,
and_xor_or_to_and,
- and_xor_or_to_xor_and]>;
+ and_xor_or_to_xor_and,
+ or_xor_or,
+ or_xor_and]>;
def bitfield_extract_from_and : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.ll
index 58b960d622dfb..fbf63d86a5245 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.ll
@@ -211,3 +211,81 @@ entry:
%and = and <4 x i32> %or, %not
ret <4 x i32> %and
}
+
+define i32 @or_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: or_xor_or:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr w0, w0, w1
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor i32 %x, %y
+ %or = or i32 %x, %y
+ %or2 = or i32 %xor, %or
+ ret i32 %or2
+}
+
+define i32 @or_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: or_xor_and:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr w0, w0, w1
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor i32 %x, %y
+ %and = and i32 %x, %y
+ %or2 = or i32 %xor, %and
+ ret i32 %or2
+}
+
+define i64 @or_xor_or_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: or_xor_or_i64:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr x0, x0, x1
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor i64 %x, %y
+ %or = or i64 %x, %y
+ %or2 = or i64 %xor, %or
+ ret i64 %or2
+}
+
+define i64 @or_xor_and_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: or_xor_and_i64:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr x0, x0, x1
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor i64 %x, %y
+ %and = and i64 %x, %y
+ %or2 = or i64 %xor, %and
+ ret i64 %or2
+}
+
+define <4 x i32> @or_xor_or_vector(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: or_xor_or_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor <4 x i32> %x, %y
+ %or = or <4 x i32> %x, %y
+ %or2 = or <4 x i32> %xor, %or
+ ret <4 x i32> %or2
+}
+
+define <4 x i32> @or_xor_and_vector(<4 x i32> %x, <4 x i32> %y) {
+; CHECK-LABEL: or_xor_and_vector:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: ret
+entry:
+; fold or (xor x, y), (x and/or y) --> or x, y
+ %xor = xor <4 x i32> %x, %y
+ %and = and <4 x i32> %x, %y
+ %or2 = or <4 x i32> %xor, %and
+ ret <4 x i32> %or2
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.mir
index 0c6dd0a585b3e..748e9f2f348ff 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-or-and-xor.mir
@@ -204,3 +204,96 @@ body: |
$q0 = COPY %and(<4 x s32>)
RET_ReallyLR implicit $q0
...
+
+---
+name: or_xor_or
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: or_xor_or
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $w0
+ ; CHECK-NEXT: %y:_(s32) = COPY $w1
+ ; CHECK-NEXT: %or2:_(s32) = G_OR %x, %y
+ ; CHECK-NEXT: $w0 = COPY %or2(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %y:_(s32) = COPY $w1
+ %xor:_(s32) = G_XOR %x, %y
+ %or:_(s32) = G_OR %x, %y
+ %or2:_(s32) = G_OR %xor, %or
+ $w0 = COPY %or2(s32)
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: or_xor_or_vector
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1
+ ; CHECK-LABEL: name: or_xor_or_vector
+ ; CHECK: liveins: $q0, $q1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s32>) = COPY $q0
+ ; CHECK-NEXT: %y:_(<4 x s32>) = COPY $q1
+ ; CHECK-NEXT: %or2:_(<4 x s32>) = G_OR %x, %y
+ ; CHECK-NEXT: $q0 = COPY %or2(<4 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %x:_(<4 x s32>) = COPY $q0
+ %y:_(<4 x s32>) = COPY $q1
+ %xor:_(<4 x s32>) = G_XOR %x, %y
+ %or:_(<4 x s32>) = G_OR %x, %y
+ %or2:_(<4 x s32>) = G_OR %xor, %or
+ $q0 = COPY %or2(<4 x s32>)
+ RET_ReallyLR implicit $q0
+...
+
+---
+name: or_xor_and
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: or_xor_and
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $w0
+ ; CHECK-NEXT: %y:_(s32) = COPY $w1
+ ; CHECK-NEXT: %or2:_(s32) = G_OR %x, %y
+ ; CHECK-NEXT: $w0 = COPY %or2(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %y:_(s32) = COPY $w1
+ %xor:_(s32) = G_XOR %x, %y
+ %and:_(s32) = G_AND %x, %y
+ %or2:_(s32) = G_OR %xor, %and
+ $w0 = COPY %or2(s32)
+ RET_ReallyLR implicit $w0
+...
+
+---
+name: or_xor_and_vector
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $q1
+ ; CHECK-LABEL: name: or_xor_and_vector
+ ; CHECK: liveins: $q0, $q1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(<4 x s32>) = COPY $q0
+ ; CHECK-NEXT: %y:_(<4 x s32>) = COPY $q1
+ ; CHECK-NEXT: %or2:_(<4 x s32>) = G_OR %x, %y
+ ; CHECK-NEXT: $q0 = COPY %or2(<4 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %x:_(<4 x s32>) = COPY $q0
+ %y:_(<4 x s32>) = COPY $q1
+ %xor:_(<4 x s32>) = G_XOR %x, %y
+ %and:_(<4 x s32>) = G_AND %x, %y
+ %or2:_(<4 x s32>) = G_OR %xor, %and
+ $q0 = COPY %or2(<4 x s32>)
+ RET_ReallyLR implicit $q0
+...
+
More information about the llvm-commits
mailing list