From c2592c374e469f343ecea82d6728609650924259 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 13 Mar 2022 11:06:53 -0400 Subject: [PATCH] [SDAG] simplify bitwise logic with repeated operand We do not have general reassociation here (and probably do not need it), but I noticed these were missing in patches/tests motivated by D111530, so we can at least handle the simplest patterns. The VE test diff looks correct, but we miss that pattern in IR currently: https://alive2.llvm.org/ce/z/u66_PM --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 19 ++++++++ .../test/CodeGen/AArch64/logic-reassociate.ll | 46 ++++++------------- llvm/test/CodeGen/VE/Scalar/max.ll | 2 +- llvm/test/CodeGen/X86/legalize-shift.ll | 20 +------- llvm/test/CodeGen/X86/pr32345.ll | 33 ++----------- llvm/test/CodeGen/X86/pr34137.ll | 13 +++--- llvm/test/CodeGen/X86/urem-seteq.ll | 5 -- 7 files changed, 48 insertions(+), 90 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d2cad6666cb2..05098753551d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1075,6 +1075,25 @@ SDValue DAGCombiner::reassociateOpsCommutative(unsigned Opc, const SDLoc &DL, return SDValue(); } } + + // Check for repeated operand logic simplifications. + if (Opc == ISD::AND || Opc == ISD::OR) { + // (N00 & N01) & N00 --> N00 & N01 + // (N00 & N01) & N01 --> N00 & N01 + // (N00 | N01) | N00 --> N00 | N01 + // (N00 | N01) | N01 --> N00 | N01 + if (N1 == N00 || N1 == N01) + return N0; + } + if (Opc == ISD::XOR) { + // (N00 ^ N01) ^ N00 --> N01 + if (N1 == N00) + return N01; + // (N00 ^ N01) ^ N01 --> N00 + if (N1 == N01) + return N00; + } + return SDValue(); } diff --git a/llvm/test/CodeGen/AArch64/logic-reassociate.ll b/llvm/test/CodeGen/AArch64/logic-reassociate.ll index 900a574f18fe..5694dfc6b474 100644 --- a/llvm/test/CodeGen/AArch64/logic-reassociate.ll +++ b/llvm/test/CodeGen/AArch64/logic-reassociate.ll @@ -4,8 +4,7 @@ define i32 @and_commute0(i32 %x, i32 %y) { ; CHECK-LABEL: and_commute0: ; CHECK: // %bb.0: -; CHECK-NEXT: and w8, w0, w1 -; CHECK-NEXT: and w0, w0, w8 +; CHECK-NEXT: and w0, w0, w1 ; CHECK-NEXT: ret %b = and i32 %x, %y %b2 = and i32 %x, %b @@ -15,10 +14,8 @@ define i32 @and_commute0(i32 %x, i32 %y) { define i128 @and_commute1(i128 %x, i128 %y) { ; CHECK-LABEL: and_commute1: ; CHECK: // %bb.0: -; CHECK-NEXT: and x8, x3, x1 -; CHECK-NEXT: and x9, x2, x0 -; CHECK-NEXT: and x0, x0, x9 -; CHECK-NEXT: and x1, x1, x8 +; CHECK-NEXT: and x0, x2, x0 +; CHECK-NEXT: and x1, x3, x1 ; CHECK-NEXT: ret %b = and i128 %y, %x %b2 = and i128 %x, %b @@ -28,8 +25,7 @@ define i128 @and_commute1(i128 %x, i128 %y) { define <4 x i32> @and_commute2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: and_commute2: ; CHECK: // %bb.0: -; CHECK-NEXT: and v1.16b, v0.16b, v1.16b -; CHECK-NEXT: and v0.16b, v1.16b, v0.16b +; CHECK-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret %b = and <4 x i32> %x, %y %b2 = and <4 x i32> %b, %x @@ -39,7 +35,6 @@ define <4 x i32> @and_commute2(<4 x i32> %x, <4 x i32> %y) { define <8 x i16> @and_commute3(<8 x i16> %x, <8 x i16> %y) { ; CHECK-LABEL: and_commute3: ; CHECK: // %bb.0: -; CHECK-NEXT: and v1.16b, v1.16b, v0.16b ; CHECK-NEXT: and v0.16b, v1.16b, v0.16b ; CHECK-NEXT: ret %b = and <8 x i16> %y, %x @@ -50,8 +45,7 @@ define <8 x i16> @and_commute3(<8 x i16> %x, <8 x i16> %y) { define i16 @or_commute0(i16 %x, i16 %y) { ; CHECK-LABEL: or_commute0: ; CHECK: // %bb.0: -; CHECK-NEXT: orr w8, w0, w1 -; CHECK-NEXT: orr w0, w0, w8 +; CHECK-NEXT: orr w0, w0, w1 ; CHECK-NEXT: ret %b = or i16 %x, %y %b2 = or i16 %x, %b @@ -61,8 +55,7 @@ define i16 @or_commute0(i16 %x, i16 %y) { define i8 @or_commute1(i8 %x, i8 %y) { ; CHECK-LABEL: or_commute1: ; CHECK: // %bb.0: -; CHECK-NEXT: orr w8, w1, w0 -; CHECK-NEXT: orr w0, w0, w8 +; CHECK-NEXT: orr w0, w1, w0 ; CHECK-NEXT: ret %b = or i8 %y, %x %b2 = or i8 %x, %b @@ -72,8 +65,7 @@ define i8 @or_commute1(i8 %x, i8 %y) { define <2 x i64> @or_commute2(<2 x i64> %x, <2 x i64> %y) { ; CHECK-LABEL: or_commute2: ; CHECK: // %bb.0: -; CHECK-NEXT: orr v1.16b, v0.16b, v1.16b -; CHECK-NEXT: orr v0.16b, v1.16b, v0.16b +; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret %b = or <2 x i64> %x, %y %b2 = or <2 x i64> %b, %x @@ -83,13 +75,9 @@ define <2 x i64> @or_commute2(<2 x i64> %x, <2 x i64> %y) { define <8 x i64> @or_commute3(<8 x i64> %x, <8 x i64> %y) { ; CHECK-LABEL: or_commute3: ; CHECK: // %bb.0: -; CHECK-NEXT: orr v7.16b, v7.16b, v3.16b -; CHECK-NEXT: orr v6.16b, v6.16b, v2.16b -; CHECK-NEXT: orr v5.16b, v5.16b, v1.16b -; CHECK-NEXT: orr v4.16b, v4.16b, v0.16b +; CHECK-NEXT: orr v2.16b, v6.16b, v2.16b ; CHECK-NEXT: orr v0.16b, v4.16b, v0.16b ; CHECK-NEXT: orr v1.16b, v5.16b, v1.16b -; CHECK-NEXT: orr v2.16b, v6.16b, v2.16b ; CHECK-NEXT: orr v3.16b, v7.16b, v3.16b ; CHECK-NEXT: ret %b = or <8 x i64> %y, %x @@ -100,8 +88,7 @@ define <8 x i64> @or_commute3(<8 x i64> %x, <8 x i64> %y) { define <16 x i8> @xor_commute0(<16 x i8> %x, <16 x i8> %y) { ; CHECK-LABEL: xor_commute0: ; CHECK: // %bb.0: -; CHECK-NEXT: eor v1.16b, v0.16b, v1.16b -; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b +; CHECK-NEXT: mov v0.16b, v1.16b ; CHECK-NEXT: ret %b = xor <16 x i8> %x, %y %b2 = xor <16 x i8> %x, %b @@ -111,10 +98,8 @@ define <16 x i8> @xor_commute0(<16 x i8> %x, <16 x i8> %y) { define <8 x i32> @xor_commute1(<8 x i32> %x, <8 x i32> %y) { ; CHECK-LABEL: xor_commute1: ; CHECK: // %bb.0: -; CHECK-NEXT: eor v2.16b, v2.16b, v0.16b -; CHECK-NEXT: eor v3.16b, v3.16b, v1.16b -; CHECK-NEXT: eor v0.16b, v0.16b, v2.16b -; CHECK-NEXT: eor v1.16b, v1.16b, v3.16b +; CHECK-NEXT: mov v1.16b, v3.16b +; CHECK-NEXT: mov v0.16b, v2.16b ; CHECK-NEXT: ret %b = xor <8 x i32> %y, %x %b2 = xor <8 x i32> %x, %b @@ -124,8 +109,7 @@ define <8 x i32> @xor_commute1(<8 x i32> %x, <8 x i32> %y) { define i64 @xor_commute2(i64 %x, i64 %y) { ; CHECK-LABEL: xor_commute2: ; CHECK: // %bb.0: -; CHECK-NEXT: eor x8, x0, x1 -; CHECK-NEXT: eor x0, x8, x0 +; CHECK-NEXT: mov x0, x1 ; CHECK-NEXT: ret %b = xor i64 %x, %y %b2 = xor i64 %b, %x @@ -135,10 +119,8 @@ define i64 @xor_commute2(i64 %x, i64 %y) { define i78 @xor_commute3(i78 %x, i78 %y) { ; CHECK-LABEL: xor_commute3: ; CHECK: // %bb.0: -; CHECK-NEXT: eor x8, x3, x1 -; CHECK-NEXT: eor x9, x2, x0 -; CHECK-NEXT: eor x0, x9, x0 -; CHECK-NEXT: eor x1, x8, x1 +; CHECK-NEXT: mov x1, x3 +; CHECK-NEXT: mov x0, x2 ; CHECK-NEXT: ret %b = xor i78 %y, %x %b2 = xor i78 %b, %x diff --git a/llvm/test/CodeGen/VE/Scalar/max.ll b/llvm/test/CodeGen/VE/Scalar/max.ll index 0e0673114ee1..5b2834ef0873 100644 --- a/llvm/test/CodeGen/VE/Scalar/max.ll +++ b/llvm/test/CodeGen/VE/Scalar/max.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s define double @maxf64(double, double) { @@ -182,7 +183,6 @@ define zeroext i1 @maxi1(i1 zeroext, i1 zeroext) { ; CHECK-LABEL: maxi1: ; CHECK: # %bb.0: ; CHECK-NEXT: or %s0, %s0, %s1 -; CHECK-NEXT: or %s0, %s1, %s0 ; CHECK-NEXT: b.l.t (, %s10) %3 = xor i1 %1, true %4 = and i1 %3, %0 diff --git a/llvm/test/CodeGen/X86/legalize-shift.ll b/llvm/test/CodeGen/X86/legalize-shift.ll index bc5764e586de..adcc78b3c6cc 100644 --- a/llvm/test/CodeGen/X86/legalize-shift.ll +++ b/llvm/test/CodeGen/X86/legalize-shift.ll @@ -5,29 +5,13 @@ define void @PR36250() nounwind { ; X86-LABEL: PR36250: ; X86: # %bb.0: -; X86-NEXT: pushl %esi -; X86-NEXT: movl (%eax), %eax -; X86-NEXT: movl %eax, %ecx -; X86-NEXT: roll %ecx -; X86-NEXT: leal (%eax,%eax), %edx -; X86-NEXT: movl %ecx, %esi -; X86-NEXT: orl %ecx, %esi -; X86-NEXT: orl %ecx, %esi -; X86-NEXT: orl %edx, %esi -; X86-NEXT: orl %eax, %esi +; X86-NEXT: cmpl $0, (%eax) ; X86-NEXT: sete (%eax) -; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; X64-LABEL: PR36250: ; X64: # %bb.0: -; X64-NEXT: movq (%rax), %rax -; X64-NEXT: movq %rax, %rcx -; X64-NEXT: rolq %rcx -; X64-NEXT: leaq (%rax,%rax), %rdx -; X64-NEXT: orq %rcx, %rcx -; X64-NEXT: orq %rdx, %rcx -; X64-NEXT: orq %rax, %rcx +; X64-NEXT: cmpq $0, (%rax) ; X64-NEXT: sete (%rax) ; X64-NEXT: retq %1 = load i448, i448* undef diff --git a/llvm/test/CodeGen/X86/pr32345.ll b/llvm/test/CodeGen/X86/pr32345.ll index 9b940d327529..e2947ffd92bf 100644 --- a/llvm/test/CodeGen/X86/pr32345.ll +++ b/llvm/test/CodeGen/X86/pr32345.ll @@ -43,27 +43,11 @@ define void @foo() { ; 6860-NEXT: .cfi_def_cfa_register %ebp ; 6860-NEXT: andl $-8, %esp ; 6860-NEXT: subl $24, %esp -; 6860-NEXT: movw var_22, %dx -; 6860-NEXT: movzwl var_27, %ecx -; 6860-NEXT: movw %cx, %ax -; 6860-NEXT: xorw %ax, %dx -; 6860-NEXT: # implicit-def: $eax -; 6860-NEXT: movw %dx, %ax -; 6860-NEXT: xorl %ecx, %eax -; 6860-NEXT: # kill: def $ax killed $ax killed $eax -; 6860-NEXT: movzwl %ax, %eax +; 6860-NEXT: movzwl var_22, %eax ; 6860-NEXT: movl %eax, {{[0-9]+}}(%esp) ; 6860-NEXT: movl $0, {{[0-9]+}}(%esp) -; 6860-NEXT: movw var_22, %dx -; 6860-NEXT: movzwl var_27, %eax -; 6860-NEXT: movw %ax, %cx -; 6860-NEXT: xorw %cx, %dx -; 6860-NEXT: # implicit-def: $ecx -; 6860-NEXT: movw %dx, %cx -; 6860-NEXT: xorl %eax, %ecx -; 6860-NEXT: # kill: def $cx killed $cx killed $ecx -; 6860-NEXT: movzwl %cx, %edx -; 6860-NEXT: movb %al, %cl +; 6860-NEXT: movzwl var_22, %edx +; 6860-NEXT: movb var_27, %cl ; 6860-NEXT: addb $30, %cl ; 6860-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ; 6860-NEXT: xorl %eax, %eax @@ -88,14 +72,10 @@ define void @foo() { ; ; X64-LABEL: foo: ; X64: # %bb.0: # %bb -; X64-NEXT: movzwl var_27(%rip), %ecx +; X64-NEXT: movb var_27(%rip), %cl ; X64-NEXT: movzwl var_22(%rip), %eax -; X64-NEXT: xorw %cx, %ax -; X64-NEXT: xorl %ecx, %eax -; X64-NEXT: movzwl %ax, %eax ; X64-NEXT: movq %rax, -{{[0-9]+}}(%rsp) ; X64-NEXT: addb $30, %cl -; X64-NEXT: # kill: def $cl killed $cl killed $ecx ; X64-NEXT: shrq %cl, %rax ; X64-NEXT: movb %al, (%rax) ; X64-NEXT: retq @@ -109,11 +89,8 @@ define void @foo() { ; 686-NEXT: .cfi_def_cfa_register %ebp ; 686-NEXT: andl $-8, %esp ; 686-NEXT: subl $8, %esp -; 686-NEXT: movzwl var_27, %ecx +; 686-NEXT: movb var_27, %cl ; 686-NEXT: movzwl var_22, %eax -; 686-NEXT: xorw %cx, %ax -; 686-NEXT: xorl %ecx, %eax -; 686-NEXT: movzwl %ax, %eax ; 686-NEXT: movl %eax, (%esp) ; 686-NEXT: movl $0, {{[0-9]+}}(%esp) ; 686-NEXT: addb $30, %cl diff --git a/llvm/test/CodeGen/X86/pr34137.ll b/llvm/test/CodeGen/X86/pr34137.ll index 650c9b8acb40..d4c92e4bf0a8 100644 --- a/llvm/test/CodeGen/X86/pr34137.ll +++ b/llvm/test/CodeGen/X86/pr34137.ll @@ -8,15 +8,16 @@ define void @pr34127() { ; CHECK-LABEL: pr34127: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: movzwl var_3(%rip), %eax -; CHECK-NEXT: movzwl var_13(%rip), %ecx -; CHECK-NEXT: andl %eax, %ecx -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: andl %eax, %ecx +; CHECK-NEXT: movzwl var_13(%rip), %eax +; CHECK-NEXT: movzwl var_3(%rip), %ecx +; CHECK-NEXT: andw %ax, %cx ; CHECK-NEXT: movzwl %cx, %ecx ; CHECK-NEXT: movl %ecx, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movzwl var_3(%rip), %ecx +; CHECK-NEXT: xorl %edx, %edx +; CHECK-NEXT: testl %eax, %ecx ; CHECK-NEXT: sete %dl -; CHECK-NEXT: andl %eax, %edx +; CHECK-NEXT: andl %ecx, %edx ; CHECK-NEXT: movq %rdx, var_212(%rip) ; CHECK-NEXT: movw $0, (%rax) ; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/urem-seteq.ll b/llvm/test/CodeGen/X86/urem-seteq.ll index 214a5162fd13..b86691241f16 100644 --- a/llvm/test/CodeGen/X86/urem-seteq.ll +++ b/llvm/test/CodeGen/X86/urem-seteq.ll @@ -367,9 +367,6 @@ define void @ossfuzz34366() { ; X86-NEXT: movl %eax, %ecx ; X86-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF ; X86-NEXT: orl %eax, %ecx -; X86-NEXT: orl %eax, %ecx -; X86-NEXT: orl %eax, %ecx -; X86-NEXT: orl %eax, %ecx ; X86-NEXT: sete (%eax) ; X86-NEXT: retl ; @@ -379,8 +376,6 @@ define void @ossfuzz34366() { ; X64-NEXT: movabsq $9223372036854775807, %rcx # imm = 0x7FFFFFFFFFFFFFFF ; X64-NEXT: andq %rax, %rcx ; X64-NEXT: orq %rax, %rcx -; X64-NEXT: orq %rax, %rcx -; X64-NEXT: orq %rax, %rcx ; X64-NEXT: sete (%rax) ; X64-NEXT: retq %L10 = load i448, i448* undef, align 4