[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