[llvm] 90c2330 - [AArch64][x86] add tests for bitwise logic + shifts; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 5 08:24:28 PST 2022


Author: Sanjay Patel
Date: 2022-03-05T11:14:45-05:00
New Revision: 90c2330c15ffb8f5c3db86089f935e5a1bb9273a

URL: https://github.com/llvm/llvm-project/commit/90c2330c15ffb8f5c3db86089f935e5a1bb9273a
DIFF: https://github.com/llvm/llvm-project/commit/90c2330c15ffb8f5c3db86089f935e5a1bb9273a.diff

LOG: [AArch64][x86] add tests for bitwise logic + shifts; NFC

Copy tests from ecf606cb4329ae and replace 'or' with 'xor' / 'and'.
This provides coverage for an enhancement of D120516 / acb96ffd149d

Added: 
    

Modified: 
    llvm/test/CodeGen/AArch64/logic-shift.ll
    llvm/test/CodeGen/X86/logic-shift.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/CodeGen/AArch64/logic-shift.ll b/llvm/test/CodeGen/AArch64/logic-shift.ll
index 8bf749d7c3e1c..058458c4dcd55 100644
--- a/llvm/test/CodeGen/AArch64/logic-shift.ll
+++ b/llvm/test/CodeGen/AArch64/logic-shift.ll
@@ -229,6 +229,490 @@ define i64 @mix_logic_lshr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
   ret i64 %r
 }
 
+define i8 @xor_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: xor_lshr_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and w8, w0, #0xff
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    and w9, w1, #0xff
+; CHECK-NEXT:    lsr w8, w8, w2
+; CHECK-NEXT:    lsr w9, w9, w2
+; CHECK-NEXT:    eor w8, w8, w3
+; CHECK-NEXT:    eor w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = lshr i8 %x0, %y
+  %sh2 = lshr i8 %x1, %y
+  %logic = xor i8 %sh1, %z
+  %r = xor i8 %logic, %sh2
+  ret i8 %r
+}
+
+define i32 @xor_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: xor_lshr_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsr w8, w0, w2
+; CHECK-NEXT:    lsr w9, w1, w2
+; CHECK-NEXT:    eor w8, w3, w8
+; CHECK-NEXT:    eor w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = lshr i32 %x0, %y
+  %sh2 = lshr i32 %x1, %y
+  %logic = xor i32 %z, %sh1
+  %r = xor i32 %logic, %sh2
+  ret i32 %r
+}
+
+define <8 x i16> @xor_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: xor_lshr_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.8h, v2.8h
+; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
+; CHECK-NEXT:    ushl v1.8h, v1.8h, v2.8h
+; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = lshr <8 x i16> %x0, %y
+  %sh2 = lshr <8 x i16> %x1, %y
+  %logic = xor <8 x i16> %sh1, %z
+  %r = xor <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+define <2 x i64> @xor_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: xor_lshr_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.2d, v2.2d
+; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    ushl v1.2d, v1.2d, v2.2d
+; CHECK-NEXT:    eor v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = lshr <2 x i64> %x0, %y
+  %sh2 = lshr <2 x i64> %x1, %y
+  %logic = xor <2 x i64> %z, %sh1
+  %r = xor <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define i16 @xor_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
+; CHECK-LABEL: xor_ashr_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sxth w8, w0
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    sxth w9, w1
+; CHECK-NEXT:    asr w8, w8, w2
+; CHECK-NEXT:    asr w9, w9, w2
+; CHECK-NEXT:    eor w8, w8, w3
+; CHECK-NEXT:    eor w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i16 %x0, %y
+  %sh2 = ashr i16 %x1, %y
+  %logic = xor i16 %sh1, %z
+  %r = xor i16 %logic, %sh2
+  ret i16 %r
+}
+
+define i64 @xor_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: xor_ashr_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    asr x8, x0, x2
+; CHECK-NEXT:    asr x9, x1, x2
+; CHECK-NEXT:    eor x8, x3, x8
+; CHECK-NEXT:    eor x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = xor i64 %z, %sh1
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+define <4 x i32> @xor_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
+; CHECK-LABEL: xor_ashr_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.4s, v2.4s
+; CHECK-NEXT:    sshl v0.4s, v0.4s, v2.4s
+; CHECK-NEXT:    sshl v1.4s, v1.4s, v2.4s
+; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = ashr <4 x i32> %x0, %y
+  %sh2 = ashr <4 x i32> %x1, %y
+  %logic = xor <4 x i32> %sh1, %z
+  %r = xor <4 x i32> %sh2, %logic
+  ret <4 x i32> %r
+}
+
+define <16 x i8> @xor_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
+; CHECK-LABEL: xor_ashr_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.16b, v2.16b
+; CHECK-NEXT:    sshl v0.16b, v0.16b, v2.16b
+; CHECK-NEXT:    sshl v1.16b, v1.16b, v2.16b
+; CHECK-NEXT:    eor v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = ashr <16 x i8> %x0, %y
+  %sh2 = ashr <16 x i8> %x1, %y
+  %logic = xor <16 x i8> %z, %sh1
+  %r = xor <16 x i8> %sh2, %logic
+  ret <16 x i8> %r
+}
+
+define i32 @xor_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: xor_shl_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsl w8, w0, w2
+; CHECK-NEXT:    lsl w9, w1, w2
+; CHECK-NEXT:    eor w8, w8, w3
+; CHECK-NEXT:    eor w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = shl i32 %x0, %y
+  %sh2 = shl i32 %x1, %y
+  %logic = xor i32 %sh1, %z
+  %r = xor i32 %logic, %sh2
+  ret i32 %r
+}
+
+define i8 @xor_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: xor_shl_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    lsl w8, w0, w2
+; CHECK-NEXT:    lsl w9, w1, w2
+; CHECK-NEXT:    eor w8, w3, w8
+; CHECK-NEXT:    eor w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = shl i8 %x0, %y
+  %sh2 = shl i8 %x1, %y
+  %logic = xor i8 %z, %sh1
+  %r = xor i8 %logic, %sh2
+  ret i8 %r
+}
+
+define <2 x i64> @xor_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: xor_shl_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    ushl v1.2d, v1.2d, v2.2d
+; CHECK-NEXT:    eor v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = shl <2 x i64> %x0, %y
+  %sh2 = shl <2 x i64> %x1, %y
+  %logic = xor <2 x i64> %sh1, %z
+  %r = xor <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define <8 x i16> @xor_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: xor_shl_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
+; CHECK-NEXT:    ushl v1.8h, v1.8h, v2.8h
+; CHECK-NEXT:    eor v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    eor v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = shl <8 x i16> %x0, %y
+  %sh2 = shl <8 x i16> %x1, %y
+  %logic = xor <8 x i16> %z, %sh1
+  %r = xor <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+; negative test - mismatched shift opcodes
+
+define i64 @xor_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: xor_mix_shr:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    asr x8, x0, x2
+; CHECK-NEXT:    lsr x9, x1, x2
+; CHECK-NEXT:    eor x8, x8, x3
+; CHECK-NEXT:    eor x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %y
+  %logic = xor i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched shift amounts
+
+define i64 @xor_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: xor_lshr_mix_shift_amount:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsr x9, x0, x2
+; CHECK-NEXT:    lsr x8, x1, x4
+; CHECK-NEXT:    eor x9, x9, x3
+; CHECK-NEXT:    eor x0, x9, x8
+; CHECK-NEXT:    ret
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %w
+  %logic = xor i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched logic opcodes
+
+define i64 @mix_logic_ashr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: mix_logic_ashr:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    asr x8, x0, x2
+; CHECK-NEXT:    asr x9, x1, x2
+; CHECK-NEXT:    orr x8, x8, x3
+; CHECK-NEXT:    eor x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = or i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+define i8 @and_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: and_lshr_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    and w8, w0, #0xff
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    and w9, w1, #0xff
+; CHECK-NEXT:    lsr w8, w8, w2
+; CHECK-NEXT:    lsr w9, w9, w2
+; CHECK-NEXT:    and w8, w8, w3
+; CHECK-NEXT:    and w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = lshr i8 %x0, %y
+  %sh2 = lshr i8 %x1, %y
+  %logic = and i8 %sh1, %z
+  %r = and i8 %logic, %sh2
+  ret i8 %r
+}
+
+define i32 @and_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: and_lshr_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsr w8, w0, w2
+; CHECK-NEXT:    lsr w9, w1, w2
+; CHECK-NEXT:    and w8, w3, w8
+; CHECK-NEXT:    and w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = lshr i32 %x0, %y
+  %sh2 = lshr i32 %x1, %y
+  %logic = and i32 %z, %sh1
+  %r = and i32 %logic, %sh2
+  ret i32 %r
+}
+
+define <8 x i16> @and_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: and_lshr_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.8h, v2.8h
+; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
+; CHECK-NEXT:    ushl v1.8h, v1.8h, v2.8h
+; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = lshr <8 x i16> %x0, %y
+  %sh2 = lshr <8 x i16> %x1, %y
+  %logic = and <8 x i16> %sh1, %z
+  %r = and <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+define <2 x i64> @and_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: and_lshr_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.2d, v2.2d
+; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    ushl v1.2d, v1.2d, v2.2d
+; CHECK-NEXT:    and v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = lshr <2 x i64> %x0, %y
+  %sh2 = lshr <2 x i64> %x1, %y
+  %logic = and <2 x i64> %z, %sh1
+  %r = and <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define i16 @and_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
+; CHECK-LABEL: and_ashr_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sxth w8, w0
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    sxth w9, w1
+; CHECK-NEXT:    asr w8, w8, w2
+; CHECK-NEXT:    asr w9, w9, w2
+; CHECK-NEXT:    and w8, w8, w3
+; CHECK-NEXT:    and w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i16 %x0, %y
+  %sh2 = ashr i16 %x1, %y
+  %logic = and i16 %sh1, %z
+  %r = and i16 %logic, %sh2
+  ret i16 %r
+}
+
+define i64 @and_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: and_ashr_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    asr x8, x0, x2
+; CHECK-NEXT:    asr x9, x1, x2
+; CHECK-NEXT:    and x8, x3, x8
+; CHECK-NEXT:    and x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = and i64 %z, %sh1
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+define <4 x i32> @and_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
+; CHECK-LABEL: and_ashr_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.4s, v2.4s
+; CHECK-NEXT:    sshl v0.4s, v0.4s, v2.4s
+; CHECK-NEXT:    sshl v1.4s, v1.4s, v2.4s
+; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = ashr <4 x i32> %x0, %y
+  %sh2 = ashr <4 x i32> %x1, %y
+  %logic = and <4 x i32> %sh1, %z
+  %r = and <4 x i32> %sh2, %logic
+  ret <4 x i32> %r
+}
+
+define <16 x i8> @and_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
+; CHECK-LABEL: and_ashr_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v2.16b, v2.16b
+; CHECK-NEXT:    sshl v0.16b, v0.16b, v2.16b
+; CHECK-NEXT:    sshl v1.16b, v1.16b, v2.16b
+; CHECK-NEXT:    and v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = ashr <16 x i8> %x0, %y
+  %sh2 = ashr <16 x i8> %x1, %y
+  %logic = and <16 x i8> %z, %sh1
+  %r = and <16 x i8> %sh2, %logic
+  ret <16 x i8> %r
+}
+
+define i32 @and_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: and_shl_commute0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsl w8, w0, w2
+; CHECK-NEXT:    lsl w9, w1, w2
+; CHECK-NEXT:    and w8, w8, w3
+; CHECK-NEXT:    and w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = shl i32 %x0, %y
+  %sh2 = shl i32 %x1, %y
+  %logic = and i32 %sh1, %z
+  %r = and i32 %logic, %sh2
+  ret i32 %r
+}
+
+define i8 @and_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: and_shl_commute1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $w2 killed $w2 def $x2
+; CHECK-NEXT:    lsl w8, w0, w2
+; CHECK-NEXT:    lsl w9, w1, w2
+; CHECK-NEXT:    and w8, w3, w8
+; CHECK-NEXT:    and w0, w8, w9
+; CHECK-NEXT:    ret
+  %sh1 = shl i8 %x0, %y
+  %sh2 = shl i8 %x1, %y
+  %logic = and i8 %z, %sh1
+  %r = and i8 %logic, %sh2
+  ret i8 %r
+}
+
+define <2 x i64> @and_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: and_shl_commute2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushl v0.2d, v0.2d, v2.2d
+; CHECK-NEXT:    ushl v1.2d, v1.2d, v2.2d
+; CHECK-NEXT:    and v0.16b, v0.16b, v3.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = shl <2 x i64> %x0, %y
+  %sh2 = shl <2 x i64> %x1, %y
+  %logic = and <2 x i64> %sh1, %z
+  %r = and <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define <8 x i16> @and_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: and_shl_commute3:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushl v0.8h, v0.8h, v2.8h
+; CHECK-NEXT:    ushl v1.8h, v1.8h, v2.8h
+; CHECK-NEXT:    and v0.16b, v3.16b, v0.16b
+; CHECK-NEXT:    and v0.16b, v1.16b, v0.16b
+; CHECK-NEXT:    ret
+  %sh1 = shl <8 x i16> %x0, %y
+  %sh2 = shl <8 x i16> %x1, %y
+  %logic = and <8 x i16> %z, %sh1
+  %r = and <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+; negative test - mismatched shift opcodes
+
+define i64 @and_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: and_mix_shr:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsr x8, x0, x2
+; CHECK-NEXT:    asr x9, x1, x2
+; CHECK-NEXT:    and x8, x8, x3
+; CHECK-NEXT:    and x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = and i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched shift amounts
+
+define i64 @and_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: and_lshr_mix_shift_amount:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsr x9, x0, x2
+; CHECK-NEXT:    lsr x8, x1, x4
+; CHECK-NEXT:    and x9, x9, x3
+; CHECK-NEXT:    and x0, x9, x8
+; CHECK-NEXT:    ret
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %w
+  %logic = and i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched logic opcodes
+
+define i64 @mix_logic_shl(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: mix_logic_shl:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    lsl x8, x0, x2
+; CHECK-NEXT:    lsl x9, x1, x2
+; CHECK-NEXT:    eor x8, x8, x3
+; CHECK-NEXT:    and x0, x8, x9
+; CHECK-NEXT:    ret
+  %sh1 = shl i64 %x0, %y
+  %sh2 = shl i64 %x1, %y
+  %logic = xor i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
 ; (shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
 
 define i32 @or_fshl_commute0(i32 %x, i32 %y) {

diff  --git a/llvm/test/CodeGen/X86/logic-shift.ll b/llvm/test/CodeGen/X86/logic-shift.ll
index bd24b2cb7188a..1a413a44f99a8 100644
--- a/llvm/test/CodeGen/X86/logic-shift.ll
+++ b/llvm/test/CodeGen/X86/logic-shift.ll
@@ -285,6 +285,646 @@ define i64 @mix_logic_lshr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
   ret i64 %r
 }
 
+define i8 @xor_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: xor_lshr_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shrb %cl, %dil
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shrb %cl, %sil
+; CHECK-NEXT:    xorb %sil, %al
+; CHECK-NEXT:    xorb %dil, %al
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i8 %x0, %y
+  %sh2 = lshr i8 %x1, %y
+  %logic = xor i8 %sh1, %z
+  %r = xor i8 %logic, %sh2
+  ret i8 %r
+}
+
+define i32 @xor_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: xor_lshr_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shrl %cl, %edi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shrl %cl, %esi
+; CHECK-NEXT:    xorl %edi, %esi
+; CHECK-NEXT:    xorl %esi, %eax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i32 %x0, %y
+  %sh2 = lshr i32 %x1, %y
+  %logic = xor i32 %z, %sh1
+  %r = xor i32 %logic, %sh2
+  ret i32 %r
+}
+
+define <8 x i16> @xor_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: xor_lshr_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero
+; CHECK-NEXT:    vpsrlvd %ymm2, %ymm0, %ymm0
+; CHECK-NEXT:    vextracti128 $1, %ymm0, %xmm4
+; CHECK-NEXT:    vpackusdw %xmm4, %xmm0, %xmm0
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT:    vpsrlvd %ymm2, %ymm1, %ymm1
+; CHECK-NEXT:    vextracti128 $1, %ymm1, %xmm2
+; CHECK-NEXT:    vpackusdw %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+  %sh1 = lshr <8 x i16> %x0, %y
+  %sh2 = lshr <8 x i16> %x1, %y
+  %logic = xor <8 x i16> %sh1, %z
+  %r = xor <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+define <2 x i64> @xor_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: xor_lshr_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsrlvq %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlvq %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vpxor %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = lshr <2 x i64> %x0, %y
+  %sh2 = lshr <2 x i64> %x1, %y
+  %logic = xor <2 x i64> %z, %sh1
+  %r = xor <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define i16 @xor_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
+; CHECK-LABEL: xor_ashr_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %r8d
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    movswl %si, %eax
+; CHECK-NEXT:    movswl %di, %edx
+; CHECK-NEXT:    sarl %cl, %edx
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    sarl %cl, %eax
+; CHECK-NEXT:    xorl %r8d, %eax
+; CHECK-NEXT:    xorl %edx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i16 %x0, %y
+  %sh2 = ashr i16 %x1, %y
+  %logic = xor i16 %sh1, %z
+  %r = xor i16 %logic, %sh2
+  ret i16 %r
+}
+
+define i64 @xor_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: xor_ashr_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    sarq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    sarq %cl, %rsi
+; CHECK-NEXT:    xorq %rdi, %rsi
+; CHECK-NEXT:    xorq %rsi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = xor i64 %z, %sh1
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+define <4 x i32> @xor_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
+; CHECK-LABEL: xor_ashr_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsravd %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsravd %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = ashr <4 x i32> %x0, %y
+  %sh2 = ashr <4 x i32> %x1, %y
+  %logic = xor <4 x i32> %sh1, %z
+  %r = xor <4 x i32> %sh2, %logic
+  ret <4 x i32> %r
+}
+
+define <16 x i8> @xor_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
+; CHECK-LABEL: xor_ashr_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm4 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpsraw $4, %xmm4, %xmm5
+; CHECK-NEXT:    vpsllw $5, %xmm2, %xmm2
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm6 = xmm2[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpblendvb %xmm6, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsraw $2, %xmm4, %xmm5
+; CHECK-NEXT:    vpaddw %xmm6, %xmm6, %xmm7
+; CHECK-NEXT:    vpblendvb %xmm7, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsraw $1, %xmm4, %xmm5
+; CHECK-NEXT:    vpaddw %xmm7, %xmm7, %xmm8
+; CHECK-NEXT:    vpblendvb %xmm8, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsrlw $8, %xmm4, %xmm9
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpsraw $4, %xmm0, %xmm5
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpblendvb %xmm2, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $2, %xmm0, %xmm5
+; CHECK-NEXT:    vpaddw %xmm2, %xmm2, %xmm4
+; CHECK-NEXT:    vpblendvb %xmm4, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $1, %xmm0, %xmm5
+; CHECK-NEXT:    vpaddw %xmm4, %xmm4, %xmm10
+; CHECK-NEXT:    vpblendvb %xmm10, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlw $8, %xmm0, %xmm0
+; CHECK-NEXT:    vpackuswb %xmm9, %xmm0, %xmm9
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm5 = xmm1[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpsraw $4, %xmm5, %xmm0
+; CHECK-NEXT:    vpblendvb %xmm6, %xmm0, %xmm5, %xmm0
+; CHECK-NEXT:    vpsraw $2, %xmm0, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm7, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $1, %xmm0, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm8, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlw $8, %xmm0, %xmm0
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm1 = xmm1[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpsraw $4, %xmm1, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm2, %xmm5, %xmm1, %xmm1
+; CHECK-NEXT:    vpsraw $2, %xmm1, %xmm2
+; CHECK-NEXT:    vpblendvb %xmm4, %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpsraw $1, %xmm1, %xmm2
+; CHECK-NEXT:    vpblendvb %xmm10, %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpsrlw $8, %xmm1, %xmm1
+; CHECK-NEXT:    vpackuswb %xmm0, %xmm1, %xmm0
+; CHECK-NEXT:    vpxor %xmm0, %xmm9, %xmm0
+; CHECK-NEXT:    vpxor %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = ashr <16 x i8> %x0, %y
+  %sh2 = ashr <16 x i8> %x1, %y
+  %logic = xor <16 x i8> %z, %sh1
+  %r = xor <16 x i8> %sh2, %logic
+  ret <16 x i8> %r
+}
+
+define i32 @xor_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: xor_shl_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shll %cl, %edi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shll %cl, %esi
+; CHECK-NEXT:    xorl %esi, %eax
+; CHECK-NEXT:    xorl %edi, %eax
+; CHECK-NEXT:    retq
+  %sh1 = shl i32 %x0, %y
+  %sh2 = shl i32 %x1, %y
+  %logic = xor i32 %sh1, %z
+  %r = xor i32 %logic, %sh2
+  ret i32 %r
+}
+
+define i8 @xor_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: xor_shl_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shlb %cl, %dil
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shlb %cl, %sil
+; CHECK-NEXT:    xorb %dil, %sil
+; CHECK-NEXT:    xorb %sil, %al
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = shl i8 %x0, %y
+  %sh2 = shl i8 %x1, %y
+  %logic = xor i8 %z, %sh1
+  %r = xor i8 %logic, %sh2
+  ret i8 %r
+}
+
+define <2 x i64> @xor_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: xor_shl_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsllvq %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsllvq %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = shl <2 x i64> %x0, %y
+  %sh2 = shl <2 x i64> %x1, %y
+  %logic = xor <2 x i64> %sh1, %z
+  %r = xor <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define <8 x i16> @xor_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: xor_shl_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero
+; CHECK-NEXT:    vpsllvd %ymm2, %ymm0, %ymm0
+; CHECK-NEXT:    vmovdqa {{.*#+}} ymm4 = [0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15,16,17,20,21,24,25,28,29,24,25,28,29,28,29,30,31]
+; CHECK-NEXT:    vpshufb %ymm4, %ymm0, %ymm0
+; CHECK-NEXT:    vpermq {{.*#+}} ymm0 = ymm0[0,2,2,3]
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT:    vpsllvd %ymm2, %ymm1, %ymm1
+; CHECK-NEXT:    vpshufb %ymm4, %ymm1, %ymm1
+; CHECK-NEXT:    vpermq {{.*#+}} ymm1 = ymm1[0,2,2,3]
+; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vpxor %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+  %sh1 = shl <8 x i16> %x0, %y
+  %sh2 = shl <8 x i16> %x1, %y
+  %logic = xor <8 x i16> %z, %sh1
+  %r = xor <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+; negative test - mismatched shift opcodes
+
+define i64 @xor_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: xor_mix_shr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    sarq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    shrq %cl, %rsi
+; CHECK-NEXT:    xorq %rsi, %rax
+; CHECK-NEXT:    xorq %rdi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %y
+  %logic = xor i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched shift amounts
+
+define i64 @xor_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: xor_lshr_mix_shift_amount:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    shrq %cl, %rdi
+; CHECK-NEXT:    movl %r8d, %ecx
+; CHECK-NEXT:    shrq %cl, %rsi
+; CHECK-NEXT:    xorq %rsi, %rax
+; CHECK-NEXT:    xorq %rdi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %w
+  %logic = xor i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched logic opcodes
+
+define i64 @mix_logic_ashr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: mix_logic_ashr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    sarq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    sarq %cl, %rsi
+; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    xorq %rsi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = or i64 %sh1, %z
+  %r = xor i64 %logic, %sh2
+  ret i64 %r
+}
+
+define i8 @and_lshr_commute0(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: and_lshr_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shrb %cl, %dil
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shrb %cl, %sil
+; CHECK-NEXT:    andb %sil, %al
+; CHECK-NEXT:    andb %dil, %al
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i8 %x0, %y
+  %sh2 = lshr i8 %x1, %y
+  %logic = and i8 %sh1, %z
+  %r = and i8 %logic, %sh2
+  ret i8 %r
+}
+
+define i32 @and_lshr_commute1(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: and_lshr_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shrl %cl, %edi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shrl %cl, %esi
+; CHECK-NEXT:    andl %edi, %esi
+; CHECK-NEXT:    andl %esi, %eax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i32 %x0, %y
+  %sh2 = lshr i32 %x1, %y
+  %logic = and i32 %z, %sh1
+  %r = and i32 %logic, %sh2
+  ret i32 %r
+}
+
+define <8 x i16> @and_lshr_commute2(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: and_lshr_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero
+; CHECK-NEXT:    vpsrlvd %ymm2, %ymm0, %ymm0
+; CHECK-NEXT:    vextracti128 $1, %ymm0, %xmm4
+; CHECK-NEXT:    vpackusdw %xmm4, %xmm0, %xmm0
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT:    vpsrlvd %ymm2, %ymm1, %ymm1
+; CHECK-NEXT:    vextracti128 $1, %ymm1, %xmm2
+; CHECK-NEXT:    vpackusdw %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+  %sh1 = lshr <8 x i16> %x0, %y
+  %sh2 = lshr <8 x i16> %x1, %y
+  %logic = and <8 x i16> %sh1, %z
+  %r = and <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+define <2 x i64> @and_lshr_commute3(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: and_lshr_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsrlvq %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlvq %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vpand %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = lshr <2 x i64> %x0, %y
+  %sh2 = lshr <2 x i64> %x1, %y
+  %logic = and <2 x i64> %z, %sh1
+  %r = and <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define i16 @and_ashr_commute0(i16 %x0, i16 %x1, i16 %y, i16 %z) {
+; CHECK-LABEL: and_ashr_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %r8d
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    movswl %si, %eax
+; CHECK-NEXT:    movswl %di, %edx
+; CHECK-NEXT:    sarl %cl, %edx
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    sarl %cl, %eax
+; CHECK-NEXT:    andl %r8d, %eax
+; CHECK-NEXT:    andl %edx, %eax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i16 %x0, %y
+  %sh2 = ashr i16 %x1, %y
+  %logic = and i16 %sh1, %z
+  %r = and i16 %logic, %sh2
+  ret i16 %r
+}
+
+define i64 @and_ashr_commute1(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: and_ashr_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    sarq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    sarq %cl, %rsi
+; CHECK-NEXT:    andq %rdi, %rsi
+; CHECK-NEXT:    andq %rsi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = ashr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = and i64 %z, %sh1
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+define <4 x i32> @and_ashr_commute2(<4 x i32> %x0, <4 x i32> %x1, <4 x i32> %y, <4 x i32> %z) {
+; CHECK-LABEL: and_ashr_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsravd %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsravd %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = ashr <4 x i32> %x0, %y
+  %sh2 = ashr <4 x i32> %x1, %y
+  %logic = and <4 x i32> %sh1, %z
+  %r = and <4 x i32> %sh2, %logic
+  ret <4 x i32> %r
+}
+
+define <16 x i8> @and_ashr_commute3(<16 x i8> %x0, <16 x i8> %x1, <16 x i8> %y, <16 x i8> %z) {
+; CHECK-LABEL: and_ashr_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm4 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpsraw $4, %xmm4, %xmm5
+; CHECK-NEXT:    vpsllw $5, %xmm2, %xmm2
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm6 = xmm2[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpblendvb %xmm6, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsraw $2, %xmm4, %xmm5
+; CHECK-NEXT:    vpaddw %xmm6, %xmm6, %xmm7
+; CHECK-NEXT:    vpblendvb %xmm7, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsraw $1, %xmm4, %xmm5
+; CHECK-NEXT:    vpaddw %xmm7, %xmm7, %xmm8
+; CHECK-NEXT:    vpblendvb %xmm8, %xmm5, %xmm4, %xmm4
+; CHECK-NEXT:    vpsrlw $8, %xmm4, %xmm9
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpsraw $4, %xmm0, %xmm5
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpblendvb %xmm2, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $2, %xmm0, %xmm5
+; CHECK-NEXT:    vpaddw %xmm2, %xmm2, %xmm4
+; CHECK-NEXT:    vpblendvb %xmm4, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $1, %xmm0, %xmm5
+; CHECK-NEXT:    vpaddw %xmm4, %xmm4, %xmm10
+; CHECK-NEXT:    vpblendvb %xmm10, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlw $8, %xmm0, %xmm0
+; CHECK-NEXT:    vpackuswb %xmm9, %xmm0, %xmm9
+; CHECK-NEXT:    vpunpckhbw {{.*#+}} xmm5 = xmm1[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15]
+; CHECK-NEXT:    vpsraw $4, %xmm5, %xmm0
+; CHECK-NEXT:    vpblendvb %xmm6, %xmm0, %xmm5, %xmm0
+; CHECK-NEXT:    vpsraw $2, %xmm0, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm7, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsraw $1, %xmm0, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm8, %xmm5, %xmm0, %xmm0
+; CHECK-NEXT:    vpsrlw $8, %xmm0, %xmm0
+; CHECK-NEXT:    vpunpcklbw {{.*#+}} xmm1 = xmm1[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
+; CHECK-NEXT:    vpsraw $4, %xmm1, %xmm5
+; CHECK-NEXT:    vpblendvb %xmm2, %xmm5, %xmm1, %xmm1
+; CHECK-NEXT:    vpsraw $2, %xmm1, %xmm2
+; CHECK-NEXT:    vpblendvb %xmm4, %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpsraw $1, %xmm1, %xmm2
+; CHECK-NEXT:    vpblendvb %xmm10, %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpsrlw $8, %xmm1, %xmm1
+; CHECK-NEXT:    vpackuswb %xmm0, %xmm1, %xmm0
+; CHECK-NEXT:    vpand %xmm0, %xmm9, %xmm0
+; CHECK-NEXT:    vpand %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = ashr <16 x i8> %x0, %y
+  %sh2 = ashr <16 x i8> %x1, %y
+  %logic = and <16 x i8> %z, %sh1
+  %r = and <16 x i8> %sh2, %logic
+  ret <16 x i8> %r
+}
+
+define i32 @and_shl_commute0(i32 %x0, i32 %x1, i32 %y, i32 %z) {
+; CHECK-LABEL: and_shl_commute0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shll %cl, %edi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shll %cl, %esi
+; CHECK-NEXT:    andl %esi, %eax
+; CHECK-NEXT:    andl %edi, %eax
+; CHECK-NEXT:    retq
+  %sh1 = shl i32 %x0, %y
+  %sh2 = shl i32 %x1, %y
+  %logic = and i32 %sh1, %z
+  %r = and i32 %logic, %sh2
+  ret i32 %r
+}
+
+define i8 @and_shl_commute1(i8 %x0, i8 %x1, i8 %y, i8 %z) {
+; CHECK-LABEL: and_shl_commute1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %ecx, %eax
+; CHECK-NEXT:    movl %edx, %ecx
+; CHECK-NEXT:    shlb %cl, %dil
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT:    shlb %cl, %sil
+; CHECK-NEXT:    andb %dil, %sil
+; CHECK-NEXT:    andb %sil, %al
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+  %sh1 = shl i8 %x0, %y
+  %sh2 = shl i8 %x1, %y
+  %logic = and i8 %z, %sh1
+  %r = and i8 %logic, %sh2
+  ret i8 %r
+}
+
+define <2 x i64> @and_shl_commute2(<2 x i64> %x0, <2 x i64> %x1, <2 x i64> %y, <2 x i64> %z) {
+; CHECK-LABEL: and_shl_commute2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpsllvq %xmm2, %xmm0, %xmm0
+; CHECK-NEXT:    vpsllvq %xmm2, %xmm1, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm3, %xmm1
+; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    retq
+  %sh1 = shl <2 x i64> %x0, %y
+  %sh2 = shl <2 x i64> %x1, %y
+  %logic = and <2 x i64> %sh1, %z
+  %r = and <2 x i64> %sh2, %logic
+  ret <2 x i64> %r
+}
+
+define <8 x i16> @and_shl_commute3(<8 x i16> %x0, <8 x i16> %x1, <8 x i16> %y, <8 x i16> %z) {
+; CHECK-LABEL: and_shl_commute3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero
+; CHECK-NEXT:    vpsllvd %ymm2, %ymm0, %ymm0
+; CHECK-NEXT:    vmovdqa {{.*#+}} ymm4 = [0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15,16,17,20,21,24,25,28,29,24,25,28,29,28,29,30,31]
+; CHECK-NEXT:    vpshufb %ymm4, %ymm0, %ymm0
+; CHECK-NEXT:    vpermq {{.*#+}} ymm0 = ymm0[0,2,2,3]
+; CHECK-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
+; CHECK-NEXT:    vpsllvd %ymm2, %ymm1, %ymm1
+; CHECK-NEXT:    vpshufb %ymm4, %ymm1, %ymm1
+; CHECK-NEXT:    vpermq {{.*#+}} ymm1 = ymm1[0,2,2,3]
+; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
+; CHECK-NEXT:    vpand %xmm0, %xmm3, %xmm0
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+  %sh1 = shl <8 x i16> %x0, %y
+  %sh2 = shl <8 x i16> %x1, %y
+  %logic = and <8 x i16> %z, %sh1
+  %r = and <8 x i16> %sh2, %logic
+  ret <8 x i16> %r
+}
+
+; negative test - mismatched shift opcodes
+
+define i64 @and_mix_shr(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: and_mix_shr:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    shrq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    sarq %cl, %rsi
+; CHECK-NEXT:    andq %rsi, %rax
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = ashr i64 %x1, %y
+  %logic = and i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched shift amounts
+
+define i64 @and_lshr_mix_shift_amount(i64 %x0, i64 %x1, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: and_lshr_mix_shift_amount:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    shrq %cl, %rdi
+; CHECK-NEXT:    movl %r8d, %ecx
+; CHECK-NEXT:    shrq %cl, %rsi
+; CHECK-NEXT:    andq %rsi, %rax
+; CHECK-NEXT:    andq %rdi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = lshr i64 %x0, %y
+  %sh2 = lshr i64 %x1, %w
+  %logic = and i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
+; negative test - mismatched logic opcodes
+
+define i64 @mix_logic_shl(i64 %x0, i64 %x1, i64 %y, i64 %z) {
+; CHECK-LABEL: mix_logic_shl:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rcx, %rax
+; CHECK-NEXT:    movq %rdx, %rcx
+; CHECK-NEXT:    shlq %cl, %rdi
+; CHECK-NEXT:    # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT:    shlq %cl, %rsi
+; CHECK-NEXT:    xorq %rdi, %rax
+; CHECK-NEXT:    andq %rsi, %rax
+; CHECK-NEXT:    retq
+  %sh1 = shl i64 %x0, %y
+  %sh2 = shl i64 %x1, %y
+  %logic = xor i64 %sh1, %z
+  %r = and i64 %logic, %sh2
+  ret i64 %r
+}
+
 ; (shl (X | Y), C1) | (srl X, C2) --> (rotl X, C1) | (shl Y, C1)
 
 define i32 @or_fshl_commute0(i32 %x, i32 %y) {


        


More information about the llvm-commits mailing list